home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 08 / dflat5 / popdown.c < prev    next >
Text File  |  1991-06-27  |  7KB  |  277 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. int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  12. {
  13.     int wd, rtn, i;
  14.     struct PopDown *pd1;
  15.     unsigned char sep[80], *cp = sep;
  16.     unsigned char sel[80];
  17.     struct PopDown *ActivePopDown = NULL;
  18.     WINDOW currFocus;
  19.  
  20.     switch (msg)    {
  21.         case CREATE_WINDOW:
  22.             ClearAttribute(wnd, HASTITLEBAR     |
  23.                                 VSCROLLBAR     |
  24.                                 MOVEABLE     |
  25.                                 SIZEABLE     |
  26.                                 HSCROLLBAR);
  27.             rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE);
  28.             SendMessage(wnd, CAPTURE_MOUSE, 0, 0);
  29.             SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
  30.             SendMessage(NULLWND, SAVE_CURSOR, 0, 0);
  31.             SendMessage(NULLWND, HIDE_CURSOR, 0, 0);
  32.             return rtn;
  33.         case BUILD_SELECTIONS:
  34.             wnd->mnu = (void *) p1;
  35.             ActivePopDown = pd1 = wnd->mnu->Selections;
  36.             wd = MenuWidth(ActivePopDown)-2;
  37.             while (wd--)
  38.                 *cp++ = LINE;
  39.             *cp = '\0';
  40.             wnd->selection = wnd->mnu->Selection;
  41.             while (pd1->SelectionTitle != NULL)    {
  42.                 if (*pd1->SelectionTitle == LINE)
  43.                     SendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
  44.                 else    {
  45.                     memset(sel, '\0', sizeof sel);
  46.                     if (pd1->Attrib & INACTIVE)    {
  47.                         strcpy(sel, "   ");
  48.                         *sel = CHANGECOLOR;
  49.                         *(sel+1) = cfg.clr[POPDOWNMENU] [HILITE_COLOR] [FG] | 0x80;
  50.                         *(sel+2) = cfg.clr[POPDOWNMENU] [STD_COLOR] [BG] | 0x80;
  51.                     }
  52.                     strcat(sel, " ");
  53.                     CopyCommand(sel+strlen(sel), pd1->SelectionTitle,
  54.                             pd1->Attrib & INACTIVE, cfg.clr[POPDOWNMENU] [STD_COLOR] [BG]);
  55.                     if (pd1->Attrib & CHECKED)
  56.                         *sel = CHECKMARK;
  57.                     if (pd1->Accelerator)    {
  58.                         int i;
  59.                         int wd1 = 2+SelectionWidth(ActivePopDown) - strlen(pd1->SelectionTitle);
  60.                         for (i = 0; keys[i].keylabel; i++)
  61.                             if (keys[i].keycode == pd1->Accelerator)    {
  62.                                 while (wd1--)
  63.                                     strcat(sel, " ");
  64.                                 strcat(sel, "[");
  65.                                 strcat(sel, keys[i].keylabel);
  66.                                 strcat(sel, "]");
  67.                                 break;
  68.                             }
  69.                     }
  70.                     strcat(sel, "  ");
  71.                     sel[strlen(sel)-1] = RESETCOLOR;
  72.                     SendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
  73.                 }
  74.                 pd1++;
  75.             }
  76.             break;
  77.         case LEFT_BUTTON:
  78.             if (SendMessage(wnd, INSIDE_WINDOW, p1, p2))
  79.                 break;
  80.             if ((int)p2 == GetTop(GetParent(wnd)))
  81.                 if (GetClass(GetParent(wnd)) == MENUBAR)
  82.                     PostMessage(GetParent(wnd), msg, p1, p2);
  83.             return FALSE;
  84.         case DOUBLE_CLICK:
  85.             return TRUE;
  86.         case BUTTON_RELEASED:
  87.             if (InsideRect((int)p1, (int)p2, ClientRect(wnd)))
  88.                 SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  89.             else    {
  90.                 WINDOW pwnd = GetParent(wnd);
  91.                 if (GetClass(pwnd) == MENUBAR && (int)p2 == GetTop(pwnd))
  92.                     break;
  93.                 if ((int)p1 == GetLeft(pwnd)+2)
  94.                     break;
  95.                 SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  96.                 return TRUE;
  97.             }
  98.             break;
  99.         case PAINT:
  100.             if (wnd->mnu == NULL)
  101.                 return TRUE;
  102.             break;
  103.         case BORDER:
  104.             if (wnd->mnu == NULL)
  105.                 return TRUE;
  106.             currFocus = inFocus;
  107.             inFocus = NULLWND;
  108.             rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE);
  109.             inFocus = currFocus;
  110.  
  111.             for (i = 0; i < ClientHeight(wnd); i++)    {
  112.                 if (*TextLine(wnd, i) == LINE)    {
  113.                     wputch(wnd, LEDGE, 0, i+1);
  114.                     wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
  115.                 }
  116.             }
  117.             return rtn;
  118.  
  119.         case LB_CHOOSE:
  120.             ActivePopDown = wnd->mnu->Selections;
  121.             if (ActivePopDown != NULL)    {
  122.                 int *attr = &(ActivePopDown+(int)p1)->Attrib;
  123.                 wnd->mnu->Selection = (int)p1;
  124.                 if (*attr & INACTIVE)
  125.                     beep();
  126.                 else if (*attr & TOGGLE)    {
  127.                     unsigned char *tl = TextLine(wnd, (int)p1);
  128.                     *attr ^= CHECKED;
  129.                     if (*attr & CHECKED)
  130.                         *tl = CHECKMARK;
  131.                     else
  132.                         *tl = ' ';
  133.                     SendMessage(wnd, PAINT, 0, 0);
  134.                 }
  135.                 else    {
  136.                     PostMessage(GetParent(wnd), COMMAND,
  137.                         (ActivePopDown+(int)p1)->ActionId, p1);
  138.                     SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  139.                 }
  140.             }
  141.             return TRUE;
  142.         case KEYBOARD:
  143.             if (wnd->mnu != NULL)    {
  144.                 ActivePopDown = wnd->mnu->Selections;
  145.                 if (ActivePopDown != NULL)    {
  146.                     int c = tolower((int)p1);
  147.                     int sel = 0;
  148.                     struct PopDown *pd = ActivePopDown;
  149.                     int a = AltConvert(c);
  150.  
  151.                     while (pd->SelectionTitle != NULL)    {
  152.                         char *cp = strchr(pd->SelectionTitle,
  153.                                         SHORTCUTCHAR);
  154.                         int sc = tolower(*(cp+1));
  155.                         if ((cp && sc == c) ||
  156.                                 (a && sc == a) ||
  157.                                     pd->Accelerator == c)    {
  158.                             PostMessage(wnd, LB_CHOOSE, sel, TRUE);
  159.                             return TRUE;
  160.                         }
  161.                         pd++, sel++;
  162.                     }
  163.                 }
  164.             }
  165.             switch ((int)p1)    {
  166.                 case F1:
  167. #ifdef INCLUDE_HELP
  168.                     if (ActivePopDown == NULL)
  169.                         SendMessage(GetParent(wnd), msg, p1, p2);
  170.                     else 
  171.                         DisplayHelp(wnd, (ActivePopDown+wnd->selection)->help);
  172.                     return TRUE;
  173. #endif
  174.                 case ESC:
  175.                     SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  176.                     return TRUE;
  177.                 case FWD:
  178.                 case BS:
  179.                     if (GetClass(GetParent(wnd)) == MENUBAR)    {
  180.                         PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  181.                         return TRUE;
  182.                     }
  183.                     break;
  184.                 case UP:
  185.                     if (wnd->selection == 0)    {
  186.                         if (wnd->wlines == ClientHeight(wnd))    {
  187.                             PostMessage(wnd, LB_SELECTION, wnd->wlines-1, FALSE);
  188.                             return TRUE;
  189.                         }
  190.                     }
  191.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  192.                 case DN:
  193.                     if (wnd->selection == wnd->wlines-1)    {
  194.                         if (wnd->wlines == ClientHeight(wnd))    {
  195.                             PostMessage(wnd, LB_SELECTION, 0, FALSE);
  196.                             return TRUE;
  197.                         }
  198.                     }
  199.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  200.                 case HOME:
  201.                 case END:
  202.                 case '\r':
  203.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  204.             }
  205.             return FALSE;
  206.         case CLOSE_WINDOW:
  207.             SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  208.             SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  209.             SendMessage(GetParent(wnd), CLOSE_POPDOWN, p1, 0);
  210.             SendMessage(NULLWND, RESTORE_CURSOR, 0, 0);
  211.             break;
  212.         default:
  213.             break;
  214.     }
  215.     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  216. }
  217.  
  218. int MenuHeight(struct PopDown *pd)
  219. {
  220.     int ht = 0;
  221.     while (pd[ht].SelectionTitle != NULL)
  222.         ht++;
  223.     return ht+2;
  224. }
  225.  
  226. int MenuWidth(struct PopDown *pd)
  227. {
  228.     int wd = 0, i;
  229.     int len = 0;
  230.  
  231.     wd = SelectionWidth(pd);
  232.     while (pd->SelectionTitle != NULL)    {
  233.         if (pd->Accelerator)    {
  234.             for (i = 0; keys[i].keylabel; i++)
  235.                 if (keys[i].keycode == pd->Accelerator)    {
  236.                     len = max(len, 2+strlen(keys[i].keylabel));
  237.                     break;
  238.                 }
  239.         }
  240.         pd++;
  241.     }
  242.     return wd+5+len;
  243. }
  244.  
  245. static int SelectionWidth(struct PopDown *pd)
  246. {
  247.     int wd = 0;
  248.     while (pd->SelectionTitle != NULL)    {
  249.         int len = strlen(pd->SelectionTitle)-1;
  250.         wd = max(wd, len);
  251.         pd++;
  252.     }
  253.     return wd;
  254. }
  255.  
  256. int CopyCommand(unsigned char *dest, unsigned char *src,
  257.                                         int skipcolor, int bg)
  258. {
  259.     unsigned char *d = dest;
  260.     while (*src && *src != '\n')    {
  261.         if (*src == SHORTCUTCHAR)    {
  262.             src++;
  263.             if (!skipcolor)    {
  264.                 *dest++ = CHANGECOLOR;
  265.                 *dest++ = cfg.clr[POPDOWNMENU] [HILITE_COLOR] [BG] | 0x80;
  266.                 *dest++ = bg | 0x80;
  267.                 *dest++ = *src++;
  268.                 *dest++ = RESETCOLOR;
  269.             }
  270.         }
  271.         else
  272.             *dest++ = *src++;
  273.     }
  274.     return (int) (dest - d);
  275. }
  276.  
  277.