/* ----------------- dialbox.c -------------- */ #include "dflat.h" static char path[MAXPATH]; static char drive[MAXDRIVE] = " :"; static char dir[MAXDIR]; static char name[MAXFILE]; static char ext[MAXEXT]; static int inFocusCommand(DBOX *); static void dbShortcutKeys(DBOX *, int); static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM); static void ChangeFocus(WINDOW, int); static CTLWINDOW *AssociatedControl(DBOX *, enum commands); static void SetRadioButton(DBOX *, CTLWINDOW *); static int SysMenuOpen; int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2) { DBOX *db = wnd->extension; CTLWINDOW *ct; WINDOW cwnd; int rtn; switch (msg) { case CREATE_WINDOW: rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2); ct = db->ctl; while (ct->class) { int attrib = VISIBLE; if (TestAttribute(wnd, NOCLIP)) attrib |= NOCLIP; if (wnd->Modal) attrib |= SAVESELF; ct->setting = ct->isetting; if (ct->class == EDITBOX && ct->dwnd.h > 1) attrib |= (MULTILINE | HASBORDER); else if (ct->class == LISTBOX || ct->class == TEXTBOX) attrib |= HASBORDER; cwnd = CreateWindow(ct->class, ct->dwnd.title, ct->dwnd.x+GetClientLeft(wnd), ct->dwnd.y+GetClientTop(wnd), ct->dwnd.h, ct->dwnd.w, ct, wnd, ControlProc, attrib); if ((ct->class == EDITBOX || ct->class == COMBOBOX) && ct->itext != NULL) SendMessage(cwnd, SETTEXT, (PARAM) ct->itext, 0); if (ct->class != BOX && ct->class != TEXT && wnd->dFocus == NULL) wnd->dFocus = ct; ct++; } return rtn; case SETFOCUS: if (wnd->Modal) { if (p1) SendMessage(inFocus, SETFOCUS, FALSE, 0); inFocus = p1 ? wnd : NULL; return TRUE; } break; case SHIFT_CHANGED: if (wnd->Modal) return TRUE; break; case LEFT_BUTTON: if (WindowSizing || WindowMoving) return FALSE; if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd))) { PostMessage(wnd, KEYBOARD, ' ', ALTKEY); return TRUE; } ct = db->ctl; while (ct->class) { WINDOW cwnd = ct->wnd; if (ct->class == COMBOBOX) { if (p2 == GetTop(cwnd)) { if (p1 == GetRight(cwnd)+1) { SendMessage(cwnd, msg, p1, p2); return TRUE; } } if (GetClass(inFocus) == LISTBOX) SendMessage(wnd, SETFOCUS, TRUE, 0); } else if (ct->class == SPINBUTTON) { if (p2 == GetTop(cwnd)) { if (p1 == GetRight(cwnd)+1 || p1 == GetRight(cwnd)+2) { SendMessage(cwnd, msg, p1, p2); return TRUE; } } } ct++; } break; case KEYBOARD: if (WindowMoving || WindowSizing) break; switch ((int)p1) { case F1: ct = wnd->dFocus; if (ct != NULL) if (DisplayHelp(wnd, ct->help)) return TRUE; break; case SHIFT_HT: case BS: case UP: ChangeFocus(wnd, FALSE); break; case ALT_F6: case '\t': case FWD: case DN: ChangeFocus(wnd, TRUE); break; case ' ': if (((int)p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX)) { SysMenuOpen = TRUE; BuildSystemMenu(wnd); } break; case CTRL_F4: case ESC: SendMessage(wnd, COMMAND, ID_CANCEL, 0); break; default: /* ------ search all the shortcut keys ----- */ dbShortcutKeys(db, (int) p1); break; } if (wnd->Modal) return TRUE; break; case CLOSE_POPDOWN: SysMenuOpen = FALSE; break; case LB_SELECTION: case LB_CHOOSE: if (SysMenuOpen) return TRUE; SendMessage(wnd, COMMAND, inFocusCommand(db), msg); break; case COMMAND: switch ((int) p1) { case ID_OK: case ID_CANCEL: if ((int)p2 != 0) return TRUE; wnd->ReturnCode = (int) p1; if (wnd->Modal) PostMessage(wnd, ENDDIALOG, 0, 0); else SendMessage(wnd, CLOSE_WINDOW, TRUE, 0); return TRUE; case ID_HELP: if ((int)p2 != 0) return TRUE; return DisplayHelp(wnd, db->HelpName); default: break; } break; case PAINT: p2 = TRUE; break; case CLOSE_WINDOW: if (!p1) { SendMessage(wnd, COMMAND, ID_CANCEL, 0); return TRUE; } break; default: break; } return BaseWndProc(DIALOG, wnd, msg, p1, p2); } int DialogBox(WINDOW wnd, DBOX *db, int Modal, int (*wndproc)(struct window *, enum messages, PARAM, PARAM)) { int rtn; int x = db->dwnd.x, y = db->dwnd.y; CTLWINDOW *ct; WINDOW oldFocus = inFocus; WINDOW DialogWnd; if (!Modal && wnd != NULL) { x += GetLeft(wnd); y += GetTop(wnd); } DialogWnd = CreateWindow(DIALOG, db->dwnd.title, x, y, db->dwnd.h, db->dwnd.w, db, wnd, wndproc, Modal ? SAVESELF : 0); DialogWnd->Modal = Modal; SendMessage(((CTLWINDOW *)(DialogWnd->dFocus))->wnd, SETFOCUS, TRUE, 0); SendMessage(DialogWnd, SHOW_WINDOW, 0, 0); SendMessage(DialogWnd, INITIATE_DIALOG, 0, 0); if (Modal) { SendMessage(DialogWnd, CAPTURE_MOUSE, 0, 0); SendMessage(DialogWnd, CAPTURE_KEYBOARD, 0, 0); while (dispatch_message()) ; rtn = DialogWnd->ReturnCode == ID_OK; SendMessage(DialogWnd, RELEASE_MOUSE, 0, 0); SendMessage(DialogWnd, RELEASE_KEYBOARD, 0, 0); SendMessage(inFocus, SETFOCUS, FALSE, 0); SendMessage(DialogWnd, CLOSE_WINDOW, TRUE, 0); SendMessage(oldFocus, SETFOCUS, TRUE, 0); if (rtn) { ct = db->ctl; while (ct->class) { ct->wnd = NULL; if (ct->class == RADIOBUTTON || ct->class == CHECKBOX) ct->isetting = ct->setting; ct++; } } return rtn; } return FALSE; } static int inFocusCommand(DBOX *db) { CTLWINDOW *ct = db->ctl; while (ct->class) { if (ct->wnd == inFocus) return ct->command; ct++; } return -1; } CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class) { CTLWINDOW *ct = db->ctl; while (ct->class) { if (ct->class == class) if (cmd == ct->command) return ct; ct++; } return NULL; } WINDOW ControlWindow(DBOX *db, enum commands cmd) { CTLWINDOW *ct = db->ctl; while (ct->class) { if (ct->class != TEXT && cmd == ct->command) return ct->wnd; ct++; } return NULL; } void PushRadioButton(DBOX *db, enum commands cmd) { CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON); if (ct != NULL) { SetRadioButton(db, ct); ct->isetting = ON; } } static struct { CTLWINDOW *rct; } rbs[MAXRADIOS]; static void SetRadioButton(DBOX *db, CTLWINDOW *ct) { CTLWINDOW *ctt = db->ctl; int i; /* --- clear all the radio buttons in this group on the dialog box --- */ /* -------- build a table of all radio buttons at the same x vector ---------- */ for (i = 0; i < MAXRADIOS; i++) rbs[i].rct = NULL; while (ctt->class) { if (ctt->class == RADIOBUTTON) if (ct->dwnd.x == ctt->dwnd.x) rbs[ctt->dwnd.y].rct = ctt; ctt++; } /* ----- find the start of the radiobutton group ---- */ i = ct->dwnd.y; while (i >= 0 && rbs[i].rct != NULL) --i; /* ---- ignore everthing before the group ------ */ while (i >= 0) rbs[i--].rct = NULL; /* ----- find the end of the radiobutton group ---- */ i = ct->dwnd.y; while (i < MAXRADIOS && rbs[i].rct != NULL) i++; /* ---- ignore everthing past the group ------ */ while (i < MAXRADIOS) rbs[i++].rct = NULL; for (i = 0; i < MAXRADIOS; i++) { if (rbs[i].rct != NULL) { int wason = rbs[i].rct->setting; rbs[i].rct->setting = OFF; if (wason) SendMessage(rbs[i].rct->wnd, PAINT, 0, 0); } } ct->setting = ON; SendMessage(ct->wnd, PAINT, 0, 0); } int RadioButtonSetting(DBOX *db, enum commands cmd) { CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON); if (ct != NULL) return (ct->setting == ON); return FALSE; } static void ControlSetting(DBOX *db, enum commands cmd, int class, int setting) { CTLWINDOW *ct = FindCommand(db, cmd, class); if (ct != NULL) ct->isetting = setting; } void SetCheckBox(DBOX *db, enum commands cmd) { ControlSetting(db, cmd, CHECKBOX, ON); } void ClearCheckBox(DBOX *db, enum commands cmd) { ControlSetting(db, cmd, CHECKBOX, OFF); } void EnableButton(DBOX *db, enum commands cmd) { ControlSetting(db, cmd, BUTTON, ON); } void DisableButton(DBOX *db, enum commands cmd) { ControlSetting(db, cmd, BUTTON, OFF); } int CheckBoxSetting(DBOX *db, enum commands cmd) { CTLWINDOW *ct = FindCommand(db, cmd, CHECKBOX); if (ct != NULL) return (ct->isetting == ON); return FALSE; } char *GetDlgTextString(DBOX *db, enum commands cmd, CLASS class) { CTLWINDOW *ct = FindCommand(db, cmd, class); if (ct != NULL) return ct->itext; else return NULL; } void SetDlgTextString(DBOX *db, enum commands cmd, char *text, CLASS class) { CTLWINDOW *ct = FindCommand(db, cmd, class); if (ct != NULL) { ct->itext = realloc(ct->itext, strlen(text)+1); if (ct->itext != NULL) strcpy(ct->itext, text); } } void PutComboListText(WINDOW wnd, enum commands cmd, char *text) { CTLWINDOW *ct = FindCommand(wnd->extension, cmd, COMBOBOX); if (ct != NULL) { WINDOW lwnd = ((WINDOW)(ct->wnd))->extension; SendMessage(lwnd, ADDTEXT, (PARAM) text, 0); } } void PutItemText(WINDOW wnd, enum commands cmd, char *text) { CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, TEXTBOX); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, COMBOBOX); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, LISTBOX); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, SPINBUTTON); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, TEXT); if (ct != NULL) { WINDOW cwnd = (WINDOW) (ct->wnd); switch (ct->class) { case COMBOBOX: case EDITBOX: SendMessage(cwnd, CLEARTEXT, 0, 0); SendMessage(cwnd, ADDTEXT, (PARAM) text, 0); if (!isMultiLine(cwnd)) SendMessage(cwnd, PAINT, 0, 0); break; case LISTBOX: case TEXTBOX: case SPINBUTTON: SendMessage(cwnd, ADDTEXT, (PARAM) text, 0); break; case TEXT: { SendMessage(cwnd, CLEARTEXT, 0, 0); SendMessage(cwnd, ADDTEXT, (PARAM) text, 0); SendMessage(cwnd, PAINT, 0, 0); break; } default: break; } } } void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len) { CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, COMBOBOX); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, TEXTBOX); if (ct == NULL) ct = FindCommand(wnd->extension, cmd, TEXT); if (ct != NULL) { WINDOW cwnd = (WINDOW) (ct->wnd); if (cwnd != NULL) { switch (ct->class) { case TEXT: if (GetText(cwnd) != NULL) { unsigned char *cp = strchr(GetText(cwnd), '\n'); if (cp != NULL) len = (int) (cp - GetText(cwnd)); strncpy(text, GetText(cwnd), len); *(text+len) = '\0'; } break; case TEXTBOX: if (GetText(cwnd) != NULL) strncpy(text, GetText(cwnd), len); break; case COMBOBOX: case EDITBOX: SendMessage(cwnd, GETTEXT, (PARAM) text, len); break; default: break; } } } } void GetDlgListText(WINDOW wnd, char *text, enum commands cmd) { CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX); int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0); SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel); } static int dircmp(const void *c1, const void *c2) { return stricmp(*(char **)c1, *(char **)c2); } int DlgDirList(WINDOW wnd, char *fspec, enum commands nameid, enum commands pathid, unsigned attrib) { int ax, i = 0, criterr = 1; struct ffblk ff; CTLWINDOW *ct = FindCommand(wnd->extension, nameid, LISTBOX); WINDOW lwnd; char **dirlist = NULL; CreatePath(path, fspec, TRUE, TRUE); if (ct != NULL) { lwnd = ct->wnd; SendMessage(ct->wnd, CLEARTEXT, 0, 0); if (attrib & 0x8000) { union REGS regs; char drname[15]; unsigned int cd, dr; cd = getdisk(); for (dr = 0; dr < 26; dr++) { unsigned ndr; setdisk(dr); ndr = getdisk(); if (ndr == dr) { /* ------- test for remapped B drive ------- */ if (dr == 1) { regs.x.ax = 0x440e; /* IOCTL function 14 */ regs.h.bl = dr+1; int86(DOS, ®s, ®s); if (regs.h.al != 0) continue; } sprintf(drname, "[%c:]", dr+'A'); /* ------ test for network or RAM disk ---- */ regs.x.ax = 0x4409; /* IOCTL function 9 */ regs.h.bl = dr+1; int86(DOS, ®s, ®s); if (!regs.x.cflag) { if (regs.x.dx & 0x1000) strcat(drname, " (Network)"); else if (regs.x.dx == 0x0800) strcat(drname, " (RAMdisk)"); } SendMessage(lwnd, ADDTEXT, (PARAM) drname, 0); } } setdisk(cd); } while (criterr == 1) { ax = findfirst(path, &ff, attrib & 0x3f); criterr = TestCriticalError(); } if (criterr) return FALSE; while (ax == 0) { if (!((attrib & 0x4000) && (ff.ff_attrib & (attrib & 0x3f)) == 0) && strcmp(ff.ff_name, ".")) { char fname[15]; sprintf(fname, (ff.ff_attrib & 0x10) ? "[%s]" : "%s" , ff.ff_name); dirlist = realloc(dirlist, sizeof(char *)*(i+1)); if (dirlist != NULL) { dirlist[i] = malloc(strlen(fname)+1); if (dirlist[i] != NULL) strcpy(dirlist[i], fname); i++; } } ax = findnext(&ff); } if (dirlist != NULL) { int j; /* -- sort file/drive/directory list box data -- */ qsort(dirlist, i, sizeof(void *), dircmp); /* ---- send sorted list to list box ---- */ for (j = 0; j < i; j++) { SendMessage(lwnd, ADDTEXT, (PARAM) dirlist[j], 0); free(dirlist[j]); } free(dirlist); } SendMessage(lwnd, SHOW_WINDOW, 0, 0); } if (pathid) { fnmerge(path, drive, dir, NULL, NULL); PutItemText(wnd, pathid, path); } return TRUE; } static CTLWINDOW *AssociatedControl(DBOX *db, enum commands Tcmd) { CTLWINDOW *ct = db->ctl; while (ct->class) { if (ct->class != TEXT) if (ct->command == Tcmd) break; ct++; } return ct; } static void dbShortcutKeys(DBOX *db, int ky) { CTLWINDOW *ct; int ch = AltConvert(ky); if (ch != 0) { ct = db->ctl; while (ct->class) { char *cp = ct->itext; while (cp && *cp) { if (*cp == SHORTCUTCHAR && tolower(*(cp+1)) == ch) { if (ct->class == TEXT) ct = AssociatedControl(db, ct->command); if (ct->class == RADIOBUTTON) SetRadioButton(db, ct); else if (ct->class == CHECKBOX) { ct->setting ^= ON; SendMessage(ct->wnd, PAINT, 0, 0); } else if (ct->class) { SendMessage(ct->wnd, SETFOCUS, TRUE, 0); if (ct->class == BUTTON) SendMessage(ct->wnd, KEYBOARD, '\r', 0); } return; } cp++; } ct++; } } } /* generic window processor used by all dialog box control windows */ static int ControlProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2) { DBOX *db; CTLWINDOW *ct; if (wnd == NULL) return FALSE; db = GetParent(wnd) ? GetParent(wnd)->extension : NULL; ct = GetControl(wnd); switch (msg) { case CREATE_WINDOW: ct = wnd->ct = wnd->extension; wnd->extension = NULL; if (ct != NULL) ct->wnd = wnd; break; case KEYBOARD: switch ((int) p1) { case F1: if (WindowMoving || WindowSizing) break; if (!DisplayHelp(wnd, ct->help)) SendMessage(GetParent(wnd), COMMAND, ID_HELP, 0); return TRUE; case ' ': if (!((int)p2 & ALTKEY)) break; case ALT_F6: case CTRL_F4: case ALT_F4: PostMessage(GetParent(wnd), msg, p1, p2); return TRUE; default: break; } if (GetClass(wnd) == EDITBOX) if (isMultiLine(wnd)) break; switch ((int) p1) { case UP: if (!isDerivedFrom(wnd, LISTBOX)) { p1 = CTRL_FIVE; p2 = LEFTSHIFT; } break; case BS: if (!isDerivedFrom(wnd, EDITBOX)) { p1 = CTRL_FIVE; p2 = LEFTSHIFT; } break; case DN: if (!isDerivedFrom(wnd, LISTBOX) && !isDerivedFrom(wnd, COMBOBOX)) p1 = '\t'; break; case FWD: if (!isDerivedFrom(wnd, EDITBOX)) p1 = '\t'; break; case '\r': if (isDerivedFrom(wnd, EDITBOX)) if (isMultiLine(wnd)) break; if (isDerivedFrom(wnd, BUTTON)) break; SendMessage(GetParent(wnd), COMMAND, ID_OK, 0); return TRUE; default: break; } break; case PAINT: if (GetClass(wnd) == EDITBOX || GetClass(wnd) == LISTBOX || GetClass(wnd) == TEXTBOX) { int oldattr = GetAttribute(wnd); if (wnd->wlines > ClientHeight(wnd)) AddAttribute(wnd, VSCROLLBAR); else ClearAttribute(wnd, VSCROLLBAR); if (wnd->textwidth > ClientWidth(wnd)) AddAttribute(wnd, HSCROLLBAR); else ClearAttribute(wnd, HSCROLLBAR); if (GetAttribute(wnd) != oldattr) SendMessage(wnd, BORDER, 0, 0); } break; case BORDER: if (GetClass(wnd) == EDITBOX) { WINDOW oldFocus = inFocus; inFocus = NULL; DefaultWndProc(wnd, msg, p1, p2); inFocus = oldFocus; return TRUE; } break; case SETFOCUS: if (p1) { DefaultWndProc(wnd, msg, p1, p2); GetParent(wnd)->dFocus = ct; SendMessage(GetParent(wnd), COMMAND, inFocusCommand(db), ENTERFOCUS); return TRUE; } else SendMessage(GetParent(wnd), COMMAND, inFocusCommand(db), LEAVEFOCUS); break; case CLOSE_WINDOW: if (ct != NULL) if (GetParent(wnd)->ReturnCode == ID_OK && (ct->class == EDITBOX || ct->class == COMBOBOX)) if (wnd->TextChanged) if ((ct->itext = realloc(ct->itext, strlen(wnd->text)+1)) != NULL) { strcpy(ct->itext, wnd->text); if (!isMultiLine(wnd)) { char *cp = ct->itext+strlen(ct->itext)-1; if (*cp == '\n') *cp = '\0'; } } break; default: break; } return DefaultWndProc(wnd, msg, p1, p2); } /* ----- Create unambiguous path from file spec, filling in the drive and directory if incomplete. Optionally change to the new drive and subdirectory ------ */ void CreatePath(char *path, char *fspec, int InclName, int Change) { int cm = 0; unsigned currdrive; char currdir[64]; char *cp; if (!Change) { /* ----- save the current drive and subdirectory ----- */ currdrive = getdisk(); getcwd(currdir, sizeof currdir); memmove(currdir, currdir+2, strlen(currdir+1)); cp = currdir+strlen(currdir)-1; if (*cp == '\\') *cp = '\0'; } *drive = *dir = *name = *ext = '\0'; fnsplit(fspec, drive, dir, name, ext); if (!InclName) *name = *ext = '\0'; *drive = toupper(*drive); if (*ext) cm |= EXTENSION; if (InclName && *name) cm |= FILENAME; if (*dir) cm |= DIRECTORY; if (*drive) cm |= DRIVE; if (cm & DRIVE) setdisk(*drive - 'A'); else { *drive = getdisk(); *drive += 'A'; } if (cm & DIRECTORY) { cp = dir+strlen(dir)-1; if (*cp == '\\') *cp = '\0'; chdir(dir); } getcwd(dir, sizeof dir); memmove(dir, dir+2, strlen(dir+1)); if (InclName) { if (!(cm & FILENAME)) strcpy(name, "*"); if (!(cm & EXTENSION) && strchr(fspec, '.') != NULL) strcpy(ext, ".*"); } else *name = *ext = '\0'; if (dir[strlen(dir)-1] != '\\') strcat(dir, "\\"); memset(path, 0, sizeof path); fnmerge(path, drive, dir, name, ext); if (!Change) { setdisk(currdrive); chdir(currdir); } } static void ChangeFocus(WINDOW wnd, int direc) { DBOX *db = wnd->extension; CTLWINDOW *ct = db->ctl; CTLWINDOW *ctt; /* --- find the control that has the focus --- */ while (ct->class) { if (ct == wnd->dFocus) break; ct++; } if (ct->class) { ctt = ct; do { /* ----- point to next or previous control ----- */ if (direc) { ct++; if (ct->class == 0) ct = db->ctl; } else { if (ct == db->ctl) while (ct->class) ct++; --ct; } if (ct->class != BOX && ct->class != TEXT) { SendMessage(ct->wnd, SETFOCUS, TRUE, 0); SendMessage(ctt->wnd, PAINT, 0, 0); SendMessage(ct->wnd, PAINT, 0, 0); break; } } while (ct != ctt); } }