aewl
changeset 1:f10194d4b76d
added gridmenu
author | Anselm R. Garbe <garbeam@wmii.de> |
---|---|
date | Mon, 10 Jul 2006 16:49:43 +0200 |
parents | 491f34c11291 |
children | a79188fe4a40 |
files | Makefile gridmenu.1 gridmenu.c |
diffstat | 3 files changed, 617 insertions(+), 3 deletions(-) [+] |
line diff
1.1 --- a/Makefile Mon Jul 10 16:38:18 2006 +0200 1.2 +++ b/Makefile Mon Jul 10 16:49:43 2006 +0200 1.3 @@ -3,12 +3,21 @@ 1.4 1.5 include config.mk 1.6 1.7 -SRC = wm.c 1.8 -OBJ = ${SRC:.c=.o} 1.9 +SRC = wm.c 1.10 +OBJ = ${SRC:.c=.o} 1.11 +MAN = gridwm.1 1.12 +BIN = gridwm gridmenu 1.13 1.14 -all: gridwm 1.15 +all: config gridwm 1.16 @echo finished 1.17 1.18 +config: 1.19 + @echo gridwm build options: 1.20 + @echo "LIBS = ${LIBS}" 1.21 + @echo "CFLAGS = ${CFLAGS}" 1.22 + @echo "LDFLAGS = ${LDFLAGS}" 1.23 + @echo "CC = ${CC}" 1.24 + 1.25 .c.o: 1.26 @echo CC $< 1.27 @${CC} -c ${CFLAGS} $< 1.28 @@ -21,3 +30,26 @@ 1.29 1.30 clean: 1.31 rm -f gridwm *.o 1.32 + 1.33 +dist: clean 1.34 + mkdir -p gridwm-${VERSION} 1.35 + cp -R Makefile README LICENSE config.mk ${SRC} ${MAN} gridwm-${VERSION} 1.36 + tar -cf gridwm-${VERSION}.tar gridwm-${VERSION} 1.37 + gzip gridwm-${VERSION}.tar 1.38 + rm -rf gridwm-${VERSION} 1.39 + 1.40 +install: all 1.41 + @mkdir -p ${DESTDIR}${PREFIX}/bin 1.42 + @cp -f ${BIN} ${DESTDIR}${PREFIX}/bin 1.43 + @echo installed executable files to ${DESTDIR}${PREFIX}/bin 1.44 + @mkdir -p ${DESTDIR}${MANPREFIX}/man1 1.45 + @cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1 1.46 + @echo installed manual pages to ${DESTDIR}${MANPREFIX}/man1 1.47 + 1.48 +uninstall: 1.49 + for i in ${BIN}; do \ 1.50 + rm -f ${DESTDIR}${PREFIX}/bin/`basename $$i`; \ 1.51 + done 1.52 + for i in ${MAN1}; do \ 1.53 + rm -f ${DESTDIR}${MANPREFIX}/man1/`basename $$i`; \ 1.54 + done
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/gridmenu.1 Mon Jul 10 16:49:43 2006 +0200 2.3 @@ -0,0 +1,84 @@ 2.4 +.TH GRIDMENU 1 grid-0.0 2.5 +.SH NAME 2.6 +gridmenu \- grid window manager menu 2.7 +.SH SYNOPSIS 2.8 +.B gridmenu 2.9 +.RB [ \-v ] 2.10 +.RB [ \-t 2.11 +.IR title ] 2.12 +.SH DESCRIPTION 2.13 +.SS Overview 2.14 +.B gridmenu 2.15 +is a generic, highly customizable, and efficient menu for the X Window System, 2.16 +originally designed for 2.17 +.BR grid (1). 2.18 +It supports arbitrary, user defined menu contents. 2.19 +.SS Options 2.20 +.TP 2.21 +.B \-v 2.22 +prints version information to stdout, then exits. 2.23 +.TP 2.24 +.BI \-t " title" 2.25 +displays 2.26 +.I title 2.27 +above the menu. 2.28 +.SS Usage 2.29 +.B gridmenu 2.30 +reads a list of newline-separated items from stdin and creates a menu. 2.31 +When the user selects an item or enters any text and presses Enter, his choice 2.32 +is printed to stdout and 2.33 +.B gridmenu 2.34 +terminates. 2.35 +.SS Keyboard Control 2.36 +.B gridmenu 2.37 +is completely controlled by the keyboard. The following keys are recognized: 2.38 +.TP 2 2.39 +Any printable character 2.40 +appends the character to the text in the input field. This works as a filter: 2.41 +only items containing this text will be displayed. 2.42 +.TP 2 2.43 +Left/Right (Control-p/Control-n) 2.44 +select the previous/next item. 2.45 +.TP 2 2.46 +Tab (Control-i) 2.47 +copy the selected item to the input field. 2.48 +.TP 2 2.49 +Enter (Control-j) 2.50 +confirm selection and quit (print the selected item to stdout). 2.51 +.TP 2 2.52 +Shift-Enter (Shift-Control-j) 2.53 +confirm selection and quit (print the text in the input field to stdout). 2.54 +.TP 2 2.55 +Escape (Control-[) 2.56 +quit without selecting an item. 2.57 +.TP 2 2.58 +Backspace (Control-h) 2.59 +remove enough characters from the input field to change its filtering effect. 2.60 +.TP 2 2.61 +Control-u 2.62 +remove all characters from the input field. 2.63 +.SS Exit codes 2.64 +.B gridmenu 2.65 +returns 2.66 +.B 0 2.67 +if Enter is pressed on termination, 2.68 +.B 1 2.69 +if Escape is pressed. 2.70 +.SH ENVIRONMENT 2.71 +.TP 2.72 +GRID_FONT 2.73 +The X11 font used to display each item in the menu. 2.74 +.br 2.75 +Default: fixed 2.76 +.TP 2.77 +GRID_NORMCOLORS 2.78 +The foreground, background, and border colors of a label. Syntactically, three blank-separated color values of the form #RRGGBB are expected. 2.79 +.br 2.80 +Default: #222222 #eeeeee #666666 2.81 +.TP 2.82 +GRID_SELCOLORS 2.83 +Like GRID_NORMCOLORS, but for the selected label. 2.84 +.br 2.85 +Default: #ffffff #335577 #447799 2.86 +.SH SEE ALSO 2.87 +.BR gridwm (1)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/gridmenu.c Mon Jul 10 16:49:43 2006 +0200 3.3 @@ -0,0 +1,498 @@ 3.4 +/* 3.5 + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> 3.6 + * (C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> 3.7 + * See LICENSE file for license details. 3.8 + */ 3.9 + 3.10 +#include <ctype.h> 3.11 +#include <stdlib.h> 3.12 +#include <stdio.h> 3.13 +#include <string.h> 3.14 +#include <sys/stat.h> 3.15 +#include <sys/wait.h> 3.16 +#include <time.h> 3.17 +#include <unistd.h> 3.18 +#include <X11/Xlib.h> 3.19 +#include <X11/cursorfont.h> 3.20 +#include <X11/Xutil.h> 3.21 +#include <X11/keysym.h> 3.22 + 3.23 +#include <blitz.h> 3.24 +#include <cext.h> 3.25 + 3.26 +typedef struct Item Item; 3.27 + 3.28 +struct Item { 3.29 + Item *next; /* traverses all items */ 3.30 + Item *left, *right; /* traverses items matching current search pattern */ 3.31 + char *text; 3.32 +}; 3.33 + 3.34 +static char *title = nil; 3.35 +static Bool done = False; 3.36 +static int ret = 0; 3.37 +static char text[4096]; 3.38 +static BlitzColor selcolor; 3.39 +static BlitzColor normcolor; 3.40 +static Window win; 3.41 +static XRectangle mrect; 3.42 +static Item *allitem = nil; /* first of all items */ 3.43 +static Item *item = nil; /* first of pattern matching items */ 3.44 +static Item *sel = nil; 3.45 +static Item *nextoff = nil; 3.46 +static Item *prevoff = nil; 3.47 +static Item *curroff = nil; 3.48 +static int nitem = 0; 3.49 +static unsigned int cmdw = 0; 3.50 +static unsigned int twidth = 0; 3.51 +static unsigned int cwidth = 0; 3.52 +static Blitz blz = {0}; 3.53 +static BlitzBrush brush = {0}; 3.54 +static const int seek = 30; /* 30px */ 3.55 + 3.56 +static void draw_menu(void); 3.57 +static void handle_kpress(XKeyEvent * e); 3.58 + 3.59 +static char version[] = "wmiimenu - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n"; 3.60 + 3.61 +static void 3.62 +usage() 3.63 +{ 3.64 + fprintf(stderr, "%s", "usage: wmiimenu [-v] [-t <title>]\n"); 3.65 + exit(1); 3.66 +} 3.67 + 3.68 +static void 3.69 +update_offsets() 3.70 +{ 3.71 + unsigned int tw, w = cmdw + 2 * seek; 3.72 + 3.73 + if(!curroff) 3.74 + return; 3.75 + 3.76 + for(nextoff = curroff; nextoff; nextoff=nextoff->right) { 3.77 + tw = blitz_textwidth(brush.font, nextoff->text); 3.78 + if(tw > mrect.width / 3) 3.79 + tw = mrect.width / 3; 3.80 + w += tw + mrect.height; 3.81 + if(w > mrect.width) 3.82 + break; 3.83 + } 3.84 + 3.85 + w = cmdw + 2 * seek; 3.86 + for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) { 3.87 + tw = blitz_textwidth(brush.font, prevoff->left->text); 3.88 + if(tw > mrect.width / 3) 3.89 + tw = mrect.width / 3; 3.90 + w += tw + mrect.height; 3.91 + if(w > mrect.width) 3.92 + break; 3.93 + } 3.94 +} 3.95 + 3.96 +static void 3.97 +update_items(char *pattern) 3.98 +{ 3.99 + unsigned int plen = strlen(pattern); 3.100 + Item *i, *j; 3.101 + 3.102 + if(!pattern) 3.103 + return; 3.104 + 3.105 + if(!title || *pattern) 3.106 + cmdw = cwidth; 3.107 + else 3.108 + cmdw = twidth; 3.109 + 3.110 + item = j = nil; 3.111 + nitem = 0; 3.112 + 3.113 + for(i = allitem; i; i=i->next) 3.114 + if(!plen || !strncmp(pattern, i->text, plen)) { 3.115 + if(!j) 3.116 + item = i; 3.117 + else 3.118 + j->right = i; 3.119 + i->left = j; 3.120 + i->right = nil; 3.121 + j = i; 3.122 + nitem++; 3.123 + } 3.124 + for(i = allitem; i; i=i->next) 3.125 + if(plen && strncmp(pattern, i->text, plen) 3.126 + && strstr(i->text, pattern)) { 3.127 + if(!j) 3.128 + item = i; 3.129 + else 3.130 + j->right = i; 3.131 + i->left = j; 3.132 + i->right = nil; 3.133 + j = i; 3.134 + nitem++; 3.135 + } 3.136 + 3.137 + curroff = prevoff = nextoff = sel = item; 3.138 + 3.139 + update_offsets(); 3.140 +} 3.141 + 3.142 +/* creates brush structs for brush mode drawing */ 3.143 +static void 3.144 +draw_menu() 3.145 +{ 3.146 + unsigned int offx = 0; 3.147 + 3.148 + Item *i; 3.149 + 3.150 + brush.align = WEST; 3.151 + 3.152 + brush.rect = mrect; 3.153 + brush.rect.x = 0; 3.154 + brush.rect.y = 0; 3.155 + brush.color = normcolor; 3.156 + brush.border = False; 3.157 + blitz_draw_tile(&brush); 3.158 + 3.159 + /* print command */ 3.160 + if(!title || text[0]) { 3.161 + brush.color = normcolor; 3.162 + cmdw = cwidth; 3.163 + if(cmdw && item) 3.164 + brush.rect.width = cmdw; 3.165 + blitz_draw_label(&brush, text); 3.166 + } 3.167 + else { 3.168 + cmdw = twidth; 3.169 + brush.color = selcolor; 3.170 + brush.rect.width = cmdw; 3.171 + blitz_draw_label(&brush, title); 3.172 + } 3.173 + offx += brush.rect.width; 3.174 + 3.175 + brush.align = CENTER; 3.176 + if(curroff) { 3.177 + brush.color = normcolor; 3.178 + brush.rect.x = offx; 3.179 + brush.rect.width = seek; 3.180 + offx += brush.rect.width; 3.181 + blitz_draw_label(&brush, (curroff && curroff->left) ? "<" : nil); 3.182 + 3.183 + /* determine maximum items */ 3.184 + for(i = curroff; i != nextoff; i=i->right) { 3.185 + brush.color = normcolor; 3.186 + brush.border = False; 3.187 + brush.rect.x = offx; 3.188 + brush.rect.width = blitz_textwidth(brush.font, i->text); 3.189 + if(brush.rect.width > mrect.width / 3) 3.190 + brush.rect.width = mrect.width / 3; 3.191 + brush.rect.width += mrect.height; 3.192 + if(sel == i) { 3.193 + brush.color = selcolor; 3.194 + brush.border = True; 3.195 + } 3.196 + blitz_draw_label(&brush, i->text); 3.197 + offx += brush.rect.width; 3.198 + } 3.199 + 3.200 + brush.color = normcolor; 3.201 + brush.border = False; 3.202 + brush.rect.x = mrect.width - seek; 3.203 + brush.rect.width = seek; 3.204 + blitz_draw_label(&brush, nextoff ? ">" : nil); 3.205 + } 3.206 + XCopyArea(blz.dpy, brush.drawable, win, brush.gc, 0, 0, mrect.width, 3.207 + mrect.height, 0, 0); 3.208 + XSync(blz.dpy, False); 3.209 +} 3.210 + 3.211 +static void 3.212 +handle_kpress(XKeyEvent * e) 3.213 +{ 3.214 + KeySym ksym; 3.215 + char buf[32]; 3.216 + int num, prev_nitem; 3.217 + unsigned int i, len = strlen(text); 3.218 + 3.219 + buf[0] = 0; 3.220 + num = XLookupString(e, buf, sizeof(buf), &ksym, 0); 3.221 + 3.222 + if(IsFunctionKey(ksym) || IsKeypadKey(ksym) 3.223 + || IsMiscFunctionKey(ksym) || IsPFKey(ksym) 3.224 + || IsPrivateKeypadKey(ksym)) 3.225 + return; 3.226 + 3.227 + /* first check if a control mask is omitted */ 3.228 + if(e->state & ControlMask) { 3.229 + switch (ksym) { 3.230 + case XK_H: 3.231 + case XK_h: 3.232 + ksym = XK_BackSpace; 3.233 + break; 3.234 + case XK_I: 3.235 + case XK_i: 3.236 + ksym = XK_Tab; 3.237 + break; 3.238 + case XK_J: 3.239 + case XK_j: 3.240 + ksym = XK_Return; 3.241 + break; 3.242 + case XK_N: 3.243 + case XK_n: 3.244 + ksym = XK_Right; 3.245 + break; 3.246 + case XK_P: 3.247 + case XK_p: 3.248 + ksym = XK_Left; 3.249 + break; 3.250 + case XK_U: 3.251 + case XK_u: 3.252 + text[0] = 0; 3.253 + update_items(text); 3.254 + draw_menu(); 3.255 + return; 3.256 + break; 3.257 + case XK_bracketleft: 3.258 + ksym = XK_Escape; 3.259 + break; 3.260 + default: /* ignore other control sequences */ 3.261 + return; 3.262 + break; 3.263 + } 3.264 + } 3.265 + switch (ksym) { 3.266 + case XK_Left: 3.267 + if(!(sel && sel->left)) 3.268 + return; 3.269 + sel=sel->left; 3.270 + if(sel->right == curroff) { 3.271 + curroff = prevoff; 3.272 + update_offsets(); 3.273 + } 3.274 + break; 3.275 + case XK_Tab: 3.276 + if(!sel) 3.277 + return; 3.278 + cext_strlcpy(text, sel->text, sizeof(text)); 3.279 + update_items(text); 3.280 + break; 3.281 + case XK_Right: 3.282 + if(!(sel && sel->right)) 3.283 + return; 3.284 + sel=sel->right; 3.285 + if(sel == nextoff) { 3.286 + curroff = nextoff; 3.287 + update_offsets(); 3.288 + } 3.289 + break; 3.290 + case XK_Return: 3.291 + if(e->state & ShiftMask) { 3.292 + if(text) 3.293 + fprintf(stdout, "%s", text); 3.294 + } 3.295 + else if(sel) 3.296 + fprintf(stdout, "%s", sel->text); 3.297 + else if(text) 3.298 + fprintf(stdout, "%s", text); 3.299 + fflush(stdout); 3.300 + done = True; 3.301 + break; 3.302 + case XK_Escape: 3.303 + ret = 1; 3.304 + done = True; 3.305 + break; 3.306 + case XK_BackSpace: 3.307 + if((i = len)) { 3.308 + prev_nitem = nitem; 3.309 + do { 3.310 + text[--i] = 0; 3.311 + update_items(text); 3.312 + } while(i && nitem && prev_nitem == nitem); 3.313 + update_items(text); 3.314 + } 3.315 + break; 3.316 + default: 3.317 + if((num == 1) && !iscntrl((int) buf[0])) { 3.318 + buf[num] = 0; 3.319 + if(len > 0) 3.320 + cext_strlcat(text, buf, sizeof(text)); 3.321 + else 3.322 + cext_strlcpy(text, buf, sizeof(text)); 3.323 + update_items(text); 3.324 + } 3.325 + } 3.326 + draw_menu(); 3.327 +} 3.328 + 3.329 +static char * 3.330 +read_allitems() 3.331 +{ 3.332 + static char *maxname = nil; 3.333 + char *p, buf[1024]; 3.334 + unsigned int len = 0, max = 0; 3.335 + Item *i, *new; 3.336 + 3.337 + i = nil; 3.338 + while(fgets(buf, sizeof(buf), stdin)) { 3.339 + len = strlen(buf); 3.340 + if (buf[len - 1] == '\n') 3.341 + buf[len - 1] = 0; 3.342 + p = cext_estrdup(buf); 3.343 + if(max < len) { 3.344 + maxname = p; 3.345 + max = len; 3.346 + } 3.347 + 3.348 + new = cext_emalloc(sizeof(Item)); 3.349 + new->next = new->left = new->right = nil; 3.350 + new->text = p; 3.351 + if(!i) 3.352 + allitem = new; 3.353 + else 3.354 + i->next = new; 3.355 + i = new; 3.356 + } 3.357 + 3.358 + return maxname; 3.359 +} 3.360 + 3.361 +int 3.362 +main(int argc, char *argv[]) 3.363 +{ 3.364 + int i; 3.365 + XSetWindowAttributes wa; 3.366 + char *maxname, *p; 3.367 + BlitzFont font = {0}; 3.368 + GC gc; 3.369 + Drawable pmap; 3.370 + XEvent ev; 3.371 + 3.372 + /* command line args */ 3.373 + for(i = 1; i < argc; i++) { 3.374 + if (argv[i][0] == '-') 3.375 + switch (argv[i][1]) { 3.376 + case 'v': 3.377 + fprintf(stdout, "%s", version); 3.378 + exit(0); 3.379 + break; 3.380 + case 't': 3.381 + if(++i < argc) 3.382 + title = argv[i]; 3.383 + else 3.384 + usage(); 3.385 + break; 3.386 + default: 3.387 + usage(); 3.388 + break; 3.389 + } 3.390 + else 3.391 + usage(); 3.392 + } 3.393 + 3.394 + blz.dpy = XOpenDisplay(0); 3.395 + if(!blz.dpy) { 3.396 + fprintf(stderr, "%s", "wmiimenu: cannot open dpy\n"); 3.397 + exit(1); 3.398 + } 3.399 + blz.screen = DefaultScreen(blz.dpy); 3.400 + blz.root = RootWindow(blz.dpy, blz.screen); 3.401 + 3.402 + maxname = read_allitems(); 3.403 + 3.404 + /* grab as early as possible, but after reading all items!!! */ 3.405 + while(XGrabKeyboard 3.406 + (blz.dpy, blz.root, True, GrabModeAsync, 3.407 + GrabModeAsync, CurrentTime) != GrabSuccess) 3.408 + usleep(1000); 3.409 + 3.410 + font.fontstr = getenv("WMII_FONT"); 3.411 + if (!font.fontstr) 3.412 + font.fontstr = cext_estrdup(BLITZ_FONT); 3.413 + blitz_loadfont(&blz, &font); 3.414 + 3.415 + if((p = getenv("WMII_NORMCOLORS"))) 3.416 + cext_strlcpy(normcolor.colstr, p, sizeof(normcolor.colstr)); 3.417 + if(strlen(normcolor.colstr) != 23) 3.418 + cext_strlcpy(normcolor.colstr, BLITZ_NORMCOLORS, sizeof(normcolor.colstr)); 3.419 + blitz_loadcolor(&blz, &normcolor); 3.420 + 3.421 + if((p = getenv("WMII_SELCOLORS"))) 3.422 + cext_strlcpy(selcolor.colstr, p, sizeof(selcolor.colstr)); 3.423 + if(strlen(selcolor.colstr) != 23) 3.424 + cext_strlcpy(selcolor.colstr, BLITZ_SELCOLORS, sizeof(selcolor.colstr)); 3.425 + blitz_loadcolor(&blz, &selcolor); 3.426 + 3.427 + wa.override_redirect = 1; 3.428 + wa.background_pixmap = ParentRelative; 3.429 + wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask 3.430 + | SubstructureRedirectMask | SubstructureNotifyMask; 3.431 + 3.432 + mrect.width = DisplayWidth(blz.dpy, blz.screen); 3.433 + mrect.height = font.ascent + font.descent + 4; 3.434 + mrect.y = DisplayHeight(blz.dpy, blz.screen) - mrect.height; 3.435 + mrect.x = 0; 3.436 + 3.437 + win = XCreateWindow(blz.dpy, blz.root, mrect.x, mrect.y, 3.438 + mrect.width, mrect.height, 0, DefaultDepth(blz.dpy, blz.screen), 3.439 + CopyFromParent, DefaultVisual(blz.dpy, blz.screen), 3.440 + CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); 3.441 + XDefineCursor(blz.dpy, win, XCreateFontCursor(blz.dpy, XC_xterm)); 3.442 + XSync(blz.dpy, False); 3.443 + 3.444 + /* pixmap */ 3.445 + gc = XCreateGC(blz.dpy, win, 0, 0); 3.446 + pmap = XCreatePixmap(blz.dpy, win, mrect.width, mrect.height, 3.447 + DefaultDepth(blz.dpy, blz.screen)); 3.448 + 3.449 + XSync(blz.dpy, False); 3.450 + 3.451 + brush.blitz = &blz; 3.452 + brush.color = normcolor; 3.453 + brush.drawable = pmap; 3.454 + brush.gc = gc; 3.455 + brush.font = &font; 3.456 + 3.457 + if(maxname) 3.458 + cwidth = blitz_textwidth(brush.font, maxname) + mrect.height; 3.459 + if(cwidth > mrect.width / 3) 3.460 + cwidth = mrect.width / 3; 3.461 + 3.462 + if(title) { 3.463 + twidth = blitz_textwidth(brush.font, title) + mrect.height; 3.464 + if(twidth > mrect.width / 3) 3.465 + twidth = mrect.width / 3; 3.466 + } 3.467 + 3.468 + cmdw = title ? twidth : cwidth; 3.469 + 3.470 + text[0] = 0; 3.471 + update_items(text); 3.472 + XMapRaised(blz.dpy, win); 3.473 + draw_menu(); 3.474 + XSync(blz.dpy, False); 3.475 + 3.476 + /* main event loop */ 3.477 + while(!XNextEvent(blz.dpy, &ev)) { 3.478 + switch (ev.type) { 3.479 + case KeyPress: 3.480 + handle_kpress(&ev.xkey); 3.481 + break; 3.482 + case Expose: 3.483 + if(ev.xexpose.count == 0) { 3.484 + draw_menu(); 3.485 + } 3.486 + break; 3.487 + default: 3.488 + break; 3.489 + } 3.490 + if(done) 3.491 + break; 3.492 + } 3.493 + 3.494 + XUngrabKeyboard(blz.dpy, CurrentTime); 3.495 + XFreePixmap(blz.dpy, pmap); 3.496 + XFreeGC(blz.dpy, gc); 3.497 + XDestroyWindow(blz.dpy, win); 3.498 + XCloseDisplay(blz.dpy); 3.499 + 3.500 + return ret; 3.501 +}