1 /*  Part of XPCE --- The SWI-Prolog GUI toolkit
2 
3     Author:        Jan Wielemaker and Anjo Anjewierden
4     E-mail:        jan@swi.psy.uva.nl
5     WWW:           http://www.swi.psy.uva.nl/projects/xpce/
6     Copyright (c)  1985-2002, University of Amsterdam
7     All rights reserved.
8 
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions
11     are met:
12 
13     1. Redistributions of source code must retain the above copyright
14        notice, this list of conditions and the following disclaimer.
15 
16     2. Redistributions in binary form must reproduce the above copyright
17        notice, this list of conditions and the following disclaimer in
18        the documentation and/or other materials provided with the
19        distribution.
20 
21     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32     POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #include <h/kernel.h>
36 #include <h/graphics.h>
37 					/* generated from Makefile */
38 
39 static status	backgroundDisplay(DisplayObj, Colour);
40 static status	foregroundDisplay(DisplayObj d, Colour c);
41 static void	attach_font_families(Class class);
42 
43 
44 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
45 Create a display.  The display is not yet opened.
46 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
47 
48 static status
initialiseDisplay(DisplayObj d,Name address)49 initialiseDisplay(DisplayObj d, Name address)
50 { DisplayManager dm = TheDisplayManager();
51 
52   assign(d, size,		NIL);
53   assign(d, address,		address);
54   assign(d, font_table,		newObject(ClassHashTable, EAV));
55   assign(d, frames,		newObject(ClassChain, EAV));
56   assign(d, inspect_handlers,	newObject(ClassChain, EAV));
57   assign(d, cache,		NIL);
58   assign(d, colour_map,		DEFAULT);
59   assign(d, display_manager,	dm);
60   assign(d, busy_locks,		ZERO);
61 
62   ws_init_display(d);
63   appendDisplayManager(dm, d);
64   protectObject(d);
65 
66   succeed;
67 }
68 
69 
70 static DisplayObj
getConvertDisplay(Class class,Any obj)71 getConvertDisplay(Class class, Any obj)
72 { Name address;
73   DisplayObj d;
74 
75   if ( (d = getMemberDisplayManager(TheDisplayManager(), obj)) )
76     answer(d);
77 
78   if ( isDefault(obj) )
79     answer(CurrentDisplay(obj));
80 
81   if ( instanceOfObject(obj, ClassVisual) )
82     answer(get(obj, NAME_display, EAV));
83 
84   if ( (address = checkType(obj, TypeName, class)) &&
85        ws_legal_display_name(strName(address)) )
86     answer(answerObject(ClassDisplay, address, EAV));
87 
88   fail;
89 }
90 
91 
92 static status
attachCacheDisplay(DisplayObj d)93 attachCacheDisplay(DisplayObj d)
94 { Size sz = getClassVariableValueObject(d, NAME_graphicsCache);
95 
96   if ( isDefault(sz) )
97     sz = getSizeDisplay(d);
98 
99   send(d, NAME_cache, newObject(ClassImage, DEFAULT, sz->w, sz->h,
100 				NAME_pixmap, EAV), EAV);
101 
102   succeed;
103 }
104 
105 
106 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107 Open a display.  If necessary, the X toolkit is initialised first and
108 a context for the application is created.
109 
110 As PCE  normally manages a  collection of main  windows an application
111 shell  widget is created to  serve as root for  all  the other (popup)
112 shells.  This widget is never realised (page 35 of Xt manual).
113 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
114 
115 status
openDisplay(DisplayObj d)116 openDisplay(DisplayObj d)
117 { if ( ws_opened_display(d) )
118     succeed;
119 
120   DEBUG(NAME_display, Cprintf("Opening display %s\n", pp(d)));
121 
122   ws_open_display(d);			/* generate exception on failure */
123   obtainClassVariablesObject(d);
124   ws_foreground_display(d, d->foreground);
125   ws_background_display(d, d->background);
126   ws_init_graphics_display(d);
127   ws_init_monitors_display(d);
128 
129   BLACK_COLOUR = newObject(ClassColour, NAME_black, EAV);
130   WHITE_COLOUR = newObject(ClassColour, NAME_white, EAV);
131 
132   attachCacheDisplay(d);
133 
134   succeed;
135 }
136 
137 
138 BoolObj
getOpenDisplay(Any d)139 getOpenDisplay(Any d)
140 { answer(ws_opened_display(d) ? ON : OFF);
141 }
142 
143 
144 static status
foregroundDisplay(DisplayObj d,Colour c)145 foregroundDisplay(DisplayObj d, Colour c)
146 { assign(d, foreground, c);
147   ws_foreground_display(d, c);
148 
149   succeed;
150 }
151 
152 
153 static status
backgroundDisplay(DisplayObj d,Colour c)154 backgroundDisplay(DisplayObj d, Colour c)
155 { assign(d, background, c);
156   ws_background_display(d, c);
157 
158   succeed;
159 }
160 
161 
162 static status
colourMapDisplay(DisplayObj d,ColourMap cm)163 colourMapDisplay(DisplayObj d, ColourMap cm)
164 { assign(d, colour_map, cm);
165 
166   succeed;
167 }
168 
169 
170 status
drawInDisplay(DisplayObj d,Graphical gr,Point pos,BoolObj invert,BoolObj subtoo)171 drawInDisplay(DisplayObj d, Graphical gr, Point pos, BoolObj invert, BoolObj subtoo)
172 { Int oldx, oldy;
173   Device dev;
174 
175   if ( isDefault(invert) )
176     invert = OFF;
177   if ( isDefault(subtoo) )
178     subtoo = OFF;
179 
180   if ( notDefault(pos) )
181   { oldx = gr->area->x;
182     oldy = gr->area->y;
183     dev = gr->device;
184     gr->device = NIL;
185     setGraphical(gr, pos->x, pos->y, DEFAULT, DEFAULT);
186   } else
187   { oldx = oldy = (Int) DEFAULT;
188     dev = NIL;				/* keep compiler happy */
189   }
190 
191   ComputeGraphical(gr);
192   openDisplay(d);
193 
194   ws_draw_in_display(d, gr, invert, subtoo);
195 
196   if ( notDefault(oldx) )
197   { setGraphical(gr, oldx, oldy, DEFAULT, DEFAULT);
198     gr->device = dev;
199   }
200 
201   succeed;
202 }
203 
204 
205 static Image
getImageDisplay(DisplayObj d,Area a)206 getImageDisplay(DisplayObj d, Area a)
207 { int x, y, w, h;
208 
209   openDisplay(d);
210   if ( isDefault(a) )
211   { Size sz = getSizeDisplay(d);
212 
213     x = y = 0;
214     w = valInt(sz->w);
215     h = valInt(sz->h);
216   } else
217   { x = valInt(a->x);
218     y = valInt(a->y);
219     w = valInt(a->w);
220     h = valInt(a->h);
221   }
222 
223   return ws_grab_image_display(d, x, y, w, h);
224 }
225 
226 
227 status
grabServerDisplay(DisplayObj d,BoolObj val)228 grabServerDisplay(DisplayObj d, BoolObj val)
229 { if ( ws_opened_display(d) )
230   { if ( val == ON )
231       ws_grab_server(d);
232     else
233       ws_ungrab_server(d);
234   }
235 
236   succeed;
237 }
238 
239 
240 static Int
getConnectionFdDisplay(DisplayObj d)241 getConnectionFdDisplay(DisplayObj d)
242 { if ( ws_opened_display(d) )
243     answer(ws_display_connection_number(d));
244 
245   fail;
246 }
247 
248 
249 static status
eventQueuedDisplay(DisplayObj d)250 eventQueuedDisplay(DisplayObj d)
251 { if ( ws_opened_display(d) )
252   { RedrawDisplayManager(d->display_manager);
253 
254     return ws_events_queued_display(d);
255   }
256 
257   fail;
258 }
259 
260 
261 status
dispatchDisplay(DisplayObj d)262 dispatchDisplay(DisplayObj d)
263 { answer(dispatchDisplayManager(d->display_manager, DEFAULT, DEFAULT));
264 }
265 
266 
267 status
flushDisplay(DisplayObj d)268 flushDisplay(DisplayObj d)
269 { if ( ws_opened_display(d) )
270   { RedrawDisplayManager(d->display_manager);
271     ws_flush_display(d);
272   }
273 
274   succeed;
275 }
276 
277 
278 status
synchroniseDisplay(DisplayObj d)279 synchroniseDisplay(DisplayObj d)
280 { if ( ws_opened_display(d) )
281   { RedrawDisplayManager(d->display_manager);
282 
283     ws_synchronise_display(d);
284   }
285 
286   succeed;
287 }
288 
289 
290 static status
screenSaverDisplay(DisplayObj d,BoolObj val)291 screenSaverDisplay(DisplayObj d, BoolObj val)
292 { openDisplay(d);
293 
294   if ( val == ON )
295     ws_activate_screen_saver(d);
296   else
297     ws_deactivate_screen_saver(d);
298 
299   succeed;
300 }
301 
302 
303 status
bellDisplay(DisplayObj d,Int vol)304 bellDisplay(DisplayObj d, Int vol)
305 { openDisplay(d);
306 
307   if ( isDefault(vol) )
308     vol = (Int) getClassVariableValueObject(d, NAME_volume);
309 
310   ws_bell_display(d, valInt(vol));
311 
312   succeed;
313 }
314 
315 
316 Size
getSizeDisplay(DisplayObj d)317 getSizeDisplay(DisplayObj d)
318 { int w=0, h=0;
319 
320   if ( notNil(d->size) )
321     answer(d->size);
322 
323   openDisplay(d);
324   ws_get_size_display(d, &w, &h);
325   assign(d, size, newObject(ClassSize, toInt(w), toInt(h), EAV));
326 
327   answer(d->size);
328 }
329 
330 
331 Int
getWidthDisplay(DisplayObj d)332 getWidthDisplay(DisplayObj d)
333 { answer(getSizeDisplay(d)->w);
334 }
335 
336 
337 Int
getHeightDisplay(DisplayObj d)338 getHeightDisplay(DisplayObj d)
339 { answer(getSizeDisplay(d)->h);
340 }
341 
342 
343 static Area
getBoundingBoxDisplay(DisplayObj d)344 getBoundingBoxDisplay(DisplayObj d)
345 { Size s = getSizeDisplay(d);
346 
347   answer( answerObject(ClassArea, ZERO, ZERO, s->w, s->h, EAV) );
348 }
349 
350 
351 static Int
getDepthDisplay(DisplayObj d)352 getDepthDisplay(DisplayObj d)
353 { TRY(openDisplay(d));
354 
355   answer(toInt(ws_depth_display(d)));
356 }
357 
358 static Name
getVisualTypeDisplay(DisplayObj d)359 getVisualTypeDisplay(DisplayObj d)
360 { TRY(openDisplay(d));
361 
362   answer(ws_get_visual_type_display(d));
363 }
364 
365 static Size
getDotsPerInchDisplay(DisplayObj d)366 getDotsPerInchDisplay(DisplayObj d)
367 { int rx, ry;
368 
369   if ( ws_resolution_display(d, &rx, &ry) )
370     answer(answerObject(ClassSize, toInt(rx), toInt(ry), EAV));
371 
372   fail;
373 }
374 
375 Point
getPointerLocationDisplay(DisplayObj d)376 getPointerLocationDisplay(DisplayObj d)
377 { int x, y;
378 
379   TRY(openDisplay(d));
380   if ( ws_pointer_location_display(d, &x, &y) )
381     answer(answerObject(ClassPoint, toInt(x), toInt(y), EAV));
382 
383   fail;
384 }
385 
386 
387 
388 		 /*******************************
389 		 *	     MONITORS		*
390 		 *******************************/
391 
392 static Chain
getMonitorsDisplay(DisplayObj d)393 getMonitorsDisplay(DisplayObj d)
394 { openDisplay(d);
395 
396   answer(d->monitors);
397 }
398 
399 
400 Monitor
getMonitorDisplay(DisplayObj d,Any obj)401 getMonitorDisplay(DisplayObj d, Any obj)
402 { Cell cell;
403 
404   openDisplay(d);
405 
406   if ( isDefault(obj) )
407   { if ( !(obj = getPointerLocationDisplay(d)) )
408       fail;
409   }
410 
411   if ( instanceOfObject(obj, ClassPoint) )
412   { Point pt = obj;
413 
414     for_cell(cell, d->monitors)
415     { Monitor mon = cell->value;
416 
417       if ( pointInArea(mon->area, pt) )
418 	return mon;
419     }
420   } else
421   { Area a = obj;
422     Monitor best = NULL;
423     Area tmp = tempObject(ClassArea, EAV);
424     int overlap = 0;
425 
426     for_cell(cell, d->monitors)
427     { Monitor mon = cell->value;
428 
429       copyArea(tmp, a);
430       if ( intersectionArea(tmp, mon->area) )
431       { int val = valInt(tmp->w)*valInt(tmp->h);
432 
433 	if ( val < 0 )
434 	  val = -val;
435 	if ( val > overlap )
436 	{ best = mon;
437 	  overlap = val;
438 	}
439       }
440     }
441 
442     considerPreserveObject(tmp);
443     return best;
444   }
445 
446   fail;
447 }
448 
449 
450 		/********************************
451 		*          CUT BUFFERS		*
452 		********************************/
453 
454 static status
cutBufferDisplay(DisplayObj d,Int n,CharArray str)455 cutBufferDisplay(DisplayObj d, Int n, CharArray str)
456 { PceString s = &str->data;
457   TRY(openDisplay(d));
458 
459   if ( isDefault(n) )
460     n = ZERO;
461 
462   return ws_set_cutbuffer(d, valInt(n), s);
463 }
464 
465 
466 static StringObj
getCutBufferDisplay(DisplayObj d,Int n)467 getCutBufferDisplay(DisplayObj d, Int n)
468 { TRY(openDisplay(d));
469 
470   if ( isDefault(n) )
471     n = ZERO;
472 
473   return ws_get_cutbuffer(d, valInt(n));
474 
475 }
476 
477 		 /*******************************
478 		 *	SELECTION INTERFACE	*
479 		 *******************************/
480 
481 static Real
getSelectionTimeoutDisplay(DisplayObj d)482 getSelectionTimeoutDisplay(DisplayObj d)
483 { unsigned long time = ws_get_selection_timeout();
484 
485   answer(CtoReal((float)time/1000.0));
486 }
487 
488 
489 static status
selectionTimeoutDisplay(DisplayObj d,Real time)490 selectionTimeoutDisplay(DisplayObj d, Real time)
491 { ws_set_selection_timeout((unsigned long)(valReal(time) * 1000.0));
492 
493   succeed;
494 }
495 
496 
497 static Any
getSelectionDisplay(DisplayObj d,Name which,Name target,Type type)498 getSelectionDisplay(DisplayObj d, Name which, Name target, Type type)
499 { Any sel;
500 
501   TRY(openDisplay(d));
502 
503   if ( isDefault(which) )  which  = NAME_primary;
504   if ( isDefault(target) ) target = NAME_text;
505   if ( isDefault(type) )   type   = nameToType(NAME_string);
506 
507   if ( (sel = ws_get_selection(d, which, target)) )
508     answer(checkType(sel, type, NIL));
509 
510   fail;
511 }
512 
513 
514 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
515 The owner of a selection is related using a hyper-object to the display.
516 This will inform the display if the selection onwner is deleted.
517 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
518 
519 static Any
getSelectionOwnerDisplay(DisplayObj d,Name which)520 getSelectionOwnerDisplay(DisplayObj d, Name which)
521 { if ( isDefault(which) )
522     which = NAME_primary;
523 
524   answer(getHyperedObject(d,
525 			  getAppendName(which, NAME_selectionOwner),
526 			  DEFAULT));
527 }
528 
529 
530 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
531 TBD: * multiple hypers for the various selection-types.
532      * proper call-back if the owner is unlinked.
533 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
534 
535 
536 status
looseSelectionDisplay(DisplayObj d,Name which)537 looseSelectionDisplay(DisplayObj d, Name which)
538 { Hyper h;
539   Code msg;
540   Name hypername = getAppendName(which, NAME_selectionOwner);
541 
542   if ( (h = getFindHyperObject(d, hypername, DEFAULT)) &&
543        (msg = getAttributeObject(h, NAME_looseMessage)) &&
544        (msg = checkType(msg, TypeCode, NIL)) )
545     forwardReceiverCode(msg, h->to, which, EAV);
546 
547   freeHypersObject(d, hypername, DEFAULT);
548 
549   succeed;
550 }
551 
552 
553 static status
selectionOwnerDisplay(DisplayObj d,Any owner,Name selection,Function convert,Code loose,Name type)554 selectionOwnerDisplay(DisplayObj d, Any owner, Name selection,
555 		      Function convert, Code loose, Name type)
556 { TRY(openDisplay(d));
557 
558   if ( isDefault(selection) )
559     selection = NAME_primary;
560   if ( isDefault(type) )
561     type = NAME_text;
562 
563   if ( isNil(owner) )
564   { Any old = getSelectionOwnerDisplay(d, selection);
565 
566     if ( old )
567     { looseSelectionDisplay(d, selection);
568       ws_disown_selection(d, selection);
569     }
570   } else
571   { Any old = getSelectionOwnerDisplay(d, selection);
572     Hyper h = NIL;
573     Name hypername = getAppendName(selection, NAME_selectionOwner);
574 
575     if ( old && old != owner )
576       looseSelectionDisplay(d, selection);
577 
578     if ( old != owner )
579       h = newObject(ClassHyper, d, owner, hypername, EAV);
580     else
581       h = getFindHyperObject(d, hypername, DEFAULT);
582 
583     attributeObject(h, NAME_convertFunction,
584 		     newObject(ClassQuoteFunction, convert, EAV));
585     attributeObject(h, NAME_looseMessage, loose);
586     attributeObject(h, NAME_type, type);
587 
588 #ifndef WIN32_GRAPHICS
589     if ( !old )
590 #endif
591     { if ( !ws_own_selection(d, selection, type) )
592       { freeHypersObject(d, hypername, DEFAULT);
593 	return errorPce(owner, NAME_cannotBecomeSelectionOwner, selection);
594       }
595     }
596   }
597 
598   succeed;
599 }
600 
601 		 /*******************************
602 		 *  SIMPLE SELECTION INTERFACE	*
603 		 *******************************/
604 
605 static status
selectionDisplay(DisplayObj d,Name which,StringObj data)606 selectionDisplay(DisplayObj d, Name which, StringObj data)
607 { StringObj s2 = get(data, NAME_copy, EAV);
608 
609   if ( s2 )
610   { lockObject(s2, ON);
611 
612     return selectionOwnerDisplay(d,
613 				 s2, which,
614 				 newObject(ClassObtain,
615 					   RECEIVER, NAME_self, EAV),
616 				 newObject(ClassMessage,
617 					   RECEIVER, NAME_free, EAV),
618 				 NAME_text);
619   }
620 
621   fail;
622 }
623 
624 
625 static status
copyDisplay(DisplayObj d,StringObj data)626 copyDisplay(DisplayObj d, StringObj data)
627 { int rval = (send(d, NAME_cutBuffer, ZERO, data, EAV) |
628 	      send(d, NAME_selection, NAME_primary, data, EAV) |
629 	      send(d, NAME_selection, NAME_clipboard, data, EAV));
630 
631 
632   return rval ? SUCCEED : FAIL;
633 }
634 
635 
636 static StringObj
getPasteDisplay(DisplayObj d,Name which)637 getPasteDisplay(DisplayObj d, Name which)
638 { static Name formats[] = { NAME_utf8_string,
639 			    NAME_text,
640 			    NAME_string,
641 			    NULL
642 			  };
643   StringObj s = NULL;
644   Name *fmt;
645 
646   if ( isDefault(which) )
647     which = NAME_clipboard;
648 
649   catchErrorPce(PCE, NAME_getSelection);
650   for(fmt = formats; *fmt; fmt++)
651   { if ( (s=get(d, NAME_selection, which, *fmt, EAV)) )
652       break;
653   }
654   if ( ! (*fmt) )
655     s = get(d, NAME_cutBuffer, ZERO, EAV);
656 
657   catchPopPce(PCE);
658 
659   if ( s )
660     answer(s);
661 
662   fail;
663 }
664 
665 
666 		/********************************
667 		*  WINDOW_MANAGER/LOOK-AND-FEEL	*
668 		********************************/
669 
670 static Name
getWindowManagerDisplay(DisplayObj d)671 getWindowManagerDisplay(DisplayObj d)
672 { Name wm;
673 
674   if ( notDefault(d->window_manager) )
675     answer(d->window_manager);
676 
677   if ( (wm = getClassVariableValueObject(d, NAME_windowManager)) &&
678        notDefault(wm) )
679   { assign(d, window_manager, wm);
680     answer(d->window_manager);
681   }
682 
683   if ( (wm = ws_window_manager(d)) )
684     assign(d, window_manager, wm);
685 
686   answer(d->window_manager);
687 }
688 
689 
690 		/********************************
691 		*        CONFIRM/INFORM		*
692 		********************************/
693 
694 static status
create_confirmer(DisplayObj d)695 create_confirmer(DisplayObj d)
696 { Any p, m, h;
697 
698   if ( getAttributeObject(d, NAME_confirmer) )
699     succeed;
700 
701   TRY( p = newObject(ClassWindow, DEFAULT, DEFAULT, d, EAV) );
702   TRY( m = newObject(ClassText, CtoName(""), NAME_center, EAV) );
703   TRY( h = newObject(ClassText, CtoName(""), NAME_center, EAV) );
704 
705   send(m, NAME_font, getClassVariableValueObject(d, NAME_labelFont), EAV);
706   send(h, NAME_font, getClassVariableValueObject(d, NAME_valueFont), EAV);
707   send(p, NAME_display, m, EAV);
708   send(p, NAME_display, h, EAV);
709   send(p, NAME_kind, NAME_popup, EAV);
710   send(p, NAME_cursor, newObject(ClassCursor, NAME_mouse, EAV), EAV);
711   send(p, NAME_border, toInt(3), EAV);
712   send(p, NAME_pen, toInt(3), EAV);
713   send(p, NAME_create, EAV);
714   send(get(p, NAME_frame, EAV), NAME_border, ONE, EAV);
715 
716   send(p, NAME_recogniser,
717           newObject(ClassHandler, NAME_button,
718 		    newObject(ClassMessage,
719 			      d, NAME_ConfirmPressed, Arg(1), EAV),
720 		    EAV),
721        EAV);
722 
723   attributeObject(d, NAME_SeenDown, OFF);
724   attributeObject(d, NAME_confirmer, p);
725   attributeObject(p, NAME_helpText, h);
726   attributeObject(p, NAME_messageText, m);
727 
728   succeed;
729 }
730 
731 
732 static status
ConfirmPressedDisplay(DisplayObj d,EventObj ev)733 ConfirmPressedDisplay(DisplayObj d, EventObj ev)
734 { if ( isDownEvent(ev) )
735     send(d, NAME_SeenDown, ON, EAV);
736   else if ( isUpEvent(ev) )
737   { if ( get(d, NAME_SeenDown, EAV) == ON )
738     { Name code = getButtonEvent(ev);
739 
740       send(get(d, NAME_confirmer, EAV), NAME_return, code, EAV);
741     } else
742     { send(get(d, NAME_confirmer, EAV), NAME_grabPointer, OFF, EAV); /* HACK */
743       send(get(d, NAME_confirmer, EAV), NAME_grabPointer, ON, EAV);
744     }
745   }
746 
747   succeed;
748 }
749 
750 
751 static Name
display_help(DisplayObj d,StringObj hlp,Name msg)752 display_help(DisplayObj d, StringObj hlp, Name msg)
753 { Any p;
754   TextObj hlp_text, msg_text;
755   int fx, fy, fw, fh, tx, ty;
756   Name rval;
757 
758   create_confirmer(d);
759   TRY( p        = getAttributeObject(d, NAME_confirmer) );
760   TRY( hlp_text = getAttributeObject(p, NAME_helpText));
761   TRY( msg_text = getAttributeObject(p, NAME_messageText));
762 
763   send(hlp_text, NAME_string, hlp, EAV);
764   send(msg_text, NAME_string, msg, EAV);
765   send(p, NAME_compute, EAV);
766 
767   fw = max(valInt(hlp_text->area->w), valInt(msg_text->area->w)) + 40;
768   fh = valInt(hlp_text->area->h) + valInt(msg_text->area->h) + 50;
769   getSizeDisplay(d);			/* initialise size argument */
770   fx = (valInt(d->size->w) - fw) / 2;
771   fy = (valInt(d->size->h) - fh) / 2;
772 
773   tx = (fw - 12 - valInt(hlp_text->area->w)) / 2;
774   send(hlp_text, NAME_set, toInt(tx), toInt(20), DEFAULT, DEFAULT, EAV);
775   tx = (fw - 12 - valInt(msg_text->area->w)) / 2;
776   ty = valInt(hlp_text->area->h) + 30;
777   send(msg_text, NAME_set, toInt(tx), toInt(ty), DEFAULT, DEFAULT, EAV);
778 
779   send(get(p, NAME_frame, EAV), NAME_set, toInt(fx), toInt(fy),
780 					toInt(fw), toInt(fh), EAV);
781 
782   send(d, NAME_SeenDown, OFF, EAV);
783   send(p, NAME_show, ON, EAV);
784   send(p, NAME_grabPointer, ON, EAV);
785   rval = get(p, NAME_confirm, DEFAULT, ON, EAV);
786   send(p, NAME_grabPointer, OFF, EAV);
787   send(p, NAME_show, OFF, EAV);
788 
789   return rval;
790 }
791 
792 
793 status
confirmDisplay(DisplayObj d,CharArray fmt,int argc,Any * argv)794 confirmDisplay(DisplayObj d, CharArray fmt, int argc, Any *argv)
795 { StringObj str;
796   ArgVector(av, argc+1);
797   int i;
798   Name button;
799 
800   av[0] = (Any) fmt;
801   for(i=0; i<argc; i++)
802     av[i+1] = argv[i];
803 
804   TRY(str = answerObjectv(ClassString, argc+1, av));
805 
806   switch( ws_message_box(str, MBX_CONFIRM) )
807   { case MBX_OK:
808       succeed;
809     case MBX_CANCEL:
810       fail;
811     default:
812     { Name msg;
813 
814       msg = CtoName("Press LEFT button to confirm, RIGHT button to cancel");
815       TRY(button = display_help(d, str, msg));
816       doneObject(str);
817 
818       if ( button == NAME_left )
819 	succeed;
820     }
821   }
822 
823   fail;
824 }
825 
826 
827 status
informDisplay(DisplayObj d,CharArray fmt,int argc,Any * argv)828 informDisplay(DisplayObj d, CharArray fmt, int argc, Any *argv)
829 { StringObj str;
830   ArgVector(av, argc+1);
831   int i;
832   Name button;
833 
834   av[0] = (Any) fmt;
835   for(i=0; i<argc; i++)
836     av[i+1] = argv[i];
837 
838   TRY(str = answerObjectv(ClassString, argc+1, av));
839 
840   switch( ws_message_box(str, MBX_INFORM) )
841   { case MBX_NOTHANDLED:
842     { Name msg;
843 
844       msg = CtoName("Press any button to remove message");
845       TRY(button = display_help(d, str, msg));
846       doneObject(str);
847     }
848   }
849 
850   succeed;
851 }
852 
853 
854 static status
reportDisplay(DisplayObj d,Name kind,CharArray fmt,int argc,Any * argv)855 reportDisplay(DisplayObj d, Name kind, CharArray fmt, int argc, Any *argv)
856 { if ( kind == NAME_error || kind == NAME_inform )
857   { ArgVector(av, argc+1);
858     StringObj str;
859 
860     av[0] = isDefault(fmt) ? (CharArray) CtoName("") : fmt;
861     copyArgs(argc, argv, &av[1]);
862     TRY(str = answerObjectv(ClassString, argc+1, av));
863     if ( kind == NAME_error )
864       alertReporteeVisual(d);
865 
866     switch( ws_message_box(str, MBX_ERROR) )
867     { case MBX_NOTHANDLED:
868       { Name msg, button;
869 
870 	msg = CtoName("Press any button to remove message");
871 	TRY(button = display_help(d, str, msg));
872 	doneObject(str);
873       }
874     }
875   } else if ( kind == NAME_warning )
876     alertReporteeVisual(d);
877 
878   succeed;
879 }
880 
881 
882 		 /*******************************
883 		 *		BUSY		*
884 		 *******************************/
885 
886 status
busyCursorDisplay(DisplayObj d,CursorObj c,BoolObj block_events)887 busyCursorDisplay(DisplayObj d, CursorObj c, BoolObj block_events)
888 { if ( !instanceOfObject(d, ClassDisplay) )
889     succeed;
890 
891   if ( notNil(c) )
892   { assign(d, busy_locks, add(d->busy_locks, ONE));
893 
894     if ( d->busy_locks == ONE )
895     { Cell cell;
896 
897       for_cell(cell, d->frames)
898 	busyCursorFrame(cell->value, c, block_events);
899       flushDisplay(d);
900     }
901   } else
902   { assign(d, busy_locks, sub(d->busy_locks, ONE));
903 
904     if ( valInt(d->busy_locks) < 0 )
905       assign(d, busy_locks, ZERO);
906 
907     if ( d->busy_locks == ZERO )
908     { Cell cell;
909 
910       for_cell(cell, d->frames)
911 	busyCursorFrame(cell->value, c, block_events);
912     }
913   }
914 
915   succeed;
916 }
917 
918 
919 		/********************************
920 		*          DEBUGGING		*
921 		********************************/
922 
923 static status
inspectHandlerDisplay(DisplayObj d,Handler h)924 inspectHandlerDisplay(DisplayObj d, Handler h)
925 { return addChain(d->inspect_handlers, h);
926 }
927 
928 
929 status
inspectDisplay(DisplayObj d,Graphical gr,EventObj ev)930 inspectDisplay(DisplayObj d, Graphical gr, EventObj ev)
931 { Handler h;
932 
933   for_chain(d->inspect_handlers, h,
934 	    { if ( isAEvent(ev, h->event) &&
935 		   forwardReceiverCode(h->message, gr, gr, ev, EAV) )
936 	      { DEBUG(NAME_inspect, Cprintf("Inspect %s succeeded on %s\n",
937 					    pp(ev->id), pp(h)));
938 		succeed;
939 	      }
940 	    })
941 
942   fail;
943 }
944 
945 
946 static status
synchronousDisplay(DisplayObj d,BoolObj val)947 synchronousDisplay(DisplayObj d, BoolObj val)
948 { TRY(openDisplay(d));
949 
950   if ( val == OFF )
951     ws_asynchronous(d);
952   else
953     ws_synchronous(d);
954 
955   succeed;
956 }
957 
958 
959 static status
resetDisplay(DisplayObj d)960 resetDisplay(DisplayObj d)
961 { PceWindow sw;
962 
963   grabServerDisplay(d, OFF);
964 
965   if ( (sw = getAttributeObject(d, NAME_confirmer)) )
966     send(sw, NAME_show, OFF, EAV);
967 
968   if ( d->busy_locks != ZERO )
969   { assign(d, busy_locks, ONE);
970     busyCursorDisplay(d, NIL, DEFAULT);
971   }
972 
973   return resetVisual((VisualObj) d);
974 }
975 
976 
977 static status
quitDisplay(DisplayObj d)978 quitDisplay(DisplayObj d)
979 { ws_quit_display(d);
980 
981   succeed;
982 }
983 
984 		/********************************
985 		*          FONT TABLES		*
986 		********************************/
987 
988 static status
loadFontFamilyDisplay(DisplayObj d,Name fam)989 loadFontFamilyDisplay(DisplayObj d, Name fam)
990 { Class class = classOfObject(d);
991 
992   if ( !getClassVariableClass(class, fam) )
993     attach_class_variable(class, fam, "chain", "[]", "Font family set");
994 
995   if ( !getClassVariableValueObject(d, fam) )
996     return errorPce(d, NAME_noFontsInFamily, fam);
997 
998   succeed;
999 }
1000 
1001 
1002 static status
loadFontsDisplay(DisplayObj d)1003 loadFontsDisplay(DisplayObj d)
1004 { Chain fams;
1005   static int done = FALSE;
1006 
1007   if ( done )
1008     succeed;
1009   done = TRUE;
1010 
1011   if ( (fams = getClassVariableValueObject(d, NAME_fontFamilies)) )
1012   { Cell cell;
1013 
1014     for_cell(cell, fams)
1015       send(d, NAME_loadFontFamily, cell->value, EAV);
1016   }
1017 
1018   succeed;
1019 }
1020 
1021 
1022 static status
loadFontAliasesDisplay(DisplayObj d,Name res)1023 loadFontAliasesDisplay(DisplayObj d, Name res)
1024 { Chain ch = getClassVariableValueObject(d, res);
1025 
1026   if ( ch )
1027   { Cell cell;
1028     Type type_font = nameToType(NAME_font);
1029 
1030     for_cell(cell, ch)
1031     { Name name;
1032       FontObj font;
1033       Any n, f;
1034 
1035       if ( instanceOfObject(cell->value, ClassBinding) )
1036       { Binding b = cell->value;
1037 	n = b->name;
1038 	f = b->value;
1039       } else if ( instanceOfObject(cell->value, ClassTuple) )
1040       { Tuple t = cell->value;
1041 	n = t->first;
1042 	f = t->second;
1043       } else if ( instanceOfObject(cell->value, ClassAttribute) )
1044       { Attribute a = cell->value;
1045 	n = a->name;
1046 	f = a->value;
1047       } else
1048       { errorPce(cell->value, NAME_unexpectedType,
1049 		 CtoType(":=|tuple|attribute"));
1050 	continue;
1051       }
1052 
1053       if ( !(name = checkType(n, TypeName, d)) ||
1054 	   !(font = checkType(f, type_font, d)) )
1055 	errorPce(d, NAME_badFontAlias, n, f);
1056       else
1057 	send(d, NAME_fontAlias, name, font, EAV);
1058     }
1059 
1060     succeed;
1061   }
1062 
1063   fail;
1064 }
1065 
1066 
1067 static status
fontAliasDisplay(DisplayObj d,Name name,FontObj font,BoolObj force)1068 fontAliasDisplay(DisplayObj d, Name name, FontObj font, BoolObj force)
1069 { if ( force == ON || !getMemberHashTable(d->font_table, name) )
1070     appendHashTable(d->font_table, name, font);
1071 
1072   succeed;
1073 }
1074 
1075 
1076 static FontObj
getFontAliasDisplay(DisplayObj d,Name name)1077 getFontAliasDisplay(DisplayObj d, Name name)
1078 { FontObj f;
1079 
1080   if ( (f = getMemberHashTable(d->font_table, name)) )
1081     answer(f);
1082 
1083   makeBuiltinFonts();
1084 
1085   answer(getMemberHashTable(d->font_table, name));
1086 }
1087 
1088 
1089 		/********************************
1090 		*             VISUAL		*
1091 		********************************/
1092 
1093 static Chain
getContainsDisplay(DisplayObj d)1094 getContainsDisplay(DisplayObj d)
1095 { answer(d->frames);
1096 }
1097 
1098 
1099 static Any
getContainedInDisplay(DisplayObj d)1100 getContainedInDisplay(DisplayObj d)
1101 { answer(d->display_manager);
1102 }
1103 
1104 		 /*******************************
1105 		 *	 CLASS DECLARATION	*
1106 		 *******************************/
1107 
1108 /* Type declarations */
1109 
1110 static char *T_cutBuffer[] =
1111         { "buffer=[0..7]", "value=string" };
1112 static char *T_busyCursor[] =
1113         { "cursor=[cursor]*", "block_input=[bool]" };
1114 static char *T_drawIn[] =
1115         { "graphical", "at=[point]", "invert=[bool]", "subwindow=[bool]" };
1116 static char *T_postscript[] =
1117         { "landscape=[bool]", "max_area=[area]" };
1118 static char *T_fontAlias[] =
1119         { "name=name", "font=font", "force=[bool]" };
1120 static char *T_name_any_XXX[] =
1121         { "name", "any ..." };
1122 static char *T_selectionOwner[] =
1123         { "owner=object*", "which=[name]", "convert=[function]",
1124 	  "loose=[code]",
1125 #ifdef WIN32_GRAPHICS
1126 	  "type=[{text,emf,wmf}]"	/* metafile types */
1127 #else
1128 	  "type=[{text}]"
1129 #endif
1130 	};
1131 static char *T_getSelection[] =
1132         { "which=[name]", "target=[name]", "type=[type]" };
1133 static char *T_selection[] =
1134         { "which=[name]", "value=char_array" };
1135 #ifdef WIN32_GRAPHICS
1136 extern Name getWinFileNameDisplay(DisplayObj obj,
1137 				  Name mode,
1138 				  Chain filters,
1139 				  CharArray title,
1140 				  CharArray file,
1141 				  Directory dir,
1142 				  Any owner,
1143 				  Chain flags);
1144 static char *T_win_file_name[] =
1145 	{ "mode={open,save}",
1146 	  "filters=[chain]",
1147 	  "title=[char_array]",
1148 	  "default=[char_array]",
1149 	  "directory=[directory]",
1150 	  "owner=[frame|int]",
1151 	  "options=[chain]"
1152 	};
1153 extern Name getWinDirectoryDisplay(DisplayObj d,
1154 				   CharArray title,
1155 				   Directory dir,
1156 				   Any owner);
1157 static char *T_win_directory[] =
1158 	{ "title=[char_array]",
1159 	  "directory=[directory]",
1160 	  "owner=[frame|int]"
1161 	};
1162 #endif
1163 
1164 /* Instance Variables */
1165 
1166 static vardecl var_display[] =
1167 { IV(NAME_size, "size*", IV_NONE,
1168      NAME_dimension, "Size (width, height) of display"),
1169   IV(NAME_address, "[name]", IV_BOTH,
1170      NAME_address, "Host/screen on which display resides"),
1171   IV(NAME_fontTable, "hash_table", IV_BOTH,
1172      NAME_font, "Mapping for logical font-names to fonts"),
1173   IV(NAME_frames, "chain", IV_GET,
1174      NAME_organisation, "Frames displayed on this display"),
1175   IV(NAME_monitors, "chain", IV_NONE,
1176      NAME_organisation, "Physical monitors attached"),
1177   IV(NAME_inspectHandlers, "chain", IV_GET,
1178      NAME_event, "Chain of handlers to support inspector tools"),
1179   SV(NAME_foreground, "colour", IV_GET|IV_STORE, foregroundDisplay,
1180      NAME_appearance, "Windows default foreground colour"),
1181   SV(NAME_background, "colour", IV_GET|IV_STORE, backgroundDisplay,
1182      NAME_appearance, "Windows default background colour"),
1183   SV(NAME_colourMap, "[colour_map]*", IV_GET|IV_STORE, colourMapDisplay,
1184      NAME_appearance, "Default for `frame ->colour_map'"),
1185   IV(NAME_quickAndDirty, "bool", IV_BOTH,
1186      NAME_cache, "Painting quick or correct?"),
1187   IV(NAME_cache, "image*", IV_BOTH,
1188      NAME_cache, "Scratch image to avoid flickering"),
1189   IV(NAME_windowManager, "[{twm,olwm,mwm}|name]", IV_SEND,
1190      NAME_windowManager, "Window manager running on this display"),
1191   IV(NAME_displayManager, "display_manager", IV_GET,
1192      NAME_organisation, "The global display manager (@display_manager)"),
1193   IV(NAME_busyLocks, "0..", IV_NONE,
1194      NAME_event, "Lock count for ->busy_cursor"),
1195   IV(NAME_wsRef, "alien:WsRef", IV_NONE,
1196      NAME_windowSystem, "Window-System reference")
1197 };
1198 
1199 /* Send Methods */
1200 
1201 static senddecl send_display[] =
1202 { SM(NAME_initialise, 1, "address=[name]", initialiseDisplay,
1203      DEFAULT, "Create at given address (<host>:<screen>)"),
1204   SM(NAME_reset, 0, NULL, resetDisplay,
1205      NAME_abort, "Closedown informer/confirmer"),
1206   SM(NAME_flush, 0, NULL, flushDisplay,
1207      NAME_animate, "Flush pending commands to X-server"),
1208   SM(NAME_grabServer, 1, "grab=bool", grabServerDisplay,
1209      NAME_animate, "Freeze all other applications"),
1210   SM(NAME_synchronise, 0, NULL, synchroniseDisplay,
1211      NAME_animate, "->flush and process pending events"),
1212   SM(NAME_synchronous, 1, "[bool]", synchronousDisplay,
1213      NAME_debugging, "Make communication to X-server synchronous"),
1214   SM(NAME_busyCursor, 2, T_busyCursor, busyCursorDisplay,
1215      NAME_event, "Define (temporary) cursor for all frames on the display"),
1216   SM(NAME_dispatch, 0, NULL, dispatchDisplay,
1217      NAME_event, "Dispatch events for 1/4th second"),
1218   SM(NAME_eventQueued, 0, NULL, eventQueuedDisplay,
1219      NAME_event, "Test if there are X-events waiting"),
1220   SM(NAME_inspectHandler, 1, "handler", inspectHandlerDisplay,
1221      NAME_event, "Register handler for inspect tool"),
1222   SM(NAME_fontAlias, 3, T_fontAlias, fontAliasDisplay,
1223      NAME_font, "Define a logical name for a font"),
1224   SM(NAME_loadFontAliases, 1, "set=name", loadFontAliasesDisplay,
1225      NAME_font, "Load font aliases from named class-variable"),
1226   SM(NAME_loadFontFamily, 1, "family=name", loadFontFamilyDisplay,
1227      NAME_font, "Create predefined fonts from family"),
1228   SM(NAME_loadFonts, 0, NULL, loadFontsDisplay,
1229      NAME_font, "Create predefined font set from defaults"),
1230   SM(NAME_ConfirmPressed, 1, "event", ConfirmPressedDisplay,
1231      NAME_internal, "Handle confirmer events"),
1232   SM(NAME_open, 0, NULL, openDisplay,
1233      NAME_open, "Open connection to X-server and initialise"),
1234   SM(NAME_Postscript, 1, "{head,body}", postscriptDisplay,
1235      NAME_postscript, "Create PostScript"),
1236   SM(NAME_quit, 0, NULL, quitDisplay,
1237      NAME_quit, "Destroy all window-system references"),
1238   SM(NAME_bell, 1, "volume=[int]", bellDisplay,
1239      NAME_report, "Ring the bell at volume"),
1240   SM(NAME_confirm, 2, T_name_any_XXX, confirmDisplay,
1241      NAME_report, "Test if the user confirms string"),
1242   SM(NAME_inform, 2, T_name_any_XXX, informDisplay,
1243      NAME_report, "Inform the user of something"),
1244   SM(NAME_report, 3, T_report, reportDisplay,
1245      NAME_report, "Report message using ->inform"),
1246   SM(NAME_drawIn, 4, T_drawIn, drawInDisplay,
1247      NAME_root, "Draw graphical in root window"),
1248   SM(NAME_cutBuffer, 2, T_cutBuffer, cutBufferDisplay,
1249      NAME_selection, "Set value of numbered X-cut buffer"),
1250   SM(NAME_selectionOwner, 5, T_selectionOwner, selectionOwnerDisplay,
1251      NAME_selection, "Define the owner of the X11 selection"),
1252   SM(NAME_selectionTimeout, 1, "real", selectionTimeoutDisplay,
1253      NAME_selection, "Set the timeout-time for getting the selection value"),
1254   SM(NAME_selection, 2, T_selection, selectionDisplay,
1255      NAME_selection, "Set the (textual) selection"),
1256   SM(NAME_copy, 1, "char_array", copyDisplay,
1257      NAME_selection, "Copy to selection and cut_buffer"),
1258 #ifndef WIN32_GRAPHICS
1259   SM(NAME_metaModifier, 1, "name", metaModifierDisplay,
1260      NAME_x, "Set the X modifier that is associated with META-"),
1261   SM(NAME_x11Threads, 1, "bool", X11ThreadsDisplay,
1262      NAME_x, "Setup X11 of multi-threading?"),
1263 #endif
1264   SM(NAME_screenSaver, 1, "bool", screenSaverDisplay,
1265      NAME_x, "Activate (@on) or deactivate (@off) screensaver")
1266 };
1267 
1268 /* Get Methods */
1269 
1270 static getdecl get_display[] =
1271 { GM(NAME_containedIn, 0, "display_manager", NULL, getContainedInDisplay,
1272      DEFAULT, "Display manager"),
1273   GM(NAME_contains, 0, "chain", NULL, getContainsDisplay,
1274      DEFAULT, "Chain with frames contained"),
1275   GM(NAME_convert, 1, "display", "any", getConvertDisplay,
1276      DEFAULT, "Convert graphical or `host:display[.screen]'"),
1277   GM(NAME_depth, 0, "bits_per_pixel=int", NULL, getDepthDisplay,
1278      NAME_colour, "Number of bits/pixel"),
1279   GM(NAME_open, 0, "bool", NULL, getOpenDisplay,
1280      NAME_open, "Query connected status of the display"),
1281   GM(NAME_visualType, 0,
1282      "{monochrome,static_grey,grey_scale,static_colour,pseudo_colour,true_colour,direct_colour}",
1283      NULL, getVisualTypeDisplay,
1284      NAME_colour, "Type of display attached"),
1285   GM(NAME_height, 0, "int", NULL, getHeightDisplay,
1286      NAME_dimension, "Height of the display in pixels"),
1287   GM(NAME_size, 0, "size", NULL, getSizeDisplay,
1288      NAME_dimension, "Size of the display"),
1289   GM(NAME_width, 0, "int", NULL, getWidthDisplay,
1290      NAME_dimension, "Width of the display in pixels"),
1291   GM(NAME_dotsPerInch, 0, "size", NULL, getDotsPerInchDisplay,
1292      NAME_dimension, "Resolution in dots per inch"),
1293   GM(NAME_pointerLocation, 0, "point", NULL, getPointerLocationDisplay,
1294      NAME_event, "Current location of the pointer"),
1295   GM(NAME_monitors, 0, "chain*", NULL, getMonitorsDisplay,
1296      NAME_monitor, "Physical monitors attached"),
1297   GM(NAME_monitor, 1, "monitor", "[point|area]", getMonitorDisplay,
1298      NAME_monitor, "Find monitor at position"),
1299   GM(NAME_fontAlias, 1, "font", "name=name", getFontAliasDisplay,
1300      NAME_font, "Lookup logical name"),
1301   GM(NAME_connectionFd, 0, "int", NULL, getConnectionFdDisplay,
1302      NAME_host, "Unix file descriptor for X-display connection"),
1303   GM(NAME_boundingBox, 0, "area", NULL, getBoundingBoxDisplay,
1304      NAME_postscript, "PostScript bounding box for the display"),
1305   GM(NAME_postscript, 2, "string", T_postscript, getPostscriptObject,
1306      NAME_postscript, "Get PostScript or (area of) display"),
1307   GM(NAME_image, 1, "image", "[area]", getImageDisplay,
1308      NAME_conversion, "Image with the pixels of a region from the display"),
1309   GM(NAME_cutBuffer, 1, "string", "buffer=[0..7]", getCutBufferDisplay,
1310      NAME_selection, "New string with value of cut-buffer"),
1311   GM(NAME_selection, 3, "any", T_getSelection, getSelectionDisplay,
1312      NAME_selection, "Query value of the X-window selection"),
1313   GM(NAME_selectionOwner, 1, "object", "which=[name]", getSelectionOwnerDisplay,
1314      NAME_selection, "Current object owning the X11 selection"),
1315   GM(NAME_selectionTimeout, 0, "real", NULL, getSelectionTimeoutDisplay,
1316      NAME_selection, "Get the current selection timeout time (seconds)"),
1317   GM(NAME_paste, 1, "string", "which=[{primary,clipboard}]", getPasteDisplay,
1318      NAME_selection, "Simple interface to get clipboard value"),
1319 #ifdef WIN32_GRAPHICS
1320   GM(NAME_winFileName, 7, "name", T_win_file_name, getWinFileNameDisplay,
1321      NAME_prompt, "Ask for a filename using Windows standard dialog"),
1322   GM(NAME_winDirectory, 3, "name", T_win_directory, getWinDirectoryDisplay,
1323      NAME_prompt, "Ask for a directory (folder) using Windows standard dialog"),
1324 #endif
1325   GM(NAME_windowManager, 0, "[{twm,olwm,mwm,fvwm}|name]", NULL,
1326      getWindowManagerDisplay,
1327      NAME_windowManager, "Window manager running on this display")
1328 };
1329 
1330 /* Resources */
1331 
1332 static classvardecl rc_display[] =
1333 { RC(NAME_background, "colour", "white",
1334      "Default background for windows"),
1335   RC(NAME_foreground, "colour", "black",
1336      "Default foreground for windows"),
1337   RC(NAME_graphicsCache, "[size]", "@default",
1338      "Size of cache image to avoid flickering"),
1339   RC(NAME_labelFont, "font", "bold",
1340      "Label font for confirm/inform"),
1341   RC(NAME_systemFonts, "chain",
1342      "[ normal    := font(helvetica, roman, 12),\n"
1343      "  bold      := font(helvetica, bold, 12),\n"
1344      "  italic    := font(helvetica, oblique, 12),\n"
1345      "  small     := font(helvetica, roman, 10),\n"
1346      "  large     := font(helvetica, roman, 14),\n"
1347      "  boldlarge := font(helvetica, bold, 14),\n"
1348      "  huge      := font(helvetica, roman, 18),\n"
1349      "  boldhuge  := font(helvetica, bold, 18),\n"
1350      "  fixed     := font(courier, roman, 12),\n"
1351      "  tt        := font(courier, roman, 12),\n"
1352      "  boldtt    := font(courier, bold, 12)\n"
1353      "]",
1354      "Predefined font-aliases"),
1355   RC(NAME_noFont, "font", "normal",
1356      "Replacement for undefined fonts"),
1357   RC(NAME_quickAndDirty, "bool", "@on",
1358      "Draw quick or correct"),
1359   RC(NAME_valueFont, "font", "normal",
1360      "Text font for confirm/inform"),
1361   RC(NAME_volume, "int", "0",
1362      "Default volume of ->bell"),
1363   RC(NAME_windowManager, "[name]", "@default",
1364      "Window manager running on this display")
1365 };
1366 
1367 /* Class Declaration */
1368 
1369 static Name display_termnames[] = { NAME_address };
1370 
1371 ClassDecl(display_decls,
1372           var_display, send_display, get_display, rc_display,
1373           1, display_termnames,
1374           "$Rev$");
1375 
1376 
1377 
1378 status
makeClassDisplay(Class class)1379 makeClassDisplay(Class class)
1380 { DisplayObj TheDisplay;
1381 
1382   declareClass(class, &display_decls);
1383   saveStyleClass(class, NAME_external);
1384   cloneStyleClass(class, NAME_none);
1385 
1386   TheDisplay = globalObject(NAME_display, ClassDisplay, EAV);
1387   globalObject(NAME_colourDisplay, ClassGreater,
1388 	       newObject(ClassObtain, TheDisplay, NAME_depth, EAV),
1389 	       ONE, EAV);
1390 
1391   attach_font_families(class);
1392 
1393   succeed;
1394 }
1395 
1396 
1397 #define PFONT(n, p, x) { n, p, XNAME(x) }
1398 #define ENDFONTLIST    { NULL, 0, NULL }
1399 
1400 typedef struct
1401 { Name style;
1402   int  points;
1403   char *xname;
1404 } fontdef, *FontDef;
1405 
1406 #if defined(WIN32_GRAPHICS) || defined(USE_XFT)
1407 #define XNAME(x) NULL
1408 #else
1409 #define XNAME(x) x
1410 #endif
1411 
1412 #ifndef FIXED_FAMILY
1413 #define FIXED_FAMILY "*"
1414 #endif
1415 
1416 static fontdef screen_fonts[] =
1417 { PFONT(NAME_roman, 10,
1418 	"-" FIXED_FAMILY "-fixed-medium-r-normal--10-*-*-*-*-*-iso10646-*"),
1419   PFONT(NAME_roman, 12,
1420 	"-" FIXED_FAMILY "-fixed-medium-r-normal--12-*-*-*-*-*-iso10646-*"),
1421   PFONT(NAME_roman, 14,
1422 	"-" FIXED_FAMILY "-fixed-medium-r-normal--14-*-*-*-*-*-iso10646-*"),
1423   PFONT(NAME_roman, 16,
1424 	"-" FIXED_FAMILY "-fixed-medium-r-normal--16-*-*-*-*-*-iso10646-*"),
1425   PFONT(NAME_bold, 10,
1426 	"-" FIXED_FAMILY "-fixed-bold-r-normal--10-*-*-*-*-*-iso10646-*"),
1427   PFONT(NAME_bold, 12,
1428 	"-" FIXED_FAMILY "-fixed-bold-r-normal--12-*-*-*-*-*-iso10646-*"),
1429   PFONT(NAME_bold, 14,
1430 	"-" FIXED_FAMILY "-fixed-bold-r-normal--14-*-*-*-*-*-iso10646-*"),
1431   PFONT(NAME_bold, 16,
1432 	"-" FIXED_FAMILY "-fixed-bold-r-normal--16-*-*-*-*-*-iso10646-*"),
1433   ENDFONTLIST
1434 };
1435 
1436 #undef XNAME
1437 #if defined(WIN32_GRAPHICS) || defined(USE_XFT)
1438 #define XNAME(x) NULL
1439 #else
1440 #define XNAME(x) x
1441 #endif
1442 
1443 static fontdef courier_fonts[] =
1444 { PFONT(NAME_roman, 10,
1445 	"-*-courier new-medium-r-normal--10-*-*-*-*-*-*-*"),
1446   PFONT(NAME_roman, 12,
1447 	"-*-courier new-medium-r-normal--12-*-*-*-*-*-*-*"),
1448   PFONT(NAME_roman, 14,
1449 	"-*-courier new-medium-r-normal--14-*-*-*-*-*-*-*"),
1450   PFONT(NAME_roman, 18,
1451 	"-*-courier new-medium-r-normal--18-*-*-*-*-*-*-*"),
1452   PFONT(NAME_roman, 24,
1453 	"-*-courier new-medium-r-normal--24-*-*-*-*-*-*-*"),
1454   PFONT(NAME_bold, 10,
1455 	"-*-courier new-bold-r-normal--10-*-*-*-*-*-*-*"),
1456   PFONT(NAME_bold, 12,
1457 	"-*-courier new-bold-r-normal--12-*-*-*-*-*-*-*"),
1458   PFONT(NAME_bold, 14,
1459 	"-*-courier new-bold-r-normal--14-*-*-*-*-*-*-*"),
1460   PFONT(NAME_bold, 18,
1461 	"-*-courier new-bold-r-normal--18-*-*-*-*-*-*-*"),
1462   PFONT(NAME_bold, 24,
1463 	"-*-courier new-bold-r-normal--24-*-*-*-*-*-*-*"),
1464   PFONT(NAME_oblique, 10,
1465 	"-*-courier new-medium-o-normal--10-*-*-*-*-*-*-*"),
1466   PFONT(NAME_oblique, 12,
1467 	"-*-courier new-medium-o-normal--12-*-*-*-*-*-*-*"),
1468   PFONT(NAME_oblique, 14,
1469 	"-*-courier new-medium-o-normal--14-*-*-*-*-*-*-*"),
1470   PFONT(NAME_oblique, 18,
1471 	"-*-courier new-medium-o-normal--18-*-*-*-*-*-*-*"),
1472   PFONT(NAME_oblique, 24,
1473 	"-*-courier new-medium-o-normal--24-*-*-*-*-*-*-*"),
1474   ENDFONTLIST
1475 };
1476 
1477 
1478 static fontdef helvetica_fonts[] =
1479 { PFONT(NAME_bold, 10,
1480 	"-*-helvetica-bold-r-normal--10-*-*-*-*-*-*-*"),
1481   PFONT(NAME_bold, 12,
1482 	"-*-helvetica-bold-r-normal--12-*-*-*-*-*-*-*"),
1483   PFONT(NAME_bold, 14,
1484 	"-*-helvetica-bold-r-normal--14-*-*-*-*-*-*-*"),
1485   PFONT(NAME_bold, 18,
1486 	"-*-helvetica-bold-r-normal--18-*-*-*-*-*-*-*"),
1487   PFONT(NAME_bold, 24,
1488 	"-*-helvetica-bold-r-normal--24-*-*-*-*-*-*-*"),
1489   PFONT(NAME_roman, 10,
1490 	"-*-helvetica-medium-r-normal--10-*-*-*-*-*-*-*"),
1491   PFONT(NAME_roman, 12,
1492 	"-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*"),
1493   PFONT(NAME_roman, 14,
1494 	"-*-helvetica-medium-r-normal--14-*-*-*-*-*-*-*"),
1495   PFONT(NAME_roman, 18,
1496 	"-*-helvetica-medium-r-normal--18-*-*-*-*-*-*-*"),
1497   PFONT(NAME_roman, 24,
1498 	"-*-helvetica-medium-r-normal--24-*-*-*-*-*-*-*"),
1499   PFONT(NAME_oblique, 10,
1500 	"-*-helvetica-medium-o-normal--10-*-*-*-*-*-*-*"),
1501   PFONT(NAME_oblique, 12,
1502 	"-*-helvetica-medium-o-normal--12-*-*-*-*-*-*-*"),
1503   PFONT(NAME_oblique, 14,
1504 	"-*-helvetica-medium-o-normal--14-*-*-*-*-*-*-*"),
1505   PFONT(NAME_oblique, 18,
1506 	"-*-helvetica-medium-o-normal--18-*-*-*-*-*-*-*"),
1507   PFONT(NAME_oblique, 24,
1508 	"-*-helvetica-medium-o-normal--24-*-*-*-*-*-*-*"),
1509   ENDFONTLIST
1510 };
1511 
1512 
1513 static fontdef times_fonts[] =
1514 { PFONT(NAME_roman, 10,
1515 	"-*-times-medium-r-normal--10-*-*-*-*-*-*-*"),
1516   PFONT(NAME_roman, 12,
1517 	"-*-times-medium-r-normal--12-*-*-*-*-*-*-*"),
1518   PFONT(NAME_roman, 14,
1519 	"-*-times-medium-r-normal--14-*-*-*-*-*-*-*"),
1520   PFONT(NAME_roman, 18,
1521 	"-*-times-medium-r-normal--18-*-*-*-*-*-*-*"),
1522   PFONT(NAME_roman, 24,
1523 	"-*-times-medium-r-normal--24-*-*-*-*-*-*-*"),
1524   PFONT(NAME_bold, 10,
1525 	"-*-times-bold-r-normal--10-*-*-*-*-*-*-*"),
1526   PFONT(NAME_bold, 12,
1527 	"-*-times-bold-r-normal--12-*-*-*-*-*-*-*"),
1528   PFONT(NAME_bold, 14,
1529 	"-*-times-bold-r-normal--14-*-*-*-*-*-*-*"),
1530   PFONT(NAME_bold, 18,
1531 	"-*-times-bold-r-normal--18-*-*-*-*-*-*-*"),
1532   PFONT(NAME_bold, 24,
1533 	"-*-times-bold-r-normal--24-*-*-*-*-*-*-*"),
1534   PFONT(NAME_italic, 10,
1535 	"-*-times-medium-i-normal--10-*-*-*-*-*-*-*"),
1536   PFONT(NAME_italic, 12,
1537 	"-*-times-medium-i-normal--12-*-*-*-*-*-*-*"),
1538   PFONT(NAME_italic, 14,
1539 	"-*-times-medium-i-normal--14-*-*-*-*-*-*-*"),
1540   PFONT(NAME_italic, 18,
1541 	"-*-times-medium-i-normal--18-*-*-*-*-*-*-*"),
1542   PFONT(NAME_italic, 24,
1543 	"-*-times-medium-i-normal--24-*-*-*-*-*-*-*"),
1544   ENDFONTLIST
1545 };
1546 
1547 
1548 static char *
default_font_list(Name fam,FontDef defs)1549 default_font_list(Name fam, FontDef defs)
1550 { char buf[10240];
1551   char *s = buf;
1552 
1553   *s++ = '[';
1554 
1555   while(defs->style)
1556   {
1557     if ( defs->xname )
1558     { sprintf(s, "font(%s, %s, %d, \"%s\")",
1559 	      strName(fam),
1560 	      strName(defs->style),
1561 	      defs->points,
1562 	      defs->xname);
1563     } else
1564     { sprintf(s, "font(%s, %s, %d)",
1565 	      strName(fam),
1566 	      strName(defs->style),
1567 	      defs->points);
1568     }
1569     s += strlen(s);
1570     defs++;
1571     if ( defs->style )
1572       strcpy(s, ",\n");
1573     s += strlen(s);
1574   }
1575 
1576   *s++ = ']';
1577   *s = EOS;
1578 
1579   return save_string(buf);
1580 }
1581 
1582 
1583 static void
attach_fonts(Class class,char * res,Name fam,FontDef defs)1584 attach_fonts(Class class, char *res, Name fam, FontDef defs)
1585 { attach_class_variable(class, CtoName(res), "chain",
1586 			default_font_list(fam, defs),
1587 			"Font family set");
1588 }
1589 
1590 
1591 static void
attach_font_families(Class class)1592 attach_font_families(Class class)
1593 { attach_class_variable(class, NAME_fontFamilies,  "chain",
1594 			"[screen_fonts,courier_fonts,"
1595 			"helvetica_fonts,times_fonts]",
1596 			"Predefined font families");
1597 
1598   attach_fonts(class, "courier_fonts",	 NAME_courier,	 courier_fonts);
1599   attach_fonts(class, "helvetica_fonts", NAME_helvetica, helvetica_fonts);
1600   attach_fonts(class, "times_fonts",	 NAME_times,	 times_fonts);
1601   attach_fonts(class, "screen_fonts",	 NAME_screen,	 screen_fonts);
1602 }
1603