1 /* $TOG: main.c /main/6 1997/03/31 13:47:48 dbl $ */
2 /*
3  * Motif
4  *
5  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
6  *
7  * These libraries and programs are free software; you can
8  * redistribute them and/or modify them under the terms of the GNU
9  * Lesser General Public License as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * These libraries and programs are distributed in the hope that
14  * they will be useful, but WITHOUT ANY WARRANTY; without even the
15  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  * PURPOSE. See the GNU Lesser General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with these librararies and programs; if not, write
21  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
22  * Floor, Boston, MA 02110-1301 USA
23  */
24 /*
25  * HISTORY
26  */
27 
28 /*
29  * The Airport Drag And Drop Demo
30  */
31 
32 #include "main.h"
33 
34 /* ============================ local constants ======================= */
35 
36 #define MAX_ARGS 8
37 
38 /* ============================ prototypes  ======================= */
39 
40 static Widget MenuBarEntry(Widget menubar, String entry, String labels[],
41 		XtCallbackProc procs[], XtPointer private[], int count);
42 
43 static void HelpCallback(Widget button, Airport this, XtPointer cbs);
44 
45 static void ExitCallback(Widget	button, Airport this, XtPointer cbs);
46 
47 static void ResizeAirport(Widget area, Airport this, XtPointer cbs);
48 /* resize callback of airport */
49 
50 static void ShowAirport(Widget area, Airport this,  XtPointer cbs);
51 /* expose callback of airport */
52 
53 static void AirportInput(Widget area, Airport this, XtPointer cbs);
54 /* Callback when pointer or keyboard input in airport */
55 
56 static void ConfigureAirport(Widget area, Airport this);
57 /* configure geometry */
58 
59 static void Warning(Airport this, XmString s1, XmString s2);
60 /* issue a warning to user */
61 
62 
63 /* ==============================================================
64  *    Main loop
65  */
66 
67 int
main(int argc,char * argv[])68 main(int argc, char *argv[])
69 {
70 #define MAIN_CHILDREN		3
71 #define FORM_CHILDREN		3
72 #define PLANE_CHILDREN		6
73 #define TRAFFIC_CHILDREN	3
74 #define SetMenuEntry(k,l,p,d) labels[k]=l;procs[k]=p;private[k]=d;
75 
76    Pixmap flying;
77    Pixmap parked;
78    Pixmap mask;
79    Widget theWidgetRoot;
80    Widget main_tab[MAIN_CHILDREN];
81    Widget from_tab[PLANE_CHILDREN];
82    Widget to_tab[TRAFFIC_CHILDREN];
83    Widget form_tab[FORM_CHILDREN];
84    Widget framed[2];
85    Widget entry;
86    static char myClass[] = "XmdAirport";
87    Arg args[10];
88    int n ;
89    String labels[4];
90    XtCallbackProc procs[4];
91    XtPointer private[4];
92    XGCValues gcv;
93    Airport this;
94 
95 
96 /*
97  * Initialize
98  */
99    this = (Airport) XtCalloc(sizeof(AirportRec), 1);
100 
101    XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL);
102 
103    theWidgetRoot = XtVaOpenApplication( &this->context,
104                                         myClass,
105 				        NULL,
106                                         0,
107                                         &argc,
108                                         argv,
109                                         NULL,
110                                         sessionShellWidgetClass,
111 				        XmNallowShellResize, True,
112                                         NULL);
113 
114    this->display = XtDisplay(theWidgetRoot);
115    FlightAtom = XmInternAtom(this->display, "FLIGHT", False);
116    DeleteAtom = XmInternAtom(this->display, "DELETE", False);
117 
118    XtGetApplicationResources(theWidgetRoot, &AirportResources,
119 			     AirportResourcesSpecs,
120 			     XtNumber(AirportResourcesSpecs),
121 			     (ArgList) NULL, 0);
122 
123 /*
124  * Create the Main Window, the menubar and the pulldown menus
125  */
126    n = 0;
127    this->main = XmCreateMainWindow(theWidgetRoot, "main", args, n);
128 
129    n = 0;
130    main_tab[0] = XmCreateMenuBar(this->main, "menubar", args, n);
131    n = 0;
132    SetMenuEntry(n, "Exit",
133 		(XtCallbackProc) ExitCallback, (XtPointer) this ); n++;
134    entry = MenuBarEntry(main_tab[0], "File", labels, procs, private, n);
135    n = 0;
136    SetMenuEntry(0, "Tutorial",
137 		(XtCallbackProc) HelpCallback, (XtPointer) this); n++;
138    entry = MenuBarEntry(main_tab[0], "Help", labels, procs, private, n);
139    n = 0;
140    XtSetArg(args[n], XmNmenuHelpWidget, entry); n++;
141    XtSetValues(main_tab[0], args, n);
142 
143 /*
144  * Create the Airport widget structure.
145  * Two framed radio boxes show state.
146  * A drawing area in the middle show track and planes
147  */
148 
149    n = 0;
150    this->screen_width = WidthOfScreen(XtScreenOfObject(this->main));
151    this->screen_height = HeightOfScreen(XtScreenOfObject(this->main));
152    XtSetArg(args[n], XmNwidth, this->screen_width*3/7); n++;
153    XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
154    main_tab[1] = XmCreateForm(this->main, "airport", args, n);
155 
156    n = 0;
157    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
158    XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM); n++;
159    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM) ; n++;
160    form_tab[0] = XmCreateFrame(main_tab[1], "flight", args, n);
161 
162    n = 0;
163    XtSetArg(args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
164    framed[0] = XmCreateLabel(form_tab[0], "title", args, n);
165 
166    n = 0;
167    XtSetArg(args[n], XmNchildType, XmFRAME_WORKAREA_CHILD); n++;
168    XtSetArg(args[n], XmNresizePolicy, XmRESIZE_GROW); n++;
169    XtSetArg(args[n], XmNradioBehavior, True); n++;
170    framed[1] = XmCreateRadioBox(form_tab[0], "panel", args, n);
171 
172    n = 0;
173    XtSetArg(args[n], XmNset, True); n++;
174    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
175    this->from.departure =
176      from_tab[0] = XmCreateToggleButton(framed[1],
177 					       "departure", args, n);
178    n = 0;
179    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
180    this->from.over_ocean =
181      from_tab[1] = XmCreateToggleButton(framed[1],
182 					       "over_ocean", args, n);
183    n = 0;
184    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
185    this->from.over_land =
186      from_tab[2] = XmCreateToggleButton(framed[1],
187 					       "over_land", args, n);
188    n = 0;
189    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
190    this->from.over_site =
191      from_tab[3] = XmCreateToggleButton(framed[1],
192 					       "radar", args, n);
193    n = 0;
194    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
195    this->from.landing =
196      from_tab[4] = XmCreateToggleButton(framed[1], "landing", args, n);
197 
198    n = 0;
199    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
200    this->from.landed =
201      from_tab[5] = XmCreateToggleButton(framed[1], "landed", args, n);
202    XtManageChildren(from_tab, PLANE_CHILDREN);
203    XtManageChildren(framed, 2);
204 
205 /*
206  * Create the Airport Traffic control state
207  */
208 
209    n = 0;
210    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
211    XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM); n++;
212    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM) ; n++;
213    form_tab[1] = XmCreateFrame(main_tab[1], "traffic", args, n);
214 
215    n = 0;
216    XtSetArg(args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
217    framed[0] = XmCreateLabel(form_tab[1], "title", args, n);
218 
219    n = 0;
220    XtSetArg(args[n], XmNchildType, XmFRAME_WORKAREA_CHILD); n++;
221    XtSetArg(args[n], XmNradioBehavior, True); n++;
222    framed[1] = XmCreateRadioBox(form_tab[1], "traffic_box", args, n);
223 
224    n = 0;
225    XtSetArg(args[n], XmNset, True); n++;
226    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
227    this->to.leave =
228      to_tab[1] = XmCreateToggleButton(framed[1],
229 				      "no_traffic", args, n);
230    n = 0;
231    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
232    this->to.enter =
233      to_tab[0] = XmCreateToggleButton(framed[1],
234 				      "radar_echo", args, n);
235    n = 0;
236    XtSetArg(args[n], XmNvisibleWhenOff, False); n++;
237    this->to.landing =
238      to_tab[2] = XmCreateToggleButton(framed[1],
239 				      "landing", args, n);
240 
241    XtManageChildren(to_tab, TRAFFIC_CHILDREN);
242    XtManageChildren(framed, 2);
243 
244 /*
245  * Create the Airport picture
246  */
247    n = 0;
248    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
249    XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM); n++;
250    XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET) ; n++;
251    XtSetArg(args[n], XmNleftWidget, form_tab[0]) ; n++;
252    XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET) ; n++;
253    XtSetArg(args[n], XmNrightWidget, form_tab[1]) ; n++;
254    this->airport =
255      form_tab[2] = XmCreateDrawingArea(main_tab[1], "da", args, n);
256    XtAddCallback(this->airport, XmNexposeCallback,
257 		 (XtCallbackProc) ShowAirport, (XtPointer) this);
258    XtAddCallback(this->airport, XmNresizeCallback,
259 		 (XtCallbackProc) ResizeAirport, (XtPointer) this);
260    XtAddCallback(this->airport, XmNinputCallback,
261 		 (XtCallbackProc) AirportInput, (XtPointer) this);
262 /*
263  * Create the Airport Message area
264  */
265 
266    n = 0;
267    main_tab[2] = XmCreateFrame(this->main, "message", args, n);
268 
269    n = 0;
270    XtSetArg(args[n], XmNchildType, XmFRAME_TITLE_CHILD); n++;
271    framed[0] = XmCreateLabel(main_tab[2], "title", args, n);
272 
273    n = 0;
274    XtSetArg(args[n], XmNchildType, XmFRAME_WORKAREA_CHILD); n++;
275    XtSetArg(args[n], XmNvisibleItemCount, 4); n++;
276    this->msg_area = XmCreateScrolledList(main_tab[2], "msg_list", args, n);
277    XtManageChild(this->msg_area);
278    framed[1] = XtParent(this->msg_area);
279    XtManageChildren(framed, 2);
280 
281    n = 0;
282    XtSetArg(args[n], XmNmenuBar, main_tab[0]); n++;
283    XtSetArg(args[n], XmNworkWindow, main_tab[1]); n++;
284    XtSetArg(args[n], XmNmessageWindow, main_tab[2]); n++;
285    XtSetValues(this->main, args, n);
286    XtManageChildren(form_tab, FORM_CHILDREN);
287    XtManageChildren(main_tab, MAIN_CHILDREN);
288    XtManageChild(this->main);
289 
290    XtRealizeWidget(theWidgetRoot);
291 
292 /*
293  * Create the drag icon
294  */
295 
296    parked = XCreateBitmapFromData(this->display,
297 			   XtWindow(this->main), (char*)plane_bits,
298 			   plane_width, plane_height);
299 
300    flying = XCreateBitmapFromData(this->display,
301 				  XtWindow(this->main), (char*)flying_bits,
302 				  flying_icon_width, flying_icon_height);
303 
304    mask = XCreateBitmapFromData(this->display,
305 				XtWindow(this->main), (char*)flying_mask_bits,
306 				flying_mask_width, flying_mask_height);
307    n = 0;
308    XtSetArg(args[n], XmNpixmap, flying); n++;
309    XtSetArg(args[n], XmNdepth, 1); n++;
310    XtSetArg(args[n], XmNmask, mask); n++;
311    XtSetArg(args[n], XmNwidth, flying_icon_width); n++;
312    XtSetArg(args[n], XmNheight, flying_icon_height) ; n++;
313    this->dragIcon = XmCreateDragIcon(form_tab[2], "drag", args, n);
314    if (this->dragIcon  == NULL) {
315       printf("cannot create drag icon\n");
316       exit(0);
317    }
318   /* Create GC for drawing planes */
319    gcv.function = GXcopy;
320    gcv.fill_style = FillOpaqueStippled;
321    gcv.stipple = parked;
322    gcv.foreground = AirportResources.spot_foreground;
323    gcv.background = AirportResources.spot_background;
324    this->park.gc = XCreateGC(this->display, XtWindow(this->main),
325 			     GCFunction|GCStipple|GCFillStyle
326 			     |GCForeground|GCBackground,
327 			     &gcv);
328 
329    gcv.line_style = LineDoubleDash;
330    gcv.line_width = AirportResources.track_border_width;
331    gcv.fill_style = FillSolid;
332    gcv.foreground = AirportResources.track_foreground;
333    gcv.background = AirportResources.track_background;
334    this->track.gc = XCreateGC(this->display, XtWindow(this->main),
335 			      GCFunction|GCLineWidth|GCLineStyle
336 			      |GCFillStyle|GCForeground|GCBackground,
337 			      &gcv);
338    XtAppMainLoop(this->context);
339 
340    return 0;    /* make compiler happy */
341 }
342 
343 /* ===============================================================
344  *   Create a cascade and a pulldown entry into a menubar,
345  * 	from a list of push button specs.
346  *   If the label is NULL, create a separator instead of a push button.
347  */
348 
MenuBarEntry(Widget menubar,String entry,String labels[],XtCallbackProc procs[],XtPointer private[],int count)349 static Widget MenuBarEntry(Widget menubar, String entry, String labels[],
350 			   XtCallbackProc procs[], XtPointer private[],
351 			   int count)
352 {
353    Widget menu;
354    Widget child;
355    Arg args[8];
356    int n;
357    int i;
358    char name[128];
359 
360    n = 0;
361    menu = XmCreatePulldownMenu(menubar,
362 			       strcat(strcpy(name, entry), "Menu"),
363 			       args, n);
364    for( i = 0; i < count; i++) {
365       n = 0;
366       if (labels[i] == NULL) {
367 	 child = XmCreateSeparator(menu, "sep", args, n);
368       }
369       else {
370 	 child = XmCreatePushButton(menu, labels[i], args, n);
371 	 if (procs[i] != NULL)
372 	   XtAddCallback(child, XmNactivateCallback, procs[i], private[i]);
373       }
374       XtManageChild(child);
375    }
376    n = 0;
377    XtSetArg(args[n], XmNlabelString, XmStringCreateSimple(entry)); n++;
378    XtSetArg(args[n], XmNsubMenuId, menu); n++;
379    child = XmCreateCascadeButton(menubar, entry, args, n);
380    XtManageChild(child);
381    return child;
382 }
383 
384 
385 /* ===============================================================
386  *   The Exit Callback.  Exit properly.
387  */
388 
ExitCallback(Widget button,Airport this,XtPointer cbs)389 static void ExitCallback(Widget	button, Airport this, XtPointer cbs)
390 {
391    XtCloseDisplay(this->display);
392    exit(0);
393 }
394 
395 /* ======================================================================
396  *  Help Callback
397  */
398 
HelpCallback(Widget button,Airport this,XtPointer cbs)399 static void HelpCallback(Widget button, Airport this, XtPointer cbs)
400 {
401   static char helpmsg[] = "Read the README file, please...";
402 
403   if ( this->help_dialog == NULL ) {
404      Arg args[8];
405      int n = 0;
406 
407      XtSetArg(args[n], XmNmessageString,
408 	      XmStringCreateLocalized(helpmsg)); n++;
409      this->help_dialog = XmCreateInformationDialog(button,
410 					    "helpdialog", args, n);
411   }
412   XtManageChild(this->help_dialog);
413 }
414 
415 /* ===============================================================
416  * Create Airport tracks. Open airport to traffic.
417  *
418  */
419 
ConfigureAirport(Widget area,Airport this)420 static void ConfigureAirport(Widget area, Airport this)
421 {
422    Arg args[10];
423    int i, n;
424    Window root, parent, *wlist;
425    unsigned int count;
426    Dimension width, height;
427    int min_width, min_height;
428 
429 /*
430  * Try to make the screen background window the ocean.
431  * Be aware of running without a window manager,
432  * or with a reparenting window manager
433  * or a window manager like HP VUEWM who have a background window
434  */
435 
436    this->ocean = (Window) NULL;
437    if (XQueryTree(this->display, XtWindow(XtParent(this->main)),
438 		  &root, &parent, &wlist, &count)  != 0) {
439       Window current;
440 
441       do {
442 	 XWindowAttributes wa;
443 
444 	 current = this->ocean = parent;
445 	 if (XQueryTree(this->display, current, &root, &parent,
446 			&wlist, &count) == 0)
447 	   break;
448 
449 	 if (current == root)
450 	   {
451 	      /* beware of HP-VUE */
452 
453 	      XGetWindowAttributes(this->display, wlist[0], &wa);
454 	      this->ocean = (wa.width >= this->screen_width
455 			     && wa.height >= this->screen_height) ?
456 			       wlist[0] : root;
457 	   }
458 	 else {
459 	    XGetWindowAttributes(this->display, current, &wa);
460 	    if (wa.width >= this->screen_width
461 		&& wa.height >= this->screen_height)
462 	      {
463 		 this->ocean = current;
464 		 break;
465 	      }
466 	 }
467       } while (root != current);
468    }
469 
470    n = 0;
471    XtSetArg(args[n], XmNwidth, &width); n++;
472    XtSetArg(args[n], XmNheight, &height); n++;
473    XtGetValues(area, args, n);
474 
475    if (this->state == open)  { /* destroy current data */
476       XtFree((char *)this->park.spots);
477       XClearWindow(this->display, XtWindow(area) );
478       this->park.spot_count = 0;
479    }
480    min_height = AirportResources.track_margin * 4 + plane_height*2
481      		+ AirportResources.track_border_width*2 + MIN_TRACK_SIZE;
482    min_width = AirportResources.track_margin*2 + plane_width ;
483    if ( min_height > (int) height || min_width > (int) width)
484      {
485 	Warning(this,
486 		XmStringCreateLocalized(AirportResources.too_small),
487 		NULL);
488 	this->state = closed;
489      }
490    else
491      {
492 	Position x, y;
493 
494 	this->track.bbox.x = (short) AirportResources.track_margin;
495 	this->track.bbox.y = (short) AirportResources.track_margin*2
496 	  + plane_height;
497 	this->track.bbox.width = width - AirportResources.track_margin*2;
498 	this->track.bbox.height = height - 2*this->track.bbox.y;
499 	this->park.plane_count = (int) this->track.bbox.width / plane_width;
500 	this->park.spot_count = 2 * this->park.plane_count;
501 	this->park.spots = (Spot) XtCalloc(sizeof(SpotRec),
502 					   this->park.spot_count);
503 	x = AirportResources.track_margin;
504 	y = AirportResources.track_margin;
505 	for (i = 0; i < this->park.plane_count ; i++) {
506 	   this->park.spots[i].empty = False;
507 	   this->park.spots[i].x = x ;
508 	   this->park.spots[i].y = y ;
509 	   x += plane_width;
510 
511 	}
512 	x = AirportResources.track_margin;
513 	y += this->track.bbox.y + this->track.bbox.height
514 	  	+ AirportResources.track_margin;
515 	for (i = this->park.plane_count; i < this->park.spot_count ; i++) {
516 	   this->park.spots[i].empty = True;
517 	   this->park.spots[i].x = x ;
518 	   this->park.spots[i].y = y ;
519 	   x += plane_width;
520 	}
521       this->park.state = normal;
522    }
523 }
524 
525 /* ===============================================================
526  *   On Resize, clear the data structure and reset airport
527  *   So the first time it is initialized.
528  */
529 
ResizeAirport(Widget area,Airport this,XtPointer cbs)530 static void ResizeAirport(Widget area, Airport this, XtPointer cbs)
531 {
532 
533    if (! XtIsRealized(area) || this->state == closed)
534      return ;
535    ConfigureAirport(area, this);
536 
537 }
538 
539 /* ===============================================================
540  *   Expose callback. Redraw the airport
541  */
ShowAirport(Widget area,Airport this,XtPointer cbs)542 static void ShowAirport(Widget area, Airport this, XtPointer cbs)
543 {
544 
545    if (this->state == closed) {
546       ConfigureAirport(area, this);
547       MakeAirportDropSite(area, this);
548       this->state = open;
549    }
550    DrawAirport(this, XtWindow(area), AirportResources.track_background,
551 	       AirportResources.track_foreground);
552 }
553 
554 /* ===============================================================
555  *  Input callback. On button 2 drag plane.
556  */
557 
AirportInput(Widget area,Airport this,XtPointer cbs)558 static void AirportInput(Widget area, Airport this, XtPointer cbs)
559 {
560    int i;
561    XButtonEvent *evt;
562    XmDrawingAreaCallbackStruct *call_data = (XmDrawingAreaCallbackStruct *)cbs;
563 
564    if ((call_data->event->type != ButtonPress)
565        && (call_data->event->type != ButtonRelease))
566      return;
567 
568    evt = (XButtonEvent *) call_data->event;
569    switch(evt->type) {
570 
571    case ButtonPress:
572       switch (evt->button) {
573 
574       case Button2: /* start drag ?? */
575 
576 	 for (i = 0; i < this->park.spot_count ; i++) {
577 	    if (evt->x >= this->park.spots[i].x
578 		&& evt->y >= this->park.spots[i].y
579 		&& evt->x <= this->park.spots[i].x + plane_width
580 		&& evt->y <= this->park.spots[i].y + plane_height ) {
581 	       /* hit detection of the starting gate */
582 	       if (this->park.spots[i].empty == False)
583 		 TakeOff(area, this, evt, i);
584 	       break;
585 	    }
586 	 }
587 	 break;
588 
589       default:
590 	 return;
591       }
592       break;
593 
594    default:
595       return;
596    }
597 }
598 
599 /* ===============================================================
600  *
601  */
DrawAirport(Airport this,Window wd,Pixel bg,Pixel fg)602 void DrawAirport(Airport this, Window wd, Pixel bg, Pixel fg)
603 {
604    int i;
605    Position y;
606 
607    XSetForeground(this->display, this->track.gc, fg);
608    XSetBackground(this->display, this->track.gc, bg);
609    XFillRectangle(this->display, wd, this->track.gc,
610 		  this->track.bbox.x, this->track.bbox.y,
611 		  this->track.bbox.width, this->track.bbox.height);
612    XDrawLine(this->display, wd, this->track.gc,
613 	     this->track.bbox.x,
614 	     this->track.bbox.y + AirportResources.track_border_width,
615 	     this->track.bbox.x + this->track.bbox.width,
616 	     this->track.bbox.y + AirportResources.track_border_width);
617    y = this->track.bbox.y + this->track.bbox.height
618 	     - AirportResources.track_border_width;
619    XDrawLine(this->display, wd, this->track.gc,
620 	     this->track.bbox.x, y,
621 	     this->track.bbox.x + this->track.bbox.width, y);
622 
623    for (i = 0; i < this->park.spot_count ; i++) {
624       if (this->park.spots[i].empty == False) {
625 	 XSetTSOrigin(this->display, this->park.gc,
626 		      this->park.spots[i].x, this->park.spots[i].y);
627 	 XFillRectangle(this->display, wd, this->park.gc,
628 			this->park.spots[i].x, this->park.spots[i].y,
629 			plane_width, plane_height);
630       }
631    }
632 }
633 
634 /* ===============================================================
635  *   Display a message in the message area
636  */
Paging(Airport this,String msg)637 void Paging(Airport this, String msg)
638 {
639    XmString item;
640 
641    item = XmStringCreateLocalized(msg);
642    XmListDeselectAllItems(this->msg_area);
643    XmListAddItem(this->msg_area, item, 0);
644    XmListSetBottomItem(this->msg_area, item);
645 }
646 
647 /* =====================================================================
648  * Show application modal warning dialogue box with specified messages
649  */
650 
Warning(Airport this,XmString s1,XmString s2)651 static void Warning(Airport this, XmString s1, XmString s2)
652 {
653    XmString msg;
654 
655    if (s1 == NULL)
656      msg = s2;
657    else if (s2 == NULL)
658      msg = s1;
659    else
660      msg = XmStringConcat(s1, s2);
661 
662    if (this->warning_dialog == NULL) {
663       Arg args[8];
664       int n = 0;
665 
666       XtSetArg(args[n], XmNdialogStyle,
667 	       XmDIALOG_FULL_APPLICATION_MODAL);
668       n++;
669       this->warning_dialog = XmCreateWarningDialog(this->main,
670 						"warning", args, n);
671    }
672    XtVaSetValues(this->warning_dialog, XmNmessageString, msg, NULL);
673    XtManageChild(this->warning_dialog);
674 }
675