1 /* x11.c: X11 window interface for Metafont, using Xt. Original by
2 rusty@garnet.berkeley.edu. */
3
4 #define EXTERN extern
5 #include "../mfd.h"
6
7 #ifdef X11WIN /* almost whole file */
8
9 /* For wchar_t et al., that the X files might want. */
10 #include <kpathsea/systypes.h>
11
12 #undef input /* the XWMHints structure has a field named `input' */
13 #undef output
14 #include <X11/Xlib.h>
15 #include <X11/Intrinsic.h>
16 #include <X11/StringDefs.h>
17 #undef wchar_t
18
19 #define PLANE 0
20
21 static unsigned int mf_defwidth = 0;
22 static unsigned int mf_defheight = 0;
23
24 static Display *mf_display;
25 static Window mf_window;
26
27 static Pixmap mf_pixmap;
28
29 static XtAppContext mf_app;
30
31 static GC mf_dgc; /* draw gc */
32 static GC mf_egc; /* erase gc */
33 static GC mf_cgc; /* copy plane gc */
34
35 typedef struct
36 {
37 unsigned int mf_width, mf_height;
38 Pixel mf_fg, mf_bg;
39 } mf_resources_struct;
40
41 static mf_resources_struct mf_x11_resources;
42
43
44 /* Don't paint anything until we're mapped. */
45 static Boolean mf_mapped;
46
47 #ifdef MF_XT_DEBUG
48 static int mf_max_x, mf_max_y;
49 static int mf_min_x, mf_min_y;
50
51 static void mf_checkextent ();
52 #endif
53
54 static XtResource mf_resources[]
55 = { { "width", "Width", XtRInt, sizeof (int),
56 XtOffset (mf_resources_struct *, mf_width), XtRInt,
57 (XtPointer) & mf_defwidth },
58
59 { "height", "Height", XtRInt, sizeof (int),
60 XtOffset (mf_resources_struct *, mf_height), XtRInt,
61 (XtPointer) &mf_defheight },
62
63 { "foreground", "Foreground", XtRPixel, sizeof (Pixel),
64 XtOffset (mf_resources_struct *, mf_fg),
65 XtRString, (XtPointer) "Black" },
66
67 { "background", "Background", XtRPixel, sizeof (Pixel),
68 XtOffset (mf_resources_struct *, mf_bg), XtRString,
69 (XtPointer) "White" },
70 };
71
72 /* Maybe someday we'll read options, until then, this is just here for
73 the resources. */
74 static XrmOptionDescRec mf_optiondesclist[]
75 = { { "-width", "width", XrmoptionSepArg, (XPointer) NULL },
76 { "-height", "height", XrmoptionSepArg, (XPointer) NULL },
77 { "-fg", "foreground", XrmoptionSepArg, (XPointer) NULL },
78 { "-bg", "background", XrmoptionSepArg, (XPointer) NULL },
79 };
80
81 static void mf_events(void);
82 static void mf_mapstatus(Widget w, XtPointer data, XEvent *ev);
83 static void mf_newpixmap(unsigned int width, unsigned int height);
84 static void mf_redraw(void);
85 static void mf_repaint(Widget w, XtPointer data, XEvent *ev);
86
87 #include <mfdisplay.h>
88
89 /* Return 1 if display opened successfully, else 0. */
90
91 int
mf_x11_initscreen(void)92 mf_x11_initscreen (void)
93 {
94 XSetWindowAttributes xwa;
95 Widget mf_toplevel;
96 Widget mf_canvas;
97 XGCValues gcv;
98 Arg args[1];
99 int mf_argc;
100 char *mf_argv[2];
101
102 mf_argv[0] = "mf";
103 mf_argv[1] = NULL;
104 mf_argc = 1;
105
106 mf_toplevel = XtInitialize ("mf", "Metafont",
107 mf_optiondesclist,
108 XtNumber (mf_optiondesclist),
109 &mf_argc, mf_argv);
110
111 XtGetApplicationResources (mf_toplevel, (XtPointer) & mf_x11_resources,
112 mf_resources, XtNumber (mf_resources),
113 NULL, 0);
114
115 if (mf_argc != 1)
116 {
117 fprintf (stderr, "Usage: %s\n", mf_argv[0]);
118 return 0;
119 }
120
121 /* If nothing specified in their resources (e.g., .Xdefaults)
122 then use the values of Metafont's "screen". */
123 if (mf_x11_resources.mf_width == 0)
124 mf_x11_resources.mf_width = screenwidth;
125 if (mf_x11_resources.mf_height == 0)
126 mf_x11_resources.mf_height = screendepth;
127
128 mf_canvas = XtCreateManagedWidget ("canvas", widgetClass, mf_toplevel,
129 NULL, 0);
130
131 XtSetArg (args[0], XtNwidth, mf_x11_resources.mf_width);
132 XtSetValues (mf_canvas, args, 1);
133 XtSetArg (args[0], XtNheight, mf_x11_resources.mf_height);
134 XtSetValues (mf_canvas, args, 1);
135
136 /* for mf_x11_updatescreen() */
137 mf_app = XtWidgetToApplicationContext (mf_canvas);
138
139 XtAddEventHandler (mf_canvas, (Cardinal) ExposureMask, True,
140 (XtEventHandler) mf_repaint, NULL);
141 XtAddEventHandler (mf_canvas, (Cardinal) StructureNotifyMask, True,
142 (XtEventHandler) mf_mapstatus, NULL);
143
144 XtRealizeWidget (mf_toplevel);
145
146 mf_display = XtDisplay (mf_canvas);
147 mf_window = XtWindow (mf_canvas);
148
149 /* Since Metafont isn't your typical x window program that
150 sits in XTMainLoop, if the server supports backing store
151 and save unders this will help keep the output looking
152 nice. */
153 xwa.backing_store = Always;
154 xwa.save_under = True;
155 XChangeWindowAttributes (mf_display, mf_window,
156 CWBackingStore | CWSaveUnder, &xwa);
157
158 gcv.background = mf_x11_resources.mf_bg;
159 gcv.foreground = mf_x11_resources.mf_fg;
160 gcv.function = GXcopy;
161
162 /* copy plane gc */
163 mf_cgc = XCreateGC (mf_display, mf_window,
164 GCForeground | GCBackground | GCFunction, &gcv);
165
166 mf_newpixmap (screenwidth > mf_x11_resources.mf_width
167 ? screenwidth : mf_x11_resources.mf_width,
168 screendepth > mf_x11_resources.mf_height
169 ? screendepth : mf_x11_resources.mf_height);
170
171 return 1;
172 }
173
174 void
mf_x11_updatescreen(void)175 mf_x11_updatescreen (void)
176 {
177 mf_events ();
178 mf_redraw ();
179
180 #ifdef MF_XT_DEBUG
181 printf ("max_x=%d, min_x=%d, max_y=%d, min_y=%d\n",
182 mf_max_x, mf_min_x,
183 mf_max_y, mf_min_y);
184 #endif
185 }
186
187
188 void
mf_x11_blankrectangle(screencol left,screencol right,screenrow top,screenrow bottom)189 mf_x11_blankrectangle(screencol left,
190 screencol right,
191 screenrow top,
192 screenrow bottom)
193 {
194 XFillRectangle (mf_display, mf_pixmap, mf_egc, (int) left, (int) top,
195 (int) (right - left + 1), (int) (bottom - top + 1));
196 mf_events ();
197 }
198
199 void
mf_x11_paintrow(screenrow row,pixelcolor init_color,transspec tvect,screencol vector_size)200 mf_x11_paintrow(screenrow row,
201 pixelcolor init_color,
202 transspec tvect,
203 screencol vector_size)
204 {
205 GC gc;
206 int col;
207
208 gc = (init_color == 0) ? mf_egc : mf_dgc;
209
210 do
211 {
212 col = *tvect++;
213
214 #ifdef MF_XT_DEBUG
215 mf_checkextent (col, *tvect, row);
216 #endif /* MF_XT_DEBUG */
217
218 XDrawLine (mf_display, mf_pixmap, gc, col, (int) row,
219 (int) *tvect, (int) row);
220
221 gc = (gc == mf_egc) ? mf_dgc : mf_egc;
222 }
223 while (--vector_size > 0);
224
225 mf_events ();
226 }
227
228 #ifdef MF_XT_DEBUG
229 static void
mf_checkextent(int x1,int x2,int y)230 mf_checkextent(int x1, int x2, int y)
231 {
232 if (x1 < mf_min_x)
233 mf_min_x = x1;
234 if (x1 > mf_max_x)
235 mf_max_x = x1;
236
237 if (x2 < mf_min_x)
238 mf_min_x = x2;
239 if (x2 > mf_max_x)
240 mf_max_x = x2;
241
242 if (y > mf_max_y)
243 mf_max_y = y;
244 if (y < mf_min_y)
245 mf_min_y = y;
246 }
247 #endif /* MF_XT_DEBUG */
248
249 static void
mf_events(void)250 mf_events (void)
251 {
252 XEvent event;
253
254 if (XtAppPending (mf_app) != 0)
255 {
256 while (XtAppPending (mf_app) != 0)
257 {
258 XtAppNextEvent (mf_app, &event);
259 XtDispatchEvent (&event);
260 }
261 }
262 }
263
264 static void
mf_newpixmap(unsigned int width,unsigned int height)265 mf_newpixmap(unsigned int width, unsigned int height)
266 {
267 XGCValues gcv;
268 Pixmap newpixmap;
269
270 /* width == mf_width and height == mf_height
271 the first time mf_newpixmap() is called.
272 */
273 if (width < mf_x11_resources.mf_width && height < mf_x11_resources.mf_height)
274 return;
275
276 newpixmap = XCreatePixmap (mf_display, mf_window, width, height, 1);
277
278 gcv.background = 0;
279 gcv.foreground = 1;
280
281 if (mf_dgc != 0)
282 XFreeGC (mf_display, mf_dgc);
283
284 /* draw gc */
285 gcv.line_width = 1;
286 mf_dgc = XCreateGC (mf_display, newpixmap,
287 GCForeground | GCBackground | GCLineWidth, &gcv);
288
289 if (mf_egc != 0)
290 XFreeGC (mf_display, mf_egc);
291
292 /* erase gc */
293 gcv.foreground = 0;
294 mf_egc = XCreateGC (mf_display, newpixmap,
295 GCForeground | GCBackground | GCLineWidth, &gcv);
296
297 XFillRectangle (mf_display, newpixmap, mf_egc, 0, 0, width, height);
298
299 if (mf_pixmap != 0)
300 {
301 XCopyArea (mf_display, mf_pixmap, newpixmap, mf_dgc, 0, 0,
302 mf_x11_resources.mf_width,
303 mf_x11_resources.mf_height, 0, 0);
304
305 XFreePixmap (mf_display, mf_pixmap);
306 }
307
308 mf_pixmap = newpixmap;
309
310 mf_x11_resources.mf_width = width;
311 mf_x11_resources.mf_height = height;
312 }
313
314 static void
mf_repaint(Widget w,XtPointer data,XEvent * ev)315 mf_repaint(Widget w, XtPointer data, XEvent *ev)
316 {
317 if (!mf_mapped || !ev || ev->type != Expose)
318 return;
319
320 /* We are a ``simple application''. */
321 if (ev->xexpose.count == 0)
322 {
323 XEvent event;
324
325 /* skip all excess redraws */
326 while (XCheckTypedEvent (mf_display, Expose, &event) != False)
327 continue;
328
329 mf_redraw ();
330 }
331 }
332
333
334 static void
mf_mapstatus(Widget w,XtPointer data,XEvent * ev)335 mf_mapstatus(Widget w, XtPointer data, XEvent *ev)
336 {
337 switch (ev->type)
338 {
339 case MapNotify:
340 mf_mapped = True;
341 break;
342
343 case UnmapNotify:
344 mf_mapped = False;
345 break;
346
347 case ConfigureNotify:
348 mf_newpixmap (ev->xconfigure.width, ev->xconfigure.height);
349 mf_redraw ();
350 break;
351 }
352 }
353
354
355 static void
mf_redraw(void)356 mf_redraw (void)
357 {
358 XCopyPlane (mf_display, mf_pixmap, mf_window, mf_cgc, 0, 0,
359 mf_x11_resources.mf_width, mf_x11_resources.mf_height,
360 0, 0, (unsigned long) 1);
361
362 XFlush (mf_display);
363 }
364
365 #else
366 int x11_dummy;
367 #endif /* X11WIN */
368