/* ---------------- menubar.c -------------- */ #include #include #include #include #include #include "dflat.h" static void reset_menubar(WINDOW); static void ClosePopDown(void); static int TestGlobalKeys(PARAM, PARAM); static char *menubar; static struct { int x1, x2; /* position in menu bar */ char sc; /* shortcut key value */ } menu[10]; static int mctr; MENU *ActiveMenu; int ActiveSelection = -1; static WINDOW mwnd = NULL; #define MSPACE 2 int MenuBarProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2) { int offset = 3, wd, offset1, i, j; int mx = (int) p1 - GetLeft(wnd); MENU *mnu; switch (msg) { case CREATE_WINDOW: reset_menubar(wnd); PostMessage(wnd, PAINT, 0, 0); break; case COMMAND: PostMessage(GetParent(wnd), msg, p1, p2); return FALSE; case SETFOCUS: if (p1) { if (!p2) return FALSE; else { /* --- accept the focus only if there are no others --- */ WINDOW wnd1 = Focus.FirstWindow; while (wnd1 != NULLWND) { if (wnd != wnd1 && GetParent(wnd) == GetParent(wnd1)) break; wnd1 = NextWindow(wnd1); } if (wnd1 != NULLWND) return FALSE; } } break; case BUILDMENU: reset_menubar(wnd); mctr = 0; ActiveMenu = (MENU *) p1; while (ActiveMenu->Title != NULL) { char *cp; menubar = realloc(menubar, strlen(menubar)+5); memmove(menubar + offset+4, menubar + offset, strlen(menubar)-offset+1); CopyCommand(menubar+offset, ActiveMenu->Title, FALSE, cfg.clr.MenuBarBG); menu[mctr].x1 = offset; offset += strlen(ActiveMenu->Title) + (3+MSPACE); menu[mctr].x2 = offset-MSPACE; cp = strchr(ActiveMenu->Title, SHORTCUTCHAR); if (cp) menu[mctr].sc = tolower(*(cp+1)); ActiveMenu++; mctr++; } ActiveMenu = (MENU *) p1; break; case PAINT: if (!isVisible(wnd)) break; SetStandardColor(wnd); ClearAttribute(wnd, NOCLIP); writefull(wnd, menubar, 0); AddAttribute(wnd, NOCLIP); if (ActiveSelection != -1) { char sel[80], *cp; offset = menu[ActiveSelection].x1; offset1 = menu[ActiveSelection].x2; menubar[offset1] = '\0'; SetReverseColor(wnd); memset(sel, '\0', sizeof sel); strcpy(sel, menubar+offset); cp = strchr(sel, CHANGECOLOR); if (cp != NULL) *(cp + 2) = background | 0x80; wputs(wnd, sel, offset-ActiveSelection*(MSPACE+2), 0); menubar[offset1] = ' '; } return FALSE; case KEYBOARD: if (mwnd == NULL) { /* ----- search for menu bar shortcut keys ---- */ for (i = 0; i < 26; i++) if ((char) p1 == altconvert[i]) break; if (i < 26) { for (j = 0; j < mctr; j++) { if (menu[j].sc == 'a' + i) { SendMessage(wnd, SELECTION, j, 0); return FALSE; } } } } /* -------- search for accelerator keys -------- */ mnu = ActiveMenu; while (mnu->Title != NULL) { struct PopDown *pd = mnu->Selections; if (mnu->PrepMenu) (*(mnu->PrepMenu))(GetParent(wnd), mnu); while (pd->SelectionTitle != NULL) { if (pd->Accelerator == (int) p1) { if (pd->Attrib & INACTIVE) beep(); else PostMessage(GetParent(wnd), COMMAND, pd->ActionId, 0); return TRUE; } pd++; } mnu++; } if (TestGlobalKeys(p1, p2)) return FALSE; if (mwnd == NULLWND) return FALSE; switch ((int)p1) { case FWD: ActiveSelection++; if (ActiveSelection == mctr) ActiveSelection = 0; SendMessage(wnd, SELECTION, ActiveSelection, 0); return FALSE; case BS: if (ActiveSelection == 0) ActiveSelection = mctr; --ActiveSelection; SendMessage(wnd, SELECTION, ActiveSelection, 0); return FALSE; default: break; } if (mwnd == (void *)-1) return FALSE; break; case LEFT_BUTTON: for (i = 0; i < mctr; i++) if (mx >= menu[i].x1-(MSPACE+2)*i && mx <= menu[i].x2-(MSPACE+2)*i-5) break; if (i < mctr) { if (i != ActiveSelection || mwnd == NULL) { SendMessage(wnd, SELECTION, i, 0); SendMessage(NULLWND, WAITMOUSE, 0, 0); } } break; case SELECTION: if (mwnd && mwnd != (void *)-1) SendMessage(mwnd, CLOSE_WINDOW, 0, 0); mwnd = NULL; ActiveSelection = (int) p1; offset = menu[ActiveSelection].x1 - (MSPACE+2) * ActiveSelection; mnu = ActiveMenu+ActiveSelection; if (mnu->PrepMenu != NULL) (*(mnu->PrepMenu))(GetParent(wnd), mnu); wd = MenuWidth(mnu->Selections); if (offset > WindowWidth(wnd)-wd) offset = WindowWidth(wnd)-wd; if (mnu->Selections[0].SelectionTitle != NULL) { mwnd = CreateWindow(POPDOWNMENU, NULL, GetLeft(wnd)+offset, GetTop(wnd)+1, MenuHeight(mnu->Selections), wd, NULL, wnd, NULL, 0); #ifdef INCLUDE_SHADOWS AddAttribute(mwnd, SHADOW); #endif SendMessage(mwnd, BUILD_SELECTIONS, LPARAM(mnu), 0); SendMessage(wnd, PAINT, 0, 0); SendMessage(mwnd, SHOW_WINDOW, 0, 0); } else mwnd = (void *)-1; SendMessage(wnd, PAINT, 0, 0); break; case BORDER: return TRUE; case INSIDE_WINDOW: return InsideRect(p1, p2, WindowRect(wnd)); case CLOSE_POPDOWN: ClosePopDown(); SendMessage(wnd, PAINT, 0, 0); break; case CLOSE_WINDOW: if (menubar != NULL) { free(menubar); menubar = NULL; } mctr = 0; ActiveSelection = -1; ActiveMenu = NULL; break; default: break; } return BaseWndProc(MENUBAR, wnd, msg, p1, p2); } static void reset_menubar(WINDOW wnd) { menubar = realloc(menubar, SCREENWIDTH+5); memset(menubar, ' ', SCREENWIDTH); *(menubar+SCREENWIDTH- (TestAttribute(GetParent(wnd), HASBORDER) ? 2 : 0)) = '\0'; } static void ClosePopDown(void) { ActiveSelection = -1; mwnd = NULLWND; } static int TestGlobalKeys(PARAM p1, PARAM p2) { switch ((int)p1) { case ALT_F6: if (GetClass(inFocus) != MENUBAR && GetClass(inFocus) != POPDOWNMENU) SetNextFocus(inFocus, FALSE); return TRUE; #ifdef INCLUDE_SYSTEM_MENUS case ALT_HYPHEN: if (GetClass(inFocus) == POPDOWNMENU) SendMessage(inFocus, CLOSE_WINDOW, 0, 0); if (GetClass(GetParent(inFocus)) == APPLICATION) BuildSystemMenu(GetParent(inFocus)); return TRUE; case ' ': if (p2 & ALTKEY) { if (GetClass(inFocus) == POPDOWNMENU) SendMessage(inFocus, CLOSE_WINDOW, 0, 0); if (GetClass(inFocus) != MENUBAR && TestAttribute(inFocus, TITLEBAR) && TestAttribute(inFocus, CONTROLBOX)) BuildSystemMenu(inFocus); return TRUE; } break; #endif case ALT_F4: if (GetClass(inFocus) != MENUBAR) PostMessage(inFocus, CLOSE_WINDOW, 0, 0); else PostMessage(GetParent(inFocus), CLOSE_WINDOW, 0, 0); return TRUE; default: break; } return FALSE; }