home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 05 / d_flat / popdown.c < prev    next >
Text File  |  1991-02-18  |  6KB  |  250 lines

  1. /* ------------- popdown.c ----------- */
  2.  
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <ctype.h>
  7. #include "dflat.h"
  8.  
  9. static int SelectionWidth(struct PopDown *);
  10.  
  11. extern char *Clipboard;
  12. static MENU *mnu;
  13.  
  14. int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  15. {
  16.     int wd, rtn, i;
  17.     struct PopDown *pd1;
  18.     char sep[80], *cp = sep;
  19.     char sel[80];
  20.     static struct PopDown *ActivePopDown = NULL;
  21.  
  22.     switch (msg)    {
  23.         case CREATE_WINDOW:
  24.             ClearAttribute(wnd, TITLEBAR     |
  25.                                 VSCROLLBAR     |
  26.                                 MOVEABLE     |
  27.                                 SIZEABLE     |
  28.                                 HSCROLLBAR);
  29.             rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE);
  30.             SendMessage(wnd, CAPTURE_MOUSE, 0, 0);
  31.             SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
  32.             SendMessage(NULLWND, SAVE_CURSOR, 0, 0);
  33.             SendMessage(NULLWND, HIDE_CURSOR, 0, 0);
  34.             return rtn;
  35.         case SETFOCUS:
  36.             return FALSE;
  37.         case BUILD_SELECTIONS:
  38.             mnu = (void *) p1;
  39.             ActivePopDown = pd1 = mnu->Selections;
  40.             wd = MenuWidth(ActivePopDown)-2;
  41.             while (wd--)
  42.                 *cp++ = LINE;
  43.             *cp = '\0';
  44.             while (pd1->SelectionTitle != NULL)    {
  45.                 if (*pd1->SelectionTitle == LINE)
  46.                     SendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
  47.                 else    {
  48.                     memset(sel, '\0', sizeof sel);
  49.                     if (pd1->Attrib & INACTIVE)    {
  50.                         strcpy(sel, "   ");
  51.                         *sel = CHANGECOLOR;
  52.                         *(sel+1) = cfg.clr.InactiveSelFG | 0x80;
  53.                         *(sel+2) = cfg.clr.PopDownBG | 0x80;
  54.                     }
  55.                     strcat(sel, " ");
  56.                     CopyCommand(sel+strlen(sel), pd1->SelectionTitle,
  57.                             pd1->Attrib & INACTIVE, cfg.clr.PopDownBG);
  58.                     if (pd1->Attrib & CHECKED)
  59.                         *sel = CHECKMARK;
  60.                     if (pd1->Accelerator)    {
  61.                         int i;
  62.                         int wd1 = 2+SelectionWidth(ActivePopDown) - strlen(pd1->SelectionTitle);
  63.                         for (i = 0; keys[i].keylabel; i++)
  64.                             if (keys[i].keycode == pd1->Accelerator)    {
  65.                                 while (wd1--)
  66.                                     strcat(sel, " ");
  67.                                 strcat(sel, "[");
  68.                                 strcat(sel, keys[i].keylabel);
  69.                                 strcat(sel, "]");
  70.                                 break;
  71.                             }
  72.                     }
  73.                     strcat(sel, "  ");
  74.                     sel[strlen(sel)-1] = RESETCOLOR;
  75.                     SendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
  76.                 }
  77.                 pd1++;
  78.                 PostMessage(wnd, LB_SETSELECTION, mnu->Selection, 0);
  79.             }
  80.             break;
  81.         case HORIZSCROLL:
  82.             return FALSE;
  83.         case LEFT_BUTTON:
  84.             if (SendMessage(wnd, INSIDE_WINDOW, p1, p2))
  85.                 break;
  86.             /* --- note: fall through here --- */
  87.         case DOUBLE_CLICK:
  88.             if (p2 == GetTop(GetParent(wnd)))
  89.                 PostMessage(GetParent(wnd), msg, p1, p2);
  90.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  91.             return FALSE;
  92.         case BORDER:
  93.             rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE);
  94.  
  95.             for (i = 0; i < ClientHeight(wnd); i++)    {
  96.                 if (*TextLine(wnd, i) == LINE)    {
  97.                     wputch(wnd, LEDGE, -1, i);
  98.                     wputch(wnd, REDGE, WindowWidth(wnd)-2, i);
  99.                 }
  100.             }
  101.             return rtn;
  102.  
  103.         case LB_SELECTION:
  104.             rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE);
  105.             if (ActivePopDown != NULL)    {
  106.                 mnu->Selection = (int)p1;
  107.                 if (p2 && GetParent(wnd))    {
  108.                     int *attr = &(ActivePopDown+(int)p1)->Attrib;
  109.                     if (*attr & INACTIVE)
  110.                         beep();
  111.                     else if (*attr & TOGGLE)    {
  112.                         char *tl = TextLine(wnd, (int)p1);
  113.                         *attr ^= CHECKED;
  114.                         if (*attr & CHECKED)
  115.                             *tl = CHECKMARK;
  116.                         else
  117.                             *tl = ' ';
  118.                         SendMessage(wnd, PAINT, 0, 0);
  119.                     }
  120.                     else    {
  121.                         PostMessage(GetParent(wnd), COMMAND,
  122.                             (ActivePopDown+(int)p1)->ActionId, p1);
  123.                         SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  124.                     }
  125.                 }
  126.             }
  127.             return rtn;
  128.         case KEYBOARD:
  129.             if (ActivePopDown != NULL)    {
  130.                 int c = tolower((int)p1);
  131.                 int sel = 0;
  132.                 struct PopDown *pd = ActivePopDown;
  133.                 while (pd->SelectionTitle != NULL)    {
  134.                     char *cp = strchr(pd->SelectionTitle,
  135.                                     SHORTCUTCHAR);
  136.                     if (cp && tolower(*(cp+1)) == c ||
  137.                             pd->Accelerator == (int) p1)    {
  138.                         PostMessage(wnd, LB_SELECTION, sel, TRUE);
  139.                         return TRUE;
  140.                     }
  141.                     pd++, sel++;
  142.                 }
  143.             }
  144.             if (p1 == ESC)    {
  145.                 SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  146.                 return TRUE;
  147.             }
  148.             switch ((int)p1)    {
  149.                 case FWD:
  150.                 case BS:
  151.                     if (GetClass(GetParent(wnd)) == MENUBAR)    {
  152.                         PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  153.                         return TRUE;
  154.                     }
  155.                     break;
  156.                 case UP:
  157.                     if (wnd->selection == 0)    {
  158.                         if (wnd->wlines == ClientHeight(wnd))    {
  159.                             PostMessage(wnd, LB_SELECTION, wnd->wlines-1, FALSE);
  160.                             return TRUE;
  161.                         }
  162.                     }
  163.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  164.                 case DN:
  165.                     if (wnd->selection == wnd->wlines-1)    {
  166.                         if (wnd->wlines == ClientHeight(wnd))    {
  167.                             PostMessage(wnd, LB_SELECTION, 0, FALSE);
  168.                             return TRUE;
  169.                         }
  170.                     }
  171.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  172.                 case HOME:
  173.                 case END:
  174.                 case '\r':
  175.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  176.             }
  177.             return FALSE;
  178.         case CLOSE_WINDOW:
  179.             SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  180.             SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  181.             SendMessage(GetParent(wnd), CLOSE_POPDOWN, 0, 0);
  182.             ActivePopDown = NULL;
  183.             mnu = NULL;
  184.             SendMessage(NULLWND, RESTORE_CURSOR, 0, 0);
  185.             break;
  186.         default:
  187.             break;
  188.     }
  189.     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  190. }
  191.  
  192. int MenuHeight(struct PopDown *pd)
  193. {
  194.     int ht = 0;
  195.     while (pd[ht].SelectionTitle != NULL)
  196.         ht++;
  197.     return ht+2;
  198. }
  199.  
  200. int MenuWidth(struct PopDown *pd)
  201. {
  202.     int wd = 0, i;
  203.     int len = 0;
  204.  
  205.     wd = SelectionWidth(pd);
  206.     while (pd->SelectionTitle != NULL)    {
  207.         if (pd->Accelerator)    {
  208.             for (i = 0; keys[i].keylabel; i++)
  209.                 if (keys[i].keycode == pd->Accelerator)    {
  210.                     len = max(len, 2+strlen(keys[i].keylabel));
  211.                     break;
  212.                 }
  213.         }
  214.         pd++;
  215.     }
  216.     return wd+5+len;
  217. }
  218.  
  219. static int SelectionWidth(struct PopDown *pd)
  220. {
  221.     int wd = 0;
  222.     while (pd->SelectionTitle != NULL)    {
  223.         int len = strlen(pd->SelectionTitle)-1;
  224.         wd = max(wd, len);
  225.         pd++;
  226.     }
  227.     return wd;
  228. }
  229.  
  230. int CopyCommand(char *dest, char *src, int skipcolor, int bg)
  231. {
  232.     char *d = dest;
  233.     while (*src && *src != '\n')    {
  234.         if (*src == SHORTCUTCHAR)    {
  235.             src++;
  236.             if (!skipcolor)    {
  237.                 *dest++ = CHANGECOLOR;
  238.                 *dest++ = cfg.clr.ShortCutFG | 0x80;
  239.                 *dest++ = bg | 0x80;
  240.                 *dest++ = *src++;
  241.                 *dest++ = RESETCOLOR;
  242.             }
  243.         }
  244.         else
  245.             *dest++ = *src++;
  246.     }
  247.     return (int) (dest - d);
  248. }
  249.  
  250.