1 /****************************************************************************
2 **
3 *W  xcmds.c                     XGAP Source                      Frank Celler
4 **
5 **
6 *Y  Copyright 1995-1997,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
7 *Y  Copyright 1997,       Frank Celler,                 Huerth,       Germany
8 */
9 #include    "utils.h"			/* utility functions 		   */
10 
11 #include    "popdial.h"			/* popup dialogs 		   */
12 #include    "gapgraph.h"		/* gap graphic sheet               */
13 #include    "gaptext.h"			/* gap text sheet                  */
14 #include    "xgap.h"
15 #include    "pty.h"
16 #include    "selfile.h"
17 
18 #include    "xcmds.h"
19 
20 /****************************************************************************
21 **
22 
23 *F  * * * * * * * * * * * * *  local variables  * * * * * * * * * * * * * * *
24 */
25 
26 
27 /****************************************************************************
28 **
29 
30 *V  DialogOkCancel  . . . . . . . . . . . . . . . . .  Cancel/OK popup dialog
31 */
32 static TypePopupDialog DialogOkCancel;
33 
34 
35 /****************************************************************************
36 **
37 *V  GapWindows	. . . . . . . . . . . . . . . . . . . list of all gap windows
38 */
39 static TypeList GapWindows;
40 
41 
42 /****************************************************************************
43 **
44 *V  HugeFont  . . . . . . . . . . . . . . . . . . . huge font for text output
45 */
46 static XFontStruct * HugeFont;
47 
48 
49 /****************************************************************************
50 **
51 *V  LargeFont . . . . . . . . . . . . . . . . . .  large font for text output
52 */
53 static XFontStruct * LargeFont;
54 
55 
56 /****************************************************************************
57 **
58 *V  NormalFont  . . . . . . . . . . . . . . . . . normal font for text output
59 */
60 XFontStruct * NormalFont;
61 
62 
63 /****************************************************************************
64 **
65 *V  PopupMenus  . . . . . . . . . . . . . . . . . . . list of all popup menus
66 */
67 static TypeList PopupMenus;
68 
69 
70 /****************************************************************************
71 **
72 *V  RunCursor . . . . . . . . . . . . cursor used when GAP is accepting input
73 */
74 static Cursor RunCursor;
75 
76 
77 /****************************************************************************
78 **
79 *V  SleepCursor . . . . . . . . .  cursor used when GAP isn't accepting input
80 */
81 static Cursor SleepCursor;
82 
83 
84 /****************************************************************************
85 **
86 *V  SmallFont . . . . . . . . . . . . . . . . . .  small font for text output
87 */
88 static XFontStruct * SmallFont;
89 
90 
91 /****************************************************************************
92 **
93 *V  TextSelectors . . . . . . . . . . . . . . . .  list of all text selectors
94 */
95 static TypeList TextSelectors;
96 
97 
98 /****************************************************************************
99 **
100 *V  TinyFont  . . . . . . . . . . . . . . . . . . . tiny font for text output
101 */
102 static XFontStruct * TinyFont;
103 
104 
105 /****************************************************************************
106 **
107 
108 *F  * * * * * * * * * * * *  communication with GAP * * * * * * * * * * * * *
109 */
110 
111 
112 /****************************************************************************
113 **
114 
115 *F  AnswerGap( <format>, <arg1>, <arg2>, <arg3>, <arg4> ) . . . return answer
116 */
117 #define ANSWER_GAP(a,b,c,d,e)  \
118     AnswerGap( a, (Long)(b), (Long)(c), (Long)(d), (Long)(e) )
119 
AnswerGap(String format,Long a1,Long a2,Long a3,Long a4)120 static Boolean AnswerGap (
121     String       format,
122     Long         a1,
123     Long         a2,
124     Long         a3,
125     Long         a4 )
126 {
127     Int          arg;
128     Int          len;
129     Int          m;
130     Int          n;
131     Long         args[4];
132     String       ptr;
133     String       qtr;
134     String       str;
135     String       wtr;
136     Char         hdr[14];
137 
138     /* give debug information */
139     DEBUG( D_COMM, ( "AnswerGap( \"%s\", ... )\n", format ) );
140 
141     /* compute length of return string */
142     args[0] = a1;  args[1] = a2;  args[2] = a3;  args[3] = a4;
143     len = 12;
144     arg = 0;
145     for ( ptr = format;  *ptr;  ptr++ )
146     {
147 	if ( arg == 4 )
148 	    return False;
149 	switch ( *ptr )
150 	{
151 	    case 'O':
152 	    case 'o':  len += 9;  break;
153 	    case 'E':
154 	    case 'e':  len += 9;  break;
155 	    case 'D':
156 	    case 'd':  len += 9;  arg++;  break;
157 	    case 'S':
158 	    case 's':  len += 9 + strlen((String)args[arg++]);  break;
159 	    default :  return False;
160 	}
161     }
162 
163     /* allocate a string of length <len> */
164     str = XtMalloc(len);
165 
166     /* parse arguments again */
167     arg = 0;
168     qtr = str;
169     for ( ptr = format;  *ptr;  ptr++ )
170     {
171 	switch ( *ptr )
172 	{
173 	    case 'O':
174 	    case 'o':
175 	        strcpy( qtr, "I0+" );
176 		qtr += 3;
177 		break;
178 	    case 'E':
179 	    case 'e':
180 		strcpy( qtr, "I1+" );
181 		qtr += 3;
182 		break;
183 	    case 'D':
184 	    case 'd':
185 		*qtr++ = 'I';
186 		n = (Int)args[arg++];
187 		for ( m = ( 0 < n ) ? n : -n;  0 < m;  m /= 10 )
188 		    *qtr++ = '0' + (m%10);
189 		if ( n < 0 )
190 		    *qtr++ = '-';
191 		else
192 		    *qtr++ = '+';
193 		break;
194 	    case 'S':
195 	    case 's':
196 		*qtr++ = 'S';
197 		wtr = (String)(args[arg++]);
198 		for ( m = strlen(wtr);  0 < m;  m /= 10 )
199 		    *qtr++ = '0' + (m%10);
200 		*qtr++ = '+';
201 		while ( *wtr )
202 		    *qtr++ = *wtr++;
203 		break;
204 	}
205     }
206     *qtr = '\0';
207 
208     /* write header */
209     hdr[0] = '@';
210     hdr[1] = 'a';
211     qtr = hdr+2;
212     for ( m = strlen(str);  0 < m;  m/= 10 ) {
213 	*qtr++ = '0' + (m%10);
214     }
215     *qtr++ = '+';
216     *qtr = '\0';
217     WriteGap( hdr, strlen(hdr) );
218 
219     /* write result back to gap process */
220     WriteGap( str, strlen(str) );
221     XtFree(str);
222     return True;
223 }
224 
225 
226 /****************************************************************************
227 **
228 *F  ParseInt( <buf>, <val> )	. . . . . . . . . . . . . . . get a int value
229 */
ParseInt(String * buf,Int * val)230 static Boolean ParseInt (
231     String    * buf,
232     Int       * val )
233 {
234     Int         mult;
235 
236     if ( *(*buf)++ != 'I' )
237 	return False;
238     *val = 0;
239     mult = 1;
240     do
241     {
242 	if ( **buf == '+' )
243 	{
244 	    (*buf)++;
245 	    return True;
246 	}
247 	else if ( **buf == '-' )
248 	{
249 	    (*buf)++;
250 	    *val = -*val;
251 	    return True;
252 	}
253 	else if ( '0' <= **buf && **buf <= '9' )
254 	    *val += mult * (*((*buf)++)-'0');
255 	else
256 	    return False;
257 	mult = mult * 10;
258     } while (1);
259 }
260 
261 
262 /****************************************************************************
263 **
264 *F  ParseString( <buf>, <str>, <len> )	. . . . . . . get a string from <ptr>
265 */
ParseString(String * buf,String * str,Int * len)266 static Boolean ParseString (
267      String	  * buf,
268      String       * str,
269      Int          * len )
270 {
271      Int            i;
272      Int            m;
273      String         ptr;
274 
275      if ( (*buf)[0] != 'S' )
276          return False;
277      ptr = (*buf)+1;
278      for ( m=1,*len=0;  '0' <= *ptr && *ptr <= '9';  ptr++,m *= 10 )
279 	 *len += ( *ptr - '0' ) * m;
280      *buf = ptr+1;
281      *str = XtMalloc( (*len)+1 );
282      for ( ptr = *str, i = *len;  0 < i;  i--, ptr++, (*buf)++ )
283 	 if ( **buf == '@' )
284 	 {
285 	     (*buf)++;
286 	     if ( **buf == '@' )
287 		 *ptr = **buf;
288 	     else
289 		 *ptr = (**buf) - 'A';
290 	 }
291 	 else
292 	     *ptr = **buf;
293      *ptr = 0;
294      return True;
295 }
296 
297 
298 /****************************************************************************
299 **
300 *F  GapWindowCmd( <cstr>, <len> ) . . . . . . . execute window command <cstr>
301 */
302 extern TypeWindowCommand WindowCommands[];
303 
GapWindowCmd(String cstr,Int len)304 Boolean GapWindowCmd (
305     String              cstr,
306     Int                 len )
307 {
308     Boolean             ret;
309     Int			ca;
310     Int			ci;
311     Int			cs;
312     Int                 i;
313     String              pa;
314     String              str = cstr+3;
315     TypeArg	        arg;
316     TypeWindowCommand * cmd;
317     char                name[4];
318 
319     /* give debug information */
320     name[0] = cstr[0];  name[1] = cstr[1];  name[2] = cstr[2];  name[3] = 0;
321     DEBUG( D_XCMD, ( "GapWindowCmd( \"%s\" )\n", name ) );
322 
323     /* try to find the command in <WindowCommands> */
324     cmd = WindowCommands;
325     while ( cmd->name )
326 	if ( !strncmp( cmd->name, name, 3 ) )
327 	    break;
328 	else
329 	    cmd++;
330     if ( !cmd->name )
331 	return ANSWER_GAP( "esss", "unknown command '", name, "'", 0 );
332 
333     /* parse arguments */
334     arg.opts = 0;
335     ci = cs = 0;
336     ca = 1;
337     pa = cmd->args;
338     while ( *pa )
339     {
340 	if ( *pa == '*' )
341 	{
342 	    arg.opts = str;
343 	    break;
344 	}
345 	else if ( *pa == 'S' || *pa == 's' )
346 	{
347 	    if ( !ParseString( &str, &(arg.sargs[cs]), &len ) )
348 	    {
349 		ret = ANSWER_GAP("eds",ca,".th arg must be a string",0,0);
350 		goto free_strings;
351 	    }
352 	    else
353 		cs++;
354 	}
355 	else if ( *pa == '#' )
356 	{
357 	    if ( !ParseInt( &str, &i ) )
358 	    {
359 		ret = ANSWER_GAP("eds",ca,".th arg must be a window nr",0,0);
360 		goto free_strings;
361 	    }
362 	    arg.iargs[ci++] = i;
363 	    if ( LEN(GapWindows) <= arg.iargs[0] || arg.iargs[0] < 0 )
364 	    {
365 		ret = ANSWER_GAP( "es", "illegal window number", 0, 0, 0 );
366 		goto free_strings;
367 	    }
368 	    arg.win = (TypeGapWindow*)(ELM(GapWindows,arg.iargs[0]));
369 	    if ( ! arg.win->used )
370 	    {
371 		ret = ANSWER_GAP( "es", "window not used", 0, 0, 0 );
372 		goto free_strings;
373 	    }
374 	}
375 	else if ( *pa == 'T' )
376 	{
377 	    if ( !ParseInt( &str, &i ) )
378 	    {
379 		ret = ANSWER_GAP("eds",ca,".th arg must be a selector",0,0);
380 		goto free_strings;
381 	    }
382 	    arg.iargs[ci++] = i;
383 	    if ( LEN(TextSelectors) <= arg.iargs[0] || arg.iargs[0] < 0 )
384 	    {
385 		ret = ANSWER_GAP( "es", "illegal selector number", 0, 0, 0 );
386 		goto free_strings;
387 	    }
388 	    arg.sel = (TypeTextSelector*)(ELM(TextSelectors,arg.iargs[0]));
389 	    if ( arg.sel == 0)
390 	    {
391 		ret = ANSWER_GAP( "es", "selector not used", 0, 0, 0 );
392 		goto free_strings;
393 	    }
394 	}
395 	else if ( *pa == 'F' )
396 	{
397 	    if ( !ParseInt( &str, &i ) )
398 	    {
399 		ret = ANSWER_GAP("eds",ca,".th arg must be an integer",0,0);
400 		goto free_strings;
401 	    }
402 	    arg.iargs[ci++] = i;
403 	    switch ( (int)arg.iargs[ci-1] )
404 	    {
405 		case 1:  arg.font = TinyFont;   break;
406 		case 2:  arg.font = SmallFont;  break;
407 		case 3:  arg.font = NormalFont; break;
408 		case 4:  arg.font = LargeFont;  break;
409 		case 5:  arg.font = HugeFont;   break;
410 		default:
411 		    ret = ANSWER_GAP( "eds", ca,
412 				      ".th arg must be a font number", 0, 0 );
413 		    goto free_strings;
414 		    break;
415 	    }
416 	}
417 	else
418 	{
419 	    if ( !ParseInt( &str, &i ) )
420 	    {
421 		ret = ANSWER_GAP("eds",ca,".th arg must be an integer",0,0);
422 		goto free_strings;
423 	    }
424 	    arg.iargs[ci++] = i;
425 	}
426 	ca++;
427 	pa++;
428     }
429     if ( *pa != '*' && *str )
430     {
431 	ret = ANSWER_GAP( "es", "too many arguments", 0, 0, 0 );
432 	goto free_strings;
433     }
434 
435 
436     /* call command */
437     ret = cmd->func( &arg );
438 
439     /* free argument strings */
440 free_strings:
441     for ( i = 0;  i < cs;  i++ )
442 	XtFree( arg.sargs[i] );
443     return ret;
444 }
445 
446 
447 /****************************************************************************
448 **
449 
450 *F  * * * * * * * * * * * functions for TextSelectors * * * * * * * * * * * *
451 */
452 
453 
454 /****************************************************************************
455 **
456 
457 *F  FunOpenSelector( <name>, <list>, <buttons> )  .  open a new text selector
458 */
ButtonSelected(Widget w,XtPointer cl,XtPointer ca)459 static void ButtonSelected (
460     Widget	    w,
461     XtPointer       cl,
462     XtPointer       ca )
463 {
464     Int             i = ((Int) ((Long)cl&0xffff)) % 256;
465     Int             n = ((Int) ((Long)cl&0xffff)) / 256;
466     char            buf[128];
467 
468     DEBUG( D_XCMD, ("ButtonSelected( #%ld, #%ld )\n", (long)n, (long)i) );
469     sprintf( buf, "ButtonSelected(%ld,%ld);\n", (long)n, (long)i );
470     SimulateInput(buf);
471 }
472 
TextSelected(Widget w,XtPointer cl,XtPointer ca)473 static void TextSelected (
474     Widget	            w,
475     XtPointer               cl,
476     XtPointer               ca )
477 {
478     XawListReturnStruct	  * ret = (XawListReturnStruct*) ca;
479     Int                     n = (Int) ((Long)cl&0xffff);
480     Int                     m = (Int) ret->list_index;
481     char                    buf[128];
482 
483     DEBUG( D_XCMD, ("TextSelected( #%ld, $%ld )\n", (long)n, (long)m+1 ) );
484     sprintf( buf, "TextSelected(%ld,%ld);\n", (long)n, (long)m+1 );
485     SimulateInput(buf);
486 }
487 
NotifyClick(Widget w,XEvent * evt,String * str,Cardinal * n)488 static void NotifyClick (
489     Widget	    	  w,
490     XEvent              * evt,
491     String        	* str,
492     Cardinal      	* n )
493 {
494     XawListReturnStruct	  * ret;
495     Int                     i;
496     char                    buf[128];
497 
498     /* get currently selected */
499     ret = XawListShowCurrent(w);
500 
501     /* if something is set,  return */
502     if ( ret->list_index != XAW_LIST_NONE )
503 	return;
504 
505     /* find widget */
506     for ( i = 0;  i < LEN(TextSelectors);  i++ )
507 	if ( ((TypeTextSelector*)ELM(TextSelectors,i))->list == w )
508 	{
509 	    sprintf( buf, "TextSelected(%ld,0);\n", (long)i );
510 	    SimulateInput(buf);
511 	    return;
512 	}
513 
514 }
515 
516 static char ButtonPressTrans[] =
517     "<Btn1Down>,<Btn1Up>: Notify() NotifyClick()";
518 
FunOpenSelector(TypeArg * arg)519 static Boolean FunOpenSelector (
520     TypeArg           * arg )
521 {
522     Int                 i;
523     Int                 n;
524     String              name = arg->sargs[0];
525     String              ptr;
526     String              qtr;
527     TypeTextSelector  * selector;
528     Widget              box;
529     Widget              button;
530     Widget              paned;
531     Widget              viewport;
532     char                buf[512];
533 
534     /* give debug info */
535     DEBUG( D_XCMD, ( "OpenSelector( \"%s\", \"%s\", \"%s\" )\n",
536 	    arg->sargs[0], arg->sargs[1], arg->sargs[2] ) );
537 
538     /* create a new selector entry */
539     selector = (TypeTextSelector*) XtMalloc( sizeof(TypeTextSelector) );
540 
541     /* create a new top level shell */
542     selector->top = XtAppCreateShell(
543 		        "TextSelector", "XGap", topLevelShellWidgetClass,
544 			GapDisplay, 0, 0 );
545 
546     /* create a "paned" for the menu and text window */
547     paned = XtVaCreateManagedWidget(
548 	        "textSelector", panedWidgetClass, selector->top, (String)NULL );
549 
550     /* create a headline */
551     XtVaCreateManagedWidget(
552         "textSelectorTitle", labelWidgetClass, paned,
553         XtNlabel, (XtArgVal)name, (String)NULL );
554 
555 
556     /* create a viewport for the text selectors */
557     viewport = XtVaCreateManagedWidget(
558 	           "textSelectorViewport", viewportWidgetClass, paned,
559 		   XtNallowHoriz,       (XtArgVal)False,
560 		   XtNallowVert,        (XtArgVal)True,
561 		   XtNuseBottom,        (XtArgVal)True,
562 		   XtNshowGrip,         (XtArgVal)False,
563 		   (String)NULL );
564 
565     /* compute number of entries */
566     for ( i = 2, qtr = arg->sargs[1];  *qtr;  qtr++ )
567 	if ( *qtr == '|' )
568 	    i++;
569     selector->text = (String*) XtMalloc(i*sizeof(String));
570 
571     /* parse text */
572     for ( ptr = arg->sargs[1], i = 0;  *ptr;  i++ )
573     {
574     	qtr = buf;
575     	while ( *ptr && *ptr != '|' )
576     	    *qtr++ = *ptr++;
577     	*qtr = 0;
578     	if ( *ptr )  ptr++;
579     	DEBUG( D_XCMD, ( "  entry = \"%s\"\n", buf ) );
580 	selector->text[i] = (String) XtMalloc(strlen(buf)+1);
581 	strcpy( selector->text[i], buf );
582     }
583     selector->text[i] = 0;
584 
585     /* find free entry in <TextSelectors> */
586     for ( n = 0;  n < LEN(TextSelectors);  n++ )
587 	if ( ELM(TextSelectors,n) == 0 )
588 	    break;
589     if ( n == LEN(TextSelectors) )
590 	AddList( TextSelectors, selector );
591     else
592 	ELM(TextSelectors,n) = selector;
593 
594     /* create a list widget containing the text */
595     selector->list = XtVaCreateManagedWidget(
596 		         "textSelectorList", listWidgetClass, viewport,
597 			 XtNlist,           (XtArgVal)selector->text,
598 			 XtNdefaultColumns, (XtArgVal)1,
599 			 XtNforceColumns,   (XtArgVal)True,
600 			 (String)NULL );
601     XtOverrideTranslations( selector->list,
602 			    XtParseTranslationTable(ButtonPressTrans) );
603     XtAddCallback( selector->list, XtNcallback, TextSelected,
604 		   (XtPointer)(n&0xffffL) );
605 
606     /* create a box containing the buttons */
607     box = XtVaCreateManagedWidget(
608 	      "textSelectorBox", boxWidgetClass, paned,
609 	      XtNorientation,           (XtArgVal)XtorientHorizontal,
610        	      XtNshowGrip,              (XtArgVal)False,
611 	      XtNskipAdjust,            (XtArgVal)True,
612 	      XtNresizeToPreferred, 	(XtArgVal)True,
613 	      (String)NULL );
614 
615     /* parse buttons */
616     selector->buttons = List(0);
617     for ( ptr = arg->sargs[2], i = 1;  *ptr;  i++ )
618     {
619     	qtr = buf;
620     	while ( *ptr && *ptr != '|' )
621     	    *qtr++ = *ptr++;
622     	*qtr = 0;
623     	if ( *ptr )  ptr++;
624     	DEBUG( D_XCMD, ( "  button = \"%s\"\n", buf ) );
625 	button = XtVaCreateManagedWidget(
626 	             "textSelectorButton", commandWidgetClass, box,
627 	             XtNlabel,      (XtArgVal)buf,
628 	             XtNshapeStyle, (XtArgVal)XmuShapeOval,
629 	             (String)NULL );
630 	XtAddCallback(button,XtNcallback,ButtonSelected,
631 		      (XtPointer)((i+n*256)&0xffffL));
632 	AddList( selector->buttons, button );
633     }
634 
635 
636     /* realize the window and return the number */
637     XtRealizeWidget(selector->top);
638 
639     /* add window to list and return window number */
640     return ANSWER_GAP( "od", n, 0, 0, 0 );
641 }
642 
643 
644 /****************************************************************************
645 **
646 *F  FunCloseSelector( <sel> ) . . . . . . . . . destroy an open text selector
647 */
FunCloseSelector(TypeArg * arg)648 static Boolean FunCloseSelector (
649     TypeArg   * arg )
650 {
651     Int         i;
652 
653     /* give debug info */
654     DEBUG( D_XCMD, ( "CloseSelector( #%ld )\n", (long)arg->iargs[0] ) );
655 
656     /* destroy top level shell (this will destroy all children) */
657     XtDestroyWidget(arg->sel->top);
658 
659     /* clear text */
660     for ( i = 0;  arg->sel->text[i];  i++ )
661 	XtFree( arg->sel->text[i] );
662     XtFree( (char*) arg->sel->text );
663 
664     /* clear button list */
665     XtFree( (char*) arg->sel->buttons->ptr );
666     XtFree( (char*) arg->sel->buttons );
667 
668     /* clear entry in <TextSelectors> */
669     ELM(TextSelectors,arg->iargs[0]) = 0;
670     XtFree((char*)arg->sel);
671 
672     /* return OK */
673     return AnswerGap( "o", 0, 0, 0, 0 );
674 }
675 
676 
677 /****************************************************************************
678 **
679 *F  FunChangeList( <sel>, <buttons> )   . . . .  change list in text selector
680 */
FunChangeList(TypeArg * arg)681 static Boolean FunChangeList (
682     TypeArg       * arg )
683 {
684     Int             i;
685     String          ptr;
686     String          qtr;
687     String        * text;
688     char            buf[512];
689 
690     /* give debug info */
691     DEBUG( D_XCMD, ( "ChangeList( #%ld, \"%s\" )\n", (long)arg->iargs[0],
692 	   arg->sargs[0] ) );
693 
694     /* compute number of entries */
695     for ( i = 2, qtr = arg->sargs[0];  *qtr;  qtr++ )
696 	if ( *qtr == '|' )
697 	    i++;
698     text = (String*) XtMalloc(i*sizeof(String));
699 
700     /* parse text */
701     for ( ptr = arg->sargs[0], i = 0;  *ptr;  i++ )
702     {
703     	qtr = buf;
704     	while ( *ptr && *ptr != '|' )
705     	    *qtr++ = *ptr++;
706     	*qtr = 0;
707     	if ( *ptr )  ptr++;
708     	DEBUG( D_XCMD, ( "  entry = \"%s\"\n", buf ) );
709 	text[i] = (String) XtMalloc(strlen(buf)+1);
710 	strcpy( text[i], buf );
711     }
712     text[i] = 0;
713 
714     /* change list */
715     XawListChange( arg->sel->list, text, 0, 0, True );
716 
717     /* clear old text */
718     for ( i = 0;  arg->sel->text[i];  i++ )
719 	XtFree( arg->sel->text[i] );
720     XtFree( (char*) arg->sel->text );
721     arg->sel->text = text;
722 
723     /* return OK */
724     return AnswerGap( "o", 0, 0, 0, 0 );
725 }
726 
727 
728 /****************************************************************************
729 **
730 *F  FunEnableButton( <sel>, <but>, <enable> ) . . . . enable/disable a button
731 */
FunEnableButton(TypeArg * arg)732 static Boolean FunEnableButton (
733     TypeArg   * arg )
734 {
735     Int         i;
736     Widget      entry;
737 
738     /* give debug info */
739     DEBUG( D_XCMD, ( "EnableButton( #%ld, #%ld, #%ld )\n",
740            (long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2] ) );
741 
742     /* check button number */
743     i = arg->iargs[1]-1;
744     if ( LEN(arg->sel->buttons) <= i || i < 0 )
745 	return ANSWER_GAP( "es", "illegal button number", 0, 0, 0 );
746     entry = ELM(arg->sel->buttons,i);
747 
748     /* enable/disable */
749     if ( arg->iargs[2] )
750 	XtVaSetValues( entry, XtNsensitive, (XtArgVal)True, (String)NULL );
751     else
752 	XtVaSetValues( entry, XtNsensitive, (XtArgVal)False, (String)NULL );
753 
754     /* return OK */
755     return AnswerGap( "o", 0, 0, 0, 0 );
756 }
757 
758 
759 /****************************************************************************
760 **
761 *F  FunUnhighlihtSelector( <sel> )  . . . . . . . . . . ..  unhighlight entry
762 */
FunUnhighlihtSelector(TypeArg * arg)763 static Boolean FunUnhighlihtSelector (
764     TypeArg   * arg )
765 {
766     /* give debug info */
767     DEBUG( D_XCMD, ( "Unhighlight( #%ld )\n", (long)arg->iargs[0] ) );
768 
769     /* unhighlight entry */
770     XawListUnhighlight(arg->sel->list);
771 
772     /* return OK */
773     return AnswerGap( "o", 0, 0, 0, 0 );
774 }
775 
776 
777 /****************************************************************************
778 **
779 
780 *F  * * * * * * * * * * *  functions for PopupMenus * * * * * * * * * * * * *
781 */
782 
783 
784 /****************************************************************************
785 **
786 
787 *F  FunPopupShell( <name>, <str> )  . . . . . . . . . .  create a popup shell
788 */
789 static Int ChosenPane = 0;
790 
PaneChosen(Widget w,XtPointer cl,XtPointer ca)791 static void PaneChosen (
792     Widget	    w,
793     XtPointer       cl,
794     XtPointer       ca )
795 {
796     TypePaneData  * pd = (TypePaneData*) cl;
797 
798     DEBUG( D_XCMD, ( "PaneChosen( #%ld, #%ld )\n", (long)pd->popup,
799            (long)pd->pane ) );
800     ChosenPane = pd->pane;
801 }
802 
PopingDown(Widget w,XtPointer cl,XtPointer ca)803 static void PopingDown (
804     Widget	w,
805     XtPointer   cl,
806     XtPointer   ca )
807 {
808     DEBUG( D_XCMD, ( "PopingDown\n" ) );
809     ANSWER_GAP( "od", ChosenPane, 0, 0, 0 );
810 }
811 
812 static char PopingDownTrans[] =
813     "<BtnUp>: notify() MenuPopdown() unhighlight()";
814 
FunPopupShell(TypeArg * arg)815 static Boolean FunPopupShell (
816     TypeArg       * arg )
817 {
818     Int             i;
819     String          ptr;
820     String          qtr;
821     TypeMenu      * menu;
822     TypePaneData  * pd;
823     Widget          pane;
824     Widget          pshell;
825     char	    buf[128];
826 
827     /* search for an identical popup shell */
828     for ( i = 0;  i < LEN(PopupMenus);  i++ )
829     {
830 	menu = ELM(PopupMenus,i);
831 	if (    ! strcmp( menu->name,   arg->sargs[0]  )
832 	     && ! strcmp( menu->string, arg->sargs[1]) )
833 	    break;
834     }
835     if ( i < LEN(PopupMenus) )
836 	return ANSWER_GAP( "od", i, 0, 0, 0 );
837 
838     /* create a shell */
839     pshell = XtVaCreatePopupShell( "pshell", simpleMenuWidgetClass,
840     	    	    	    	   XGap, XtNcursor, (XtArgVal)CursorTL,
841                                    (String)NULL );
842     XtOverrideTranslations( pshell,
843 			    XtParseTranslationTable(PopingDownTrans) );
844 
845     /* create headline */
846     DEBUG( D_XCMD, ( "PopupShell( \"%s\", ... )\n", arg->sargs[0] ) );
847     XtVaCreateManagedWidget( "menulabel", smeBSBObjectClass, pshell,
848     	    	    	     XtNsensitive, (XtArgVal)False,
849     	    	    	     XtNlabel,     (XtArgVal)(arg->sargs[0]),
850     	    	    	     (String)NULL );
851     XtVaCreateManagedWidget( "line", smeLineObjectClass, pshell, (String)NULL );
852 
853     /* add popdown callback */
854     XtAddCallback( pshell, XtNpopdownCallback, PopingDown, 0 );
855 
856     /* create menu entries */
857     menu = (TypeMenu*) XtMalloc( sizeof(TypeMenu) );
858     menu->shell   = pshell;
859     menu->entries = List(0);
860     menu->name    = XtMalloc(strlen(arg->sargs[0])+1);
861     menu->string  = XtMalloc(strlen(arg->sargs[1])+1);
862     strcpy( menu->name,   arg->sargs[0] );
863     strcpy( menu->string, arg->sargs[1] );
864     for ( ptr = arg->sargs[1], i = 1;  *ptr;  i++ )
865     {
866     	qtr = buf;
867     	while ( *ptr && *ptr != '|' )
868     	    *qtr++ = *ptr++;
869     	*qtr = 0;
870     	if ( *ptr )  ptr++;
871     	DEBUG( D_XCMD, ( "  entry = \"%s\"\n", buf ) );
872     	pane = XtVaCreateManagedWidget( "menupane", smeBSBObjectClass,
873     	    	    	    	    	pshell, XtNlabel, (XtArgVal)buf,
874                                         (String)NULL );
875     	pd = (TypePaneData*) XtMalloc( sizeof(TypePaneData) );
876     	pd->pane   = i;
877     	pd->popup  = LEN(PopupMenus);
878     	pd->shell  = pshell;
879     	XtAddCallback( pane, XtNcallback, PaneChosen, pd );
880 	AddList( menu->entries, (void*) pd );
881     }
882 
883     /* add shell to popup shell list */
884     AddList( PopupMenus, (void*) menu );
885     return ANSWER_GAP( "od", LEN(PopupMenus)-1, 0, 0, 0 );
886 }
887 
888 
889 /****************************************************************************
890 **
891 *F  FunShowPopup( <nr> )  . . . . . . . . . . . . . . . . popup a popup shell
892 */
FunShowPopup(TypeArg * arg)893 static Boolean FunShowPopup (
894     TypeArg       * arg )
895 {
896     Dimension       w1,  h1,  bw;
897     Int        	    x,  y,  x2,  y2;
898     Position        tmp;
899     UInt            bt;
900     Widget     	    popup;
901     Window          child;
902     Window          root;
903 
904     /* check popup number */
905     if ( LEN(PopupMenus) <= arg->iargs[0] || arg->iargs[0] < 0 )
906 	return ANSWER_GAP("esd","illegal popup menu ",arg->iargs[0],0,0);
907     popup = ((TypeMenu*)ELM(PopupMenus,arg->iargs[0]))->shell;
908 
909     /* get size of popup dialog */
910     XtVaGetValues( popup,
911                    XtNwidth,       (XtArgVal)&w1,
912                    XtNheight,      (XtArgVal)&h1,
913                    XtNborderWidth, (XtArgVal)&bw,
914                    (String)NULL );
915 
916     /* compute screen position */
917     XQueryPointer( GapDisplay, MyRootWindow,
918     	    	   &root, &child, &x, &y, &x2, &y2, &bt );
919     tmp = DisplayWidth( GapDisplay, GapScreen );
920     if ( x+w1 > tmp )
921 	x = tmp-w1;
922     tmp = DisplayHeight( GapDisplay, GapScreen );
923     if ( y+h1 > tmp )
924 	y = tmp-h1;
925 
926     /* popup the popup shell */
927     XtVaSetValues( popup, XtNx, (XtArgVal)(x-10), XtNy, (XtArgVal)(y-10),
928                    (String)NULL );
929     XawSimpleMenuClearActiveEntry( popup );
930     XtPopupSpringLoaded( popup );
931     XtGrabPointer( popup, True, ButtonPressMask|ButtonReleaseMask,
932 		   GrabModeAsync, GrabModeAsync, None, None, CurrentTime );
933 
934     /* reset 'ChosenPane' */
935     ChosenPane = 0;
936 
937     /* gap will be answered by 'PopingDown' */
938     return True;
939 }
940 
941 
942 /****************************************************************************
943 **
944 
945 *F  * * * * * * * * * * * * functions for Dialogs * * * * * * * * * * * * * *
946 */
947 
948 
949 /****************************************************************************
950 **
951 
952 *F  FunShowDialog( <nr>, <msg>, <def> )	. . . . . . . . . . show popup dialog
953 */
FunShowDialog(TypeArg * arg)954 static Boolean FunShowDialog (
955     TypeArg       * arg )
956 {
957     Int             first;
958     Int             res;
959     String          str;
960 #ifndef NO_FILE_SELECTOR
961     static String   tmp = 0;
962 #endif
963 
964     /* OK/Cancel dialog */
965     if ( arg->iargs[0] == 1 )
966     {
967 	first  = 4;
968 	res    = PopupDialog( DialogOkCancel, arg->sargs[0],
969 			      arg->sargs[1], &str );
970     }
971 
972     /* filename dialog */
973     else if ( arg->iargs[0] == 2 )
974     {
975 #       ifdef NO_FILE_SELECTOR
976 	  first  = 4;
977 	  res    = PopupDialog( DialogOkCancel, arg->sargs[0],
978 			        arg->sargs[1], &str );
979 #       else
980 
981 	  /* free memory from the previous run */
982 	  if ( tmp ) {
983 	      XtFree(tmp);
984               tmp = NULL;
985           }
986 
987 	  /* call the file selector */
988 	  if ( *(arg->sargs[1]) )
989 	      res = XsraSelFile(XGap,arg->sargs[0],arg->sargs[1],0,&str);
990 	  else
991 	      res = XsraSelFile(XGap,arg->sargs[0],0,0,&str);
992 
993 	  /* ok is first button */
994 	  first = 1;
995 	  if ( res != first )
996 	      str = "";
997           else
998 	      tmp = str;
999 
1000 #       endif
1001     }
1002 
1003     /* unkown dialog */
1004     else
1005 	return ANSWER_GAP("esd","illegal popup dialog ",arg->iargs[0],0,0);
1006 
1007     /* return the result */
1008     return ANSWER_GAP( "ods", (res==first)?0:1, str, 0, 0 );
1009 }
1010 
1011 
1012 /****************************************************************************
1013 **
1014 
1015 *F  * * * * * * * * * * * * functions for Windows * * * * * * * * * * * * * *
1016 */
1017 
1018 
1019 /****************************************************************************
1020 **
1021 
1022 *F  CloseWindow( <win> )  . . . . . . . . . . . . . . .  close an open window
1023 */
CloseWindow(TypeGapWindow * win)1024 static void CloseWindow (
1025     TypeGapWindow * win )
1026 {
1027     Int             i;
1028     Int             j;
1029     TypeMenu      * menu;
1030 
1031     /* set <used> to false */
1032     win->used = False;
1033 
1034     /* free all menus */
1035     for ( i = 0;  i < LEN(win->menus);  i++ )
1036 	if ( (menu=ELM(win->menus,i)) != 0 )
1037 	{
1038 	    for ( j = 0;  j < LEN(menu->entries);  j++ )
1039 		XtFree((char*)ELM(menu->entries,j));
1040 	    XtFree((char*)menu->entries->ptr);
1041 	    XtFree((char*)menu->entries);
1042 	    XtFree((char*)menu);
1043 	}
1044     XtFree((char*)win->menus->ptr);
1045     XtFree((char*)win->menus);
1046 
1047     /* destroy top level shell (this will destroy all children) */
1048     XtDestroyWidget(win->top);
1049 }
1050 
1051 
1052 /****************************************************************************
1053 **
1054 *F  MouseClickWindow( <talk>, <cd>, <evt>, <ctd> )  . .  handle a mouse click
1055 */
MouseClickWindow(Widget talk,XtPointer cd,XEvent * evt,Boolean * ctd)1056 static void MouseClickWindow (
1057     Widget 	    talk,
1058     XtPointer       cd,
1059     XEvent        * evt,
1060     Boolean       * ctd )
1061 {
1062     Int             bn;
1063     TypeGapWindow * gap = ELM(GapWindows,(Int)((Long)cd&0xffff));
1064     char            buf[100];
1065 
1066     /* we only have a two button mouse */
1067     if ( evt->xbutton.button == Button1 )
1068         bn = 1;
1069     else if ( evt->xbutton.button == Button3 )
1070         bn = 2;
1071     else
1072 	return;
1073 
1074     /* check boundaries */
1075     if ( gap->width <= evt->xbutton.x || gap->height <= evt->xbutton.y )
1076 	return;
1077 
1078     /* give debug information */
1079     DEBUG( D_XCMD, ( "MouseClickWindow( %ld, %ld, %ld, %ld )\n", (long)cd,
1080 	    (long)(evt->xbutton.x), (long)(evt->xbutton.y), (long)bn ) );
1081 
1082     /* construct gap command */
1083     sprintf( buf, "PointerButtonDown(%ld,%ld,%ld,%ld);\n", (long)cd,
1084 	     (long)evt->xbutton.x, (long)evt->xbutton.y, (long)bn );
1085     SimulateInput(buf);
1086 }
1087 
1088 
1089 /****************************************************************************
1090 **
1091 *F  WmDeleteWindow( <w>, <event>, <pars>, <n> ) . . . . . . wm delete request
1092 */
1093 static char * WmDeleteWindowTranslation =
1094     "<Message>WM_PROTOCOLS: WmDeleteWindow()\n";
1095 
WmDeleteWindow(Widget w,XEvent * event,String * pars,Cardinal * n)1096 static void WmDeleteWindow (
1097     Widget 	    w,
1098     XEvent        * event,
1099     String        * pars,
1100     Cardinal      * n )
1101 {
1102     TypeGapWindow * win;
1103     Int             i;
1104 
1105     if ( event->type == ClientMessage
1106          && event->xclient.data.l[0] != WmDeleteWindowAtom )
1107 	return;
1108     for ( i = 0;  i < LEN(GapWindows);  i++ )
1109     {
1110 	win = (TypeGapWindow*)ELM(GapWindows,i);
1111 	if ( win->used && win->top == w )
1112 	    break;
1113     }
1114     if ( i < LEN(GapWindows) )
1115 	CloseWindow(win);
1116 }
1117 
1118 
1119 /****************************************************************************
1120 **
1121 *F  FunOpenWindow( <name>, <width>, <height> )	. open a new window, external
1122 */
CreateTitleWindow(Widget paned)1123 static Widget CreateTitleWindow (
1124     Widget	    paned )
1125 {
1126     return XtVaCreateManagedWidget(
1127 		       "xgapWindowText",
1128 		       labelWidgetClass,     paned,
1129 		       XtNlabel,             (XtArgVal)"GAP window",
1130  		       XtNskipAdjust,        (XtArgVal)True,
1131 		       XtNshowGrip,          (XtArgVal)False,
1132 		       (String)NULL );
1133 }
1134 
1135 
FunOpenWindow(TypeArg * arg)1136 static Boolean FunOpenWindow (
1137     TypeArg       * arg )
1138 {
1139     Int             h = arg->iargs[1];
1140     Int             w = arg->iargs[0];
1141     Short           h1;
1142     Short           w1;
1143     String          name = arg->sargs[0];
1144     String          title;
1145     TypeGapWindow * window;
1146     Widget          button;
1147     Widget          paned;
1148 
1149     /* check arguments */
1150     if ( arg->iargs[0] < 1 || arg->iargs[1] < 1 )
1151 	return ANSWER_GAP( "esdsd", "illegal window dimensions ",
1152 			   arg->iargs[0], "x", arg->iargs[1] );
1153     /* give debug info */
1154     DEBUG( D_XCMD, ( "OpenWindow( \"%s\", %ld, %ld )\n", arg->sargs[0],
1155 	   (long)arg->iargs[0], (long)arg->iargs[1] ) );
1156 
1157     /* setup a new window structure, this structure will live forever */
1158     window = (TypeGapWindow*) XtMalloc( sizeof(TypeGapWindow) );
1159     window->line_width = 0;
1160     window->color      = C_BLACK;
1161     window->menus      = List(0);
1162     window->used       = True;
1163     window->text       = 0;
1164 
1165     /* find title position */
1166     XtVaGetValues( GapTalk, XtNtitlePosition, (XtArgVal)&title, (String)NULL );
1167 
1168     /* create a new top level shell */
1169     window->top = XtVaAppCreateShell(
1170 		      "XGap", "GraphicSheet",
1171 		      topLevelShellWidgetClass, GapDisplay,
1172 		      (String)NULL );
1173 
1174     /* create a "paned" for the menu and text window */
1175     paned = XtVaCreateManagedWidget(
1176 	        "xgapWindow", panedWidgetClass, window->top, (String)NULL );
1177 
1178     /* add TOP tile */
1179     if ( *title == 'T' || *title == 't' )
1180 	window->text = CreateTitleWindow(paned);
1181 
1182     /* create a menu box for the menu buttons */
1183     window->box = XtVaCreateManagedWidget(
1184 		      "xgapWindowMenu", boxWidgetClass, paned,
1185  		      XtNskipAdjust,   		(XtArgVal)True,
1186 		      XtNresizeToPreferred, 	(XtArgVal)True,
1187 		      XtNshowGrip,     		(XtArgVal)False,
1188 		      (String)NULL );
1189 
1190     /* create a dummy menu button */
1191     button = XtVaCreateManagedWidget( "dummy", commandWidgetClass,
1192 				      window->box, XtNx, (XtArgVal)0,
1193                                       (String)NULL );
1194 
1195     /* add MIDDLE tile */
1196     if ( *title == 'M' || *title == 'm' )
1197 	window->text = CreateTitleWindow(paned);
1198 
1199     /* create a viewport for the window */
1200     window->viewport = XtVaCreateManagedWidget(
1201 		          "xgapWindowViewport",
1202 			  viewportWidgetClass, paned,
1203 			  XtNallowHoriz,       (XtArgVal)True,
1204 			  XtNallowVert,        (XtArgVal)True,
1205 			  XtNuseBottom,        (XtArgVal)True,
1206 			  XtNshowGrip,         (XtArgVal)False,
1207                           XtNresizable,        (XtArgVal)True,
1208 			  (String)NULL );
1209 
1210     /* create a drawable */
1211     window->draw = XtVaCreateManagedWidget(
1212 	               "xgapWindowDrawable",
1213 		       gapGraphicWidgetClass, window->viewport,
1214                        XtNwidth,              (XtArgVal)w,
1215 	               XtNheight,             (XtArgVal)h,
1216 		       (String)NULL );
1217     window->width  = w;
1218     window->height = h;
1219 
1220     /* fix dimensions of viewport */
1221     XtVaGetValues( window->viewport, XtNwidth, (XtArgVal)&w1,
1222                                      XtNheight, (XtArgVal)&h1,
1223                                      (String)NULL );
1224     w1 = ( w1 < w ) ? w1 : w;
1225     h1 = ( h1 < h ) ? h1 : h;
1226     XtVaSetValues( window->viewport, XtNwidth, (XtArgVal)w1,
1227                                      XtNheight, (XtArgVal)h1, (String)NULL );
1228 
1229     /* add BOTTOM tile */
1230     if ( window->text == 0 )
1231 	window->text = CreateTitleWindow(paned);
1232 
1233     /* realize the window and return the number */
1234     XtRealizeWidget(window->top);
1235 
1236     /* add event handler for mouse clicks */
1237     XtAddEventHandler( window->draw, ButtonPressMask,
1238 		       False, MouseClickWindow,
1239 		       (XtPointer)(LEN(GapWindows)&0xffffL) );
1240 
1241     /* set handler for WM_DELETE_WINDOW */
1242     XSetWMProtocols(GapDisplay,XtWindow(window->top),&WmDeleteWindowAtom,1);
1243     XtOverrideTranslations(
1244 	window->top,
1245         XtParseTranslationTable(WmDeleteWindowTranslation) );
1246 
1247     /* remove dummy button and dummy text */
1248     XtDestroyWidget(button);
1249     XtVaSetValues( window->text, XtNlabel, (XtArgVal)name, (String)NULL );
1250 
1251     /* define cursor */
1252     XDefineCursor( GapDisplay, XtWindow(window->top), SleepCursor );
1253 
1254     /* add window to list and return window number */
1255     AddList( GapWindows, (void*) window );
1256     return ANSWER_GAP( "od", LEN(GapWindows)-1, 0, 0, 0 );
1257 }
1258 
1259 
1260 /****************************************************************************
1261 **
1262 *F  FunCloseWindow( <win> ) . . . . . . . . .  close an open window, external
1263 */
FunCloseWindow(TypeArg * arg)1264 static Boolean FunCloseWindow (
1265     TypeArg   * arg )
1266 {
1267     /* give debug info */
1268     DEBUG( D_XCMD, ( "CloseWindow( #%ld )\n", (long)arg->iargs[0] ) );
1269 
1270     /* close window */
1271     CloseWindow(arg->win);
1272 
1273     /* return OK */
1274     return AnswerGap( "o", 0, 0, 0, 0 );
1275 }
1276 
1277 /****************************************************************************
1278 **
1279 *F  FunAddTitle( <win>, <str> ) . . . . . . . . . . . . . . add a (sub) title
1280 */
FunAddTitle(TypeArg * arg)1281 static Boolean FunAddTitle (
1282     TypeArg   * arg )
1283 {
1284     XtVaSetValues( arg->win->text, XtNlabel, (XtArgVal)(arg->sargs[0]),
1285                    (String)NULL );
1286     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1287 }
1288 
1289 
1290 /****************************************************************************
1291 **
1292 *F  FunColorModel() . . . . . . . color model used for gap graphics, external
1293 */
FunColorModel(TypeArg * arg)1294 static Boolean FunColorModel (
1295     TypeArg   * arg )
1296 {
1297     return ANSWER_GAP( "od", GCColorModel(GapDisplay), 0, 0, 0 );
1298 }
1299 
1300 
1301 /****************************************************************************
1302 **
1303 *F  FunFastUpdate( <win>, <flag> )  . . . . . . . . . en-/disable fast update
1304 */
FunFastUpdate(TypeArg * arg)1305 static Boolean FunFastUpdate (
1306     TypeArg *	arg )
1307 {
1308     Boolean	flag;
1309 
1310     flag = ( arg->iargs[1] == 0 ) ? False : True;
1311     if ( arg->win->fast_update != flag )
1312     {
1313 	arg->win->fast_update = flag;
1314 	GGFastUpdate( arg->win->draw, flag );
1315     }
1316     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1317 }
1318 
1319 
1320 
1321 /****************************************************************************
1322 **
1323 *F  FunFontInfo( <win>, <fid> ) . . . . . . . . . .   information about fonts
1324 */
FunFontInfo(TypeArg * arg)1325 static Boolean FunFontInfo (
1326     TypeArg	* arg )
1327 {
1328     XFontStruct * font = arg->font;
1329 
1330     return ANSWER_GAP( "oddd", font->ascent, font->descent,
1331 		               font->max_bounds.width, 0 );
1332 }
1333 
1334 
1335 /****************************************************************************
1336 **
1337 *F  FunQueryPointer( <win> )  . . . . . . . . . . . . . . . . . query pointer
1338 */
FunQueryPointer(TypeArg * arg)1339 static Boolean FunQueryPointer (
1340     TypeArg       * arg )
1341 {
1342     Int        	    x,  y,  x2,  y2;
1343     UInt            bt;
1344     UInt            md;
1345     UInt            pt;
1346     Window          child;
1347     Window          root;
1348 
1349     /* query pointer */
1350     XQueryPointer( XtDisplay(arg->win->draw), XtWindow(arg->win->draw),
1351     	    	   &root, &child, &x, &y, &x2, &y2, &pt );
1352 
1353     /* and make a sanity check */
1354     if ( arg->win->width < x2 || x2 < 0 )
1355 	x2 = -1;
1356     if ( arg->win->height < y2 || y2 < 0 )
1357 	y2 = -1;
1358 
1359     /* check mouse buttons */
1360     bt = 0;
1361     if ( pt & Button1Mask )
1362 	bt |= 1;
1363     if ( pt & Button3Mask )
1364 	bt |= 2;
1365 
1366     /* check modifier keys */
1367     md = 0;
1368     if ( pt & ShiftMask )
1369 	md |= 1;
1370     if ( pt & ControlMask )
1371 	md |= 2;
1372     if ( pt & Mod1Mask )
1373 	md |= 4;
1374 
1375     /* gap will be answered by 'PopingDown' */
1376     return ANSWER_GAP( "odddd", x2, y2, bt, md );
1377 }
1378 
1379 
1380 /****************************************************************************
1381 **
1382 *F  FunResize( <win>, <width>, <height> ) . . . . . . . . . . . resize window
1383 */
FunResize(TypeArg * arg)1384 static Boolean FunResize (
1385     TypeArg * 		arg )
1386 {
1387     ViewportWidget	viewport = (ViewportWidget)arg->win->viewport;
1388     Widget              dummy;
1389 
1390     /* check arguments */
1391     if ( arg->iargs[1] < 1 || arg->iargs[2] < 1 )
1392 	return ANSWER_GAP( "esdsd", "illegal window dimensions ",
1393 			   arg->iargs[1], "x", arg->iargs[2] );
1394 
1395     /* resize window */
1396     arg->win->width  = arg->iargs[1];
1397     arg->win->height = arg->iargs[2];
1398     GGResize( arg->win->draw, arg->iargs[1], arg->iargs[2] );
1399 
1400     /* try to update scrollbars */
1401     XtUnmanageChild(arg->win->draw);
1402     dummy = XtVaCreateManagedWidget(
1403 	               "xgapWindowDrawable",
1404 		       gapGraphicWidgetClass, (Widget)viewport,
1405                        XtNwidth,              (XtArgVal)(arg->win->width),
1406 	               XtNheight,             (XtArgVal)(arg->win->height),
1407 		       (String)NULL );
1408     XtUnmanageChild(dummy);
1409     XtManageChild(arg->win->draw);
1410     XtDestroyWidget(dummy);
1411 
1412     /* and return */
1413     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1414 }
1415 
1416 
1417 /****************************************************************************
1418 **
1419 
1420 *F  * * * * * * * * * * * * * functions for Menus * * * * * * * * * * * * * *
1421 */
1422 
1423 
1424 /****************************************************************************
1425 **
1426 
1427 *F  FunMenu( <win>, <name>, <str> ) . . . . . . . . . . . create a menu entry
1428 */
MenuClick(Widget w,XtPointer cl,XtPointer ca)1429 static void MenuClick (
1430     Widget	    w,
1431     XtPointer       cl,
1432     XtPointer       ca )
1433 {
1434     TypeMenuData  * pd = (TypeMenuData*) cl;
1435     char            buf[128];
1436 
1437     DEBUG( D_XCMD, ("MenuSelected( #%ld, #%ld, #%ld )\n", (long)pd->window,
1438 	   (long)pd->popup, (long)pd->pane) );
1439     sprintf( buf, "MenuSelected( %ld, %ld, %ld );\n", (long)pd->window,
1440 	     (long)pd->popup, (long)pd->pane );
1441     SimulateInput(buf);
1442 }
1443 
FunMenu(TypeArg * arg)1444 static Boolean FunMenu (
1445     TypeArg       * arg )
1446 {
1447     Int             i;
1448     String          ptr;
1449     String          qtr;
1450     TypeMenu      * menu;
1451     TypeMenuData  * pd;
1452     Widget          button;
1453     Widget          pane;
1454     Widget          pshell;
1455     char	    buf[128];
1456 
1457     /* create a menu button */
1458     DEBUG( D_XCMD, ( "Menu( \"%s\", ... )\n", arg->sargs[0] ) );
1459     button = XtVaCreateManagedWidget( "menuButton", menuButtonWidgetClass,
1460 				      arg->win->box,
1461 				      XtNlabel,      (XtArgVal)(arg->sargs[0]),
1462 				      XtNshapeStyle, (XtArgVal)XmuShapeOval,
1463 				      XtNleftBitmap, (XtArgVal)MenuSymbol,
1464 				      (String)NULL );
1465 
1466     /* create a shell */
1467     pshell = XtVaCreatePopupShell( "menu", simpleMenuWidgetClass,
1468     	    	    	    	   button, XtNcursor, (XtArgVal)CursorTL,
1469                                    (String)NULL );
1470 
1471     /* create menu entries */
1472     menu = (TypeMenu*) XtMalloc( sizeof(TypeMenu) );
1473     menu->button  = button;
1474     menu->shell   = pshell;
1475     menu->entries = List(0);
1476     for ( ptr = arg->sargs[1], i = 1;  *ptr; )
1477     {
1478     	qtr = buf;
1479     	while ( *ptr && *ptr != '|' )
1480     	    *qtr++ = *ptr++;
1481     	*qtr = 0;
1482     	if ( *ptr )  ptr++;
1483     	DEBUG( D_XCMD, ( "  entry = \"%s\"\n", buf ) );
1484 	if ( *buf == '-' )
1485 	    XtVaCreateManagedWidget( "line", smeLineObjectClass, pshell,
1486                                      (String)NULL );
1487 	else
1488 	{
1489 	    pane = XtVaCreateManagedWidget( buf, smeBSBObjectClass,
1490     	    	    	    	    	    pshell,
1491 					    XtNlabel,       (XtArgVal)buf,
1492 					    XtNrightMargin, (XtArgVal)14,
1493                                             XtNrightBitmap,
1494                                                     (XtArgVal)EmptyMarkSymbol,
1495 	                                    (String)NULL );
1496 	    pd = (TypeMenuData*) XtMalloc( sizeof(TypeMenuData) );
1497 	    pd->window = arg->iargs[0];
1498 	    pd->pane   = i;
1499 	    pd->popup  = LEN(arg->win->menus);
1500 	    pd->shell  = pane;
1501 	    XtAddCallback( pane, XtNcallback, MenuClick, pd );
1502 	    i++;
1503 	    AddList( menu->entries, (void*) pd );
1504 	}
1505     }
1506 
1507     /* add shell to popup shell list */
1508     AddList( arg->win->menus, (void*) menu );
1509     return ANSWER_GAP( "od", LEN(arg->win->menus)-1, 0, 0, 0 );
1510 }
1511 
1512 
1513 /****************************************************************************
1514 **
1515 *F  FunDeleteMenu( <win>, <menu> )  . . . . . . . . . . . . . . delete a menu
1516 */
FunDeleteMenu(TypeArg * arg)1517 static Boolean FunDeleteMenu (
1518     TypeArg   * arg )
1519 {
1520     TypeMenu  * menu;
1521     Int         j;
1522 
1523     /* check menu number */
1524     DEBUG( D_XCMD, ( "CheckMenuEntry( #%ld, #%ld, #%ld, %ld )\n",
1525 	   (long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2],
1526 	   (long)arg->iargs[3] ) );
1527     if ( LEN(arg->win->menus) <= arg->iargs[1] || arg->iargs[1] < 0 )
1528 	return ANSWER_GAP("esd","illegal menu number ",arg->iargs[1],0,0);
1529     menu = (TypeMenu*)ELM(arg->win->menus,arg->iargs[1]);
1530     if ( menu == 0 )
1531 	return ANSWER_GAP( "esds", "menu ", arg->iargs[1],
1532  			   " is no longer used", 0 );
1533 
1534     /* delete this entry */
1535     ELM( arg->win->menus, arg->iargs[1] ) = 0;
1536     for ( j = 0;  j < LEN(menu->entries);  j++ )
1537 	XtFree((char*)ELM(menu->entries,j));
1538     XtFree((char*)menu->entries->ptr);
1539     XtFree((char*)menu->entries);
1540     XtDestroyWidget(menu->button);
1541     XtFree((char*)menu);
1542     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1543 }
1544 
1545 
1546 /****************************************************************************
1547 **
1548 *F  FunCheckMenuEntry( <win>, <menu>, <entry>, <check> )  . .  add check mark
1549 */
FunCheckMenuEntry(TypeArg * arg)1550 static Boolean FunCheckMenuEntry (
1551     TypeArg   * arg )
1552 {
1553     TypeMenu  * menu;
1554     Widget      entry;
1555 
1556     /* check menu number */
1557     DEBUG( D_XCMD, ( "CheckMenuEntry( #%ld, #%ld, #%ld, %ld )\n",
1558 	   (long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2],
1559 	   (long)arg->iargs[3] ) );
1560     if ( LEN(arg->win->menus) <= arg->iargs[1] || arg->iargs[1] < 0 )
1561 	return ANSWER_GAP("esd","illegal menu number ",arg->iargs[1],0,0);
1562     menu = (TypeMenu*)ELM(arg->win->menus,arg->iargs[1]);
1563     if ( menu == 0 )
1564 	return ANSWER_GAP( "esds", "menu ", arg->iargs[1],
1565 			   " is no longer used", 0 );
1566 
1567     /* check menu entry number */
1568     if ( LEN(menu->entries) < arg->iargs[2] || arg->iargs[2] <= 0 )
1569 	return ANSWER_GAP("esd","illegal menu entry ",arg->iargs[2],0,0);
1570     entry = ((TypeMenuData*)ELM(menu->entries,arg->iargs[2]-1))->shell;
1571 
1572     /* set or clear check mark */
1573     if ( arg->iargs[3] )
1574 	XtVaSetValues( entry, XtNrightBitmap, (XtArgVal)CheckMarkSymbol,
1575                        (String)NULL );
1576     else
1577 	XtVaSetValues( entry, XtNrightBitmap, (XtArgVal)EmptyMarkSymbol,
1578                        (String)NULL );
1579     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1580 }
1581 
1582 
1583 /****************************************************************************
1584 **
1585 *F  FunEnableMenuEntry( <win>, <menu>, <entry>, <check> ) . .  enable/disable
1586 */
FunEnableMenuEntry(TypeArg * arg)1587 static Boolean FunEnableMenuEntry (
1588     TypeArg   * arg )
1589 {
1590     TypeMenu  * menu;
1591     Widget      entry;
1592 
1593     /* check menu number */
1594     DEBUG( D_XCMD, ( "EnableMenuEntry( #%ld, #%ld, #%ld, %ld )\n",
1595 	   (long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2],
1596 	   (long)arg->iargs[3] ) );
1597     if ( LEN(arg->win->menus) <= arg->iargs[1] || arg->iargs[1] < 0 )
1598 	return ANSWER_GAP("esd","illegal menu number ",arg->iargs[1],0,0);
1599     menu = (TypeMenu*)ELM(arg->win->menus,arg->iargs[1]);
1600     if ( menu == 0 )
1601 	return ANSWER_GAP( "esds", "menu ", arg->iargs[1],
1602 			   " is no longer used", 0 );
1603 
1604     /* check menu entry number */
1605     if ( LEN(menu->entries) < arg->iargs[2] || arg->iargs[2] <= 0 )
1606 	return ANSWER_GAP("esd","illegal menu entry ",arg->iargs[2],0,0);
1607     entry = ((TypeMenuData*)ELM(menu->entries,arg->iargs[2]-1))->shell;
1608 
1609     /* set or clear check mark */
1610     if ( arg->iargs[3] )
1611 	XtVaSetValues( entry, XtNsensitive, (XtArgVal)True, (String)NULL );
1612     else
1613 	XtVaSetValues( entry, XtNsensitive, (XtArgVal)False, (String)NULL );
1614     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1615 }
1616 
1617 
1618 /****************************************************************************
1619 **
1620 
1621 *F  * * * * * * * * * * * functions for GraphicObjects  * * * * * * * * * * *
1622 */
1623 
1624 
1625 /****************************************************************************
1626 **
1627 
1628 *D  CHECK_BBOX( <obj> )	. . . . . . . . . .  check dimensions of bounding box
1629 */
1630 #define	CHECK_BBOX(obj)	obj->x = ( obj->x < 0 ) ? 0 : obj-> x; \
1631                         obj->y = ( obj->y < 0 ) ? 0 : obj-> y
1632 
1633 
1634 /****************************************************************************
1635 **
1636 *F  FunClearAll( <win> )  . . . . . . . . . . . . . . . . . clear all objects
1637 */
FunClearAll(TypeArg * arg)1638 static Boolean FunClearAll (
1639     TypeArg   * arg )
1640 {
1641     GGFreeAllObjects( arg->win->draw );
1642     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1643 }
1644 
1645 
1646 /****************************************************************************
1647 **
1648 *F  FunRemoveObjects( <win>, <obj>, ... )   . . . . .  remove a window object
1649 */
FunRemoveObjects(TypeArg * arg)1650 static Boolean FunRemoveObjects (
1651     TypeArg     * arg )
1652 {
1653     String	  str;
1654     Int           n;
1655 
1656     /* return if no optional args are given */
1657     if ( (str=arg->opts) == 0 )
1658 	return ANSWER_GAP( "es", "no objects given", 0, 0, 0 );
1659 
1660     /* give debug info */
1661     DEBUG( D_XCMD, ("RemoveObject( #%ld, %s )\n",(long)arg->iargs[0],str) );
1662 
1663     /* remove objects */
1664     if ( !arg->win->fast_update )
1665 	GGStartRemove(arg->win->draw);
1666     while ( *str )
1667     {
1668 	if ( !ParseInt( &str, &n ) )
1669 	{
1670 	    if ( !arg->win->fast_update )
1671 		GGStopRemove(arg->win->draw);
1672 	    return ANSWER_GAP( "es", "illegal argument", 0, 0, 0 );
1673 	}
1674 	if ( GGRemoveObject( arg->win->draw, n ) )
1675 	{
1676 	    if ( !arg->win->fast_update )
1677 		GGStopRemove(arg->win->draw);
1678 	    return ANSWER_GAP("esds","illegal object number: '",n,"'",0);
1679 	}
1680     }
1681     if ( !arg->win->fast_update )
1682 	GGStopRemove(arg->win->draw);
1683     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1684 }
1685 
1686 
1687 /****************************************************************************
1688 **
1689 *F  FunSetLineWidth( <win>, <wdt> ) . . . . . set line width for next objects
1690 */
FunSetLineWidth(TypeArg * arg)1691 static Boolean FunSetLineWidth (
1692     TypeArg   * arg )
1693 {
1694     arg->win->line_width = ( arg->iargs[1] <= 1 ) ? 0 : arg->iargs[1];
1695     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1696 }
1697 
1698 
1699 /****************************************************************************
1700 **
1701 *F  FunSetColor( <win>, <col> ) . . . . . . . . .  set color for next objects
1702 */
FunSetColor(TypeArg * arg)1703 static Boolean FunSetColor (
1704     TypeArg   * arg )
1705 {
1706     if ( arg->iargs[1] < 0 )
1707 	arg->win->color = C_BLACK;
1708     else if ( C_LAST < arg->iargs[1] )
1709 	arg->win->color = C_BLACK;
1710     else
1711 	arg->win->color = arg->iargs[1];
1712     return ANSWER_GAP( "o", 0, 0, 0, 0 );
1713 }
1714 
1715 
1716 /****************************************************************************
1717 **
1718 *F  FunDrawBox( <win>, <x1>, <y1>, <x2>, <y2> ) . . . draw a filled rectangle
1719 */
FunDrawBox(TypeArg * arg)1720 static Boolean FunDrawBox (
1721     TypeArg               * arg )
1722 {
1723     TypeGapGraphicObject  * obj;
1724     Int	                    n;
1725 
1726     /* create a line object */
1727     obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );
1728 
1729     /* convert <x> and <y> coordinates to X windows style */
1730     obj->type  = T_BOX;
1731     obj->color = arg->win->color;
1732     obj->desc.rect.x1 = MIN( arg->iargs[1], arg->iargs[3] );
1733     obj->desc.rect.y1 = MIN( arg->iargs[2], arg->iargs[4] );
1734     obj->desc.rect.x2 = MAX( arg->iargs[1], arg->iargs[3] );
1735     obj->desc.rect.y2 = MAX( arg->iargs[2], arg->iargs[4] );
1736     obj->x = MIN( obj->desc.rect.x1, obj->desc.rect.x2 )-1;
1737     obj->y = MIN( obj->desc.rect.y1, obj->desc.rect.y2 )-1;
1738     obj->w = MAX( obj->desc.rect.x1, obj->desc.rect.x2 )+1;
1739     obj->h = MAX( obj->desc.rect.y1, obj->desc.rect.y2 )+1;
1740     CHECK_BBOX(obj);
1741     DEBUG( D_XCMD, ( "DrawBox( #%ld, %ld, %ld, %ld )\n",
1742 	   (long)arg->iargs[0], (long)arg->iargs[1],
1743 	   (long)arg->iargs[2], (long)arg->iargs[3] ) );
1744 
1745     /* use 'GGAddObject' to draw the object */
1746     n = GGAddObject( arg->win->draw, obj );
1747     return ANSWER_GAP( "od", n, 0, 0, 0 );
1748 }
1749 
1750 
1751 /****************************************************************************
1752 **
1753 *F  FunDrawCircle( <win>, <x>, <y>, <r> ) . . . . . . . . . . . draw a circle
1754 */
FunDrawCircle(TypeArg * arg)1755 static Boolean FunDrawCircle (
1756     TypeArg               * arg )
1757 {
1758     TypeGapGraphicObject  * obj;
1759     Int 	            n;
1760     Int                     w;
1761 
1762     /* create a circle object */
1763     obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );
1764 
1765     /* convert <x> and <y> coordinates to X windows style */
1766     obj->type  = T_CIRCLE;
1767     obj->color = arg->win->color;
1768     obj->desc.circle.r = 2 * arg->iargs[3];
1769     obj->desc.circle.x = arg->iargs[1] - arg->iargs[3];
1770     obj->desc.circle.y = arg->iargs[2] - arg->iargs[3];
1771     w = obj->desc.circle.w  = arg->win->line_width;
1772     obj->x = obj->desc.circle.x - w - 1;
1773     obj->y = obj->desc.circle.y - w - 1;
1774     obj->w = obj->desc.circle.r+1 + 2*w + 2;
1775     obj->h = obj->desc.circle.r+1 + 2*w + 2;
1776     CHECK_BBOX(obj);
1777     DEBUG( D_XCMD, ( "DrawCircle( #%ld, %ld, %ld, %ld )\n",
1778 	   (long)arg->iargs[0], (long)arg->iargs[1],
1779 	   (long)arg->iargs[2], (long)arg->iargs[3] ) );
1780 
1781     /* use 'GGAddObject' to draw the object */
1782     n = GGAddObject( arg->win->draw, obj );
1783     return ANSWER_GAP( "od", n, 0, 0, 0 );
1784 }
1785 
1786 
1787 /****************************************************************************
1788 **
1789 *F  FunDrawDisc( <win>, <x>, <y>, <r> ) . . . . . . . . . . draw a solid disc
1790 */
FunDrawDisc(TypeArg * arg)1791 static Boolean FunDrawDisc (
1792     TypeArg               * arg )
1793 {
1794     TypeGapGraphicObject  * obj;
1795     Int 	            n;
1796 
1797     /* create a disc object */
1798     obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );
1799 
1800     /* convert <x> and <y> coordinates to X windows style */
1801     obj->type  = T_DISC;
1802     obj->color = arg->win->color;
1803     obj->desc.disc.r = 2 * arg->iargs[3];
1804     obj->desc.disc.x = arg->iargs[1] - arg->iargs[3];
1805     obj->desc.disc.y = arg->iargs[2] - arg->iargs[3];
1806     obj->x = obj->desc.disc.x;
1807     obj->y = obj->desc.disc.y;
1808     obj->w = obj->desc.disc.r+1;
1809     obj->h = obj->desc.disc.r+1;
1810     CHECK_BBOX(obj);
1811     DEBUG( D_XCMD, ( "DrawCircle( #%ld, %ld, %ld, %ld )\n",
1812 	   (long)arg->iargs[0], (long)arg->iargs[1],
1813 	   (long)arg->iargs[2], (long)arg->iargs[3] ) );
1814 
1815     /* use 'GGAddObject' to draw the object */
1816     n = GGAddObject( arg->win->draw, obj );
1817     return ANSWER_GAP( "od", n, 0, 0, 0 );
1818 }
1819 
1820 
1821 /****************************************************************************
1822 **
1823 *F  FunDrawLine( <win>, <x1>, <y1>, <x2>, <y2> )  . . . . . . . . draw a line
1824 */
FunDrawLine(TypeArg * arg)1825 static Boolean FunDrawLine (
1826     TypeArg               * arg )
1827 {
1828     TypeGapGraphicObject  * obj;
1829     Int 	            n;
1830     Int                     w;
1831 
1832     /* create a line object */
1833     obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );
1834     obj->type  = T_LINE;
1835     obj->color = arg->win->color;
1836     obj->desc.line.x1 = arg->iargs[1];
1837     obj->desc.line.y1 = arg->iargs[2];
1838     obj->desc.line.x2 = arg->iargs[3];
1839     obj->desc.line.y2 = arg->iargs[4];
1840     w = obj->desc.line.w  = arg->win->line_width;
1841     obj->x = MIN( obj->desc.line.x1, obj->desc.line.x2 ) - w;
1842     obj->y = MIN( obj->desc.line.y1, obj->desc.line.y2 ) - w;
1843     obj->w = MAX( obj->desc.line.x1, obj->desc.line.x2 ) - obj->x + 1 + 2*w;
1844     obj->h = MAX( obj->desc.line.y1, obj->desc.line.y2 ) - obj->y + 1 + 2*w;
1845     CHECK_BBOX(obj);
1846     DEBUG( D_XCMD, ( "DrawLine( #%ld, %ld, %ld, %ld, %ld )\n",
1847 	   (long)arg->iargs[0], (long)obj->desc.line.x1,
1848 	   (long)obj->desc.line.y1, (long)obj->desc.line.x2,
1849 	   (long)obj->desc.line.y2 ) );
1850 
1851     /* use 'GGAddObject' to draw the object */
1852     n = GGAddObject( arg->win->draw, obj );
1853     return ANSWER_GAP( "od", n, 0, 0, 0 );
1854 }
1855 
1856 
1857 
1858 /****************************************************************************
1859 **
1860 *F  FunDrawRectangle( <win>, <x1>, <y1>, <x2>, <y2> ) . . .  draw a rectangle
1861 */
FunDrawRectangle(TypeArg * arg)1862 static Boolean FunDrawRectangle (
1863     TypeArg               * arg )
1864 {
1865     TypeGapGraphicObject  * obj;
1866     Int 	            n;
1867     Int                     w;
1868 
1869     /* create a line object */
1870     obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );
1871 
1872     /* convert <x> and <y> coordinates to X windows style */
1873     obj->type  = T_RECT;
1874     obj->color = arg->win->color;
1875     obj->desc.rect.x1 = MIN( arg->iargs[1], arg->iargs[3] );
1876     obj->desc.rect.y1 = MIN( arg->iargs[2], arg->iargs[4] );
1877     obj->desc.rect.x2 = MAX( arg->iargs[1], arg->iargs[3] );
1878     obj->desc.rect.y2 = MAX( arg->iargs[2], arg->iargs[4] );
1879     w = obj->desc.rect.w  = arg->win->line_width;
1880     obj->x = MIN( obj->desc.rect.x1, obj->desc.rect.x2 ) - w;
1881     obj->y = MIN( obj->desc.rect.y1, obj->desc.rect.y2 ) - w;
1882     obj->w = MAX( obj->desc.rect.x1, obj->desc.rect.x2 ) - obj->x + 1 + 2*w;
1883     obj->h = MAX( obj->desc.rect.y1, obj->desc.rect.y2 ) - obj->y + 1 + 2*w;
1884     CHECK_BBOX(obj);
1885     DEBUG( D_XCMD, ( "DrawRectangle( #%ld, %ld, %ld, %ld )\n",
1886 	   (long)arg->iargs[0], (long)arg->iargs[1],
1887 	   (long)arg->iargs[2], (long)arg->iargs[3] ) );
1888 
1889     /* use 'GGAddObject' to draw the object */
1890     n = GGAddObject( arg->win->draw, obj );
1891     return ANSWER_GAP( "od", n, 0, 0, 0 );
1892 }
1893 
1894 
1895 /****************************************************************************
1896 **
1897 *F  FunDrawText( <win>, <fid>, <x>, <y>, <str> )  . . . . . . draw text <str>
1898 */
FunDrawText(TypeArg * arg)1899 static Boolean FunDrawText (
1900     TypeArg               * arg )
1901 {
1902     TypeGapGraphicObject  * obj;
1903     XFontStruct           * font = arg->font;
1904     Int  	            n;
1905 
1906     /* create a TEXT object */
1907     obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );
1908 
1909     /* convert <x> and <y> coordinates to X windows style */
1910     obj->type  = T_TEXT;
1911     obj->color = arg->win->color;
1912     obj->desc.text.x    = arg->iargs[2];
1913     obj->desc.text.y    = arg->iargs[3];
1914     obj->desc.text.font = font->fid;
1915     obj->desc.text.len  = strlen(arg->sargs[0]);
1916     obj->desc.text.str  = XtMalloc(obj->desc.text.len+1);
1917     strcpy( obj->desc.text.str, arg->sargs[0] );
1918     obj->x = arg->iargs[2] - 1;
1919     obj->y = arg->iargs[3] - font->ascent - 1;
1920     obj->w = obj->desc.text.len*font->max_bounds.width + 2;
1921     obj->h = font->descent + font->ascent + 2;
1922     CHECK_BBOX(obj);
1923     DEBUG( D_XCMD, ( "DrawText( #%ld, %ld, %ld, %s )\n",
1924 	   (long)arg->iargs[0], (long)arg->iargs[1],
1925 	   (long)arg->iargs[2], arg->sargs[0] ) );
1926 
1927     /* use 'GGAddObject' to draw the object */
1928     n = GGAddObject( arg->win->draw, obj );
1929     return ANSWER_GAP( "od", n, 0, 0, 0 );
1930 }
1931 
1932 
1933 /****************************************************************************
1934 **
1935 
1936 *F  FunPlaybackFile( <filename> ) . . . . . . . . .  playback file <filename>
1937 */
FunPlaybackFile(TypeArg * arg)1938 static Boolean FunPlaybackFile (
1939     TypeArg               * arg )
1940 {
1941     return PlaybackFile(arg->sargs[0]) ?
1942         ANSWER_GAP( "o", 0, 0, 0, 0 )
1943       : ANSWER_GAP( "es", "cannot open file", 0, 0, 0 );
1944 }
1945 
1946 
1947 /****************************************************************************
1948 **
1949 *F  FunResumePlayback() . . . . . . . . . . . . . . . resume playback of file
1950 */
FunResumePlayback(TypeArg * arg)1951 static Boolean FunResumePlayback (
1952     TypeArg               * arg )
1953 {
1954     return ResumePlayback() ?
1955         ANSWER_GAP( "o", 0, 0, 0, 0 )
1956       : ANSWER_GAP( "es", "no playback in progress", 0, 0, 0 );
1957 }
1958 
1959 
1960 /****************************************************************************
1961 **
1962 
1963 *F  * * * * * * * * * *  interface to the main program  * * * * * * * * * * *
1964 */
1965 
1966 
1967 /****************************************************************************
1968 **
1969 
1970 *V  WindowCommands[]  . . . . . . . . . .  . . . . .  list of window commands
1971 */
1972 TypeWindowCommand WindowCommands[] =
1973 {
1974     { "XAT",    "#S",       FunAddTitle             },
1975     { "XCA",    "#",        FunClearAll             },
1976     { "XCL",    "TS",       FunChangeList           },
1977     { "XCM",    "#III",     FunCheckMenuEntry 	    },
1978     { "XCN",    "",         FunColorModel           },
1979     { "XCO",    "#I",       FunSetColor             },
1980     { "XCS",    "T",        FunCloseSelector        },
1981     { "XCW",    "#",        FunCloseWindow          },
1982     { "XDB",    "#IIII",    FunDrawBox              },
1983     { "XDC",    "#III",     FunDrawCircle           },
1984     { "XDD",    "#III",     FunDrawDisc             },
1985     { "XDL",    "#IIII",    FunDrawLine             },
1986     { "XDM",    "#I",       FunDeleteMenu           },
1987     { "XDR",    "#IIII",    FunDrawRectangle        },
1988     { "XDT",    "#FIIS",    FunDrawText             },
1989     { "XEB",    "TII",      FunEnableButton         },
1990     { "XEM",    "#III",     FunEnableMenuEntry 	    },
1991     { "XFI",    "F",        FunFontInfo             },
1992     { "XFU",    "#I",       FunFastUpdate           },
1993     { "XLW",    "#I",       FunSetLineWidth         },
1994     { "XME",    "#SS",      FunMenu                 },
1995     { "XOS",    "SSS",      FunOpenSelector         },
1996     { "XOW",  	"SII",      FunOpenWindow           },
1997     { "XPF",    "S",        FunPlaybackFile         },
1998     { "XPS",    "SS" ,      FunPopupShell           },
1999     { "XQP",    "#",        FunQueryPointer         },
2000     { "XRE",    "#II",      FunResize               },
2001     { "XRP",    "",         FunResumePlayback       },
2002     { "XRO",    "#*",       FunRemoveObjects        },
2003     { "XSD",    "ISS",      FunShowDialog           },
2004     { "XSP",    "I",        FunShowPopup            },
2005     { "XUS",    "T",        FunUnhighlihtSelector   },
2006     { 0L,       0L,         0L              	    }
2007 };
2008 
2009 
2010 /****************************************************************************
2011 **
2012 *V  PrivateActions  . . . . . . . . . . . . . . . . . . . .  action functions
2013 */
2014 static XtActionsRec PrivateActions[] =
2015 {
2016     { "NotifyClick",  	NotifyClick    },
2017     { "WmDeleteWindow", WmDeleteWindow }
2018 };
2019 
2020 
2021 /****************************************************************************
2022 **
2023 *F  InitXCMDS()	. . . . . . . . . . . . . . .  initalize all global variables
2024 */
InitXCMDS()2025 void InitXCMDS ()
2026 {
2027 
2028     /* get the fonts form the database for <GapTalk> */
2029     XtVaGetValues( GapTalk,
2030 		   XtNtinyFont,     (XtArgVal)&TinyFont,
2031 		   XtNsmallFont,    (XtArgVal)&SmallFont,
2032 		   XtNnormalFont,   (XtArgVal)&NormalFont,
2033 		   XtNlargeFont,    (XtArgVal)&LargeFont,
2034                    XtNhugeFont,     (XtArgVal)&HugeFont,
2035 		   (String)NULL );
2036 
2037     /* create lists for windows, popups, and selectors */
2038     GapWindows    = List(0);
2039     PopupMenus    = List(0);
2040     TextSelectors = List(0);
2041 
2042     /* create cursors */
2043     SleepCursor = XCreateFontCursor( GapDisplay, XC_watch );
2044     RunCursor   = XCreateFontCursor( GapDisplay, XC_top_left_arrow );
2045 
2046     /* create popup dialogs */
2047     DialogOkCancel = CreatePopupDialog( AppContext, XGap, "OkCancelDialog",
2048 				        PD_OK | PD_CANCEL, PD_OK, 0 );
2049 
2050     /* register private actions */
2051     XtAppAddActions( AppContext, PrivateActions, XtNumber(PrivateActions) );
2052 }
2053 
2054 
2055 /****************************************************************************
2056 **
2057 *F  UpdateXCMDS( <state> )  . . . . . . . . . .  gap is/isn't accepting input
2058 */
UpdateXCMDS(state)2059 void UpdateXCMDS ( state )
2060     Boolean             state;
2061 {
2062     TypeGapWindow *	win;
2063     Int                 i;
2064 
2065     /* GAP accepts input */
2066     if ( state )
2067     {
2068 	for ( i = 0;  i < LEN(GapWindows);  i++ )
2069 	{
2070 	    win = ELM( GapWindows, i );
2071 	    if ( win && win->used == True )
2072 		XDefineCursor( GapDisplay, XtWindow(win->top), RunCursor );
2073 	}
2074     }
2075 
2076     /* GAP doesn't accept input */
2077     else
2078     {
2079 	for ( i = 0;  i < LEN(GapWindows);  i++ )
2080 	{
2081 	    win = ELM( GapWindows, i );
2082 	    if ( win && win->used == True )
2083 		XDefineCursor( GapDisplay, XtWindow(win->top), SleepCursor );
2084 	}
2085     }
2086 }
2087 
2088 
2089 /****************************************************************************
2090 **
2091 *F  ExitXCMDS()	. . . . . . . . . . . . . . . . .  clear all global variables
2092 */
ExitXCMDS()2093 void ExitXCMDS ()
2094 {
2095     TypeArg         arg;
2096     TypeMenu      * menu;
2097     Int             i;
2098     Int             j;
2099 
2100     /* clear list of windows and popups */
2101     for ( i = 0;  i < LEN(GapWindows);  i++ )
2102     {
2103 	arg.win = ELM(GapWindows,i);
2104 	if ( arg.win->used )
2105 	    FunCloseWindow(&arg);
2106 	XtFree((char*)ELM(GapWindows,i));
2107     }
2108     XtFree((char*)GapWindows);
2109     for ( i = 0;  i < LEN(TextSelectors);  i++ )
2110     {
2111 	arg.sel = ELM(TextSelectors,i);
2112 	if ( arg.sel != 0 )
2113 	{
2114 	    FunCloseSelector(&arg);
2115 	    XtFree((char*)ELM(TextSelectors,i));
2116 	}
2117     }
2118     XtFree((char*)TextSelectors);
2119     for (i = 0;  i < LEN(PopupMenus);  i++ )
2120 	if ( (menu = ELM(PopupMenus,i)) != 0 )
2121 	{
2122 	    for ( j = 0;  j < LEN(menu->entries);  j++ )
2123 		XtFree((char*)ELM(menu->entries,j));
2124 	    XtFree((char*)menu->entries);
2125 	    XtFree((char*)menu);
2126 	}
2127     XtFree((char*)PopupMenus);
2128 }
2129 
2130 
2131 /****************************************************************************
2132 **
2133 
2134 *E  xcmds.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
2135 */
2136