--- rxvt-unicode/src/menubar.C 2004/02/13 12:16:21 1.8 +++ rxvt-unicode/src/menubar.C 2004/03/03 04:07:52 1.12 @@ -23,6 +23,10 @@ *----------------------------------------------------------------------*/ #include "../config.h" /* NECESSARY */ + +#include +#include + #include "rxvt.h" /* NECESSARY */ #ifdef MENUBAR #include "version.h" @@ -46,6 +50,30 @@ /*}}} */ +static void +draw_string (rxvt_drawable &d, GC gc, rxvt_fontset *fs, int x, int y, char *str, int len) +{ + mbstate mbs; + + while (len) + { + wchar_t w; + int l = mbrtowc (&w, str, len, mbs); + + if (l <= 0) + break; + + len -= l; + str += l; + + rxvt_font *font = (*fs)[fs->find_font (w)]; + text_t ch = w; + font->draw (d, x, y, &ch, 1, Color_bg, Color_scroll); + + x += font->width * wcwidth (w); + } +} + /* * find an item called NAME in MENU */ @@ -330,7 +358,7 @@ if (!parse[i].len) continue; - str = rxvt_malloc (parse[i].len + xtra_len + 1); + str = (unsigned char *) rxvt_malloc (parse[i].len + xtra_len + 1); len = 0; if (beg.len) @@ -408,7 +436,7 @@ item->name2 = NULL; len = STRLEN (name); - item->name = rxvt_malloc (len + 1); + item->name = (char *)rxvt_malloc (len + 1); STRCPY (item->name, name); if (name[0] == '.' && name[1] != '.') len = 0; /* hidden menu name */ @@ -436,7 +464,7 @@ item->name2 = NULL; else { - item->name2 = rxvt_malloc (len + 1); + item->name2 = (char *)rxvt_malloc (len + 1); STRCPY (item->name2, name2); } item->len2 = len; @@ -451,7 +479,7 @@ } if (len) { - unsigned char *str = rxvt_malloc (len + 1); + unsigned char *str = (unsigned char *)rxvt_malloc (len + 1); STRCPY (str, action); @@ -493,16 +521,19 @@ if (*p == '/') path = p; } + if (path[0] == '/') { path++; *menu = NULL; } + while ((p = STRCHR (path, '/')) != NULL) { p[0] = '\0'; if (path[0] == '\0') return NULL; + if (!STRCMP (path, DOT)) { /* nothing to do */ @@ -525,6 +556,7 @@ path = (p + 1); } } + if (!STRCMP (path, DOTS)) { path += STRLEN (DOTS); @@ -532,14 +564,13 @@ *menu = (*menu)->parent; return path; } + /* find this menu */ if (*menu == NULL) { for (m = CurrentBar->tail; m != NULL; m = m->prev) - { - if (!STRCMP (path, m->name)) - break; - } + if (!STRCMP (path, m->name)) + break; } else { @@ -554,11 +585,13 @@ } } } + if (m != NULL) { *menu = m; path += STRLEN (path); } + return path; } @@ -570,7 +603,6 @@ { menu_t *parent = NULL, *prev, *next; menuitem_t *item; - bar_t *CurrentBar = CurrentBar; #ifdef DEBUG_STRICT assert (CurrentBar != NULL); @@ -620,14 +652,13 @@ item = menu->tail; while (item != NULL) { - menuitem_t *p = item->prev; + menuitem_t *p = item->prev; menuitem_free (menu, item); item = p; } - if (menu->name != NULL) - free (menu->name); + free (menu->name); free (menu); return parent; @@ -636,8 +667,7 @@ menu_t * rxvt_term::menu_add (menu_t *parent, char *path) { - menu_t *menu; - bar_t *CurrentBar = CurrentBar; + menu_t *menu; #ifdef DEBUG_STRICT assert (CurrentBar != NULL); @@ -645,7 +675,7 @@ if (STRCHR (path, '/') != NULL) { - char *p; + char *p; if (path[0] == '/') { @@ -675,7 +705,7 @@ menu->width = 0; menu->parent = parent; menu->len = STRLEN (path); - menu->name = rxvt_malloc ((menu->len + 1)); + menu->name = (char *)rxvt_malloc ((menu->len + 1)); STRCPY (menu->name, path); /* initialize head/tail */ @@ -683,6 +713,7 @@ menu->prev = menu->next = NULL; menu->win = None; + menu->drawable = 0; menu->x = menu->y = menu->w = menu->h = 0; menu->item = NULL; @@ -781,8 +812,7 @@ x -= SHADOW + (3 * w / 2); y += SHADOW * 3; - rxvt_Draw_Triangle (display->display, ActiveMenu->win, top, bot, x, y, w, - 'r'); + rxvt_Draw_Triangle (display->display, ActiveMenu->win, top, bot, x, y, w, 'r'); } void @@ -824,6 +854,7 @@ fprintf (stderr, "Top Level menu\n"); return; } + fprintf (stderr, "menu %s ", menu->name); if (menu->parent != NULL) { @@ -837,12 +868,14 @@ break; } } + if (item == NULL) { fprintf (stderr, "is an orphan!\n"); return; } } + fprintf (stderr, "\n"); rxvt_print_menu_ancestors (menu->parent); } @@ -895,9 +928,8 @@ void rxvt_term::menu_show () { - int x, y, xright; - menu_t *ActiveMenu = ActiveMenu; - menuitem_t *item; + int x, y, xright; + menuitem_t *item; if (ActiveMenu == NULL) return; @@ -922,6 +954,7 @@ : HEIGHT_TEXT + 2 * SHADOW; ActiveMenu->h = h + 2 * SHADOW; } + if (ActiveMenu->win == None) { ActiveMenu->win = XCreateSimpleWindow (display->display, TermWin.vt, @@ -930,8 +963,10 @@ 0, PixColors[Color_fg], PixColors[Color_scroll]); + ActiveMenu->drawable = new rxvt_drawable (display, ActiveMenu->win); XMapWindow (display->display, ActiveMenu->win); } + rxvt_Draw_Shadow (display->display, ActiveMenu->win, topShadowGC, botShadowGC, 0, 0, ActiveMenu->w, ActiveMenu->h); @@ -943,9 +978,9 @@ for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { - const int xoff = (SHADOW + Width2Pixel (HSPACE) / 2); - register int h; - GC gc = menubarGC; + const int xoff = (SHADOW + Width2Pixel (HSPACE) / 2); + register int h; + GC gc = menubarGC; if (isSeparator (item->name)) { @@ -961,9 +996,7 @@ int len = item->len; if (item->entry.type == MenuLabel) - { - gc = botShadowGC; - } + gc = botShadowGC; else if (item->entry.type == MenuSubMenu) { int x1, y1; @@ -1005,40 +1038,16 @@ name = NULL; if (len && name) - { -#ifdef USE_XIM - if (TermWin.fontset) - XmbDrawString (display->display, - ActiveMenu->win, TermWin.fontset, - gc, xoff, - 2 * SHADOW + y + TermWin.font->ascent + 1, - name, len); - else -#endif - XDrawString (display->display, ActiveMenu->win, gc, xoff, - 2 * SHADOW + y + TermWin.font->ascent + 1, - name, len); - } + draw_string (*ActiveMenu->drawable, gc, TermWin.fontset, + xoff, 2 * SHADOW + y, name, len); len = item->len2; name = item->name2; + if (len && name) - { -#ifdef USE_XIM - if (TermWin.fontset) - XmbDrawString (display->display, - ActiveMenu->win, TermWin.fontset, - gc, - ActiveMenu->w - (xoff + Width2Pixel (xright)), - 2 * SHADOW + y + TermWin.font->ascent + 1, - name, len); - else -#endif - XDrawString (display->display, ActiveMenu->win, gc, - ActiveMenu->w - (xoff + Width2Pixel (xright)), - 2 * SHADOW + y + TermWin.font->ascent + 1, - name, len); - } + draw_string (*ActiveMenu->drawable, gc, TermWin.fontset, + ActiveMenu->w - (xoff + Width2Pixel (xright)), 2 * SHADOW + y, name, len); + h = HEIGHT_TEXT + 2 * SHADOW; } y += h; @@ -1046,12 +1055,12 @@ } void -rxvt_term::menu_display (void (*update) (rxvt_t *)) +rxvt_term::menu_display (void (rxvt_term::*update) ()) { - menu_t *ActiveMenu = ActiveMenu; - if (ActiveMenu == NULL) return; + + delete ActiveMenu->drawable; if (ActiveMenu->win != None) XDestroyWindow (display->display, ActiveMenu->win); ActiveMenu->win = None; @@ -1059,20 +1068,21 @@ if (ActiveMenu->parent == NULL) drawbox_menubar (ActiveMenu->x, ActiveMenu->len, +1); + ActiveMenu = ActiveMenu->parent; - update (r); + (this->*update) (); } void rxvt_term::menu_hide_all () { - menu_display (rxvt_menu_hide_all); + menu_display (&rxvt_term::menu_hide_all); } void rxvt_term::menu_hide () { - menu_display (rxvt_menu_show); + menu_display (&rxvt_term::menu_show); } void @@ -1080,7 +1090,7 @@ { if (menu != NULL) { - menuitem_t *item = menu->tail; + menuitem_t *item = menu->tail; while (item != NULL) { @@ -1097,15 +1107,13 @@ void rxvt_term::menubar_clear () { - bar_t *CurrentBar = CurrentBar; - if (CurrentBar != NULL) { - menu_t *menu = CurrentBar->tail; + menu_t *menu = CurrentBar->tail; while (menu != NULL) { - menu_t *prev = menu->prev; + menu_t *prev = menu->prev; menu_delete (menu); menu = prev; @@ -1117,8 +1125,10 @@ free (CurrentBar->title); CurrentBar->title = NULL; } + menuarrow_free (0); /* remove all arrow functions */ } + ActiveMenu = NULL; } @@ -1127,7 +1137,7 @@ bar_t * rxvt_term::menubar_find (const char *name) { - bar_t *bar = CurrentBar; + bar_t *bar = CurrentBar; #ifdef DEBUG_MENUBAR_STACKING fprintf (stderr, "looking for [menu:%s] ...", name ? name : " (nil)"); @@ -1161,8 +1171,8 @@ int rxvt_term::menubar_push (const char *name) { - int ret = 1; - bar_t *bar; + int ret = 1; + bar_t *bar; if (CurrentBar == NULL) { @@ -1220,6 +1230,7 @@ CurrentBar = bar; } + menubar_clear (); } } @@ -1274,8 +1285,8 @@ void rxvt_action_decode (FILE *fp, action_t *act) { - unsigned char *str; - short len; + unsigned char *str; + short len; if (act == NULL || (len = act->len) == 0 || (str = act->str) == NULL) return; @@ -1308,6 +1319,7 @@ break; } } + /* * control character form is preferred, since backslash-escaping * can be really ugly looking when the backslashes themselves also @@ -1343,8 +1355,10 @@ fprintf (fp, "%c", ch); break; } + len--; } + fprintf (fp, "\n"); } @@ -1396,7 +1410,7 @@ time (&t); fprintf (fp, - "# " APL_SUBCLASS " (%s) Pid: %u\n# Date: %s\n\n", + "# " RESCLASS " (%s) Pid: %u\n# Date: %s\n\n", rs[Rs_name], (unsigned int)getpid (), ctime (&t)); /* dump in reverse order */ @@ -1460,6 +1474,7 @@ file = (char *)rxvt_File_find (filename, ".menu", rs[Rs_path]); if (file == NULL) return; + fp = fopen (file, "rb"); free (file); if (fp == NULL) @@ -1575,10 +1590,10 @@ void rxvt_term::menubar_dispatch (char *str) { - int n, cmd; - char *path, *name, *name2; + int n, cmd; + char *path, *name, *name2; - if (menubar_visible (r) && ActiveMenu != NULL) + if (menubar_visible () && ActiveMenu != NULL) menubar_expose (); else ActiveMenu = NULL; @@ -1676,8 +1691,7 @@ { if (*str) { - name = rxvt_realloc (CurrentBar->title, - STRLEN (str) + 1); + name = (char *)rxvt_realloc (CurrentBar->title, STRLEN (str) + 1); if (name != NULL) { STRCPY (name, str); @@ -1743,7 +1757,7 @@ /* enough space to hold the results */ char buffer[32]; - sprintf (buffer, "/tmp/" APL_SUBCLASS "-%u", + sprintf (buffer, "/tmp/" RESCLASS "-%u", (unsigned int)getpid ()); if ((fp = fopen (buffer, "wb")) != NULL) @@ -1998,9 +2012,9 @@ for (i = 0; i < NARROWS; i++) { - const int w = Width2Pixel (1); - const int y = (menuBar_TotalHeight () - w) / 2; - int x = Arrows_x + (5 * Width2Pixel (i)) / 4; + const int w = Width2Pixel (1); + const int y = (menuBar_TotalHeight () - w) / 2; + int x = Arrows_x + (5 * Width2Pixel (i)) / 4; if (!name || name == Arrows[i].name) rxvt_Draw_Triangle (display->display, menuBar.win, top, bot, x, y, w, @@ -2012,10 +2026,10 @@ void rxvt_term::menubar_expose () { - menu_t *menu; - int x; + menu_t *menu; + int x; - if (!menubar_visible (r) || menuBar.win == 0) + if (!menubar_visible () || menuBar.win == 0) return; if (menubarGC == None) @@ -2023,17 +2037,13 @@ /* Create the graphics context */ XGCValues gcvalue; - gcvalue.font = TermWin.font->fid; - gcvalue.foreground = (XDEPTH <= 2 ? PixColors[Color_fg] : PixColors[Color_Black]); menubarGC = XCreateGC (display->display, menuBar.win, - GCForeground | GCFont, &gcvalue); + GCForeground, &gcvalue); } /* make sure the font is correct */ - XSetFont (display->display, menubarGC, TermWin.font->fid); - XSetFont (display->display, botShadowGC, TermWin.font->fid); XClearWindow (display->display, menuBar.win); menu_hide_all (); @@ -2055,18 +2065,9 @@ len = (TermWin.ncol - (menu->x + HSPACE)); drawbox_menubar (menu->x, len, +1); -#ifdef USE_XIM - if (TermWin.fontset) - XmbDrawString (display->display, - menuBar.win, TermWin.fontset, - menubarGC, - (Width2Pixel (menu->x) + Width2Pixel (HSPACE) / 2), - menuBar_height () - SHADOW, menu->name, len); - else -#endif - XDrawString (display->display, menuBar.win, menubarGC, - (Width2Pixel (menu->x) + Width2Pixel (HSPACE) / 2), - menuBar_height () - SHADOW, menu->name, len); + draw_string (*menuBar.drawable, menubarGC, TermWin.fontset, + (Width2Pixel (menu->x) + Width2Pixel (HSPACE) / 2), + SHADOW, menu->name, len); if (x >= TermWin.ncol) break; @@ -2127,20 +2128,9 @@ ncol -= (x + len + HSPACE); if (len > 0 && ncol >= 0) - { -#ifdef USE_XIM - if (TermWin.fontset) - XmbDrawString (display->display, - menuBar.win, TermWin.fontset, - menubarGC, - Width2Pixel (x) + Width2Pixel (ncol + HSPACE) / 2, - menuBar_height () - SHADOW, title, len); - else -#endif - XDrawString (display->display, menuBar.win, menubarGC, - Width2Pixel (x) + Width2Pixel (ncol + HSPACE) / 2, - menuBar_height () - SHADOW, title, len); - } + draw_string (*menuBar.drawable, menubarGC, TermWin.fontset, + Width2Pixel (x) + Width2Pixel (ncol + HSPACE) / 2, + SHADOW, title, len); } } @@ -2149,7 +2139,7 @@ { int change = 0; - if (map && !menubar_visible (r)) + if (map && !menubar_visible ()) { menuBar.state = 1; if (menuBar.win == 0) @@ -2157,7 +2147,7 @@ XMapWindow (display->display, menuBar.win); change = 1; } - else if (!map && menubar_visible (r)) + else if (!map && menubar_visible ()) { menubar_expose (); menuBar.state = 0; @@ -2171,49 +2161,52 @@ } int -rxvt_term::menu_select (XButtonEvent *ev) +rxvt_term::menu_select (XButtonEvent &ev) { - menuitem_t *thisitem, *item = NULL; - int this_y, y; - menu_t *ActiveMenu = ActiveMenu; - - Window unused_root, unused_child; - int unused_root_x, unused_root_y; - unsigned int unused_mask; + menuitem_t *thisitem, *item = NULL; + int this_y, y; + + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; if (ActiveMenu == NULL) return 0; XQueryPointer (display->display, ActiveMenu->win, - &unused_root, &unused_child, - &unused_root_x, &unused_root_y, - & (ev->x), & (ev->y), &unused_mask); + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &ev.x, &ev.y, &unused_mask); - if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0)) + if (ActiveMenu->parent != NULL && (ev.x < 0 || ev.y < 0)) { menu_hide (); return 1; } + /* determine the menu item corresponding to the Y index */ y = SHADOW; - if (ev->x >= 0 && ev->x <= (ActiveMenu->w - SHADOW)) + if (ev.x >= 0 && ev.x <= (ActiveMenu->w - SHADOW)) { for (item = ActiveMenu->head; item != NULL; item = item->next) { - int h = HEIGHT_TEXT + 2 * SHADOW; + int h = HEIGHT_TEXT + 2 * SHADOW; if (isSeparator (item->name)) h = HEIGHT_SEPARATOR; - else if (ev->y >= y && ev->y < (y + h)) + else if (ev.y >= y && ev.y < (y + h)) break; + y += h; } } - if (item == NULL && ev->type == ButtonRelease) + + if (item == NULL && ev.type == ButtonRelease) { menu_hide_all (); return 0; } + thisitem = item; this_y = y - SHADOW; @@ -2222,10 +2215,9 @@ { if (ActiveMenu->item != thisitem) { - for (y = 0, item = ActiveMenu->head; item != NULL; - item = item->next) + for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { - int h; + int h; if (isSeparator (item->name)) h = HEIGHT_SEPARATOR; @@ -2235,16 +2227,18 @@ drawbox_menuitem (y, 0); /* No Shadow */ if (item->entry.type == MenuSubMenu) drawtriangle (ActiveMenu->w, y, +1); + break; } else h = HEIGHT_TEXT + 2 * SHADOW; + y += h; } } else { - switch (ev->type) + switch (ev.type) { case ButtonRelease: switch (item->entry.type) @@ -2256,24 +2250,21 @@ case MenuAction: case MenuTerminalAction: - drawbox_menuitem (_y, -1); - { + drawbox_menuitem (this_y, -1); #ifdef HAVE_NANOSLEEP - struct timespec rqt; + struct timespec rqt; - rqt.tv_sec = 0; - rqt.tv_nsec = MENU_DELAY_USEC * 1000; - nanosleep (&rqt, NULL); + rqt.tv_sec = 0; + rqt.tv_nsec = MENU_DELAY_USEC * 1000; + nanosleep (&rqt, NULL); #else - /* use select for timing */ - struct timeval tv; + /* use select for timing */ + struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = MENU_DELAY_USEC; - select (0, NULL, NULL, NULL, &tv); + tv.tv_sec = 0; + tv.tv_usec = MENU_DELAY_USEC; + select (0, NULL, NULL, NULL, &tv); #endif - - } /* remove menu before sending keys to the application */ menu_hide_all (); #ifndef DEBUG_MENU @@ -2294,21 +2285,24 @@ return 0; } } + DoMenu: ActiveMenu->item = thisitem; y = this_y; - if (item != NULL) + + if (thisitem != NULL) { item = ActiveMenu->item; if (item->entry.type != MenuLabel) drawbox_menuitem (y, +1); + if (item->entry.type == MenuSubMenu) { - int x; + int x; drawtriangle (ActiveMenu->w, y, -1); - x = ev->x + (ActiveMenu->parent + x = ev.x + (ActiveMenu->parent ? ActiveMenu->x : Width2Pixel (ActiveMenu->x)); @@ -2324,37 +2318,37 @@ } void -rxvt_term::menubar_select (XButtonEvent *ev) +rxvt_term::menubar_select (XButtonEvent &ev) { - menu_t *menu = NULL; + menu_t *menu = NULL; /* determine the pulldown menu corresponding to the X index */ - if (ev->y >= 0 && ev->y <= menuBar_height () && CurrentBar != NULL) + if (ev.y >= 0 && ev.y <= menuBar_height () && CurrentBar != NULL) { for (menu = CurrentBar->head; menu != NULL; menu = menu->next) { - int x = Width2Pixel (menu->x); - int w = Width2Pixel (menu->len + HSPACE); + int x = Width2Pixel (menu->x); + int w = Width2Pixel (menu->len + HSPACE); - if ((ev->x >= x && ev->x < x + w)) + if ((ev.x >= x && ev.x < x + w)) break; } } - switch (ev->type) + switch (ev.type) { case ButtonRelease: menu_hide_all (); break; case ButtonPress: - if (menu == NULL && Arrows_x && ev->x >= Arrows_x) + if (menu == NULL && Arrows_x && ev.x >= Arrows_x) { int i; for (i = 0; i < NARROWS; i++) { - if (ev->x >= (Arrows_x + (Width2Pixel (4 * i + i)) / 4) - && ev->x < (Arrows_x + if (ev.x >= (Arrows_x + (Width2Pixel (4 * i + i)) / 4) + && ev.x < (Arrows_x + (Width2Pixel (4 * i + i + 4)) / 4)) { draw_Arrows (Arrows[i].name, -1); @@ -2394,10 +2388,7 @@ CurrentBar->arrows[i].str); } #else /* DEBUG_MENUARROWS */ - if (CurrentBar == NULL - || rxvt_action_dispatch (r, - & (CurrentBar->arrows[i])) - ) + if (CurrentBar == NULL || action_dispatch (&CurrentBar->arrows[i])) { if (Arrows[i].str != NULL && Arrows[i].str[0] != 0) tt_write ((Arrows[i].str + 1), @@ -2429,29 +2420,29 @@ * it would be nice to have `sticky' menus */ void -rxvt_term::menubar_control (XButtonEvent *ev) +rxvt_term::menubar_control (XButtonEvent &ev) { - switch (ev->type) + switch (ev.type) { case ButtonPress: - if (ev->button == Button1) + if (ev.button == Button1) menubar_select (ev); break; case ButtonRelease: - if (ev->button == Button1) + if (ev.button == Button1) menu_select (ev); break; case MotionNotify: while (XCheckTypedWindowEvent (display->display, TermWin.parent[0], - MotionNotify, (XEvent *) ev)) ; + MotionNotify, (XEvent *)&ev)) ; if (ActiveMenu) while (menu_select (ev)) ; else - ev->y = -1; - if (ev->y < 0) + ev.y = -1; + if (ev.y < 0) { Window unused_root, unused_child; int unused_root_x, unused_root_y; @@ -2460,7 +2451,7 @@ XQueryPointer (display->display, menuBar.win, &unused_root, &unused_child, &unused_root_x, &unused_root_y, - & (ev->x), & (ev->y), &unused_mask); + &ev.x, &ev.y, &unused_mask); menubar_select (ev); } break;