/* ------------- popdown.c ----------- */ #include #include #include #include #include "dflat.h" static int SelectionWidth(struct PopDown *); extern char *Clipboard; static MENU *mnu; int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2) { int wd, rtn, i; struct PopDown *pd1; char sep[80], *cp = sep; char sel[80]; static struct PopDown *ActivePopDown = NULL; switch (msg) { case CREATE_WINDOW: ClearAttribute(wnd, TITLEBAR | VSCROLLBAR | MOVEABLE | SIZEABLE | HSCROLLBAR); rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE); SendMessage(wnd, CAPTURE_MOUSE, 0, 0); SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0); SendMessage(NULLWND, SAVE_CURSOR, 0, 0); SendMessage(NULLWND, HIDE_CURSOR, 0, 0); return rtn; case SETFOCUS: return FALSE; case BUILD_SELECTIONS: mnu = (void *) p1; ActivePopDown = pd1 = mnu->Selections; wd = MenuWidth(ActivePopDown)-2; while (wd--) *cp++ = LINE; *cp = '\0'; while (pd1->SelectionTitle != NULL) { if (*pd1->SelectionTitle == LINE) SendMessage(wnd, ADDTEXT, LPARAM(sep), 0); else { memset(sel, '\0', sizeof sel); if (pd1->Attrib & INACTIVE) { strcpy(sel, " "); *sel = CHANGECOLOR; *(sel+1) = cfg.clr.InactiveSelFG | 0x80; *(sel+2) = cfg.clr.PopDownBG | 0x80; } strcat(sel, " "); CopyCommand(sel+strlen(sel), pd1->SelectionTitle, pd1->Attrib & INACTIVE, cfg.clr.PopDownBG); if (pd1->Attrib & CHECKED) *sel = CHECKMARK; 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, " "); strcat(sel, "["); strcat(sel, keys[i].keylabel); strcat(sel, "]"); break; } } strcat(sel, " "); sel[strlen(sel)-1] = RESETCOLOR; SendMessage(wnd, ADDTEXT, LPARAM(sel), 0); } pd1++; PostMessage(wnd, LB_SETSELECTION, mnu->Selection, 0); } break; case LEFT_BUTTON: if (SendMessage(wnd, INSIDE_WINDOW, p1, p2)) break; /* --- note: fall through here --- */ case DOUBLE_CLICK: if (p2 == GetTop(GetParent(wnd))) PostMessage(GetParent(wnd), msg, p1, p2); SendMessage(wnd, CLOSE_WINDOW, 0, 0); return FALSE; case BORDER: rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE); 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; case LB_SELECTION: rtn = BaseWndProc(POPDOWNMENU, wnd, msg, p1, FALSE); if (ActivePopDown != NULL) { mnu->Selection = (int)p1; if (p2 && GetParent(wnd)) { int *attr = &(ActivePopDown+(int)p1)->Attrib; if (*attr & INACTIVE) beep(); else if (*attr & TOGGLE) { char *tl = TextLine(wnd, (int)p1); *attr ^= CHECKED; if (*attr & CHECKED) *tl = CHECKMARK; else *tl = ' '; SendMessage(wnd, PAINT, 0, 0); } else { PostMessage(GetParent(wnd), COMMAND, (ActivePopDown+(int)p1)->ActionId, p1); SendMessage(wnd, CLOSE_WINDOW, 0, 0); } } } return rtn; case KEYBOARD: if (ActivePopDown != NULL) { int c = tolower((int)p1); int sel = 0; struct PopDown *pd = ActivePopDown; while (pd->SelectionTitle != NULL) { char *cp = strchr(pd->SelectionTitle, SHORTCUTCHAR); if (cp && tolower(*(cp+1)) == c || pd->Accelerator == (int) p1) { PostMessage(wnd, LB_SELECTION, sel, TRUE); return TRUE; } pd++, sel++; } } if (p1 == ESC) { SendMessage(wnd, CLOSE_WINDOW, 0, 0); return TRUE; } switch ((int)p1) { case FWD: case BS: if (GetClass(GetParent(wnd)) == MENUBAR) { PostMessage(GetParent(wnd), KEYBOARD, p1, p2); return TRUE; } break; case UP: if (wnd->selection == 0) { if (wnd->wlines == ClientHeight(wnd)) { PostMessage(wnd, LB_SELECTION, wnd->wlines-1, FALSE); return TRUE; } } return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2); case DN: if (wnd->selection == wnd->wlines-1) { if (wnd->wlines == ClientHeight(wnd)) { PostMessage(wnd, LB_SELECTION, 0, FALSE); return TRUE; } } return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2); case HOME: case END: case '\r': return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2); } return FALSE; case CLOSE_WINDOW: SendMessage(wnd, RELEASE_MOUSE, 0, 0); SendMessage(wnd, RELEASE_KEYBOARD, 0, 0); SendMessage(GetParent(wnd), CLOSE_POPDOWN, 0, 0); ActivePopDown = NULL; mnu = NULL; SendMessage(NULLWND, RESTORE_CURSOR, 0, 0); break; 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; } } 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(char *dest, char *src, int skipcolor, int bg) { char *d = dest; while (*src && *src != '\n') { if (*src == SHORTCUTCHAR) { src++; if (!skipcolor) { *dest++ = CHANGECOLOR; *dest++ = cfg.clr.ShortCutFG | 0x80; *dest++ = bg | 0x80; *dest++ = *src++; *dest++ = RESETCOLOR; } } else *dest++ = *src++; } return (int) (dest - d); }