1 #ifndef lint
2 static char *rcsid = "$Id: ConvDisp.c,v 1.19 1992/08/05 01:51:35 ishisone Rel $";
3 #endif
4 /*
5  * Copyright (c) 1990  Software Research Associates, Inc.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation for any purpose and without fee is hereby granted, provided
9  * that the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Software Research Associates not be
12  * used in advertising or publicity pertaining to distribution of the
13  * software without specific, written prior permission.  Software Research
14  * Associates makes no representations about the suitability of this software
15  * for any purpose.  It is provided "as is" without express or implied
16  * warranty.
17  *
18  * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
19  */
20 
21 #include <X11/IntrinsicP.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xmu/Atoms.h>
24 #include <X11/Xmu/Converters.h>
25 #include "CachedAtom.h"
26 #include "ConvDispP.h"
27 
28 #define DEBUG_VAR debug_ConvDisplay
29 #include "DebugPrint.h"
30 
31 static XtResource resources[] = {
32 #define offset(field) XtOffset(ConvDisplayObject, convDisplay.field)
33     { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
34 	offset(foreground), XtRString, XtDefaultForeground },
35     { XtNbackground, XtCBackground, XtRPixel, sizeof (Pixel),
36 	offset(background), XtRString, XtDefaultBackground },
37     { XtNcursorBitmap, XtCCursorBitmap, XtRBitmap, sizeof (Pixmap),
38 	offset(cursor), XtRImmediate, None },
39     { XtNhotX, XtCHotX, XtRPosition, sizeof (Position),
40 	offset(hotx), XtRString, "3" },
41     { XtNhotY, XtCHotY, XtRPosition, sizeof (Position),
42 	offset(hoty), XtRString, "2" },
43 #undef offset
44 };
45 
46 static void ClassInitialize();
47 static void ClassPartInitialize();
48 
49 static void Initialize();
50 static void Destroy();
51 static Boolean SetValues();
52 
53 static Pixmap DefaultCursor();
54 static void GetGC();
55 static void ComputeBounds();
56 
57 static int StringWidth();
58 static int LineHeight();
59 static void DrawString();
60 static int MaxChar();
61 static void DrawCursor();
62 static void GetCursorBounds();
63 static void SetFonts();
64 
65 ConvDisplayClassRec convDisplayClassRec = {
66   { /* object fields */
67     /* superclass		*/	(WidgetClass) &objectClassRec,
68     /* class_name		*/	"ConvDisplay",
69     /* widget_size		*/	sizeof(ConvDisplayRec),
70     /* class_initialize		*/	ClassInitialize,
71     /* class_part_initialize	*/	ClassPartInitialize,
72     /* class_inited		*/	FALSE,
73     /* initialize		*/	Initialize,
74     /* initialize_hook		*/	NULL,
75     /* obj1			*/	NULL,
76     /* obj2			*/	NULL,
77     /* obj3			*/	0,
78     /* resources		*/	resources,
79     /* num_resources		*/	XtNumber(resources),
80     /* xrm_class		*/	NULLQUARK,
81     /* obj4			*/	FALSE,
82     /* obj5			*/	FALSE,
83     /* obj6			*/	FALSE,
84     /* obj7			*/	FALSE,
85     /* destroy			*/	Destroy,
86     /* obj8			*/	NULL,
87     /* obj9			*/	NULL,
88     /* set_values		*/	SetValues,
89     /* set_values_hook		*/	NULL,
90     /* obj10			*/	NULL,
91     /* get_values_hook		*/	NULL,
92     /* obj11			*/	NULL,
93     /* version			*/	XtVersion,
94     /* callback_private		*/	NULL,
95     /* obj12			*/	NULL,
96     /* obj13			*/	NULL,
97     /* obj14			*/	NULL,
98     /* extension		*/	NULL
99   },
100   { /* convDisplay fields */
101     /* StringWidth		*/	StringWidth,
102     /* LineHeight		*/	LineHeight,
103     /* DrawString		*/	DrawString,
104     /* MaxChar			*/	MaxChar,
105     /* DrawCursor		*/	DrawCursor,
106     /* GetCursorBounds		*/	GetCursorBounds,
107     /* SetFonts			*/	SetFonts,
108   }
109 };
110 
111 WidgetClass convDisplayObjectClass = (WidgetClass)&convDisplayClassRec;
112 
113 static void
ClassInitialize()114 ClassInitialize()
115 {
116     static XtConvertArgRec screenConvertArg[] = {
117         { XtBaseOffset, (caddr_t) XtOffset(Widget, core.screen),
118 	   sizeof(Screen *) }
119     };
120 
121     /* add string->bitmap converter (for insert-cursor) */
122     XtAddConverter("String", "Bitmap", XmuCvtStringToBitmap,
123                    screenConvertArg, XtNumber(screenConvertArg));
124 }
125 
126 static void
ClassPartInitialize(cl)127 ClassPartInitialize(cl)
128 WidgetClass cl;
129 {
130     ConvDisplayObjectClass class = (ConvDisplayObjectClass)cl;
131     ConvDisplayObjectClass super = (ConvDisplayObjectClass)class->object_class.superclass;
132     ConvDisplayClassPart *classpart = &(class->convDisplay_class);
133     ConvDisplayClassPart *superpart = &(super->convDisplay_class);
134 
135     if (classpart->StringWidth == XtInheritStringWidth)
136 	classpart->StringWidth = superpart->StringWidth;
137     if (classpart->LineHeight == XtInheritLineHeight)
138 	classpart->LineHeight = superpart->LineHeight;
139     if (classpart->DrawString == XtInheritDrawString)
140 	classpart->DrawString = superpart->DrawString;
141     if (classpart->MaxChar == XtInheritMaxChar)
142 	classpart->MaxChar = superpart->MaxChar;
143     if (classpart->DrawCursor == XtInheritDrawCursor)
144 	classpart->DrawCursor = superpart->DrawCursor;
145     if (classpart->GetCursorBounds == XtInheritGetCursorBounds)
146 	classpart->GetCursorBounds = superpart->GetCursorBounds;
147     if (classpart->SetFonts == XtInheritSetFonts)
148 	classpart->SetFonts = superpart->SetFonts;
149 }
150 
151 /* ARGSUSED */
152 static void
Initialize(req,new,args,num_args)153 Initialize(req, new, args, num_args)
154 Widget req;
155 Widget new;
156 ArgList args;
157 Cardinal *num_args;
158 {
159     ConvDisplayObject obj = (ConvDisplayObject)new;
160 
161     if (obj->convDisplay.cursor == None) {
162 	obj->convDisplay.cursor = DefaultCursor(obj);
163 	obj->convDisplay.cursorcreated = True;
164     } else {
165 	obj->convDisplay.cursorcreated = False;
166     }
167     obj->convDisplay.cursorvisible = False;
168     GetGC(obj);
169     ComputeBounds(obj);
170 }
171 
172 static void
Destroy(w)173 Destroy(w)
174 Widget w;
175 {
176     ConvDisplayObject obj = (ConvDisplayObject)w;
177 
178     XtReleaseGC(w, obj->convDisplay.cursorgc);
179     if (obj->convDisplay.cursorcreated == True) {
180 	XFreePixmap(XtDisplayOfObject(w), obj->convDisplay.cursor);
181     }
182 }
183 
184 /* ARGSUSED */
185 static Boolean
SetValues(cur,req,wid,args,num_args)186 SetValues(cur, req, wid, args, num_args)
187 Widget cur;
188 Widget req;
189 Widget wid;
190 ArgList args;
191 Cardinal *num_args;
192 {
193     ConvDisplayObject new = (ConvDisplayObject)wid;
194     ConvDisplayObject old = (ConvDisplayObject)cur;
195 
196     if (new->convDisplay.foreground != old->convDisplay.foreground ||
197 	new->convDisplay.background != old->convDisplay.background) {
198 	XtReleaseGC(wid, old->convDisplay.cursorgc);
199 	GetGC(new);
200     }
201 
202     if (new->convDisplay.cursor != old->convDisplay.cursor ||
203 	new->convDisplay.hotx != old->convDisplay.hotx ||
204 	new->convDisplay.hoty != old->convDisplay.hoty) {
205 	if (new->convDisplay.cursor != old->convDisplay.cursor &&
206 	    old->convDisplay.cursorcreated) {
207 	    XFreePixmap(XtDisplayOfObject(wid), old->convDisplay.cursor);
208 	    new->convDisplay.cursorcreated = False;
209 	}
210 	ComputeBounds(new);
211     }
212 
213     return False;
214 }
215 
216 static Pixmap
DefaultCursor(obj)217 DefaultCursor(obj)
218 ConvDisplayObject obj;
219 {
220     static char default_bits[] = { 0x0c, 0x0c, 0x1e, 0x3f, 0x33 };
221     return XCreateBitmapFromData(XtDisplayOfObject((Widget)obj),
222 				 RootWindowOfScreen(XtScreenOfObject((Widget)obj)),
223 				 default_bits,
224 				 6, 5);
225 }
226 
227 static void
GetGC(obj)228 GetGC(obj)
229 ConvDisplayObject obj;
230 {
231     XtGCMask mask = GCFunction|GCForeground|GCBackground;
232     XGCValues values;
233 
234     values.function = GXxor;
235     values.foreground = obj->convDisplay.foreground ^ obj->convDisplay.background;
236     values.background = 0;
237     obj->convDisplay.cursorgc = XtGetGC((Widget)obj, mask, &values);
238 }
239 
240 static void
ComputeBounds(obj)241 ComputeBounds(obj)
242 ConvDisplayObject obj;
243 {
244     unsigned int width, height;
245     Window junkroot;
246     int junkx, junky;
247     unsigned int junkbw, junkdepth;
248 
249     if (obj->convDisplay.cursor == None ||
250 	!XGetGeometry(XtDisplayOfObject((Widget)obj), obj->convDisplay.cursor,
251 		      &junkroot, &junkx, &junky, &width, &height,
252 		      &junkbw, &junkdepth)) {
253 	obj->convDisplay.cursor = None;
254 	width = height = 0;
255     }
256     obj->convDisplay.cursorbounds.width = width;
257     obj->convDisplay.cursorbounds.height = height;
258     obj->convDisplay.cursorbounds.x = -obj->convDisplay.hotx;
259     obj->convDisplay.cursorbounds.y = -obj->convDisplay.hoty;
260 }
261 
262 /* ARGSUSED */
263 static int
StringWidth(w,str,start,end)264 StringWidth(w, str, start, end)
265 Widget w;
266 ICString *str;
267 int start;
268 int end;
269 {
270     XtAppError(XtWidgetToApplicationContext(w),
271 	       "ConvDisplay Object: StringWidth function isn't defined.");
272     return 0;	/* for lint */
273 }
274 
275 /* ARGSUSED */
276 static int
LineHeight(w,ascentp)277 LineHeight(w, ascentp)
278 Widget w;
279 Position *ascentp;
280 {
281     XtAppError(XtWidgetToApplicationContext(w),
282 	       "ConvDisplay Object: LineHeight function isn't defined.");
283     return 0;	/* for lint */
284 }
285 
286 /* ARGSUSED */
287 static void
DrawString(w,canvas,str,start,end,x,y)288 DrawString(w, canvas, str, start, end, x, y)
289 Widget w;
290 Widget canvas;
291 ICString *str;
292 int start;
293 int end;
294 int x;
295 int y;
296 {
297     XtAppError(XtWidgetToApplicationContext(w),
298 	       "ConvDisplay Object: DrawString function isn't defined.");
299 }
300 
301 /* ARGSUSED */
302 static int
MaxChar(w,str,start,width)303 MaxChar(w, str, start, width)
304 Widget w;
305 ICString *str;
306 int start;
307 int width;
308 {
309     XtAppError(XtWidgetToApplicationContext(w),
310 	       "ConvDisplay Object: MaxChar function isn't defined.");
311     return 0;	/* for lint */
312 }
313 
314 static void
DrawCursor(w,canvas,x,y,on)315 DrawCursor(w, canvas, x, y, on)
316 Widget w;
317 Widget canvas;
318 int x;
319 int y;
320 int on;
321 {
322     ConvDisplayObject obj = (ConvDisplayObject)w;
323 
324     if (!XtIsRealized(canvas) ||
325 	obj->convDisplay.cursor == None ||
326 	(obj->convDisplay.cursorvisible && on) ||
327 	(!obj->convDisplay.cursorvisible && !on)) {
328 	obj->convDisplay.cursorvisible = (on != 0);
329 	return;
330     }
331 
332     XCopyPlane(XtDisplay(canvas),
333 	       obj->convDisplay.cursor, XtWindow(canvas),
334 	       obj->convDisplay.cursorgc,
335 	       0, 0,
336 	       obj->convDisplay.cursorbounds.width,
337 	       obj->convDisplay.cursorbounds.height,
338 	       x + obj->convDisplay.cursorbounds.x,
339 	       y + obj->convDisplay.cursorbounds.y,
340 	       1L);
341     obj->convDisplay.cursorvisible = (on != 0);
342 }
343 
344 static void
GetCursorBounds(w,bounds)345 GetCursorBounds(w, bounds)
346 Widget w;
347 XRectangle *bounds;
348 {
349     ConvDisplayObject obj = (ConvDisplayObject)w;
350 
351      bounds->x = obj->convDisplay.cursorbounds.x;
352      bounds->y = obj->convDisplay.cursorbounds.y;
353      bounds->width = obj->convDisplay.cursorbounds.width;
354      bounds->height = obj->convDisplay.cursorbounds.height;
355 }
356 
357 /* ARGSUSED */
358 static void
SetFonts(w,fonts,num_fonts)359 SetFonts(w, fonts, num_fonts)
360 Widget w;
361 XFontStruct **fonts;
362 Cardinal num_fonts;
363 {
364     XtAppError(XtWidgetToApplicationContext(w),
365 	       "ConvDisplay Object: SetFonts function isn't defined.");
366 }
367 
368 
369 /*
370  * public functions
371  */
372 
373 int
CDStringWidth(w,str,start,end)374 CDStringWidth(w, str, start, end)
375 Widget w;
376 ICString *str;
377 int start;
378 int end;
379 {
380     ConvDisplayObjectClass class = (ConvDisplayObjectClass)w->core.widget_class;
381 
382     XtCheckSubclass(w, convDisplayObjectClass, "CDStringWidth()");
383     return (*class->convDisplay_class.StringWidth)(w, str, start, end);
384 }
385 
386 int
CDLineHeight(w,ascent)387 CDLineHeight(w, ascent)
388 Widget w;
389 Position *ascent;
390 {
391     ConvDisplayObjectClass class = (ConvDisplayObjectClass)w->core.widget_class;
392 
393     XtCheckSubclass(w, convDisplayObjectClass, "CDLineHeight()");
394     return (*class->convDisplay_class.LineHeight)(w, ascent);
395 }
396 
397 void
CDDrawString(w,canvas,str,start,end,x,y)398 CDDrawString(w, canvas, str, start, end, x, y)
399 Widget w;
400 Widget canvas;
401 ICString *str;
402 int start;
403 int end;
404 int x;
405 int y;
406 {
407     ConvDisplayObjectClass class = (ConvDisplayObjectClass)w->core.widget_class;
408 
409     XtCheckSubclass(w, convDisplayObjectClass, "CDDrawString()");
410     (*class->convDisplay_class.DrawString)(w, canvas, str, start, end, x, y);
411 }
412 
413 int
CDMaxChar(w,str,start,width)414 CDMaxChar(w, str, start, width)
415 Widget w;
416 ICString *str;
417 int start;
418 int width;
419 {
420     ConvDisplayObjectClass class = (ConvDisplayObjectClass)w->core.widget_class;
421 
422     XtCheckSubclass(w, convDisplayObjectClass, "CDMaxChar()");
423     return (*class->convDisplay_class.MaxChar)(w, str, start, width);
424 }
425 
426 void
CDDrawCursor(w,canvas,x,y,on)427 CDDrawCursor(w, canvas, x, y, on)
428 Widget w;
429 Widget canvas;
430 int x;
431 int y;
432 int on;
433 {
434     ConvDisplayObjectClass class = (ConvDisplayObjectClass)w->core.widget_class;
435 
436     XtCheckSubclass(w, convDisplayObjectClass, "CDDrawCursor()");
437     (*class->convDisplay_class.DrawCursor)(w, canvas, x, y, on);
438 }
439 
440 void
CDGetCursorBounds(w,bounds)441 CDGetCursorBounds(w, bounds)
442 Widget w;
443 XRectangle *bounds;
444 {
445     ConvDisplayObjectClass class = (ConvDisplayObjectClass)w->core.widget_class;
446 
447     XtCheckSubclass(w, convDisplayObjectClass, "CDGetCursorBounds()");
448     (*class->convDisplay_class.GetCursorBounds)(w, bounds);
449 }
450 
451 void
CDSetFonts(w,fonts,num_fonts)452 CDSetFonts(w, fonts, num_fonts)
453 Widget w;
454 XFontStruct **fonts;
455 Cardinal num_fonts;
456 {
457     ConvDisplayObjectClass class = (ConvDisplayObjectClass)w->core.widget_class;
458 
459     XtCheckSubclass(w, convDisplayObjectClass, "CDSetFonts()");
460     (*class->convDisplay_class.SetFonts)(w, fonts, num_fonts);
461 }
462 
463 
464 void
CDSetBlockCursor(w,shape)465 CDSetBlockCursor(w, shape)
466 Widget w;
467 XRectangle *shape;
468 {
469     ConvDisplayObject obj = (ConvDisplayObject)w;
470     Display *dpy = XtDisplayOfObject((Widget)obj);
471     Pixmap block;
472     GC tmpgc;
473     XGCValues values;
474 
475     XtCheckSubclass(w, convDisplayObjectClass, "CDMakeBlockCursor()");
476 
477     block = XCreatePixmap(dpy,
478 			  RootWindowOfScreen(XtScreenOfObject((Widget)obj)),
479 			  shape->width, shape->height, 1);
480 
481     values.function = GXset;
482     tmpgc = XtGetGC(w, GCFunction, &values);
483     XFillRectangle(dpy, block, tmpgc, 0, 0, shape->width, shape->height);
484     XtReleaseGC(w, tmpgc);
485 
486     XtVaSetValues(w,
487 		  XtNcursorBitmap, block,
488 		  XtNhotX, -shape->x,
489 		  XtNhotY, -shape->y,
490 		  NULL);
491 }
492 
493 
494 /*
495  * semi-public function (for subclass use)
496  */
497 
498 int
_CDPickupFonts(widget,fontspecs,num_specs,fonts,num_fonts)499 _CDPickupFonts(widget, fontspecs, num_specs, fonts, num_fonts)
500 Widget widget;
501 FontSpec *fontspecs;
502 Cardinal num_specs;
503 XFontStruct **fonts;
504 Cardinal num_fonts;
505 {
506     Display *dpy = XtDisplayOfObject(widget);
507     Atom cs_reg = CachedInternAtom(dpy, "CHARSET_REGISTRY", False);
508     Atom cs_enc = CachedInternAtom(dpy, "CHARSET_ENCODING", False);
509     Atom atom;
510     Cardinal i, j;
511     FontSpec *fsp;
512     int npick;
513 
514     DPRINT(("_CDPickupFonts()\n"));
515 
516     /* pickup fonts */
517     npick = 0;
518     for (i = 0, fsp = fontspecs; i < num_specs; i++, fsp++) {
519 	DPRINT(("\tlooking for a font..."));
520 
521 	fsp->font = NULL;
522 	for (j = 0; j < num_fonts; j++) {
523 	    if (fonts[j] != NULL &&
524 		XGetFontProperty(fonts[j], cs_reg, (unsigned long *)&atom) &&
525 		atom == fsp->registry &&
526 		XGetFontProperty(fonts[j], cs_enc, (unsigned long *)&atom) &&
527 		atom == fsp->encoding) {
528 		DPRINT((" found"));
529 		fsp->font = fonts[j];
530 		npick++;
531 		break;
532 	    }
533 	}
534 	DPRINT(("\n"));
535     }
536 
537     return npick;
538 }
539