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