]> icculus.org git repositories - mikachu/openbox.git/blob - src/Screen.cc
that segfaulted. oops. added a workaround so setImageDither doesnt reconfig when...
[mikachu/openbox.git] / src / Screen.cc
1 // Screen.cc for Openbox
2 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
3 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22
23 // stupid macros needed to access some functions in version 2 of the GNU C
24 // library
25 #ifndef   _GNU_SOURCE
26 #define   _GNU_SOURCE
27 #endif // _GNU_SOURCE
28
29 #ifdef    HAVE_CONFIG_H
30 #  include "../config.h"
31 #endif // HAVE_CONFIG_H
32
33 #include <X11/Xatom.h>
34 #include <X11/keysym.h>
35
36 #include "i18n.h"
37 #include "openbox.h"
38 #include "Clientmenu.h"
39 #include "Iconmenu.h"
40 #include "Image.h"
41 #include "Screen.h"
42
43 #ifdef    SLIT
44 #include "Slit.h"
45 #endif // SLIT
46
47 #include "Rootmenu.h"
48 #include "Toolbar.h"
49 #include "Window.h"
50 #include "Workspace.h"
51 #include "Workspacemenu.h"
52
53 #ifdef    HAVE_STDLIB_H
54 #  include <stdlib.h>
55 #endif // HAVE_STDLIB_H
56
57 #ifdef    HAVE_STRING_H
58 #  include <string.h>
59 #endif // HAVE_STRING_H
60
61 #ifdef    HAVE_SYS_TYPES_H
62 #  include <sys/types.h>
63 #endif // HAVE_SYS_TYPES_H
64
65 #ifdef    HAVE_CTYPE_H
66 #  include <ctype.h>
67 #endif // HAVE_CTYPE_H
68
69 #ifdef    HAVE_DIRENT_H
70 #  include <dirent.h>
71 #endif // HAVE_DIRENT_H
72
73 #ifdef    HAVE_LOCALE_H
74 #  include <locale.h>
75 #endif // HAVE_LOCALE_H
76
77 #ifdef    HAVE_UNISTD_H
78 #  include <sys/types.h>
79 #  include <unistd.h>
80 #endif // HAVE_UNISTD_H
81
82 #ifdef    HAVE_SYS_STAT_H
83 #  include <sys/stat.h>
84 #endif // HAVE_SYS_STAT_H
85
86 #ifdef    HAVE_STDARG_H
87 #  include <stdarg.h>
88 #endif // HAVE_STDARG_H
89
90 #ifndef    HAVE_SNPRINTF
91 #  include "bsd-snprintf.h"
92 #endif // !HAVE_SNPRINTF
93
94 #ifndef   MAXPATHLEN
95 #define   MAXPATHLEN 255
96 #endif // MAXPATHLEN
97
98 #ifndef   FONT_ELEMENT_SIZE
99 #define   FONT_ELEMENT_SIZE 50
100 #endif // FONT_ELEMENT_SIZE
101
102 #include <strstream>
103 #include <string>
104 #include <algorithm>
105
106 static Bool running = True;
107
108 static int anotherWMRunning(Display *display, XErrorEvent *) {
109   fprintf(stderr, i18n->getMessage(ScreenSet, ScreenAnotherWMRunning,
110      "BScreen::BScreen: an error occured while querying the X server.\n"
111              "  another window manager already running on display %s.\n"),
112           DisplayString(display));
113
114   running = False;
115
116   return(-1);
117 }
118
119 struct dcmp {
120   bool operator()(const char *one, const char *two) const {
121     return (strcmp(one, two) < 0) ? True : False;
122   }
123 };
124
125 #ifndef    HAVE_STRCASESTR
126 static const char * strcasestr(const char *str, const char *ptn) {
127   const char *s2, *p2;
128   for( ; *str; str++) {
129     for(s2=str,p2=ptn; ; s2++,p2++) {
130       if (!*p2) return str;
131       if (toupper(*s2) != toupper(*p2)) break;
132     }
133   }
134   return NULL;
135 }
136 #endif // HAVE_STRCASESTR
137
138 static const char *getFontElement(const char *pattern, char *buf, int bufsiz, ...) {
139   const char *p, *v;
140   char *p2;
141   va_list va;
142
143   va_start(va, bufsiz);
144   buf[bufsiz-1] = 0;
145   buf[bufsiz-2] = '*';
146   while((v = va_arg(va, char *)) != NULL) {
147     p = strcasestr(pattern, v);
148     if (p) {
149       strncpy(buf, p+1, bufsiz-2);
150       p2 = strchr(buf, '-');
151       if (p2) *p2=0;
152       va_end(va);
153       return p;
154     }
155   }
156   va_end(va);
157   strncpy(buf, "*", bufsiz);
158   return NULL;
159 }
160
161 static const char *getFontSize(const char *pattern, int *size) {
162   const char *p;
163   const char *p2=NULL;
164   int n=0;
165
166   for (p=pattern; 1; p++) {
167     if (!*p) {
168       if (p2!=NULL && n>1 && n<72) {
169         *size = n; return p2+1;
170       } else {
171         *size = 16; return NULL;
172       }
173     } else if (*p=='-') {
174       if (n>1 && n<72 && p2!=NULL) {
175         *size = n;
176         return p2+1;
177       }
178       p2=p; n=0;
179     } else if (*p>='0' && *p<='9' && p2!=NULL) {
180       n *= 10;
181       n += *p-'0';
182     } else {
183       p2=NULL; n=0;
184     }
185   }
186 }
187
188
189 BScreen::BScreen(Openbox &ob, int scrn, Resource &conf) : ScreenInfo(ob, scrn),
190   openbox(ob), config(conf)
191 {
192   event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
193                SubstructureRedirectMask | KeyPressMask | KeyReleaseMask |
194                ButtonPressMask | ButtonReleaseMask;
195
196   XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
197   XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), event_mask);
198   XSync(getBaseDisplay().getXDisplay(), False);
199   XSetErrorHandler((XErrorHandler) old);
200
201   managed = running;
202   if (! managed) return;
203
204   fprintf(stderr, i18n->getMessage(ScreenSet, ScreenManagingScreen,
205                      "BScreen::BScreen: managing screen %d "
206                      "using visual 0x%lx, depth %d\n"),
207           getScreenNumber(), XVisualIDFromVisual(getVisual()),
208           getDepth());
209
210   rootmenu = 0;
211
212   resource.mstyle.t_fontset = resource.mstyle.f_fontset =
213     resource.tstyle.fontset = resource.wstyle.fontset = NULL;
214   resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font =
215     resource.wstyle.font = NULL;
216
217 #ifdef   SLIT
218   slit = NULL;
219 #endif // SLIT
220   toolbar = NULL;
221
222 #ifdef    HAVE_GETPID
223   pid_t bpid = getpid();
224
225   XChangeProperty(getBaseDisplay().getXDisplay(), getRootWindow(),
226                   openbox.getOpenboxPidAtom(), XA_CARDINAL,
227                   sizeof(pid_t) * 8, PropModeReplace,
228                   (unsigned char *) &bpid, 1);
229 #endif // HAVE_GETPID
230
231   XDefineCursor(getBaseDisplay().getXDisplay(), getRootWindow(),
232                 openbox.getSessionCursor());
233
234   workspaceNames = new LinkedList<char>;
235   workspacesList = new LinkedList<Workspace>;
236   rootmenuList = new LinkedList<Rootmenu>;
237   netizenList = new LinkedList<Netizen>;
238   iconList = new LinkedList<OpenboxWindow>;
239
240   image_control =
241     new BImageControl(openbox, *this, True, openbox.getColorsPerChannel(),
242                       openbox.getCacheLife(), openbox.getCacheMax());
243   image_control->installRootColormap();
244   root_colormap_installed = True;
245
246   image_control->setDither(resource.image_dither);
247
248   load();       // load config options from Resources
249   LoadStyle();
250
251   XGCValues gcv;
252   unsigned long gc_value_mask = GCForeground;
253   if (! i18n->multibyte()) gc_value_mask |= GCFont;
254
255   gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(),
256                               getScreenNumber())
257                  ^ BlackPixel(getBaseDisplay().getXDisplay(),
258                               getScreenNumber());
259   gcv.function = GXxor;
260   gcv.subwindow_mode = IncludeInferiors;
261   opGC = XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
262                    GCForeground | GCFunction | GCSubwindowMode, &gcv);
263
264   gcv.foreground = resource.wstyle.l_text_focus.getPixel();
265   if (resource.wstyle.font)
266     gcv.font = resource.wstyle.font->fid;
267   resource.wstyle.l_text_focus_gc =
268     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
269               gc_value_mask, &gcv);
270
271   gcv.foreground = resource.wstyle.l_text_unfocus.getPixel();
272   if (resource.wstyle.font)
273     gcv.font = resource.wstyle.font->fid;
274   resource.wstyle.l_text_unfocus_gc =
275     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
276               gc_value_mask, &gcv);
277
278   gcv.foreground = resource.wstyle.b_pic_focus.getPixel();
279   resource.wstyle.b_pic_focus_gc =
280     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
281               GCForeground, &gcv);
282
283   gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel();
284   resource.wstyle.b_pic_unfocus_gc =
285     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
286               GCForeground, &gcv);
287
288   gcv.foreground = resource.mstyle.t_text.getPixel();
289   if (resource.mstyle.t_font)
290     gcv.font = resource.mstyle.t_font->fid;
291   resource.mstyle.t_text_gc =
292     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
293               gc_value_mask, &gcv);
294
295   gcv.foreground = resource.mstyle.f_text.getPixel();
296   if (resource.mstyle.f_font)
297     gcv.font = resource.mstyle.f_font->fid;
298   resource.mstyle.f_text_gc =
299     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
300               gc_value_mask, &gcv);
301
302   gcv.foreground = resource.mstyle.h_text.getPixel();
303   resource.mstyle.h_text_gc =
304     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
305               gc_value_mask, &gcv);
306
307   gcv.foreground = resource.mstyle.d_text.getPixel();
308   resource.mstyle.d_text_gc =
309     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
310               gc_value_mask, &gcv);
311
312   gcv.foreground = resource.mstyle.hilite.getColor()->getPixel();
313   resource.mstyle.hilite_gc =
314     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
315               gc_value_mask, &gcv);
316
317   gcv.foreground = resource.tstyle.l_text.getPixel();
318   if (resource.tstyle.font)
319     gcv.font = resource.tstyle.font->fid;
320   resource.tstyle.l_text_gc =
321     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
322               gc_value_mask, &gcv);
323
324   gcv.foreground = resource.tstyle.w_text.getPixel();
325   resource.tstyle.w_text_gc =
326     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
327               gc_value_mask, &gcv);
328
329   gcv.foreground = resource.tstyle.c_text.getPixel();
330   resource.tstyle.c_text_gc =
331     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
332               gc_value_mask, &gcv);
333
334   gcv.foreground = resource.tstyle.b_pic.getPixel();
335   resource.tstyle.b_pic_gc =
336     XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(),
337               gc_value_mask, &gcv);
338
339   const char *s =  i18n->getMessage(ScreenSet, ScreenPositionLength,
340                                     "0: 0000 x 0: 0000");
341   int l = strlen(s);
342
343   if (i18n->multibyte()) {
344     XRectangle ink, logical;
345     XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
346     geom_w = logical.width;
347
348     geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
349   } else {
350     geom_h = resource.wstyle.font->ascent +
351              resource.wstyle.font->descent;
352
353     geom_w = XTextWidth(resource.wstyle.font, s, l);
354   }
355
356   geom_w += (resource.bevel_width * 2);
357   geom_h += (resource.bevel_width * 2);
358
359   XSetWindowAttributes attrib;
360   unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder;
361   attrib.border_pixel = getBorderColor()->getPixel();
362   attrib.colormap = getColormap();
363   attrib.save_under = True;
364
365   geom_window =
366     XCreateWindow(getBaseDisplay().getXDisplay(), getRootWindow(),
367                   0, 0, geom_w, geom_h, resource.border_width, getDepth(),
368                   InputOutput, getVisual(), mask, &attrib);
369   geom_visible = False;
370
371   if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) {
372     if (resource.wstyle.t_focus.getTexture() ==
373                                       (BImage_Flat | BImage_Solid)) {
374       geom_pixmap = None;
375       XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
376                            resource.wstyle.t_focus.getColor()->getPixel());
377     } else {
378       geom_pixmap = image_control->renderImage(geom_w, geom_h,
379                                                &resource.wstyle.t_focus);
380       XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
381                                  geom_window, geom_pixmap);
382     }
383   } else {
384     if (resource.wstyle.l_focus.getTexture() ==
385                                       (BImage_Flat | BImage_Solid)) {
386       geom_pixmap = None;
387       XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
388                            resource.wstyle.l_focus.getColor()->getPixel());
389     } else {
390       geom_pixmap = image_control->renderImage(geom_w, geom_h,
391                                                &resource.wstyle.l_focus);
392       XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
393                                  geom_window, geom_pixmap);
394     }
395   }
396
397   workspacemenu = new Workspacemenu(*this);
398   iconmenu = new Iconmenu(*this);
399   configmenu = new Configmenu(*this);
400
401   Workspace *wkspc = NULL;
402   if (resource.workspaces != 0) {
403     for (int i = 0; i < resource.workspaces; ++i) {
404       wkspc = new Workspace(*this, workspacesList->count());
405       workspacesList->insert(wkspc);
406       saveWorkspaceNames();
407       workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
408     }
409   } else {
410     wkspc = new Workspace(*this, workspacesList->count());
411     workspacesList->insert(wkspc);
412     saveWorkspaceNames();
413     workspacemenu->insert(wkspc->getName(), wkspc->getMenu());
414   }
415
416   workspacemenu->insert(i18n->getMessage(IconSet, IconIcons, "Icons"),
417                         iconmenu);
418   workspacemenu->update();
419
420   current_workspace = workspacesList->first();
421   workspacemenu->setItemSelected(2, True);
422
423   toolbar = new Toolbar(*this, config);
424
425 #ifdef    SLIT
426   slit = new Slit(*this, config);
427 #endif // SLIT
428
429   InitMenu();
430
431   raiseWindows(0, 0);
432   rootmenu->update();
433
434   changeWorkspaceID(0);
435
436   int i;
437   unsigned int nchild;
438   Window r, p, *children;
439   XQueryTree(getBaseDisplay().getXDisplay(), getRootWindow(), &r, &p,
440              &children, &nchild);
441
442   // preen the window list of all icon windows... for better dockapp support
443   for (i = 0; i < (int) nchild; i++) {
444     if (children[i] == None) continue;
445
446     XWMHints *wmhints = XGetWMHints(getBaseDisplay().getXDisplay(),
447                                     children[i]);
448
449     if (wmhints) {
450       if ((wmhints->flags & IconWindowHint) &&
451           (wmhints->icon_window != children[i]))
452         for (int j = 0; j < (int) nchild; j++)
453           if (children[j] == wmhints->icon_window) {
454             children[j] = None;
455
456             break;
457           }
458
459       XFree(wmhints);
460     }
461   }
462
463   // manage shown windows
464   for (i = 0; i < (int) nchild; ++i) {
465     if (children[i] == None || (! openbox.validateWindow(children[i])))
466       continue;
467
468     XWindowAttributes attrib;
469     if (XGetWindowAttributes(getBaseDisplay().getXDisplay(), children[i],
470                              &attrib)) {
471       if (attrib.override_redirect) continue;
472
473       if (attrib.map_state != IsUnmapped) {
474         new OpenboxWindow(openbox, children[i], this);
475
476         OpenboxWindow *win = openbox.searchWindow(children[i]);
477         if (win) {
478           XMapRequestEvent mre;
479           mre.window = children[i];
480           win->restoreAttributes();
481           win->mapRequestEvent(&mre);
482         }
483       }
484     }
485   }
486
487   if (! resource.sloppy_focus)
488     XSetInputFocus(getBaseDisplay().getXDisplay(), toolbar->getWindowID(),
489                    RevertToParent, CurrentTime);
490
491   XFree(children);
492   XFlush(getBaseDisplay().getXDisplay());
493 }
494
495
496 BScreen::~BScreen(void) {
497   if (! managed) return;
498
499   if (geom_pixmap != None)
500     image_control->removeImage(geom_pixmap);
501
502   if (geom_window != None)
503     XDestroyWindow(getBaseDisplay().getXDisplay(), geom_window);
504
505   removeWorkspaceNames();
506
507   while (workspacesList->count())
508     delete workspacesList->remove(0);
509
510   while (rootmenuList->count())
511     rootmenuList->remove(0);
512
513   while (iconList->count())
514     delete iconList->remove(0);
515
516   while (netizenList->count())
517     delete netizenList->remove(0);
518
519 #ifdef    HAVE_STRFTIME
520   if (resource.strftime_format)
521     delete [] resource.strftime_format;
522 #endif // HAVE_STRFTIME
523
524   delete rootmenu;
525   delete workspacemenu;
526   delete iconmenu;
527   delete configmenu;
528
529 #ifdef    SLIT
530   delete slit;
531 #endif // SLIT
532
533   delete toolbar;
534   delete image_control;
535
536   delete workspacesList;
537   delete workspaceNames;
538   delete rootmenuList;
539   delete iconList;
540   delete netizenList;
541
542   if (resource.wstyle.fontset)
543     XFreeFontSet(getBaseDisplay().getXDisplay(), resource.wstyle.fontset);
544   if (resource.mstyle.t_fontset)
545     XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.t_fontset);
546   if (resource.mstyle.f_fontset)
547     XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.f_fontset);
548   if (resource.tstyle.fontset)
549     XFreeFontSet(getBaseDisplay().getXDisplay(), resource.tstyle.fontset);
550
551   if (resource.wstyle.font)
552     XFreeFont(getBaseDisplay().getXDisplay(), resource.wstyle.font);
553   if (resource.mstyle.t_font)
554     XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.t_font);
555   if (resource.mstyle.f_font)
556     XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.f_font);
557   if (resource.tstyle.font)
558     XFreeFont(getBaseDisplay().getXDisplay(), resource.tstyle.font);
559   if (resource.root_command != NULL)
560     delete [] resource.root_command;
561
562   XFreeGC(getBaseDisplay().getXDisplay(), opGC);
563
564   XFreeGC(getBaseDisplay().getXDisplay(),
565           resource.wstyle.l_text_focus_gc);
566   XFreeGC(getBaseDisplay().getXDisplay(),
567           resource.wstyle.l_text_unfocus_gc);
568   XFreeGC(getBaseDisplay().getXDisplay(),
569           resource.wstyle.b_pic_focus_gc);
570   XFreeGC(getBaseDisplay().getXDisplay(),
571           resource.wstyle.b_pic_unfocus_gc);
572
573   XFreeGC(getBaseDisplay().getXDisplay(),
574           resource.mstyle.t_text_gc);
575   XFreeGC(getBaseDisplay().getXDisplay(),
576           resource.mstyle.f_text_gc);
577   XFreeGC(getBaseDisplay().getXDisplay(),
578           resource.mstyle.h_text_gc);
579   XFreeGC(getBaseDisplay().getXDisplay(),
580           resource.mstyle.d_text_gc);
581   XFreeGC(getBaseDisplay().getXDisplay(),
582           resource.mstyle.hilite_gc);
583
584   XFreeGC(getBaseDisplay().getXDisplay(),
585           resource.tstyle.l_text_gc);
586   XFreeGC(getBaseDisplay().getXDisplay(),
587           resource.tstyle.w_text_gc);
588   XFreeGC(getBaseDisplay().getXDisplay(),
589           resource.tstyle.c_text_gc);
590   XFreeGC(getBaseDisplay().getXDisplay(),
591           resource.tstyle.b_pic_gc);
592 }
593
594 void BScreen::readDatabaseTexture(const char *rname, const char *rclass,
595                                   BTexture *texture,
596                                   unsigned long default_pixel)
597 {
598   std::string s;
599   
600   if (resource.styleconfig.getValue(rname, rclass, s))
601     image_control->parseTexture(texture, s.c_str());
602   else
603     texture->setTexture(BImage_Solid | BImage_Flat);
604
605   if (texture->getTexture() & BImage_Solid) {
606     int clen = strlen(rclass) + 32, nlen = strlen(rname) + 32;
607
608     char *colorclass = new char[clen], *colorname = new char[nlen];
609
610     sprintf(colorclass, "%s.Color", rclass);
611     sprintf(colorname,  "%s.color", rname);
612
613     readDatabaseColor(colorname, colorclass, texture->getColor(),
614                       default_pixel);
615
616 #ifdef    INTERLACE
617     sprintf(colorclass, "%s.ColorTo", rclass);
618     sprintf(colorname,  "%s.colorTo", rname);
619
620     readDatabaseColor(colorname, colorclass, texture->getColorTo(),
621                       default_pixel);
622 #endif // INTERLACE
623
624     delete [] colorclass;
625     delete [] colorname;
626
627     if ((! texture->getColor()->isAllocated()) ||
628         (texture->getTexture() & BImage_Flat))
629       return;
630
631     XColor xcol;
632
633     xcol.red = (unsigned int) (texture->getColor()->getRed() +
634                                (texture->getColor()->getRed() >> 1));
635     if (xcol.red >= 0xff) xcol.red = 0xffff;
636     else xcol.red *= 0xff;
637     xcol.green = (unsigned int) (texture->getColor()->getGreen() +
638                                  (texture->getColor()->getGreen() >> 1));
639     if (xcol.green >= 0xff) xcol.green = 0xffff;
640     else xcol.green *= 0xff;
641     xcol.blue = (unsigned int) (texture->getColor()->getBlue() +
642                                 (texture->getColor()->getBlue() >> 1));
643     if (xcol.blue >= 0xff) xcol.blue = 0xffff;
644     else xcol.blue *= 0xff;
645
646     if (! XAllocColor(getBaseDisplay().getXDisplay(),
647                       getColormap(), &xcol))
648       xcol.pixel = 0;
649
650     texture->getHiColor()->setPixel(xcol.pixel);
651
652     xcol.red =
653       (unsigned int) ((texture->getColor()->getRed() >> 2) +
654                       (texture->getColor()->getRed() >> 1)) * 0xff;
655     xcol.green =
656       (unsigned int) ((texture->getColor()->getGreen() >> 2) +
657                       (texture->getColor()->getGreen() >> 1)) * 0xff;
658     xcol.blue =
659       (unsigned int) ((texture->getColor()->getBlue() >> 2) +
660                       (texture->getColor()->getBlue() >> 1)) * 0xff;
661
662     if (! XAllocColor(getBaseDisplay().getXDisplay(),
663                       getColormap(), &xcol))
664       xcol.pixel = 0;
665
666     texture->getLoColor()->setPixel(xcol.pixel);
667   } else if (texture->getTexture() & BImage_Gradient) {
668     int clen = strlen(rclass) + 10, nlen = strlen(rname) + 10;
669
670     char *colorclass = new char[clen], *colorname = new char[nlen],
671       *colortoclass = new char[clen], *colortoname = new char[nlen];
672
673     sprintf(colorclass, "%s.Color", rclass);
674     sprintf(colorname,  "%s.color", rname);
675
676     sprintf(colortoclass, "%s.ColorTo", rclass);
677     sprintf(colortoname,  "%s.colorTo", rname);
678
679     readDatabaseColor(colorname, colorclass, texture->getColor(),
680                       default_pixel);
681     readDatabaseColor(colortoname, colortoclass, texture->getColorTo(),
682                       default_pixel);
683
684     delete [] colorclass;
685     delete [] colorname;
686     delete [] colortoclass;
687     delete [] colortoname;
688   }
689 }
690
691
692 void BScreen::readDatabaseColor(const char *rname, const  char *rclass,
693                                 BColor *color, unsigned long default_pixel)
694 {
695   std::string s;
696   
697   if (resource.styleconfig.getValue(rname, rclass, s))
698     image_control->parseColor(color, s.c_str());
699   else {
700     // parsing with no color string just deallocates the color, if it has
701     // been previously allocated
702     image_control->parseColor(color);
703     color->setPixel(default_pixel);
704   }
705 }
706
707
708 void BScreen::readDatabaseFontSet(const char *rname, const char *rclass,
709                                   XFontSet *fontset) {
710   if (! fontset) return;
711
712   static char *defaultFont = "fixed";
713   bool load_default = false;
714   std::string s;
715
716   if (*fontset)
717     XFreeFontSet(getBaseDisplay().getXDisplay(), *fontset);
718
719   if (resource.styleconfig.getValue(rname, rclass, s)) {
720     if (! (*fontset = createFontSet(s.c_str())))
721       load_default = true;
722   } else
723     load_default = true;
724
725   if (load_default) {
726     *fontset = createFontSet(defaultFont);
727
728     if (! *fontset) {
729       fprintf(stderr, i18n->getMessage(ScreenSet, ScreenDefaultFontLoadFail,
730                        "BScreen::LoadStyle(): couldn't load default font.\n"));
731       exit(2);
732     }
733   }
734 }
735
736
737 void BScreen::readDatabaseFont(const char *rname, const char *rclass,
738                                XFontStruct **font) {
739   if (! font) return;
740
741   static char *defaultFont = "fixed";
742   bool load_default = false;
743   std::string s;
744
745   if (*font)
746     XFreeFont(getBaseDisplay().getXDisplay(), *font);
747
748   if (resource.styleconfig.getValue(rname, rclass, s)) {
749     if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(),
750                                 s.c_str())) == NULL) {
751       fprintf(stderr, i18n->getMessage(ScreenSet, ScreenFontLoadFail,
752                          "BScreen::LoadStyle(): couldn't load font '%s'\n"),
753               s.c_str());
754       load_default = true;
755     }
756   } else
757     load_default = true;
758
759   if (load_default) {
760     if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(),
761                                 defaultFont)) == NULL) {
762       fprintf(stderr, i18n->getMessage(ScreenSet, ScreenDefaultFontLoadFail,
763                  "BScreen::LoadStyle(): couldn't load default font.\n"));
764       exit(2);
765     }
766   }
767 }
768
769
770 XFontSet BScreen::createFontSet(const char *fontname) {
771   XFontSet fs;
772   char **missing, *def = "-";
773   int nmissing, pixel_size = 0, buf_size = 0;
774   char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];
775
776   fs = XCreateFontSet(getBaseDisplay().getXDisplay(),
777                       fontname, &missing, &nmissing, &def);
778   if (fs && (! nmissing)) return fs;
779
780 #ifdef    HAVE_SETLOCALE
781   if (! fs) {
782     if (nmissing) XFreeStringList(missing);
783
784     setlocale(LC_CTYPE, "C");
785     fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname,
786                         &missing, &nmissing, &def);
787     setlocale(LC_CTYPE, "");
788   }
789 #endif // HAVE_SETLOCALE
790
791   if (fs) {
792     XFontStruct **fontstructs;
793     char **fontnames;
794     XFontsOfFontSet(fs, &fontstructs, &fontnames);
795     fontname = fontnames[0];
796   }
797
798   getFontElement(fontname, weight, FONT_ELEMENT_SIZE,
799                  "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
800   getFontElement(fontname, slant, FONT_ELEMENT_SIZE,
801                  "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
802   getFontSize(fontname, &pixel_size);
803
804   if (! strcmp(weight, "*")) strncpy(weight, "medium", FONT_ELEMENT_SIZE);
805   if (! strcmp(slant, "*")) strncpy(slant, "r", FONT_ELEMENT_SIZE);
806   if (pixel_size < 3) pixel_size = 3;
807   else if (pixel_size > 97) pixel_size = 97;
808
809   buf_size = strlen(fontname) + (FONT_ELEMENT_SIZE * 2) + 64;
810   char *pattern2 = new char[buf_size];
811   snprintf(pattern2, buf_size - 1,
812            "%s,"
813            "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
814            "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
815            fontname, weight, slant, pixel_size, pixel_size);
816   fontname = pattern2;
817
818   if (nmissing) XFreeStringList(missing);
819   if (fs) XFreeFontSet(getBaseDisplay().getXDisplay(), fs);
820
821   fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname,
822                       &missing, &nmissing, &def);
823   delete [] pattern2;
824
825   return fs;
826 }
827
828
829 void BScreen::setSloppyFocus(bool b) {
830   resource.sloppy_focus = b;
831   std::ostrstream s;
832   s << "session.screen" << getScreenNumber() << ".focusModel" << ends;
833   config.setValue(s.str(),
834                   (resource.sloppy_focus ?
835                   (resource.auto_raise ? "AutoRaiseSloppyFocus" : "SloppyFocus")
836                   : "ClickToFocus"));
837   s.rdbuf()->freeze(0);
838 }
839
840
841 void BScreen::setAutoRaise(bool a) {
842   resource.auto_raise = a;
843   std::ostrstream s;
844   s << "session.screen" << getScreenNumber() << ".focusModel" << ends;
845   config.setValue(s.str(),
846                   (resource.sloppy_focus ?
847                   (resource.auto_raise ? "AutoRaiseSloppyFocus" : "SloppyFocus")
848                   : "ClickToFocus"));
849   s.rdbuf()->freeze(0);
850 }
851
852
853 void BScreen::setImageDither(bool d, bool reconfig) {
854   resource.image_dither = d;
855   std::ostrstream s;
856   s << "session.screen" << getScreenNumber() << ".imageDither" << ends;
857   config.setValue(s.str(), resource.image_dither);
858   s.rdbuf()->freeze(0);
859   if (reconfig)
860     openbox.reconfigure();
861 }
862
863
864 void BScreen::setOpaqueMove(bool o) {
865   resource.opaque_move = o;
866   std::ostrstream s;
867   s << "session.screen" << getScreenNumber() << ".opaqueMove" << ends;
868   config.setValue(s.str(), resource.opaque_move);
869   s.rdbuf()->freeze(0);
870 }
871
872
873 void BScreen::setFullMax(bool f) {
874   resource.full_max = f;
875   std::ostrstream s;
876   s << "session.screen" << getScreenNumber() << ".fullMaximization" << ends;
877   config.setValue(s.str(), resource.full_max);
878   s.rdbuf()->freeze(0);
879 }
880
881
882 void BScreen::setFocusNew(bool f) {
883   resource.focus_new = f;
884   std::ostrstream s;
885   s << "session.screen" << getScreenNumber() << ".focusNewWindows" << ends;
886   config.setValue(s.str(), resource.focus_new);
887   s.rdbuf()->freeze(0);
888 }
889
890
891 void BScreen::setFocusLast(bool f) {
892   resource.focus_last = f;
893   std::ostrstream s;
894   s << "session.screen" << getScreenNumber() << ".focusLastWindow" << ends;
895   config.setValue(s.str(), resource.focus_last);
896   s.rdbuf()->freeze(0);
897 }
898
899
900 void BScreen::setWindowZones(int z) {
901   resource.zones = z;
902   std::ostrstream s;
903   s << "session.screen" << getScreenNumber() << ".windowZones" << ends;
904   config.setValue(s.str(), resource.zones);
905   s.rdbuf()->freeze(0);
906 }
907
908
909 void BScreen::setWorkspaceCount(int w) {
910   resource.workspaces = w;
911   std::ostrstream s;
912   s << "session.screen" << getScreenNumber() << ".workspaces" << ends;
913   config.setValue(s.str(), resource.workspaces);
914   s.rdbuf()->freeze(0);
915 }
916
917
918 void BScreen::setPlacementPolicy(int p) {
919   resource.placement_policy = p;
920   std::ostrstream s;
921   s << "session.screen" << getScreenNumber() << ".windowPlacement" << ends;
922   const char *placement;
923   switch (resource.placement_policy) {
924   case CascadePlacement: placement = "CascadePlacement"; break;
925   case BestFitPlacement: placement = "BestFitPlacement"; break;
926   case ColSmartPlacement: placement = "ColSmartPlacement"; break;
927   default:
928   case RowSmartPlacement: placement = "RowSmartPlacement"; break;
929   }
930   config.setValue(s.str(), placement);
931   s.rdbuf()->freeze(0);
932 }
933
934
935 void BScreen::setEdgeSnapThreshold(int t) {
936   resource.edge_snap_threshold = t;
937   std::ostrstream s;
938   s << "session.screen" << getScreenNumber() << ".edgeSnapThreshold" << ends;
939   config.setValue(s.str(), resource.edge_snap_threshold);
940   s.rdbuf()->freeze(0);
941 }
942
943
944 void BScreen::setRowPlacementDirection(int d) {
945   resource.row_direction = d;
946   std::ostrstream s;
947   s << "session.screen" << getScreenNumber() << ".rowPlacementDirection" <<
948     ends;
949   config.setValue(s.str(),
950                   resource.row_direction == LeftRight ?
951                   "LeftToRight" : "RightToLeft");
952   s.rdbuf()->freeze(0);
953 }
954
955
956 void BScreen::setColPlacementDirection(int d) {
957   resource.col_direction = d;
958   std::ostrstream s;
959   s << "session.screen" << getScreenNumber() << ".colPlacementDirection" <<
960     ends;
961   config.setValue(s.str(),
962                   resource.col_direction == TopBottom ?
963                   "TopToBottom" : "BottomToTop");
964   s.rdbuf()->freeze(0);
965 }
966
967
968 void BScreen::setRootCommand(const char *cmd) {
969 if (resource.root_command != NULL)
970     delete [] resource.root_command;
971   if (cmd != NULL)
972     resource.root_command = bstrdup(cmd);
973   else
974     resource.root_command = NULL;
975   // this doesn't save to the Resources config because it can't be changed
976   // inside Openbox, and this way we dont add an empty command which would over-
977   // ride the styles command when none has been specified
978 }
979
980
981 #ifdef    HAVE_STRFTIME
982 void BScreen::setStrftimeFormat(const char *f) {
983   if (resource.strftime_format != NULL)
984     delete [] resource.strftime_format;
985
986   resource.strftime_format = bstrdup(f);
987   std::ostrstream s;
988   s << "session.screen" << getScreenNumber() << ".strftimeFormat" << ends;
989   config.setValue(s.str(), resource.strftime_format);
990   s.rdbuf()->freeze(0);
991 }
992
993 #else // !HAVE_STRFTIME
994 void BScreen::setDateFormat(int f) {
995   resource.date_format = f;
996   std::ostrstream s;
997   s << "session.screen" << getScreenNumber() << ".dateFormat" << ends;
998   config.setValue(s.str(), resource.date_format == B_EuropeanDate ?
999                   "European" : "American");
1000   s.rdbuf()->freeze(0);
1001 }
1002
1003 void BScreen::setClock24Hour(Bool c) {
1004   resource.clock24hour = c;
1005   std::ostrstream s;
1006   s << "session.screen" << getScreenNumber() << ".clockFormat" << ends;
1007   config.setValue(s.str(), resource.clock24hour ? 24 : 12);
1008   s.rdbuf()->freeze(0);
1009 }
1010 #endif // HAVE_STRFTIME
1011
1012 void BScreen::setHideToolbar(bool b) {
1013   resource.hide_toolbar = b;
1014   if (resource.hide_toolbar)
1015     getToolbar()->unMapToolbar();
1016   else
1017     getToolbar()->mapToolbar();
1018   std::ostrstream s;
1019   s << "session.screen" << getScreenNumber() << ".hideToolbar" << ends;
1020   config.setValue(s.str(), resource.hide_toolbar ? "True" : "False");
1021   s.rdbuf()->freeze(0);
1022 }
1023
1024 void BScreen::saveWorkspaceNames() {
1025   std::ostrstream rc, names;
1026
1027   for (int i = 0; i < resource.workspaces; i++) {
1028     Workspace *w = getWorkspace(i);
1029     if (w != NULL) {
1030       names << w->getName();
1031       if (i < resource.workspaces-1)
1032         names << ',';
1033     }
1034   }
1035   names << ends;
1036
1037   rc << "session.screen" << getScreenNumber() << ".workspaceNames" << ends;
1038   config.setValue(rc.str(), names.str());
1039   rc.rdbuf()->freeze(0);
1040   names.rdbuf()->freeze(0);
1041 }
1042
1043 void BScreen::save() {
1044   setSloppyFocus(resource.sloppy_focus);
1045   setAutoRaise(resource.auto_raise);
1046   setImageDither(resource.image_dither, false);
1047   setOpaqueMove(resource.opaque_move);
1048   setFullMax(resource.full_max);
1049   setFocusNew(resource.focus_new);
1050   setFocusLast(resource.focus_last);
1051   setWindowZones(resource.zones);
1052   setWorkspaceCount(resource.workspaces);
1053   setPlacementPolicy(resource.placement_policy);
1054   setEdgeSnapThreshold(resource.edge_snap_threshold);
1055   setRowPlacementDirection(resource.row_direction);
1056   setColPlacementDirection(resource.col_direction);
1057   setRootCommand(resource.root_command);
1058 #ifdef    HAVE_STRFTIME
1059   // it deletes the current value before setting the new one, so we have to
1060   // duplicate the current value.
1061   std::string s = resource.strftime_format;
1062   setStrftimeFormat(s.c_str()); 
1063 #else // !HAVE_STRFTIME
1064   setDateFormat(resource.date_format);
1065   setClock24Hour(resource.clock24hour);
1066 #endif // HAVE_STRFTIME
1067   setHideToolbar(resource.hide_toolbar);
1068 }
1069
1070 void BScreen::load() {
1071   std::ostrstream rscreen, rname, rclass;
1072   std::string s;
1073   bool b;
1074   long l;
1075   rscreen << "session.screen" << getScreenNumber() << '.' << ends;
1076
1077   rname << rscreen.str() << "hideToolbar" << ends;
1078   rclass << rscreen.str() << "HideToolbar" << ends;
1079   if (config.getValue(rname.str(), rclass.str(), b))
1080     resource.hide_toolbar = b;
1081   else
1082     resource.hide_toolbar = false;
1083   Toolbar *t = getToolbar();
1084   if (t != NULL) {
1085     if (resource.hide_toolbar)
1086       t->unMapToolbar();
1087     else
1088       t->mapToolbar();
1089   }
1090
1091   rname.seekp(0); rclass.seekp(0);
1092   rname << rscreen.str() << "fullMaximization" << ends;
1093   rclass << rscreen.str() << "FullMaximization" << ends;
1094   if (config.getValue(rname.str(), rclass.str(), b))
1095     resource.full_max = b;
1096   else
1097     resource.full_max = false;
1098
1099   rname.seekp(0); rclass.seekp(0);
1100   rname << rscreen.str() << "focusNewWindows" << ends;
1101   rclass << rscreen.str() << "FocusNewWindows" << ends;
1102   if (config.getValue(rname.str(), rclass.str(), b))
1103     resource.focus_new = b;
1104   else
1105     resource.focus_new = false;
1106
1107   rname.seekp(0); rclass.seekp(0);
1108   rname << rscreen.str() << "focusLastWindow" << ends;
1109   rclass << rscreen.str() << "FocusLastWindow" << ends;
1110   if (config.getValue(rname.str(), rclass.str(), b))
1111     resource.focus_last = b;
1112   else
1113     resource.focus_last = false;
1114
1115   rname.seekp(0); rclass.seekp(0);
1116   rname << rscreen.str() << "rowPlacementDirection" << ends;
1117   rclass << rscreen.str() << "RowPlacementDirection" << ends;
1118   if (config.getValue(rname.str(), rclass.str(), s)) {
1119     if (0 == strncasecmp(s.c_str(), "RightToLeft", s.length()))
1120       resource.row_direction = RightLeft;
1121     else if (0 == strncasecmp(s.c_str(), "LeftToRight", s.length()))
1122       resource.row_direction = LeftRight;
1123   } else
1124     resource.row_direction = LeftRight;
1125
1126   rname.seekp(0); rclass.seekp(0);
1127   rname << rscreen.str() << "colPlacementDirection" << ends;
1128   rclass << rscreen.str() << "ColPlacementDirection" << ends;
1129   if (config.getValue(rname.str(), rclass.str(), s)) {
1130     if (0 == strncasecmp(s.c_str(), "BottomToTop", s.length()))
1131       resource.col_direction = BottomTop;
1132     else if (0 == strncasecmp(s.c_str(), "TopToBottom", s.length()))
1133       resource.col_direction = TopBottom;
1134   } else
1135     resource.col_direction = TopBottom;
1136
1137   rname.seekp(0); rclass.seekp(0);
1138   rname << rscreen.str() << "workspaces" << ends;
1139   rclass << rscreen.str() << "Workspaces" << ends;
1140   if (config.getValue(rname.str(), rclass.str(), l))
1141     resource.workspaces = l;
1142   else
1143     resource.workspaces = 1;
1144
1145   removeWorkspaceNames();
1146   rname.seekp(0); rclass.seekp(0);
1147   rname << rscreen.str() << "workspaceNames" << ends;
1148   rclass << rscreen.str() << "WorkspaceNames" << ends;
1149   if (config.getValue(rname.str(), rclass.str(), s)) {
1150     std::string::const_iterator it = s.begin(), end = s.end();
1151     while(1) {
1152       std::string::const_iterator tmp = it;// current string.begin()
1153       it = std::find(tmp, end, ',');       // look for comma between tmp and end
1154       std::string name(tmp, it);           // name = s[tmp:it]
1155       addWorkspaceName(name.c_str());
1156       if (it == end)
1157         break;
1158       ++it;
1159     }
1160   }
1161   
1162   rname.seekp(0); rclass.seekp(0);
1163   rname << rscreen.str() << "focusModel" << ends;
1164   rclass << rscreen.str() << "FocusModel" << ends;
1165   if (config.getValue(rname.str(), rclass.str(), s)) {
1166     if (0 == strncasecmp(s.c_str(), "ClickToFocus", s.length())) {
1167       resource.auto_raise = false;
1168       resource.sloppy_focus = false;
1169     } else if (0 == strncasecmp(s.c_str(), "AutoRaiseSloppyFocus",
1170                                 s.length())) {
1171       resource.sloppy_focus = true;
1172       resource.auto_raise = true;
1173     } else if (0 == strncasecmp(s.c_str(), "SloppyFocus", s.length())) {
1174       resource.sloppy_focus = true;
1175       resource.auto_raise = false;
1176     }
1177   } else {
1178     resource.sloppy_focus = true;
1179     resource.auto_raise = false;
1180   }
1181
1182   rname.seekp(0); rclass.seekp(0);
1183   rname << rscreen.str() << "windowZones" << ends;
1184   rclass << rscreen.str() << "WindowZones" << ends;
1185   if (config.getValue(rname.str(), rclass.str(), l))
1186     resource.zones = (l == 1 || l == 2 || l == 4) ? l : 1;
1187   else
1188     resource.zones = 4;
1189
1190   rname.seekp(0); rclass.seekp(0);
1191   rname << rscreen.str() << "windowPlacement" << ends;
1192   rclass << rscreen.str() << "WindowPlacement" << ends;
1193   if (config.getValue(rname.str(), rclass.str(), s)) {
1194     if (0 == strncasecmp(s.c_str(), "RowSmartPlacement", s.length()))
1195       resource.placement_policy = RowSmartPlacement;
1196     else if (0 == strncasecmp(s.c_str(), "ColSmartPlacement", s.length()))
1197       resource.placement_policy = ColSmartPlacement;
1198     else if (0 == strncasecmp(s.c_str(), "BestFitPlacement", s.length()))
1199       resource.placement_policy = BestFitPlacement;
1200     else if (0 == strncasecmp(s.c_str(), "CascadePlacement", s.length()))
1201       resource.placement_policy = CascadePlacement;
1202   } else
1203     resource.placement_policy = CascadePlacement;
1204
1205 #ifdef    HAVE_STRFTIME
1206   rname.seekp(0); rclass.seekp(0);
1207   rname << rscreen.str() << "strftimeFormat" << ends;
1208   rclass << rscreen.str() << "StrftimeFormat" << ends;
1209
1210   if (resource.strftime_format != NULL)
1211     delete [] resource.strftime_format;
1212
1213   if (config.getValue(rname.str(), rclass.str(), s))
1214     resource.strftime_format = bstrdup(s.c_str());
1215   else
1216     resource.strftime_format = bstrdup("%I:%M %p");
1217 #else // !HAVE_STRFTIME
1218   rname.seekp(0); rclass.seekp(0);
1219   rname << rscreen.str() << "dateFormat" << ends;
1220   rclass << rscreen.str() << "DateFormat" << ends;
1221   if (config.getValue(rname.str(), rclass.str(), s)) {
1222     if (strncasecmp(s.c_str(), "European", s.length()))
1223       resource.date_format = B_EuropeanDate;
1224     else if (strncasecmp(s.c_str(), "American", s.length()))
1225       resource.date_format = B_AmericanDate;
1226   } else
1227     resource.date_format = B_AmericanDate;
1228
1229   rname.seekp(0); rclass.seekp(0);
1230   rname << rscreen.str() << "clockFormat" << ends;
1231   rclass << rscreen.str() << "ClockFormat" << ends;
1232   if (config.getValue(rname.str(), rclass.str(), l)) {
1233     if (clock == 24)
1234       resource.clock24hour = true;
1235     else if (clock == 12)
1236       resource.clock24hour =  false;
1237   } else
1238     resource.clock24hour =  false;
1239 #endif // HAVE_STRFTIME
1240
1241   rname.seekp(0); rclass.seekp(0);
1242   rname << rscreen.str() << "edgeSnapThreshold" << ends;
1243   rclass << rscreen.str() << "EdgeSnapThreshold" << ends;
1244   if (config.getValue(rname.str(), rclass.str(), l))
1245     resource.edge_snap_threshold = l;
1246   else
1247     resource.edge_snap_threshold = 4;
1248
1249   rname.seekp(0); rclass.seekp(0);
1250   rname << rscreen.str() << "imageDither" << ends;
1251   rclass << rscreen.str() << "ImageDither" << ends;
1252   if (config.getValue(rname.str(), rclass.str(), b))
1253     resource.image_dither = b;
1254   else
1255     resource.image_dither = true;
1256
1257   rname.seekp(0); rclass.seekp(0);
1258   rname << rscreen.str() << "rootCommand" << ends;
1259   rclass << rscreen.str() << "RootCommand" << ends;
1260
1261   if (resource.root_command != NULL)
1262     delete [] resource.root_command;
1263   
1264   if (config.getValue(rname.str(), rclass.str(), s))
1265     resource.root_command = bstrdup(s.c_str());
1266   else
1267     resource.root_command = NULL;
1268
1269   rname.seekp(0); rclass.seekp(0);
1270   rname << rscreen.str() << "opaqueMove" << ends;
1271   rclass << rscreen.str() << "OpaqueMove" << ends;
1272   if (config.getValue(rname.str(), rclass.str(), b))
1273     resource.opaque_move = b;
1274   else
1275     resource.opaque_move = false;
1276
1277   rscreen.rdbuf()->freeze(0);
1278   rname.rdbuf()->freeze(0);
1279   rclass.rdbuf()->freeze(0);
1280 }
1281
1282 void BScreen::reconfigure(void) {
1283   load();
1284   toolbar->load();
1285 #ifdef    SLIT
1286   slit->load();
1287 #endif // SLIT
1288   LoadStyle();
1289
1290   XGCValues gcv;
1291   unsigned long gc_value_mask = GCForeground;
1292   if (! i18n->multibyte()) gc_value_mask |= GCFont;
1293
1294   gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(),
1295                               getScreenNumber());
1296   gcv.function = GXinvert;
1297   gcv.subwindow_mode = IncludeInferiors;
1298   XChangeGC(getBaseDisplay().getXDisplay(), opGC,
1299             GCForeground | GCFunction | GCSubwindowMode, &gcv);
1300
1301   gcv.foreground = resource.wstyle.l_text_focus.getPixel();
1302   if (resource.wstyle.font)
1303     gcv.font = resource.wstyle.font->fid;
1304   XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_focus_gc,
1305             gc_value_mask, &gcv);
1306
1307   gcv.foreground = resource.wstyle.l_text_unfocus.getPixel();
1308   XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_unfocus_gc,
1309             gc_value_mask, &gcv);
1310
1311   gcv.foreground = resource.wstyle.b_pic_focus.getPixel();
1312   XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_focus_gc,
1313             GCForeground, &gcv);
1314
1315   gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel();
1316   XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_unfocus_gc,
1317             GCForeground, &gcv);
1318
1319   gcv.foreground = resource.mstyle.t_text.getPixel();
1320   if (resource.mstyle.t_font)
1321     gcv.font = resource.mstyle.t_font->fid;
1322   XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.t_text_gc,
1323             gc_value_mask, &gcv);
1324
1325   gcv.foreground = resource.mstyle.f_text.getPixel();
1326   if (resource.mstyle.f_font)
1327     gcv.font = resource.mstyle.f_font->fid;
1328   XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.f_text_gc,
1329             gc_value_mask, &gcv);
1330
1331   gcv.foreground = resource.mstyle.h_text.getPixel();
1332   XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.h_text_gc,
1333             gc_value_mask, &gcv);
1334
1335   gcv.foreground = resource.mstyle.d_text.getPixel();
1336   XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.d_text_gc,
1337             gc_value_mask, &gcv);
1338
1339   gcv.foreground = resource.mstyle.hilite.getColor()->getPixel();
1340   XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.hilite_gc,
1341             gc_value_mask, &gcv);
1342
1343   gcv.foreground = resource.tstyle.l_text.getPixel();
1344   if (resource.tstyle.font)
1345     gcv.font = resource.tstyle.font->fid;
1346   XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.l_text_gc,
1347             gc_value_mask, &gcv);
1348
1349   gcv.foreground = resource.tstyle.w_text.getPixel();
1350   XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.w_text_gc,
1351             gc_value_mask, &gcv);
1352
1353   gcv.foreground = resource.tstyle.c_text.getPixel();
1354   XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.c_text_gc,
1355             gc_value_mask, &gcv);
1356
1357   gcv.foreground = resource.tstyle.b_pic.getPixel();
1358   XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.b_pic_gc,
1359             gc_value_mask, &gcv);
1360
1361   const char *s = i18n->getMessage(ScreenSet, ScreenPositionLength,
1362                                    "0: 0000 x 0: 0000");
1363   int l = strlen(s);
1364
1365   if (i18n->multibyte()) {
1366     XRectangle ink, logical;
1367     XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical);
1368     geom_w = logical.width;
1369
1370     geom_h = resource.wstyle.fontset_extents->max_ink_extent.height;
1371   } else {
1372     geom_w = XTextWidth(resource.wstyle.font, s, l);
1373
1374     geom_h = resource.wstyle.font->ascent +
1375              resource.wstyle.font->descent; 
1376   }
1377
1378   geom_w += (resource.bevel_width * 2);
1379   geom_h += (resource.bevel_width * 2);
1380
1381   Pixmap tmp = geom_pixmap;
1382   if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) {
1383     if (resource.wstyle.t_focus.getTexture() ==
1384                                       (BImage_Flat | BImage_Solid)) {
1385       geom_pixmap = None;
1386       XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
1387                          resource.wstyle.t_focus.getColor()->getPixel());
1388     } else {
1389       geom_pixmap = image_control->renderImage(geom_w, geom_h,
1390                                                &resource.wstyle.t_focus);
1391       XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
1392                                  geom_window, geom_pixmap);
1393     }
1394   } else {
1395     if (resource.wstyle.l_focus.getTexture() ==
1396                                       (BImage_Flat | BImage_Solid)) {
1397       geom_pixmap = None;
1398       XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window,
1399                          resource.wstyle.l_focus.getColor()->getPixel());
1400     } else {
1401       geom_pixmap = image_control->renderImage(geom_w, geom_h,
1402                                                &resource.wstyle.l_focus);
1403       XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(),
1404                                  geom_window, geom_pixmap);
1405     }
1406   }
1407   if (tmp) image_control->removeImage(tmp);
1408
1409   XSetWindowBorderWidth(getBaseDisplay().getXDisplay(), geom_window,
1410                         resource.border_width);
1411   XSetWindowBorder(getBaseDisplay().getXDisplay(), geom_window,
1412                    resource.border_color.getPixel());
1413
1414   workspacemenu->reconfigure();
1415   iconmenu->reconfigure();
1416
1417   {
1418     int remember_sub = rootmenu->getCurrentSubmenu();
1419     InitMenu();
1420     raiseWindows(0, 0);
1421     rootmenu->reconfigure();
1422     rootmenu->drawSubmenu(remember_sub);
1423   }
1424
1425   configmenu->reconfigure();
1426
1427   toolbar->reconfigure();
1428
1429 #ifdef    SLIT
1430   slit->reconfigure();
1431 #endif // SLIT
1432
1433   LinkedListIterator<Workspace> wit(workspacesList);
1434   for (Workspace *w = wit.current(); w; wit++, w = wit.current())
1435     w->reconfigure();
1436
1437   LinkedListIterator<OpenboxWindow> iit(iconList);
1438   for (OpenboxWindow *bw = iit.current(); bw; iit++, bw = iit.current())
1439     if (bw->validateClient())
1440       bw->reconfigure();
1441
1442   image_control->timeout();
1443 }
1444
1445
1446 void BScreen::rereadMenu(void) {
1447   InitMenu();
1448   raiseWindows(0, 0);
1449
1450   rootmenu->reconfigure();
1451 }
1452
1453
1454 void BScreen::removeWorkspaceNames(void) {
1455   while (workspaceNames->count())
1456     delete [] workspaceNames->remove(0);
1457 }
1458
1459
1460 void BScreen::LoadStyle(void) {
1461   Resource &conf = resource.styleconfig;
1462   
1463   const char *sfile = openbox.getStyleFilename();
1464   bool loaded = false;
1465   if (sfile != NULL) {
1466     conf.setFile(sfile);
1467     loaded = conf.load();
1468   }
1469   if (!loaded) {
1470     conf.setFile(DEFAULTSTYLE);
1471     if (!conf.load()) {
1472       fprintf(stderr, i18n->getMessage(ScreenSet, ScreenDefaultStyleLoadFail,
1473                                        "BScreen::LoadStyle(): couldn't load "
1474                                        "default style.\n"));
1475       exit(2);
1476     }
1477   }
1478
1479   std::string s;
1480   long l;
1481   
1482   // load fonts/fontsets
1483
1484   if (i18n->multibyte()) {
1485     readDatabaseFontSet("window.font", "Window.Font",
1486                         &resource.wstyle.fontset);
1487     readDatabaseFontSet("toolbar.font", "Toolbar.Font",
1488                         &resource.tstyle.fontset);
1489     readDatabaseFontSet("menu.title.font", "Menu.Title.Font",
1490                         &resource.mstyle.t_fontset);
1491     readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font",
1492                         &resource.mstyle.f_fontset);
1493
1494     resource.mstyle.t_fontset_extents =
1495       XExtentsOfFontSet(resource.mstyle.t_fontset);
1496     resource.mstyle.f_fontset_extents =
1497       XExtentsOfFontSet(resource.mstyle.f_fontset);
1498     resource.tstyle.fontset_extents =
1499       XExtentsOfFontSet(resource.tstyle.fontset);
1500     resource.wstyle.fontset_extents =
1501       XExtentsOfFontSet(resource.wstyle.fontset);
1502   } else {
1503     readDatabaseFont("window.font", "Window.Font",
1504                      &resource.wstyle.font);
1505     readDatabaseFont("menu.title.font", "Menu.Title.Font",
1506                      &resource.mstyle.t_font);
1507     readDatabaseFont("menu.frame.font", "Menu.Frame.Font",
1508                      &resource.mstyle.f_font);
1509     readDatabaseFont("toolbar.font", "Toolbar.Font",
1510                      &resource.tstyle.font);
1511   }
1512
1513   // load window config
1514   readDatabaseTexture("window.title.focus", "Window.Title.Focus",
1515                       &resource.wstyle.t_focus,
1516                       WhitePixel(getBaseDisplay().getXDisplay(),
1517                                  getScreenNumber()));
1518   readDatabaseTexture("window.title.unfocus", "Window.Title.Unfocus",
1519                       &resource.wstyle.t_unfocus,
1520                       BlackPixel(getBaseDisplay().getXDisplay(),
1521                                  getScreenNumber()));
1522   readDatabaseTexture("window.label.focus", "Window.Label.Focus",
1523                       &resource.wstyle.l_focus,
1524                       WhitePixel(getBaseDisplay().getXDisplay(),
1525                                  getScreenNumber()));
1526   readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus",
1527                       &resource.wstyle.l_unfocus,
1528                       BlackPixel(getBaseDisplay().getXDisplay(),
1529                                  getScreenNumber()));
1530   readDatabaseTexture("window.handle.focus", "Window.Handle.Focus",
1531                       &resource.wstyle.h_focus,
1532                       WhitePixel(getBaseDisplay().getXDisplay(),
1533                                  getScreenNumber()));
1534   readDatabaseTexture("window.handle.unfocus", "Window.Handle.Unfocus",
1535                       &resource.wstyle.h_unfocus,
1536                       BlackPixel(getBaseDisplay().getXDisplay(),
1537                                  getScreenNumber()));
1538   readDatabaseTexture("window.grip.focus", "Window.Grip.Focus",
1539                       &resource.wstyle.g_focus,
1540                       WhitePixel(getBaseDisplay().getXDisplay(),
1541                                  getScreenNumber()));
1542   readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus",
1543                       &resource.wstyle.g_unfocus,
1544                       BlackPixel(getBaseDisplay().getXDisplay(),
1545                                  getScreenNumber()));
1546   readDatabaseTexture("window.button.focus", "Window.Button.Focus",
1547                       &resource.wstyle.b_focus,
1548                       WhitePixel(getBaseDisplay().getXDisplay(),
1549                                  getScreenNumber()));
1550   readDatabaseTexture("window.button.unfocus", "Window.Button.Unfocus",
1551                       &resource.wstyle.b_unfocus,
1552                       BlackPixel(getBaseDisplay().getXDisplay(),
1553                                  getScreenNumber()));
1554   readDatabaseTexture("window.button.pressed", "Window.Button.Pressed",
1555                       &resource.wstyle.b_pressed,
1556                       BlackPixel(getBaseDisplay().getXDisplay(),
1557                                  getScreenNumber()));
1558   readDatabaseColor("window.frame.focusColor",
1559                     "Window.Frame.FocusColor",
1560                     &resource.wstyle.f_focus,
1561                     WhitePixel(getBaseDisplay().getXDisplay(),
1562                                getScreenNumber()));
1563   readDatabaseColor("window.frame.unfocusColor",
1564                     "Window.Frame.UnfocusColor",
1565                     &resource.wstyle.f_unfocus,
1566                     BlackPixel(getBaseDisplay().getXDisplay(),
1567                                getScreenNumber()));
1568   readDatabaseColor("window.label.focus.textColor",
1569                     "Window.Label.Focus.TextColor",
1570                     &resource.wstyle.l_text_focus,
1571                     BlackPixel(getBaseDisplay().getXDisplay(),
1572                                getScreenNumber()));
1573   readDatabaseColor("window.label.unfocus.textColor",
1574                     "Window.Label.Unfocus.TextColor",
1575                     &resource.wstyle.l_text_unfocus,
1576                     WhitePixel(getBaseDisplay().getXDisplay(),
1577                                getScreenNumber()));
1578   readDatabaseColor("window.button.focus.picColor",
1579                     "Window.Button.Focus.PicColor",
1580                     &resource.wstyle.b_pic_focus,
1581                     BlackPixel(getBaseDisplay().getXDisplay(),
1582                                getScreenNumber()));
1583   readDatabaseColor("window.button.unfocus.picColor",
1584                     "Window.Button.Unfocus.PicColor",
1585                     &resource.wstyle.b_pic_unfocus,
1586                     WhitePixel(getBaseDisplay().getXDisplay(),
1587                                getScreenNumber()));
1588
1589   if (conf.getValue("window.justify", "Window.Justify", s)) {
1590     if (0 == strncasecmp(s.c_str(), "right", s.length()))
1591       resource.wstyle.justify = BScreen::RightJustify;
1592     else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1593       resource.wstyle.justify = BScreen::CenterJustify;
1594     else
1595       resource.wstyle.justify = BScreen::LeftJustify;
1596   } else
1597     resource.wstyle.justify = BScreen::LeftJustify;
1598
1599   // load toolbar config
1600   readDatabaseTexture("toolbar", "Toolbar",
1601                       &resource.tstyle.toolbar,
1602                       BlackPixel(getBaseDisplay().getXDisplay(),
1603                                  getScreenNumber()));
1604   readDatabaseTexture("toolbar.label", "Toolbar.Label",
1605                       &resource.tstyle.label,
1606                       BlackPixel(getBaseDisplay().getXDisplay(),
1607                                  getScreenNumber()));
1608   readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel",
1609                       &resource.tstyle.window,
1610                       BlackPixel(getBaseDisplay().getXDisplay(),
1611                                  getScreenNumber()));
1612   readDatabaseTexture("toolbar.button", "Toolbar.Button",
1613                       &resource.tstyle.button,
1614                       WhitePixel(getBaseDisplay().getXDisplay(),
1615                                  getScreenNumber()));
1616   readDatabaseTexture("toolbar.button.pressed", "Toolbar.Button.Pressed",
1617                       &resource.tstyle.pressed,
1618                       BlackPixel(getBaseDisplay().getXDisplay(),
1619                                  getScreenNumber()));
1620   readDatabaseTexture("toolbar.clock", "Toolbar.Clock",
1621                       &resource.tstyle.clock,
1622                       BlackPixel(getBaseDisplay().getXDisplay(),
1623                                  getScreenNumber()));
1624   readDatabaseColor("toolbar.label.textColor", "Toolbar.Label.TextColor",
1625                     &resource.tstyle.l_text,
1626                     WhitePixel(getBaseDisplay().getXDisplay(),
1627                                getScreenNumber()));
1628   readDatabaseColor("toolbar.windowLabel.textColor",
1629                     "Toolbar.WindowLabel.TextColor",
1630                     &resource.tstyle.w_text,
1631                     WhitePixel(getBaseDisplay().getXDisplay(),
1632                                getScreenNumber()));
1633   readDatabaseColor("toolbar.clock.textColor", "Toolbar.Clock.TextColor",
1634                     &resource.tstyle.c_text,
1635                     WhitePixel(getBaseDisplay().getXDisplay(),
1636                                getScreenNumber()));
1637   readDatabaseColor("toolbar.button.picColor", "Toolbar.Button.PicColor",
1638                     &resource.tstyle.b_pic,
1639                     BlackPixel(getBaseDisplay().getXDisplay(),
1640                                getScreenNumber()));
1641
1642   if (conf.getValue("toolbar.justify", "Toolbar.Justify", s)) {
1643     if (0 == strncasecmp(s.c_str(), "right", s.length()))
1644       resource.tstyle.justify = BScreen::RightJustify;
1645     else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1646       resource.tstyle.justify = BScreen::CenterJustify;
1647     else
1648       resource.tstyle.justify = BScreen::LeftJustify;
1649   } else
1650     resource.tstyle.justify = BScreen::LeftJustify;
1651
1652   // load menu config
1653   readDatabaseTexture("menu.title", "Menu.Title",
1654                       &resource.mstyle.title,
1655                       WhitePixel(getBaseDisplay().getXDisplay(),
1656                                  getScreenNumber()));
1657   readDatabaseTexture("menu.frame", "Menu.Frame",
1658                       &resource.mstyle.frame,
1659                       BlackPixel(getBaseDisplay().getXDisplay(),
1660                                  getScreenNumber()));
1661   readDatabaseTexture("menu.hilite", "Menu.Hilite",
1662                       &resource.mstyle.hilite,
1663                       WhitePixel(getBaseDisplay().getXDisplay(),
1664                                  getScreenNumber()));
1665   readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor",
1666                     &resource.mstyle.t_text,
1667                     BlackPixel(getBaseDisplay().getXDisplay(),
1668                                getScreenNumber()));
1669   readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor",
1670                     &resource.mstyle.f_text,
1671                     WhitePixel(getBaseDisplay().getXDisplay(),
1672                                getScreenNumber()));
1673   readDatabaseColor("menu.frame.disableColor", "Menu.Frame.DisableColor",
1674                     &resource.mstyle.d_text,
1675                     BlackPixel(getBaseDisplay().getXDisplay(),
1676                                getScreenNumber()));
1677   readDatabaseColor("menu.hilite.textColor", "Menu.Hilite.TextColor",
1678                     &resource.mstyle.h_text,
1679                     BlackPixel(getBaseDisplay().getXDisplay(),
1680                                getScreenNumber()));
1681
1682   if (conf.getValue("menu.title.justify", "Menu.Title.Justify", s)) {
1683     if (0 == strncasecmp(s.c_str(), "right", s.length()))
1684       resource.mstyle.t_justify = BScreen::RightJustify;
1685     else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1686       resource.mstyle.t_justify = BScreen::CenterJustify;
1687     else
1688       resource.mstyle.t_justify = BScreen::LeftJustify;
1689   } else
1690     resource.mstyle.t_justify = BScreen::LeftJustify;
1691
1692   if (conf.getValue("menu.frame.justify", "Menu.Frame.Justify", s)) {
1693     if (0 == strncasecmp(s.c_str(), "right", s.length()))
1694       resource.mstyle.f_justify = BScreen::RightJustify;
1695     else if (0 == strncasecmp(s.c_str(), "center", s.length()))
1696       resource.mstyle.f_justify = BScreen::CenterJustify;
1697     else
1698       resource.mstyle.f_justify = BScreen::LeftJustify;
1699   } else
1700     resource.mstyle.f_justify = BScreen::LeftJustify;
1701
1702   if (conf.getValue("menu.bullet", "Menu.Bullet", s)) {
1703     if (0 == strncasecmp(s.c_str(), "empty", s.length()))
1704       resource.mstyle.bullet = Basemenu::Empty;
1705     else if (0 == strncasecmp(s.c_str(), "square", s.length()))
1706       resource.mstyle.bullet = Basemenu::Square;
1707     else if (0 == strncasecmp(s.c_str(), "diamond", s.length()))
1708       resource.mstyle.bullet = Basemenu::Diamond;
1709     else
1710       resource.mstyle.bullet = Basemenu::Triangle;
1711   } else
1712     resource.mstyle.bullet = Basemenu::Triangle;
1713
1714   if (conf.getValue("menu.bullet.position", "Menu.Bullet.Position", s)) {
1715     if (0 == strncasecmp(s.c_str(), "right", s.length()))
1716       resource.mstyle.bullet_pos = Basemenu::Right;
1717     else
1718       resource.mstyle.bullet_pos = Basemenu::Left;
1719   } else
1720     resource.mstyle.bullet_pos = Basemenu::Left;
1721
1722   readDatabaseColor("borderColor", "BorderColor", &resource.border_color,
1723                     BlackPixel(getBaseDisplay().getXDisplay(),
1724                                getScreenNumber()));
1725
1726   // load bevel, border and handle widths
1727   if (conf.getValue("handleWidth", "HandleWidth", l)) {
1728     if (l <= size().w() / 2 && l != 0)
1729       resource.handle_width = l;
1730     else
1731       resource.handle_width = 6;
1732   } else
1733     resource.handle_width = 6;
1734
1735   if (conf.getValue("borderWidth", "BorderWidth", l))
1736     resource.border_width = l;
1737   else
1738     resource.border_width = 1;
1739
1740   if (conf.getValue("bevelWidth", "BevelWidth", l)) {
1741     if (l <= size().w() / 2 && l != 0)
1742       resource.bevel_width = l;
1743     else
1744       resource.bevel_width = 3;
1745   } else
1746     resource.bevel_width = 3;
1747
1748   if (conf.getValue("frameWidth", "FrameWidth", l)) {
1749     if (l <= size().w() / 2)
1750       resource.frame_width = l;
1751     else
1752       resource.frame_width = resource.bevel_width;
1753   } else
1754     resource.frame_width = resource.bevel_width;
1755
1756   const char *cmd = resource.root_command;
1757   if (cmd != NULL || conf.getValue("rootCommand", "RootCommand", s)) {
1758     if (cmd == NULL)
1759       cmd = s.c_str(); // not specified by the screen, so use the one from the
1760                        // style file
1761 #ifndef    __EMX__
1762     char displaystring[MAXPATHLEN];
1763     sprintf(displaystring, "DISPLAY=%s",
1764             DisplayString(getBaseDisplay().getXDisplay()));
1765     sprintf(displaystring + strlen(displaystring) - 1, "%d",
1766             getScreenNumber());
1767
1768     bexec(cmd, displaystring);
1769 #else //   __EMX__
1770     spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", cmd, NULL);
1771 #endif // !__EMX__
1772   }
1773 }
1774
1775
1776 void BScreen::addIcon(OpenboxWindow *w) {
1777   if (! w) return;
1778
1779   w->setWorkspace(-1);
1780   w->setWindowNumber(iconList->count());
1781
1782   iconList->insert(w);
1783
1784   iconmenu->insert((const char **) w->getIconTitle());
1785   iconmenu->update();
1786 }
1787
1788
1789 void BScreen::removeIcon(OpenboxWindow *w) {
1790   if (! w) return;
1791
1792   iconList->remove(w->getWindowNumber());
1793
1794   iconmenu->remove(w->getWindowNumber());
1795   iconmenu->update();
1796
1797   LinkedListIterator<OpenboxWindow> it(iconList);
1798   OpenboxWindow *bw = it.current();
1799   for (int i = 0; bw; it++, bw = it.current())
1800     bw->setWindowNumber(i++);
1801 }
1802
1803
1804 OpenboxWindow *BScreen::getIcon(int index) {
1805   if (index >= 0 && index < iconList->count())
1806     return iconList->find(index);
1807
1808   return NULL;
1809 }
1810
1811
1812 int BScreen::addWorkspace(void) {
1813   Workspace *wkspc = new Workspace(*this, workspacesList->count());
1814   workspacesList->insert(wkspc);
1815   saveWorkspaceNames();
1816
1817   workspacemenu->insert(wkspc->getName(), wkspc->getMenu(),
1818                         wkspc->getWorkspaceID() + 2);
1819   workspacemenu->update();
1820
1821   toolbar->reconfigure();
1822
1823   updateNetizenWorkspaceCount();
1824
1825   return workspacesList->count();
1826 }
1827
1828
1829 int BScreen::removeLastWorkspace(void) {
1830   if (workspacesList->count() == 1)
1831     return 0;
1832
1833   Workspace *wkspc = workspacesList->last();
1834
1835   if (current_workspace->getWorkspaceID() == wkspc->getWorkspaceID())
1836     changeWorkspaceID(current_workspace->getWorkspaceID() - 1);
1837
1838   wkspc->removeAll();
1839
1840   workspacemenu->remove(wkspc->getWorkspaceID() + 2);
1841   workspacemenu->update();
1842
1843   workspacesList->remove(wkspc);
1844   delete wkspc;
1845
1846   toolbar->reconfigure();
1847
1848   updateNetizenWorkspaceCount();
1849
1850   return workspacesList->count();
1851 }
1852
1853
1854 void BScreen::changeWorkspaceID(int id) {
1855   if (! current_workspace) return;
1856
1857   if (id != current_workspace->getWorkspaceID()) {
1858     current_workspace->hideAll();
1859
1860     workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2,
1861                                    False);
1862
1863     if (openbox.getFocusedWindow() &&
1864         openbox.getFocusedWindow()->getScreen() == this &&
1865         (! openbox.getFocusedWindow()->isStuck())) {
1866       current_workspace->setLastFocusedWindow(openbox.getFocusedWindow());
1867       openbox.setFocusedWindow(NULL);
1868     }
1869
1870     current_workspace = getWorkspace(id);
1871
1872     workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2,
1873                                    True);
1874     toolbar->redrawWorkspaceLabel(True);
1875
1876     current_workspace->showAll();
1877
1878     if (resource.focus_last && current_workspace->getLastFocusedWindow()) {
1879       XSync(openbox.getXDisplay(), False);
1880       current_workspace->getLastFocusedWindow()->setInputFocus();
1881     }
1882   }
1883
1884   updateNetizenCurrentWorkspace();
1885 }
1886
1887
1888 void BScreen::addNetizen(Netizen *n) {
1889   netizenList->insert(n);
1890
1891   n->sendWorkspaceCount();
1892   n->sendCurrentWorkspace();
1893
1894   LinkedListIterator<Workspace> it(workspacesList);
1895   for (Workspace *w = it.current(); w; it++, w = it.current()) {
1896     for (int i = 0; i < w->getCount(); i++)
1897       n->sendWindowAdd(w->getWindow(i)->getClientWindow(),
1898                        w->getWorkspaceID());
1899   }
1900
1901   Window f = ((openbox.getFocusedWindow()) ?
1902               openbox.getFocusedWindow()->getClientWindow() : None);
1903   n->sendWindowFocus(f);
1904 }
1905
1906
1907 void BScreen::removeNetizen(Window w) {
1908   LinkedListIterator<Netizen> it(netizenList);
1909   int i = 0;
1910
1911   for (Netizen *n = it.current(); n; it++, i++, n = it.current())
1912     if (n->getWindowID() == w) {
1913       Netizen *tmp = netizenList->remove(i);
1914       delete tmp;
1915
1916       break;
1917     }
1918 }
1919
1920
1921 void BScreen::updateNetizenCurrentWorkspace(void) {
1922   LinkedListIterator<Netizen> it(netizenList);
1923   for (Netizen *n = it.current(); n; it++, n = it.current())
1924     n->sendCurrentWorkspace();
1925 }
1926
1927
1928 void BScreen::updateNetizenWorkspaceCount(void) {
1929   LinkedListIterator<Netizen> it(netizenList);
1930   for (Netizen *n = it.current(); n; it++, n = it.current())
1931     n->sendWorkspaceCount();
1932 }
1933
1934
1935 void BScreen::updateNetizenWindowFocus(void) {
1936   Window f = ((openbox.getFocusedWindow()) ?
1937               openbox.getFocusedWindow()->getClientWindow() : None);
1938   LinkedListIterator<Netizen> it(netizenList);
1939   for (Netizen *n = it.current(); n; it++, n = it.current())
1940     n->sendWindowFocus(f);
1941 }
1942
1943
1944 void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
1945   LinkedListIterator<Netizen> it(netizenList);
1946   for (Netizen *n = it.current(); n; it++, n = it.current())
1947     n->sendWindowAdd(w, p);
1948 }
1949
1950
1951 void BScreen::updateNetizenWindowDel(Window w) {
1952   LinkedListIterator<Netizen> it(netizenList);
1953   for (Netizen *n = it.current(); n; it++, n = it.current())
1954     n->sendWindowDel(w);
1955 }
1956
1957
1958 void BScreen::updateNetizenWindowRaise(Window w) {
1959   LinkedListIterator<Netizen> it(netizenList);
1960   for (Netizen *n = it.current(); n; it++, n = it.current())
1961     n->sendWindowRaise(w);
1962 }
1963
1964
1965 void BScreen::updateNetizenWindowLower(Window w) {
1966   LinkedListIterator<Netizen> it(netizenList);
1967   for (Netizen *n = it.current(); n; it++, n = it.current())
1968     n->sendWindowLower(w);
1969 }
1970
1971
1972 void BScreen::updateNetizenConfigNotify(XEvent *e) {
1973   LinkedListIterator<Netizen> it(netizenList);
1974   for (Netizen *n = it.current(); n; it++, n = it.current())
1975     n->sendConfigNotify(e);
1976 }
1977
1978
1979 void BScreen::raiseWindows(Window *workspace_stack, int num) {
1980   Window *session_stack = new
1981     Window[(num + workspacesList->count() + rootmenuList->count() + 13)];
1982   int i = 0, k = num;
1983
1984   XRaiseWindow(getBaseDisplay().getXDisplay(), iconmenu->getWindowID());
1985   *(session_stack + i++) = iconmenu->getWindowID();
1986
1987   LinkedListIterator<Workspace> wit(workspacesList);
1988   for (Workspace *tmp = wit.current(); tmp; wit++, tmp = wit.current())
1989     *(session_stack + i++) = tmp->getMenu()->getWindowID();
1990
1991   *(session_stack + i++) = workspacemenu->getWindowID();
1992
1993   *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID();
1994   *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID();
1995   *(session_stack + i++) = configmenu->getWindowID();
1996
1997 #ifdef    SLIT
1998   *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID();
1999   *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID();
2000   *(session_stack + i++) = slit->getMenu()->getWindowID();
2001 #endif // SLIT
2002
2003   *(session_stack + i++) =
2004     toolbar->getMenu()->getPlacementmenu()->getWindowID();
2005   *(session_stack + i++) = toolbar->getMenu()->getWindowID();
2006
2007   LinkedListIterator<Rootmenu> rit(rootmenuList);
2008   for (Rootmenu *tmp = rit.current(); tmp; rit++, tmp = rit.current())
2009     *(session_stack + i++) = tmp->getWindowID();
2010   *(session_stack + i++) = rootmenu->getWindowID();
2011
2012   if (toolbar->onTop())
2013     *(session_stack + i++) = toolbar->getWindowID();
2014
2015 #ifdef    SLIT
2016   if (slit->onTop())
2017     *(session_stack + i++) = slit->getWindowID();
2018 #endif // SLIT
2019
2020   while (k--)
2021     *(session_stack + i++) = *(workspace_stack + k);
2022
2023   XRestackWindows(getBaseDisplay().getXDisplay(), session_stack, i);
2024
2025   delete [] session_stack;
2026 }
2027
2028
2029 void BScreen::addWorkspaceName(const char *name) {
2030   workspaceNames->insert(bstrdup(name));
2031 }
2032
2033 char* BScreen::getNameOfWorkspace(int id) {
2034   char *name = NULL;
2035
2036   if (id >= 0 && id < workspaceNames->count()) {
2037     char *wkspc_name = workspaceNames->find(id);
2038
2039     if (wkspc_name)
2040       name = wkspc_name;
2041   }
2042   return name;
2043 }
2044
2045
2046 void BScreen::reassociateWindow(OpenboxWindow *w, int wkspc_id, Bool ignore_sticky) {
2047   if (! w) return;
2048
2049   if (wkspc_id == -1)
2050     wkspc_id = current_workspace->getWorkspaceID();
2051
2052   if (w->getWorkspaceNumber() == wkspc_id)
2053     return;
2054
2055   if (w->isIconic()) {
2056     removeIcon(w);
2057     getWorkspace(wkspc_id)->addWindow(w);
2058   } else if (ignore_sticky || ! w->isStuck()) {
2059     getWorkspace(w->getWorkspaceNumber())->removeWindow(w);
2060     getWorkspace(wkspc_id)->addWindow(w);
2061   }
2062 }
2063
2064
2065 void BScreen::nextFocus(void) {
2066   Bool have_focused = False;
2067   int focused_window_number = -1;
2068   OpenboxWindow *next;
2069
2070   if (openbox.getFocusedWindow()) {
2071     if (openbox.getFocusedWindow()->getScreen()->getScreenNumber() ==
2072         getScreenNumber()) {
2073       have_focused = True;
2074       focused_window_number = openbox.getFocusedWindow()->getWindowNumber();
2075     }
2076   }
2077
2078   if ((getCurrentWorkspace()->getCount() > 1) && have_focused) {
2079     int next_window_number = focused_window_number;
2080     do {
2081       if ((++next_window_number) >= getCurrentWorkspace()->getCount())
2082         next_window_number = 0;
2083
2084       next = getCurrentWorkspace()->getWindow(next_window_number);
2085     } while ((! next->setInputFocus()) && (next_window_number !=
2086                                            focused_window_number));
2087
2088     if (next_window_number != focused_window_number)
2089       getCurrentWorkspace()->raiseWindow(next);
2090   } else if (getCurrentWorkspace()->getCount() >= 1) {
2091     next = current_workspace->getWindow(0);
2092
2093     current_workspace->raiseWindow(next);
2094     next->setInputFocus();
2095   }
2096 }
2097
2098
2099 void BScreen::prevFocus(void) {
2100   Bool have_focused = False;
2101   int focused_window_number = -1;
2102   OpenboxWindow *prev;
2103
2104   if (openbox.getFocusedWindow()) {
2105     if (openbox.getFocusedWindow()->getScreen()->getScreenNumber() ==
2106         getScreenNumber()) {
2107       have_focused = True;
2108       focused_window_number = openbox.getFocusedWindow()->getWindowNumber();
2109     }
2110   }
2111
2112   if ((getCurrentWorkspace()->getCount() > 1) && have_focused) {
2113     int prev_window_number = focused_window_number;
2114     do {
2115       if ((--prev_window_number) < 0)
2116         prev_window_number = getCurrentWorkspace()->getCount() - 1;
2117
2118       prev = getCurrentWorkspace()->getWindow(prev_window_number);
2119     } while ((! prev->setInputFocus()) && (prev_window_number !=
2120                                            focused_window_number));
2121
2122     if (prev_window_number != focused_window_number)
2123       getCurrentWorkspace()->raiseWindow(prev);
2124   } else if (getCurrentWorkspace()->getCount() >= 1) {
2125     prev = current_workspace->getWindow(0);
2126
2127     current_workspace->raiseWindow(prev);
2128     prev->setInputFocus();
2129   }
2130 }
2131
2132
2133 void BScreen::raiseFocus(void) {
2134   Bool have_focused = False;
2135   int focused_window_number = -1;
2136
2137   if (openbox.getFocusedWindow()) {
2138     if (openbox.getFocusedWindow()->getScreen()->getScreenNumber() ==
2139         getScreenNumber()) {
2140       have_focused = True;
2141       focused_window_number = openbox.getFocusedWindow()->getWindowNumber();
2142     }
2143   }
2144
2145   if ((getCurrentWorkspace()->getCount() > 1) && have_focused)
2146     getWorkspace(openbox.getFocusedWindow()->getWorkspaceNumber())->
2147       raiseWindow(openbox.getFocusedWindow());
2148 }
2149
2150
2151 void BScreen::InitMenu(void) {
2152   if (rootmenu) {
2153     while (rootmenuList->count())
2154       rootmenuList->remove(0);
2155
2156     while (rootmenu->getCount())
2157       rootmenu->remove(0);
2158   } else {
2159     rootmenu = new Rootmenu(*this);
2160   }
2161   Bool defaultMenu = True;
2162
2163   if (openbox.getMenuFilename()) {
2164     FILE *menu_file = fopen(openbox.getMenuFilename(), "r");
2165
2166     if (!menu_file) {
2167       perror(openbox.getMenuFilename());
2168     } else {
2169       if (feof(menu_file)) {
2170         fprintf(stderr, i18n->getMessage(ScreenSet, ScreenEmptyMenuFile,
2171                                          "%s: Empty menu file"),
2172                 openbox.getMenuFilename());
2173       } else {
2174         char line[1024], label[1024];
2175         memset(line, 0, 1024);
2176         memset(label, 0, 1024);
2177
2178         while (fgets(line, 1024, menu_file) && ! feof(menu_file)) {
2179           if (line[0] != '#') {
2180             int i, key = 0, index = -1, len = strlen(line);
2181
2182             key = 0;
2183             for (i = 0; i < len; i++) {
2184               if (line[i] == '[') index = 0;
2185               else if (line[i] == ']') break;
2186               else if (line[i] != ' ')
2187                 if (index++ >= 0)
2188                   key += tolower(line[i]);
2189             }
2190
2191             if (key == 517) {
2192               index = -1;
2193               for (i = index; i < len; i++) {
2194                 if (line[i] == '(') index = 0;
2195                 else if (line[i] == ')') break;
2196                 else if (index++ >= 0) {
2197                   if (line[i] == '\\' && i < len - 1) i++;
2198                   label[index - 1] = line[i];
2199                 }
2200               }
2201
2202               if (index == -1) index = 0;
2203               label[index] = '\0';
2204
2205               rootmenu->setLabel(label);
2206               defaultMenu = parseMenuFile(menu_file, rootmenu);
2207               break;
2208             }
2209           }
2210         }
2211       }
2212       fclose(menu_file);
2213     }
2214   }
2215
2216   if (defaultMenu) {
2217     rootmenu->setInternalMenu();
2218     rootmenu->insert(i18n->getMessage(ScreenSet, Screenxterm, "xterm"),
2219                      BScreen::Execute,
2220                      i18n->getMessage(ScreenSet, Screenxterm, "xterm"));
2221     rootmenu->insert(i18n->getMessage(ScreenSet, ScreenRestart, "Restart"),
2222                      BScreen::Restart);
2223     rootmenu->insert(i18n->getMessage(ScreenSet, ScreenExit, "Exit"),
2224                      BScreen::Exit);
2225   } else {
2226     openbox.setMenuFilename(openbox.getMenuFilename());
2227   }
2228 }
2229
2230
2231 Bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) {
2232   char line[1024], label[1024], command[1024];
2233
2234   while (! feof(file)) {
2235     memset(line, 0, 1024);
2236     memset(label, 0, 1024);
2237     memset(command, 0, 1024);
2238
2239     if (fgets(line, 1024, file)) {
2240       if (line[0] != '#') {
2241         register int i, key = 0, parse = 0, index = -1,
2242           line_length = strlen(line),
2243           label_length = 0, command_length = 0;
2244
2245         // determine the keyword
2246         key = 0;
2247         for (i = 0; i < line_length; i++) {
2248           if (line[i] == '[') parse = 1;
2249           else if (line[i] == ']') break;
2250           else if (line[i] != ' ')
2251             if (parse)
2252               key += tolower(line[i]);
2253         }
2254
2255         // get the label enclosed in ()'s
2256         parse = 0;
2257
2258         for (i = 0; i < line_length; i++) {
2259           if (line[i] == '(') {
2260             index = 0;
2261             parse = 1;
2262           } else if (line[i] == ')') break;
2263           else if (index++ >= 0) {
2264             if (line[i] == '\\' && i < line_length - 1) i++;
2265             label[index - 1] = line[i];
2266           }
2267         }
2268
2269         if (parse) {
2270           label[index] = '\0';
2271           label_length = index;
2272         } else {
2273           label[0] = '\0';
2274           label_length = 0;
2275         }
2276
2277         // get the command enclosed in {}'s
2278         parse = 0;
2279         index = -1;
2280         for (i = 0; i < line_length; i++) {
2281           if (line[i] == '{') {
2282             index = 0;
2283             parse = 1;
2284           } else if (line[i] == '}') break;
2285           else if (index++ >= 0) {
2286             if (line[i] == '\\' && i < line_length - 1) i++;
2287             command[index - 1] = line[i];
2288           }
2289         }
2290
2291         if (parse) {
2292           command[index] = '\0';
2293           command_length = index;
2294         } else {
2295           command[0] = '\0';
2296           command_length = 0;
2297         }
2298
2299         switch (key) {
2300         case 311: //end
2301           return ((menu->getCount() == 0) ? True : False);
2302
2303           break;
2304
2305         case 333: // nop
2306           menu->insert(label);
2307
2308           break;
2309
2310         case 421: // exec
2311           if ((! *label) && (! *command)) {
2312             fprintf(stderr, i18n->getMessage(ScreenSet, ScreenEXECError,
2313                              "BScreen::parseMenuFile: [exec] error, "
2314                              "no menu label and/or command defined\n"));
2315             continue;
2316           }
2317
2318           menu->insert(label, BScreen::Execute, command);
2319
2320           break;
2321
2322         case 442: // exit
2323           if (! *label) {
2324             fprintf(stderr, i18n->getMessage(ScreenSet, ScreenEXITError,
2325                                      "BScreen::parseMenuFile: [exit] error, "
2326                                      "no menu label defined\n"));
2327             continue;
2328           }
2329
2330           menu->insert(label, BScreen::Exit);
2331
2332           break;
2333
2334         case 561: // style
2335           {
2336             if ((! *label) || (! *command)) {
2337               fprintf(stderr, i18n->getMessage(ScreenSet, ScreenSTYLEError,
2338                                  "BScreen::parseMenuFile: [style] error, "
2339                                  "no menu label and/or filename defined\n"));
2340               continue;
2341             }
2342
2343             char style[MAXPATHLEN];
2344
2345             // perform shell style ~ home directory expansion
2346             char *homedir = 0;
2347             int homedir_len = 0;
2348             if (*command == '~' && *(command + 1) == '/') {
2349               homedir = getenv("HOME");
2350               homedir_len = strlen(homedir);
2351             }
2352
2353             if (homedir && homedir_len != 0) {
2354               strncpy(style, homedir, homedir_len);
2355
2356               strncpy(style + homedir_len, command + 1,
2357                       command_length - 1);
2358               *(style + command_length + homedir_len - 1) = '\0';
2359             } else {
2360               strncpy(style, command, command_length);
2361               *(style + command_length) = '\0';
2362             }
2363
2364             menu->insert(label, BScreen::SetStyle, style);
2365           }
2366
2367           break;
2368
2369         case 630: // config
2370           if (! *label) {
2371             fprintf(stderr, i18n->getMessage(ScreenSet, ScreenCONFIGError,
2372                                "BScreen::parseMenufile: [config] error, "
2373                                "no label defined"));
2374             continue;
2375           }
2376
2377           menu->insert(label, configmenu);
2378
2379           break;
2380
2381         case 740: // include
2382           {
2383             if (! *label) {
2384               fprintf(stderr, i18n->getMessage(ScreenSet, ScreenINCLUDEError,
2385                                  "BScreen::parseMenuFile: [include] error, "
2386                                  "no filename defined\n"));
2387               continue;
2388             }
2389
2390             char newfile[MAXPATHLEN];
2391
2392             // perform shell style ~ home directory expansion
2393             char *homedir = 0;
2394             int homedir_len = 0;
2395             if (*label == '~' && *(label + 1) == '/') {
2396               homedir = getenv("HOME");
2397               homedir_len = strlen(homedir);
2398             }
2399
2400             if (homedir && homedir_len != 0) {
2401               strncpy(newfile, homedir, homedir_len);
2402
2403               strncpy(newfile + homedir_len, label + 1,
2404                       label_length - 1);
2405               *(newfile + label_length + homedir_len - 1) = '\0';
2406             } else {
2407               strncpy(newfile, label, label_length);
2408               *(newfile + label_length) = '\0';
2409             }
2410
2411             if (newfile) {
2412               FILE *submenufile = fopen(newfile, "r");
2413
2414               if (submenufile) {
2415                 struct stat buf;
2416                 if (fstat(fileno(submenufile), &buf) ||
2417                     (! S_ISREG(buf.st_mode))) {
2418                   fprintf(stderr,
2419                           i18n->getMessage(ScreenSet, ScreenINCLUDEErrorReg,
2420                              "BScreen::parseMenuFile: [include] error: "
2421                              "'%s' is not a regular file\n"), newfile);
2422                   break;
2423                 }
2424
2425                 if (! feof(submenufile)) {
2426                   if (! parseMenuFile(submenufile, menu))
2427                     openbox.setMenuFilename(newfile);
2428
2429                   fclose(submenufile);
2430                 }
2431               } else
2432                 perror(newfile);
2433             }
2434           }
2435
2436           break;
2437
2438         case 767: // submenu
2439           {
2440             if (! *label) {
2441               fprintf(stderr, i18n->getMessage(ScreenSet, ScreenSUBMENUError,
2442                                  "BScreen::parseMenuFile: [submenu] error, "
2443                                  "no menu label defined\n"));
2444               continue;
2445             }
2446
2447             Rootmenu *submenu = new Rootmenu(*this);
2448
2449             if (*command)
2450               submenu->setLabel(command);
2451             else
2452               submenu->setLabel(label);
2453
2454             parseMenuFile(file, submenu);
2455             submenu->update();
2456             menu->insert(label, submenu);
2457             rootmenuList->insert(submenu);
2458           }
2459
2460           break;
2461
2462         case 773: // restart
2463           {
2464             if (! *label) {
2465               fprintf(stderr, i18n->getMessage(ScreenSet, ScreenRESTARTError,
2466                                  "BScreen::parseMenuFile: [restart] error, "
2467                                  "no menu label defined\n"));
2468               continue;
2469             }
2470
2471             if (*command)
2472               menu->insert(label, BScreen::RestartOther, command);
2473             else
2474               menu->insert(label, BScreen::Restart);
2475           }
2476
2477           break;
2478
2479         case 845: // reconfig
2480           {
2481             if (! *label) {
2482               fprintf(stderr, i18n->getMessage(ScreenSet, ScreenRECONFIGError,
2483                                  "BScreen::parseMenuFile: [reconfig] error, "
2484                                  "no menu label defined\n"));
2485               continue;
2486             }
2487
2488             menu->insert(label, BScreen::Reconfigure);
2489           }
2490
2491           break;
2492
2493         case 995: // stylesdir
2494         case 1113: // stylesmenu
2495           {
2496             Bool newmenu = ((key == 1113) ? True : False);
2497
2498             if ((! *label) || ((! *command) && newmenu)) {
2499               fprintf(stderr,
2500                       i18n->getMessage(ScreenSet, ScreenSTYLESDIRError,
2501                          "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2502                          " error, no directory defined\n"));
2503               continue;
2504             }
2505
2506             char stylesdir[MAXPATHLEN];
2507
2508             char *directory = ((newmenu) ? command : label);
2509             int directory_length = ((newmenu) ? command_length : label_length);
2510
2511             // perform shell style ~ home directory expansion
2512             char *homedir = 0;
2513             int homedir_len = 0;
2514
2515             if (*directory == '~' && *(directory + 1) == '/') {
2516               homedir = getenv("HOME");
2517               homedir_len = strlen(homedir);
2518             }
2519
2520             if (homedir && homedir_len != 0) {
2521               strncpy(stylesdir, homedir, homedir_len);
2522
2523               strncpy(stylesdir + homedir_len, directory + 1,
2524                       directory_length - 1);
2525               *(stylesdir + directory_length + homedir_len - 1) = '\0';
2526             } else {
2527               strncpy(stylesdir, directory, directory_length);
2528               *(stylesdir + directory_length) = '\0';
2529             }
2530
2531             struct stat statbuf;
2532
2533             if (! stat(stylesdir, &statbuf)) {
2534               if (S_ISDIR(statbuf.st_mode)) {
2535                 Rootmenu *stylesmenu;
2536
2537                 if (newmenu)
2538                   stylesmenu = new Rootmenu(*this);
2539                 else
2540                   stylesmenu = menu;
2541
2542                 DIR *d = opendir(stylesdir);
2543                 int entries = 0;
2544                 struct dirent *p;
2545
2546                 // get the total number of directory entries
2547                 while ((p = readdir(d))) entries++;
2548                 rewinddir(d);
2549
2550                 char **ls = new char* [entries];
2551                 int index = 0;
2552                 while ((p = readdir(d)))
2553                   ls[index++] = bstrdup(p->d_name);
2554
2555                 closedir(d);
2556
2557                 std::sort(ls, ls + entries, dcmp());
2558
2559                 int n, slen = strlen(stylesdir);
2560                 for (n = 0; n < entries; n++) {
2561                   if (ls[n][strlen(ls[n])-1] != '~') {
2562                     int nlen = strlen(ls[n]);
2563                     char style[MAXPATHLEN + 1];
2564
2565                     strncpy(style, stylesdir, slen);
2566                     *(style + slen) = '/';
2567                     strncpy(style + slen + 1, ls[n], nlen + 1);
2568
2569                     if ((! stat(style, &statbuf)) && S_ISREG(statbuf.st_mode))
2570                       stylesmenu->insert(ls[n], BScreen::SetStyle, style);
2571                   }
2572
2573                   delete [] ls[n];
2574                 }
2575
2576                 delete [] ls;
2577
2578                 stylesmenu->update();
2579
2580                 if (newmenu) {
2581                   stylesmenu->setLabel(label);
2582                   menu->insert(label, stylesmenu);
2583                   rootmenuList->insert(stylesmenu);
2584                 }
2585
2586                 openbox.setMenuFilename(stylesdir);
2587               } else {
2588                 fprintf(stderr, i18n->getMessage(ScreenSet,
2589                                                  ScreenSTYLESDIRErrorNotDir,
2590                                    "BScreen::parseMenuFile:"
2591                                    " [stylesdir/stylesmenu] error, %s is not a"
2592                                    " directory\n"), stylesdir);
2593               }
2594             } else {
2595               fprintf(stderr,
2596                       i18n->getMessage(ScreenSet, ScreenSTYLESDIRErrorNoExist,
2597                          "BScreen::parseMenuFile: [stylesdir/stylesmenu]"
2598                          " error, %s does not exist\n"), stylesdir);
2599             }
2600
2601             break;
2602           }
2603
2604         case 1090: // workspaces
2605           {
2606             if (! *label) {
2607               fprintf(stderr,
2608                       i18n->getMessage(ScreenSet, ScreenWORKSPACESError,
2609                                "BScreen:parseMenuFile: [workspaces] error, "
2610                                "no menu label defined\n"));
2611               continue;
2612             }
2613
2614             menu->insert(label, workspacemenu);
2615
2616             break;
2617           }
2618         }
2619       }
2620     }
2621   }
2622
2623   return ((menu->getCount() == 0) ? True : False);
2624 }
2625
2626
2627 void BScreen::shutdown(void) {
2628   openbox.grab();
2629
2630   XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), NoEventMask);
2631   XSync(getBaseDisplay().getXDisplay(), False);
2632
2633   LinkedListIterator<Workspace> it(workspacesList);
2634   for (Workspace *w = it.current(); w; it++, w = it.current())
2635     w->shutdown();
2636
2637   while (iconList->count()) {
2638     iconList->first()->restore();
2639     delete iconList->first();
2640   }
2641
2642 #ifdef    SLIT
2643   slit->shutdown();
2644 #endif // SLIT
2645
2646   openbox.ungrab();
2647 }
2648
2649
2650 void BScreen::showPosition(int x, int y) {
2651   if (! geom_visible) {
2652     XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window,
2653                       (size().w() - geom_w) / 2,
2654                       (size().h() - geom_h) / 2, geom_w, geom_h);
2655     XMapWindow(getBaseDisplay().getXDisplay(), geom_window);
2656     XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window);
2657
2658     geom_visible = True;
2659   }
2660
2661   char label[1024];
2662
2663   sprintf(label, i18n->getMessage(ScreenSet, ScreenPositionFormat,
2664                                   "X: %4d x Y: %4d"), x, y);
2665
2666   XClearWindow(getBaseDisplay().getXDisplay(), geom_window);
2667
2668   if (i18n->multibyte()) {
2669     XmbDrawString(getBaseDisplay().getXDisplay(), geom_window,
2670                   resource.wstyle.fontset, resource.wstyle.l_text_focus_gc,
2671                   resource.bevel_width, resource.bevel_width -
2672                   resource.wstyle.fontset_extents->max_ink_extent.y,
2673                   label, strlen(label));
2674   } else {
2675     XDrawString(getBaseDisplay().getXDisplay(), geom_window,
2676                 resource.wstyle.l_text_focus_gc,
2677                 resource.bevel_width,
2678                 resource.wstyle.font->ascent +
2679                 resource.bevel_width, label, strlen(label));
2680   }
2681 }
2682
2683
2684 void BScreen::showGeometry(unsigned int gx, unsigned int gy) {
2685   if (! geom_visible) {
2686     XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window,
2687                       (size().w() - geom_w) / 2,
2688                       (size().h() - geom_h) / 2, geom_w, geom_h);
2689     XMapWindow(getBaseDisplay().getXDisplay(), geom_window);
2690     XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window);
2691
2692     geom_visible = True;
2693   }
2694
2695   char label[1024];
2696
2697   sprintf(label, i18n->getMessage(ScreenSet, ScreenGeometryFormat,
2698                                   "W: %4d x H: %4d"), gx, gy);
2699
2700   XClearWindow(getBaseDisplay().getXDisplay(), geom_window);
2701
2702   if (i18n->multibyte()) {
2703     XmbDrawString(getBaseDisplay().getXDisplay(), geom_window,
2704                   resource.wstyle.fontset, resource.wstyle.l_text_focus_gc,
2705                   resource.bevel_width, resource.bevel_width -
2706                   resource.wstyle.fontset_extents->max_ink_extent.y,
2707                   label, strlen(label));
2708   } else {
2709     XDrawString(getBaseDisplay().getXDisplay(), geom_window,
2710                 resource.wstyle.l_text_focus_gc,
2711                 resource.bevel_width,
2712                 resource.wstyle.font->ascent +
2713                 resource.bevel_width, label, strlen(label));
2714   }
2715 }
2716
2717 void BScreen::hideGeometry(void) {
2718   if (geom_visible) {
2719     XUnmapWindow(getBaseDisplay().getXDisplay(), geom_window);
2720     geom_visible = False;
2721   }
2722 }