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