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