1 /****************************************************************************
2  * This module is mostly all new
3  * by Rob Nation
4  * Copyright 1993 Robert Nation. No restrictions are placed on this code,
5  * as long as the copyright notice is preserved
6  ****************************************************************************
7  * slightly modified for BowMan
8  * by Bo Yang
9  *
10  * slightly modified for AfterStep
11  * by Frank Fejes
12  *
13  ****************************************************************************
14  *
15  * Configure.c: reads the .steprc or system.steprc file, interprets it,
16  * and sets up menus, bindings, colors, and fonts as specified
17  *
18  ***************************************************************************/
19 
20 #include "../configure.h"
21 
22 #include <stdio.h>
23 #include <signal.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <pwd.h>
30 
31 #include <X11/Xproto.h>
32 #include <X11/Xatom.h>
33 #ifdef M4
34 #include <X11/Xmu/SysUtil.h>
35 #endif
36 
37 
38 #include "afterstep.h"
39 #include "menus.h"
40 #include "misc.h"
41 #include "parse.h"
42 #include "screen.h"
43 #include "../version.h"
44 
45 #define AFTER_BUTTONS 1
46 #define AFTER_ICONS 1
47 #include "asbuttons.h"
48 
49 #ifdef XPM
50 #include <X11/xpm.h>
51 char *PixmapPath=AFTER_ICONDIR;
52 #endif
53 char *IconPath = AFTER_ICONDIR;
54 char *ModulePath = AFTERDIR;
55 
56 char *white = "white";
57 char *black = "black";
58 char *grey = "SlateGrey";
59 char *Menuback;
60 char *Menufore;
61 char *Menustipple;
62 char *Stdback;
63 char *Stdfore;
64 char *Stickyback;
65 char *Stickyfore;
66 char *Hiback;
67 char *Hifore;
68 #ifndef NO_PAGER
69 char *Pagerback;
70 char *Pagerfore;
71 #endif
72 
73 void     GetColors(void);
74 Pixel    GetColor(char *);
75 MenuRoot *NewMenuRoot(char *name);
76 char     *stripcpy(char *);
77 char     *stripcpy2(char *,int, Bool);
78 char     *stripcpy3(char *, Bool);
79 #ifndef NO_PAGER
80 void     initialize_pager(int x, int y);
81 #endif
82 void     bad_binding(int num);
83 void     nofont(char *name);
84 void nocolor(char *note, char *name);
85 int contexts;
86 int mods,func,func_val_1,func_val_2;
87 
88 #ifndef NO_PAGER
89 int pager_x=10000,pager_y=10000;
90 #endif
91 
92 #ifdef ENABLE_TEXTURE
93 #include "stepgfx.h"
94 char    *TitleStyle=NULL;
95 char	*TexTypes=NULL;
96 char	*TexMaxcols=NULL;
97 char	*TColor=NULL, *IColor=NULL, *MColor=NULL, *UColor=NULL, *SColor=NULL;
98 char	*TGColor=NULL;
99 char	*TPixmap=NULL,*UPixmap=NULL,*SPixmap=NULL;
100 extern void InitTextureData(TextureInfo   *info, char *title, char*utitle,
101 			    char *mtitle, char *menu, char *sticky, char *text);
102 int   IconTexType = TEXTURE_BUILTIN;
103 char *IconBgColor;
104 char *IconTexColor;
105 int   IconMaxColors = 16;
106 char *IconPixmapFile;
107 int   IconTexFlags = 0;
108 #endif
109 
110 unsigned PopupCount = 0;
111 MenuRoot *PopupTable[MAXPOPUPS];
112 int dummy;
113 char *config_file = ".steprc";
114 
115 extern XContext MenuContext;		/* context for afterstep menus */
116 extern Bool DoHandlePageing;
117 
118 /* value for the rubberband XORing */
119 unsigned long XORvalue;
120 int have_the_colors = 0;
121 
122 /*
123  * Order is important here! if one keyword is the same as the first part of
124  * another keyword, the shorter one must come first!
125  */
126 struct config main_config[] =
127 {
128   {"OpaqueResize",      SetFlag,        (char **)OpaqueResize,(int *)0},
129   {"StubbornIcons",     SetFlag,        (char **)StubbornIcons,(int *)0},
130   {"StubbornPlacement", SetFlag,        (char **)StubbornPlacement,(int *)0},
131   {"StubbornIconPlacement", SetFlag,    (char **)StubbornIconPlacement,
132                                                  (int *)0},
133   {"Font",              assign_string,  &Scr.StdFont.name, (int *)0},
134   {"WindowFont",        assign_string,  &Scr.WindowFont.name, (int *)0},
135   {"MenuForeColor",     assign_string,  &Menufore, (int *)0},
136   {"MenuBackColor",     assign_string,  &Menuback, (int *)0},
137   {"MenuStippleColor",  assign_string,  &Menustipple, (int *)0},
138   {"StdForeColor",      assign_string,  &Stdfore, (int *)0},
139   {"StdBackColor",      assign_string,  &Stdback, (int *)0},
140 #ifdef XPM
141   {"PixmapPath",        assign_string,  &PixmapPath, (int *)0},
142 #endif
143   {"StickyForeColor",   assign_string,  &Stickyfore, (int *)0},
144   {"StickyBackColor",   assign_string,  &Stickyback, (int *)0},
145   {"HiForeColor",       assign_string,  &Hifore, (int *)0},
146   {"HiBackColor",       assign_string,  &Hiback, (int *)0},
147   {"IconPath",          assign_string,  &IconPath, (int *)0},
148   {"IconBox",           SetBox,         (char **)0, (int *)0},
149   {"StickyIcons",       SetFlag,        (char **)StickyIcons, (int *)0},
150   {"IconFont",          assign_string,  &Scr.IconFont.name, (int *)0},
151   {"IconTitle",		SetFlag,	(char **)IconTitle, (int*)0},
152 #ifndef PRUNE
153   {"Icon",              SetOneStyle,    (char **)&Scr.TheList,(int *)ICON_FLAG},
154 #endif
155   {"KeepIconWindows",   SetFlag,        (char **)KeepIconWindows, (int *)0},
156 /*
157   {"MWMDecorHints",     SetFlag,        (char **)MWMDecorHints, (int *)0},
158   {"MWMFunctionHints",  SetFlag,        (char **)MWMFunctionHints, (int *)0},
159   {"MWMHintOverride",   SetFlag,        (char **)MWMHintOverride, (int *)0},
160 */
161 /*  {"Lenience",          SetFlag,        (char **)Lenience, (int *)0},
162 */
163   {"NoPPosition",       SetFlag,        (char **)NoPPosition, (int *)0},
164   {"CirculateSkipIcons",SetFlag,        (char **)CirculateSkipIcons, (int *)0},
165 
166 #ifndef PRUNE
167   {"NoFocus",           SetOneStyle,    (char **)&Scr.TheList,
168                                         (int *)NOFOCUS_FLAG},
169   {"NoTitle",           SetOneStyle,    (char **)&Scr.TheList,
170                                         (int *)NOTITLE_FLAG},
171   {"NoBorder",          SetOneStyle,    (char **)&Scr.TheList,
172                                         (int *)NOBORDER_FLAG},
173   {"Sticky",            SetOneStyle,    (char **)&Scr.TheList,
174                                         (int *)STICKY_FLAG},
175   {"StaysOnTop",        SetOneStyle,    (char **)&Scr.TheList,
176                                         (int *)STAYSONTOP_FLAG},
177   {"StartsOnDesk",      SetOneStyle,    (char **)&Scr.TheList,
178                                         (int *)STAYSONDESK_FLAG},
179   {"CirculateSkip",     SetOneStyle,    (char **)&Scr.TheList,
180                                         (int *)CIRCULATESKIP_FLAG},
181   {"WindowListSkip",    SetOneStyle,    (char **)&Scr.TheList,
182                                         (int *)LISTSKIP_FLAG},
183 #endif
184   {"Style",             ParseStyle,     (char **)0, (int *)0},
185   {"EdgeScroll",        SetInts,        (char **)&Scr.EdgeScrollX,
186                                                  &Scr.EdgeScrollY},
187   {"RandomPlacement",   SetFlag,        (char **)RandomPlacement, (int *)0},
188   {"SmartPlacement",    SetFlag,        (char **)SMART_PLACEMENT, (int *)0},
189 #ifndef PRUNE
190   {"SuppressIcons",     SetFlag,        (char **)SuppressIcons, (int *)0},
191 #endif
192   {"DontMoveOff",       SetFlag,        (char **)DontMoveOff, (int *)0},
193   {"DecorateTransients",SetFlag,        (char **)DecorateTransients, (int *)0},
194   {"CenterOnCirculate", SetFlag,        (char **)CenterOnCirculate, (int *)0},
195   {"AutoRaise",         SetInts,        (char **)&Scr.AutoRaiseDelay,&dummy},
196 #ifndef NO_PAGER
197   {"PagerBackColor",    assign_string,  &Pagerback, (int *)0},
198   {"PagerForeColor",    assign_string,  &Pagerfore, (int *)0},
199   {"PagerFont",         assign_string,  &Scr.PagerFont.name, (int *)0},
200   {"Pager",             SetInts,        (char **)&pager_x, &pager_y},
201 #endif
202   {"DeskTopScale",      SetInts,        (char **)&Scr.VScale, &dummy},
203   {"DeskTopSize",       SetInts,        (char **)&Scr.VxMax, &Scr.VyMax},
204   {"ClickTime",         SetInts,        (char **)&Scr.ClickTime, &dummy},
205   {"OpaqueMove",        SetInts,        (char **)&Scr.OpaqueSize, &dummy},
206 #ifndef PRUNE
207   {"BoundaryWidth",     SetInts,        (char **)&Scr.BoundaryWidth,&dummy},
208   {"NoBoundaryWidth",   SetInts,        (char **)&Scr.NoBoundaryWidth,&dummy},
209 #endif
210   {"XorValue",          SetInts,        (char **)&XORvalue, &dummy},
211   {"Mouse",             ParseMouseEntry,(char **)1, (int *)0},
212   {"Popup",             ParsePopupEntry,(char **)1, (int *)0},
213   {"Function",          ParsePopupEntry,(char **)1, (int *)0},
214   {"Key",               ParseKeyEntry,  (char **)1, (int *)0},
215   {"ClickToFocus",      SetFlag,        (char **)ClickToFocus,
216                                                  (int *)EatFocusClick},
217   {"ClickToRaise",  SetButtonList,  (char **)&Scr.RaiseButtons, (int*)0},
218   {"MenusHigh",          SetFlag,    	(char **)MenusHigh,(int *)0},
219   {"SloppyFocus",       SetFlag,        (char **)SloppyFocus,(int *)0},
220   {"Cursor",            SetCursor,      (char **)0, (int *)0},
221   {"PagingDefault",     SetInts,        (char **)&DoHandlePageing, &dummy},
222   {"EdgeResistance",    SetInts,        (char **)&Scr.ScrollResistance,
223                                                  &Scr.MoveResistance},
224   {"BackingStore",      SetFlag,        (char **)BackingStore, (int *)0},
225   {"AppsBackingStore",  SetFlag,        (char **)AppsBackingStore, (int *)0},
226   {"SaveUnders",        SetFlag,        (char **)SaveUnders, (int *)0},
227 
228   {"ModulePath",        assign_string,  &ModulePath, (int *)0},
229 #ifndef PRUNE
230   {"Module",            executeModule,  (char **)0, (int *)0},
231 #endif
232 #ifdef ENABLE_TEXTURE
233   {"TitleBarStyle",	assign_string,	&TitleStyle,	(int *)0},
234   {"TextureTypes",	assign_string,	&TexTypes, (int *)0},
235   {"TextureMaxColors", assign_string,	&TexMaxcols, (int *)0},
236 
237   {"TitleTextureColor", assign_string,  &TColor, (int*)0}, /* title */
238   {"MenuTextureColor", assign_string,  &IColor, (int*)0},  /* menu items */
239   {"UTitleTextureColor", assign_string,  &UColor, (int*)0}, /*unfocused title*/
240   {"MTitleTextureColor", assign_string,  &MColor, (int*)0}, /* menu title */
241   {"STitleTextureColor", assign_string,  &SColor, (int*)0}, /* sticky title */
242   {"TitlePixmap", assign_string, &TPixmap, (int*)0},	/* title pixmap */
243   {"UTitlePixmap", assign_string, &UPixmap, (int*)0},	/* title pixmap */
244   {"STitlePixmap", assign_string, &SPixmap, (int*)0},	/* title pixmap */
245   {"TextGradientColor", assign_string,  &TGColor, (int*)0}, /* title text */
246   {"TexturedHandle", SetTextureFlag,	(char **)TexturedHandle, (int *)0},
247   {"TitlebarNoPush", SetTextureFlag,	(char **)TitlebarNoPush, (int *)0},
248   {"GradientText", SetTextureFlag,	(char **)GradientText, (int *)0},
249   {"ButtonTextureType", SetInts,        (char **)&IconTexType, &dummy},
250   {"ButtonBgColor",     assign_string,  &IconBgColor, (int *)0},
251   {"ButtonTextureColor",assign_string,  &IconTexColor, (int *)0},
252   {"ButtonMaxColors",   SetInts,        (char **)&IconMaxColors, &dummy},
253   {"ButtonPixmap",      assign_string,  &IconPixmapFile, (int *)0},
254   {"ButtonNoBorder",    SetIconFlag,    (char **)IconNoBorder, (int *)0},
255 #endif
256   {"TitleTextAlign",    SetInts,        (char **)&Scr.TitleTextAlign, &dummy},
257   {"TitleButton",       SetTitleButton, (char **)1, (int *)0},
258   {"",                  0,              (char **)0, (int *)0}
259 };
260 
261 struct config func_config[] =
262 {
263   {"Nop",          set_func,(char **)F_NOP},
264   {"Title",        set_func,(char **)F_TITLE},
265   {"Beep",         set_func,(char **)F_BEEP},
266   {"Quit",         set_func,(char **)F_QUIT},
267   {"Refresh",      set_func,(char **)F_REFRESH},
268   {"Move",         set_func,(char **)F_MOVE},
269   {"Iconify",      set_func,(char **)F_ICONIFY},
270   {"Maximize",     set_func,(char **)F_MAXIMIZE},
271   {"Shade",	   set_func,(char **)F_SHADE},
272   {"Resize",       set_func,(char **)F_RESIZE},
273   {"RaiseLower",   set_func,(char **)F_RAISELOWER},
274   {"Raise",        set_func,(char **)F_RAISE},
275   {"PutOnTop",	   set_func,(char **)F_PUTONTOP},
276   {"Lower",        set_func,(char **)F_LOWER},
277   {"Delete",       set_func,(char **)F_DELETE},
278   {"Close",        set_func,(char **)F_CLOSE},
279   {"Destroy",      set_func,(char **)F_DESTROY},
280   {"PopUp",        set_func,(char **)F_POPUP},
281   {"Function",     set_func,(char **)F_FUNCTION},
282   {"CursorMove",   set_func,(char **)F_MOVECURSOR},
283   {"Stick",        set_func,(char **)F_STICK},
284   {"CirculateUp",  set_func,(char **)F_CIRCULATE_UP},
285   {"CirculateDown",set_func,(char **)F_CIRCULATE_DOWN},
286   {"Wait",         set_func,(char **)F_WAIT},
287   {"Warp",         set_func,(char **)F_WARP},
288   {"Desk",         set_func,(char **)F_DESK},
289   {"WindowsDesk",  set_func,(char **)F_CHANGE_WINDOWS_DESK},
290   {"Focus",        set_func,(char **)F_FOCUS},
291   {"Module",       set_func,(char **)F_MODULE},
292   {"Quickie",       set_func,(char **)F_QUICKIE},
293   {"Send_WindowList",set_func, (char **)F_SEND_WINDOW_LIST},
294 
295 #ifndef NON_VIRTUAL
296   {"Scroll",       set_func,(char **)F_SCROLL},
297   {"GotoPage",     set_func,(char **)F_GOTO_PAGE},
298   {"TogglePage",   set_func,(char **)F_TOGGLE_PAGE},
299 #endif
300   {"Exec",         set_func,(char **)F_EXEC},
301   {"Restart",      set_func,(char **)F_RESTART},
302 #ifndef NO_WINDOWLIST
303   {"WindowList",   set_func,(char **)F_WINDOWLIST},
304 #endif
305   {"",                    0,(char **)0}
306 };
307 
308 struct charstring
309 {
310   char key;
311   int  value;
312 };
313 
314 
315 /* The keys musat be in lower case! */
316 struct charstring win_contexts[]=
317 {
318   {'w',C_WINDOW},
319   {'t',C_TITLE},
320   {'i',C_ICON},
321   {'r',C_ROOT},
322   {'f',C_FRAME},
323   {'s',C_SIDEBAR},
324   {'1',C_L1},
325   {'2',C_R1},
326   {'3',C_L2},
327   {'4',C_R2},
328   {'5',C_L3},
329   {'6',C_R3},
330   {'7',C_L4},
331   {'8',C_R4},
332   {'9',C_L5},
333   {'0',C_R5},
334   {'a',C_WINDOW|C_TITLE|C_ICON|C_ROOT|C_FRAME|C_SIDEBAR|
335      C_L1|C_L2|C_L3|C_L4|C_L5|C_R1|C_R2|C_R3|C_R4|C_R5},
336   {0,0}
337 };
338 
339 /* The keys musat be in lower case! */
340 struct charstring key_modifiers[]=
341 {
342   {'s',ShiftMask},
343   {'c',ControlMask},
344   {'m',Mod1Mask},
345   {'1',Mod1Mask},
346   {'2',Mod2Mask},
347   {'3',Mod3Mask},
348   {'4',Mod4Mask},
349   {'5',Mod5Mask},
350   {'a',AnyModifier},
351   {'n',0},
352   {0,0}
353 };
354 
355 void     find_context(char *, int *, struct charstring *);
356 char *orig_tline;
357 FILE *config_fd = (FILE *)0;
358 /* we'll let modules get the afterstep_file that configuration was based on
359  * for consistency */
360 char *afterstep_file;
361 
362 #ifdef M4
363 static char *m4_defs(Display*, const char*, char*, char*);
364 #endif
365 
366 /***************************************************************
367  *
368  * Read a XPM file
369  *
370  **************************************************************/
GetXPMTile(char * file)371 Pixmap GetXPMTile(char *file)
372 {
373     XWindowAttributes root_attr;
374     XpmAttributes xpm_attributes;
375     extern char *PixmapPath;
376     char *path = NULL;
377     Pixmap pix, mask;
378 #ifdef XPM
379 
380     path = findIconFile(file, PixmapPath,R_OK);
381     if(path == NULL)return None;
382 
383     XGetWindowAttributes(dpy,Scr.Root,&root_attr);
384     xpm_attributes.colormap = root_attr.colormap;
385     xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
386     xpm_attributes.valuemask = XpmReturnPixels | XpmColormap | XpmCloseness;
387 
388     if (XpmReadFileToPixmap(dpy, Scr.Root, path,
389 			    &pix, &mask,
390 			    &xpm_attributes) != XpmSuccess ) {
391 	free(path);
392 	return None;
393     }
394     free(path);
395     if (mask!=None)
396       XFreePixmap(dpy,mask);
397 #else
398     pix = None;
399 #endif
400     return pix;
401 }
402 
403 /*****************************************************************************
404  *
405  * This routine is responsible for reading and parsing the config file
406  *
407  ****************************************************************************/
MakeMenus(const char * display_name,char * m4_options)408 void MakeMenus(const char *display_name, char *m4_options)
409 {
410   char *system_file = STEPRC;
411   char *home_file;
412   char line[256],*tline;
413   char *Home;			/* the HOME environment variable */
414   int HomeLen;			/* length of Home */
415 #ifdef ENABLE_TEXTURE
416   int icol, mcol, ucol, tcol, scol;	/* texture colors */
417   int defcol;
418 #endif
419 
420 #ifdef M4
421   extern int m4_enable;
422 #endif
423   XORvalue = (((unsigned long) 1) << Scr.d_depth) - 1;
424 
425   Menuback = white;
426   Menufore = black;
427   Menustipple = grey;
428   Stdback = white;
429   Stdfore = black;
430   Stickyback = NULL;
431   Stickyfore = NULL;
432   Hiback = white;
433   Hifore = black;
434 #ifndef NO_PAGER
435   Pagerback = white;
436   Pagerfore = black;
437 #endif
438 
439   /* initialize some lists */
440   Scr.MouseButtonRoot = NULL;
441   Scr.FuncKeyRoot.next = NULL;
442   Scr.TheList = NULL;
443 
444   Scr.DefaultIcon = NULL;
445 
446   /* find the home directory to look in */
447   Home = getenv("HOME");
448   if (Home == NULL)
449     Home = "./";
450   HomeLen = strlen(Home);
451 
452   if(config_file[0] == '/')
453     {
454       home_file = safemalloc(strlen(config_file)+1);
455       strcpy(home_file,config_file);
456     }
457   else if(strncmp(config_file,"~/",2)==0)
458     {
459       home_file = safemalloc(HomeLen + strlen(&config_file[2])+3);
460       strcpy(home_file,Home);
461       strcat(home_file,"/");
462       strcat(home_file,&config_file[2]);
463     }
464   else
465     {
466       home_file = safemalloc(HomeLen+strlen(config_file)+3);
467       strcpy(home_file,Home);
468       strcat(home_file,"/");
469       strcat(home_file,config_file);
470     }
471   afterstep_file = home_file;
472   config_fd = fopen(home_file,"r");
473   if(config_fd == (FILE *)NULL)
474     {
475       afterstep_file = system_file;
476       config_fd = fopen(system_file,"r");
477     }
478   if(config_fd == (FILE *)NULL)
479     {
480       afterstep_err("can't open %s or %s",system_file,home_file,NULL);
481       exit(1);
482     }
483   if(afterstep_file != home_file)
484     free(home_file);
485 
486 #ifdef M4
487   if (m4_enable)
488     {
489       /*
490        * Process the config file through m4 and save the
491        * results in a temp file.
492        */
493 
494       afterstep_file = m4_defs(dpy, display_name, m4_options, afterstep_file);
495       fclose(config_fd);
496 
497       config_fd = fopen(afterstep_file, "r");
498 
499       if (config_fd == (FILE *) 0)
500 	{
501 	  perror("Cannot open m4-processed config file\n");
502 	  exit(1);
503 	}
504     }
505 #endif	/* M4 */
506 
507   tline = fgets(line,(sizeof line)-1,config_fd);
508   orig_tline = tline;
509   while(tline != (char *)0)
510     {
511       while(isspace(*tline))tline++;
512       if((strlen(&tline[0])>1)&&(tline[0]!='#')&&(tline[0]!='*'))
513 	match_string(main_config,tline,"error in config:",config_fd);
514       tline = fgets(line,(sizeof line)-1,config_fd);
515       orig_tline = tline;
516     }
517   fclose(config_fd);
518   config_fd = (FILE *)NULL;
519 
520 #ifdef ENABLE_TEXTURE
521     if (!TexTypes) {
522 	Textures.Ttype = 0;
523 	Textures.Itype = 0;
524 	Textures.Utype = 0;
525 	Textures.Mtype = 0;
526 	Textures.Stype = 0;
527     } else {
528 	scol=tcol=ucol=mcol=icol=-1;
529 	sscanf(TexTypes, "%i %i %i %i %i",&tcol, &ucol, &scol, &mcol,&icol);
530 	Textures.Ttype = (tcol >= 0 ? tcol : 0);
531 	Textures.Itype = (icol >= 0 ? icol : 0);
532 	Textures.Utype = (ucol >= 0 ? ucol : 0);
533 	Textures.Mtype = (mcol >= 0 ? mcol : 0);
534 	Textures.Stype = (scol >= 0 ? scol : 0);
535     }
536     if (Scr.d_depth > 8) {
537 	defcol = 32;
538     } else {
539 	defcol = 10;
540     }
541     if (!TexMaxcols) {
542 	Textures.Tmaxcols = defcol;
543 	Textures.Imaxcols = defcol;
544 	Textures.Mmaxcols = defcol;
545 	Textures.Umaxcols = defcol;
546 	Textures.Smaxcols = defcol;
547     } else {
548 	scol=tcol=ucol=mcol=icol=-1;
549 	sscanf(TexMaxcols, "%i %i %i %i %i",&tcol, &ucol, &scol, &mcol, &icol);
550 	Textures.Tmaxcols = (tcol >= 0 ? tcol : defcol);
551 	Textures.Imaxcols = (icol >= 0 ? icol : defcol);
552 	Textures.Umaxcols = (ucol >= 0 ? ucol : defcol);
553 	Textures.Mmaxcols = (mcol >= 0 ? mcol : defcol);
554 	Textures.Smaxcols = (scol >= 0 ? scol : defcol);
555     }
556     InitTextureData(&Textures, TColor, UColor, MColor, IColor, SColor,
557 					TGColor);
558     /* load titlebar pixmaps */
559     if (Textures.Ttype==TEXTURE_PIXMAP) {
560 	if (TPixmap==NULL)
561 	  Textures.Ttype=0;
562 	else  {
563 	    if ((Scr.ForeTitle=GetXPMTile(TPixmap))==None) {
564 		printf("couldn't load Titlebar tile pixmap\n");
565      		Textures.Ttype = 0;
566 	    }
567 	}
568     }
569     if (Textures.Utype==TEXTURE_PIXMAP) {
570 	if (UPixmap==NULL)
571 	  Textures.Utype=0;
572 	else  {
573 	    if ((Scr.BackTitle=GetXPMTile(UPixmap))==None) {
574 		printf("couldn't load unfocused Titlebar tile pixmap\n");
575      		Textures.Utype = 0;
576 	    }
577 	}
578     }
579     if (Textures.Stype==TEXTURE_PIXMAP) {
580 	if (SPixmap==NULL)
581 	  Textures.Stype=0;
582 	else  {
583 	    if ((Scr.StickyTitle=GetXPMTile(SPixmap))==None) {
584 		printf("couldn't load sticky Titlebar tile pixmap\n");
585      		Textures.Stype = 0;
586 	    }
587 	}
588     }
589 
590     /* cache textures for ideal cases (types 2 and 3) */
591     if (Textures.Ttype==2 || Textures.Ttype==3) {
592 		Scr.ForeTitle = XCreatePixmap(dpy, Scr.Root, Scr.MyDisplayWidth-1,
593 									  NS_TITLE_HEIGHT, Scr.d_depth);
594 		if (Scr.ForeTitle!=None) {
595 			if (!DrawHGradient(dpy, Scr.ForeTitle, 0, 0,
596 							   Scr.MyDisplayWidth-1, NS_TITLE_HEIGHT,
597 							   Textures.Tfrom, Textures.Tto, 1,
598 							   Textures.Tmaxcols, Textures.Ttype-2)) {
599 				XFreePixmap(dpy, Scr.ForeTitle);
600 				Scr.ForeTitle = None;
601 				Textures.Ttype = 0;
602 			}
603 		} else {
604 			Textures.Ttype = 0;
605 		}
606     }
607 	if (Textures.Ttype!=0) {
608 		unsigned long light, dark;
609 		XGCValues gcv;
610 
611 		if (MakeShadowColors(dpy, Textures.Tfrom, Textures.Tto,
612 				     &dark, &light)) {
613 			gcv.foreground=light;
614 			Scr.BevelReliefGC = XCreateGC(dpy, Scr.Root, GCForeground, &gcv);
615 			gcv.foreground=dark;
616 			Scr.BevelShadowGC = XCreateGC(dpy, Scr.Root, GCForeground, &gcv);
617 		} else {
618 			Scr.BevelReliefGC = Scr.BevelShadowGC = None;
619 		}
620 	} else {
621 		Scr.BevelReliefGC = Scr.BevelShadowGC = None;
622 	}
623 	if (Textures.flags & GradientText) {
624 		Scr.TitleGradient=XCreatePixmap(dpy,Scr.Root,Scr.MyDisplayWidth-1,
625 									   Scr.WindowFont.height, Scr.d_depth);
626 		if (!DrawHGradient(dpy, Scr.TitleGradient, 0, 0,
627 						   Scr.MyDisplayWidth-1, Scr.WindowFont.height,
628 						   Textures.TGfrom, Textures.TGto, 0, 6, 0)) {
629 			XFreePixmap(dpy,Scr.TitleGradient);
630 			Scr.TitleGradient=None;
631 			Textures.flags &= ~GradientText;
632 		}
633 	}
634     if (Textures.Utype==2 || Textures.Utype==3) {
635 	Scr.BackTitle = XCreatePixmap(dpy, Scr.Root, Scr.MyDisplayWidth-1,
636 				      NS_TITLE_HEIGHT, Scr.d_depth);
637 	if (Scr.BackTitle!=None) {
638 	    if (!DrawHGradient(dpy, Scr.BackTitle, 0, 0,
639 			       Scr.MyDisplayWidth-1, NS_TITLE_HEIGHT,
640 			       Textures.Ufrom, Textures.Uto, 1,
641 			       Textures.Umaxcols, Textures.Utype-2)) {
642 		XFreePixmap(dpy, Scr.BackTitle);
643 		Scr.BackTitle = None;
644 		Textures.Utype = 0;
645 	    }
646 	} else
647 	  Textures.Utype = 0;
648     }
649 
650     if (Textures.Stype==2 || Textures.Stype==3) {
651 	Scr.StickyTitle = XCreatePixmap(dpy, Scr.Root, Scr.MyDisplayWidth-1,
652 					NS_TITLE_HEIGHT, Scr.d_depth);
653 	if (Scr.StickyTitle!=None) {
654 	    if (!DrawHGradient(dpy, Scr.StickyTitle, 0, 0,
655 			       Scr.MyDisplayWidth-1, NS_TITLE_HEIGHT,
656 			       Textures.Sfrom, Textures.Sto, 1,
657 			       Textures.Smaxcols, Textures.Stype-2)) {
658 		XFreePixmap(dpy, Scr.StickyTitle);
659 		Scr.StickyTitle = None;
660 		Textures.Stype=0;
661 	    }
662 	} else
663 	  Textures.Stype=0;
664     }
665 #endif	/* ENABLE_TEXTURE */
666 
667     /* create pixmaps for buttons */
668   ButtonStyle();
669 
670   /* If no edge scroll line is provided in the setup file, use
671    * a default */
672   if(Scr.EdgeScrollX == -100000)
673     Scr.EdgeScrollX = 25;
674   if(Scr.EdgeScrollY == -100000)
675     Scr.EdgeScrollY = Scr.EdgeScrollX;
676 
677   /* if edgescroll >1000 and < 100000m
678    * wrap at edges of desktop (a "spherical" desktop) */
679    if (Scr.EdgeScrollX >= 1000)
680      {
681        Scr.EdgeScrollX /= 1000;
682        Scr.flags |= EdgeWrapX;
683      }
684    if (Scr.EdgeScrollY >= 1000)
685      {
686        Scr.EdgeScrollY /= 1000;
687        Scr.flags |= EdgeWrapY;
688      }
689 
690   Scr.EdgeScrollX=Scr.EdgeScrollX*Scr.MyDisplayWidth/100;
691   Scr.EdgeScrollY=Scr.EdgeScrollY*Scr.MyDisplayHeight/100;
692 
693   Scr.VxMax = Scr.VxMax*Scr.MyDisplayWidth - Scr.MyDisplayWidth;
694   Scr.VyMax = Scr.VyMax*Scr.MyDisplayHeight - Scr.MyDisplayHeight;
695   if(Scr.VxMax <0)
696     Scr.VxMax = 0;
697   if(Scr.VyMax <0)
698     Scr.VyMax = 0;
699 
700   if (Scr.VxMax == 0)
701     Scr.flags &= ~EdgeWrapX;
702   if (Scr.VyMax == 0)
703     Scr.flags &= ~EdgeWrapY;
704 
705   GetColors();
706 
707     /* create pixmap for icon button background */
708   IconStyle();
709 
710 #ifndef NO_PAGER
711   if(pager_x < 10000)initialize_pager(pager_x,pager_y);
712 #endif
713 
714   if ((Scr.flags & ClickToRaise) && (Scr.AutoRaiseDelay == 0))
715       Scr.AutoRaiseDelay = -1;
716 
717   return;
718 }
719 
720 
721 /*****************************************************************************
722  *
723  * Copies a text string from the config file to a specified location
724  *
725  ****************************************************************************/
assign_string(char * text,FILE * fd,char ** arg,int * junk)726 void assign_string(char *text, FILE *fd, char **arg, int *junk)
727 {
728   *arg = stripcpy(text);
729 }
730 
731 /*****************************************************************************
732  *
733  * read the button pixmaps
734  *
735  ****************************************************************************/
ButtonStyle()736 void ButtonStyle()
737 {
738   XWindowAttributes root_attr;
739   XpmAttributes xpm_attributes;
740   Pixmap mask;
741 
742 
743   XGetWindowAttributes(dpy, Scr.Root, &root_attr);
744   xpm_attributes.colormap = root_attr.colormap;
745   xpm_attributes.closeness = 4000;
746   xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|XpmCloseness;
747 
748   if (!Scr.button_pixmap[2]) {
749     if( XpmCreatePixmapFromData(dpy, Scr.Root, closebutton_xpm,
750 				&Scr.button_pixmap[2], &mask,
751 				&xpm_attributes) != XpmSuccess ) {
752       afterstep_err("Can not read closebutton_xpm to buttonstyles",NULL, NULL, NULL);
753       return;
754     }
755     Scr.button_width[2] = xpm_attributes.width;
756     Scr.button_height[2] = xpm_attributes.height;
757     Scr.button_style[2] = XPM_BUTTON_STYLE;
758 
759     if (mask!=None)
760       XFreePixmap(dpy,mask);
761   }
762 
763   if (!Scr.button_pixmap[1]) {
764     if ( XpmCreatePixmapFromData(dpy, Scr.Root, minbutton_xpm,
765 				 &Scr.button_pixmap[1], &mask,
766 				 &xpm_attributes) != XpmSuccess  ) {
767       afterstep_err("Can not read minbutton_xpm to buttonstyles",NULL, NULL, NULL);
768       return;
769     }
770     Scr.button_width[1] = xpm_attributes.width;
771     Scr.button_height[1] = xpm_attributes.height;
772     Scr.button_style[1] = XPM_BUTTON_STYLE;
773 
774     if (mask!=None)
775       XFreePixmap(dpy,mask);
776   }
777 }
778 
779 /****************************************************************************
780  *
781  *  Read Titlebar pixmap button
782  *
783  ****************************************************************************/
SetTitleButton(char * tline,FILE * fd,char ** junk,int * junk2)784 void SetTitleButton(char *tline,FILE *fd, char **junk,int *junk2)
785 {
786 #ifdef XPM
787   XWindowAttributes root_attr;
788   XpmAttributes xpm_attributes;
789   extern char *PixmapPath;
790   char *path = NULL;
791   Pixmap mask;
792   int num;
793   char file[256];
794   int n;
795 
796   n = sscanf(tline,"%d %s",&num,file);
797 
798   if (n != 2) {
799     printf("wrong number of parameters given with TitleButton\n");
800   }
801   if (num < 0 || num > 9) {
802     printf("invalid Titlebar button number: %d\n", num);
803   }
804 
805   path = findIconFile(file,PixmapPath,R_OK);
806   if(path == NULL) {
807     printf("couldn't find Titlebar button %s\n", file);
808     return;
809   }
810 
811   XGetWindowAttributes(dpy,Scr.Root,&root_attr);
812   xpm_attributes.colormap  = root_attr.colormap;
813   xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
814   xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|XpmCloseness;
815 
816   if (XpmReadFileToPixmap(dpy, Scr.Root, path,
817 			  &Scr.button_pixmap[num], &mask,
818 			  &xpm_attributes) != XpmSuccess ) {
819     printf("couldn't read Titlebar button pixmap %s\n", path);
820     free(path);
821     return;
822   }
823 
824   Scr.button_width[num]  = xpm_attributes.width;
825   Scr.button_height[num] = xpm_attributes.height;
826   Scr.button_style[num]  = XPM_BUTTON_STYLE;
827 
828   free(path);
829   if (mask!=None)
830     XFreePixmap(dpy,mask);
831 
832 #endif /* XPM */
833 }
834 
835 /****************************************************************************
836  *
837  * Use builtin pixmap for iconized window background (aka Buttons)
838  *
839  ****************************************************************************/
SetBuiltInIconBg()840 static void SetBuiltInIconBg()
841 {
842 #ifdef XPM
843   XWindowAttributes root_attr;
844   XpmAttributes xpm_attributes;
845 
846   XGetWindowAttributes(dpy,Scr.Root,&root_attr);
847   xpm_attributes.colormap = root_attr.colormap;
848   xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
849   xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
850 
851   if(XpmCreatePixmapFromData(dpy, Scr.Root, button_xpm,
852 			     &Scr.IconBgPixmap, &Scr.IconBgMask,
853 			     &xpm_attributes) == XpmSuccess ) {
854     Scr.IconBgWidth = xpm_attributes.width;
855     Scr.IconBgHeight = xpm_attributes.height;
856     Scr.IconBgDepth = Scr.d_depth;
857   } else {
858     afterstep_err("couldn't create background icon pixmap.",NULL, NULL, NULL);
859     exit(1);
860   }
861 #endif /* XPM */
862 }
863 
864 
865 /****************************************************************************
866  *
867  * Giv'em that raised look ... the eazy way :-)
868  *
869  ****************************************************************************/
DrawOutline(Drawable d,int w,int h)870 static void DrawOutline(Drawable d, int w, int h)
871 {
872   if (IconTexFlags & IconNoBorder)
873     return;
874   /* top */
875   XDrawLine( dpy, d, Scr.NormalGC, 0, 0, w-1, 0);
876   XDrawLine( dpy, d, Scr.StdReliefGC, 0, 1, w-1, 1);
877   /* bottom */
878   XFillRectangle(dpy, d, Scr.StdShadowGC, 0,h-2,w-1,h-1);
879 
880   /* left */
881   XDrawLine( dpy, d, Scr.NormalGC, 0, 1, 0, h-1);
882   XDrawLine( dpy, d, Scr.StdReliefGC, 1, 2, 1, h-2);
883   /* right */
884   XDrawLine( dpy, d, Scr.StdShadowGC, w-1, 1, w-1, h-1);
885   XDrawLine( dpy, d, Scr.StdShadowGC, w-2, 2, w-2, h-2);
886 }
887 
888 /***************************************************************
889  *
890  * Read a XPM Icon Background from file
891  *
892  **************************************************************/
GetXPMIconFile(char * file)893 static int GetXPMIconFile(char *file)
894 {
895 #ifdef XPM
896     XWindowAttributes root_attr;
897     XpmAttributes xpm_attributes;
898     extern char *PixmapPath;
899     char *path = NULL;
900 
901     path = findIconFile(file, PixmapPath,R_OK);
902     if(path == NULL) return False;
903 
904     XGetWindowAttributes(dpy,Scr.Root,&root_attr);
905     xpm_attributes.colormap = root_attr.colormap;
906     xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
907     xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
908 
909     if (XpmReadFileToPixmap(dpy, Scr.Root, path,
910 			    &Scr.IconBgPixmap, &Scr.IconBgMask,
911 			    &xpm_attributes) != XpmSuccess ) {
912 	free(path);
913 	return False;
914     }
915     free(path);
916     Scr.IconBgWidth = xpm_attributes.width;
917     Scr.IconBgHeight = xpm_attributes.height;
918     Scr.IconBgDepth = Scr.d_depth;
919 
920     DrawOutline(Scr.IconBgPixmap,Scr.IconBgWidth,Scr.IconBgHeight);
921 
922     return True;
923 #else
924     return False;
925 #endif
926 }
927 
928 /*******************************************************************
929  *
930  * Make a gradient pixmap for iconized windows background (aka Buttons)
931  *
932  *******************************************************************/
933 
GetXPMGradient(int from[3],int to[3],int maxcols,int type)934 static int GetXPMGradient(int from[3], int to[3], int maxcols, int type)
935 {
936   Scr.IconBgPixmap = XCreatePixmap(dpy,Scr.Root,64,64,Scr.d_depth);
937   Scr.IconBgMask = None;
938   Scr.IconBgWidth = 64;
939   Scr.IconBgHeight = 64;
940   Scr.IconBgDepth = Scr.d_depth;
941 
942   switch (type) {
943     case TEXTURE_GRADIENT:
944       if (!DrawDegradeRelief(dpy, Scr.IconBgPixmap, 0,0,64,64,
945 			     from, to, 0, maxcols)) {
946 	XFreePixmap(dpy, Scr.IconBgPixmap);
947 	return 0;
948       }
949       break;
950     case TEXTURE_HGRADIENT:
951     case TEXTURE_HCGRADIENT:
952       if (!DrawHGradient(dpy, Scr.IconBgPixmap, 0, 0, 64,64,
953                          from, to, 0, maxcols, type-TEXTURE_HGRADIENT)) {
954 	XFreePixmap(dpy, Scr.IconBgPixmap);
955 	return 0;
956       }
957       break;
958     case TEXTURE_VGRADIENT:
959     case TEXTURE_VCGRADIENT:
960       if (!DrawVGradient(dpy, Scr.IconBgPixmap, 0, 0, 64,64,
961                          from, to, 0, maxcols, type-TEXTURE_VGRADIENT)) {
962 	XFreePixmap(dpy, Scr.IconBgPixmap);
963 	return 0;
964       }
965       break;
966     default:
967       return 0;
968   }
969 
970   DrawOutline(Scr.IconBgPixmap,64,64);
971   return 1;
972 }
973 
974 /*******************************************************************
975  *
976  * Make a solid color pixmap for iconized windows background (aka Buttons)
977  *
978  *******************************************************************/
979 
GetSolidXPM(Pixel pixel)980 static int GetSolidXPM(Pixel pixel)
981 {
982     GC gc;
983     XGCValues gcv;
984 
985     gcv.foreground = pixel;
986     gc = XCreateGC(dpy,Scr.Root,GCForeground, &gcv);
987 
988     Scr.IconBgPixmap = XCreatePixmap(dpy,Scr.Root,64,64, Scr.d_depth);
989     Scr.IconBgMask = None;
990     Scr.IconBgWidth = 64;
991     Scr.IconBgHeight = 64;
992     Scr.IconBgDepth = Scr.d_depth;
993 
994     XFillRectangle(dpy,Scr.IconBgPixmap,gc,0,0,64,64);
995 
996     XFreeGC(dpy,gc);
997     DrawOutline(Scr.IconBgPixmap,64,64);
998 
999     return 1;
1000 }
1001 
1002 /*****************************************************************************
1003  *
1004  * Create pixmap for icon background
1005  *
1006  ****************************************************************************/
IconStyle()1007 void IconStyle()
1008 {
1009 #ifdef ENABLE_TEXTURE
1010 int FromColor[3] = {0x4000,0x4000,0x4000};
1011 int ToColor[3]   = {0x8000,0x8000,0x8000};
1012 Pixel BgColor;
1013 #endif	/* ENABLE_TEXTURE */
1014 
1015 #ifdef XPM
1016   /* Free resources if this is a restart */
1017   if (Scr.IconBgPixmap != None)
1018     XFreePixmap(dpy,Scr.IconBgPixmap);
1019   if (Scr.IconBgMask != None)
1020     XFreePixmap(dpy,Scr.IconBgMask);
1021 #endif /* XPM */
1022 
1023 #ifdef ENABLE_TEXTURE
1024   switch (IconTexType) {
1025     case TEXTURE_PIXMAP:
1026       if (IconPixmapFile == NULL) {
1027 	fprintf(stderr,"No Icon background pixmap defined. Using default.\n");
1028 	SetBuiltInIconBg();
1029       } else if (!GetXPMIconFile(IconPixmapFile)){
1030 	fprintf(stderr,"Unable to load %s. Using default.\n", IconPixmapFile);
1031 	SetBuiltInIconBg();
1032       }
1033       break;
1034 
1035     case TEXTURE_GRADIENT:
1036     case TEXTURE_HGRADIENT:
1037     case TEXTURE_HCGRADIENT:
1038     case TEXTURE_VGRADIENT:
1039     case TEXTURE_VCGRADIENT:
1040       if (IconTexColor) {
1041 	if (!ParseColor(IconTexColor, FromColor, ToColor)) {
1042 	  afterstep_err("Invalid ButtonTextureColor %s\n",IconTexColor,NULL,NULL);
1043 	}
1044       }
1045       if (!GetXPMGradient(FromColor, ToColor, IconMaxColors, IconTexType)) {
1046 	afterstep_err("couldn't create Textured Button. Using default.\n",NULL,NULL,NULL);
1047 	SetBuiltInIconBg();
1048       }
1049       break;
1050 
1051     case TEXTURE_SOLID:
1052       if (IconBgColor) {
1053 	BgColor=GetColor(IconBgColor);
1054       } else {
1055 	BgColor=GetColor("grey");
1056       }
1057 
1058       if (!GetSolidXPM(BgColor)) {
1059 	afterstep_err("couldn't create Solid Button. Using default.\n",NULL,NULL,NULL);
1060 	SetBuiltInIconBg();
1061       }
1062       break;
1063 
1064     case TEXTURE_BUILTIN:
1065     default:
1066       SetBuiltInIconBg();
1067   }
1068 #else	/* ENABLE_TEXTURE */
1069   SetBuiltInIconBg();
1070 #endif	/* ENABLE_TEXTURE */
1071     /* if the the user want icon titles, draw the titlebar into the
1072      * pixmap, so that there's less flickering */
1073   if (Scr.flags & IconTitle) {
1074 	  XSetForeground(dpy, Scr.IconGC, Scr.HiColors.back);
1075 	  XFillRectangle(dpy, Scr.IconBgPixmap, Scr.IconGC, 1, 1,
1076 			 Scr.IconBgWidth-2,Scr.IconFont.height+2);
1077   }
1078 }
1079 
1080 /*****************************************************************************
1081  *
1082  * Changes a cursor def.
1083  *
1084  ****************************************************************************/
SetCursor(char * text,FILE * fd,char ** arg,int * junk)1085 void SetCursor(char *text, FILE *fd, char **arg,int *junk)
1086 {
1087   int num,cursor_num,cursor_style;
1088 
1089   num = sscanf(text,"%d %d",&cursor_num, &cursor_style);
1090   if((num != 2)||(cursor_num >= MAX_CURSORS)||(cursor_num<0))
1091     {
1092       afterstep_err("Bad cursor in line %s",orig_tline,NULL,NULL);
1093       return;
1094     }
1095   Scr.ASCursors[cursor_num] = XCreateFontCursor(dpy,cursor_style);
1096 }
1097 
1098 /*****************************************************************************
1099  *
1100  * Sets a boolean flag to true
1101  *
1102  ****************************************************************************/
1103 /* void SetFlag(char *text, FILE *fd, char **arg,int *junk) */
SetFlag(char * text,FILE * fd,char ** arg,int * another)1104 void SetFlag(char *text, FILE *fd, char **arg, int *another)
1105 {
1106   Scr.flags |= (unsigned long)arg;
1107   if (another) {
1108     long i = strtol(text, NULL, 0);
1109     if (i)
1110       Scr.flags |= (unsigned long) another;
1111   }
1112 }
SetTextureFlag(char * text,FILE * fd,char ** arg,int * junk)1113 void SetTextureFlag(char *text, FILE *fd, char **arg,int *junk)
1114 {
1115   Textures.flags |= (unsigned long)arg;
1116 }
SetIconFlag(char * text,FILE * fd,char ** arg,int * junk)1117 void SetIconFlag(char *text, FILE *fd, char **arg,int *junk)
1118 {
1119   IconTexFlags |= (unsigned long)arg;
1120 }
1121 
1122 /*****************************************************************************
1123  *
1124  * Reads in one or two integer values
1125  *
1126  ****************************************************************************/
SetInts(char * text,FILE * fd,char ** arg1,int * arg2)1127 void SetInts(char *text, FILE *fd, char **arg1, int *arg2)
1128 {
1129   sscanf(text,"%d%*c%d",(int *)arg1,(int *)arg2);
1130 }
1131 
1132 
1133 /*****************************************************************************
1134  *
1135  * Reads in a list of mouse button numbers
1136  *
1137  ****************************************************************************/
SetButtonList(char * text,FILE * fd,char ** arg1,int * arg2)1138 void SetButtonList(char *text, FILE* fd, char **arg1, int *arg2)
1139 {
1140   int i, b;
1141   char* next;
1142   for (i = 0; i < MAX_BUTTONS; i++)
1143     {
1144       b = (int)strtol(text, &next, 0);
1145       if(next == text)  break;
1146       text = next;
1147       if (*text == ',') text++;
1148       if((b > 0) && (b <= MAX_BUTTONS))
1149 	  Scr.RaiseButtons |= 1<<b;
1150     }
1151   Scr.flags |= ClickToRaise;
1152 }
1153 
1154 
1155 /*****************************************************************************
1156  *
1157  * Reads Dimensions for an icon box from the config file
1158  *
1159  ****************************************************************************/
SetBox(char * text,FILE * fd,char ** arg,int * junk)1160 void SetBox(char *text, FILE *fd, char **arg,int *junk)
1161 {
1162   int num;
1163 
1164   if(Scr.NumBoxes < MAX_BOXES)
1165     {
1166       /* Standard X11 geometry string */
1167       num = sscanf(text,"%d%d%d%d",&Scr.IconBoxes[Scr.NumBoxes][0],
1168 	     &Scr.IconBoxes[Scr.NumBoxes][1],
1169 	     &Scr.IconBoxes[Scr.NumBoxes][2],
1170 	     &Scr.IconBoxes[Scr.NumBoxes][3]);
1171 
1172       /* check for negative locations */
1173       if(Scr.IconBoxes[Scr.NumBoxes][0] < 0)
1174 	Scr.IconBoxes[Scr.NumBoxes][0] += Scr.MyDisplayWidth;
1175       if(Scr.IconBoxes[Scr.NumBoxes][1] < 0)
1176 	Scr.IconBoxes[Scr.NumBoxes][1] += Scr.MyDisplayHeight;
1177 
1178       if(Scr.IconBoxes[Scr.NumBoxes][2] < 0)
1179 	Scr.IconBoxes[Scr.NumBoxes][2] += Scr.MyDisplayWidth;
1180       if(Scr.IconBoxes[Scr.NumBoxes][3] < 0)
1181 	Scr.IconBoxes[Scr.NumBoxes][3] += Scr.MyDisplayHeight;
1182 
1183       if(num == 4)
1184 	Scr.NumBoxes++;
1185     }
1186 }
1187 
1188 
1189 /****************************************************************************
1190  *
1191  * This routine computes the shadow color from the background color
1192  *
1193  ****************************************************************************/
GetShadow(Pixel background)1194 Pixel GetShadow(Pixel background)
1195 {
1196   XColor bg_color;
1197   XWindowAttributes attributes;
1198   unsigned int r,g,b;
1199 
1200   XGetWindowAttributes(dpy,Scr.Root,&attributes);
1201 
1202   bg_color.pixel = background;
1203   XQueryColor(dpy,attributes.colormap,&bg_color);
1204 
1205   r = bg_color.red % 0xffff;
1206   g = bg_color.green % 0xffff;
1207   b = bg_color.blue % 0xffff;
1208 
1209   r = r >>1;
1210   g = g >>1;
1211   b = b >>1;
1212 
1213   /* pure black: use gray */
1214   if( r==0 && g== 0 && b==0)
1215      r = g = b = 0x7fff;
1216   bg_color.red = r;
1217   bg_color.green = g;
1218   bg_color.blue = b;
1219 
1220   if(!XAllocColor(dpy,attributes.colormap,&bg_color))
1221     {
1222       nocolor("alloc shadow","");
1223       bg_color.pixel = background;
1224     }
1225 
1226   return bg_color.pixel;
1227 }
1228 
1229 /****************************************************************************
1230  *
1231  * This routine computes the hilight color from the background color
1232  *
1233  ****************************************************************************/
GetHilite(Pixel background)1234 Pixel GetHilite(Pixel background)
1235 {
1236   XColor bg_color, white_p;
1237   XWindowAttributes attributes;
1238 
1239   XGetWindowAttributes(dpy,Scr.Root,&attributes);
1240 
1241   bg_color.pixel = background;
1242   XQueryColor(dpy,attributes.colormap,&bg_color);
1243 
1244   white_p.pixel = GetColor(white);
1245   XQueryColor(dpy,attributes.colormap,&white_p);
1246 
1247 #ifndef min
1248 #define min(a,b) (((a)<(b)) ? (a) : (b))
1249 #define max(a,b) (((a)>(b)) ? (a) : (b))
1250 #endif
1251 
1252   /* pure black: use gray */
1253   if( bg_color.red==0 && bg_color.green== 0 && bg_color.blue==0)
1254      bg_color.red = bg_color.green = bg_color.blue = 0xbfff;
1255  else {
1256   bg_color.red = max((white_p.red/5), bg_color.red);
1257   bg_color.green = max((white_p.green/5), bg_color.green);
1258   bg_color.blue = max((white_p.blue/5), bg_color.blue);
1259 
1260   bg_color.red = min(white_p.red, (bg_color.red*140)/100);
1261   bg_color.green = min(white_p.green, (bg_color.green*140)/100);
1262   bg_color.blue = min(white_p.blue, (bg_color.blue*140)/100);
1263  }
1264 #undef min
1265 #ifdef max
1266 #undef max
1267 #endif
1268 
1269   if(!XAllocColor(dpy,attributes.colormap,&bg_color))
1270     {
1271       nocolor("alloc hilight","");
1272       bg_color.pixel = background;
1273     }
1274   return bg_color.pixel;
1275 }
1276 
1277 /****************************************************************************
1278  *
1279  * This routine loads all needed colors, and fonts,
1280  * and creates the GC's
1281  *
1282  ***************************************************************************/
1283 #ifndef NO_PAGER
1284 Pixel PagerBackColor;
1285 Pixel PagerForeColor;
1286 #endif
GetColors(void)1287 void GetColors(void)
1288 {
1289   extern MyFont *IconFont;
1290 
1291   if(have_the_colors) return;
1292 
1293   if(Stickyback == NULL)
1294     Stickyback = Stdback;
1295   if(Stickyfore == NULL)
1296     Stickyfore = Stdfore;
1297   have_the_colors = 1;
1298 
1299   /* setup default colors */
1300   if(Scr.d_depth < 2)
1301     {
1302       /* black and white - override user choices */
1303 
1304       Scr.MenuColors.back = GetColor(white);
1305       Scr.MenuColors.fore = GetColor(black);
1306       Scr.MenuStippleColors.back = GetColor(white);
1307       Scr.MenuStippleColors.fore = GetColor(black);
1308       Scr.MenuRelief.back = GetColor(black);
1309       Scr.MenuRelief.fore = GetColor(white);
1310       Scr.StdColors.back = GetColor(white);
1311       Scr.StdColors.fore = GetColor(black);
1312       Scr.StickyColors.back = GetColor(white);
1313       Scr.StickyColors.fore = GetColor(black);
1314       Scr.HiColors.back  = GetColor(white);
1315       Scr.HiColors.fore  = GetColor(black);
1316       Scr.StdRelief.back = GetColor(black);
1317       Scr.StdRelief.fore = GetColor(white);
1318       Scr.StickyRelief.back = GetColor(black);
1319       Scr.StickyRelief.fore = GetColor(white);
1320       Scr.HiRelief.back  = GetColor(black);
1321       Scr.HiRelief.fore  = GetColor(white);
1322 #ifndef NO_PAGER
1323       PagerBackColor     = GetColor(white);
1324       PagerForeColor     = GetColor(black);
1325 #endif
1326     }
1327   else
1328     {
1329       /* color - accept user choices */
1330 
1331       Scr.MenuColors.back = GetColor(Menuback);
1332       Scr.MenuColors.fore = GetColor(Menufore);
1333       Scr.MenuStippleColors.back = GetColor(Menuback);
1334       Scr.MenuStippleColors.fore = GetColor(Menustipple);
1335       Scr.MenuRelief.back = GetShadow(Scr.MenuColors.back);
1336       Scr.MenuRelief.fore = GetHilite(Scr.MenuColors.back);
1337       Scr.StdColors.back = GetColor(Stdback);
1338       Scr.StdColors.fore = GetColor(Stdfore);
1339       Scr.StickyColors.back = GetColor(Stickyback);
1340       Scr.StickyColors.fore = GetColor(Stickyfore);
1341       Scr.HiColors.back  =  GetColor(Hiback);
1342       Scr.HiColors.fore  = GetColor(Hifore);
1343       Scr.StdRelief.back = GetShadow(Scr.StdColors.back);
1344       Scr.StdRelief.fore = GetHilite(Scr.StdColors.back);
1345       Scr.StickyRelief.back = GetShadow(Scr.StickyColors.back);
1346       Scr.StickyRelief.fore = GetHilite(Scr.StickyColors.back);
1347       Scr.HiRelief.back  = GetShadow(Scr.HiColors.back);
1348       Scr.HiRelief.fore  = GetHilite(Scr.HiColors.back);
1349 #ifndef NO_PAGER
1350       PagerBackColor     = GetColor(Pagerback);
1351       PagerForeColor     = GetColor(Pagerfore);
1352 #endif
1353     }
1354 
1355   /* load the font */
1356   if ((Scr.StdFont.font = XLoadQueryFont(dpy, Scr.StdFont.name)) == NULL)
1357     {
1358       nofont(Scr.StdFont.name);
1359       if ((Scr.StdFont.font = XLoadQueryFont(dpy, "fixed")) == NULL)
1360 	exit(1);
1361     }
1362   Scr.StdFont.height = Scr.StdFont.font->ascent + Scr.StdFont.font->descent;
1363   Scr.StdFont.y = Scr.StdFont.font->ascent;
1364   Scr.EntryHeight = Scr.StdFont.height + HEIGHT_EXTRA +2;
1365   /* load the window-title font */
1366   if ((Scr.WindowFont.font = XLoadQueryFont(dpy, Scr.WindowFont.name)) == NULL)
1367     {
1368       nofont(Scr.WindowFont.name);
1369       if ((Scr.WindowFont.font = XLoadQueryFont(dpy, "fixed")) == NULL)
1370 	exit(1);
1371     }
1372 
1373   Scr.WindowFont.height=
1374     Scr.WindowFont.font->ascent+Scr.WindowFont.font->descent;
1375   Scr.WindowFont.y = Scr.WindowFont.font->ascent;
1376 
1377   /* load the pager-label font */
1378 #ifndef NO_PAGER
1379   if(Scr.PagerFont.name != NULL)
1380     {
1381       if ((Scr.PagerFont.font = XLoadQueryFont(dpy, Scr.PagerFont.name))!=NULL)
1382 	{
1383 	  Scr.PagerFont.height=
1384 	    Scr.PagerFont.font->ascent+Scr.PagerFont.font->descent;
1385 	  Scr.PagerFont.y = Scr.PagerFont.font->ascent;
1386 	}
1387       else
1388 	nofont(Scr.PagerFont.name);
1389     }
1390 #endif
1391 
1392   IconFont = &Scr.StdFont;
1393   if(Scr.IconFont.name != NULL) {
1394 	  if ((Scr.IconFont.font = XLoadQueryFont(dpy, Scr.IconFont.name))!=NULL) {
1395 		  Scr.IconFont.height=
1396 			Scr.IconFont.font->ascent+Scr.IconFont.font->descent;
1397 		  Scr.IconFont.y = Scr.IconFont.font->ascent;
1398 		  IconFont = &Scr.IconFont;
1399 	  } else
1400 		nofont(Scr.IconFont.name);
1401   } else {
1402 	  if ((Scr.IconFont.font = XLoadQueryFont(dpy, "fixed"))!=NULL) {
1403 		  Scr.IconFont.height=
1404 			Scr.IconFont.font->ascent+Scr.IconFont.font->descent;
1405 		  Scr.IconFont.y = Scr.IconFont.font->ascent;
1406 		  IconFont = &Scr.IconFont;
1407 	  } else {
1408 		  nofont("fixed: that's bad...");
1409 		  exit(1);
1410 	  }
1411   }
1412 
1413 
1414   /* create graphics contexts */
1415   CreateGCs();
1416   XSync(dpy,0);
1417   return;
1418 }
1419 
1420 /****************************************************************************
1421  *
1422  *  Prints an error message for font loading
1423  *
1424  ****************************************************************************/
nofont(char * name)1425 void nofont(char *name)
1426 {
1427   afterstep_err("can't get font %s", name,NULL,NULL);
1428 }
1429 
1430 /****************************************************************************
1431  *
1432  *  Processes a menu body definition
1433  *
1434  ****************************************************************************/
ParseMenuBody(char * name,FILE * fd)1435 MenuRoot *ParseMenuBody(char *name,FILE *fd)
1436 {
1437   MenuRoot *mr;
1438   char newline[256];
1439   register char *pline;
1440   char unit_1,unit_2;
1441   int n;
1442 
1443   pline = fgets(newline,(sizeof newline)-1,fd);
1444   orig_tline = pline;
1445   if (pline == NULL)
1446     return 0;
1447 
1448   mr = NewMenuRoot(name);
1449   GetColors();
1450 
1451   while(isspace(*pline))pline++;
1452   while((pline != (char *)0)
1453       &&(mystrncasecmp("End",pline,3)!=0))
1454     {
1455       if((*pline!='#')&&(*pline != 0)&&(*pline!='*'))
1456 	{
1457 	  char *ptr2 = 0;
1458 	  match_string(func_config,pline, "bad menu body function:",fd);
1459 	  if((func == F_EXEC)||(func == F_POPUP)||(func == F_RESTART)
1460 	     ||(func == F_FUNCTION)||(func == F_MODULE))
1461 	    ptr2=stripcpy3(pline,True);
1462 	  else
1463 	    ptr2=stripcpy3(pline,False);
1464 
1465 	  func_val_1 = 0;
1466 	  func_val_2 = 0;
1467 	  unit_1 = 's';
1468 	  unit_2 = 's';
1469 	  if(ptr2 != NULL)
1470 	    {
1471 	      n = sscanf(ptr2,"%d %d",&func_val_1,&func_val_2);
1472 	      if( n < 2)
1473 		n = sscanf(ptr2,"%d%c %d%c",&func_val_1,&unit_1,&func_val_2,&unit_2);
1474 	    }
1475 	  if( *stripcpy2(pline,1,True))
1476 	      AddToMenu(mr, stripcpy2(pline,1,True), stripcpy2(pline,2,True),
1477 		    ptr2, func,func_val_1,func_val_2, unit_1, unit_2);
1478 	}
1479 
1480       pline = fgets(newline,(sizeof newline)-1,fd);
1481       if(pline == (char *)0)return NULL;
1482 
1483       orig_tline = pline;
1484 
1485       while(isspace(*pline))pline++;
1486     }
1487   MakeMenu(mr);
1488 
1489   return mr;
1490 }
1491 
1492 /****************************************************************************
1493  *
1494  *  Parses a popup definition
1495  *
1496  ****************************************************************************/
ParsePopupEntry(char * tline,FILE * fd,char ** junk,int * junk2)1497 void ParsePopupEntry(char *tline,FILE *fd, char **junk,int *junk2)
1498 {
1499   MenuRoot *mr=0;
1500 
1501   mr = ParseMenuBody(stripcpy2(tline,0,True),fd);
1502 
1503   if (PopupCount < MAXPOPUPS)
1504     {
1505       PopupTable[PopupCount] = mr;
1506       PopupCount++;
1507       if(strcmp(mr->name,"InitFunction")==0)
1508 	{
1509 	  Scr.InitFunction = mr;
1510 	}
1511       else if(strcmp(mr->name,"RestartFunction")==0)
1512 	{
1513 	  Scr.RestartFunction = mr;
1514 	}
1515     }
1516   else
1517     {
1518       fprintf(stderr,"Popup/Function %s ignored, you have more than %u\n",
1519 	      mr->name,MAXPOPUPS);
1520       free(mr);
1521     }
1522 }
1523 
1524 /****************************************************************************
1525  *
1526  *  Parses a mouse binding
1527  *
1528  ****************************************************************************/
ParseMouseEntry(char * tline,FILE * fd,char ** junk,int * junk2)1529 void ParseMouseEntry(char *tline,FILE *fd, char **junk,int *junk2)
1530 {
1531   char context[256],modifiers[256],function[256],*ptr;
1532   MenuRoot *mr=0;
1533   MenuItem *mi=0;
1534   MouseButton *temp;
1535   int button,i,j;
1536   int n;
1537   char unit_1, unit_2;
1538 
1539   unit_1 = 's';
1540   unit_2 = 's';
1541   func_val_1 = 0;
1542   func_val_2 = 0;
1543 
1544   n = sscanf(tline,"%d %s %s %s %d %d",&button,context,modifiers,function,
1545 	 &func_val_1,&func_val_2);
1546   if(n < 6)
1547     n = sscanf(tline,"%d %s %s %s %d%c %d%c",&button,context,modifiers,function,
1548 	   &func_val_1,&unit_1,&func_val_2,&unit_2);
1549 
1550   find_context(context,&contexts,win_contexts);
1551   if((contexts != C_ALL) && (contexts & C_LALL))
1552     {
1553       /* check for nr_left_buttons */
1554       i=0;
1555       j=(contexts &C_LALL)/C_L1;
1556       while(j>0)
1557 	{
1558 	  i++;
1559 	  j=j>>1;
1560 	}
1561       if(Scr.nr_left_buttons <i)
1562 	Scr.nr_left_buttons = i;
1563     }
1564   if((contexts != C_ALL) && (contexts & C_RALL))
1565     {
1566       /* check for nr_right_buttons */
1567       i=0;
1568       j=(contexts&C_RALL)/C_R1;
1569       while(j>0)
1570 	{
1571 	  i++;
1572 	  j=j>>1;
1573 	}
1574       if(Scr.nr_right_buttons <i)
1575 	Scr.nr_right_buttons = i;
1576     }
1577   find_context(modifiers,&mods,key_modifiers);
1578   if((contexts & C_WINDOW)&&(((mods==0)||mods == AnyModifier)))
1579     {
1580       Scr.buttons2grab &= ~(1<<(button-1));
1581     }
1582 
1583   func = F_NOP;
1584   match_string(func_config,function,"bad mouse function:",fd);
1585 
1586   if((func == F_POPUP)||(func == F_FUNCTION))
1587     {
1588       unsigned i;
1589       ptr = stripcpy2(tline,0,True);
1590       if(ptr != NULL)
1591 	for (i = 0; i < PopupCount; i++)
1592 	  if (mystrcasecmp(PopupTable[i]->name,ptr) == 0)
1593 	    {
1594 	      mr = PopupTable[i];
1595 	      break;
1596 	    }
1597       if (!mr)
1598 	{
1599 	  no_popup(ptr);
1600 	  func = F_NOP;
1601 	}
1602       if(ptr != NULL)
1603 	free(ptr);
1604     }
1605   else if((func == F_EXEC)||(func == F_RESTART)||
1606 	  (func == F_CIRCULATE_UP)||(func == F_CIRCULATE_DOWN)||
1607 	  (func == F_WARP)||(func == F_MODULE))
1608     {
1609       mi = (MenuItem *)safemalloc(sizeof(MenuItem));
1610 
1611       mi->next = (MenuItem *)NULL;
1612       mi->prev = (MenuItem *)NULL;
1613       mi->item_num = 0;
1614       if((func == F_EXEC)||(func == F_RESTART)||(func== F_MODULE))
1615 	{
1616 	  mi->item = stripcpy2(tline,0,True);
1617 	  mi->action = stripcpy3(tline,True);
1618 	}
1619       else
1620 	{
1621 	  mi->item = stripcpy2(tline,0,False);
1622 	  mi->action = stripcpy3(tline,False);
1623 	}
1624       mi->state = 0;
1625       mi->func = func;
1626       mi->strlen = strlen(mi->item);
1627       mi->val1 = 0;
1628       mi->val2 = 0;
1629       mi->val1_unit = 1;
1630       mi->val2_unit = 1;
1631     }
1632 
1633   temp = Scr.MouseButtonRoot;
1634   Scr.MouseButtonRoot = (MouseButton *)safemalloc(sizeof(MouseButton));
1635   Scr.MouseButtonRoot->func = func;
1636   Scr.MouseButtonRoot->menu = mr;
1637   Scr.MouseButtonRoot->item = mi;
1638   Scr.MouseButtonRoot->Button = button;
1639   Scr.MouseButtonRoot->Context = contexts;
1640   Scr.MouseButtonRoot->Modifier = mods;
1641   Scr.MouseButtonRoot->NextButton = temp;
1642   Scr.MouseButtonRoot->val1 = func_val_1;
1643   Scr.MouseButtonRoot->val2 = func_val_2;
1644   if((unit_1 == 'p')||(unit_1 == 'P'))
1645     Scr.MouseButtonRoot->val1_unit = 100;
1646   else
1647     Scr.MouseButtonRoot->val1_unit = Scr.MyDisplayWidth;
1648   if((unit_2 == 'p')||(unit_2 == 'P'))
1649     Scr.MouseButtonRoot->val2_unit = 100;
1650   else
1651     Scr.MouseButtonRoot->val2_unit = Scr.MyDisplayHeight;
1652 
1653   return;
1654 }
1655 
no_popup(char * ptr)1656 void no_popup(char *ptr)
1657 {
1658   if((ptr)&&(orig_tline))
1659     fprintf(stderr,"Popup '%s' not defined in line %s",ptr,orig_tline);
1660 }
1661 
1662 
1663 /****************************************************************************
1664  *
1665  *  Processes a line with a key binding
1666  *
1667  ****************************************************************************/
ParseKeyEntry(char * tline,FILE * fd,char ** junk,int * junk2)1668 void ParseKeyEntry(char *tline, FILE *fd,char **junk,int *junk2)
1669 {
1670   char context[256],modifiers[256],function[256],*ptr;
1671   char name[256];
1672   MenuRoot *mr = 0;
1673   char unit_1, unit_2;
1674   int n;
1675 
1676 
1677   ptr = NULL;
1678   func_val_1 = 0;
1679   func_val_2 = 0;
1680   unit_1 = 's';
1681   unit_2 = 's';
1682   n = sscanf(tline,"%s %s %s %s %d %d",name,context,modifiers,function,
1683 	 &func_val_1,&func_val_2);
1684   if(n < 6)
1685     n = sscanf(tline,"%s %s %s %s %d%c %d%c",name,context,modifiers,function,
1686 	       &func_val_1,&unit_1,&func_val_2,&unit_2);
1687   find_context(context,&contexts,win_contexts);
1688   find_context(modifiers,&mods,key_modifiers);
1689   match_string(func_config,function,"bad key function:",fd);
1690 
1691   /* Make CirculateUp and CirculateDown take args. by Y.NOMURA */
1692 
1693   if ((func == F_CIRCULATE_UP) || (func == F_CIRCULATE_DOWN)||
1694       (func == F_WARP))
1695     ptr = stripcpy3(tline,False);
1696 
1697   /* End of addition */
1698 
1699   if((func == F_EXEC)||(func == F_RESTART)||(func == F_MODULE))
1700     {
1701       ptr = stripcpy3(tline,True);
1702     }
1703   else if((func == F_POPUP)||(func == F_FUNCTION))
1704     {
1705       unsigned i;
1706       ptr = stripcpy2(tline,0,True);
1707       if(ptr != NULL)
1708 	{
1709 	  for (i = 0; i < PopupCount; i++)
1710 	    if (mystrcasecmp(PopupTable[i]->name,ptr) == 0)
1711 	      {
1712 		mr = PopupTable[i];
1713 		break;
1714 	      }
1715 	}
1716       if (!mr)
1717 	{
1718 	  no_popup(ptr);
1719 	  func = F_NOP;
1720 	}
1721     }
1722 
1723   AddFuncKey(name,contexts,mods,func,ptr,func_val_1,func_val_2,mr, unit_1,unit_2);
1724 }
1725 
1726 /****************************************************************************
1727  *
1728  * Sets menu/keybinding/mousebinding function to specified value
1729  *
1730  ****************************************************************************/
set_func(char * text,FILE * fd,char ** value,int * junk)1731 void set_func(char *text, FILE *fd, char **value,int *junk)
1732 {
1733   func = (unsigned long)value;
1734 }
1735 
1736 /****************************************************************************
1737  *
1738  * Turns a  string context of context or modifier values into an array of
1739  * true/false values (bits)
1740  *
1741  ****************************************************************************/
find_context(char * string,int * output,struct charstring * table)1742 void find_context(char *string, int *output, struct charstring *table)
1743 {
1744   int i=0,j=0;
1745   Bool matched;
1746   char tmp1;
1747 
1748   *output=0;
1749   i=0;
1750   while(i<strlen(string))
1751     {
1752       j=0;
1753       matched = FALSE;
1754       while((!matched)&&(table[j].key != 0))
1755 	{
1756 	  /* in some BSD implementations, tolower(c) is not defined
1757 	   * unless isupper(c) is true */
1758 	  tmp1=string[i];
1759 	  if(isupper(tmp1))
1760 	    tmp1=tolower(tmp1);
1761 	  /* end of ugly BSD patch */
1762 
1763 	  if(tmp1 == table[j].key)
1764 	    {
1765 	      *output |= table[j].value;
1766 	      matched = TRUE;
1767 	    }
1768 	  j++;
1769 	}
1770       if(!matched)
1771 	{
1772 	  fprintf(stderr,"afterstep: bad entry %c in line %s",
1773 		  string[i],orig_tline);
1774 	}
1775       i++;
1776     }
1777   return;
1778 }
1779 
1780 /****************************************************************************
1781  *
1782  * Matches text from config to a table of strings, calls routine
1783  * indicated in table.
1784  *
1785  ****************************************************************************/
match_string(struct config * table,char * text,char * error_msg,FILE * fd)1786 void match_string(struct config *table, char *text, char *error_msg, FILE *fd)
1787 {
1788   int j;
1789   Bool matched;
1790 
1791   j=0;
1792   matched = FALSE;
1793   while((!matched)&&(strlen(table[j].keyword)>0))
1794     {
1795       if(mystrncasecmp(text,table[j].keyword,strlen(table[j].keyword))==0)
1796 	{
1797 	  matched=TRUE;
1798 	  /* found key word */
1799 	  table[j].action(&text[strlen(table[j].keyword)],
1800 				fd,table[j].arg,table[j].arg2);
1801 	}
1802       else
1803 	j++;
1804     }
1805   if(!matched)
1806     {
1807       afterstep_err("%s %s in line %s",error_msg,text,orig_tline);
1808     }
1809 }
1810 
1811 
1812 
1813 
1814 /****************************************************************************
1815  *
1816  * Generates the window for a menu
1817  *
1818  ****************************************************************************/
MakeMenu(MenuRoot * mr)1819 void MakeMenu(MenuRoot *mr)
1820 {
1821   MenuItem *cur;
1822   unsigned long valuemask;
1823   XSetWindowAttributes attributes;
1824   int y;
1825 
1826   /* lets first size the window accordingly */
1827   mr->width += 15;
1828   if(mr->width2 > 0)
1829     mr->width += 5;
1830   /* allow two pixels for top border */
1831   for (y=0, cur = mr->first; cur != NULL; cur = cur->next)
1832   {
1833     cur->y_offset = y;
1834     cur->x = 5;
1835     if(cur->func==F_TITLE)
1836 	/* Title */
1837 	cur->y_height = NS_TITLE_HEIGHT+1;
1838     else if(cur->func==F_NOP && *cur->item==0)
1839       /* Separator */
1840       cur->y_height = HEIGHT_SEPARATOR;
1841     else
1842       /* Normal text entry */
1843       cur->y_height = Scr.EntryHeight;
1844     y += cur->y_height;
1845     if(mr->width2 == 0)
1846       {
1847 	cur->x2 = cur->x;
1848       }
1849     else
1850       {
1851 	cur->x2 = mr->width -5;
1852       }
1853   }
1854   mr->in_use = 0;
1855   mr->height = y;
1856 
1857 #ifndef NO_SAVEUNDERS
1858   valuemask = (CWBackPixel | CWEventMask | CWCursor | CWSaveUnder);
1859 #else
1860   valuemask = (CWBackPixel | CWEventMask | CWCursor);
1861 #endif
1862   attributes.background_pixel = Scr.MenuColors.back;
1863   attributes.event_mask = (ExposureMask | EnterWindowMask);
1864   attributes.cursor = Scr.ASCursors[MENU];
1865 #ifndef NO_SAVEUNDERS
1866   attributes.save_under = TRUE;
1867 #endif
1868   mr->width = mr->width + mr->width2;
1869 
1870   mr->w = XCreateWindow (dpy, Scr.Root, 0, 0, (unsigned int) (mr->width),
1871 			 (unsigned int) mr->height, (unsigned int) 0,
1872 			 CopyFromParent, (unsigned int) InputOutput,
1873 			 (Visual *) CopyFromParent,
1874 			 valuemask, &attributes);
1875   XSaveContext(dpy,mr->w,MenuContext,(caddr_t)mr);
1876 
1877   return;
1878 }
1879 
1880 /***********************************************************************
1881  * Procedure:
1882  *	scanForHotkeys - Look for hotkey markers in a MenuItem
1883  * 							(pete@tecc.co.uk)
1884  *
1885  * Inputs:
1886  *	it	- MenuItem to scan
1887  * 	which 	- +1 to look in it->item1 and -1 to look in it->item2.
1888  *
1889  ***********************************************************************/
1890 
scanForHotkeys(MenuItem * it,int which)1891 void scanForHotkeys(MenuItem *it, int which)
1892 {
1893   char *start, *txt;
1894 
1895   start = (which > 0) ? it->item : it->item2;	/* Get start of string	*/
1896   for (txt = start; *txt != '\0'; txt++)
1897     {	/* Scan whole string	*/
1898       if (*txt == '&')
1899 	{		/* A hotkey marker?			*/
1900       if (txt[1] == '&')
1901 	{	/* Just an escaped &			*/
1902 	  char *tmp;		/* Copy the string down over it		*/
1903 	  for (tmp = txt; *tmp != '\0'; tmp++) tmp[0] = tmp[1];
1904 	  continue;		/* ...And skip to the key char		*/
1905 	}
1906       /* It's a hot key marker - work out the offset value		*/
1907       it->hotkey = txt[1];
1908       for (; txt[1] != '\0'; txt++)
1909 	txt[0] = txt[2];	/* Copy down..	*/
1910       return;			/* Only one hotkey per item...		*/
1911     }
1912   }
1913   it->hotkey = 0;		/* No hotkey found.  Set offset to zero	*/
1914 }
1915 
1916 
1917 
1918 /***********************************************************************
1919  *
1920  *  Procedure:
1921  *	AddToMenu - add an item to a root menu
1922  *
1923  *  Returned Value:
1924  *	(MenuItem *)
1925  *
1926  *  Inputs:
1927  *	menu	- pointer to the root menu to add the item
1928  *	item	- the text to appear in the menu
1929  *	action	- the string to possibly execute
1930  *	func	- the numeric function
1931  *
1932  ***********************************************************************/
AddToMenu(MenuRoot * menu,char * item,char * item2,char * action,int func,long func_val_1,long func_val_2,char unit_1,char unit_2)1933 void AddToMenu(MenuRoot *menu, char *item, char *item2, char *action,int func,
1934 	       long func_val_1,long func_val_2, char unit_1, char unit_2)
1935 {
1936   MenuItem *tmp;
1937   int width;
1938 
1939 
1940   if(item == NULL)
1941      return;
1942   tmp = (MenuItem *)safemalloc(sizeof(MenuItem));
1943   if (menu->first == NULL)
1944     {
1945       menu->first = tmp;
1946       tmp->prev = NULL;
1947     }
1948   else
1949     {
1950       menu->last->next = tmp;
1951       tmp->prev = menu->last;
1952     }
1953   menu->last = tmp;
1954 
1955   tmp->item = item;
1956   if (item != (char *)0)
1957     {
1958       scanForHotkeys(tmp, 1);				/* pete@tecc.co.uk */
1959       tmp->strlen = strlen(item);
1960     }
1961   else
1962     tmp->strlen = 0;
1963 
1964   tmp->item2 = item2;
1965   if (item2 != (char *)0)
1966     {
1967       if (tmp->hotkey == 0) scanForHotkeys(tmp, -1);	/* pete@tecc.co.uk */
1968       tmp->strlen2 = strlen(item2);
1969     }
1970   else
1971     tmp->strlen2 = 0;
1972   tmp->menu = 0;
1973 
1974   if((func == F_POPUP)||(func == F_FUNCTION))
1975     {
1976       unsigned i;
1977       if(action != (char *)0)
1978 	{
1979 	  for (i = 0; i < PopupCount; i++)
1980 	    if (mystrcasecmp(PopupTable[i]->name,action) == 0)
1981 	      {
1982 		tmp->menu = PopupTable[i];
1983 		break;
1984 	      }
1985 	}
1986       if(tmp->menu == (MenuRoot *)0)
1987 	{
1988 	  no_popup(action);
1989 	  func = F_NOP;
1990 	}
1991     }
1992   tmp->action = action;
1993   tmp->next = NULL;
1994   tmp->state = 0;
1995   tmp->func = func;
1996   tmp->val1 = func_val_1;
1997   tmp->val2 = func_val_2;
1998   if((unit_1 == 'p')||(unit_1 == 'P'))
1999     tmp->val1_unit = 100;
2000   else
2001     tmp->val1_unit = Scr.MyDisplayWidth;
2002   if((unit_2 == 'p')||(unit_2 == 'P'))
2003     tmp->val2_unit = 100;
2004   else
2005     tmp->val2_unit = Scr.MyDisplayHeight;
2006 
2007      if(func==F_TITLE)
2008        width = XTextWidth(Scr.WindowFont.font, item, tmp->strlen);
2009      else
2010   	width = XTextWidth(Scr.StdFont.font, item, tmp->strlen);
2011   if(tmp->func == F_POPUP || tmp->hotkey)
2012     width += 15;
2013   if (width <= 0)
2014     width = 1;
2015   if (width > menu->width)
2016     menu->width = width;
2017   width = XTextWidth(Scr.StdFont.font, item2, tmp->strlen2);
2018   if (width < 0)
2019     width = 0;
2020   if (width > menu->width2)
2021     menu->width2 = width;
2022   if((width==0)&&(tmp->strlen2>0))
2023     menu->width2 = 1;
2024 
2025   tmp->item_num = menu->items++;
2026 }
2027 
2028 /***********************************************************************
2029  *
2030  *  Procedure:
2031  *	NewMenuRoot - create a new menu root
2032  *
2033  *  Returned Value:
2034  *	(MenuRoot *)
2035  *
2036  *  Inputs:
2037  *	name	- the name of the menu root
2038  *
2039  ***********************************************************************/
NewMenuRoot(char * name)2040 MenuRoot *NewMenuRoot(char *name)
2041 {
2042   MenuRoot *tmp;
2043 
2044   tmp = (MenuRoot *) safemalloc(sizeof(MenuRoot));
2045   tmp->name = name;
2046   tmp->first = NULL;
2047   tmp->last = NULL;
2048   tmp->items = 0;
2049   tmp->width = 0;
2050   tmp->width2 = 0;
2051 #ifdef ENABLE_TEXTURE
2052   tmp->titlebg = None;
2053   tmp->itembg = None;
2054 #endif
2055   tmp->w = None;
2056   return (tmp);
2057 }
2058 
2059 
2060 
2061 /***********************************************************************
2062  *
2063  *  Procedure:
2064  *	AddFuncKey - add a function key to the list
2065  *
2066  *  Inputs:
2067  *	name	- the name of the key
2068  *	cont	- the context to look for the key press in
2069  *	mods	- modifier keys that need to be pressed
2070  *	func	- the function to perform
2071  *	action	- the action string associated with the function (if any)
2072  *
2073  ***********************************************************************/
AddFuncKey(char * name,int cont,int mods,int func,char * action,int val1,int val2,MenuRoot * mr,char unit_1,char unit_2)2074 void AddFuncKey (char *name, int cont, int mods, int func,  char *action,
2075 		 int val1, int val2,MenuRoot *mr, char unit_1, char unit_2)
2076 {
2077   FuncKey *tmp;
2078   KeySym keysym;
2079   KeyCode keycode;
2080   int i, min, max;
2081 
2082   /*
2083    * Don't let a 0 keycode go through, since that means AnyKey to the
2084    * XGrabKey call in GrabKeys().
2085    */
2086   if ((keysym = XStringToKeysym(name)) == NoSymbol ||
2087       (keycode = XKeysymToKeycode(dpy, keysym)) == 0)
2088     return;
2089 
2090 
2091   XDisplayKeycodes(dpy, &min, &max);
2092   for (i=min; i<=max; i++)
2093     if (XkbKeycodeToKeysym(dpy, i, 0, 0) == keysym)
2094       {
2095 	tmp = (FuncKey *) safemalloc(sizeof(FuncKey));
2096 	tmp->next = Scr.FuncKeyRoot.next;
2097 	Scr.FuncKeyRoot.next = tmp;
2098 
2099 	tmp->name = name;
2100 	tmp->keycode = i;
2101 	tmp->cont = cont;
2102 	tmp->mods = mods;
2103 	tmp->func = func;
2104 	tmp->action = action;
2105 	tmp->val1 = val1;
2106 	tmp->val2 = val2;
2107 	if((unit_1 == 'p')||(unit_1 == 'P'))
2108 	  tmp->val1_unit = 100;
2109 	else
2110 	  tmp->val1_unit = Scr.MyDisplayWidth;
2111 	if((unit_2 == 'p')||(unit_2 == 'P'))
2112 	  tmp->val2_unit = 100;
2113 	else
2114 	  tmp->val2_unit = Scr.MyDisplayHeight;
2115 
2116 	tmp->menu = mr;
2117       }
2118   return;
2119 }
2120 
2121 /****************************************************************************
2122  *
2123  * Loads a single color
2124  *
2125  ****************************************************************************/
GetColor(char * name)2126 Pixel GetColor(char *name)
2127 {
2128   XColor color;
2129   XWindowAttributes attributes;
2130 
2131   XGetWindowAttributes(dpy,Scr.Root,&attributes);
2132   color.pixel = 0;
2133    if (!XParseColor (dpy, attributes.colormap, name, &color))
2134      {
2135        nocolor("parse",name);
2136      }
2137    else if(!XAllocColor (dpy, attributes.colormap, &color))
2138      {
2139        nocolor("alloc",name);
2140      }
2141   return color.pixel;
2142 }
2143 
nocolor(char * note,char * name)2144 void nocolor(char *note, char *name)
2145 {
2146   afterstep_err("can't %s color %s", note,name,NULL);
2147 }
2148 /****************************************************************************
2149  *
2150  * Copies a string into a new, malloc'ed string
2151  * Strips leading spaces and trailing spaces and new lines
2152  *
2153  ****************************************************************************/
stripcpy(char * source)2154 char *stripcpy(char *source)
2155 {
2156   char *tmp,*ptr;
2157   int len;
2158 
2159   while(isspace(*source))
2160     source++;
2161   len = strlen(source);
2162   tmp = source + len -1;
2163   while(((isspace(*tmp))||(*tmp == '\n'))&&(tmp >=source))
2164     {
2165       tmp--;
2166       len--;
2167     }
2168   ptr = safemalloc(len+1);
2169   strncpy(ptr,source,len);
2170   ptr[len]=0;
2171   return ptr;
2172 }
2173 
2174 
2175 /****************************************************************************
2176  *
2177  * Copies a string into a new, malloc'ed string
2178  * Strips all data before the first quote and after the second
2179  *
2180  ****************************************************************************/
stripcpy2(char * source,int tab_sensitive,Bool error)2181 char *stripcpy2(char *source, int tab_sensitive, Bool error)
2182 {
2183   char *ptr;
2184   int count;
2185   while((*source != '"')&&(*source != 0))
2186     source++;
2187   if(*source == 0)
2188     {
2189       if(error)
2190 	bad_binding(2);
2191       return 0;
2192     }
2193   source++;
2194   ptr = source;
2195   count = 0;
2196   if(!tab_sensitive)
2197     while((*ptr!='"')&&(*ptr != 0))
2198       {
2199 	ptr++;
2200 	count++;
2201       }
2202   else if(tab_sensitive==1)
2203     while((*ptr!='"')&&(*ptr != 0)&&(*ptr!='\t'))
2204       {
2205 	ptr++;
2206 	count++;
2207       }
2208   else if(tab_sensitive==2)
2209     {
2210       while((*ptr!='"')&&(*ptr != 0)&&(*ptr!='\t'))
2211 	{
2212 	  source++;
2213 	  ptr++;
2214 	}
2215       if((*ptr!='"')&&(*ptr != 0))
2216 	{
2217 	  ptr++;
2218 	  source++;
2219 	}
2220       while((*ptr!='"')&&(*ptr != 0))
2221 	{
2222 	  ptr++;
2223 	  count++;
2224 	}
2225     }
2226   ptr = safemalloc(count+1);
2227   strncpy(ptr,source,count);
2228   ptr[count]=0;
2229   return ptr;
2230 }
2231 
2232 
2233 /****************************************************************************
2234  *
2235  * Copies a string into a new, malloc'ed string
2236  * Strips all data before the second quote. and strips trailing spaces and
2237  * new lines
2238  *
2239  ****************************************************************************/
stripcpy3(char * source,Bool Warn)2240 char *stripcpy3(char *source,Bool Warn)
2241 {
2242   while((*source != '"')&&(*source != 0))
2243     source++;
2244   if(*source != 0)
2245     source++;
2246   while((*source != '"')&&(*source != 0))
2247     source++;
2248   if(*source == 0)
2249     {
2250       if(Warn)bad_binding(3);
2251       return 0;
2252     }
2253   source++;
2254   return stripcpy(source);
2255 }
2256 
bad_binding(int num)2257 void bad_binding(int num)
2258 {
2259   afterstep_err("bad binding in line %s",orig_tline,NULL,NULL);
2260   return;
2261 }
2262 
2263 
2264 /***********************************************************************
2265  *
2266  *  Procedure:
2267  *	CreateGCs - open fonts and create all the needed GC's.  I only
2268  *		    want to do this once, hence the first_time flag.
2269  *
2270  ***********************************************************************/
CreateGCs(void)2271 void CreateGCs(void)
2272 {
2273   XGCValues gcv;
2274   unsigned long gcm;
2275 
2276   /* create GC's */
2277   gcm = GCLineWidth|GCForeground|GCBackground|GCFunction;
2278   gcv.function = GXcopy;
2279   gcv.line_width = 1;
2280   gcv.foreground = Scr.StdColors.fore;
2281   gcv.background = Scr.StdColors.back;
2282   Scr.LineGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2283 
2284   gcm = GCFunction|GCLineWidth|GCForeground|GCSubwindowMode;
2285   gcv.function = GXxor;
2286   gcv.line_width = 0;
2287   gcv.foreground = XORvalue;
2288   gcv.subwindow_mode = IncludeInferiors;
2289   Scr.DrawGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2290 
2291   gcm = GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
2292     GCBackground|GCFont;
2293   gcv.line_width = 0;
2294   gcv.function = GXcopy;
2295   gcv.plane_mask = AllPlanes;
2296   gcv.foreground = Scr.StdColors.fore;
2297   gcv.background = Scr.StdColors.back;
2298   gcv.font =  Scr.StdFont.font->fid;
2299   /*
2300    * Prevent GraphicsExpose and NoExpose events.  We'd only get NoExpose
2301    * events anyway;  they cause BadWindow errors from XGetWindowAttributes
2302    * call in FindScreenInfo (events.c) (since drawable is a pixmap).
2303    */
2304   gcv.graphics_exposures = False;
2305 
2306   Scr.NormalGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2307 
2308 
2309   /* GC for pager labels */
2310   Scr.FontGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2311 
2312   gcv.fill_style = FillStippled;
2313   gcv.stipple = Scr.gray_bitmap;
2314   gcm = GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
2315     GCBackground|GCFont|GCStipple|GCFillStyle;
2316 
2317   Scr.StippleGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2318 
2319   gcm = GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
2320     GCBackground|GCFont;
2321   Globalgcm = gcm;
2322   Globalgcv = gcv;
2323   gcv.foreground = Scr.HiRelief.fore;
2324   gcv.background = Scr.HiRelief.back;
2325   gcv.fill_style = FillSolid;
2326   Scr.HiReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2327 
2328   gcv.foreground = Scr.HiRelief.back;
2329   gcv.background = Scr.HiRelief.fore;
2330   Scr.HiShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2331 
2332   if (Scr.BevelReliefGC==None)
2333 	  Scr.BevelReliefGC=Scr.HiReliefGC;
2334   if (Scr.BevelShadowGC==None)
2335 	  Scr.BevelShadowGC=Scr.HiShadowGC;
2336   gcv.foreground = Scr.MenuColors.fore;
2337   gcv.background = Scr.MenuColors.back;
2338   Scr.MenuGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2339 
2340   gcv.foreground = Scr.StdRelief.fore;
2341   gcv.background = Scr.StdRelief.back;
2342   Scr.ScratchGC1 = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2343 
2344   if(Scr.d_depth < 2)
2345     {
2346       gcv.fill_style = FillStippled;
2347       gcv.stipple = Scr.gray_bitmap;
2348       gcm=GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
2349 	GCBackground|GCFont|GCStipple|GCFillStyle;
2350       Scr.MenuStippleGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2351 
2352       gcm=GCFunction|GCPlaneMask|GCGraphicsExposures|GCLineWidth|GCForeground|
2353 	GCBackground|GCFont;
2354       gcv.fill_style = FillSolid;
2355     }
2356   else
2357     {
2358       gcv.foreground = Scr.MenuStippleColors.fore;
2359       gcv.background = Scr.MenuStippleColors.back;
2360       Scr.MenuStippleGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2361     }
2362   gcv.foreground = Scr.MenuRelief.fore;
2363   gcv.background = Scr.MenuRelief.back;
2364   Scr.MenuReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2365 
2366   gcv.foreground = Scr.MenuRelief.back;
2367   gcv.background = Scr.MenuRelief.fore;
2368   Scr.MenuShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2369 
2370   gcv.foreground = Scr.StdRelief.fore;
2371   gcv.background = Scr.StdRelief.back;
2372   Scr.StdReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2373 
2374   gcv.foreground = Scr.StdRelief.back;
2375   gcv.background = Scr.StdRelief.fore;
2376   Scr.StdShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2377   Scr.ScratchGC2 = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2378 
2379   gcv.foreground = Scr.StickyRelief.fore;
2380   gcv.background = Scr.StickyRelief.back;
2381   Scr.StickyReliefGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2382 
2383   gcv.foreground = Scr.StickyRelief.back;
2384   gcv.background = Scr.StickyRelief.fore;
2385   Scr.StickyShadowGC = XCreateGC(dpy, Scr.Root, gcm, &gcv);
2386 
2387   gcv.foreground = Scr.HiColors.fore;
2388   gcv.font = Scr.IconFont.font->fid;
2389   Scr.IconGC = XCreateGC(dpy, Scr.Root, GCForeground|GCFont, &gcv);
2390 }
2391 
2392 /***********************************************************************
2393  *
2394  *  Procedure:
2395  *	SetOneStyle - add a window name to the no title list
2396  *
2397  *  Inputs:
2398  *	name	- a pointer to the name of the window
2399  *
2400  ***********************************************************************/
2401 #ifndef PRUNE
SetOneStyle(char * text,FILE * fd,char ** list,int * junk)2402 void SetOneStyle(char *text, FILE *fd, char **list, int *junk)
2403 {
2404   char *name;
2405   unsigned long new_flags;
2406   char *icon_name = NULL;
2407   int desknumber = 0;
2408 
2409   new_flags = (unsigned long)junk;
2410 
2411   /* first, see if an entry for this name exists */
2412   if((new_flags & ICON_FLAG) || (new_flags & STAYSONDESK_FLAG))
2413     name = stripcpy2(text,FALSE,TRUE);
2414   else
2415     name = stripcpy(text);
2416 
2417   /* in case there was no argument! */
2418   if(name == NULL)
2419     return;
2420 
2421   /* capture default icons */
2422   if(strlen(name) == 0)
2423     {
2424       if(new_flags & ICON_FLAG)
2425 	Scr.DefaultIcon = stripcpy3(text,TRUE);
2426       free(name);
2427       return;
2428     }
2429   if(new_flags & ICON_FLAG)
2430     {
2431       icon_name = stripcpy3(text,TRUE);
2432     }
2433   else if (new_flags & STAYSONDESK_FLAG)
2434     {
2435       char *p = stripcpy3(text,TRUE);
2436       desknumber = atoi (p);
2437       free (p);
2438     }
2439   AddToList(name,icon_name,new_flags,0,desknumber,0,0,NULL,NULL,0,0);
2440 }
2441 #endif
2442 
2443 #ifdef	M4
2444 
2445 /* For m4... */
2446 #include <X11/Xmu/CharSet.h>
2447 
2448 #include <sys/param.h>
2449 #include <sys/types.h>
2450 #include <sys/socket.h>
2451 #include <netdb.h>
2452 
2453 /* Code taken and munged from xrdb.c */
2454 #define MAXHOSTNAME 255
2455 #define Resolution(pixels, mm)  ((((pixels) * 100000 / (mm)) + 50) / 100)
2456 
2457 /* EXTRA should be the length of the strings
2458    "define(" + ", ``" + "'')dnl\n". */
2459 
2460 #define EXTRA   50
2461 
2462 extern int m4_prefix;
2463 extern char m4_prog[];
2464 extern int m4_default_quotes;
2465 extern char m4_startquote[];
2466 extern char m4_endquote[];
2467 
MkDef(char * name,char * def)2468 static char *MkDef(char *name, char *def)
2469 {
2470     static char *cp = NULL;
2471     static int maxsize = 0;
2472     int n;
2473 
2474     /* The char * storage only lasts for 1 call... */
2475 
2476     /* Get space to hold everything, if needed */
2477 
2478     n = EXTRA + strlen(name) + strlen(def);
2479     if (n > maxsize) {
2480 	maxsize = n;
2481 	if (cp == NULL) {
2482 	    cp = malloc(n);
2483 	} else {
2484 	    cp = realloc(cp, n);
2485 	}
2486     }
2487 
2488     if (cp == NULL) {
2489 	perror("MkDef can't allocate enough space for a macro definition");
2490 	exit(0377);
2491     }
2492 
2493     /* Create the macro definition, using the appropriate prefix, if any */
2494 
2495     if (m4_prefix)
2496       {
2497 	strcpy(cp, "m4_define(");
2498       }
2499     else
2500       strcpy(cp, "define(");
2501 
2502     strcat(cp, name);
2503 
2504     /* Tack on "," and 2 sets of starting quotes */
2505     strcat(cp, ",");
2506     strcat(cp, m4_startquote);
2507     strcat(cp, m4_startquote);
2508 
2509     /* The definition itself */
2510     strcat(cp, def);
2511 
2512     /* Add 2 sets of closing quotes */
2513     strcat(cp, m4_endquote);
2514     strcat(cp, m4_endquote);
2515 
2516     /* End the definition, appropriately */
2517     strcat(cp, ")");
2518     if (m4_prefix)
2519       {
2520 	strcat(cp, "m4_");
2521       }
2522 
2523     strcat(cp, "dnl\n");
2524 
2525     return(cp);
2526 }
2527 
MkNum(char * name,int def)2528 static char *MkNum(char *name,int def)
2529 {
2530     char num[20];
2531 
2532     sprintf(num, "%d", def);
2533     return(MkDef(name, num));
2534 }
2535 
m4_defs(Display * display,const char * host,char * m4_options,char * config_file)2536 static char *m4_defs(Display *display, const char *host, char *m4_options, char *config_file)
2537 {
2538     Screen *screen;
2539     Visual *visual;
2540     char client[MAXHOSTNAME], server[MAXHOSTNAME], *colon;
2541     char ostype[BUFSIZ];
2542     char options[BUFSIZ];
2543     static char tmp_name[BUFSIZ];
2544     struct hostent *hostname;
2545     char *vc;			/* Visual Class */
2546     FILE *tmpf;
2547     struct passwd *pwent;
2548     /* Generate a temporary filename.  Honor the TMPDIR environment variable,
2549        if set. Hope nobody deletes this file! */
2550 
2551     if ((vc=getenv("TMPDIR"))) {
2552       strcpy(tmp_name, vc);
2553     } else {
2554       strcpy(tmp_name, "/tmp");
2555     }
2556     strcat(tmp_name, "/steprcXXXXX");
2557     mktemp(tmp_name);
2558 
2559     if (*tmp_name == '\0')
2560       {
2561 	perror("mktemp failed in m4_defs");
2562 	exit(0377);
2563       }
2564 
2565     /*
2566      * Create the appropriate command line to run m4, and
2567      * open a pipe to the command.
2568      */
2569 
2570     sprintf(options, "%s %s %s > %s\n",
2571 	    m4_prog,
2572 	    ((m4_prefix == 0) ? "" : "--prefix-builtins"),
2573 	    m4_options, tmp_name);
2574 
2575     tmpf = popen(options, "w");
2576     if (tmpf == NULL) {
2577 	perror("Cannot open pipe to m4");
2578 	exit(0377);
2579     }
2580 
2581     mygethostname(client,MAXHOSTNAME);
2582 
2583     mygetostype  (ostype, sizeof ostype);
2584 
2585     /* Change the quoting characters, if specified */
2586 
2587     if (!m4_default_quotes)
2588       {
2589 	fprintf(tmpf, "changequote(%s, %s)dnl\n", m4_startquote, m4_endquote);
2590       }
2591 
2592     hostname = gethostbyname(client);
2593     strcpy(server, XDisplayName(host));
2594     colon = strchr(server, ':');
2595     if (colon != NULL) *colon = '\0';
2596     if ((server[0] == '\0') || (!strcmp(server, "unix")))
2597       strcpy(server, client);	/* must be connected to :0 or unix:0 */
2598 
2599     /* TWM_TYPE is afterstep, for completeness */
2600 
2601     fputs(MkDef("TWM_TYPE", "afterstep"), tmpf);
2602 
2603     /* The machine running the X server */
2604     fputs(MkDef("SERVERHOST", server), tmpf);
2605     /* The machine running the window manager process */
2606     fputs(MkDef("CLIENTHOST", client), tmpf);
2607     if (hostname)
2608       fputs(MkDef("HOSTNAME", (char *)hostname->h_name), tmpf);
2609     else
2610       fputs(MkDef("HOSTNAME", (char *)client), tmpf);
2611 
2612     fputs(MkDef("OSTYPE", ostype), tmpf);
2613 
2614     pwent=getpwuid(geteuid());
2615     fputs(MkDef("USER", pwent->pw_name), tmpf);
2616 
2617     fputs(MkDef("HOME", getenv("HOME")), tmpf);
2618     fputs(MkNum("VERSION", ProtocolVersion(display)), tmpf);
2619     fputs(MkNum("REVISION", ProtocolRevision(display)), tmpf);
2620     fputs(MkDef("VENDOR", ServerVendor(display)), tmpf);
2621     fputs(MkNum("RELEASE", VendorRelease(display)), tmpf);
2622     screen = ScreenOfDisplay(display, Scr.screen);
2623     visual = DefaultVisualOfScreen(screen);
2624     fputs(MkNum("WIDTH", Scr.MyDisplayWidth), tmpf);
2625     fputs(MkNum("HEIGHT", Scr.MyDisplayHeight), tmpf);
2626 
2627     fputs(MkNum("X_RESOLUTION",Resolution(screen->width,screen->mwidth)),tmpf);
2628     fputs(MkNum("Y_RESOLUTION",Resolution(screen->height,screen->mheight)),tmpf);
2629     fputs(MkNum("PLANES",DisplayPlanes(display, Scr.screen)), tmpf);
2630 
2631     fputs(MkNum("BITS_PER_RGB", visual->bits_per_rgb), tmpf);
2632 
2633     switch(visual->class)
2634       {
2635 	case(StaticGray):
2636 	  vc = "StaticGray";
2637 	break;
2638 	case(GrayScale):
2639 	  vc = "GrayScale";
2640 	break;
2641 	case(StaticColor):
2642 	  vc = "StaticColor";
2643 	break;
2644 	case(PseudoColor):
2645 	  vc = "PseudoColor";
2646 	break;
2647 	case(TrueColor):
2648 	  vc = "TrueColor";
2649 	break;
2650 	case(DirectColor):
2651 	  vc = "DirectColor";
2652 	break;
2653       default:
2654 	vc = "NonStandard";
2655 	break;
2656       }
2657 
2658     fputs(MkDef("CLASS", vc), tmpf);
2659     if (visual->class != StaticGray && visual->class != GrayScale)
2660       fputs(MkDef("COLOR", "Yes"), tmpf);
2661     else
2662       fputs(MkDef("COLOR", "No"), tmpf);
2663     fputs(MkDef("AFTER_VERSION", VERSION), tmpf);
2664 
2665     /* Add options together */
2666     *options = '\0';
2667 #ifdef	SHAPE
2668     strcat(options, "SHAPE ");
2669 #endif
2670 #ifdef	XPM
2671     strcat(options, "XPM ");
2672 #endif
2673 
2674     strcat(options, "M4 ");
2675 
2676 #ifdef	NO_PAGER
2677     strcat(options, "NO_PAGER ");
2678 #endif
2679 #ifdef	NON_VIRTUAL
2680     strcat(options, "NON_VIRTUAL ");
2681 #endif
2682 #ifdef	NO_SAVEUNDERS
2683     strcat(options, "NO_SAVEUNDERS ");
2684 #endif
2685 #ifdef	NO_WINDOWLIST
2686     strcat(options, "NO_WINDOWLIST ");
2687 #endif
2688 #ifdef	PRUNE
2689     strcat(options, "PRUNE ");
2690 #endif
2691     fputs(MkDef("OPTIONS", options), tmpf);
2692 
2693     fputs(MkDef("AFTERDIR", AFTERDIR), tmpf);
2694 
2695     /*
2696      * At this point, we've sent the definitions to m4.  Just include
2697      * the steprc file now.
2698      */
2699 
2700     fprintf(tmpf, "%sinclude(%s%s%s)\n",
2701 	    (m4_prefix) ? "m4_": "",
2702 	    m4_startquote,
2703 	    config_file,
2704 	    m4_endquote);
2705 
2706     pclose(tmpf);
2707     return(tmp_name);
2708 }
2709 #endif /* M4 */
2710