/* ----------------- dialbox.c -------------- */ #include #include #include #ifdef MSC #include #else #include #endif #include #include #include "dflat.h" static int inFocusCommand(DBOX *); static void SetRadioButton(WINDOW, DBOX *, CTLWINDOW *); static void dbShortcutKeys(WINDOW, DBOX *, int); static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM); static int SysMenuOpen = FALSE; int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2) { int rtn; DBOX *db; CTLWINDOW *ct; db = wnd->extension; switch (msg) { case SETFOCUS: if (p1) 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) { if (ct->class == RADIOBUTTON) { int mx = (int) p1 - GetClientLeft(wnd); int my = (int) p2 - GetClientTop(wnd); if (my == ct->dwnd.y && mx == ct->dwnd.x+1) SetRadioButton(wnd, db, ct); } ct++; } break; case PAINT: if (!isVisible(wnd)) break; if (!p2) BaseWndProc(DIALOG, wnd, msg, p1, p2); ct = p2 ? (CTLWINDOW *) p2 : db->ctl; while (ct->class) { if (ct->class == RADIOBUTTON) { char rb[] = "( )"; if (ct->itext) rb[1] = 7; SetClassColors(BUTTON); writeline(wnd, rb, ct->dwnd.x, ct->dwnd.y, FALSE); } else if (ct->class == TEXT && ct->vtext != NULL) { char txt[100]; char *cp = ct->vtext; int len = min(ct->dwnd.h, MsgHeight(cp)); int i; for (i = 0; i < len; i++) { int mlen, dif; char *np = strchr(cp, '\n'); memset(txt, ' ', sizeof txt); mlen = CopyCommand(txt, cp, FALSE, WndBackground(wnd)); if (np == NULL) dif = mlen - strlen(cp); else dif = mlen - (int) (np - cp); txt[ct->dwnd.w + 1 + dif] = '\0'; SetStandardColor(wnd); writeline(wnd, txt, ct->dwnd.x, ct->dwnd.y+i, FALSE); if ((cp = strchr(cp, '\n')) != NULL) cp++; } } ct++; if (p2) break; } return TRUE; case KEYBOARD: switch ((int)p1) { case '\t': case ALT_F6: SetNextFocus(inFocus, FALSE); break; case ' ': if ((p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX)) { wnd->dFocus = inFocus; SysMenuOpen = TRUE; BuildSystemMenu(wnd); } break; case ALT_F4: case ESC: if (!(WindowMoving || WindowSizing)) SendMessage(wnd, COMMAND, ID_CANCEL, 0); case UP: case DN: case BS: case FWD: case '\r': if (WindowMoving || WindowSizing) return BaseWndProc(DIALOG, wnd, msg, p1, p2); break; default: /* ------ search all the shortcut keys ----- */ dbShortcutKeys(wnd, db, (int) p1); break; } return TRUE; case CLOSE_POPDOWN: SysMenuOpen = FALSE; break; case BUTTON_RELEASED: if (!WindowMoving && !WindowSizing) break; rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2); SendMessage(wnd->dFocus, SETFOCUS, TRUE, 0); return rtn; 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: wnd->ReturnCode = (int) p1; PostMessage(wnd, ENDDIALOG, 0, 0); return TRUE; default: break; } break; case CLOSE_WINDOW: if (!p1) SendMessage(wnd, COMMAND, ID_CANCEL, 0); else { ct = db->ctl; while (ct->class) { if (ct->vtext != NULL && ct->class == TEXT) { free(ct->vtext); ct->vtext = NULL; } ct++; } } break; default: break; } return BaseWndProc(DIALOG, wnd, msg, p1, p2); } int DialogBox(WINDOW wnd, DBOX *db, int (*wndproc)(struct window *, enum messages, PARAM, PARAM)) { int rtn; WINDOW Dwnd; CTLWINDOW *ct; WINDOW oldFocus = inFocus; Dwnd = CreateWindow(DIALOG, db->dwnd.title, db->dwnd.x, db->dwnd.y, db->dwnd.h, db->dwnd.w, db, wnd, wndproc, NOCLIP); ct = db->ctl; while (ct->class) { if (ct->class != TEXT && ct->class != RADIOBUTTON) { WINDOW cwnd; int attrib = 0; ct->vtext = ct->itext; if ((ct->class == EDITBOX || ct->class == LISTBOX) && ct->dwnd.h > 1) attrib |= (MULTILINE | HASBORDER); cwnd = CreateWindow(ct->class, ct->dwnd.title, ct->dwnd.x+GetClientLeft(Dwnd), ct->dwnd.y+GetClientTop(Dwnd), ct->dwnd.h, ct->dwnd.w, ct, Dwnd, ControlProc, attrib); ct->wnd = cwnd; if (Dwnd->dFocus == NULLWND) Dwnd->dFocus = cwnd; if (ct->itext) { char txt[SCREENWIDTH]; memset(txt, '\0', sizeof txt); CopyCommand(txt, ct->itext, FALSE, WndBackground(cwnd)); SendMessage(cwnd, ADDTEXT, (PARAM) txt, 0); } } else if (ct->class == TEXT && ct->itext != NULL) { int len = strlen(ct->itext)+1; ct->vtext = malloc(len); strncpy(ct->vtext, ct->itext, len); } ct++; } SendMessage(Dwnd->dFocus, SETFOCUS, TRUE, 0); SendMessage(Dwnd, SHOW_WINDOW, 0, 0); SendMessage(Dwnd, INITIATE_DIALOG, 0, 0); SendMessage(Dwnd, CAPTURE_MOUSE, 0, 0); SendMessage(Dwnd, CAPTURE_KEYBOARD, 0, 0); while (dispatch_message()) ; rtn = Dwnd->ReturnCode == ID_OK; SendMessage(Dwnd, RELEASE_MOUSE, 0, 0); SendMessage(Dwnd, RELEASE_KEYBOARD, 0, 0); SendMessage(Dwnd, CLOSE_WINDOW, TRUE, 0); SendMessage(oldFocus, SETFOCUS, TRUE, TRUE); return rtn; } static int inFocusCommand(DBOX *db) { CTLWINDOW *ct = db->ctl; while (ct->class) { if (ct->wnd == inFocus) return ct->command; ct++; } return -1; } static CTLWINDOW *FindCommand(DBOX *db, enum commands cmd) { CTLWINDOW *ct = db->ctl; while (ct->class) { if (cmd == ct->command) return ct; ct++; } return NULL; } void PushRadioButton(DBOX *db, enum commands cmd) { CTLWINDOW *ct = FindCommand(db, cmd); SetRadioButton(NULLWND, db, ct); } static void SetRadioButton(WINDOW wnd, DBOX *db, CTLWINDOW *ct) { CTLWINDOW *ctt = db->ctl; while (ctt->class) { if (ctt->class == RADIOBUTTON) { ctt->itext = OFF; if (wnd != NULLWND) SendMessage(wnd, PAINT, 0, (PARAM) ctt); } ctt++; } ct->itext = ON; if (wnd != NULLWND) { SendMessage(wnd, PAINT, 0, (PARAM) ct); PostMessage(GetParent(wnd), COMMAND, ct->command, 0); } } int RadioButtonSetting(DBOX *db, enum commands cmd) { CTLWINDOW *ct = FindCommand(db, cmd); if (ct != NULL && ct->class == RADIOBUTTON) return (ct->itext != NULL); return FALSE; } void PutItemText(WINDOW wnd, enum commands cmd, char *text) { CTLWINDOW *ct = FindCommand(wnd->extension, cmd); if (ct != NULL) { switch (ct->class) { case EDITBOX: SendMessage(ct->wnd, EB_PUTTEXT, (PARAM) text, 0); SendMessage(ct->wnd, PAINT, 0, 0); break; case TEXT: { ct->vtext = realloc(ct->vtext, strlen(text)+1); strcpy(ct->vtext, text); SendMessage(wnd, PAINT, 0, (PARAM) ct); break; } default: break; } } } void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len) { CTLWINDOW *ct = FindCommand(wnd->extension, cmd); if (ct != NULL) { switch (ct->class) { case EDITBOX: SendMessage(ct->wnd, EB_GETTEXT, (PARAM) text, len); break; case TEXT: strncpy(text, ct->vtext, len); break; default: break; } } } void GetDlgListText(WINDOW wnd, char *text, enum commands cmd) { CTLWINDOW *ct = FindCommand(wnd->extension, cmd); int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0); SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel); } int DlgDirList(WINDOW wnd, char *fspec, enum commands nameid, enum commands pathid, unsigned attrib) { static char drive[MAXDRIVE] = " :"; static char dir[MAXDIR]; static char path[MAXPATH]; static char name[MAXFILE]; static char ext[MAXEXT]; int cm; int ax, criterr = 1; struct ffblk ff; CTLWINDOW *ct = FindCommand(wnd->extension, nameid); WINDOW lwnd; cm = #ifdef MSC 0; #endif fnsplit(fspec, drive, dir, name, ext); *drive = toupper(*drive); #ifdef MSC if (*ext) cm |= EXTENSION; if (*name) cm |= FILENAME; if (*dir) cm |= DIRECTORY; if (*drive) cm |= DRIVE; #endif if (cm & DRIVE) setdisk(*drive - 'A'); if (cm & DIRECTORY) { char *cp = dir+strlen(dir)-1; if (*cp == '\\') *cp = '\0'; chdir(dir); } if (!(cm & DRIVE)) { #ifdef MSC _dos_getdrive((unsigned *)drive); *drive -= 1; #else *drive = getdisk(); #endif *drive += 'A'; } getcwd(dir, sizeof dir); if ((attrib & 0x10) || !(cm & FILENAME)) strcpy(name, "*"); if ((attrib & 0x10) || !(cm & EXTENSION)) strcpy(ext, ".*"); fnmerge(path, drive, dir+2, name, ext); if (ct != NULL) { lwnd = ct->wnd; SendMessage(ct->wnd, CLEARTEXT, 0, 0); if (attrib & 0x8000) { union REGS regs; char drname[15]; int cd, dr; #ifdef MSC _dos_getdrive(&cd); cd -= 1; #else cd = getdisk(); #endif for (dr = 0; dr < 26; dr++) { unsigned ndr; setdisk(dr); #ifdef MSC _dos_getdrive(&ndr); ndr -= 1; #else ndr = getdisk(); #endif 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(ct->wnd, 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); SendMessage(ct->wnd, ADDTEXT, (PARAM) fname, 0); } ax = findnext(&ff); } if (lwnd->wlines > ClientHeight(lwnd)) AddAttribute(lwnd, VSCROLLBAR); else ClearAttribute(lwnd, VSCROLLBAR); PostMessage(lwnd, SHOW_WINDOW, 0, 0); } if (pathid) { fnmerge(path, drive, dir+2, NULL, NULL); PutItemText(wnd, pathid, path); } return TRUE; } int MsgHeight(char *msg) { int h = 1; while ((msg = strchr(msg, '\n')) != NULL) { h++; msg++; } return h; } int MsgWidth(char *msg) { int w = 0; char *cp = msg; while ((cp = strchr(msg, '\n')) != NULL) { w = max(w, (int) (cp-msg)); msg = cp+1; } return w == 0 ? strlen(msg) : w; } static void dbShortcutKeys(WINDOW wnd, DBOX *db, int ky) { int i; CTLWINDOW *ct; for (i = 0; i < 36; i++) if ((char) ky == altconvert[i]) break; if (i < 36) { ct = db->ctl; while (ct->class) { char *cp = ct->vtext; while (*cp) { if (*cp == SHORTCUTCHAR) { int ch; if (i < 26) ch = 'a' + i; else ch = '0' + i - 26; if (tolower(*(cp+1)) == ch) { if (ct->class == TEXT) ct++; if (ct->class == RADIOBUTTON) SetRadioButton(wnd, db, ct); else SendMessage(ct->wnd, SETFOCUS, TRUE, 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 = GetParent(wnd)->extension; switch (msg) { case KEYBOARD: if (GetClass(wnd) == EDITBOX && !isMultiLine(wnd)) { if ((int) p1 == '\r') { SendMessage(GetParent(wnd), COMMAND, ID_OK, 0); return TRUE; } } break; case SETFOCUS: if (GetClass(wnd) != BUTTON) { if (p1) { DefaultWndProc(wnd, msg, p1, p2); SendMessage(GetParent(wnd), COMMAND, inFocusCommand(db), ENTERFOCUS); return TRUE; } else SendMessage(GetParent(wnd), COMMAND, inFocusCommand(db), LEAVEFOCUS); } break; default: break; } return DefaultWndProc(wnd, msg, p1, p2); }