/* ------------- popdown.c ----------- */ #include "dflat.h" static int SelectionWidth(struct PopDown *); static int py = -1; static int CreateWindowMsg(WINDOW wnd) { int rtn; ClearAttribute(wnd, HASTITLEBAR | VSCROLLBAR | MOVEABLE | SIZEABLE | HSCROLLBAR); rtn = BaseWndProc(POPDOWNMENU, wnd, CREATE_WINDOW, 0, 0); SendMessage(wnd, CAPTURE_MOUSE, 0, 0); SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0); SendMessage(NULL, SAVE_CURSOR, 0, 0); SendMessage(NULL, HIDE_CURSOR, 0, 0); return rtn; } static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2) { int my = (int) p2 - GetTop(wnd); if (InsideRect(p1, p2, ClientRect(wnd))) { if (my != py) { SendMessage(wnd, LB_SELECTION, (PARAM) wnd->wtop+my-1, TRUE); py = my; } } else if ((int)p2 == GetTop(GetParent(wnd))) if (GetClass(GetParent(wnd)) == MENUBAR) PostMessage(GetParent(wnd), LEFT_BUTTON, p1, p2); } static int ButtonReleasedMsg(WINDOW wnd, PARAM p1, PARAM p2) { py = -1; if (InsideRect((int)p1, (int)p2, ClientRect(wnd))) { int sel = (int)p2 - GetClientTop(wnd); if (*TextLine(wnd, sel) != LINE) SendMessage(wnd, LB_CHOOSE, wnd->selection, 0); } else { WINDOW pwnd = GetParent(wnd); if (GetClass(pwnd) == MENUBAR && (int)p2 == GetTop(pwnd)) return FALSE; if ((int)p1 == GetLeft(pwnd)+2) return FALSE; SendMessage(wnd, CLOSE_WINDOW, TRUE, 0); return TRUE; } return FALSE; } static void PaintMsg(WINDOW wnd) { int wd; unsigned char sep[80], *cp = sep; unsigned char sel[80]; struct PopDown *ActivePopDown; struct PopDown *pd1; ActivePopDown = pd1 = wnd->mnu->Selections; wd = MenuWidth(ActivePopDown)-2; while (wd--) *cp++ = LINE; *cp = '\0'; SendMessage(wnd, CLEARTEXT, 0, 0); wnd->selection = wnd->mnu->Selection; while (pd1->SelectionTitle != NULL) { if (*pd1->SelectionTitle == LINE) SendMessage(wnd, ADDTEXT, (PARAM) sep, 0); else { int len; memset(sel, '\0', sizeof sel); if (pd1->Attrib & INACTIVE) sprintf(sel, "%c%c%c", CHANGECOLOR, wnd->WindowColors [HILITE_COLOR] [FG] | 0x80, wnd->WindowColors [STD_COLOR] [BG] | 0x80); strcat(sel, " "); if (pd1->Attrib & CHECKED) sel[strlen(sel)-1] = CHECKMARK; len = CopyCommand(sel+strlen(sel), pd1->SelectionTitle, pd1->Attrib & INACTIVE, wnd->WindowColors [STD_COLOR] [BG]); if (pd1->Accelerator) { int i; int wd1 = 2+SelectionWidth(ActivePopDown) - strlen(pd1->SelectionTitle); for (i = 0; keys[i].keylabel; i++) { if (keys[i].keycode == pd1->Accelerator) { while (wd1--) strcat(sel, " "); sprintf(sel+strlen(sel), "[%s]", keys[i].keylabel); break; } } } if (pd1->Attrib & CASCADED) { if (!pd1->Accelerator) { wd = MenuWidth(ActivePopDown)-len+1; while (wd--) strcat(sel, " "); } sel[strlen(sel)-1] = CASCADEPOINTER; } else strcat(sel, " "); strcat(sel, " "); sel[strlen(sel)-1] = RESETCOLOR; SendMessage(wnd, ADDTEXT, (PARAM) sel, 0); } pd1++; } } static int BorderMsg(WINDOW wnd) { int i, rtn = TRUE; WINDOW currFocus; if (wnd->mnu != NULL) { currFocus = inFocus; inFocus = NULL; rtn = BaseWndProc(POPDOWNMENU, wnd, BORDER, 0, 0); inFocus = currFocus; for (i = 0; i < ClientHeight(wnd); i++) { if (*TextLine(wnd, i) == LINE) { wputch(wnd, LEDGE, 0, i+1); wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1); } } } return rtn; } static void LBChooseMsg(WINDOW wnd, PARAM p1) { struct PopDown *ActivePopDown = wnd->mnu->Selections; if (ActivePopDown != NULL) { int *attr = &(ActivePopDown+(int)p1)->Attrib; wnd->mnu->Selection = (int)p1; if (!(*attr & INACTIVE)) { if (*attr & TOGGLE) *attr ^= CHECKED; PostMessage(GetParent(wnd), COMMAND, (ActivePopDown+(int)p1)->ActionId, p1); } else beep(); } } static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2) { struct PopDown *ActivePopDown = wnd->mnu->Selections; if (wnd->mnu != NULL) { if (ActivePopDown != NULL) { int c = (int)p1; int sel = 0; int a; struct PopDown *pd = ActivePopDown; if ((c & OFFSET) == 0) c = tolower(c); a = AltConvert(c); while (pd->SelectionTitle != NULL) { char *cp = strchr(pd->SelectionTitle, SHORTCUTCHAR); int sc = tolower(*(cp+1)); if ((cp && sc == c) || (a && sc == a) || pd->Accelerator == c) { PostMessage(wnd, LB_SELECTION, sel, 0); PostMessage(wnd, LB_CHOOSE, sel, TRUE); return TRUE; } pd++, sel++; } } } switch ((int)p1) { case F1: if (ActivePopDown == NULL) SendMessage(GetParent(wnd), KEYBOARD, p1, p2); else DisplayHelp(wnd, (ActivePopDown+wnd->selection)->help); return TRUE; case ESC: SendMessage(wnd, CLOSE_WINDOW, TRUE, 0); return TRUE; case FWD: case BS: if (GetClass(GetParent(wnd)) == MENUBAR) PostMessage(GetParent(wnd), KEYBOARD, p1, p2); return TRUE; case UP: if (wnd->selection == 0) { if (wnd->wlines == ClientHeight(wnd)) { PostMessage(wnd, LB_SELECTION, wnd->wlines-1, FALSE); return TRUE; } } break; case DN: if (wnd->selection == wnd->wlines-1) { if (wnd->wlines == ClientHeight(wnd)) { PostMessage(wnd, LB_SELECTION, 0, FALSE); return TRUE; } } break; case HOME: case END: case '\r': break; default: return TRUE; } return FALSE; } static int CloseWindowMsg(WINDOW wnd, PARAM p1, PARAM p2) { int rtn; WINDOW pwnd = GetParent(wnd); SendMessage(wnd, RELEASE_MOUSE, 0, 0); SendMessage(wnd, RELEASE_KEYBOARD, 0, 0); SendMessage(NULL, RESTORE_CURSOR, 0, 0); rtn = BaseWndProc(POPDOWNMENU, wnd, CLOSE_WINDOW, p1, p2); SendMessage(pwnd, CLOSE_POPDOWN, p1, 0); return rtn; } int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2) { switch (msg) { case CREATE_WINDOW: return CreateWindowMsg(wnd); case LEFT_BUTTON: LeftButtonMsg(wnd, p1, p2); return FALSE; case DOUBLE_CLICK: return TRUE; case LB_SELECTION: if (*TextLine(wnd, (int)p1) == LINE) return TRUE; wnd->mnu->Selection = (int)p1; break; case BUTTON_RELEASED: if (ButtonReleasedMsg(wnd, p1, p2)) return TRUE; break; case BUILD_SELECTIONS: wnd->mnu = (void *) p1; wnd->selection = wnd->mnu->Selection; break; case PAINT: if (wnd->mnu == NULL) return TRUE; PaintMsg(wnd); break; case BORDER: return BorderMsg(wnd); case LB_CHOOSE: LBChooseMsg(wnd, p1); return TRUE; case KEYBOARD: if (KeyboardMsg(wnd, p1, p2)) return TRUE; break; case CLOSE_WINDOW: return CloseWindowMsg(wnd, p1, p2); default: break; } return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2); } int MenuHeight(struct PopDown *pd) { int ht = 0; while (pd[ht].SelectionTitle != NULL) ht++; return ht+2; } int MenuWidth(struct PopDown *pd) { int wd = 0, i; int len = 0; wd = SelectionWidth(pd); while (pd->SelectionTitle != NULL) { if (pd->Accelerator) { for (i = 0; keys[i].keylabel; i++) if (keys[i].keycode == pd->Accelerator) { len = max(len, 2+strlen(keys[i].keylabel)); break; } } if (pd->Attrib & CASCADED) len = max(len, 2); pd++; } return wd+5+len; } static int SelectionWidth(struct PopDown *pd) { int wd = 0; while (pd->SelectionTitle != NULL) { int len = strlen(pd->SelectionTitle)-1; wd = max(wd, len); pd++; } return wd; } int CopyCommand(unsigned char *dest, unsigned char *src, int skipcolor, int bg) { unsigned char *d = dest; while (*src && *src != '\n') { if (*src == SHORTCUTCHAR) { src++; if (!skipcolor) { *dest++ = CHANGECOLOR; *dest++ = cfg.clr[POPDOWNMENU] [HILITE_COLOR] [BG] | 0x80; *dest++ = bg | 0x80; *dest++ = *src++; *dest++ = RESETCOLOR; } } else *dest++ = *src++; } return (int) (dest - d); }