//----------------------------------------------------------------------------- // Copyright 2007 Jonathan Westhues // // This file is part of LDmicro. // // LDmicro is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // LDmicro is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with LDmicro. If not, see . //------ // // All the simple dialogs that just require a row of text boxes: timer name // and delay, counter name and count, move and arithmetic destination and // operands. Try to reuse code a bit. // Jonathan Westhues, Nov 2004 //----------------------------------------------------------------------------- #include #include #include #include #include "ldmicro.h" static HWND SimpleDialog; #define MAX_BOXES 5 static HWND Textboxes[MAX_BOXES]; static HWND Labels[MAX_BOXES]; static LONG_PTR PrevAlnumOnlyProc[MAX_BOXES]; static LONG_PTR PrevNumOnlyProc[MAX_BOXES]; static BOOL NoCheckingOnBox[MAX_BOXES]; //----------------------------------------------------------------------------- // Don't allow any characters other than -A-Za-z0-9_ in the box. //----------------------------------------------------------------------------- static LRESULT CALLBACK MyAlnumOnlyProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if(msg == WM_CHAR) { if(!(isalpha(wParam) || isdigit(wParam) || wParam == '_' || wParam == '\b' || wParam == '-' || wParam == '\'')) { return 0; } } int i; for(i = 0; i < MAX_BOXES; i++) { if(hwnd == Textboxes[i]) { return CallWindowProc((WNDPROC)PrevAlnumOnlyProc[i], hwnd, msg, wParam, lParam); } } oops(); } //----------------------------------------------------------------------------- // Don't allow any characters other than -0-9. in the box. //----------------------------------------------------------------------------- static LRESULT CALLBACK MyNumOnlyProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if(msg == WM_CHAR) { if(!(isdigit(wParam) || wParam == '.' || wParam == '\b' || wParam == '-')) { return 0; } } int i; for(i = 0; i < MAX_BOXES; i++) { if(hwnd == Textboxes[i]) { return CallWindowProc((WNDPROC)PrevNumOnlyProc[i], hwnd, msg, wParam, lParam); } } oops(); } static void MakeControls(int boxes, char **labels, DWORD fixedFontMask) { int i; HDC hdc = GetDC(SimpleDialog); SelectObject(hdc, MyNiceFont); SIZE si; int maxLen = 0; for(i = 0; i < boxes; i++) { GetTextExtentPoint32(hdc, labels[i], strlen(labels[i]), &si); if(si.cx > maxLen) maxLen = si.cx; } int adj; if(maxLen > 70) { adj = maxLen - 70; } else { adj = 0; } for(i = 0; i < boxes; i++) { GetTextExtentPoint32(hdc, labels[i], strlen(labels[i]), &si); Labels[i] = CreateWindowEx(0, WC_STATIC, labels[i], WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, (80 + adj) - si.cx - 4, 13 + i*30, si.cx, 21, SimpleDialog, NULL, Instance, NULL); NiceFont(Labels[i]); Textboxes[i] = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, "", WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE, 80 + adj, 12 + 30*i, 120 - adj, 21, SimpleDialog, NULL, Instance, NULL); if(fixedFontMask & (1 << i)) { FixedFont(Textboxes[i]); } else { NiceFont(Textboxes[i]); } } ReleaseDC(SimpleDialog, hdc); OkButton = CreateWindowEx(0, WC_BUTTON, _("OK"), WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE | BS_DEFPUSHBUTTON, 218, 11, 70, 23, SimpleDialog, NULL, Instance, NULL); NiceFont(OkButton); CancelButton = CreateWindowEx(0, WC_BUTTON, _("Cancel"), WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE, 218, 41, 70, 23, SimpleDialog, NULL, Instance, NULL); NiceFont(CancelButton); } BOOL ShowSimpleDialog(char *title, int boxes, char **labels, DWORD numOnlyMask, DWORD alnumOnlyMask, DWORD fixedFontMask, char **dests) { BOOL didCancel; if(boxes > MAX_BOXES) oops(); SimpleDialog = CreateWindowClient(0, "LDmicroDialog", title, WS_OVERLAPPED | WS_SYSMENU, 100, 100, 304, 15 + 30*(boxes < 2 ? 2 : boxes), NULL, NULL, Instance, NULL); MakeControls(boxes, labels, fixedFontMask); int i; for(i = 0; i < boxes; i++) { SendMessage(Textboxes[i], WM_SETTEXT, 0, (LPARAM)dests[i]); if(numOnlyMask & (1 << i)) { PrevNumOnlyProc[i] = SetWindowLongPtr(Textboxes[i], GWLP_WNDPROC, (LONG_PTR)MyNumOnlyProc); } if(alnumOnlyMask & (1 << i)) { PrevAlnumOnlyProc[i] = SetWindowLongPtr(Textboxes[i], GWLP_WNDPROC, (LONG_PTR)MyAlnumOnlyProc); } } EnableWindow(MainWindow, FALSE); ShowWindow(SimpleDialog, TRUE); SetFocus(Textboxes[0]); SendMessage(Textboxes[0], EM_SETSEL, 0, -1); MSG msg; DWORD ret; DialogDone = FALSE; DialogCancel = FALSE; while((ret = GetMessage(&msg, NULL, 0, 0)) && !DialogDone) { if(msg.message == WM_KEYDOWN) { if(msg.wParam == VK_RETURN) { DialogDone = TRUE; break; } else if(msg.wParam == VK_ESCAPE) { DialogDone = TRUE; DialogCancel = TRUE; break; } } if(IsDialogMessage(SimpleDialog, &msg)) continue; TranslateMessage(&msg); DispatchMessage(&msg); } didCancel = DialogCancel; if(!didCancel) { for(i = 0; i < boxes; i++) { if(NoCheckingOnBox[i]) { char get[64]; SendMessage(Textboxes[i], WM_GETTEXT, 60, (LPARAM)get); strcpy(dests[i], get); } else { char get[20]; SendMessage(Textboxes[i], WM_GETTEXT, 15, (LPARAM)get); if( (!strchr(get, '\'')) || (get[0] == '\'' && get[2] == '\'' && strlen(get)==3) ) { if(strlen(get) == 0) { Error(_("Empty textbox; not permitted.")); } else { strcpy(dests[i], get); } } else { Error(_("Bad use of quotes: <%s>"), get); } } } } EnableWindow(MainWindow, TRUE); DestroyWindow(SimpleDialog); return !didCancel; } void ShowTimerDialog(int which, int *delay, char *name) { char *s; switch(which) { case ELEM_TON: s = _("Turn-On Delay"); break; case ELEM_TOF: s = _("Turn-Off Delay"); break; case ELEM_RTO: s = _("Retentive Turn-On Delay"); break; default: oops(); break; } char *labels[] = { _("Name:"), _("Delay (ms):") }; char delBuf[16]; char nameBuf[16]; sprintf(delBuf, "%.3f", (*delay / 1000.0)); strcpy(nameBuf, name+1); char *dests[] = { nameBuf, delBuf }; if(ShowSimpleDialog(s, 2, labels, (1 << 1), (1 << 0), (1 << 0), dests)) { name[0] = 'T'; strcpy(name+1, nameBuf); double del = atof(delBuf); if(del > 2140000) { // 2**31/1000, don't overflow signed int Error(_("Delay too long; maximum is 2**31 us.")); } else if(del <= 0) { Error(_("Delay cannot be zero or negative.")); } else { *delay = (int)(1000*del + 0.5); } } } void ShowCounterDialog(int which, int *maxV, char *name) { char *title; switch(which) { case ELEM_CTU: title = _("Count Up"); break; case ELEM_CTD: title = _("Count Down"); break; case ELEM_CTC: title = _("Circular Counter"); break; default: oops(); } char *labels[] = { _("Name:"), (which == ELEM_CTC ? _("Max value:") : _("True if >= :")) }; char maxS[128]; sprintf(maxS, "%d", *maxV); char *dests[] = { name+1, maxS }; ShowSimpleDialog(title, 2, labels, 0x2, 0x1, 0x1, dests); *maxV = atoi(maxS); } void ShowCmpDialog(int which, char *op1, char *op2) { char *title; char *l2; switch(which) { case ELEM_EQU: title = _("If Equals"); l2 = "= :"; break; case ELEM_NEQ: title = _("If Not Equals"); l2 = "/= :"; break; case ELEM_GRT: title = _("If Greater Than"); l2 = "> :"; break; case ELEM_GEQ: title = _("If Greater Than or Equal To"); l2 = ">= :"; break; case ELEM_LES: title = _("If Less Than"); l2 = "< :"; break; case ELEM_LEQ: title = _("If Less Than or Equal To"); l2 = "<= :"; break; default: oops(); } char *labels[] = { _("'Closed' if:"), l2 }; char *dests[] = { op1, op2 }; ShowSimpleDialog(title, 2, labels, 0, 0x3, 0x3, dests); } void ShowMoveDialog(char *dest, char *src) { char *labels[] = { _("Destination:"), _("Source:") }; char *dests[] = { dest, src }; ShowSimpleDialog(_("Move"), 2, labels, 0, 0x3, 0x3, dests); } void ShowReadAdcDialog(char *name) { char *labels[] = { _("Destination:") }; char *dests[] = { name }; ShowSimpleDialog(_("Read A/D Converter"), 1, labels, 0, 0x1, 0x1, dests); } void ShowSetPwmDialog(char *name, int *targetFreq) { char freq[100]; sprintf(freq, "%d", *targetFreq); char *labels[] = { _("Duty cycle var:"), _("Frequency (Hz):") }; char *dests[] = { name, freq }; ShowSimpleDialog(_("Set PWM Duty Cycle"), 2, labels, 0x2, 0x1, 0x1, dests); *targetFreq = atoi(freq); } void ShowUartDialog(int which, char *name) { char *labels[] = { (which == ELEM_UART_RECV) ? _("Destination:") : _("Source:") }; char *dests[] = { name }; ShowSimpleDialog((which == ELEM_UART_RECV) ? _("Receive from UART") : _("Send to UART"), 1, labels, 0, 0x1, 0x1, dests); } void ShowMathDialog(int which, char *dest, char *op1, char *op2) { char *l2, *title; if(which == ELEM_ADD) { l2 = "+ :"; title = _("Add"); } else if(which == ELEM_SUB) { l2 = "- :"; title = _("Subtract"); } else if(which == ELEM_MUL) { l2 = "* :"; title = _("Multiply"); } else if(which == ELEM_DIV) { l2 = "/ :"; title = _("Divide"); } else oops(); char *labels[] = { _("Destination:"), _("is set := :"), l2 }; char *dests[] = { dest, op1, op2 }; ShowSimpleDialog(title, 3, labels, 0, 0x7, 0x7, dests); } void ShowShiftRegisterDialog(char *name, int *stages) { char stagesStr[20]; sprintf(stagesStr, "%d", *stages); char *labels[] = { _("Name:"), _("Stages:") }; char *dests[] = { name, stagesStr }; ShowSimpleDialog(_("Shift Register"), 2, labels, 0x2, 0x1, 0x1, dests); *stages = atoi(stagesStr); if(*stages <= 0 || *stages >= 200) { Error(_("Not a reasonable size for a shift register.")); *stages = 1; } } void ShowFormattedStringDialog(char *var, char *string) { char *labels[] = { _("Variable:"), _("String:") }; char *dests[] = { var, string }; NoCheckingOnBox[0] = TRUE; NoCheckingOnBox[1] = TRUE; ShowSimpleDialog(_("Formatted String Over UART"), 2, labels, 0x0, 0x1, 0x3, dests); NoCheckingOnBox[0] = FALSE; NoCheckingOnBox[1] = FALSE; } void ShowPersistDialog(char *var) { char *labels[] = { _("Variable:") }; char *dests[] = { var }; ShowSimpleDialog(_("Make Persistent"), 1, labels, 0, 1, 1, dests); }