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