home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 06 / dflat3 / listbox.c < prev    next >
Text File  |  1991-05-14  |  10KB  |  402 lines

  1. /* ------------- listbox.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "dflat.h"
  7.  
  8. #ifdef INCLUDE_MULTILINE
  9. static int ExtendSelections(WINDOW, int, int);
  10. static void TestExtended(WINDOW, PARAM);
  11. static void ClearAllSelections(WINDOW);
  12. static void SetSelection(WINDOW, int);
  13. static void FlipSelection(WINDOW, int);
  14. static void ClearSelection(WINDOW, int);
  15. #endif
  16. static void near writeselection(WINDOW, int, int, RECT *);
  17. static void near change_selection(WINDOW, int, int);
  18. static int near selection_in_window(WINDOW, int);
  19.  
  20. int ListBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  21. {
  22.     int rtn, sel;
  23.     static int py = -1;
  24.     int my = (int) p2 - GetTop(wnd);
  25.     RECT rc;
  26.  
  27.     if (my >= wnd->wlines-wnd->wtop)
  28.         my = wnd->wlines - wnd->wtop;
  29.  
  30.     switch (msg)    {
  31.         case CREATE_WINDOW:
  32.             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  33.             wnd->selection = -1;
  34.             wnd->AddMode = FALSE;
  35.             wnd->AnchorPoint = -1;
  36.             wnd->SelectCount = 0;
  37.             return rtn;
  38. #ifdef INCLUDE_MULTILINE
  39.         case BORDER:
  40.             if (isMultiLine(wnd))    {
  41.                 char ttl[80] = "";
  42.                 WINDOW wnd1 = wnd;
  43.                 char *cp;
  44.                 if (!TestAttribute(wnd1, TITLEBAR))    {
  45.                     if ((wnd1 = GetParent(wnd)) == NULLWND)
  46.                         break;
  47.                     if (!TestAttribute(wnd1, TITLEBAR))
  48.                         break;
  49.                 }
  50.                 if (wnd1->title)
  51.                     strcpy(ttl, wnd1->title);
  52.                 if ((cp = strstr(ttl, " (Add)")) != NULL)
  53.                     *cp = '\0';
  54.                 if (wnd->AddMode)
  55.                     /* ---- in Add mode ---- */
  56.                     strcat(ttl, " (Add)");
  57.                 InsertTitle(wnd1, ttl);
  58.                 if (wnd != wnd1)
  59.                     SendMessage(wnd1, BORDER, 0, 0);
  60.             }
  61.             break;
  62. #endif
  63.         case ADDTEXT:
  64.             if (wnd->selection == -1)
  65.                 PostMessage(wnd, LB_SETSELECTION, 0, 0);
  66.             if (*(char *)p1 == LISTSELECTOR)
  67.                 wnd->SelectCount++;
  68.             p2 = wnd->wlines == wnd->selection;
  69.             break;
  70.         case CLEARTEXT:
  71.             wnd->selection = -1;
  72.             wnd->AnchorPoint = -1;
  73.             wnd->SelectCount = 0;
  74.             break;
  75.         case SCROLL:
  76.             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  77.             writeselection(wnd, wnd->selection, TRUE, NULL);
  78.             return rtn;
  79.         case KEYBOARD:
  80. #ifdef INCLUDE_SYSTEM_MENUS
  81.             if (WindowMoving || WindowSizing)
  82.                 break;
  83. #endif
  84.             switch ((int) p1)    {
  85. #ifdef INCLUDE_MULTILINE
  86.                 case SHIFT_F8:
  87.                     if (isMultiLine(wnd))    {
  88.                         wnd->AddMode ^= TRUE;
  89.                         SendMessage(wnd, BORDER, 0, 0);
  90.                     }
  91.                     return TRUE;
  92. #endif
  93.                 case UP:
  94. #ifdef INCLUDE_MULTILINE
  95.                     TestExtended(wnd, p2);
  96. #endif
  97.                     if (wnd->selection > 0)    {
  98.                         if (wnd->selection == wnd->wtop)    {
  99.                             writeselection(wnd, wnd->selection, FALSE, NULL);
  100.                             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  101.                             PostMessage(wnd, LB_SELECTION, wnd->selection-1,
  102.                                 isMultiLine(wnd) ? p2 : FALSE);
  103.                         }
  104.                         else    {
  105.                             int newsel = wnd->selection-1;
  106.                             if (wnd->wlines == ClientHeight(wnd))
  107.                                 while (*TextLine(wnd, newsel) == LINE)
  108.                                     --newsel;
  109.                             PostMessage(wnd, LB_SELECTION, newsel,
  110.                                 isMultiLine(wnd) ? p2 : FALSE);
  111.                         }
  112.                     }
  113.                     return TRUE;
  114.                 case DN:
  115. #ifdef INCLUDE_MULTILINE
  116.                     TestExtended(wnd, p2);
  117. #endif
  118.                     if (wnd->selection < wnd->wlines-1)    {
  119.                         if (wnd->selection == wnd->wtop+ClientHeight(wnd)-1)    {
  120.                             writeselection(wnd, wnd->selection, FALSE, NULL);
  121.                             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  122.                             PostMessage(wnd, LB_SELECTION, wnd->selection+1,
  123.                                 isMultiLine(wnd) ? p2 : FALSE);
  124.                         }
  125.                         else    {
  126.                             int newsel = wnd->selection+1;
  127.                             if (wnd->wlines == ClientHeight(wnd))
  128.                                 while (*TextLine(wnd, newsel) == LINE)
  129.                                     newsel++;
  130.                             PostMessage(wnd, LB_SELECTION, newsel,
  131.                                 isMultiLine(wnd) ? p2 : FALSE);
  132.                         }
  133.                     }
  134.                     return TRUE;
  135.                 case PGUP:
  136.                 case HOME:
  137. #ifdef INCLUDE_MULTILINE
  138.                     TestExtended(wnd, p2);
  139. #endif
  140.                     rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  141.                     PostMessage(wnd, LB_SELECTION, wnd->wtop,
  142.                         isMultiLine(wnd) ? p2 : FALSE);
  143.                     return rtn;
  144.                 case PGDN:
  145.                 case END:
  146. #ifdef INCLUDE_MULTILINE
  147.                     TestExtended(wnd, p2);
  148. #endif
  149.                     rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  150.                     PostMessage(wnd, LB_SELECTION,
  151.                         wnd->wtop+ClientHeight(wnd)-1,
  152.                         isMultiLine(wnd) ? p2 : FALSE);
  153.                     return rtn;
  154. #ifdef INCLUDE_MULTILINE
  155.                 case ' ':
  156.                     if (!isMultiLine(wnd))
  157.                         break;
  158.                     sel = SendMessage(wnd, LB_CURRENTSELECTION, 0, 0);
  159.                     if (sel == -1)
  160.                         break;
  161.                     if (wnd->AddMode)
  162.                         FlipSelection(wnd, sel);
  163.                     else     {
  164.                         ClearAllSelections(wnd);
  165.                         SetSelection(wnd, sel);
  166.                     }
  167.                     if (!((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))
  168.                         wnd->AnchorPoint = sel;
  169.                     if (ItemSelected(wnd, sel))
  170.                         ExtendSelections(wnd, sel, (int) p2);
  171.                     SendMessage(wnd, PAINT, 0, 0);
  172.                     break;
  173. #endif
  174.                 case '\r':
  175.                     if (wnd->selection != -1)    {
  176.                         WINDOW pwnd = GetParent(wnd);
  177.                         int sel = wnd->selection;
  178.                         SendMessage(wnd, LB_SELECTION, sel, TRUE);
  179.                         SendMessage(pwnd, LB_CHOOSE, sel, 0);
  180.                     }
  181.                     return TRUE;
  182.                 default:
  183.                     break;
  184.             }
  185.             break;
  186.         case BUTTON_RELEASED:
  187.             py = -1;
  188.             break;
  189.         case LEFT_BUTTON:
  190. #ifdef INCLUDE_SYSTEM_MENUS
  191.             if (WindowMoving || WindowSizing)
  192.                 break;
  193. #endif
  194.             rc = ClientRect(wnd);
  195.             if (!InsideRect(p1, p2, rc))
  196.                 break;
  197.             if (my != py)    {
  198.                 int sel = wnd->wtop+my-1;
  199. #ifdef INCLUDE_MULTILINE
  200.                 int sh = getshift();
  201.                 if (!(sh & (LEFTSHIFT | RIGHTSHIFT)))    {
  202.                     if (!(sh & CTRLKEY))
  203.                         ClearAllSelections(wnd);
  204.                     wnd->AnchorPoint = sel;
  205.                     SendMessage(wnd, PAINT, 0, 0);
  206.                 }
  207. #endif
  208.                 if (*TextLine(wnd, sel) != LINE)
  209.                     SendMessage(wnd, LB_SELECTION, sel, TRUE);
  210.                 py = my;
  211.             }
  212.             return TRUE;
  213.         case DOUBLE_CLICK:
  214.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  215. #ifdef INCLUDE_SYSTEM_MENUS
  216.             if (WindowMoving || WindowSizing)
  217.                 break;
  218. #endif
  219.             rc = ClientRect(wnd);
  220.             if (InsideRect(p1, p2, rc))
  221.                 SendMessage(GetParent(wnd), LB_CHOOSE,
  222.                     wnd->selection, 0);
  223.             return TRUE;
  224.         case LB_SETSELECTION:
  225.             change_selection(wnd, (int) p1, 0);
  226.             return TRUE;
  227.         case LB_SELECTION:    {
  228.             WINDOW pwnd = GetParent(wnd);
  229.             CLASS class = GetClass(pwnd);
  230.             change_selection(wnd, (int) p1, (int) p2);
  231.             if (class != LISTBOX && DerivedClass(class) != LISTBOX)
  232.                 SendMessage(GetParent(wnd), LB_SELECTION, wnd->selection, 0);
  233.             return TRUE;
  234.         }
  235.         case LB_CURRENTSELECTION:
  236.             return wnd->selection;
  237.         case LB_GETTEXT:
  238.             if ((int)p2 != -1)    {
  239.                 char *cp1 = (char *)p1;
  240.                 char *cp2 = TextLine(wnd, (int)p2);
  241.                 while (cp2 && *cp2 && *cp2 != '\n')
  242.                     *cp1++ = *cp2++;
  243.                 *cp1 = '\0';
  244.             }
  245.             return TRUE;
  246.         case PAINT:
  247.             if (isVisible(wnd))    {
  248.                 rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  249. #ifdef INCLUDE_MULTILINE
  250.                 if (isMultiLine(wnd))    {
  251.                     int sel = 0;
  252.                     for (sel = 0; sel < wnd->wlines; sel++)    {
  253.                         if (ItemSelected(wnd, sel))
  254.                             writeselection(wnd, sel, TRUE, (RECT *)p1);
  255.                     }
  256.                 }
  257. #endif
  258.                 writeselection(wnd, wnd->selection, TRUE, (RECT *)p1);
  259.                 return rtn;
  260.             }
  261.             break;
  262.         case HORIZSCROLL:
  263.             return TRUE;
  264.         case CLOSE_WINDOW:
  265.             if (isMultiLine(wnd) && wnd->AddMode)    {
  266.                 wnd->AddMode = FALSE;
  267.                 SendMessage(wnd, BORDER, 0, 0);
  268.             }
  269.             break;
  270.         default:
  271.             break;
  272.     }
  273.     return BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  274. }
  275.  
  276. #ifdef INCLUDE_MULTILINE
  277.  
  278. static void TestExtended(WINDOW wnd, PARAM p2)
  279. {
  280.     if (isMultiLine(wnd) && !wnd->AddMode &&
  281.             !((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))    {
  282.         if (wnd->SelectCount > 1)    {
  283.             ClearAllSelections(wnd);
  284.             SendMessage(wnd, PAINT, 0, 0);
  285.         }
  286.     }
  287. }
  288.  
  289. static void ClearAllSelections(WINDOW wnd)
  290. {
  291.     if (isMultiLine(wnd) && wnd->SelectCount > 0)    {
  292.         int sel;
  293.         for (sel = 0; sel < wnd->wlines; sel++)
  294.             ClearSelection(wnd, sel);
  295.     }
  296. }
  297.  
  298. static void FlipSelection(WINDOW wnd, int sel)
  299. {
  300.     if (isMultiLine(wnd))    {
  301.         if (ItemSelected(wnd, sel))
  302.             ClearSelection(wnd, sel);
  303.         else
  304.             SetSelection(wnd, sel);
  305.     }
  306. }
  307.  
  308. static int ExtendSelections(WINDOW wnd, int sel, int shift)
  309. {    
  310.     if (shift & (LEFTSHIFT | RIGHTSHIFT) &&
  311.                         wnd->AnchorPoint != -1)    {
  312.         int i = sel;
  313.         int j = wnd->AnchorPoint;
  314.         int rtn;
  315.         if (j > i)
  316.             swap(i,j);
  317.         rtn = i - j;
  318.         while (j <= i)
  319.             SetSelection(wnd, j++);
  320.         return rtn;
  321.     }
  322.     return 0;
  323. }
  324.  
  325. static void SetSelection(WINDOW wnd, int sel)
  326. {
  327.     if (isMultiLine(wnd) && !ItemSelected(wnd, sel))    {
  328.         char *lp = TextLine(wnd, sel);
  329.         *lp = LISTSELECTOR;
  330.         wnd->SelectCount++;
  331.     }
  332. }
  333.  
  334. static void ClearSelection(WINDOW wnd, int sel)
  335. {
  336.     if (isMultiLine(wnd) && ItemSelected(wnd, sel))    {
  337.         char *lp = TextLine(wnd, sel);
  338.         *lp = ' ';
  339.         --wnd->SelectCount;
  340.     }
  341. }
  342.  
  343. int ItemSelected(WINDOW wnd, int sel)
  344. {
  345.     if (isMultiLine(wnd) && sel < wnd->wlines)    {
  346.         char *cp = TextLine(wnd, sel);
  347.         return (int)((*cp) & 255) == LISTSELECTOR;
  348.     }
  349.     return FALSE;
  350. }
  351.  
  352. #endif
  353.  
  354. static int near selection_in_window(WINDOW wnd, int sel)
  355. {
  356.     return (wnd->wlines && sel >= wnd->wtop &&
  357.             sel < wnd->wtop+ClientHeight(wnd));
  358. }
  359.  
  360. static void near writeselection(WINDOW wnd, int sel, int reverse, RECT *rc)
  361. {
  362.     if (selection_in_window(wnd, sel))
  363.         WriteTextLine(wnd, rc, sel, reverse);
  364. }
  365.  
  366. static void near change_selection(WINDOW wnd, int sel, int shift)
  367. {
  368.     if (sel != wnd->selection)    {
  369. #ifdef INCLUDE_MULTILINE
  370.         if (isMultiLine(wnd))        {
  371.             int sels;
  372.             if (!wnd->AddMode)
  373.                 ClearAllSelections(wnd);
  374.             sels = ExtendSelections(wnd, sel, shift);
  375.             if (sels > 1)
  376.                 SendMessage(wnd, PAINT, 0, 0);
  377.             if (sels == 0 && !wnd->AddMode)    {
  378.                 ClearSelection(wnd, wnd->selection);
  379.                 SetSelection(wnd, sel);
  380.                 wnd->AnchorPoint = sel;
  381.             }
  382.         }
  383. #endif
  384.         writeselection(wnd, wnd->selection,
  385. #ifdef INCLUDE_MULTILINE
  386.                 isMultiLine(wnd) ?
  387.                 ItemSelected(wnd, wnd->selection) :
  388. #endif
  389.                 FALSE,
  390.                 NULL);
  391.         wnd->selection = sel;
  392.         writeselection(wnd, sel,
  393. #ifdef INCLUDE_MULTILINE
  394.                 (isMultiLine(wnd) && wnd->AddMode) ?
  395.                 !ItemSelected(wnd, sel) :
  396. #endif
  397.                 TRUE,
  398.                 NULL);
  399.         
  400.     }
  401. }
  402.