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