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