home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / vrac / dflt20.zip / POPDOWN.C < prev    next >
Text File  |  1995-01-28  |  12KB  |  396 lines

  1. /* ------------- popdown.c ----------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static int SelectionWidth(struct PopDown *);
  6. static int py = -1;
  7. int CurrentMenuSelection;
  8.  
  9. /* ------------ CREATE_WINDOW Message ------------- */
  10. static int CreateWindowMsg(WINDOW wnd)
  11. {
  12.     int rtn, adj;
  13.     ClearAttribute(wnd, HASTITLEBAR     |
  14.                         VSCROLLBAR     |
  15.                         MOVEABLE     |
  16.                         SIZEABLE     |
  17.                         HSCROLLBAR);
  18.     /* ------ adjust to keep popdown on screen ----- */
  19.     adj = SCREENHEIGHT-1-wnd->rc.bt;
  20.     if (adj < 0)    {
  21.         wnd->rc.tp += adj;
  22.         wnd->rc.bt += adj;
  23.     }
  24.     adj = SCREENWIDTH-1-wnd->rc.rt;
  25.     if (adj < 0)    {
  26.         wnd->rc.lf += adj;
  27.         wnd->rc.rt += adj;
  28.     }
  29.     rtn = BaseWndProc(POPDOWNMENU, wnd, CREATE_WINDOW, 0, 0);
  30.     SendMessage(wnd, CAPTURE_MOUSE, 0, 0);
  31.     SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
  32.     SendMessage(NULL, SAVE_CURSOR, 0, 0);
  33.     SendMessage(NULL, HIDE_CURSOR, 0, 0);
  34.     wnd->oldFocus = inFocus;
  35.     inFocus = wnd;
  36.     return rtn;
  37. }
  38.  
  39. /* --------- LEFT_BUTTON Message --------- */
  40. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  41. {
  42.     int my = (int) p2 - GetTop(wnd);
  43.     if (InsideRect(p1, p2, ClientRect(wnd)))    {
  44.         if (my != py)    {
  45.             SendMessage(wnd, LB_SELECTION,
  46.                     (PARAM) wnd->wtop+my-1, TRUE);
  47.             py = my;
  48.         }
  49.     }
  50.     else if ((int)p2 == GetTop(GetParent(wnd)))
  51.         if (GetClass(GetParent(wnd)) == MENUBAR)
  52.             PostMessage(GetParent(wnd), LEFT_BUTTON, p1, p2);
  53. }
  54.  
  55. /* -------- BUTTON_RELEASED Message -------- */
  56. static BOOL ButtonReleasedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  57. {
  58.     py = -1;
  59.     if (InsideRect((int)p1, (int)p2, ClientRect(wnd)))    {
  60.         int sel = (int)p2 - GetClientTop(wnd);
  61.         if (*TextLine(wnd, sel) != LINE)
  62.             SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  63.     }
  64.     else    {
  65.         WINDOW pwnd = GetParent(wnd);
  66.         if (GetClass(pwnd) == MENUBAR && (int)p2==GetTop(pwnd))
  67.             return FALSE;
  68.         if ((int)p1 == GetLeft(pwnd)+2)
  69.             return FALSE;
  70.         SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  71.         return TRUE;
  72.     }
  73.     return FALSE;
  74. }
  75.  
  76. /* --------- PAINT Message -------- */
  77. static void PaintMsg(WINDOW wnd)
  78. {
  79.     int wd;
  80.     unsigned char sep[80], *cp = sep;
  81.     unsigned char sel[80];
  82.     struct PopDown *ActivePopDown;
  83.     struct PopDown *pd1;
  84.  
  85.     ActivePopDown = pd1 = wnd->mnu->Selections;
  86.     wd = MenuWidth(ActivePopDown)-2;
  87.     while (wd--)
  88.         *cp++ = LINE;
  89.     *cp = '\0';
  90.     SendMessage(wnd, CLEARTEXT, 0, 0);
  91.     wnd->selection = wnd->mnu->Selection;
  92.     while (pd1->SelectionTitle != NULL)    {
  93.         if (*pd1->SelectionTitle == LINE)
  94.             SendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
  95.         else    {
  96.             int len;
  97.             memset(sel, '\0', sizeof sel);
  98.             if (pd1->Attrib & INACTIVE)
  99.                 /* ------ inactive menu selection ----- */
  100.                 sprintf(sel, "%c%c%c",
  101.                     CHANGECOLOR,
  102.                     wnd->WindowColors [HILITE_COLOR] [FG]|0x80,
  103.                     wnd->WindowColors [STD_COLOR] [BG]|0x80);
  104.             strcat(sel, " ");
  105.             if (pd1->Attrib & CHECKED)
  106.                 /* ---- paint the toggle checkmark ---- */
  107.                 sel[strlen(sel)-1] = CHECKMARK;
  108.             len=CopyCommand(sel+strlen(sel),pd1->SelectionTitle,
  109.                     pd1->Attrib & INACTIVE,
  110.                     wnd->WindowColors [STD_COLOR] [BG]);
  111.             if (pd1->Accelerator)    {
  112.                 /* ---- paint accelerator key ---- */
  113.                 int i;
  114.                 int wd1 = 2+SelectionWidth(ActivePopDown) -
  115.                                     strlen(pd1->SelectionTitle);
  116.                 int key = pd1->Accelerator;
  117.                 if (key > 0 && key < 27)    {
  118.                     /* --- CTRL+ key --- */
  119.                     while (wd1--)
  120.                         strcat(sel, " ");
  121.                        sprintf(sel+strlen(sel), "[Ctrl+%c]", key-1+'A');
  122.                 }
  123.                 else    {
  124.                     for (i = 0; keys[i].keylabel; i++)    {
  125.                         if (keys[i].keycode == key)   {
  126.                             while (wd1--)
  127.                                 strcat(sel, " ");
  128.                             sprintf(sel+strlen(sel), "[%s]",
  129.                                 keys[i].keylabel);
  130.                             break;
  131.                         }
  132.                     }
  133.                 }
  134.             }
  135.             if (pd1->Attrib & CASCADED)    {
  136.                 /* ---- paint cascaded menu token ---- */
  137.                 if (!pd1->Accelerator)    {
  138.                     wd = MenuWidth(ActivePopDown)-len+1;
  139.                     while (wd--)
  140.                         strcat(sel, " ");
  141.                 }
  142.                 sel[strlen(sel)-1] = CASCADEPOINTER;
  143.             }
  144.             else
  145.                 strcat(sel, " ");
  146.             strcat(sel, " ");
  147.             sel[strlen(sel)-1] = RESETCOLOR;
  148.             SendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
  149.         }
  150.         pd1++;
  151.     }
  152. }
  153.  
  154. /* ---------- BORDER Message ----------- */
  155. static int BorderMsg(WINDOW wnd)
  156. {
  157.     int i, rtn = TRUE;
  158.     WINDOW currFocus;
  159.     if (wnd->mnu != NULL)    {
  160.         currFocus = inFocus;
  161.         inFocus = NULL;
  162.         rtn = BaseWndProc(POPDOWNMENU, wnd, BORDER, 0, 0);
  163.         inFocus = currFocus;
  164.         for (i = 0; i < ClientHeight(wnd); i++)    {
  165.             if (*TextLine(wnd, i) == LINE)    {
  166.                 wputch(wnd, LEDGE, 0, i+1);
  167.                 wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
  168.             }
  169.         }
  170.     }
  171.     return rtn;
  172. }
  173.  
  174. /* -------------- LB_CHOOSE Message -------------- */
  175. static void LBChooseMsg(WINDOW wnd, PARAM p1)
  176. {
  177.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  178.     if (ActivePopDown != NULL)    {
  179.         int *attr = &(ActivePopDown+(int)p1)->Attrib;
  180.         wnd->mnu->Selection = (int)p1;
  181.         if (!(*attr & INACTIVE))    {
  182.             WINDOW pwnd = GetParent(wnd);
  183.             if (*attr & TOGGLE)
  184.                 *attr ^= CHECKED;
  185.             if (pwnd != NULL)    {
  186.                 CurrentMenuSelection = p1;
  187.                 PostMessage(pwnd, COMMAND,
  188.                     (ActivePopDown+(int)p1)->ActionId, 0); // p2 was p1
  189.             }
  190.         }
  191.         else
  192.             beep();
  193.     }
  194. }
  195.  
  196. /* ---------- KEYBOARD Message --------- */
  197. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  198. {
  199.     struct PopDown *ActivePopDown = wnd->mnu->Selections;
  200.     if (wnd->mnu != NULL)    {
  201.         if (ActivePopDown != NULL)    {
  202.             int c = (int)p1;
  203.             int sel = 0;
  204.             int a;
  205.             struct PopDown *pd = ActivePopDown;
  206.  
  207.             if ((c & OFFSET) == 0)
  208.                 c = tolower(c);
  209.             a = AltConvert(c);
  210.  
  211.             while (pd->SelectionTitle != NULL)    {
  212.                 char *cp = strchr(pd->SelectionTitle,
  213.                                 SHORTCUTCHAR);
  214.                 int sc = tolower(*(cp+1));
  215.                 if ((cp && sc == c) ||
  216.                         (a && sc == a) ||
  217.                             pd->Accelerator == c)    {
  218.                     PostMessage(wnd, LB_SELECTION, sel, 0);
  219.                     PostMessage(wnd, LB_CHOOSE, sel, TRUE);
  220.                     return TRUE;
  221.                 }
  222.                 pd++, sel++;
  223.             }
  224.         }
  225.     }
  226.     switch ((int)p1)    {
  227.         case F1:
  228.             if (ActivePopDown == NULL)
  229.                 SendMessage(GetParent(wnd), KEYBOARD, p1, p2);
  230.             else 
  231.                 DisplayHelp(wnd,
  232.                     (ActivePopDown+wnd->selection)->help);
  233.             return TRUE;
  234.         case ESC:
  235.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  236.             return TRUE;
  237.         case FWD:
  238.         case BS:
  239.             if (GetClass(GetParent(wnd)) == MENUBAR)
  240.                 PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
  241.             return TRUE;
  242.         case UP:
  243.             if (wnd->selection == 0)    {
  244.                 if (wnd->wlines == ClientHeight(wnd))    {
  245.                     PostMessage(wnd, LB_SELECTION,
  246.                                     wnd->wlines-1, FALSE);
  247.                     return TRUE;
  248.                 }
  249.             }
  250.             break;
  251.         case DN:
  252.             if (wnd->selection == wnd->wlines-1)    {
  253.                 if (wnd->wlines == ClientHeight(wnd))    {
  254.                     PostMessage(wnd, LB_SELECTION, 0, FALSE);
  255.                     return TRUE;
  256.                 }
  257.             }
  258.             break;
  259.         case HOME:
  260.         case END:
  261.         case '\r':
  262.             break;
  263.         default:
  264.             return TRUE;
  265.     }
  266.     return FALSE;
  267. }
  268.  
  269. /* ----------- CLOSE_WINDOW Message ---------- */
  270. static int CloseWindowMsg(WINDOW wnd)
  271. {
  272.     int rtn;
  273.     WINDOW pwnd = GetParent(wnd);
  274.     SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  275.     SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  276.     SendMessage(NULL, RESTORE_CURSOR, 0, 0);
  277.     inFocus = wnd->oldFocus;
  278.     rtn = BaseWndProc(POPDOWNMENU, wnd, CLOSE_WINDOW, 0, 0);
  279.     SendMessage(pwnd, CLOSE_POPDOWN, 0, 0);
  280.     return rtn;
  281. }
  282.  
  283. /* - Window processing module for POPDOWNMENU window class - */
  284. int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  285. {
  286.     switch (msg)    {
  287.         case CREATE_WINDOW:
  288.             return CreateWindowMsg(wnd);
  289.         case LEFT_BUTTON:
  290.             LeftButtonMsg(wnd, p1, p2);
  291.             return FALSE;
  292.         case DOUBLE_CLICK:
  293.             return TRUE;
  294.         case LB_SELECTION:
  295.             if (*TextLine(wnd, (int)p1) == LINE)
  296.                 return TRUE;
  297.             wnd->mnu->Selection = (int)p1;
  298.             break;
  299.         case BUTTON_RELEASED:
  300.             if (ButtonReleasedMsg(wnd, p1, p2))
  301.                 return TRUE;
  302.             break;
  303.         case BUILD_SELECTIONS:
  304.             wnd->mnu = (void *) p1;
  305.             wnd->selection = wnd->mnu->Selection;
  306.             break;
  307.         case PAINT:
  308.             if (wnd->mnu == NULL)
  309.                 return TRUE;
  310.             PaintMsg(wnd);
  311.             break;
  312.         case BORDER:
  313.             return BorderMsg(wnd);
  314.         case LB_CHOOSE:
  315.             LBChooseMsg(wnd, p1);
  316.             return TRUE;
  317.         case KEYBOARD:
  318.             if (KeyboardMsg(wnd, p1, p2))
  319.                 return TRUE;
  320.             break;
  321.         case CLOSE_WINDOW:
  322.             return CloseWindowMsg(wnd);
  323.         default:
  324.             break;
  325.     }
  326.     return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
  327. }
  328.  
  329. /* --------- compute menu height -------- */
  330. int MenuHeight(struct PopDown *pd)
  331. {
  332.     int ht = 0;
  333.     while (pd[ht].SelectionTitle != NULL)
  334.         ht++;
  335.     return ht+2;
  336. }
  337.  
  338. /* --------- compute menu width -------- */
  339. int MenuWidth(struct PopDown *pd)
  340. {
  341.     int wd = 0, i;
  342.     int len = 0;
  343.  
  344.     wd = SelectionWidth(pd);
  345.     while (pd->SelectionTitle != NULL)    {
  346.         if (pd->Accelerator)    {
  347.             for (i = 0; keys[i].keylabel; i++)
  348.                 if (keys[i].keycode == pd->Accelerator)    {
  349.                     len = max(len, 2+strlen(keys[i].keylabel));
  350.                     break;
  351.                 }
  352.         }
  353.         if (pd->Attrib & CASCADED)
  354.             len = max(len, 2);
  355.         pd++;
  356.     }
  357.     return wd+5+len;
  358. }
  359.  
  360. /* ---- compute the maximum selection width in a menu ---- */
  361. static int SelectionWidth(struct PopDown *pd)
  362. {
  363.     int wd = 0;
  364.     while (pd->SelectionTitle != NULL)    {
  365.         int len = strlen(pd->SelectionTitle)-1;
  366.         wd = max(wd, len);
  367.         pd++;
  368.     }
  369.     return wd;
  370. }
  371.  
  372. /* ----- copy a menu command to a display buffer ---- */
  373. int CopyCommand(unsigned char *dest, unsigned char *src,
  374.                                         int skipcolor, int bg)
  375. {
  376.     unsigned char *d = dest;
  377.     while (*src && *src != '\n')    {
  378.         if (*src == SHORTCUTCHAR)    {
  379.             src++;
  380.             if (!skipcolor)    {
  381.                 *dest++ = CHANGECOLOR;
  382.                 *dest++ = cfg.clr[POPDOWNMENU]
  383.                             [HILITE_COLOR] [BG] | 0x80;
  384.                 *dest++ = bg | 0x80;
  385.                 *dest++ = *src++;
  386.                 *dest++ = RESETCOLOR;
  387.             }
  388.         }
  389.         else
  390.             *dest++ = *src++;
  391.     }
  392.     return (int) (dest - d);
  393. }
  394.  
  395. 
  396.