#include #ifdef _plan9_ #include #include #else #ifndef NO_MALLOC_H #include #endif #include #endif #include #include #include #include #include #include #include #include #include #include "uiint.h" #define HISTORYSIZE 10 static int historypos; static struct xshl_line *lines; static int helpwidth, helpheight, helpx, helpy; static struct uih_window *helpw; static int textheight; static char *ui_helppage[HISTORYSIZE]; static int ui_helppos[HISTORYSIZE]; int helpvisible; static struct xshl_item *presseditem; static struct xshl_item *selecteditem; static int pressedline; static int selectedline; #define SCROOLSIZE 10 #define XPOS(xp) (2 * BORDERWIDTH + (xp)) #define YPOS(yp) (2*BORDERWIDTH+ (yp)-ui_helppos[historypos]+10) #define SCROOLSTART (helpx+helpwidth-WBORDERS) #define WBORDERS (4*BORDERWIDTH+SCROOLSIZE) #define HBORDERS (xtextheight(uih->font)+8*BORDERHEIGHT) #define WIDTH (uih->image->width-WBORDERS) #define HEIGHT (uih->image->height-HBORDERS) static int pressedbutton = -1; static int selectedbutton = -1; #define NBUTTONS 3 CONST char *CONST names[] = { "OK", "Back", "Main" }; #define BUTTONSTART(i) (helpx+BORDERWIDTH+(helpwidth-2*BORDERWIDTH)/NBUTTONS*(i)) static void ui_build_help(char *name); static void ui_backhelp(void) { historypos--; if (historypos < 0) historypos = HISTORYSIZE - 1; ui_build_help(ui_helppage[historypos]); } static void do_button(int i) { switch (i) { case 0: ui_close_help(); break; case 1: ui_backhelp(); break; case 2: ui_help("main"); break; } } void ui_close_help(void) { if (helpw != NULL) { xshl_free(lines); helpvisible = 0; uih_removew(uih, helpw); uih->display = 1; helpw = NULL; } } static int getwidth(void *data, int flags, CONST char *text) { if (uih->image->flags & AAIMAGE) return (xtextwidth(uih->font, text)); return (xtextwidth(uih->font, text) - 1); } static void helpsize(struct uih_context *c, int *x, int *y, int *width, int *height, void *data) { *x = helpx; *y = helpy; *width = helpwidth; *height = helpheight; } static void drawhelp(struct uih_context *c, void *data) { int i = 0; int y; int percentx, percenty; struct xshl_item *curritem; uih_drawborder(uih, helpx + BORDERWIDTH, helpy + BORDERHEIGHT, helpwidth - WBORDERS + SCROOLSIZE, helpheight - HBORDERS, BORDER_PRESSED); if (ui_helppos[historypos] > textheight - helpheight / 2 + HBORDERS) ui_helppos[historypos] = textheight - helpheight / 2 + HBORDERS; if (ui_helppos[historypos] < 0) ui_helppos[historypos] = 0; /*draw scroolbar */ percentx = (helpheight - HBORDERS) * ui_helppos[historypos] / textheight; percenty = (helpheight - HBORDERS) * (ui_helppos[historypos] + helpheight - HBORDERS) / textheight; if (percentx < BORDERHEIGHT) percentx = BORDERHEIGHT; if (percenty < BORDERHEIGHT) percenty = BORDERHEIGHT; if (percentx > helpheight - HBORDERS - BORDERHEIGHT) percentx = helpheight - HBORDERS - BORDERHEIGHT; if (percenty > helpheight - HBORDERS - BORDERHEIGHT) percenty = helpheight - HBORDERS - BORDERHEIGHT; uih_drawborder(uih, SCROOLSTART, helpy + BORDERHEIGHT + percentx, SCROOLSIZE - 1, percenty - percentx, 0); for (i = 0; i < NBUTTONS; i++) { ui_drawbutton(names[i], pressedbutton == i, selectedbutton == i, BUTTONSTART(i) + BORDERWIDTH, BUTTONSTART(i + 1) - BORDERWIDTH, helpy + helpheight - BUTTONHEIGHT - BORDERHEIGHT); } i = 0; while (YPOS(lines[i].y) < 2 * BORDERWIDTH) { i++; if (lines[i].y < 0) return; } while ((y = YPOS(lines[i].y)) < helpheight - HBORDERS - xtextheight(uih->font) && lines[i].y >= 0) { curritem = lines[i].first; while (curritem != NULL) { unsigned int bgcolor = BGCOLOR(uih); unsigned int fgcolor = /*FGCOLOR (uih) */ LIGHTGRAYCOLOR2(uih); int flags = 0; int x = XPOS(curritem->x); if (curritem->c.flags & (XSHL_BIG | XSHL_RED)) fgcolor = SELCOLOR(uih); else if (curritem->c.flags & (XSHL_EMPH | XSHL_MONOSPACE)) fgcolor = uih->image-> flags & AAIMAGE ? SELCOLOR(uih) : FGCOLOR(uih); else if (curritem->c.flags & (XSHL_BLACK)) bgcolor = fgcolor = BGCOLOR(uih), flags = TEXT_PRESSED; else bgcolor = fgcolor, flags |= TEXT_PRESSED; if (uih->palette->type & BITMAPS) { flags = TEXT_PRESSED; fgcolor = BGCOLOR(uih); } if (curritem->c.linktext != NULL) { if (uih->palette->type & BITMAPS) { if (curritem == presseditem || curritem == selecteditem) fgcolor = FGCOLOR(uih), xrectangle(uih->image, x + helpx, y + helpy, curritem->width, xtextheight(uih-> font), BGCOLOR(uih)); else xhline(uih->image, x + helpx, y + helpy + xtextheight(uih->font) - 1, curritem->width, BGCOLOR(uih)); } else { if (uih->image->flags & AAIMAGE) fgcolor = curritem == presseditem || curritem == selecteditem ? SELCOLOR(uih) : BGCOLOR(uih); else { int i; i = strlen(curritem->c.linktext); if (i > 3 && !strcmp(".xaf", curritem->c.linktext + i - 4)) xhline(uih->image, x + helpx, y + helpy + xtextheight(uih->font) - 1, curritem->width, curritem == presseditem || curritem == selecteditem ? SELCOLOR(uih) : SELCOLOR(uih)); else xhline(uih->image, x + helpx, y + helpy + xtextheight(uih->font) - 1, curritem->width, curritem == presseditem || curritem == selecteditem ? SELCOLOR(uih) : LIGHTGRAYCOLOR2(uih)); xhline(uih->image, x + helpx + 1, y + helpy + xtextheight(uih->font) - 0, curritem->width, BGCOLOR(uih)); } flags = 0; bgcolor = BGCOLOR(uih); if (fgcolor == LIGHTGRAYCOLOR2(uih)) fgcolor = FGCOLOR(uih); if (curritem == presseditem || curritem == selecteditem) fgcolor = SELCOLOR(uih); } } xprint(uih->image, uih->font, x + helpx, y + helpy, curritem->text, fgcolor, bgcolor, flags); curritem = curritem->next; } i++; } } int ui_helpkeys(int key) { int i; if (helpw == NULL) return 0; switch (key) { case 'h': ui_close_help(); ui_menu("tutor"); return 1; case 'm': ui_help("main"); return 1; case UIKEY_DOWN: case 'j': ui_helppos[historypos] += 8, uih->display = 1; presseditem = NULL; selecteditem = NULL; break; case UIKEY_UP: case 'k': ui_helppos[historypos] -= 8, uih->display = 1; presseditem = NULL; selecteditem = NULL; break; case UIKEY_PGDOWN: case '+': case 'f': case ' ': ui_helppos[historypos] += helpheight - HBORDERS - 32, uih->display = 1; presseditem = NULL; selecteditem = NULL; break; case UIKEY_PGUP: case '-': ui_helppos[historypos] -= helpheight - HBORDERS - 32, uih->display = 1; presseditem = NULL; selecteditem = NULL; break; case 'b': case 1: ui_backhelp(); break; case UIKEY_ESC: case 'q': case 'c': case 'o': ui_close_help(); break; case UIKEY_TAB: case UIKEY_RIGHT: uih->display = 1; if (selectedbutton < 0 || selectedbutton == NBUTTONS - 1) { if (selecteditem == NULL) { i = 0; while (YPOS(lines[i].y) < 2 * BORDERWIDTH) { i++; if (lines[i].y < 0) break; } selecteditem = lines[i].first; } else i = selectedline, selecteditem = selecteditem->next; for (; lines[i].y >= 0 && YPOS(lines[i].y) < helpheight - HBORDERS; i++) { selectedline = i; while (selecteditem != NULL) { if (selecteditem->c.linktext != NULL) { selectedbutton = -1; return 0; } selecteditem = selecteditem->next; } selecteditem = lines[i + 1].first; } selecteditem = NULL; selectedbutton = 0; } else selectedbutton++; break; case 13: case '\n': if (selecteditem != NULL) { ui_help(selecteditem->c.linktext); return 1; } if (selectedbutton >= 0) do_button(selectedbutton); } return 1; } int ui_helpmouse(int x, int y, int buttons, int flags) { static int grabbed = 0; int atpressed = 0; if (helpw == NULL) return 0; if (x < helpx || y < helpy || x > helpx + helpwidth || y > helpy + helpheight) { if (flags & MOUSE_PRESS) ui_close_help(); pressedbutton = -1; if (pressedbutton != -1) pressedbutton = -1, uih->display = 1; return 1; } else { if (y > helpy + helpheight - BUTTONHEIGHT - 2 * BORDERHEIGHT) { int button; int i; for (i = 0; i <= NBUTTONS; i++) if (x < BUTTONSTART(i)) break; button = i - 1; if (flags & MOUSE_DRAG) { if (pressedbutton != selectedbutton || pressedbutton != button) pressedbutton = selectedbutton = button, uih->display = 1; } else { if (pressedbutton != -1) pressedbutton = -1, uih->display = 1; if (flags & MOUSE_RELEASE) do_button(button); } return 1; } if (pressedbutton != -1) pressedbutton = -1, uih->display = 1; if (buttons && ((x > SCROOLSTART && y < helpy + helpheight - HBORDERS) || grabbed)) { /*we are in scroolbar */ int pos = (y - helpy) * textheight / (helpheight - HBORDERS); if (pos != ui_helppos[historypos]) ui_helppos[historypos] = pos, uih->display = 1; grabbed = 1; return 1; } else grabbed = 0; y -= helpy + xtextheight(uih->font); x -= 2 * BORDERWIDTH + helpx; pressedbutton = -1; if (presseditem != NULL) { if (YPOS(lines[pressedline].y) + 1 >= y && YPOS(lines[pressedline].y) <= y + xtextheight(uih->font) && presseditem->x <= x && presseditem->x + presseditem->width >= x) atpressed = 1; } if (flags & MOUSE_PRESS || ((flags & MOUSE_DRAG) && !atpressed)) { int i = 0; for (i = 0; lines[i].y >= 0 && (YPOS(lines[i].y) + 1 <= y || YPOS(lines[i].y) >= y + xtextheight(uih->font)); i++); if (lines[i].y >= 0) { struct xshl_item *item = lines[i].first; while (item != NULL) { if (item->c.linktext != NULL && item->x <= x && item->x + item->width >= x) break; item = item->next; } if (item != NULL) { uih->display = 1; presseditem = item; pressedline = i; } } } else if (flags & MOUSE_MOVE) { if (!atpressed && presseditem != NULL) uih->display = 1, presseditem = 0; } else if ((flags & MOUSE_RELEASE)) { if (atpressed) { ui_help(presseditem->c.linktext); return 1; } if (presseditem != NULL) presseditem = NULL, uih->display = 1; /*odfajruj to! */ } } return 1; } static void ui_build_help(char *name) { int i; int width; if (ui_nogui) { printf("help \"%s\"\n", name); return; } if (driver->gui_driver && driver->gui_driver->help) { driver->gui_driver->help(uih, name); return; } if (helpw != NULL) ui_close_help(); pressedbutton = -1; helpvisible = 1; width = 80 * xtextwidth(uih->font, "w"); if (width > WIDTH) width = WIDTH; lines = help_make(name ? name : "main", getwidth, width - 2, xtextheight(uih->font), xtextheight(uih->font)); if (lines == NULL) { lines = help_make("main", getwidth, width - 2, xtextheight(uih->font), xtextheight(uih->font)); if (lines == NULL) { helpvisible = 0; uih_message(uih, "Help file not found"); return; } } width += WBORDERS; uih->display = 1; presseditem = selecteditem = NULL; helpwidth = width; helpx = (uih->image->width - width) / 2; for (i = 0; lines[i].y >= 0; i++); textheight = lines[i - 1].y + 4 * xtextheight(uih->font); if (textheight < HEIGHT) helpheight = textheight; else helpheight = HEIGHT; helpheight += HBORDERS; helpy = (uih->image->height - helpheight) / 2; helpw = uih_registerw(uih, helpsize, drawhelp, 0, DRAWBORDER); } void ui_help(CONST char *name) { if (strlen(name) > 4 && !strcmp(name + strlen(name) - 4, ".xaf")) { uih_playtutorial(uih, name); if (helpw != NULL) ui_close_help(); /*FIXME!!!!!!! This needs to be queued! */ return; } historypos++; historypos %= HISTORYSIZE; ui_helppage[historypos] = mystrdup(name); /* NOTE we are not freeing this memory. I believe it is not problem. */ ui_helppos[historypos] = 0; ui_build_help(ui_helppage[historypos]); }