home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 06 / dflat3 / popdown.c < prev    next >
Text File  |  1991-05-19  |  6KB  |  248 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, LPARAM(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, LPARAM(sel), 0);
  76.                 }
  77.                 pd1++;
  78.                 PostMessage(wnd, LB_SETSELECTION, mnu->Selection, 0);
  79.             }
  80.             break;
  81.         case LEFT_BUTTON:
  82.             if (SendMessage(wnd, INSIDE_WINDOW, p1, p2))
  83.                 break;
  84.             /* --- note: fall through here --- */
  85.         case DOUBLE_CLICK:
  86.             if (p2 == GetTop(GetParent(wnd)))
  87.                 PostMessage(GetParent(wnd), msg, p1, p2);
  88.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  89.             return FALSE;
  90.         case BORDER:
  91.             rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE);
  92.  
  93.             for (i = 0; i < ClientHeight(wnd); i++)    {
  94.                 if (*TextLine(wnd, i) == LINE)    {
  95.                     wputch(wnd, LEDGE, 0, i+1);
  96.                     wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
  97.                 }
  98.             }
  99.             return rtn;
  100.  
  101.         case LB_SELECTION:
  102.             rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE);
  103.             if (ActivePopDown != NULL)    {
  104.                 mnu->Selection = (int)p1;
  105.                 if (p2 && GetParent(wnd))    {
  106.                     int *attr = &(ActivePopDown+(int)p1)->Attrib;
  107.                     if (*attr & INACTIVE)
  108.                         beep();
  109.                     else if (*attr & TOGGLE)    {
  110.                         char *tl = TextLine(wnd, (int)p1);
  111.                         *attr ^= CHECKED;
  112.                         if (*attr & CHECKED)
  113.                             *tl = CHECKMARK;
  114.                         else
  115.                             *tl = ' ';
  116.                         SendMessage(wnd, PAINT, 0, 0);
  117.                     }
  118.                     else    {
  119.                         PostMessage(GetParent(wnd), COMMAND,
  120.                             (ActivePopDown+(int)p1)->ActionId, p1);
  121.                         SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  122.                     }
  123.                 }
  124.             }
  125.             return rtn;
  126.         case KEYBOARD:
  127.             if (ActivePopDown != NULL)    {
  128.                 int c = tolower((int)p1);
  129.                 int sel = 0;
  130.                 struct PopDown *pd = ActivePopDown;
  131.                 while (pd->SelectionTitle != NULL)    {
  132.                     char *cp = strchr(pd->SelectionTitle,
  133.                                     SHORTCUTCHAR);
  134.                     if (cp && tolower(*(cp+1)) == c ||
  135.                             pd->Accelerator == (int) p1)    {
  136.                         PostMessage(wnd, LB_SELECTION, sel, TRUE);
  137.                         return TRUE;
  138.                     }
  139.                     pd++, sel++;
  140.                 }
  141.             }
  142.             if (p1 == ESC)    {
  143.                 SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  144.                 return TRUE;
  145.             }
  146.             switch ((int)p1)    {
  147.                 case FWD:
  148.                 case BS:
  149.                     if (GetClass(GetParent(wnd)) == MENUBAR)    {
  150.                         PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  151.                         return TRUE;
  152.                     }
  153.                     break;
  154.                 case UP:
  155.                     if (wnd->selection == 0)    {
  156.                         if (wnd->wlines == ClientHeight(wnd))    {
  157.                             PostMessage(wnd, LB_SELECTION, wnd->wlines-1, FALSE);
  158.                             return TRUE;
  159.                         }
  160.                     }
  161.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  162.                 case DN:
  163.                     if (wnd->selection == wnd->wlines-1)    {
  164.                         if (wnd->wlines == ClientHeight(wnd))    {
  165.                             PostMessage(wnd, LB_SELECTION, 0, FALSE);
  166.                             return TRUE;
  167.                         }
  168.                     }
  169.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  170.                 case HOME:
  171.                 case END:
  172.                 case '\r':
  173.                     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  174.             }
  175.             return FALSE;
  176.         case CLOSE_WINDOW:
  177.             SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  178.             SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  179.             SendMessage(GetParent(wnd), CLOSE_POPDOWN, 0, 0);
  180.             ActivePopDown = NULL;
  181.             mnu = NULL;
  182.             SendMessage(NULLWND, RESTORE_CURSOR, 0, 0);
  183.             break;
  184.         default:
  185.             break;
  186.     }
  187.     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  188. }
  189.  
  190. int MenuHeight(struct PopDown *pd)
  191. {
  192.     int ht = 0;
  193.     while (pd[ht].SelectionTitle != NULL)
  194.         ht++;
  195.     return ht+2;
  196. }
  197.  
  198. int MenuWidth(struct PopDown *pd)
  199. {
  200.     int wd = 0, i;
  201.     int len = 0;
  202.  
  203.     wd = SelectionWidth(pd);
  204.     while (pd->SelectionTitle != NULL)    {
  205.         if (pd->Accelerator)    {
  206.             for (i = 0; keys[i].keylabel; i++)
  207.                 if (keys[i].keycode == pd->Accelerator)    {
  208.                     len = max(len, 2+strlen(keys[i].keylabel));
  209.                     break;
  210.                 }
  211.         }
  212.         pd++;
  213.     }
  214.     return wd+5+len;
  215. }
  216.  
  217. static int SelectionWidth(struct PopDown *pd)
  218. {
  219.     int wd = 0;
  220.     while (pd->SelectionTitle != NULL)    {
  221.         int len = strlen(pd->SelectionTitle)-1;
  222.         wd = max(wd, len);
  223.         pd++;
  224.     }
  225.     return wd;
  226. }
  227.  
  228. int CopyCommand(char *dest, char *src, int skipcolor, int bg)
  229. {
  230.     char *d = dest;
  231.     while (*src && *src != '\n')    {
  232.         if (*src == SHORTCUTCHAR)    {
  233.             src++;
  234.             if (!skipcolor)    {
  235.                 *dest++ = CHANGECOLOR;
  236.                 *dest++ = cfg.clr.ShortCutFG | 0x80;
  237.                 *dest++ = bg | 0x80;
  238.                 *dest++ = *src++;
  239.                 *dest++ = RESETCOLOR;
  240.             }
  241.         }
  242.         else
  243.             *dest++ = *src++;
  244.     }
  245.     return (int) (dest - d);
  246. }
  247.  
  248.