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