/* help.c program info, keyboard shortcuts */ /* * xcheckers: a point and click checkerboard * (C): 1999, 2000 Peter Chiocchetti */ #include #include #include #include #include "xcheckers.h" #include "help.h" #include "xcheckers.xbm" #include "resource.h" #include "child.h" #define border 1 #define hline(i) ((font->ascent + font->descent) * i) #define shift (font->descent + 1) #define gutter (XTextWidth (font, "n", 1)) #define header (icon_height + shift + gutter) #define hheight (header + hline (5) + gutter) #define MAX 12 #define maxlen(str) (str ? (strlen(str) >= MAX ? MAX : strlen (str)) : 0) #define safeGet(id) (resGet (id) ? resGet (id) : "") #define HELPMASK (ButtonPressMask | ButtonReleaseMask \ | PointerMotionMask | ButtonMotionMask \ | EnterWindowMask | LeaveWindowMask \ | ExposureMask) #define HGCMASK (GCBackground | GCForeground | GCFont) #define nlabels (sizeof (labels) / sizeof (macro)) int help = 0; macro *labelp; Pixmap icon; GC hgc; int hwidth, mwidth; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * program info * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* return the button column the pointer is over */ static int mcol(int x) { if (x > gutter && x < gutter + mwidth) return 0; if (x > gutter + mwidth + gutter && x < gutter + mwidth + gutter + mwidth) return 1; return -1; } /* return the button row the pointer is over */ static int mrow(int y) { y -= header; if (y > 0 && y < hline(5)) return (y / hline(1)); return -1; } /* invert button the pointer is over */ void helpSel(int curx, int cury) { static int oldx = 0; static int oldy = 0; cury -= shift; if ((mcol(curx) == mcol(oldx)) && (mrow(cury) == mrow(oldy))) return; if (mcol(oldx) >= 0 && mrow(oldy) >= 0) XFillRectangle(dpy, hwin, hgc, gutter + (gutter + mwidth) * mcol(oldx), header + shift + hline(mrow(oldy)), mwidth, hline(1)); if (mcol(curx) < 0 || mrow(cury) < 0) { oldx = 0; oldy = 0; return; } XFillRectangle(dpy, hwin, hgc, gutter + (gutter + mwidth) * mcol(curx), header + shift + hline(mrow(cury)), mwidth, hline(1)); oldx = curx; oldy = cury; } /* display help window */ void showHelp(void) { if (!help) { XMoveWindow(dpy,hwin, (board_width - hwidth) / 2 - border, (board_height - hheight) / 2 - border); XMapWindow(dpy, hwin); help = 1; } else { helpSel(0, 0); XUnmapWindow(dpy, hwin); help = 0; } } /* send message from button that was clicked */ void helpBut(int x, int y) { y -= shift; x = mcol(x); y = mrow(y); if (x >= 0 && y >= 0) { showHelp(); y += x * 5; message(strdup((labelp + y)->call)); } } /* draw into the help window */ void drawHelp(void) { int i; macro *tmp; /* header: program icon, program name */ XCopyArea(dpy, icon, hwin, gc, 0, 0, icon_width, icon_height, gutter, header - icon_height - shift); XDrawString(dpy, hwin, gc, gutter + icon_width + gutter, header - shift, progname, maxlen(progname)); XDrawLine(dpy, hwin, gc, gutter, header, hwidth - gutter, header); /* buttons */ for (i = 1, tmp = labelp; i <= 5; i++, tmp++) { XDrawString(dpy, hwin, gc, gutter, header + hline(i), tmp->label, maxlen(tmp->label)); XDrawString(dpy, hwin, gc, gutter + mwidth + gutter, header + hline(i), (tmp + 5)->label, maxlen((tmp + 5)->label)); } } /* prepare help window */ void initHelp(unsigned long paper, unsigned long pen) { int tmp; int i; macro labels[] = { {safeGet("button0_label"), safeGet("button0_call")}, {safeGet("button1_label"), safeGet("button1_call")}, {safeGet("button2_label"), safeGet("button2_call")}, {safeGet("button3_label"), safeGet("button3_call")}, {safeGet("button4_label"), safeGet("button4_call")}, {safeGet("button5_label"), safeGet("button5_call")}, {safeGet("button6_label"), safeGet("button6_call")}, {safeGet("button7_label"), safeGet("button7_call")}, {safeGet("button8_label"), safeGet("button8_call")}, {safeGet("button9_label"), safeGet("button9_call")}, }; labelp = (macro *) malloc(sizeof(labels)); memcpy(labelp, labels, sizeof(labels)); for (mwidth = 0, i = 0; i < nlabels; i++) if ((tmp = XTextWidth(font, labels[i].label, maxlen(labels[i].label))) > mwidth) mwidth = tmp; hwidth = gutter + mwidth + gutter + mwidth + gutter; if ((tmp = gutter + icon_width + gutter + XTextWidth(font, "progname", maxlen(progname)) + gutter) > hwidth) hwidth = tmp; hwin = XCreateSimpleWindow(dpy, win, (board_width - hwidth) / 2, (board_height - hheight) / 2, hwidth, hheight, border, pen, paper); icon = XCreatePixmapFromBitmapData(dpy, hwin, icon_bits, icon_width, icon_height, pen, paper, DefaultDepth(dpy, screen)); hgc = XCreateGC(dpy, hwin, 0, NULL); XCopyGC(dpy, gc, HGCMASK, hgc); XSetForeground(dpy, hgc, pen ^ paper); XSetFunction(dpy, hgc, GXxor); XSelectInput(dpy, hwin, HELPMASK); showHelp(); }