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