wmbiff: Remove unused variable.
[dockapps.git] / wmbutton / wmb_libs.c
blob55802ff57ad87c544d8b44bfdfb3dc765fbf6888
1 /* wmb_libs.c - Edward H. Flora - ehf_dockapps@cox.net */
2 /* Last Modified: 4/3/04 */
3 /*
4 * These functions are designed to work with wmbutton.
5 */
7 /* PORTABILITY:
8 ******************
9 * Coded in ANSI C, using ANSI prototypes.
12 /****** Include Files *************************************************/
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include "wmbutton.h"
18 /****** ToolTip Globals ***********************************************/
20 static struct timeval _tStart;
22 extern struct Config_t Config;
23 int _bTooltip = 0;
24 XFontStruct* _fTooltip;
25 int _nFontHeight, _nFontY;
26 int _nScreenWidth, _nScreenHeight;
27 GC _gcMono = 0;
28 Window _wTooltip;
30 /****** Parse Command Line ********************************************/
31 void parseargs(int argc, char **argv)
33 int current;
34 char *Home = getenv("HOME");
36 while (-1 != (current = getopt(argc, argv, "vhnmsF:b:g:d:f:"))) {
37 switch (current) {
38 case 'v':
39 Config.Verbose = 1;
40 break;
41 case '?':
42 case 'h':
43 show_usage();
44 break;
45 case 'm':
46 Config.mmouse = 1;
47 break;
48 case 'n':
49 Config.bTooltipDisable = 1;
50 break;
51 case 's':
52 Config.bTooltipSwapColors = 1;
53 break;
54 case 'g':
55 Config.Geometry_str = strdup(optarg);
56 break;
57 case 'd':
58 Config.Display_str = strdup(optarg);
59 break;
60 case 'f':
61 Config.configfile = strdup(optarg);
62 break;
63 case 'F':
64 Config.szTooltipFont = strdup(optarg);
65 break;
66 case 'b':
67 Config.buttonfile = strdup(optarg);
68 break;
72 if (!Config.configfile) {
73 if (Home != NULL) {
74 Config.configfile = malloc(strlen(Home) +
75 strlen(CONFFILENAME) + 1);
76 sprintf(Config.configfile, "%s%s", Home, CONFFILENAME);
80 if (!Config.buttonfile) {
81 if (Home != NULL) {
82 Config.buttonfile = malloc(strlen(Home) +
83 strlen(BUTTONFILENAME) + 1);
84 sprintf(Config.buttonfile, "%s%s", Home, BUTTONFILENAME);
88 if (!Config.Geometry_str)
89 Config.Geometry_str = "64x64+0+0";
91 if (!Config.Display_str)
92 Config.Display_str = "";
94 if (!Config.szTooltipFont)
95 Config.szTooltipFont = TOOLTIP_FONT;
97 if (!Config.bTooltipDisable)
98 Config.bTooltipDisable = !TOOLTIP_SUPPORT;
102 /****** Show Usage Information ****************************************/
103 void show_usage(void)
105 extern char *app_name;
107 fprintf(stderr, "\n");
108 fprintf(stderr, "usage: %s [-g geom] [-d dpy] [-f cfgfile] [-b btnfile] "\
109 "[-F <font>] [-v] [-s] [-n]\n",app_name);
110 fprintf(stderr, "\n");
111 fprintf(stderr, " wmbutton version %s\n", VER_STR);
112 fprintf(stderr, "\n");
113 fprintf(stderr, "-g <geometry> Window Geometry - ie: 64x64+10+10\n");
114 fprintf(stderr, "-d <display> Display - ie: 127.0.0.1:0.0\n");
115 fprintf(stderr, "-f <filename> Full path to configuration file.\n");
116 fprintf(stderr, "-b <filename> Full path to button xpm.\n");
117 fprintf(stderr, "-F <font> Custom tooltip font (e.g. -b\\&h-lucidatypewriter-medium-*-*-*-12-*)\n");
118 fprintf(stderr, "-v Verbose Mode.\n");
119 fprintf(stderr, "-h Help. This message.\n");
120 fprintf(stderr, "-m Disable Middle Mouse functionality.\n");
121 fprintf(stderr, "-s Swap tooltip colors.\n");
122 fprintf(stderr, "-n Turn off tooltips.\n");
123 fprintf(stderr, "\n");
124 exit(0);
126 /***********************************************************************/
128 /****** Error Handler Routine *****************************************/
129 void err_mess(int err, char *str)
131 switch (err) {
132 case FAILDISP:
133 fprintf(stderr, "Fail: XOpenDisplay for %s\n", str);
134 exit(err);
135 case FAILSWIN:
136 fprintf(stderr, "Fail: XCreateSimpleWindow\n");
137 exit(err);
138 case FAILICON:
139 fprintf(stderr, "Fail: XCreateSimpleWindow\n");
140 exit(err);
141 case FAILXPM:
142 fprintf(stderr, "Fail: XCreateBitmapFromData\n");
143 break;
144 case FAILWNAM:
145 fprintf(stderr, "%s: Can't set up window name\n", str);
146 exit(err);
147 case FAILGC:
148 fprintf(stderr, "Fail: XCreateGC\n");
149 exit(err);
150 case FAILCONF:
151 fprintf(stderr, "Fail: Can't Find user or system configuration file.\n");
152 fprintf(stderr, "Fail: User Config: '%s'\n", str);
153 fprintf(stderr, "Fail: System Config: '%s'\n", CONFIGGLOBAL);
154 exit(err);
155 case FAILTMPL:
156 fprintf(stderr, "Fail: Can't Create 'template' Pixmap\n");
157 exit(err);
158 case FAILVIS:
159 fprintf(stderr, "Fail: Can't Create 'visible' Pixmap\n");
160 exit(err);
161 case FAILBUT:
162 fprintf(stderr, "Fail: Can't Create 'buttons' Pixmap\n");
163 exit(err);
164 default:
165 fprintf(stderr, "Fail: UnSpecified Error: %d\n", err);
166 fprintf(stderr, "Fail: %s\n", str);
167 exit(err);
170 /***********************************************************************/
172 /***********************************************************************
173 * RunAppN(int app)
175 * Run the command given in the configuration file 'configfile'
176 ***********************************************************************/
177 void RunAppN(int app)
179 char *cmndstr;
180 extern struct Config_t Config;
182 cmndstr = Parse(app); /* Get command to pass to system */
184 if (Config.Verbose)
185 fprintf(stderr, "Command String: %s", cmndstr);
187 if (cmndstr != NULL) {
188 system(cmndstr); /* if there's a command, run it */
189 free(cmndstr);
192 /***********************************************************************/
194 /***********************************************************************
195 * Parse(int app)
197 * Parses the file 'configfile' for command to execute.
198 ***********************************************************************/
199 char *Parse(int app)
201 FILE *fp;
202 char Buf[BUFFER_SIZE];
203 char *Ptr;
205 if ((fp = fopen(Config.configfile, "r")) == NULL)
206 if ((fp = fopen(CONFIGGLOBAL, "r")) == NULL)
207 err_mess(FAILCONF,Config.configfile);
209 while ((Ptr = fgets(Buf, BUFFER_SIZE, fp))) {
210 if (atoi(Buf) == app)
211 break;
214 fclose(fp);
216 if (!Ptr)
217 return Ptr;
219 Ptr = strchr(Buf, '\t'); /* find first tab */
220 if (Ptr == NULL)
221 Ptr = strchr(Buf, ' '); /* or space charater */
223 if (Ptr == NULL)
224 return(NULL);
226 Ptr++;
227 Ptr = strdup(Ptr);
229 return Ptr;
231 /**********************************************************************/
233 /***********************************************************************
234 * initTime
236 * Copyright (c) 2001 Bruno Essmann <essmann@users.sourceforge.net>
237 ***********************************************************************/
239 void initTime(void)
241 extern struct Config_t Config;
243 if (Config.Verbose)
244 fprintf(stdout, "[ ] initializing time\n");
246 gettimeofday(&_tStart, NULL);
248 /**********************************************************************/
250 long currentTimeMillis(void)
252 struct timeval tNow, tElapsed;
254 gettimeofday(&tNow, NULL);
256 if (_tStart.tv_usec > tNow.tv_usec) {
257 tNow.tv_usec += 1000000;
258 tNow.tv_sec--;
261 tElapsed.tv_sec = tNow.tv_sec - _tStart.tv_sec;
262 tElapsed.tv_usec = tNow.tv_usec - _tStart.tv_usec;
263 return (tElapsed.tv_sec * 1000) + (tElapsed.tv_usec / 1000);
265 /**********************************************************************/
267 void getWindowOrigin(Window w, int *nX, int *nY)
269 extern Display *display;
270 Window wWindow, wParent, wRoot;
271 Window* wChildren;
272 unsigned int nChildren, ww, wh, wb, wd;
273 int wx, wy;
275 wParent = w;
276 do {
277 wWindow = wParent;
278 if (!XQueryTree(display, wParent, &wRoot, &wParent, &wChildren, &nChildren))
279 return;
281 if (wChildren)
282 XFree(wChildren);
284 } while (wParent != wRoot);
286 if (XGetGeometry(display, wWindow, &wRoot, &wx, &wy, &ww, &wh, &wb, &wd)) {
287 if (nX)
288 *nX = wx;
290 if (nY)
291 *nY = wy;
294 /**********************************************************************/
296 /***********************************************************************
297 * getButtonLocation
299 * compute location for each button's tooltip (not perfect)
300 ***********************************************************************/
301 void getButtonLocation (int nButton, int *nLocationX, int *nLocationY)
303 *nLocationX = 0;
304 *nLocationY = 8;
306 while (nButton > BUTTON_COLS) {
307 *nLocationY += BUTTON_SIZE;
308 nButton -= BUTTON_COLS;
311 while (nButton > 0) {
312 *nLocationX += BUTTON_SIZE - 1;
313 nButton--;
316 /**********************************************************************/
318 /* SkipWord & SkipSpaces: utility functions for getNicenedString */
319 char *SkipWord(char *Text) {
320 char *Result = Text;
322 while ((*Result != ' ') && (*Result != '\t') &&
323 (*Result != '\n') && (*Result != 0x00))
324 Result++;
326 return Result;
329 char *SkipSpaces(char *Text) {
330 char *Result = Text;
332 while ((*Result == ' ') || (*Result == '\t') || (*Result == '\n'))
333 Result++;
335 return Result;
338 /***********************************************************************
339 * getNicenedString
341 * nicen the parsed command from the .wmbutton config file
342 * - cut if too long
343 * - remove parameters, whitespace and the '&'...
344 ***********************************************************************/
345 char *getNicenedString(char *old, int andAddSeparator)
347 char *WorkStr, *WorkStrEnd, *StartPtr, *EndPtr, *RetStr;
349 if (!old) {
350 if (andAddSeparator)
351 return strdup("-- | ");
352 else
353 return strdup("--");
356 RetStr = malloc(strlen(old) + 3 + 1); /* 3 for Seperator */
357 *RetStr = 0x00;
359 WorkStr = strdup(old);
360 WorkStrEnd = strchr(WorkStr, 0x00);
361 StartPtr = WorkStr;
363 while (StartPtr < WorkStrEnd) {
364 StartPtr = SkipSpaces(StartPtr);
365 EndPtr = SkipWord(StartPtr);
366 *EndPtr = 0x00;
368 if ((*StartPtr == '&') || (*StartPtr == '-'))
369 break;
371 strcat(RetStr, StartPtr);
372 strcat(RetStr, " ");
373 StartPtr = EndPtr + 1;
376 free(WorkStr);
378 if (andAddSeparator)
379 strcat(RetStr, "| ");
381 return RetStr;
384 /***********************************************************************
385 * getButtonAppNames
387 *returns the 1..3 application names / commands to be shown in tooltip
388 ***********************************************************************/
389 char *getButtonAppNames(int nButton)
391 char *tmp1, *tmp2, *str = NULL;
393 if (!( nButton < 0 || nButton > 9 )) {
395 /* FIXME: _Might_ overflow, but it's unlikely.
396 * Perhaps one should fix this sometime ;) */
397 str = (char*) calloc (sizeof(char), BUFFER_SIZE);
399 tmp1 = Parse(nButton + LMASK);
400 tmp2 = getNicenedString(tmp1, 1);
401 strcat(str, tmp2);
402 free(tmp1);
403 free(tmp2);
405 tmp1 = Parse(nButton + MMASK);
406 tmp2 = getNicenedString(tmp1, 1);
407 strcat(str, tmp2);
408 free(tmp1);
409 free(tmp2);
411 tmp1 = Parse(nButton + RMASK);
412 tmp2 = getNicenedString(tmp1, 0);
413 strcat(str, tmp2);
414 free(tmp1);
415 free(tmp2);
418 return str;
420 /**********************************************************************/
423 int hasTooltipSupport(void)
425 return !Config.bTooltipDisable;
427 /**********************************************************************/
429 void showTooltip (int nButton, int nMouseX, int nMouseY)
431 Pixmap pixmap, mask;
432 int nMainWinX, nMainWinY;
433 int nButtonX = 0, nButtonY = 0, nButtonWidth = 0, nButtonHeight = 0;
434 int nTextY, nX, nY, nWidth, nHeight, nSide;
435 char* szText;
436 extern struct Config_t Config;
437 extern Window iconwin;
438 extern Pixel bg_pixel, fg_pixel;
439 extern Display *display;
440 extern GC gc;
442 if (Config.bTooltipDisable || nButton == -1)
443 return;
445 if (_bTooltip)
446 hideTooltip();
448 if (Config.Verbose)
449 fprintf(stdout,
450 "[%8ld] showing tooltip for button %d at %d, %d\n",
451 currentTimeMillis(), nButton, nMouseX, nMouseY);
453 szText = getButtonAppNames(nButton);
454 if(!szText)
455 return;
457 _bTooltip = 1;
459 nWidth = XTextWidth(_fTooltip, szText, strlen(szText)) + 16;
460 nHeight = _nFontHeight + 4;
461 if (nHeight < 16)
462 nHeight = 16;
464 if (nWidth < nHeight)
465 nWidth = nHeight;
467 if (Config.Verbose)
468 fprintf(stdout, "[%8ld] tooltip size: %d, %d\n",
469 currentTimeMillis(), nWidth, nHeight);
471 getWindowOrigin(iconwin, &nMainWinX, &nMainWinY);
472 getButtonLocation(nButton, &nButtonX, &nButtonY);
473 nButtonX += nMainWinX;
474 nButtonY += nMainWinY;
475 nButtonWidth = BUTTON_SIZE;
476 nButtonHeight = BUTTON_SIZE;
478 if (nButtonX + nWidth > _nScreenWidth) {
479 nSide = TOOLTIP_RIGHT;
480 nX = nButtonX - nWidth + nButtonWidth / 2;
481 if (nX < 0)
482 nX = 0;
483 } else {
484 nSide = TOOLTIP_LEFT;
485 nX = nButtonX + nButtonWidth / 2;
488 if (nX + nWidth > _nScreenWidth)
489 nX = _nScreenWidth - nWidth;
491 if (nButtonY - (nHeight + TOOLTIP_SPACE) < 0) {
492 nSide |= TOOLTIP_TOP;
493 nY = nButtonY + nButtonHeight - 1;
494 nTextY = TOOLTIP_SPACE;
495 } else {
496 nSide |= TOOLTIP_BOTTOM;
497 nY = nButtonY - (nHeight + TOOLTIP_SPACE);
498 nTextY = 0;
501 pixmap = createTooltipPixmap(nWidth, nHeight, nSide, &mask);
503 XSetForeground(display, gc, Config.bTooltipSwapColors ? fg_pixel : bg_pixel);
504 XSetFont(display, gc, _fTooltip->fid);
505 XDrawString(display, pixmap, gc,
506 8, nTextY + (nHeight - _nFontHeight) / 2 + _nFontY,
507 szText, strlen(szText));
509 XSetWindowBackgroundPixmap(display, _wTooltip, pixmap);
511 XResizeWindow(display, _wTooltip, nWidth, nHeight + TOOLTIP_SPACE);
512 XShapeCombineMask(display, _wTooltip, ShapeBounding, 0, 0, mask, ShapeSet);
513 XFreePixmap(display, mask);
514 XMoveWindow(display, _wTooltip, nX, nY);
515 XMapRaised(display, _wTooltip);
516 XFreePixmap(display, pixmap);
518 free(szText);
520 /**********************************************************************/
522 void hideTooltip(void)
524 extern struct Config_t Config;
525 extern Display *display;
527 if (Config.bTooltipDisable)
528 return;
530 if (_bTooltip) {
531 if (Config.Verbose)
532 fprintf(stdout, "[%8ld] hiding tooltip\n", currentTimeMillis());
534 XUnmapWindow(display, _wTooltip);
535 _bTooltip = 0;
538 /**********************************************************************/
540 int hasTooltip(void)
542 if (Config.bTooltipDisable)
543 return 0;
545 return _bTooltip;
547 /**********************************************************************/
549 void initTooltip(void)
551 XSetWindowAttributes attribs;
552 unsigned long vmask;
553 extern Display *display;
554 extern char *app_name;
555 extern int screen;
556 extern Window rootwin, win;
558 if (Config.bTooltipDisable) {
559 if (Config.Verbose)
560 fprintf(stdout, "[%8ld] initializing tooltips (disabled)\n",
561 currentTimeMillis());
563 return;
565 if (Config.Verbose)
566 fprintf(stdout, "[%8ld] initializing tooltips\n", currentTimeMillis());
568 _fTooltip = XLoadQueryFont(display, Config.szTooltipFont);
569 if (!_fTooltip) {
570 fprintf(stderr, "%s: couldn't allocate font '%s'.\n", app_name, Config.szTooltipFont);
571 if (!strcmp(Config.szTooltipFont, TOOLTIP_FONT))
572 fprintf(stderr, "%s: Use option -F <font>\n", app_name);
573 exit(-1);
576 _nFontHeight = _fTooltip->ascent + _fTooltip->descent;
577 _nFontY = _fTooltip->ascent;
578 _nScreenWidth = WidthOfScreen(ScreenOfDisplay(display, screen));
579 _nScreenHeight = HeightOfScreen(ScreenOfDisplay(display, screen));
580 if (Config.Verbose)
581 fprintf(stdout, "[%8ld] configuring tooltip font:\n" \
582 "[%8ld] - '%s'\n" \
583 "[%8ld] - font-height= %d, font-ascent= %d\n" \
584 "[%8ld] configuring screen size: %dx%d\n",
585 currentTimeMillis(),
586 currentTimeMillis(), Config.szTooltipFont,
587 currentTimeMillis(), _nFontHeight, _nFontY,
588 currentTimeMillis(), _nScreenWidth, _nScreenHeight);
590 vmask = CWSaveUnder | CWOverrideRedirect | CWBorderPixel;
591 attribs.save_under = True;
592 attribs.override_redirect = True;
593 attribs.border_pixel = 0;
594 _wTooltip = XCreateWindow(display, rootwin, 1, 1, 10, 10, 1,
595 CopyFromParent, CopyFromParent,
596 CopyFromParent, vmask, &attribs);
598 if (win == 0) {
599 fprintf(stderr, "Cannot create tooltip window.\n");
600 exit(-1);
603 /**********************************************************************/
605 void destroyTooltip(void)
607 extern Display *display;
609 if (Config.bTooltipDisable)
610 return;
612 if (_gcMono) {
613 XFreeGC(display, _gcMono);
614 _gcMono = 0;
617 XDestroyWindow(display, _wTooltip);
619 /**********************************************************************/
621 void drawTooltipBalloon(Pixmap pix, GC gc, int x, int y, int w, int h, int side)
623 extern Display *display;
624 int rad = h * 3 / 10;
625 XPoint pt[3];
627 XFillArc(display, pix, gc, x, y, rad, rad, 90 * 64, 90 * 64);
628 XFillArc(display, pix, gc, x, y + h - 1 - rad, rad, rad, 180 * 64, 90 * 64);
630 XFillArc(display, pix, gc, x + w - 1 - rad, y, rad, rad, 0 * 64, 90 * 64);
631 XFillArc(display, pix, gc, x + w - 1 - rad, y + h - 1 - rad, rad, rad, 270 * 64, 90 * 64);
633 XFillRectangle(display, pix, gc, x, y + rad / 2, w, h - rad);
634 XFillRectangle(display, pix, gc, x + rad / 2, y, w - rad, h);
636 if (side & TOOLTIP_BOTTOM) {
637 pt[0].y = y + h - 1;
638 pt[1].y = y + h - 1 + TOOLTIP_SPACE;
639 pt[2].y = y + h - 1;
640 } else {
641 pt[0].y = y;
642 pt[1].y = y-TOOLTIP_SPACE;
643 pt[2].y = y;
646 if (side & TOOLTIP_RIGHT) {
647 pt[0].x = x + w - h + 2 * h / 16;
648 pt[1].x = x + w - h + 11 * h / 16;
649 pt[2].x = x + w - h + 7 * h / 16;
650 } else {
651 pt[0].x = x + h - 2 * h /16;
652 pt[1].x = x + h - 11 * h /16;
653 pt[2].x = x + h - 7 * h /16;
656 XFillPolygon(display, pix, gc, pt, 3, Convex, CoordModeOrigin);
658 /**********************************************************************/
660 Pixmap createTooltipPixmap(int width, int height, int side, Pixmap *mask)
662 extern Display *display;
663 extern GC gc;
664 extern Pixel bg_pixel, fg_pixel;
665 extern int depth;
666 extern Window rootwin;
667 Pixmap bitmap, pixmap;
668 int x, y;
670 bitmap = XCreatePixmap(display, rootwin,
671 width+TOOLTIP_SPACE, height+TOOLTIP_SPACE, 1);
673 if (!_gcMono)
674 _gcMono = XCreateGC(display, bitmap, 0, NULL);
676 XSetForeground(display, _gcMono, 0);
677 XFillRectangle(display, bitmap, _gcMono, 0, 0,
678 width+TOOLTIP_SPACE, height+TOOLTIP_SPACE);
680 pixmap = XCreatePixmap(display, rootwin, width+TOOLTIP_SPACE,
681 height+TOOLTIP_SPACE, depth);
682 XSetForeground(display, gc, Config.bTooltipSwapColors ? fg_pixel : bg_pixel);
683 XFillRectangle(display, pixmap, gc, 0, 0, width+TOOLTIP_SPACE,
684 height+TOOLTIP_SPACE);
686 if (side & TOOLTIP_BOTTOM)
687 y = 0;
688 else
689 y = TOOLTIP_SPACE;
691 x = 0;
693 XSetForeground(display, _gcMono, 1);
694 drawTooltipBalloon(bitmap, _gcMono, x, y, width, height, side);
695 XSetForeground(display, gc, Config.bTooltipSwapColors ? bg_pixel : fg_pixel);
696 drawTooltipBalloon(pixmap, gc, x+1, y+1, width-2, height-2, side);
698 *mask = bitmap;
700 return pixmap;
702 /***********************************************************************/
705 /***********************************************************************
706 * flush_expose
708 * Everyone else has one of these... Can't hurt to throw it in.
709 ***********************************************************************/
710 int flush_expose(Window w)
712 extern Display *display;
713 XEvent dummy;
714 int i = 0;
716 while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
717 i++;
719 return i;
721 /***********************************************************************/