]> git.zerfleddert.de Git - proxmark3-svn/blame - winsrc/gui.cpp
Added a way to overlay a grid to graph window
[proxmark3-svn] / winsrc / gui.cpp
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// Routines for the user interface when doing interactive things with prox\r
3// cards; this is basically a command line thing, in one window, and then\r
4// another window to do the graphs.\r
5// Jonathan Westhues, Sept 2005\r
6//-----------------------------------------------------------------------------\r
7#include <windows.h>\r
8#include <limits.h>\r
9#include <commctrl.h>\r
10#include <stdlib.h>\r
11#include <stdio.h>\r
12#include <math.h>\r
13\r
14#include "prox.h"\r
15\r
16#define oops() do { \\r
17 char line[100]; \\r
18 sprintf(line, "Internal error at line %d file '%s'", __LINE__, \\r
19 __FILE__); \\r
20 MessageBox(NULL, line, "Error", MB_ICONERROR); \\r
21 exit(-1); \\r
22} while(0)\r
23\r
24void dbp(char *str, ...)\r
25{\r
26 va_list f;\r
27 char buf[1024];\r
28 va_start(f, str);\r
29 vsprintf(buf, str, f);\r
30 OutputDebugString(buf);\r
31 OutputDebugString("\n");\r
32}\r
33\r
34int GraphBuffer[MAX_GRAPH_TRACE_LEN];\r
35int GraphTraceLen;\r
36\r
bd4cc2c9 37HPEN GreyPenLite, GreyPen, GreenPen, WhitePen, YellowPen;\r
6658905f 38HBRUSH GreenBrush, YellowBrush;\r
39\r
40static int GraphStart = 0;\r
41static double GraphPixelsPerPoint = 1;\r
42\r
bd4cc2c9 43static int PlotGridX = 0, PlotGridY = 0;\r
6658905f 44static int CursorAPos;\r
45static int CursorBPos;\r
46double CursorScaleFactor = 1.0;\r
47static HPEN CursorAPen;\r
48static HPEN CursorBPen;\r
49\r
50static HWND CommandWindow;\r
51static HWND GraphWindow;\r
52static HWND ScrollbackEdit;\r
53static HWND CommandEdit;\r
54\r
55#define COMMAND_HISTORY_MAX 16\r
56static char CommandHistory[COMMAND_HISTORY_MAX][256];\r
57static int CommandHistoryPos = -1;\r
58static int CommandHistoryNext;\r
59\r
60static HFONT MyFixedFont;\r
61#define FixedFont(x) SendMessage((x), WM_SETFONT, (WPARAM)MyFixedFont, TRUE)\r
62\r
63void ExecCmd(char *cmd)\r
64{\r
6658905f 65}\r
bd4cc2c9 66\r
6658905f 67int CommandFinished;\r
30f2a7d3 68int offset = 64;\r
6658905f 69\r
bd4cc2c9 70void SetGraphGrid(int x, int y)\r
71{\r
72 PlotGridX = x;\r
73 PlotGridY = y;\r
74}\r
75\r
6658905f 76static void ResizeCommandWindow(void)\r
77{\r
78 int w, h;\r
79 RECT r;\r
80 GetClientRect(CommandWindow, &r);\r
81 w = r.right - r.left;\r
82 h = r.bottom - r.top;\r
83 MoveWindow(ScrollbackEdit, 10, 10, w - 20, h - 50, TRUE);\r
84 MoveWindow(CommandEdit, 10, h - 29, w - 20, 22, TRUE);\r
85}\r
86\r
87void RepaintGraphWindow(void)\r
88{\r
89 InvalidateRect(GraphWindow, NULL, TRUE);\r
90}\r
91\r
92static LRESULT CALLBACK\r
93 CommandWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
94{\r
95 switch (msg) {\r
96 case WM_DESTROY:\r
97 case WM_QUIT:\r
98 exit(0);\r
99 return 0;\r
100\r
101 case WM_SIZE:\r
102 ResizeCommandWindow();\r
103 return 0;\r
104\r
105 case WM_SETFOCUS:\r
106 SetFocus(CommandEdit);\r
107 break;\r
108\r
109 default:\r
110 return DefWindowProc(hwnd, msg, wParam, lParam);\r
111 }\r
112\r
113 return 1;\r
114}\r
115\r
116static void PaintGraph(HDC hdc)\r
117{\r
bd4cc2c9 118 RECT r;\r
6658905f 119 HBRUSH brush;\r
120 HPEN pen;\r
bd4cc2c9 121 char str[250];\r
122 int yMin = INT_MAX;\r
123 int yMax = INT_MIN;\r
124 int yMean = 0;\r
125 int startMax = 0;\r
126 int absYMax = 1;\r
127 int n = 0, i = 0;\r
6658905f 128\r
129 brush = GreenBrush;\r
130 pen = GreenPen;\r
131\r
6658905f 132 GetClientRect(GraphWindow, &r);\r
bd4cc2c9 133 int zeroHeight = (r.top + r.bottom) >> 1;\r
134\r
135 // plot X and Y grid lines\r
136 if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) {\r
137 for(i = offset; i < r.right; i += (int)(PlotGridX * GraphPixelsPerPoint)) {\r
138 SelectObject(hdc, GreyPenLite);\r
139 MoveToEx(hdc, r.left + i, r.top, NULL);\r
140 LineTo(hdc, r.left + i, r.bottom);\r
141 }\r
142 }\r
143\r
144 if ((PlotGridY > 0) && ((PlotGridY * GraphPixelsPerPoint) > 1)){\r
145 for(i = 0; i < ((r.top + r.bottom)>>1); i += (int)(PlotGridY * GraphPixelsPerPoint)) {\r
146 SelectObject(hdc, GreyPenLite);\r
147 MoveToEx(hdc, r.left, zeroHeight + i, NULL);\r
148 LineTo(hdc, r.right, zeroHeight + i);\r
149 MoveToEx(hdc, r.left, zeroHeight - i, NULL);\r
150 LineTo(hdc, r.right, zeroHeight - i);\r
151 }\r
152 }\r
6658905f 153\r
bd4cc2c9 154 // print vertical separator white line on the left of the window\r
6658905f 155 SelectObject(hdc, WhitePen);\r
30f2a7d3 156 MoveToEx(hdc, r.left + offset, r.top, NULL);\r
157 LineTo(hdc, r.left + offset, r.bottom);\r
6658905f 158\r
bd4cc2c9 159 // print horizontal grey zero axis line\r
6658905f 160 SelectObject(hdc, GreyPen);\r
161 MoveToEx(hdc, r.left, zeroHeight, NULL);\r
162 LineTo(hdc, r.right, zeroHeight);\r
163\r
bd4cc2c9 164 startMax = (GraphTraceLen - (int)((r.right - r.left - offset) / GraphPixelsPerPoint));\r
165 // check boundaries\r
166 if(startMax < 0) startMax = 0;\r
167 if(GraphStart > startMax) GraphStart = startMax;\r
168 if(GraphStart < 0) GraphStart = 0;\r
6658905f 169\r
6658905f 170\r
171 SelectObject(hdc, pen);\r
172\r
bd4cc2c9 173 // go over the portion of the graph to be displayed and find the largest\r
174 // absolute value which will be used to auto scale the graph when displayed\r
6658905f 175 for(i = GraphStart; ; i++) {\r
176 if(i >= GraphTraceLen) {\r
177 break;\r
178 }\r
179 if(fabs((double)GraphBuffer[i]) > absYMax) {\r
180 absYMax = (int)fabs((double)GraphBuffer[i]);\r
181 }\r
30f2a7d3 182 int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint);\r
6658905f 183 if(x > r.right) {\r
184 break;\r
185 }\r
186 }\r
187\r
188 absYMax = (int)(absYMax*1.2 + 1);\r
189 SelectObject(hdc, MyFixedFont);\r
190 SetTextColor(hdc, RGB(255, 255, 255));\r
191 SetBkColor(hdc, RGB(0, 0, 0));\r
192\r
193 // number of points that will be plotted\r
30f2a7d3 194 double span = (int)((r.right - r.left) / GraphPixelsPerPoint);\r
195\r
196 // one label every offset pixels, let us say\r
197 int labels = (r.right - r.left - offset) / offset;\r
6658905f 198 if(labels <= 0) labels = 1;\r
30f2a7d3 199 // round to nearest power of 2\r
200 int pointsPerLabel = (int)(log(span / labels)/log(2.0));\r
6658905f 201 if(pointsPerLabel <= 0) pointsPerLabel = 1;\r
30f2a7d3 202 pointsPerLabel = (int)pow(2.0,pointsPerLabel);\r
6658905f 203\r
bd4cc2c9 204 // go over the graph and plot samples and labels\r
6658905f 205 for(i = GraphStart; ; i++) {\r
206 if(i >= GraphTraceLen) {\r
207 break;\r
208 }\r
30f2a7d3 209 int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint);\r
6658905f 210 if(x > r.right + GraphPixelsPerPoint) {\r
211 break;\r
212 }\r
213\r
214 int y = GraphBuffer[i];\r
bd4cc2c9 215 if(y < yMin) yMin = y;\r
216 if(y > yMax) yMax = y;\r
6658905f 217 yMean += y;\r
218 n++;\r
219\r
220 y = (y * (r.top - r.bottom) / (2*absYMax)) + zeroHeight;\r
221 if(i == GraphStart) {\r
222 MoveToEx(hdc, x, y, NULL);\r
223 } else {\r
224 LineTo(hdc, x, y);\r
225 }\r
226\r
227 if(GraphPixelsPerPoint > 10) {\r
228 RECT f;\r
229 f.left = x - 3;\r
230 f.top = y - 3;\r
231 f.right = x + 3;\r
232 f.bottom = y + 3;\r
233 FillRect(hdc, &f, brush);\r
234 }\r
235\r
bd4cc2c9 236 // plot labels\r
6658905f 237 if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {\r
238 SelectObject(hdc, WhitePen);\r
30f2a7d3 239 MoveToEx(hdc, x, zeroHeight - 8, NULL);\r
240 LineTo(hdc, x, zeroHeight + 8);\r
6658905f 241\r
bd4cc2c9 242 sprintf(str, "+%d", i);\r
6658905f 243 SIZE size;\r
244 GetTextExtentPoint32(hdc, str, strlen(str), &size);\r
245 TextOut(hdc, x - size.cx, zeroHeight + 8, str, strlen(str));\r
246\r
247 SelectObject(hdc, pen);\r
248 MoveToEx(hdc, x, y, NULL);\r
249 }\r
250\r
bd4cc2c9 251 // plot measurement cursors\r
6658905f 252 if(i == CursorAPos || i == CursorBPos) {\r
253 if(i == CursorAPos) {\r
254 SelectObject(hdc, CursorAPen);\r
255 } else {\r
256 SelectObject(hdc, CursorBPen);\r
257 }\r
258 MoveToEx(hdc, x, r.top, NULL);\r
259 LineTo(hdc, x, r.bottom);\r
260\r
261 SelectObject(hdc, pen);\r
262 MoveToEx(hdc, x, y, NULL);\r
263 }\r
264 }\r
265\r
266 if(n != 0) {\r
267 yMean /= n;\r
268 }\r
269\r
bd4cc2c9 270 // print misc information at bottom of graph window\r
67b9b62a 271 sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f] zoom=%.3f CursorA=%d [%d] CursorB=%d [%d]",\r
6658905f 272 GraphStart, yMax, yMin, yMean, n, GraphTraceLen,\r
48f8a3d6 273 CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor, GraphPixelsPerPoint,\r
274 CursorAPos, GraphBuffer[CursorAPos], CursorBPos, GraphBuffer[CursorBPos]);\r
6658905f 275 TextOut(hdc, 50, r.bottom - 20, str, strlen(str));\r
276}\r
277\r
278static LRESULT CALLBACK\r
279 GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
280{\r
281 switch (msg) {\r
282 case WM_DESTROY:\r
283 case WM_QUIT:\r
284 GraphWindow = NULL;\r
285 return DefWindowProc(hwnd, msg, wParam, lParam);\r
286\r
287 case WM_SIZE:\r
288 RepaintGraphWindow();\r
289 return 0;\r
290\r
291 case WM_PAINT: {\r
292 PAINTSTRUCT ps;\r
293 HDC hdc = BeginPaint(hwnd, &ps);\r
294 if(GraphStart < 0) {\r
295 GraphStart = 0;\r
296 }\r
297 // This draws the trace.\r
298 PaintGraph(hdc);\r
299 EndPaint(hwnd, &ps);\r
300 break;\r
301 }\r
302 case WM_KEYDOWN:\r
303 switch(wParam) {\r
304 case VK_DOWN:\r
30f2a7d3 305 if(GraphPixelsPerPoint <= 8) {\r
6658905f 306 GraphPixelsPerPoint *= 2;\r
307 }\r
308 break;\r
309\r
310 case VK_UP:\r
30f2a7d3 311 if(GraphPixelsPerPoint >= 0.01) {\r
6658905f 312 GraphPixelsPerPoint /= 2;\r
313 }\r
314 break;\r
315\r
316 case VK_RIGHT:\r
30f2a7d3 317 if(GraphPixelsPerPoint < 16) {\r
318 GraphStart += (int)(16 / GraphPixelsPerPoint);\r
6658905f 319 } else {\r
320 GraphStart++;\r
321 }\r
322 break;\r
323\r
324 case VK_LEFT:\r
30f2a7d3 325 if(GraphPixelsPerPoint < 16) {\r
326 GraphStart -= (int)(16 / GraphPixelsPerPoint);\r
6658905f 327 } else {\r
328 GraphStart--;\r
329 }\r
330 break;\r
331\r
332 default:\r
333 goto nopaint;\r
334 }\r
335 RepaintGraphWindow();\r
336nopaint:\r
337 break;\r
338\r
339 case WM_LBUTTONDOWN:\r
340 case WM_RBUTTONDOWN: {\r
341 int x = LOWORD(lParam);\r
30f2a7d3 342 x -= offset;\r
6658905f 343 x = (int)(x / GraphPixelsPerPoint);\r
344 x += GraphStart;\r
48f8a3d6 345\r
6658905f 346 if(msg == WM_LBUTTONDOWN) {\r
347 CursorAPos = x;\r
348 } else {\r
349 CursorBPos = x;\r
350 }\r
351 RepaintGraphWindow();\r
352 break;\r
353 }\r
354 default:\r
355 return DefWindowProc(hwnd, msg, wParam, lParam);\r
356 }\r
357\r
358 return 1;\r
359}\r
360\r
361void PrintToScrollback(char *fmt, ...)\r
362{\r
363 va_list f;\r
364 char str[1024];\r
365 strcpy(str, "\r\n");\r
366 va_start(f, fmt);\r
367 vsprintf(str+2, fmt, f);\r
368\r
369 static char TextBuf[1024*32];\r
370 SendMessage(ScrollbackEdit, WM_GETTEXT, (WPARAM)sizeof(TextBuf),\r
371 (LPARAM)TextBuf);\r
372\r
373 if(strlen(TextBuf) + strlen(str) + 1 <= sizeof(TextBuf)) {\r
374 strcat(TextBuf, str);\r
375 } else {\r
376 lstrcpyn(TextBuf, str, sizeof(TextBuf));\r
377 }\r
378\r
379 SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)TextBuf);\r
380 SendMessage(ScrollbackEdit, EM_LINESCROLL, 0, (LPARAM)INT_MAX);\r
381}\r
382\r
383void ShowGraphWindow(void)\r
384{\r
385 if(GraphWindow) return;\r
386\r
387 GraphWindow = CreateWindowEx(0, "Graph", "graphed",\r
388 WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |\r
389 WS_SIZEBOX | WS_VISIBLE, 200, 150, 600, 500, NULL, NULL, NULL,\r
390 NULL);\r
391 if(!GraphWindow) oops();\r
392}\r
393\r
394void HideGraphWindow(void)\r
395{\r
396 if(GraphWindow) {\r
397 DestroyWindow(GraphWindow);\r
398 GraphWindow = NULL;\r
399 }\r
400}\r
401\r
402static void SetCommandEditTo(char *str)\r
403{\r
404 SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)str);\r
405 SendMessage(CommandEdit, EM_SETSEL, strlen(str), strlen(str));\r
406}\r
407\r
9760414b 408void ShowGui()\r
6658905f 409{\r
410 WNDCLASSEX wc;\r
411 memset(&wc, 0, sizeof(wc));\r
412 wc.cbSize = sizeof(wc);\r
413\r
414 wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC;\r
415 wc.lpfnWndProc = (WNDPROC)CommandWindowProc;\r
416 wc.hInstance = NULL;\r
417 wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW);\r
418 wc.lpszClassName = "Command";\r
419 wc.lpszMenuName = NULL;\r
420 wc.hCursor = LoadCursor(NULL, IDC_ARROW);\r
421\r
422 if(!RegisterClassEx(&wc)) oops();\r
423\r
424 wc.lpszClassName = "Graph";\r
425 wc.lpfnWndProc = (WNDPROC)GraphWindowProc;\r
426 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);\r
427\r
428 if(!RegisterClassEx(&wc)) oops();\r
429\r
430 CommandWindow = CreateWindowEx(0, "Command", "prox",\r
431 WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |\r
432 WS_SIZEBOX | WS_VISIBLE, 20, 20, 500, 400, NULL, NULL, NULL,\r
433 NULL);\r
434 if(!CommandWindow) oops();\r
435\r
436 ScrollbackEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",\r
437 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_MULTILINE |\r
438 ES_AUTOVSCROLL | WS_VSCROLL, 0, 0, 0, 0, CommandWindow, NULL,\r
439 NULL, NULL);\r
440\r
441 CommandEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",\r
442 WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE |\r
443 ES_AUTOHSCROLL, 0, 0, 0, 0, CommandWindow, NULL, NULL, NULL);\r
444\r
445 MyFixedFont = CreateFont(14, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,\r
446 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,\r
447 FF_DONTCARE, "Lucida Console");\r
448 if(!MyFixedFont)\r
449 MyFixedFont = (HFONT)GetStockObject(SYSTEM_FONT);\r
450\r
451 FixedFont(ScrollbackEdit);\r
452 FixedFont(CommandEdit);\r
453\r
454 ResizeCommandWindow();\r
455 SetFocus(CommandEdit);\r
456\r
457 PrintToScrollback(">> Started prox, built " __DATE__ " " __TIME__);\r
458 PrintToScrollback(">> Connected to device");\r
459\r
bd4cc2c9 460 GreyPenLite = CreatePen(PS_SOLID, 1, RGB(50, 50, 50));\r
6658905f 461 GreyPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100));\r
462 GreenPen = CreatePen(PS_SOLID, 1, RGB(100, 255, 100));\r
463 YellowPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0));\r
464 GreenBrush = CreateSolidBrush(RGB(100, 255, 100));\r
465 YellowBrush = CreateSolidBrush(RGB(255, 255, 0));\r
466 WhitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
467\r
468 CursorAPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));\r
469 CursorBPen = CreatePen(PS_DASH, 1, RGB(255, 0, 255));\r
470\r
471 MSG msg;\r
472 for(;;) {\r
473 if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {\r
474 if(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN) {\r
475 char got[1024];\r
476 SendMessage(CommandEdit, WM_GETTEXT, (WPARAM)sizeof(got),\r
477 (LPARAM)got);\r
478\r
479 if(strcmp(got, "cls")==0) {\r
480 SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)"");\r
481 } else {\r
482 CommandReceived(got);\r
483 }\r
484 SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");\r
485\r
486 // Insert it into the command history, unless it is\r
487 // identical to the previous command in the history.\r
488 int prev = CommandHistoryNext - 1;\r
489 if(prev < 0) prev += COMMAND_HISTORY_MAX;\r
490 if(strcmp(CommandHistory[prev], got) != 0) {\r
491 strcpy(CommandHistory[CommandHistoryNext], got);\r
492 CommandHistoryNext++;\r
493 if(CommandHistoryNext == COMMAND_HISTORY_MAX) {\r
494 CommandHistoryNext = 0;\r
495 }\r
496 }\r
497 CommandHistoryPos = -1;\r
498 } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_UP &&\r
499 msg.hwnd == CommandEdit)\r
500 {\r
501 if(CommandHistoryPos == -1) {\r
502 CommandHistoryPos = CommandHistoryNext;\r
503 }\r
504 CommandHistoryPos--;\r
505 if(CommandHistoryPos < 0) {\r
506 CommandHistoryPos = COMMAND_HISTORY_MAX-1;\r
507 }\r
508 SetCommandEditTo(CommandHistory[CommandHistoryPos]);\r
509 } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_DOWN &&\r
510 msg.hwnd == CommandEdit)\r
511 {\r
512 CommandHistoryPos++;\r
513 if(CommandHistoryPos >= COMMAND_HISTORY_MAX) {\r
514 CommandHistoryPos = 0;\r
515 }\r
516 SetCommandEditTo(CommandHistory[CommandHistoryPos]);\r
517 } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE &&\r
518 msg.hwnd == CommandEdit)\r
519 {\r
520 SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");\r
521 } else {\r
522 if(msg.message == WM_KEYDOWN) {\r
523 CommandHistoryPos = -1;\r
524 }\r
525 TranslateMessage(&msg);\r
526 DispatchMessage(&msg);\r
527 }\r
528 }\r
529\r
9760414b 530 if (!offline)\r
531 {\r
532 UsbCommand c;\r
533 if(ReceiveCommandPoll(&c))\r
534 UsbCommandReceived(&c);\r
6658905f 535 }\r
536\r
537 Sleep(10);\r
538 }\r
539}\r
Impressum, Datenschutz