home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 08 / dflat5 / dialbox.c < prev    next >
Text File  |  1991-06-27  |  21KB  |  910 lines

  1. /* ----------------- dialbox.c -------------- */
  2.  
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <stdlib.h>
  6. #ifdef MSC
  7. #include <direct.h>
  8. #else
  9. #include <dir.h>
  10. #endif
  11. #include <dos.h>
  12. #include <io.h>
  13. #include "dflat.h"
  14.  
  15. static char path[MAXPATH];
  16. static char drive[MAXDRIVE] = " :";
  17. static char dir[MAXDIR];
  18. static char name[MAXFILE];
  19. static char ext[MAXEXT];
  20.  
  21. #ifdef INCLUDE_DIALOG_BOXES
  22.  
  23. static int inFocusCommand(DBOX *);
  24. static void SetRadioButton(WINDOW, DBOX *, CTLWINDOW *);
  25. static void InvertCheckBox(WINDOW, CTLWINDOW *);
  26. static void dbShortcutKeys(WINDOW, DBOX *, int);
  27. static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM);
  28. static void ChangeFocus(WINDOW, int);
  29.  
  30. #ifdef INCLUDE_SYSTEM_MENUS
  31. static int SysMenuOpen = FALSE;
  32. #endif
  33.  
  34. int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  35. {
  36.     int rtn;
  37.     DBOX *db;
  38.     CTLWINDOW *ct;
  39.  
  40.     db = wnd->extension;
  41.  
  42.     switch (msg)    {
  43.         case SHIFT_CHANGED:
  44.             return TRUE;
  45.         case LEFT_BUTTON:
  46. #ifdef INCLUDE_SYSTEM_MENUS
  47.             if (WindowSizing || WindowMoving)
  48.                 return FALSE;
  49. #endif
  50.             if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd)))    {
  51.                 PostMessage(wnd, KEYBOARD, ' ', ALTKEY);
  52.                 return TRUE;
  53.             }
  54.             ct = db->ctl;
  55.             while (ct->class)    {
  56.                 int mx = (int) p1 - GetClientLeft(wnd);
  57.                 int my = (int) p2 - GetClientTop(wnd);
  58.                 if (ct->class == RADIOBUTTON)    {
  59.                     if (my == ct->dwnd.y && mx == ct->dwnd.x+1)
  60.                         SetRadioButton(wnd, db, ct);
  61.                 }
  62.                 else if (ct->class == CHECKBOX)    {
  63.                     if (my == ct->dwnd.y && mx == ct->dwnd.x+1)
  64.                         InvertCheckBox(wnd, ct);
  65.                 }
  66.                 ct++;
  67.             }
  68.             break;
  69.         case PAINT:
  70.             if (!isVisible(wnd))
  71.                 break;
  72.             if (!p2)
  73.                 BaseWndProc(DIALOG, wnd, msg, p1, p2);
  74.             ct = p2 ? (CTLWINDOW *) p2 : db->ctl;
  75.             while (ct->class)    {
  76.                 if (ct->class == RADIOBUTTON)    {
  77.                     char rb[] = "( )";
  78.                     if (ct->setting)
  79.                         rb[1] = 7;
  80.                     SetClassColors(DIALOG);
  81.                     writeline(wnd, rb, ct->dwnd.x+1, ct->dwnd.y+1, FALSE);
  82.                 }
  83.                 else if (ct->class == CHECKBOX)    {
  84.                     char rb[] = "[ ]";
  85.                     if (ct->setting)
  86.                         rb[1] = 'X';
  87.                     SetClassColors(DIALOG);
  88.                     writeline(wnd, rb, ct->dwnd.x+1, ct->dwnd.y+1, FALSE);
  89.                 }
  90.                 else if (ct->class == TEXT && ct->vtext != NULL)    {
  91.                     char *cp = ct->vtext;
  92.                     int len = min(ct->dwnd.h, MsgHeight(cp));
  93.                     int i;
  94.                     for (i = 0; i < len; i++)    {
  95.                         int mlen;
  96.                         char *txt = cp;
  97.                         char *cp1 = cp;
  98.                         char *np = strchr(cp, '\n');
  99.                         if (np != NULL)
  100.                             *np = '\0';
  101.                         mlen = strlen(cp);
  102.                         while ((cp1 = strchr(cp1, SHORTCUTCHAR)) != NULL)    {
  103.                             mlen += 3;
  104.                             cp1++;
  105.                         }
  106.                         if (np != NULL)
  107.                             *np = '\n';
  108.                         if ((txt = malloc(mlen+1)) != NULL)    {
  109.                              CopyCommand(txt, cp, FALSE, WndBackground(wnd));
  110.                             txt[mlen] = '\0';
  111.                             SetStandardColor(wnd);
  112.                             writeline(wnd, txt, ct->dwnd.x+1, ct->dwnd.y+i+1, FALSE);
  113.                             if ((cp = strchr(cp, '\n')) != NULL)
  114.                                 cp++;
  115.                             free(txt);
  116.                         }
  117.                     }
  118.                 }
  119.                 ct++;
  120.                 if (p2)
  121.                     break;
  122.             }
  123.             return TRUE;
  124.         case KEYBOARD:
  125.             switch ((int)p1)    {
  126.                 case CTRL_FIVE:        /* same as SHIFT-TAB */
  127.                     if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))
  128.                         ChangeFocus(wnd, FALSE);
  129.                     break;
  130.                 case '\t':
  131.                     ChangeFocus(wnd, TRUE);
  132.                     break;
  133. #ifdef INCLUDE_SYSTEM_MENUS
  134.                 case ' ':
  135.                     if (((int)p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX))    {
  136.                         wnd->dFocus = inFocus;
  137.                         SysMenuOpen = TRUE;
  138.                         BuildSystemMenu(wnd);
  139.                     }
  140.                     break;
  141. #endif
  142.                 case CTRL_F4:
  143.                 case ESC:
  144. #ifdef INCLUDE_SYSTEM_MENUS
  145.                     if (!(WindowMoving || WindowSizing))
  146. #endif
  147.                         SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  148. #ifdef INCLUDE_SYSTEM_MENUS
  149.                 case UP:
  150.                 case DN:
  151.                 case BS:
  152.                 case FWD:
  153.                 case '\r':
  154.                     if (WindowMoving || WindowSizing)
  155.                         return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  156.                     break;
  157. #endif
  158.                 default:
  159.                     /* ------ search all the shortcut keys ----- */
  160.                     dbShortcutKeys(wnd, db, (int) p1);
  161.                     break;
  162.             }
  163.             if (wnd->Modal)
  164.                 return TRUE;
  165.             break;
  166. #ifdef INCLUDE_SYSTEM_MENUS
  167.         case CLOSE_POPDOWN:
  168.             SysMenuOpen = FALSE;
  169.             break;
  170. #endif
  171.         case BUTTON_RELEASED:
  172. #ifdef INCLUDE_SYSTEM_MENUS
  173.             if (!WindowMoving && !WindowSizing)
  174.                 break;
  175. #endif
  176.             rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2);
  177.             SendMessage(wnd->dFocus, SETFOCUS, TRUE, 0);
  178.             return rtn;
  179.         case LB_SELECTION:
  180.         case LB_CHOOSE:
  181. #ifdef INCLUDE_SYSTEM_MENUS
  182.             if (SysMenuOpen)
  183.                 return TRUE;
  184. #endif
  185.             SendMessage(wnd, COMMAND, inFocusCommand(db), msg);
  186.             break;
  187.         case COMMAND:
  188.             switch ((int) p1)    {
  189.                 case ID_OK:
  190.                 case ID_CANCEL:
  191.                     wnd->ReturnCode = (int) p1;
  192.                     if (wnd->Modal)
  193.                         PostMessage(wnd, ENDDIALOG, 0, 0);
  194.                     else
  195.                         SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  196.                     return TRUE;
  197. #ifdef INCLUDE_HELP
  198.                 case ID_HELP:
  199.                     return DisplayHelp(wnd, db->HelpName);
  200. #endif
  201.                 default:
  202.                     break;
  203.             }
  204.             break;
  205.         case CLOSE_WINDOW:
  206.             if (!p1)    {
  207.                 SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  208.                 return TRUE;
  209.             }
  210.             break;
  211.         default:
  212.             break;
  213.     }
  214.     return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  215. }
  216.  
  217. int DialogBox(WINDOW wnd, DBOX *db, int Modal,
  218.     int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
  219. {
  220.     int rtn;
  221.     WINDOW Dwnd;
  222.     CTLWINDOW *ct;
  223.     WINDOW oldFocus = inFocus;
  224.     Dwnd = CreateWindow(DIALOG,
  225.                         db->dwnd.title,
  226.                         db->dwnd.x,
  227.                         db->dwnd.y,
  228.                         db->dwnd.h,
  229.                         db->dwnd.w,
  230.                         db,
  231.                         wnd,
  232.                         wndproc,
  233.                         Modal ? SAVESELF : 0);
  234.     Dwnd->Modal = Modal;
  235.     ct = db->ctl;
  236.     while (ct->class)    {
  237.         if (ct->class != TEXT &&
  238.                 ct->class != RADIOBUTTON &&
  239.                     ct->class != CHECKBOX)    {
  240.             WINDOW cwnd;
  241.             int attrib = VISIBLE | NOCLIP;
  242.             ct->vtext = ct->itext;
  243.             ct->setting = ct->isetting;
  244.             if (ct->class == EDITBOX && ct->dwnd.h > 1)
  245.                 attrib |= (MULTILINE | HASBORDER);
  246.             else if (ct->class == LISTBOX || ct->class == TEXTBOX)
  247.                 attrib |= HASBORDER;
  248.             cwnd = CreateWindow(ct->class,
  249.                                 ct->dwnd.title,
  250.                                 ct->dwnd.x+GetClientLeft(Dwnd),
  251.                                 ct->dwnd.y+GetClientTop(Dwnd),
  252.                                 ct->dwnd.h,
  253.                                 ct->dwnd.w,
  254.                                 NULL,
  255.                                 Dwnd,
  256.                                 ControlProc,
  257.                                 attrib);
  258.             ct->wnd = cwnd;
  259.             if (Dwnd->dFocus == NULLWND)
  260.                 Dwnd->dFocus = cwnd;
  261.             if (ct->itext != NULL)    {
  262.                 unsigned char txt[SCREENWIDTH] = "";
  263.                 memset(txt, '\0', sizeof txt);
  264.                 if (ct->class == BUTTON && ct->setting == OFF)    {
  265.                     txt[0] = CHANGECOLOR;
  266.                     txt[1] = cfg.clr[BUTTON] [HILITE_COLOR] [FG] | 0x80;
  267.                     txt[2] = cfg.clr[BUTTON] [STD_COLOR] [BG] | 0x80;
  268.                 }
  269.                 CopyCommand(txt+strlen(txt), ct->itext, !ct->setting,
  270.                     WndBackground(cwnd));
  271.                 SendMessage(cwnd, ADDTEXT, (PARAM) txt, 0);
  272.             }
  273.         }
  274.         else if (ct->class == TEXT && ct->itext != NULL)    {
  275.             int len = strlen(ct->itext)+1;
  276.             if ((ct->vtext = calloc(1, len)) != NULL)
  277.                 strncpy(ct->vtext, ct->itext, len);
  278.         }
  279.         else if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  280.             ct->setting = ct->isetting;
  281.         ct++;
  282.     }
  283.     SendMessage(Dwnd->dFocus, SETFOCUS, TRUE, 0);
  284.     SendMessage(Dwnd, SHOW_WINDOW, 0, 0);
  285.     SendMessage(Dwnd, INITIATE_DIALOG, 0, 0);
  286.     if (Modal)    {
  287.         SendMessage(Dwnd, CAPTURE_MOUSE, 0, 0);
  288.         SendMessage(Dwnd, CAPTURE_KEYBOARD, 0, 0);
  289.         while (dispatch_message())
  290.             ;
  291.         rtn = Dwnd->ReturnCode == ID_OK;
  292.         SendMessage(Dwnd, RELEASE_MOUSE, 0, 0);
  293.         SendMessage(Dwnd, RELEASE_KEYBOARD, 0, 0);
  294.         SendMessage(Dwnd, CLOSE_WINDOW, TRUE, 0);
  295.         SendMessage(oldFocus, SETFOCUS, TRUE, TRUE);
  296.         if (rtn)    {
  297.             ct = db->ctl;
  298.             while (ct->class)    {
  299.                 if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  300.                     ct->isetting = ct->setting;
  301.                 ct++;
  302.             }
  303.         }
  304.         return rtn;
  305.     }
  306.     return FALSE;
  307. }
  308.  
  309. static int inFocusCommand(DBOX *db)
  310. {
  311.     CTLWINDOW *ct = db->ctl;
  312.     while (ct->class)    {
  313.         if (ct->wnd == inFocus)
  314.             return ct->command;
  315.         ct++;
  316.     }
  317.     return -1;
  318. }
  319.  
  320. static CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
  321. {
  322.     CTLWINDOW *ct = db->ctl;
  323.     while (ct->class)    {
  324.         if (ct->class == class)
  325.             if (cmd == ct->command)
  326.                 return ct;
  327.         ct++;
  328.     }
  329.     return NULL;
  330. }
  331.  
  332. WINDOW ControlWindow(DBOX *db, enum commands cmd)
  333. {
  334.     CTLWINDOW *ct = db->ctl;
  335.     while (ct->class)    {
  336.         if (ct->class != TEXT && cmd == ct->command)
  337.             return ct->wnd;
  338.         ct++;
  339.     }
  340.     return NULLWND;
  341. }
  342.  
  343. CTLWINDOW *ControlBox(DBOX *db, WINDOW wnd)
  344. {
  345.     CTLWINDOW *ct = db->ctl;
  346.     while (ct->class)    {
  347.         if (ct->class != TEXT && wnd == ct->wnd)
  348.             return ct;
  349.         ct++;
  350.     }
  351.     return NULL;
  352. }
  353.  
  354. void PushRadioButton(DBOX *db, enum commands cmd)
  355. {
  356.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  357.     if (ct != NULL)    {
  358.         SetRadioButton(NULLWND, db, ct);
  359.         ct->isetting = ON;
  360.     }
  361. }
  362.  
  363. #define MAXRADIOS 50
  364.  
  365. static struct {
  366.     CTLWINDOW *rct;
  367. } rbs[MAXRADIOS];
  368.  
  369. static void SetRadioButton(WINDOW wnd, DBOX *db, CTLWINDOW *ct)
  370. {
  371.     CTLWINDOW *ctt = db->ctl;
  372.     int i;
  373.  
  374.     /* --- clear all the radio buttons
  375.                 in this group on the dialog box --- */
  376.  
  377.     /* -------- build a table of all radio buttons at the
  378.             same x vector ---------- */
  379.     for (i = 0; i < MAXRADIOS; i++)
  380.         rbs[i].rct = NULL;
  381.     while (ctt->class)    {
  382.         if (ctt->class == RADIOBUTTON)
  383.             if (ct->dwnd.x == ctt->dwnd.x)
  384.                 rbs[ctt->dwnd.y].rct = ctt;
  385.         ctt++;
  386.     }
  387.  
  388.     /* ----- find the start of the radiobutton group ---- */
  389.     i = ct->dwnd.y;
  390.     while (i >= 0 && rbs[i].rct != NULL)
  391.         --i;
  392.     /* ---- ignore everthing before the group ------ */
  393.     while (i >= 0)
  394.         rbs[i--].rct = NULL;
  395.  
  396.     /* ----- find the end of the radiobutton group ---- */
  397.     i = ct->dwnd.y;
  398.     while (i < MAXRADIOS && rbs[i].rct != NULL)
  399.         i++;
  400.     /* ---- ignore everthing past the group ------ */
  401.     while (i < MAXRADIOS)
  402.         rbs[i++].rct = NULL;
  403.  
  404.     for (i = 0; i < MAXRADIOS; i++)    {
  405.         if (rbs[i].rct != NULL)    {
  406.             rbs[i].rct->setting = OFF;
  407.             if (wnd != NULLWND)
  408.                 SendMessage(wnd, PAINT, 0, (PARAM) rbs[i].rct);
  409.         }
  410.     }
  411.     ct->setting = ON;
  412.     if (wnd != NULLWND)
  413.         SendMessage(wnd, PAINT, 0, (PARAM) ct);
  414. }
  415.  
  416. int RadioButtonSetting(DBOX *db, enum commands cmd)
  417. {
  418.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  419.     if (ct != NULL)
  420.         return (ct->setting == ON);
  421.     return FALSE;
  422. }
  423.  
  424. static void ControlSetting(DBOX *db, enum commands cmd,
  425.                                     int class, int setting)
  426. {
  427.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  428.     if (ct != NULL)
  429.         ct->isetting = setting;
  430. }
  431.  
  432. void SetCheckBox(DBOX *db, enum commands cmd)
  433. {
  434.     ControlSetting(db, cmd, CHECKBOX, ON);
  435. }
  436.  
  437. void ClearCheckBox(DBOX *db, enum commands cmd)
  438. {
  439.     ControlSetting(db, cmd, CHECKBOX, OFF);
  440. }
  441.  
  442. void EnableButton(DBOX *db, enum commands cmd)
  443. {
  444.     ControlSetting(db, cmd, BUTTON, ON);
  445. }
  446.  
  447. void DisableButton(DBOX *db, enum commands cmd)
  448. {
  449.     ControlSetting(db, cmd, BUTTON, OFF);
  450. }
  451.  
  452. int CheckBoxSetting(DBOX *db, enum commands cmd)
  453. {
  454.     CTLWINDOW *ct = FindCommand(db, cmd, CHECKBOX);
  455.     if (ct != NULL)
  456.         return (ct->isetting == ON);
  457.     return FALSE;
  458. }
  459.  
  460. static void InvertCheckBox(WINDOW wnd, CTLWINDOW *ct)
  461. {
  462.     ct->setting ^= ON;
  463.     SendMessage(wnd, PAINT, 0, (PARAM) ct);
  464. }
  465.  
  466. void PutItemText(WINDOW wnd, enum commands cmd, char *text)
  467. {
  468.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  469.  
  470.     if (ct == NULL)
  471.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  472.     if (ct == NULL)
  473.         ct = FindCommand(wnd->extension, cmd, TEXT);
  474.     if (ct != NULL)        {
  475.         WINDOW cwnd = (WINDOW) (ct->wnd);
  476.         MESSAGE msg = ADDTEXT;
  477.         switch (ct->class)    {
  478.             case EDITBOX:
  479.                 msg = EB_PUTTEXT;
  480.             case TEXTBOX:
  481.                 SendMessage(cwnd, msg, (PARAM) text, 0);
  482.                 if (ct->class == EDITBOX && !isMultiLine(cwnd))
  483.                     SendMessage(cwnd, PAINT, 0, 0);
  484.                 if (cwnd->wlines > ClientHeight(cwnd) &&
  485.                         !TestAttribute(cwnd, VSCROLLBAR))    {
  486.                     AddAttribute(cwnd, VSCROLLBAR);
  487.                     SendMessage(cwnd, BORDER, 0, 0);
  488.                 }
  489.                 break;
  490.             case TEXT:    {
  491.                 ct->vtext = realloc(ct->vtext, strlen(text)+1);
  492.                 if (ct->vtext != NULL)
  493.                     strcpy(ct->vtext, text);
  494.                 SendMessage(wnd, PAINT, 0, (PARAM) ct);
  495.                 break;
  496.             }
  497.             default:
  498.                 break;
  499.         }
  500.     }
  501. }
  502.  
  503. char *GetEditBoxText(DBOX *db, enum commands cmd)
  504. {
  505.     CTLWINDOW *ct = FindCommand(db, cmd, EDITBOX);
  506.     if (ct != NULL)
  507.         return ct->itext;
  508.     else
  509.         return NULL;
  510. }
  511.  
  512. void SetEditBoxText(DBOX *db, enum commands cmd, char *text)
  513. {
  514.     CTLWINDOW *ct = FindCommand(db, cmd, EDITBOX);
  515.     if (ct != NULL)    {
  516.         ct->itext = realloc(ct->itext, strlen(text)+1);
  517.         if (ct->itext != NULL)
  518.             strcpy(ct->itext, text);
  519.     }
  520. }
  521.  
  522. void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len)
  523. {
  524.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  525.  
  526.     if (ct == NULL)
  527.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  528.     if (ct == NULL)
  529.         ct = FindCommand(wnd->extension, cmd, TEXT);
  530.     if (ct != NULL)    {
  531.         WINDOW cwnd = (WINDOW) (ct->wnd);
  532.         switch (ct->class)    {
  533.             case TEXTBOX:
  534.                 if (cwnd != NULL)    {
  535.                     char *cp = GetText(cwnd);
  536.                     if (cp != NULL)
  537.                         strncpy(text, cp, len);
  538.                 }
  539.                 break;
  540.             case EDITBOX:
  541.                 if (cwnd != NULL)
  542.                     SendMessage(cwnd, EB_GETTEXT, (PARAM) text, len);
  543.                 break;
  544.             case TEXT:
  545.                 strncpy(text, ct->vtext, len);
  546.                 break;
  547.             default:
  548.                 break;
  549.         }
  550.     }
  551. }
  552.  
  553. void GetDlgListText(WINDOW wnd, char *text, enum commands cmd)
  554. {
  555.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
  556.     int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
  557.     SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel);
  558. }
  559.  
  560. static int dircmp(const void *c1, const void *c2)
  561. {
  562.     return stricmp(*(char **)c1, *(char **)c2);
  563. }
  564.  
  565. int DlgDirList(WINDOW wnd, char *fspec,
  566.                 enum commands nameid, enum commands pathid,
  567.                 unsigned attrib)
  568. {
  569.     int ax, i = 0, criterr = 1;
  570.     struct ffblk ff;
  571.     CTLWINDOW *ct = FindCommand(wnd->extension, nameid, LISTBOX);
  572.     WINDOW lwnd;
  573.     char **dirlist = NULL;
  574.  
  575.     CreatePath(path, fspec, TRUE, TRUE);
  576.  
  577.     if (ct != NULL)    {
  578.         lwnd = ct->wnd;
  579.         SendMessage(ct->wnd, CLEARTEXT, 0, 0);
  580.  
  581.         if (attrib & 0x8000)    {
  582.             union REGS regs;
  583.             char drname[15];
  584.             unsigned int cd, dr;
  585.  
  586. #ifdef MSC
  587.             _dos_getdrive(&cd);
  588.             cd -= 1;
  589. #else
  590.             cd = getdisk();
  591. #endif
  592.             for (dr = 0; dr < 26; dr++)    {
  593.                 unsigned ndr;
  594.                 setdisk(dr);
  595. #ifdef MSC
  596.                 _dos_getdrive(&ndr);
  597.                 ndr -= 1;
  598. #else
  599.                 ndr = getdisk();
  600. #endif
  601.                 if (ndr == dr)    {
  602.                     /* ------- test for remapped B drive ------- */
  603.                     if (dr == 1)    {
  604.                         regs.x.ax = 0x440e;        /* IOCTL function 14 */
  605.                         regs.h.bl = dr+1;
  606.                         int86(DOS, ®s, ®s);
  607.                         if (regs.h.al != 0)
  608.                             continue;
  609.                     }
  610.  
  611.                     sprintf(drname, "[%c:]", dr+'A');
  612.  
  613.                     /* ------ test for network or RAM disk ---- */
  614.                     regs.x.ax = 0x4409;        /* IOCTL function 9 */
  615.                     regs.h.bl = dr+1;
  616.                     int86(DOS, ®s, ®s);
  617.                     if (!regs.x.cflag)    {
  618.                         if (regs.x.dx & 0x1000)
  619.                             strcat(drname, " (Network)");
  620.                         else if (regs.x.dx == 0x0800)
  621.                             strcat(drname, " (RAMdisk)");
  622.                     }
  623.                     SendMessage(lwnd, ADDTEXT, (PARAM) drname, 0);
  624.                 }
  625.             }
  626.             setdisk(cd);
  627.         }
  628.  
  629.         while (criterr == 1)    {
  630.             ax = findfirst(path, &ff, attrib & 0x3f);
  631.             criterr = TestCriticalError();
  632.         }
  633.         if (criterr)
  634.             return FALSE;
  635.         while (ax == 0)    {
  636.             if (!((attrib & 0x4000) &&
  637.                     (ff.ff_attrib & (attrib & 0x3f)) == 0) &&
  638.                         strcmp(ff.ff_name, "."))    {
  639.                 char fname[15];
  640.                 sprintf(fname, (ff.ff_attrib & 0x10) ?
  641.                                 "[%s]" : "%s" , ff.ff_name);
  642.                 dirlist = realloc(dirlist, sizeof(char *)*(i+1));
  643.                 if (dirlist != NULL)    {
  644.                     dirlist[i] = malloc(strlen(fname)+1);
  645.                     if (dirlist[i] != NULL)
  646.                         strcpy(dirlist[i], fname);
  647.                     i++;
  648.                 }
  649.             }
  650.             ax = findnext(&ff);
  651.         }
  652.         if (dirlist != NULL)    {
  653.             int j;
  654.             /* -- sort file/drive/directory list box data -- */
  655.             qsort(dirlist, i, sizeof(void *), dircmp);
  656.  
  657.             /* ---- send sorted list to list box ---- */
  658.             for (j = 0; j < i; j++)    {
  659.                 SendMessage(lwnd, ADDTEXT, (PARAM) dirlist[j], 0);
  660.                 free(dirlist[j]);
  661.             }
  662.             free(dirlist);
  663.         }
  664. #ifdef INCLUDE_SCROLLBARS
  665.         if (lwnd->wlines > ClientHeight(lwnd))
  666.             AddAttribute(lwnd, VSCROLLBAR);
  667.         else
  668.             ClearAttribute(lwnd, VSCROLLBAR);
  669. #endif
  670.         SendMessage(lwnd, SHOW_WINDOW, 0, 0);
  671.     }
  672.  
  673.     if (pathid)    {
  674.         fnmerge(path, drive, dir, NULL, NULL);
  675.         PutItemText(wnd, pathid, path);
  676.     }
  677.  
  678.     return TRUE;
  679. }
  680.  
  681. static void dbShortcutKeys(WINDOW wnd, DBOX *db, int ky)
  682. {
  683.     CTLWINDOW *ct;
  684.     int ch = AltConvert(ky);
  685.  
  686.     if (ch != 0)    {
  687.         ct = db->ctl;
  688.         while (ct->class)    {
  689.             char *cp = ct->vtext;
  690.             while (cp && *cp)    {
  691.                 if (*cp == SHORTCUTCHAR && tolower(*(cp+1)) == ch)    {
  692.                     if (ct->class == TEXT)    {
  693.                         enum commands Tcmd = ct->command;
  694.                         /* --- find the associated control --- */
  695.                         ct = db->ctl;
  696.                         while (ct->class)    {
  697.                             if (ct->class != TEXT)
  698.                                 if (ct->command == Tcmd)
  699.                                     break;
  700.                             ct++;
  701.                         }
  702.                     }
  703.                     if (ct->class == RADIOBUTTON)
  704.                         SetRadioButton(wnd, db, ct);
  705.                     else if (ct->class == CHECKBOX)
  706.                         InvertCheckBox(wnd, ct);
  707.                     else if (ct->class)    {
  708.                         SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  709.                         if (ct->class == BUTTON)
  710.                             SendMessage(ct->wnd, KEYBOARD, '\r', 0);
  711.                     }
  712.                     return;
  713.                 }
  714.                 cp++;
  715.             }
  716.             ct++;
  717.         }
  718.     }
  719. }
  720.  
  721. /* generic window processor used by all dialog box control windows */
  722. static int ControlProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  723. {
  724.     DBOX *db;
  725.     CTLWINDOW *ct;
  726.  
  727.     if (wnd == NULLWND)
  728.         return FALSE;
  729.     db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
  730.     ct = db ? ControlBox(db, wnd) : NULL;
  731.     switch (msg)    {
  732.         case KEYBOARD:
  733.             switch ((int) p1)    {
  734.                 case '\r':
  735.                     if (GetClass(wnd) == EDITBOX && !isMultiLine(wnd))    {
  736.                         SendMessage(GetParent(wnd), COMMAND, ID_OK, 0);
  737.                         return TRUE;
  738.                     }
  739.                     break;
  740. #ifdef INCLUDE_HELP
  741.                 case F1:
  742. #ifdef INCLUDE_SYSTEM_MENUS
  743.                     if (WindowMoving || WindowSizing)
  744.                         break;
  745. #endif
  746.                     if (!DisplayHelp(wnd, ct->help))
  747.                         SendMessage(GetParent(wnd), COMMAND, ID_HELP, 0);
  748.                     return TRUE;
  749. #endif
  750.                 default:
  751.                     break;
  752.             }
  753.             break;
  754.         case SETFOCUS:
  755.             if (GetClass(wnd) != BUTTON)    {
  756.                 if (p1)    {
  757.                     DefaultWndProc(wnd, msg, p1, p2);
  758.                     SendMessage(GetParent(wnd), COMMAND,
  759.                         inFocusCommand(db), ENTERFOCUS);
  760.                     return TRUE;
  761.                 }
  762.                 else 
  763.                     SendMessage(GetParent(wnd), COMMAND,
  764.                         inFocusCommand(db), LEAVEFOCUS);
  765.             }
  766.             break;
  767.         case CLOSE_WINDOW:
  768.             if (db != NULL && ct != NULL)    {
  769.                 WINDOW pwnd = GetParent(wnd);
  770.                 if (ct->vtext != NULL && ct->class == TEXT)    {
  771.                     free(ct->vtext);
  772.                     ct->vtext = NULL;
  773.                 }
  774.                 if (pwnd && pwnd->ReturnCode == ID_OK &&
  775.                                 ct->class == EDITBOX) {
  776.                     if (wnd->TextChanged)    {
  777.                         int len = strlen(wnd->text);
  778.                         ct->itext = realloc(ct->itext, len+1);
  779.                         if (ct->itext != NULL)
  780.                             strcpy(ct->itext, wnd->text);
  781.                     }
  782.                 }
  783.             }
  784.             break;
  785.         default:
  786.             break;
  787.     }
  788.     return DefaultWndProc(wnd, msg, p1, p2);
  789. }
  790.  
  791. #endif
  792.  
  793. /* ----- Create unambiguous path from file spec, filling in the
  794.      drive and directory if incomplete. Optionally change to
  795.      the new drive and subdirectory ------ */
  796. void CreatePath(char *path, char *fspec, int InclName, int Change)
  797. {
  798.     int cm = 0;
  799.     unsigned currdrive;
  800.     char currdir[64];
  801.     char *cp;
  802.  
  803.     if (!Change)    {
  804.         /* ----- save the current drive and subdirectory ----- */
  805. #ifdef MSC
  806.         _dos_getdrive(&currdrive);
  807.         currdrive -= 1;
  808. #else
  809.         currdrive = getdisk();
  810. #endif
  811.         getcwd(currdir, sizeof currdir);
  812.         memmove(currdir, currdir+2, strlen(currdir+1));
  813.         cp = currdir+strlen(currdir)-1;
  814.         if (*cp == '\\')
  815.             *cp = '\0';
  816.     }
  817.  
  818.     *drive = *dir = *name = *ext = '\0';
  819. #ifndef MSC
  820.     cm =
  821. #endif
  822.     fnsplit(fspec, drive, dir, name, ext);
  823.     if (!InclName)
  824.         *name = *ext = '\0';
  825.     *drive = toupper(*drive);
  826.  
  827. #ifdef MSC
  828.     if (*ext)
  829.         cm |= EXTENSION;
  830.     if (InclName && *name)
  831.         cm |= FILENAME;
  832.     if (*dir)
  833.         cm |= DIRECTORY;
  834.     if (*drive)
  835.         cm |= DRIVE;
  836. #endif
  837.  
  838.     if (cm & DRIVE)
  839.         setdisk(*drive - 'A');
  840.     else     {
  841. #ifdef MSC
  842.         _dos_getdrive((unsigned *)drive);
  843.         *drive -= 1;
  844. #else
  845.         *drive = getdisk();
  846. #endif
  847.         *drive += 'A';
  848.     }
  849.  
  850.     if (cm & DIRECTORY)    {
  851.         cp = dir+strlen(dir)-1;
  852.         if (*cp == '\\')
  853.             *cp = '\0';
  854.         chdir(dir);
  855.     }
  856.     getcwd(dir, sizeof dir);
  857.     memmove(dir, dir+2, strlen(dir+1));
  858.  
  859.     if (InclName)    {
  860.         if (!(cm & FILENAME))
  861.             strcpy(name, "*");
  862.         if (!(cm & EXTENSION))
  863.             strcpy(ext, ".*");
  864.     }
  865.     else
  866.         *name = *ext = '\0';
  867.     if (dir[strlen(dir)-1] != '\\')
  868.         strcat(dir, "\\");
  869.     memset(path, 0, sizeof path);
  870.     fnmerge(path, drive, dir, name, ext);
  871.  
  872.     if (!Change)    {
  873.         setdisk(currdrive);
  874.         chdir(currdir);
  875.     }
  876. }
  877.  
  878. static void ChangeFocus(WINDOW wnd, int direc)
  879. {
  880.     DBOX *db = wnd->extension;
  881.      CTLWINDOW *ct = db->ctl;
  882.      CTLWINDOW *ctt;
  883.  
  884.     while (ct->class)    {
  885.         if (ct->wnd == inFocus)
  886.             break;
  887.         ct++;
  888.     }
  889.     if (ct->class)    {
  890.         ctt = ct;
  891.         do    {
  892.             if (direc)    {
  893.                 ct++;
  894.                 if (ct->class == 0)
  895.                     ct = db->ctl;
  896.             }
  897.             else    {
  898.                 if (ct == db->ctl)
  899.                     while (ct->class)
  900.                         ct++;
  901.                 --ct;
  902.             }
  903.             if (ct->wnd != NULLWND)    {
  904.                 SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  905.                 break;
  906.             }
  907.         } while (ct != ctt);
  908.     }
  909. }
  910.