home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1992 / 06 / dflat.692 < prev    next >
Text File  |  1992-04-22  |  22KB  |  729 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. /* ----------------- dialbox.c -------------- */
  7.  
  8. #include "dflat.h"
  9.  
  10. static int inFocusCommand(DBOX *);
  11. static void dbShortcutKeys(DBOX *, int);
  12. static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM);
  13. static void ChangeFocus(WINDOW, int);
  14. static CTLWINDOW *AssociatedControl(DBOX *, enum commands);
  15.  
  16. static BOOL SysMenuOpen;
  17.  
  18. static DBOX **dbs = NULL;
  19. static int dbct = 0;
  20.  
  21. /* --- clear all heap allocations to control text fields --- */
  22. void ClearDialogBoxes(void)
  23. {
  24.     int i;
  25.     for (i = 0; i < dbct; i++)    {
  26.         CTLWINDOW *ct = (*(dbs+i))->ctl;
  27.         while (ct->class)    {
  28.             if ((ct->class == EDITBOX ||
  29.                     ct->class == COMBOBOX) &&
  30.                     ct->itext != NULL)
  31.                 free(ct->itext);
  32.             ct++;
  33.         }
  34.     }
  35.     if (dbs != NULL)    {
  36.         free(dbs);
  37.         dbs = NULL;
  38.     }
  39.     dbct = 0;
  40. }
  41.  
  42. /* -------- CREATE_WINDOW Message --------- */
  43. static int CreateWindowMsg(WINDOW wnd, PARAM p1, PARAM p2)
  44. {
  45.     DBOX *db = wnd->extension;
  46.     CTLWINDOW *ct = db->ctl;
  47.     WINDOW cwnd;
  48.     int rtn, i;
  49.     /* ---- build a table of processed dialog boxes ---- */
  50.     for (i = 0; i < dbct; i++)
  51.         if (db == dbs[i])
  52.             break;
  53.     if (i == dbct)    {
  54.         dbs = realloc(dbs, sizeof(DBOX *) * (dbct+1));
  55.         if (dbs != NULL)
  56.             *(dbs + dbct++) = db;
  57.     }
  58.     rtn = BaseWndProc(DIALOG, wnd, CREATE_WINDOW, p1, p2);
  59.     ct = db->ctl;
  60.     while (ct->class)    {
  61.         int attrib = 0;
  62.         if (TestAttribute(wnd, NOCLIP))
  63.             attrib |= NOCLIP;
  64.         if (wnd->Modal)
  65.             attrib |= SAVESELF;
  66.         ct->setting = ct->isetting;
  67.         if (ct->class == EDITBOX && ct->dwnd.h > 1)
  68.             attrib |= (MULTILINE | HASBORDER);
  69.         else if (ct->class == LISTBOX || ct->class == TEXTBOX)
  70.             attrib |= HASBORDER;
  71.         cwnd = CreateWindow(ct->class,
  72.                         ct->dwnd.title,
  73.                         ct->dwnd.x+GetClientLeft(wnd),
  74.                         ct->dwnd.y+GetClientTop(wnd),
  75.                         ct->dwnd.h,
  76.                         ct->dwnd.w,
  77.                         ct,
  78.                         wnd,
  79.                         ControlProc,
  80.                         attrib);
  81.         if ((ct->class == EDITBOX ||
  82.                 ct->class == COMBOBOX) &&
  83.                     ct->itext != NULL)
  84.             SendMessage(cwnd, SETTEXT, (PARAM) ct->itext, 0);
  85.         if (ct->class != BOX &&
  86.             ct->class != TEXT &&
  87.                 wnd->dFocus == NULL)
  88.             wnd->dFocus = ct;
  89.         ct++;
  90.     }
  91.     return rtn;
  92. }
  93.  
  94. /* -------- LEFT_BUTTON Message --------- */
  95. static BOOL LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  96. {
  97.     DBOX *db = wnd->extension;
  98.     CTLWINDOW *ct = db->ctl;
  99.     if (WindowSizing || WindowMoving)
  100.         return TRUE;
  101.     if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd))) {
  102.         PostMessage(wnd, KEYBOARD, ' ', ALTKEY);
  103.         return TRUE;
  104.     }
  105.     while (ct->class)    {
  106.         WINDOW cwnd = ct->wnd;
  107.         if (ct->class == COMBOBOX)    {
  108.             if (p2 == GetTop(cwnd))    {
  109.                 if (p1 == GetRight(cwnd)+1)    {
  110.                     SendMessage(cwnd, LEFT_BUTTON, p1, p2);
  111.                     return TRUE;
  112.                 }
  113.             }
  114.             if (GetClass(inFocus) == LISTBOX)
  115.                 SendMessage(wnd, SETFOCUS, TRUE, 0);
  116.         }
  117.         else if (ct->class == SPINBUTTON)    {
  118.             if (p2 == GetTop(cwnd))    {
  119.                 if (p1 == GetRight(cwnd)+1 ||
  120.                         p1 == GetRight(cwnd)+2)    {
  121.                     SendMessage(cwnd, LEFT_BUTTON, p1, p2);
  122.                     return TRUE;
  123.                 }
  124.             }
  125.         }
  126.         ct++;
  127.     }
  128.     return FALSE;
  129. }
  130.  
  131. /* -------- KEYBOARD Message --------- */
  132. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  133. {
  134.     DBOX *db = wnd->extension;
  135.     CTLWINDOW *ct = db->ctl;
  136.  
  137.     if (WindowMoving || WindowSizing)
  138.         return FALSE;
  139.     switch ((int)p1)    {
  140.         case F1:
  141.             ct = wnd->dFocus;
  142.             if (ct != NULL)
  143.                 if (DisplayHelp(wnd, ct->help))
  144.                     return TRUE;
  145.             break;
  146.         case SHIFT_HT:
  147.         case BS:
  148.         case UP:
  149.             ChangeFocus(wnd, FALSE);
  150.             break;
  151.         case ALT_F6:
  152.         case '\t':
  153.         case FWD:
  154.         case DN:
  155.             ChangeFocus(wnd, TRUE);
  156.             break;
  157.         case ' ':
  158.             if (((int)p2 & ALTKEY) &&
  159.                     TestAttribute(wnd, CONTROLBOX))    {
  160.                 SysMenuOpen = TRUE;
  161.                 BuildSystemMenu(wnd);
  162.             }
  163.             break;
  164.         case CTRL_F4:
  165.         case ESC:
  166.             SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  167.             break;
  168.         default:
  169.             /* ------ search all the shortcut keys ----- */
  170.             dbShortcutKeys(db, (int) p1);
  171.             break;
  172.     }
  173.     return wnd->Modal;
  174. }
  175.  
  176. /* -------- COMMAND Message --------- */
  177. static BOOL CommandMsg(WINDOW wnd, PARAM p1, PARAM p2)
  178. {
  179.     DBOX *db = wnd->extension;
  180.     switch ((int) p1)    {
  181.         case ID_OK:
  182.         case ID_CANCEL:
  183.             if ((int)p2 != 0)
  184.                 return TRUE;
  185.             wnd->ReturnCode = (int) p1;
  186.             if (wnd->Modal)
  187.                 PostMessage(wnd, ENDDIALOG, 0, 0);
  188.             else
  189.                 SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  190.             return TRUE;
  191.         case ID_HELP:
  192.             if ((int)p2 != 0)
  193.                 return TRUE;
  194.             return DisplayHelp(wnd, db->HelpName);
  195.         default:
  196.             break;
  197.     }
  198.     return FALSE;
  199. }
  200.  
  201. /* ----- window-processing module, DIALOG window class ----- */
  202. int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  203. {
  204.     DBOX *db = wnd->extension;
  205.  
  206.     switch (msg)    {
  207.         case CREATE_WINDOW:
  208.             return CreateWindowMsg(wnd, p1, p2);
  209.         case SETFOCUS:
  210.             if (wnd->Modal)    {
  211.                 if (p1)
  212.                     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  213.                 inFocus = p1 ? wnd : NULL;
  214.                 return TRUE;
  215.             }
  216.             break;
  217.         case SHIFT_CHANGED:
  218.             if (wnd->Modal)
  219.                 return TRUE;
  220.             break;
  221.         case LEFT_BUTTON:
  222.             if (LeftButtonMsg(wnd, p1, p2))
  223.                 return TRUE;
  224.             break;
  225.         case KEYBOARD:
  226.             if (KeyboardMsg(wnd, p1, p2))
  227.                 return TRUE;
  228.             break;
  229.         case CLOSE_POPDOWN:
  230.             SysMenuOpen = FALSE;
  231.             break;
  232.         case LB_SELECTION:
  233.         case LB_CHOOSE:
  234.             if (SysMenuOpen)
  235.                 return TRUE;
  236.             SendMessage(wnd, COMMAND, inFocusCommand(db), msg);
  237.             break;
  238.         case COMMAND:
  239.             if (CommandMsg(wnd, p1, p2))
  240.                 return TRUE;
  241.             break;
  242.         case PAINT:
  243.             p2 = TRUE;
  244.             break;
  245.         case CLOSE_WINDOW:
  246.             if (!p1)    {
  247.                 SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  248.                 return TRUE;
  249.             }
  250.             break;
  251.         default:
  252.             break;
  253.     }
  254.     return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  255. }
  256.  
  257. /* ------- create and execute a dialog box ---------- */
  258. BOOL DialogBox(WINDOW wnd, DBOX *db, BOOL Modal,
  259.   int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
  260. {
  261.     BOOL rtn;
  262.     int x = db->dwnd.x, y = db->dwnd.y;
  263.     CTLWINDOW *ct;
  264.     WINDOW oldFocus = inFocus;
  265.     WINDOW DialogWnd;
  266.  
  267.     if (!Modal && wnd != NULL)    {
  268.         x += GetLeft(wnd);
  269.         y += GetTop(wnd);
  270.     }
  271.     DialogWnd = CreateWindow(DIALOG,
  272.                         db->dwnd.title,
  273.                         x, y,
  274.                         db->dwnd.h,
  275.                         db->dwnd.w,
  276.                         db,
  277.                         wnd,
  278.                         wndproc,
  279.                         Modal ? SAVESELF : 0);
  280.     DialogWnd->Modal = Modal;
  281.     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  282.     SendMessage(DialogWnd, SHOW_WINDOW, 0, 0);
  283.     SendMessage(((CTLWINDOW *)(DialogWnd->dFocus))->wnd,
  284.         SETFOCUS, TRUE, 0);
  285.     SendMessage(DialogWnd, INITIATE_DIALOG, 0, 0);
  286.     if (Modal)    {
  287.         SendMessage(DialogWnd, CAPTURE_MOUSE, 0, 0);
  288.         SendMessage(DialogWnd, CAPTURE_KEYBOARD, 0, 0);
  289.         while (dispatch_message())
  290.             ;
  291.         rtn = DialogWnd->ReturnCode == ID_OK;
  292.         SendMessage(DialogWnd, RELEASE_MOUSE, 0, 0);
  293.         SendMessage(DialogWnd, RELEASE_KEYBOARD, 0, 0);
  294.         SendMessage(inFocus, SETFOCUS, FALSE, 0);
  295.         SendMessage(DialogWnd, CLOSE_WINDOW, TRUE, 0);
  296.         SendMessage(oldFocus, SETFOCUS, TRUE, 0);
  297.         if (rtn)    {
  298.             ct = db->ctl;
  299.             while (ct->class)    {
  300.                 ct->wnd = NULL;
  301.                 if (ct->class == RADIOBUTTON ||
  302.                         ct->class == CHECKBOX)
  303.                     ct->isetting = ct->setting;
  304.                 ct++;
  305.             }
  306.         }
  307.         return rtn;
  308.     }
  309.     return FALSE;
  310. }
  311.  
  312. /* ----- return command code of in-focus control window ---- */
  313. static int inFocusCommand(DBOX *db)
  314. {
  315.     CTLWINDOW *ct = db->ctl;
  316.     while (ct->class)    {
  317.         if (ct->wnd == inFocus)
  318.             return ct->command;
  319.         ct++;
  320.     }
  321.     return -1;
  322. }
  323.  
  324. /* -------- find a specified control structure ------- */
  325. CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
  326. {
  327.     CTLWINDOW *ct = db->ctl;
  328.     while (ct->class)    {
  329.         if (ct->class == class)
  330.             if (cmd == ct->command)
  331.                 return ct;
  332.         ct++;
  333.     }
  334.     return NULL;
  335. }
  336.  
  337. /* ---- return the window handle of a specified command ---- */
  338. WINDOW ControlWindow(DBOX *db, enum commands cmd)
  339. {
  340.     CTLWINDOW *ct = db->ctl;
  341.     while (ct->class)    {
  342.         if (ct->class != TEXT && cmd == ct->command)
  343.             return ct->wnd;
  344.         ct++;
  345.     }
  346.     return NULL;
  347. }
  348.  
  349. /* ---- set a control ON or OFF ----- */
  350. void ControlSetting(DBOX *db, enum commands cmd,
  351.                                 int class, int setting)
  352. {
  353.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  354.     if (ct != NULL)
  355.         ct->isetting = setting;
  356. }
  357.  
  358. /* ---- return pointer to the text of a control window ---- */
  359. char *GetDlgTextString(DBOX *db,enum commands cmd,CLASS class)
  360. {
  361.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  362.     if (ct != NULL)
  363.         return ct->itext;
  364.     else
  365.         return NULL;
  366. }
  367.  
  368. /* ------- set the text of a control specification ------ */
  369. void SetDlgTextString(DBOX *db, enum commands cmd,
  370.                                     char *text, CLASS class)
  371. {
  372.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  373.     if (ct != NULL)    {
  374.         ct->itext = realloc(ct->itext, strlen(text)+1);
  375.         if (ct->itext != NULL)
  376.             strcpy(ct->itext, text);
  377.     }
  378. }
  379.  
  380. /* ------- set the text of a control window ------ */
  381. void PutItemText(WINDOW wnd, enum commands cmd, char *text)
  382. {
  383.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  384.  
  385.     if (ct == NULL)
  386.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  387.     if (ct == NULL)
  388.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  389.     if (ct == NULL)
  390.         ct = FindCommand(wnd->extension, cmd, LISTBOX);
  391.     if (ct == NULL)
  392.         ct = FindCommand(wnd->extension, cmd, SPINBUTTON);
  393.     if (ct == NULL)
  394.         ct = FindCommand(wnd->extension, cmd, TEXT);
  395.     if (ct != NULL)        {
  396.         WINDOW cwnd = (WINDOW) (ct->wnd);
  397.         switch (ct->class)    {
  398.             case COMBOBOX:
  399.             case EDITBOX:
  400.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  401.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  402.                 if (!isMultiLine(cwnd))
  403.                     SendMessage(cwnd, PAINT, 0, 0);
  404.                 break;
  405.             case LISTBOX:
  406.             case TEXTBOX:
  407.             case SPINBUTTON:
  408.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  409.                 break;
  410.             case TEXT:    {
  411.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  412.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  413.                 SendMessage(cwnd, PAINT, 0, 0);
  414.                 break;
  415.             }
  416.             default:
  417.                 break;
  418.         }
  419.     }
  420. }
  421.  
  422. /* ------- get the text of a control window ------ */
  423. void GetItemText(WINDOW wnd, enum commands cmd,
  424.                                 char *text, int len)
  425. {
  426.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  427.     unsigned char *cp;
  428.  
  429.     if (ct == NULL)
  430.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  431.     if (ct == NULL)
  432.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  433.     if (ct == NULL)
  434.         ct = FindCommand(wnd->extension, cmd, TEXT);
  435.     if (ct != NULL)    {
  436.         WINDOW cwnd = (WINDOW) (ct->wnd);
  437.         if (cwnd != NULL)    {
  438.             switch (ct->class)    {
  439.                 case TEXT:
  440.                     if (GetText(cwnd) != NULL)    {
  441.                         cp = strchr(GetText(cwnd), '\n');
  442.                         if (cp != NULL)
  443.                             len = (int) (cp - GetText(cwnd));
  444.                         strncpy(text, GetText(cwnd), len);
  445.                         *(text+len) = '\0';
  446.                     }
  447.                     break;
  448.                 case TEXTBOX:
  449.                     if (GetText(cwnd) != NULL)
  450.                         strncpy(text, GetText(cwnd), len);
  451.                     break;
  452.                 case COMBOBOX:
  453.                 case EDITBOX:
  454.                     SendMessage(cwnd,GETTEXT,(PARAM)text,len);
  455.                     break;
  456.                 default:
  457.                     break;
  458.             }
  459.         }
  460.     }
  461. }
  462.  
  463. /* ------- set the text of a listbox control window ------ */
  464. void GetDlgListText(WINDOW wnd, char *text, enum commands cmd)
  465. {
  466.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
  467.     int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
  468.     SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel);
  469. }
  470.  
  471. /* -- find control structure associated with text control -- */
  472. static CTLWINDOW *AssociatedControl(DBOX *db,enum commands Tcmd)
  473. {
  474.     CTLWINDOW *ct = db->ctl;
  475.     while (ct->class)    {
  476.         if (ct->class != TEXT)
  477.             if (ct->command == Tcmd)
  478.                 break;
  479.         ct++;
  480.     }
  481.     return ct;
  482. }
  483.  
  484. /* --- process dialog box shortcut keys --- */
  485. static void dbShortcutKeys(DBOX *db, int ky)
  486. {
  487.     CTLWINDOW *ct;
  488.     int ch = AltConvert(ky);
  489.  
  490.     if (ch != 0)    {
  491.         ct = db->ctl;
  492.         while (ct->class)    {
  493.             char *cp = ct->itext;
  494.             while (cp && *cp)    {
  495.                 if (*cp == SHORTCUTCHAR &&
  496.                             tolower(*(cp+1)) == ch)    {
  497.                     if (ct->class == TEXT)
  498.                         ct = AssociatedControl(db, ct->command);
  499.                     if (ct->class == RADIOBUTTON)
  500.                         SetRadioButton(db, ct);
  501.                     else if (ct->class == CHECKBOX)    {
  502.                         ct->setting ^= ON;
  503.                         SendMessage(ct->wnd, PAINT, 0, 0);
  504.                     }
  505.                     else if (ct->class)    {
  506.                         SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  507.                         if (ct->class == BUTTON)
  508.                            SendMessage(ct->wnd,KEYBOARD,'\r',0);
  509.                     }
  510.                     return;
  511.                 }
  512.                 cp++;
  513.             }
  514.             ct++;
  515.         }
  516.     }
  517. }
  518.  
  519. /* --- dynamically add or remove scroll bars
  520.                             from a control window ---- */
  521. void SetScrollBars(WINDOW wnd)
  522. {
  523.     int oldattr = GetAttribute(wnd);
  524.     if (wnd->wlines > ClientHeight(wnd))
  525.         AddAttribute(wnd, VSCROLLBAR);
  526.     else 
  527.         ClearAttribute(wnd, VSCROLLBAR);
  528.     if (wnd->textwidth > ClientWidth(wnd))
  529.         AddAttribute(wnd, HSCROLLBAR);
  530.     else 
  531.         ClearAttribute(wnd, HSCROLLBAR);
  532.     if (GetAttribute(wnd) != oldattr)
  533.         SendMessage(wnd, BORDER, 0, 0);
  534. }
  535.  
  536. /* ------- CREATE_WINDOW Message (Control) ----- */
  537. static void CtlCreateWindowMsg(WINDOW wnd)
  538. {
  539.     CTLWINDOW *ct;
  540.     ct = wnd->ct = wnd->extension;
  541.     wnd->extension = NULL;
  542.     if (ct != NULL)
  543.         ct->wnd = wnd;
  544. }
  545.  
  546. /* ------- KEYBOARD Message (Control) ----- */
  547. static BOOL CtlKeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  548. {
  549.     CTLWINDOW *ct = GetControl(wnd);
  550.     switch ((int) p1)    {
  551.         case F1:
  552.             if (WindowMoving || WindowSizing)
  553.                 break;
  554.             if (!DisplayHelp(wnd, ct->help))
  555.                 SendMessage(GetParent(wnd),COMMAND,ID_HELP,0);
  556.             return TRUE;
  557.         case ' ':
  558.             if (!((int)p2 & ALTKEY))
  559.                 break;
  560.         case ALT_F6:
  561.         case CTRL_F4:
  562.         case ALT_F4:
  563.             PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  564.             return TRUE;
  565.         default:
  566.             break;
  567.     }
  568.     if (GetClass(wnd) == EDITBOX)
  569.         if (isMultiLine(wnd))
  570.             return FALSE;
  571.     switch ((int) p1)    {
  572.         case UP:
  573.             if (!isDerivedFrom(wnd, LISTBOX))    {
  574.                 p1 = CTRL_FIVE;
  575.                 p2 = LEFTSHIFT;
  576.             }
  577.             break;
  578.         case BS:
  579.             if (!isDerivedFrom(wnd, EDITBOX))    {
  580.                 p1 = CTRL_FIVE;
  581.                 p2 = LEFTSHIFT;
  582.             }
  583.             break;
  584.         case DN:
  585.             if (!isDerivedFrom(wnd, LISTBOX) &&
  586.                     !isDerivedFrom(wnd, COMBOBOX))
  587.                 p1 = '\t';
  588.             break;
  589.         case FWD:
  590.             if (!isDerivedFrom(wnd, EDITBOX))
  591.                 p1 = '\t';
  592.             break;
  593.         case '\r':
  594.             if (isDerivedFrom(wnd, EDITBOX))
  595.                 if (isMultiLine(wnd))
  596.                     break;
  597.             if (isDerivedFrom(wnd, BUTTON))
  598.                 break;
  599.             SendMessage(GetParent(wnd), COMMAND, ID_OK, 0);
  600.             return TRUE;
  601.         default:
  602.             break;
  603.     }
  604.     return FALSE;
  605. }
  606.  
  607. /* ------- CLOSE_WINDOW Message (Control) ----- */
  608. static void CtlCloseWindowMsg(WINDOW wnd)
  609. {
  610.     CTLWINDOW *ct = GetControl(wnd);
  611.     if (ct != NULL)    {
  612.         if (GetParent(wnd)->ReturnCode == ID_OK &&
  613.                 (ct->class == EDITBOX ||
  614.                     ct->class == COMBOBOX))    {
  615.             if (wnd->TextChanged)    {
  616.                 ct->itext=realloc(ct->itext,strlen(wnd->text)+1);
  617.                 strcpy(ct->itext, wnd->text);
  618.                 if (!isMultiLine(wnd))    {
  619.                     char *cp = ct->itext+strlen(ct->itext)-1;
  620.                     if (*cp == '\n')
  621.                         *cp = '\0';
  622.                 }
  623.             }
  624.         }
  625.     }
  626. }
  627.  
  628. /* -- generic window processor used by dialog box controls -- */
  629. static int ControlProc(WINDOW wnd,MESSAGE msg,PARAM p1,PARAM p2)
  630. {
  631.     DBOX *db;
  632.     CTLWINDOW *ct;
  633.  
  634.     if (wnd == NULL)
  635.         return FALSE;
  636.     db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
  637.     ct = GetControl(wnd);
  638.  
  639.     switch (msg)    {
  640.         case CREATE_WINDOW:
  641.             CtlCreateWindowMsg(wnd);
  642.             break;
  643.         case KEYBOARD:
  644.             if (CtlKeyboardMsg(wnd, p1, p2))
  645.                 return TRUE;
  646.             break;
  647.         case PAINT:
  648.             if (GetClass(wnd) == EDITBOX ||
  649.                     GetClass(wnd) == LISTBOX ||
  650.                         GetClass(wnd) == TEXTBOX)
  651.                 SetScrollBars(wnd);
  652.             break;
  653.         case BORDER:
  654.             if (GetClass(wnd) == EDITBOX)    {
  655.                 WINDOW oldFocus = inFocus;
  656.                 inFocus = NULL;
  657.                 DefaultWndProc(wnd, msg, p1, p2);
  658.                 inFocus = oldFocus;
  659.                 return TRUE;
  660.             }
  661.             break;
  662.         case SETFOCUS:
  663.             if (p1)    {
  664.                 DefaultWndProc(wnd, msg, p1, p2);
  665.                 GetParent(wnd)->dFocus = ct;
  666.                 SendMessage(GetParent(wnd), COMMAND,
  667.                     inFocusCommand(db), ENTERFOCUS);
  668.                 return TRUE;
  669.             }
  670.             else 
  671.                 SendMessage(GetParent(wnd), COMMAND,
  672.                     inFocusCommand(db), LEAVEFOCUS);
  673.             break;
  674.         case CLOSE_WINDOW:
  675.             CtlCloseWindowMsg(wnd);
  676.             break;
  677.         default:
  678.             break;
  679.     }
  680.     return DefaultWndProc(wnd, msg, p1, p2);
  681. }
  682.  
  683. /* ---- change the focus to the next or previous control --- */
  684. static void ChangeFocus(WINDOW wnd, int direc)
  685. {
  686.     DBOX *db = wnd->extension;
  687.      CTLWINDOW *ct = db->ctl;
  688.      CTLWINDOW *ctt;
  689.  
  690.     /* --- find the control that has the focus --- */
  691.     while (ct->class)    {
  692.         if (ct == wnd->dFocus)
  693.             break;
  694.         ct++;
  695.     }
  696.     if (ct->class)    {
  697.         ctt = ct;
  698.         do    {
  699.             /* ----- point to next or previous control ----- */
  700.             if (direc)    {
  701.                 ct++;
  702.                 if (ct->class == 0)
  703.                     ct = db->ctl;
  704.             }
  705.             else    {
  706.                 if (ct == db->ctl)
  707.                     while (ct->class)
  708.                         ct++;
  709.                 --ct;
  710.             }
  711.  
  712.             if (ct->class != BOX && ct->class != TEXT)    {
  713.                 SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  714.                 SendMessage(ctt->wnd, PAINT, 0, 0);
  715.                 SendMessage(ct->wnd, PAINT, 0, 0);
  716.                 break;
  717.             }
  718.         } while (ct != ctt);
  719.     }
  720. }
  721.  
  722. void SetFocusCursor(WINDOW wnd)
  723. {
  724.     if (wnd == inFocus)    {
  725.         SendMessage(NULL, SHOW_CURSOR, 0, 0);
  726.         SendMessage(wnd, KEYBOARD_CURSOR, 1, 0);
  727.     }
  728. }
  729.