1 /* Copyright (C) 1993, 1992 Nathan Sidwell */
2 /* RCS $Id: makemred.c,v 4.30 1995/12/14 13:53:27 nathan Exp $ */
3 /*{{{  includes*/
4 #include "xmred.h"
5 #include "defmred.h"
6 #include <X11/Xaw/Form.h>
7 #include <X11/Xaw/Paned.h>
8 #include "makecom.c"
9 #include <X11/IntrinsicP.h>
10 #include <X11/CoreP.h>
11 #include "Icon.h"
12 #include "PixmapList.h"
13 #ifdef SCROLLBARBUGFIX
14 #include <X11/Xaw/Scrollbar.h>
15 #endif
16 /*}}}*/
17 /*{{{  define*/
18 /*{{{  gizmos*/
19 #define GIZMO_MRED   0
20 #define GIZMO_PANE   1
21 #define GIZMO_MENU   2
22 #define GIZMO_ONE    3
23 #define GIZMO_ALL    4
24 #define GIZMO_GARDEN 5
25 #define GIZMO_PANEL  6
26 /*}}}*/
27 /*}}}*/
28 /*{{{  tables*/
29 /*{{{  static GIZMO gizmos[] =*/
30 static GIZMO gizmos[] =
31 {
32   {"mred", -1, &formWidgetClass},
33   {"pane", GIZMO_MRED, &panedWidgetClass},
34   {"menus", GIZMO_PANE, &panedWidgetClass},
35   {"one", GIZMO_PANE, &panedWidgetClass},
36   {"all", GIZMO_PANE, &panedWidgetClass},
37   {"garden", GIZMO_ONE, &gardenWidgetClass},
38   {"panel", GIZMO_ONE, &formWidgetClass},
39 };
40 /*}}}*/
41 /*{{{  static Arg toplevel_args[] =*/
42 static Arg toplevel_args[] =
43 {
44   {XtNinput, True},
45 };
46 /*}}}*/
47 /*{{{  static Arg highlight_args[] =*/
48 static Arg highlight_args[] =
49 {
50   {XtNforeground, (XtArgVal)0},
51 };
52 /*}}}*/
53 /*{{{  static Arg color_args[] =*/
54 static Arg color_args[] =
55 {
56   {XtNforeground, (XtArgVal)0},
57   {XtNbackground, (XtArgVal)0},
58   {XtNborderColor, (XtArgVal)0},
59   {XtNinternalBorderColor, (XtArgVal)0},
60 };
61 /*}}}*/
62 /*{{{  static char CONST *fallback_resources[] =*/
63 static char CONST *fallback_resources[] =
64 {
65 #if __STDC__
66 "Xmris.Font:" FONT_NAME,
67 #else
68 "Xmris.Font:",
69 #endif
70 "*TransientShell.allowShellResize:yes",
71 "*Text.useStringInPlace:no",
72 "*dialog*resize:yes",
73 "*load*Text*editType:textAppend",
74 "*comment*Text.baseTranslations:#override",
75 "*load*Text.baseTranslations:#override \
76 <Key>Return:\n",
77 "*TransientShell.Dialog.Text.baseTranslations:#override \
78 <Key>Return:set-dialog-button(agree)\n\
79 Ctrl<Key>g:set-dialog-button(disagree)\n\
80 <Key>Escape:set-dialog-button(disagree)\n",
81 "*dialog*ok.label:Ok",
82 "*dialog*continue.label:Continue",
83 "*dialog*retry.label:Retry",
84 "*dialog*cancel.label:Cancel",
85 "*dialog*clear.label:Clear",
86 "*dialog*abort.label:Abort",
87 "*dialog*default.label:Default",
88 "*altered.title:Altered",
89 "*showGrip:no",
90 "*mred.defaultDistance:0",
91 "*pane.orientation:vertical",
92 "*menus.orientation:horizontal",
93 "*menus*allowResize:yes",
94 "*menus*justify:left",
95 "*file.label:File",
96 "*garden.label:Garden",
97 "*menu.undo.label:Undo",
98 "*menu.redo.label:Redo",
99 "*menu.clear.label:Clear",
100 "*menu.new.label:New",
101 "*menu.load.label:Load",
102 "*menu.insert.label:Insert",
103 "*menu.save.label:Save",
104 "*menu.saveas.label:Save As",
105 "*menu.quit.label:Quit",
106 "*Form.borderWidth:0",
107 "*Label.borderWidth:0",
108 "*all.orientation:horizontal",
109 "*buffer.skipAdjust:yes",
110 "*buffer.Icon.top:chainTop",
111 "*buffer.Icon.bottom:chainTop",
112 "*all.gardens.orientation:vertical",
113 "*gardens.gardens.min:51",
114 "*gardens.orientation:horizontal",
115 "*gardens.scrollbar.orientation:horizontal",
116 "*gardens.scrollbar.height:12",
117 "*gardens.scrollbar.thumb:None",
118 "*gardens.scrollbar.skipAdjust:yes",
119 "*edit.skipAdjust:yes",
120 "*edit.Icon.top:chainTop",
121 "*edit.Icon.bottom:chainTop",
122 "*edit.include.fromHoriz:comment",
123 "*edit.garden.fromHoriz:include",
124 "*one.defaultDistance:0",
125 "*one.orientation:horizontal",
126 "*one.garden.skipAdjust:yes",
127 "*one.panel.attach:garden",
128 "*panel.defaultDistance:0",
129 "*panel*Label.internalHeight:0",
130 "*panel*Label.internalWidth:0",
131 "*controls.defaultDistance:0",
132 "*controls*left:chainLeft",
133 "*controls*right:chainLeft",
134 "*controls.Form.Icon.top:chainTop",
135 "*controls.Form.Icon.bottom:chainTop",
136 "*options.label.label:Options",
137 "*controls*Icon.fromVert:label",
138 "*options.random.fromHoriz:apple",
139 "*options.cherry.fromHoriz:random",
140 "*options.path.fromHoriz:cherry",
141 "*options.player.fromHoriz:path",
142 "*options.den.fromHoriz:player",
143 "*fills.fromVert:options",
144 "*fills.label.label:Fills",
145 "*fills.fill1.fromHoriz:fill0",
146 "*fills.fill2.fromHoriz:fill1",
147 "*fills.fill3.fromHoriz:fill2",
148 "*colors.fromVert:fills",
149 "*colors.label.label:Colors",
150 "*colors.color1.fromHoriz:color0",
151 "*colors.color2.fromHoriz:color1",
152 "*buttons.fromVert:colors",
153 "*buttons.label.label:Buttons",
154 "*buttons.button2.fromHoriz:button1",
155 "*buttons.button3.fromHoriz:button2",
156 "*buttons.button4.fromHoriz:button3",
157 "*buttons.button5.fromHoriz:button4",
158 "*buttons.button1.option:path",
159 "*buttons.button2.option:cherry",
160 "*buttons.button3.option:apple",
161 "*buttons.button4.option:random",
162 "*totals.fromVert:controls",
163 "*totals.left:chainLeft",
164 "*totals.right:chainLeft",
165 "*totals.label.label:Totals",
166 "*totals.label.horizDistance:4",
167 "*totals.Form.defaultDistance:0",
168 "*total0.fromVert:label",
169 "*total0.horizDistance:28",
170 "*total1.fromVert:total0",
171 "*total1.horizDistance:28",
172 "*total2.fromVert:total1",
173 "*total2.horizDistance:28",
174 "*total3.fromVert:total2",
175 "*total3.horizDistance:28",
176 "*total4.fromVert:label",
177 "*total4.horizDistance:30",
178 "*total5.fromVert:total4",
179 "*total5.horizDistance:30",
180 "*total6.fromVert:total5",
181 "*total6.horizDistance:30",
182 "*total7.fromVert:total6",
183 "*total7.horizDistance:30",
184 "*total4.fromHoriz:total0",
185 "*total5.fromHoriz:total1",
186 "*total6.fromHoriz:total2",
187 "*total7.fromHoriz:total3",
188 "*total8.fromVert:total3",
189 "*total8.horizDistance:28",
190 "*total9.fromHoriz:total8",
191 "*total9.fromVert:total7",
192 "*total9.horizDistance:30",
193 "*count.fromHoriz:icon",
194 "*count.horizDistance:4",
195 "*totals.total5.icon.fromHoriz:scrollbar",
196 "*totals.Form.icon.horizDistance:0",
197 "*total5.scrollbar.height:32",
198 "*total5.scrollbar.width:12",
199 "*total5.scrollbar.minimumThumb:1",
200 "*total5.scrollbar.thumb:None",
201 "*total5.scrollbar.baseTranslations:#override \
202 ~Shift<KeyPress>space:StartScroll(Forward) NotifyScroll(FullLength) EndScroll()\n\
203 Shift<KeyPress>space:StartScroll(Backward) NotifyScroll(FullLength) EndScroll()\n",
204 "*totals.Form.icon.fromHoriz:warning",
205 "*panel.totals.Form.warning.width:12",
206 "*panel.totals.Form.warning.internalHeight:5",
207 "*panel.totals.Form.warning.internalWidth:1",
208 "*panel.totals.Form.count.height:34",
209 "*panel.totals.Form.count.width:32",
210 "*totals.Form.count.resize:no",
211 "*totals.Form.left:chainLeft",
212 "*totals.Form.right:chainLeft",
213 "*totals.Form.top:chainTop",
214 "*totals.Form.bottom:chainTop",
215 "*panel.mode.fromVert:totals",
216 "*mode.fromHoriz:comment",
217 "*mode.horizDistance:40",
218 "*mode.Icon.left:chainRight",
219 "*mode.Icon.right:chainRight",
220 "*mode.label.left:chainRight",
221 "*mode.label.right:chainRight",
222 "*mode.Icon.top:chainTop",
223 "*mode.Icon.bottom:chainTop",
224 "*mode.label.top:chainTop",
225 "*mode.label.bottom:chainTop",
226 "*mode.label.label:Mode",
227 "*mode.label.height:32",
228 "*mode.combined.fromHoriz:label",
229 "*mode.separate.fromHoriz:combined",
230 "*mode.random.fromHoriz:separate",
231 "*mode.left:chainLeft",
232 "*mode.right:chainLeft",
233 "*mode.top:chainBottom",
234 "*mode.bottom:chainBottom",
235 "*panel.comment.fromVert:totals",
236 "*comment.vertDistance:4",
237 "*comment.horizDistance:4",
238 "*comment.left:chainLeft",
239 "*comment.right:chainLeft",
240 "*comment.top:chainBottom",
241 "*comment.bottom:chainBottom",
242 NULL
243 };
244 /*}}}*/
245 /*}}}*/
246 /*{{{  prototypes*/
247 /*}}}*/
248 /*{{{  void create_gizmos(root, gizmos, num_gizmos)*/
249 extern VOIDFUNC create_gizmos
250 FUNCARG((root, gizmos, num_gizmos),
251 	Widget    root
252 ARGSEP  GIZMO     *gizmos
253 ARGSEP  Cardinal  num_gizmos
254 )
255 /*
256  * Creates a widget hierarchy according to the gizmo table
257  * supplied.
258  * The widget creation is done in this complicated fashion, so
259  * that the layout of form widget children can be specified in
260  * any order, and is not constrained by the order in which the
261  * widgets are created.
262  * I have also added an 'attach' resource for children of composite
263  * widgets.
264  */
265 {
266   /*{{{  resources*/
267   static char CONST *resources[] =
268     {
269       XtNfromHoriz,
270       XtNfromVert
271     };
272   /*}}}*/
273   GIZMO     *gptr;
274   int       parent;
275   int       count;
276   Widget    parent_widget;
277   int       parent_form;
278   int       parent_attach;
279   int       ix;
280 
281   count = num_gizmos;
282   while(count)
283     {
284       unsigned  children;
285 
286       for(gptr = gizmos, ix = num_gizmos; ix--; gptr++)
287 	if(!gptr->widget &&
288 	    (gptr->parent < 0 || gizmos[gptr->parent].widget))
289 	  break;
290       assert(ix >= 0);
291       parent = gptr->parent;
292       parent_widget = parent < 0 ? root : gizmos[parent].widget;
293       parent_form = XtClass(parent_widget) == formWidgetClass;
294       parent_attach = XtIsComposite(parent_widget) &&
295 	  !XtIsConstraint(parent_widget);
296       children = 0;
297       /*{{{  find siblings*/
298       for(gptr = gizmos, ix = num_gizmos; ix--; gptr++)
299 	if(gptr->parent == parent)
300 	  {
301 	    if(parent_form || parent_attach)
302 	      /*{{{  mark dependencies on siblings*/
303 	      {
304 		/*{{{  static XtResource formresources[] =*/
305 		static XtResource formresources[] =
306 		{
307 		  {XtNfromHoriz, XtCWidget, XtRString, sizeof(String),
308 		      0 * sizeof(String), XtRImmediate, NULL},
309 		  {XtNfromVert, XtCWidget, XtRString, sizeof(String),
310 		      1 * sizeof(String), XtRImmediate, NULL},
311 		};
312 		/*}}}*/
313 		/*{{{  static XtResource attachresources[] =*/
314 		static XtResource attachresources[] =
315 		{
316 		  {"attach", XtCWidget, XtRString, sizeof(String),
317 		      0 * sizeof(String), XtRImmediate, NULL},
318 		};
319 		/*}}}*/
320 		unsigned  ix;
321 		unsigned  child;
322 		GIZMO     *subptr;
323 		String    subrecs[2];
324 
325 		subrecs[1] = NULL;
326 		XtGetSubresources(parent_widget, (XtPointer)subrecs,
327 		    gptr->name,
328 		    ((CoreClassRec *)*gptr->class)->core_class.class_name,
329 		    parent_form ? formresources : attachresources,
330 		    parent_form ? XtNumber(formresources) :
331 		      XtNumber(attachresources), NULL, 0);
332 		child = 0;
333 		for(subptr = gizmos, ix = num_gizmos; ix--; subptr++)
334 		  if(subptr->parent == parent)
335 		    {
336 		      if(gptr != subptr)
337 			{
338 			  unsigned  i;
339 
340 			  for(i = 2; i--;)
341 			    if(subrecs[i] &&
342 				!strcmp(subrecs[i], subptr->name))
343 			      gptr->align[i] = num_gizmos - ix;
344 			}
345 		      child++;
346 		    }
347 	      }
348 	      /*}}}*/
349 	    children++;
350 	  }
351       /*}}}*/
352       count -= children;
353       /* create the siblings */
354       while(children--)
355 	{
356 	  /*{{{  find a child*/
357 	  {
358 	    GIZMO     *fptr;
359 
360 	    fptr = NULL;
361 	    for(gptr = gizmos, ix = num_gizmos; ix--; gptr++)
362 	      if(gptr->parent == parent && !gptr->widget)
363 		{
364 		  if(!parent_attach || !gptr->align[0] ||
365 		      gizmos[gptr->align[0] - 1].widget)
366 		    break;
367 		  if(!fptr)
368 		    fptr = gptr;
369 		}
370 	    if(ix < 0)
371 	      gptr = fptr;
372 	  }
373 	  /*}}}*/
374 	  /* create it */
375 	  {
376 	    Arg       args[2];
377 	    unsigned  nargs;
378 	    unsigned  count;
379 	    WidgetClass class;
380 
381 	    nargs = 0;
382 	    if(parent_form)
383 	      for(count = 2; count--;)
384 		if(gptr->align[count])
385 		  {
386 		    XtSetArg(args[nargs], (String)resources[count], NULL);
387 		    nargs++;
388 		  }
389 	    for(class = *gptr->class; class;
390 		class = ((CoreClassPart *)class)->superclass)
391 	      if(class == shellWidgetClass)
392 		{
393 		  gptr->widget = XtCreatePopupShell(gptr->name,
394 		      *gptr->class, parent_widget, args, nargs);
395 		  break;
396 		}
397 	    if(!class)
398 	      gptr->widget = XtCreateManagedWidget(gptr->name,
399 		  *gptr->class, parent_widget, args, nargs);
400 	    if(gptr->args)
401 	      XtSetValues(gptr->widget, gptr->args, gptr->num_args);
402 #ifdef SCROLLBARBUGFIX
403 	    if(*gptr->class == scrollbarWidgetClass)
404 	      /* EMPTY */;
405 	    else
406 #endif
407 	    if(display.black || display.white)
408 	      XtSetValues(gptr->widget, color_args, XtNumber(color_args));
409 	    if(data.mono == False && (*gptr->class == iconWidgetClass ||
410 		*gptr->class == pixmapListWidgetClass))
411 	      XtSetValues(gptr->widget, highlight_args,
412 		  XtNumber(highlight_args));
413 	  }
414 	}
415       if(parent_form)
416 	/*{{{  set args on siblings*/
417 	for(gptr = gizmos, ix = num_gizmos; ix--; gptr++)
418 	  if(gptr->parent == parent)
419 	    {
420 	      Arg       args[2];
421 	      unsigned  nargs;
422 	      unsigned  count;
423 
424 	      nargs = 0;
425 	      for(count = 2; count--;)
426 		if(gptr->align[count])
427 		  {
428 		    XtSetArg(args[nargs], (String)resources[count],
429 			gizmos[gptr->align[count] - 1].widget);
430 		    nargs++;
431 		  }
432 	      XtSetValues(gptr->widget, args, nargs);
433 	    }
434 	/*}}}*/
435     }
436   return;
437 }
438 /*}}}*/
439 /*{{{  void create_widget()*/
440 extern VOIDFUNC create_widget FUNCARGVOID
441 /*
442  * Create the graphics contexts, sprites and colours and stuff.
443  * sets visual and stuff for the toplevel widget
444  */
445 {
446   gizmos[GIZMO_GARDEN].name = &names[data.gender != False][1];
447   create_gizmos(display.toplevel, gizmos, XtNumber(gizmos));
448   create_resources(gizmos[GIZMO_GARDEN].widget);
449   color_args[0].value = (XtArgVal)display.black;
450   color_args[1].value = (XtArgVal)display.white;
451   color_args[2].value = (XtArgVal)display.border;
452   color_args[3].value = (XtArgVal)display.border;
453   if(data.mono == False)
454     highlight_args[0].value = (XtArgVal)colors[COLOR_APPLE_FAINT].pixel;
455   install_menubar(gizmos[GIZMO_MENU].widget);
456   install_control(gizmos[GIZMO_PANEL].widget);
457   install_garden(gizmos[GIZMO_GARDEN].widget);
458   install_all(gizmos[GIZMO_ALL].widget);
459   install_dialogs(gizmos[GIZMO_MRED].widget);
460   return;
461 }
462 /*}}}*/
463 /*{{{  void open_toolkit(arc, argv)*/
464 extern VOIDFUNC open_toolkit
465 FUNCARG((argc, argv),
466 	int     argc
467 ARGSEP  String  *argv
468 )
469 {
470 /*{{{  knr?*/
471 #if !__STDC__
472   {
473     char      *ptr;
474 
475     ptr = XtMalloc(strlen(fallback_resources[0]) + strlen(FONT_NAME) + 1);
476     strcpy(ptr, fallback_resources[0]);
477     strcat(ptr, FONT_NAME);
478     fallback_resources[0] = ptr;
479   }
480 #endif
481 /*}}}*/
482   extract_options(&argc, argv, command_options);
483   default_gender = GAME_GENDER;
484   if(data.help == False)
485     {
486       XrmOptionDescRec CONST *ptr;
487 
488       /* as options is an extern of unknown size, I can't use
489        * XtNumber() to get its size, so I've done it this way
490        */
491       for(ptr = options; *(char CONST **)ptr; ptr++)
492 	/* EMPTY */;
493       display.toplevel = XtAppInitialize(&display.context, "Xmris",
494 	  options, (Cardinal)(ptr - options),
495 	  (Cardinal *)&argc, (String *)argv,
496 	  (String *)fallback_resources,
497 	  toplevel_args, XtNumber(toplevel_args));
498       if(argc > 1)
499 	/*{{{  error*/
500 	{
501 	  unsigned  ix;
502 
503 	  data.help = True;
504 	  data.colors = False;
505 	  fprintf(stderr, "%s: Unknown option%s:", argv[0],
506 	      argc > 2 ? "s" : "");
507 	  for(ix = 1; ix != argc; ix++)
508 	    fprintf(stderr, "%s %s", ix == 1 ? "" : ",", argv[ix]);
509 	  fputc('\n', stderr);
510 	}
511 	/*}}}*/
512       else
513 	{
514 	  XtResource CONST *ptr;
515 
516 	  XtAppSetTypeConverter(display.context, XtRString, XtRGender,
517 	      convert_string2gender, (XtConvertArgRec *)NULL, 0, XtCacheNone,
518 	      (void (*)PROTOARG((XtAppContext, XrmValue *, XtPointer,
519 		  XrmValue *, Cardinal *)))NULL);
520 	  display.display = XtDisplay(display.toplevel);
521 	  for(ptr = resources; *(char CONST **)ptr; ptr++)
522 	    /* EMPTY */;
523 	  XtGetApplicationResources(display.toplevel, (XtPointer)&data,
524 	      resources, (Cardinal)(ptr - resources), (Arg *)NULL, 0);
525 #ifndef NDEBUG
526 	  XSetErrorHandler(error_handler);
527 #endif /* NDEBUG */
528 	  gettoplevelresources();
529 	}
530     }
531   return;
532 }
533 /*}}}*/
534