--- /dev/null
+//-----------------------------------------------------------------------------\r
+// Routines for the user interface when doing interactive things with prox\r
+// cards; this is basically a command line thing, in one window, and then\r
+// another window to do the graphs.\r
+// Jonathan Westhues, Sept 2005\r
+//-----------------------------------------------------------------------------\r
+#include <windows.h>\r
+#include <limits.h>\r
+#include <commctrl.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <math.h>\r
+\r
+#include "prox.h"\r
+\r
+#define oops() do { \\r
+ char line[100]; \\r
+ sprintf(line, "Internal error at line %d file '%s'", __LINE__, \\r
+ __FILE__); \\r
+ MessageBox(NULL, line, "Error", MB_ICONERROR); \\r
+ exit(-1); \\r
+} while(0)\r
+\r
+void dbp(char *str, ...)\r
+{\r
+ va_list f;\r
+ char buf[1024];\r
+ va_start(f, str);\r
+ vsprintf(buf, str, f);\r
+ OutputDebugString(buf);\r
+ OutputDebugString("\n");\r
+}\r
+\r
+int GraphBuffer[MAX_GRAPH_TRACE_LEN];\r
+int GraphTraceLen;\r
+\r
+HPEN GreyPen, GreenPen, WhitePen, YellowPen;\r
+HBRUSH GreenBrush, YellowBrush;\r
+\r
+static int GraphStart = 0;\r
+static double GraphPixelsPerPoint = 1;\r
+\r
+static int CursorAPos;\r
+static int CursorBPos;\r
+double CursorScaleFactor = 1.0;\r
+static HPEN CursorAPen;\r
+static HPEN CursorBPen;\r
+\r
+static HWND CommandWindow;\r
+static HWND GraphWindow;\r
+static HWND ScrollbackEdit;\r
+static HWND CommandEdit;\r
+\r
+#define COMMAND_HISTORY_MAX 16\r
+static char CommandHistory[COMMAND_HISTORY_MAX][256];\r
+static int CommandHistoryPos = -1;\r
+static int CommandHistoryNext;\r
+\r
+static HFONT MyFixedFont;\r
+#define FixedFont(x) SendMessage((x), WM_SETFONT, (WPARAM)MyFixedFont, TRUE)\r
+\r
+void ExecCmd(char *cmd)\r
+{\r
+\r
+}\r
+int CommandFinished;\r
+\r
+static void ResizeCommandWindow(void)\r
+{\r
+ int w, h;\r
+ RECT r;\r
+ GetClientRect(CommandWindow, &r);\r
+ w = r.right - r.left;\r
+ h = r.bottom - r.top;\r
+ MoveWindow(ScrollbackEdit, 10, 10, w - 20, h - 50, TRUE);\r
+ MoveWindow(CommandEdit, 10, h - 29, w - 20, 22, TRUE);\r
+}\r
+\r
+void RepaintGraphWindow(void)\r
+{\r
+ InvalidateRect(GraphWindow, NULL, TRUE);\r
+}\r
+\r
+static LRESULT CALLBACK\r
+ CommandWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (msg) {\r
+ case WM_DESTROY:\r
+ case WM_QUIT:\r
+ exit(0);\r
+ return 0;\r
+\r
+ case WM_SIZE:\r
+ ResizeCommandWindow();\r
+ return 0;\r
+\r
+ case WM_SETFOCUS:\r
+ SetFocus(CommandEdit);\r
+ break;\r
+\r
+ default:\r
+ return DefWindowProc(hwnd, msg, wParam, lParam);\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+static void PaintGraph(HDC hdc)\r
+{\r
+ HBRUSH brush;\r
+ HPEN pen;\r
+\r
+ brush = GreenBrush;\r
+ pen = GreenPen;\r
+\r
+ if(GraphStart < 0) {\r
+ GraphStart = 0;\r
+ }\r
+\r
+ RECT r;\r
+ GetClientRect(GraphWindow, &r);\r
+\r
+ SelectObject(hdc, WhitePen);\r
+\r
+ MoveToEx(hdc, r.left + 40, r.top, NULL);\r
+ LineTo(hdc, r.left + 40, r.bottom);\r
+\r
+ int zeroHeight = r.top + (r.bottom - r.top) / 2;\r
+ SelectObject(hdc, GreyPen);\r
+ MoveToEx(hdc, r.left, zeroHeight, NULL);\r
+ LineTo(hdc, r.right, zeroHeight);\r
+\r
+ int startMax =\r
+ (GraphTraceLen - (int)((r.right - r.left - 40) / GraphPixelsPerPoint));\r
+ if(startMax < 0) {\r
+ startMax = 0;\r
+ }\r
+ if(GraphStart > startMax) {\r
+ GraphStart = startMax;\r
+ }\r
+\r
+ int absYMax = 1;\r
+\r
+ SelectObject(hdc, pen);\r
+\r
+ int i;\r
+ for(i = GraphStart; ; i++) {\r
+ if(i >= GraphTraceLen) {\r
+ break;\r
+ }\r
+ if(fabs((double)GraphBuffer[i]) > absYMax) {\r
+ absYMax = (int)fabs((double)GraphBuffer[i]);\r
+ }\r
+ int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint);\r
+ if(x > r.right) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ absYMax = (int)(absYMax*1.2 + 1);\r
+ SelectObject(hdc, MyFixedFont);\r
+ SetTextColor(hdc, RGB(255, 255, 255));\r
+ SetBkColor(hdc, RGB(0, 0, 0));\r
+\r
+ // number of points that will be plotted\r
+ int span = (int)((r.right - r.left) / GraphPixelsPerPoint);\r
+ // one label every 100 pixels, let us say\r
+ int labels = (r.right - r.left - 40) / 100;\r
+ if(labels <= 0) labels = 1;\r
+ int pointsPerLabel = span / labels;\r
+ if(pointsPerLabel <= 0) pointsPerLabel = 1;\r
+\r
+ int yMin = INT_MAX;\r
+ int yMax = INT_MIN;\r
+ int yMean = 0;\r
+ int n = 0;\r
+\r
+ for(i = GraphStart; ; i++) {\r
+ if(i >= GraphTraceLen) {\r
+ break;\r
+ }\r
+ int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint);\r
+ if(x > r.right + GraphPixelsPerPoint) {\r
+ break;\r
+ }\r
+\r
+ int y = GraphBuffer[i];\r
+ if(y < yMin) {\r
+ yMin = y;\r
+ }\r
+ if(y > yMax) {\r
+ yMax = y;\r
+ }\r
+ yMean += y;\r
+ n++;\r
+\r
+ y = (y * (r.top - r.bottom) / (2*absYMax)) + zeroHeight;\r
+ if(i == GraphStart) {\r
+ MoveToEx(hdc, x, y, NULL);\r
+ } else {\r
+ LineTo(hdc, x, y);\r
+ }\r
+\r
+ if(GraphPixelsPerPoint > 10) {\r
+ RECT f;\r
+ f.left = x - 3;\r
+ f.top = y - 3;\r
+ f.right = x + 3;\r
+ f.bottom = y + 3;\r
+ FillRect(hdc, &f, brush);\r
+ }\r
+\r
+ if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {\r
+ SelectObject(hdc, WhitePen);\r
+ MoveToEx(hdc, x, zeroHeight - 3, NULL);\r
+ LineTo(hdc, x, zeroHeight + 3);\r
+\r
+ char str[100];\r
+ sprintf(str, "+%d", (i - GraphStart));\r
+ SIZE size;\r
+ GetTextExtentPoint32(hdc, str, strlen(str), &size);\r
+ TextOut(hdc, x - size.cx, zeroHeight + 8, str, strlen(str));\r
+\r
+ SelectObject(hdc, pen);\r
+ MoveToEx(hdc, x, y, NULL);\r
+ }\r
+\r
+ if(i == CursorAPos || i == CursorBPos) {\r
+ if(i == CursorAPos) {\r
+ SelectObject(hdc, CursorAPen);\r
+ } else {\r
+ SelectObject(hdc, CursorBPen);\r
+ }\r
+ MoveToEx(hdc, x, r.top, NULL);\r
+ LineTo(hdc, x, r.bottom);\r
+\r
+ SelectObject(hdc, pen);\r
+ MoveToEx(hdc, x, y, NULL);\r
+ }\r
+ }\r
+\r
+ if(n != 0) {\r
+ yMean /= n;\r
+ }\r
+\r
+ char str[100];\r
+ sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f]",\r
+ GraphStart, yMax, yMin, yMean, n, GraphTraceLen,\r
+ CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor);\r
+ TextOut(hdc, 50, r.bottom - 20, str, strlen(str));\r
+}\r
+\r
+static LRESULT CALLBACK\r
+ GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch (msg) {\r
+ case WM_DESTROY:\r
+ case WM_QUIT:\r
+ GraphWindow = NULL;\r
+ return DefWindowProc(hwnd, msg, wParam, lParam);\r
+\r
+ case WM_SIZE:\r
+ RepaintGraphWindow();\r
+ return 0;\r
+\r
+ case WM_PAINT: {\r
+ PAINTSTRUCT ps;\r
+ HDC hdc = BeginPaint(hwnd, &ps);\r
+ if(GraphStart < 0) {\r
+ GraphStart = 0;\r
+ }\r
+ // This draws the trace.\r
+ PaintGraph(hdc);\r
+ EndPaint(hwnd, &ps);\r
+ break;\r
+ }\r
+ case WM_KEYDOWN:\r
+ switch(wParam) {\r
+ case VK_DOWN:\r
+ if(GraphPixelsPerPoint <= 50) {\r
+ GraphPixelsPerPoint *= 2;\r
+ }\r
+ break;\r
+\r
+ case VK_UP:\r
+ if(GraphPixelsPerPoint >= 0.02) {\r
+ GraphPixelsPerPoint /= 2;\r
+ }\r
+ break;\r
+\r
+ case VK_RIGHT:\r
+ if(GraphPixelsPerPoint < 20) {\r
+ GraphStart += (int)(20 / GraphPixelsPerPoint);\r
+ } else {\r
+ GraphStart++;\r
+ }\r
+ break;\r
+\r
+ case VK_LEFT:\r
+ if(GraphPixelsPerPoint < 20) {\r
+ GraphStart -= (int)(20 / GraphPixelsPerPoint);\r
+ } else {\r
+ GraphStart--;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ goto nopaint;\r
+ }\r
+ RepaintGraphWindow();\r
+nopaint:\r
+ break;\r
+\r
+ case WM_LBUTTONDOWN:\r
+ case WM_RBUTTONDOWN: {\r
+ int x = LOWORD(lParam);\r
+ x -= 40;\r
+ x = (int)(x / GraphPixelsPerPoint);\r
+ x += GraphStart;\r
+ if(msg == WM_LBUTTONDOWN) {\r
+ CursorAPos = x;\r
+ } else {\r
+ CursorBPos = x;\r
+ }\r
+ RepaintGraphWindow();\r
+ break;\r
+ }\r
+ default:\r
+ return DefWindowProc(hwnd, msg, wParam, lParam);\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+void PrintToScrollback(char *fmt, ...)\r
+{\r
+ va_list f;\r
+ char str[1024];\r
+ strcpy(str, "\r\n");\r
+ va_start(f, fmt);\r
+ vsprintf(str+2, fmt, f);\r
+\r
+ static char TextBuf[1024*32];\r
+ SendMessage(ScrollbackEdit, WM_GETTEXT, (WPARAM)sizeof(TextBuf),\r
+ (LPARAM)TextBuf);\r
+\r
+ if(strlen(TextBuf) + strlen(str) + 1 <= sizeof(TextBuf)) {\r
+ strcat(TextBuf, str);\r
+ } else {\r
+ lstrcpyn(TextBuf, str, sizeof(TextBuf));\r
+ }\r
+\r
+ SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)TextBuf);\r
+ SendMessage(ScrollbackEdit, EM_LINESCROLL, 0, (LPARAM)INT_MAX);\r
+}\r
+\r
+void ShowGraphWindow(void)\r
+{\r
+ if(GraphWindow) return;\r
+\r
+ GraphWindow = CreateWindowEx(0, "Graph", "graphed",\r
+ WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |\r
+ WS_SIZEBOX | WS_VISIBLE, 200, 150, 600, 500, NULL, NULL, NULL,\r
+ NULL);\r
+ if(!GraphWindow) oops();\r
+}\r
+\r
+void HideGraphWindow(void)\r
+{\r
+ if(GraphWindow) {\r
+ DestroyWindow(GraphWindow);\r
+ GraphWindow = NULL;\r
+ }\r
+}\r
+\r
+static void SetCommandEditTo(char *str)\r
+{\r
+ SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)str);\r
+ SendMessage(CommandEdit, EM_SETSEL, strlen(str), strlen(str));\r
+}\r
+\r
+void ShowGui(void)\r
+{\r
+ WNDCLASSEX wc;\r
+ memset(&wc, 0, sizeof(wc));\r
+ wc.cbSize = sizeof(wc);\r
+\r
+ wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC;\r
+ wc.lpfnWndProc = (WNDPROC)CommandWindowProc;\r
+ wc.hInstance = NULL;\r
+ wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW);\r
+ wc.lpszClassName = "Command";\r
+ wc.lpszMenuName = NULL;\r
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);\r
+\r
+ if(!RegisterClassEx(&wc)) oops();\r
+\r
+ wc.lpszClassName = "Graph";\r
+ wc.lpfnWndProc = (WNDPROC)GraphWindowProc;\r
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);\r
+\r
+ if(!RegisterClassEx(&wc)) oops();\r
+\r
+ CommandWindow = CreateWindowEx(0, "Command", "prox",\r
+ WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |\r
+ WS_SIZEBOX | WS_VISIBLE, 20, 20, 500, 400, NULL, NULL, NULL,\r
+ NULL);\r
+ if(!CommandWindow) oops();\r
+\r
+ ScrollbackEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",\r
+ WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_MULTILINE |\r
+ ES_AUTOVSCROLL | WS_VSCROLL, 0, 0, 0, 0, CommandWindow, NULL,\r
+ NULL, NULL);\r
+\r
+ CommandEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",\r
+ WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE |\r
+ ES_AUTOHSCROLL, 0, 0, 0, 0, CommandWindow, NULL, NULL, NULL);\r
+\r
+ MyFixedFont = CreateFont(14, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,\r
+ ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,\r
+ FF_DONTCARE, "Lucida Console");\r
+ if(!MyFixedFont)\r
+ MyFixedFont = (HFONT)GetStockObject(SYSTEM_FONT);\r
+\r
+ FixedFont(ScrollbackEdit);\r
+ FixedFont(CommandEdit);\r
+\r
+ ResizeCommandWindow();\r
+ SetFocus(CommandEdit);\r
+\r
+ PrintToScrollback(">> Started prox, built " __DATE__ " " __TIME__);\r
+ PrintToScrollback(">> Connected to device");\r
+\r
+ GreyPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100));\r
+ GreenPen = CreatePen(PS_SOLID, 1, RGB(100, 255, 100));\r
+ YellowPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0));\r
+ GreenBrush = CreateSolidBrush(RGB(100, 255, 100));\r
+ YellowBrush = CreateSolidBrush(RGB(255, 255, 0));\r
+ WhitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
+\r
+ CursorAPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));\r
+ CursorBPen = CreatePen(PS_DASH, 1, RGB(255, 0, 255));\r
+\r
+ MSG msg;\r
+ for(;;) {\r
+ if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {\r
+ if(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN) {\r
+ char got[1024];\r
+ SendMessage(CommandEdit, WM_GETTEXT, (WPARAM)sizeof(got),\r
+ (LPARAM)got);\r
+\r
+ if(strcmp(got, "cls")==0) {\r
+ SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)"");\r
+ } else {\r
+ CommandReceived(got);\r
+ }\r
+ SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");\r
+\r
+ // Insert it into the command history, unless it is\r
+ // identical to the previous command in the history.\r
+ int prev = CommandHistoryNext - 1;\r
+ if(prev < 0) prev += COMMAND_HISTORY_MAX;\r
+ if(strcmp(CommandHistory[prev], got) != 0) {\r
+ strcpy(CommandHistory[CommandHistoryNext], got);\r
+ CommandHistoryNext++;\r
+ if(CommandHistoryNext == COMMAND_HISTORY_MAX) {\r
+ CommandHistoryNext = 0;\r
+ }\r
+ }\r
+ CommandHistoryPos = -1;\r
+ } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_UP &&\r
+ msg.hwnd == CommandEdit)\r
+ {\r
+ if(CommandHistoryPos == -1) {\r
+ CommandHistoryPos = CommandHistoryNext;\r
+ }\r
+ CommandHistoryPos--;\r
+ if(CommandHistoryPos < 0) {\r
+ CommandHistoryPos = COMMAND_HISTORY_MAX-1;\r
+ }\r
+ SetCommandEditTo(CommandHistory[CommandHistoryPos]);\r
+ } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_DOWN &&\r
+ msg.hwnd == CommandEdit)\r
+ {\r
+ CommandHistoryPos++;\r
+ if(CommandHistoryPos >= COMMAND_HISTORY_MAX) {\r
+ CommandHistoryPos = 0;\r
+ }\r
+ SetCommandEditTo(CommandHistory[CommandHistoryPos]);\r
+ } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE &&\r
+ msg.hwnd == CommandEdit)\r
+ {\r
+ SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");\r
+ } else {\r
+ if(msg.message == WM_KEYDOWN) {\r
+ CommandHistoryPos = -1;\r
+ }\r
+ TranslateMessage(&msg);\r
+ DispatchMessage(&msg);\r
+ }\r
+ }\r
+\r
+ UsbCommand c;\r
+ if(ReceiveCommandPoll(&c)) {\r
+ UsbCommandReceived(&c);\r
+ }\r
+\r
+ Sleep(10);\r
+ }\r
+}\r