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