Back to index

tetex-bin  3.0
x11-Xt.c
Go to the documentation of this file.
00001 /* x11.c: X11 window interface for Metafont, using Xt.  Original by
00002    rusty@garnet.berkeley.edu.  */
00003 
00004 #define       EXTERN extern
00005 #include "../mfd.h"
00006 
00007 #ifdef X11WIN               /* almost whole file */
00008 
00009 /* For wchar_t et al., that the X files might want. */
00010 #include <kpathsea/systypes.h>
00011 
00012 /* See xdvik/xdvi.h for the purpose of the FOIL...  */
00013 #ifdef FOIL_X_WCHAR_T
00014 #define wchar_t foil_x_defining_wchar_t
00015 #define X_WCHAR
00016 #endif
00017 #undef input /* the XWMHints structure has a field named `input' */
00018 #undef output
00019 #include <X11/Xlib.h>
00020 #include <X11/Intrinsic.h>
00021 #include <X11/StringDefs.h>
00022 #undef wchar_t
00023 
00024 #define PLANE 0
00025 
00026 static unsigned int mf_defwidth = 0;
00027 static unsigned int mf_defheight = 0;
00028 
00029 static Display *mf_display;
00030 static Window mf_window;
00031 
00032 static Pixmap mf_pixmap;
00033 
00034 static XtAppContext mf_app;
00035 
00036 static GC mf_dgc;           /* draw gc */
00037 static GC mf_egc;           /* erase gc */
00038 static GC mf_cgc;           /* copy plane gc */
00039 
00040 typedef struct
00041 {
00042   unsigned int mf_width, mf_height;
00043   Pixel mf_fg, mf_bg;
00044 } mf_resources_struct;
00045 
00046 static mf_resources_struct mf_x11_resources;
00047 
00048 
00049 /* Don't paint anything until we're mapped.  */
00050 static Boolean mf_mapped;
00051 
00052 #ifdef MF_XT_DEBUG
00053 static int mf_max_x, mf_max_y;
00054 static int mf_min_x, mf_min_y;
00055 
00056 static void mf_checkextent ();
00057 #endif
00058 
00059 static XtResource mf_resources[]
00060   = { { "width", "Width", XtRInt, sizeof (int),
00061         XtOffset (mf_resources_struct *, mf_width), XtRInt,
00062         (XtPointer) & mf_defwidth },
00063 
00064       { "height", "Height", XtRInt, sizeof (int),
00065         XtOffset (mf_resources_struct *, mf_height), XtRInt,
00066         (XtPointer) &mf_defheight },
00067 
00068       { "foreground", "Foreground", XtRPixel, sizeof (Pixel),
00069         XtOffset (mf_resources_struct *, mf_fg),
00070         XtRString, (XtPointer) "Black" },
00071 
00072       { "background", "Background", XtRPixel, sizeof (Pixel),
00073         XtOffset (mf_resources_struct *, mf_bg), XtRString,
00074         (XtPointer) "White" },
00075 };
00076 
00077 /* Maybe someday we'll read options, until then, this is just here for
00078    the resources.  */
00079 static XrmOptionDescRec mf_optiondesclist[]
00080 = { { "-width",   "width", XrmoptionSepArg, (XPointer) NULL },
00081     { "-height", "height", XrmoptionSepArg, (XPointer) NULL },
00082     { "-fg", "foreground", XrmoptionSepArg, (XPointer) NULL },
00083     { "-bg", "background", XrmoptionSepArg, (XPointer) NULL },
00084 };
00085 
00086 static void mf_events ();
00087 static void mf_mapstatus ();
00088 static void mf_newpixmap P2H(unsigned int, unsigned int);
00089 static void mf_redraw ();
00090 static void mf_repaint ();
00091 
00092 /* Return 1 if display opened successfully, else 0.  */
00093 
00094 int
00095 mf_x11_initscreen ()
00096 {
00097   XSetWindowAttributes xwa;
00098   Widget mf_toplevel;
00099   Widget mf_canvas;
00100   XGCValues gcv;
00101   Arg args[1];
00102   int mf_argc;
00103   char *mf_argv[2];
00104 
00105   mf_argv[0] = "mf";
00106   mf_argv[1] = NULL;
00107   mf_argc = 1;
00108 
00109   mf_toplevel = XtInitialize ("mf", "Metafont",
00110                            mf_optiondesclist,
00111                            XtNumber (mf_optiondesclist),
00112                            &mf_argc, mf_argv);
00113 
00114   XtGetApplicationResources (mf_toplevel, (XtPointer) & mf_x11_resources,
00115                           mf_resources, XtNumber (mf_resources),
00116                           NULL, 0);
00117 
00118   if (mf_argc != 1)
00119     {
00120       fprintf (stderr, "Usage: %s\n", mf_argv[0]);
00121       return 0;
00122     }
00123 
00124   /* If nothing specified in their resources (e.g., .Xdefaults)
00125      then use the values of Metafont's "screen".  */
00126   if (mf_x11_resources.mf_width == 0)
00127     mf_x11_resources.mf_width = screenwidth;
00128   if (mf_x11_resources.mf_height == 0)
00129     mf_x11_resources.mf_height = screendepth;
00130 
00131   mf_canvas = XtCreateManagedWidget ("canvas", widgetClass, mf_toplevel,
00132                                  NULL, 0);
00133 
00134   XtSetArg (args[0], XtNwidth, mf_x11_resources.mf_width);
00135   XtSetValues (mf_canvas, args, 1);
00136   XtSetArg (args[0], XtNheight, mf_x11_resources.mf_height);
00137   XtSetValues (mf_canvas, args, 1);
00138 
00139   /* for mf_x11_updatescreen() */
00140   mf_app = XtWidgetToApplicationContext (mf_canvas);
00141 
00142   XtAddEventHandler (mf_canvas, (Cardinal) ExposureMask, True,
00143                    mf_repaint, NULL);
00144   XtAddEventHandler (mf_canvas, (Cardinal) StructureNotifyMask, True,
00145                    mf_mapstatus, NULL);
00146 
00147   XtRealizeWidget (mf_toplevel);
00148 
00149   mf_display = XtDisplay (mf_canvas);
00150   mf_window = XtWindow (mf_canvas);
00151 
00152   /* Since Metafont isn't your typical x window program that
00153      sits in XTMainLoop, if the server supports backing store
00154      and save unders this will help keep the output looking
00155      nice.  */
00156   xwa.backing_store = Always;
00157   xwa.save_under = True;
00158   XChangeWindowAttributes (mf_display, mf_window,
00159                         CWBackingStore | CWSaveUnder, &xwa);
00160 
00161   gcv.background = mf_x11_resources.mf_bg;
00162   gcv.foreground = mf_x11_resources.mf_fg;
00163   gcv.function = GXcopy;
00164 
00165   /* copy plane gc */
00166   mf_cgc = XCreateGC (mf_display, mf_window,
00167                     GCForeground | GCBackground | GCFunction, &gcv);
00168 
00169   mf_newpixmap (screenwidth > mf_x11_resources.mf_width
00170                 ? screenwidth : mf_x11_resources.mf_width,
00171               screendepth > mf_x11_resources.mf_height
00172                ? screendepth : mf_x11_resources.mf_height);
00173 
00174   return 1;
00175 }
00176 
00177 void
00178 mf_x11_updatescreen ()
00179 {
00180   mf_events ();
00181   mf_redraw ();
00182 
00183 #ifdef MF_XT_DEBUG
00184   printf ("max_x=%d, min_x=%d, max_y=%d, min_y=%d\n",
00185          mf_max_x, mf_min_x,
00186          mf_max_y, mf_min_y);
00187 #endif
00188 }
00189 
00190 
00191 void
00192 mf_x11_blankrectangle P4C(screencol, left,
00193                           screencol, right,
00194                           screenrow, top,
00195                           screenrow, bottom)
00196 {
00197   XFillRectangle (mf_display, mf_pixmap, mf_egc, (int) left, (int) top,
00198                 (int) (right - left + 1), (int) (bottom - top + 1));
00199   mf_events ();
00200 }
00201 
00202 void
00203 mf_x11_paintrow P4C(screenrow, row,
00204                     pixelcolor, init_color,
00205                     transspec, tvect,
00206                     register screencol, vector_size)
00207 {
00208   GC gc;
00209   int col;
00210 
00211   gc = (init_color == 0) ? mf_egc : mf_dgc;
00212 
00213   do
00214     {
00215       col = *tvect++;
00216 
00217 #ifdef MF_XT_DEBUG
00218       mf_checkextent (col, *tvect, row);
00219 #endif /* MF_XT_DEBUG */
00220 
00221       XDrawLine (mf_display, mf_pixmap, gc, col, (int) row,
00222                (int) *tvect, (int) row);
00223 
00224       gc = (gc == mf_egc) ? mf_dgc : mf_egc;
00225     }
00226   while (--vector_size > 0);
00227 
00228   mf_events ();
00229 }
00230 
00231 #ifdef MF_XT_DEBUG
00232 static void
00233 mf_checkextent P3C(int, x1, int, x2, int, y)
00234 {
00235   if (x1 < mf_min_x)
00236     mf_min_x = x1;
00237   if (x1 > mf_max_x)
00238     mf_max_x = x1;
00239 
00240   if (x2 < mf_min_x)
00241     mf_min_x = x2;
00242   if (x2 > mf_max_x)
00243     mf_max_x = x2;
00244 
00245   if (y > mf_max_y)
00246     mf_max_y = y;
00247   if (y < mf_min_y)
00248     mf_min_y = y;
00249 }
00250 #endif /* MF_XT_DEBUG */
00251 
00252 static void
00253 mf_events ()
00254 {
00255   XEvent event;
00256 
00257   if (XtAppPending (mf_app) != 0)
00258     {
00259       while (XtAppPending (mf_app) != 0)
00260        {
00261          XtAppNextEvent (mf_app, &event);
00262          XtDispatchEvent (&event);
00263        }
00264     }
00265 }
00266 
00267 static void
00268 mf_newpixmap P2C(unsigned int, width, unsigned int, height)
00269 {
00270   XGCValues gcv;
00271   Pixmap newpixmap;
00272 
00273   /* width == mf_width and height == mf_height
00274      the first time mf_newpixmap() is called.
00275    */
00276   if (width < mf_x11_resources.mf_width && height < mf_x11_resources.mf_height)
00277     return;
00278 
00279   newpixmap = XCreatePixmap (mf_display, mf_window, width, height, 1);
00280 
00281   gcv.background = 0;
00282   gcv.foreground = 1;
00283 
00284   if (mf_dgc != 0)
00285     XFreeGC (mf_display, mf_dgc);
00286 
00287   /* draw gc */
00288   gcv.line_width = 1;
00289   mf_dgc = XCreateGC (mf_display, newpixmap,
00290                     GCForeground | GCBackground | GCLineWidth, &gcv);
00291 
00292   if (mf_egc != 0)
00293     XFreeGC (mf_display, mf_egc);
00294 
00295   /* erase gc */
00296   gcv.foreground = 0;
00297   mf_egc = XCreateGC (mf_display, newpixmap,
00298                     GCForeground | GCBackground | GCLineWidth, &gcv);
00299 
00300   XFillRectangle (mf_display, newpixmap, mf_egc, 0, 0, width, height);
00301 
00302   if (mf_pixmap != 0)
00303     {
00304       XCopyArea (mf_display, mf_pixmap, newpixmap, mf_dgc, 0, 0,
00305                mf_x11_resources.mf_width,
00306                mf_x11_resources.mf_height, 0, 0);
00307 
00308       XFreePixmap (mf_display, mf_pixmap);
00309     }
00310 
00311   mf_pixmap = newpixmap;
00312 
00313   mf_x11_resources.mf_width = width;
00314   mf_x11_resources.mf_height = height;
00315 }
00316 
00317 static void
00318 mf_repaint P3C(Widget, w, XtPointer, data, XEvent*, ev)
00319 {
00320   if (!mf_mapped || !ev || ev->type != Expose)
00321     return;
00322 
00323   /* We are a ``simple application''. */
00324   if (ev->xexpose.count == 0)
00325     {
00326       XEvent event;
00327 
00328       /* skip all excess redraws */
00329       while (XCheckTypedEvent (mf_display, Expose, &event) != False)
00330        continue;
00331 
00332       mf_redraw ();
00333     }
00334 }
00335 
00336 
00337 static void
00338 mf_mapstatus P3C(Widget, w, XtPointer, data, XEvent*, ev)
00339 {
00340   switch (ev->type)
00341     {
00342     case MapNotify:
00343       mf_mapped = True;
00344       break;
00345     
00346     case UnmapNotify:
00347       mf_mapped = False;
00348       break;
00349 
00350     case ConfigureNotify:
00351       mf_newpixmap (ev->xconfigure.width, ev->xconfigure.height);
00352       mf_redraw ();
00353       break;
00354     }
00355 }
00356 
00357 
00358 static void
00359 mf_redraw ()
00360 {
00361   XCopyPlane (mf_display, mf_pixmap, mf_window, mf_cgc, 0, 0,
00362              mf_x11_resources.mf_width, mf_x11_resources.mf_height,
00363              0, 0, (unsigned long) 1);
00364 
00365   XFlush (mf_display);
00366 }
00367 
00368 #else
00369 int x11_dummy;
00370 #endif /* X11WIN */