home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xfd / fontgrid.c next >
Encoding:
C/C++ Source or Header  |  1991-07-18  |  16.1 KB  |  539 lines

  1. /*
  2.  * $XConsortium: fontgrid.c,v 1.25 91/07/18 14:59:57 rws Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising
  11.  * or publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Jim Fulton, MIT X Consortium
  24.  */
  25.  
  26.  
  27. #include <X11/IntrinsicP.h>
  28. #include <X11/StringDefs.h>
  29. #include <X11/Xaw/SimpleP.h>
  30. #include <X11/Xmu/Converters.h>
  31. #include "fontgridP.h"
  32.  
  33.  
  34. #define Bell(w) XBell(XtDisplay(w), 50)
  35.  
  36.  
  37. static void ClassInitialize(), Initialize(), Realize(), Redisplay(), Notify();
  38. static void Destroy(), Resize(), paint_grid();
  39. static Boolean SetValues();
  40.  
  41. #define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field)
  42.  
  43. static XtResource resources[] = {
  44.     { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  45.     Offset(text_font), XtRString, (XtPointer) NULL },
  46.     { XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int),
  47.     Offset(cell_cols), XtRImmediate, (XtPointer) 0 },
  48.     { XtNcellRows, XtCCellRows, XtRInt, sizeof(int),
  49.     Offset(cell_rows), XtRImmediate, (XtPointer) 0 },
  50.     { XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int),
  51.     Offset(cell_width), XtRImmediate, (XtPointer) 0 },
  52.     { XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int),
  53.     Offset(cell_height), XtRImmediate, (XtPointer) 0 },
  54.     { XtNstartChar, XtCStartChar, XtRDimension, sizeof(Dimension),
  55.     Offset(start_char), XtRImmediate, (XtPointer) 0xffff },
  56.     { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  57.     Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground },
  58.     { XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean),
  59.     Offset(center_chars), XtRImmediate, (XtPointer) FALSE },
  60.     { XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean),
  61.     Offset(box_chars), XtRImmediate, (XtPointer) FALSE },
  62.     { XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel),
  63.     Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground },
  64.     { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
  65.     Offset(callbacks), XtRCallback, (XtPointer) NULL },
  66.     { XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int),
  67.     Offset(internal_pad), XtRImmediate, (XtPointer) 4 },
  68.     { XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int),
  69.     Offset(grid_width), XtRImmediate, (XtPointer) 1 },
  70. };
  71.  
  72. #undef Offset
  73.  
  74. static char defaultTranslations[] = 
  75.   "<ButtonPress>:  notify()";
  76.  
  77. static XtActionsRec actions_list[] = {
  78.     { "notify",        Notify },
  79. };
  80.  
  81. FontGridClassRec fontgridClassRec = {
  82.   { /* core fields */
  83.     /* superclass               */      (WidgetClass) &simpleClassRec,
  84.     /* class_name               */      "FontGrid",
  85.     /* widget_size              */      sizeof(FontGridRec),
  86.     /* class_initialize         */      ClassInitialize,
  87.     /* class_part_initialize    */      NULL,
  88.     /* class_inited             */      FALSE,
  89.     /* initialize               */      Initialize,
  90.     /* initialize_hook          */      NULL,
  91.     /* realize                  */      Realize,
  92.     /* actions                  */      actions_list,
  93.     /* num_actions              */      XtNumber(actions_list),
  94.     /* resources                */      resources,
  95.     /* num_resources            */      XtNumber(resources),
  96.     /* xrm_class                */      NULLQUARK,
  97.     /* compress_motion          */      TRUE,
  98.     /* compress_exposure        */      TRUE,
  99.     /* compress_enterleave      */      TRUE,
  100.     /* visible_interest         */      FALSE,
  101.     /* destroy                  */      Destroy,
  102.     /* resize                   */      Resize,
  103.     /* expose                   */      Redisplay,
  104.     /* set_values               */      SetValues,
  105.     /* set_values_hook          */      NULL,
  106.     /* set_values_almost        */      XtInheritSetValuesAlmost,
  107.     /* get_values_hook          */      NULL,
  108.     /* accept_focus             */      NULL,
  109.     /* version                  */      XtVersion,
  110.     /* callback_private         */      NULL,
  111.     /* tm_table                 */      defaultTranslations,
  112.     /* query_geometry           */      XtInheritQueryGeometry,
  113.     /* display_accelerator      */      XtInheritDisplayAccelerator,
  114.     /* extension                */      NULL
  115.   },
  116.   { /* simple fields */
  117.     /* change_sensitive        */    XtInheritChangeSensitive
  118.   }
  119. };
  120.  
  121. WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec;
  122.  
  123.  
  124. /*
  125.  * public routines
  126.  */
  127.  
  128. void GetFontGridCellDimensions (w, startp, ncolsp, nrowsp)
  129.     Widget w;
  130.     Dimension *startp;
  131.     int *ncolsp, *nrowsp;
  132. {
  133.     FontGridWidget fgw = (FontGridWidget) w;
  134.     *startp = (long)fgw->fontgrid.start_char;
  135.     *ncolsp = fgw->fontgrid.cell_cols;
  136.     *nrowsp = fgw->fontgrid.cell_rows;
  137. }
  138.  
  139.  
  140. void GetPrevNextStates (w, prevvalidp, nextvalidp)
  141.     Widget w;
  142.     Bool *prevvalidp, *nextvalidp;
  143. {
  144.     FontGridWidget fgw = (FontGridWidget) w;
  145.  
  146.     XFontStruct *fs = fgw->fontgrid.text_font;
  147.     long minn = (long) ((fs->min_byte1 << 0) | fs->min_char_or_byte2);
  148.     long maxn = (long) ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
  149.  
  150.     *prevvalidp = ((long)fgw->fontgrid.start_char > minn);
  151.     *nextvalidp = (((long)fgw->fontgrid.start_char +
  152.             (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows))
  153.            < maxn);
  154. }
  155.  
  156.  
  157.  
  158. /*
  159.  * private routines and methods
  160.  */
  161.  
  162.  
  163. static GC get_gc (fgw, fore)
  164.     FontGridWidget fgw;
  165.     Pixel fore;
  166. {
  167.     XtGCMask mask;
  168.     XGCValues gcv;
  169.  
  170.     mask = (GCForeground | GCBackground | GCFunction | GCFont);
  171.     gcv.foreground = fore;
  172.     gcv.background = fgw->core.background_pixel;
  173.     gcv.function = GXcopy;
  174.     gcv.font = fgw->fontgrid.text_font->fid;
  175.     gcv.cap_style = CapProjecting;
  176.     mask |= GCCapStyle;
  177.     if (fgw->fontgrid.grid_width > 0) {
  178.     mask |= GCLineWidth;
  179.     gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 : 
  180.               fgw->fontgrid.grid_width);
  181.     }
  182.     return (XtGetGC ((Widget) fgw, mask, &gcv));
  183. }
  184.  
  185.  
  186. static void ClassInitialize ()
  187. {
  188.     XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0);
  189. }
  190.  
  191.  
  192. static void Initialize (request, new)
  193.     Widget request, new;
  194. {
  195.     FontGridWidget reqfg = (FontGridWidget) request;
  196.     FontGridWidget newfg = (FontGridWidget) new;
  197.     XFontStruct *fs = newfg->fontgrid.text_font;
  198.     unsigned maxn;
  199.  
  200.     if (reqfg->fontgrid.cell_cols <= 0)
  201.       newfg->fontgrid.cell_cols = 16;
  202.  
  203.     if (reqfg->fontgrid.cell_rows <= 0) {
  204.     if (fs && fs->max_byte1 == 0) {
  205.         newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / 
  206.                      newfg->fontgrid.cell_cols) + 1;
  207.         if (newfg->fontgrid.cell_rows > 16)
  208.           newfg->fontgrid.cell_rows = 16;
  209.     } else
  210.       newfg->fontgrid.cell_rows = 16;
  211.     }
  212.  
  213.     if (reqfg->fontgrid.cell_width <= 0)
  214.       newfg->fontgrid.cell_width = (fs ? DefaultCellWidth (newfg) : 1);
  215.     if (reqfg->fontgrid.cell_height <= 0)
  216.       newfg->fontgrid.cell_height = (fs ? DefaultCellHeight (newfg) : 1);
  217.  
  218.     /* give a nice size that fits one screen full */
  219.     if (newfg->core.width == 0)
  220.       newfg->core.width = (newfg->fontgrid.cell_width *
  221.                newfg->fontgrid.cell_cols +
  222.                newfg->fontgrid.grid_width *
  223.                (newfg->fontgrid.cell_cols + 1));
  224.  
  225.     if (newfg->core.height == 0) 
  226.       newfg->core.height = (newfg->fontgrid.cell_height * 
  227.                 newfg->fontgrid.cell_rows +
  228.                 newfg->fontgrid.grid_width *
  229.                 (newfg->fontgrid.cell_rows + 1));
  230.  
  231.     /*
  232.      * select the first character
  233.      */
  234.  
  235.     if (newfg->fontgrid.start_char == 0xffff) {
  236.     newfg->fontgrid.start_char = (fs ? (unsigned)(fs->min_byte1 << 8) : 0);
  237.     }
  238.     if (fs) {
  239.     maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
  240.     if (newfg->fontgrid.start_char > maxn) 
  241.       newfg->fontgrid.start_char = (maxn + 1 - 
  242.                     (newfg->fontgrid.cell_cols * 
  243.                      newfg->fontgrid.cell_rows));
  244.     }
  245. }
  246.  
  247. static void Realize (gw, valueMask, attributes)
  248.     Widget gw;
  249.     Mask *valueMask;
  250.     XSetWindowAttributes *attributes;
  251. {
  252.     FontGridWidget fgw = (FontGridWidget) gw;
  253.     FontGridPart *p = &fgw->fontgrid;
  254.  
  255.     p->text_gc = get_gc (fgw, p->foreground_pixel);
  256.     p->box_gc = get_gc (fgw, p->box_pixel);
  257.     Resize (gw);
  258.  
  259.     (*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes);
  260.     return;
  261. }
  262.  
  263.  
  264.  
  265. static void Destroy (gw)
  266.     Widget gw;
  267. {
  268.     FontGridWidget fgw = (FontGridWidget) gw;
  269.  
  270.     XtReleaseGC (gw, fgw->fontgrid.text_gc);
  271.     XtReleaseGC (gw, fgw->fontgrid.box_gc);
  272. }
  273.  
  274.  
  275. static void Resize (gw)
  276.     Widget gw;
  277. {
  278.     FontGridWidget fgw = (FontGridWidget) gw;
  279.  
  280.     /* recompute in case we've changed size */
  281.     fgw->fontgrid.cell_width = CellWidth (fgw);
  282.     if (fgw->fontgrid.cell_width <= 0)
  283.     fgw->fontgrid.cell_width = 1;
  284.     fgw->fontgrid.cell_height = CellHeight (fgw);
  285.     if (fgw->fontgrid.cell_height <= 0)
  286.     fgw->fontgrid.cell_height = 1;
  287.     fgw->fontgrid.xoff = (fgw->fontgrid.cell_width -
  288.                 DefaultCellWidth (fgw)) / 2;
  289.     fgw->fontgrid.yoff = (fgw->fontgrid.cell_height -
  290.                 DefaultCellHeight (fgw)) / 2;
  291.  
  292. }
  293.  
  294.  
  295. /* ARGSUSED */
  296. static void Redisplay (gw, event, region)
  297.     Widget gw;
  298.     XEvent *event;
  299.     Region region;
  300. {
  301.     FontGridWidget fgw = (FontGridWidget) gw;
  302.     XRectangle rect;            /* bounding rect for region */
  303.     int left, right, top, bottom;    /* which cells were damaged */
  304.     int cw, ch;                /* cell size */
  305.  
  306.     if (!fgw->fontgrid.text_font) {
  307.     Bell (gw);
  308.     return;
  309.     }
  310.  
  311.     /*
  312.      * compute the left, right, top, and bottom cells that were damaged
  313.      */
  314.     XClipBox (region, &rect);
  315.     cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width;
  316.     ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width;
  317.     if ((left = (((int) rect.x) / cw)) < 0) left = 0;
  318.     right = (((int) (rect.x + rect.width - 1)) / cw);
  319.     if ((top = (((int) rect.y) / ch)) < 0) top = 0;
  320.     bottom = (((int) (rect.y + rect.height - 1)) / ch);
  321.  
  322.     paint_grid (fgw, left, top, right - left + 1, bottom - top + 1);
  323. }
  324.  
  325.  
  326. static void paint_grid (fgw, col, row, ncols, nrows)
  327.     FontGridWidget fgw;            /* widget in which to draw */
  328.     int col, row;            /* where to start */
  329.     int ncols, nrows;            /* number of cells */
  330. {
  331.     FontGridPart *p = &fgw->fontgrid;
  332.     int i, j;
  333.     Display *dpy = XtDisplay(fgw);
  334.     Window wind = XtWindow(fgw);
  335.     int cw = p->cell_width + p->grid_width;
  336.     int ch = p->cell_height + p->grid_width;
  337.     int tcols = p->cell_cols;
  338.     int trows = p->cell_rows;
  339.     int x1, y1, x2, y2, x, y;
  340.     unsigned maxn = ((p->text_font->max_byte1 << 8) |
  341.              p->text_font->max_char_or_byte2);
  342.     unsigned n, prevn;
  343.     int startx;
  344.  
  345.     if (col + ncols >= tcols) {
  346.     ncols = tcols - col;
  347.     if (ncols < 1) return;
  348.     }
  349.  
  350.     if (row + nrows >= trows) {
  351.     nrows = trows - row;
  352.     if (nrows < 1) return;
  353.     }
  354.  
  355.     /*
  356.      * paint the grid lines for the indicated rows 
  357.      */
  358.     if (p->grid_width > 0) {
  359.     int half_grid_width = p->grid_width >> 1;
  360.     x1 = col * cw + half_grid_width;
  361.     y1 = row * ch + half_grid_width;
  362.     x2 = x1 + ncols * cw;
  363.     y2 = y1 + nrows * ch;
  364.     for (i = 0, x = x1; i <= ncols; i++, x += cw) {
  365.         XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2);
  366.     }
  367.     for (i = 0, y = y1; i <= nrows; i++, y += ch) {
  368.         XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y);
  369.     }
  370.     }
  371.  
  372.     
  373.     /*
  374.      * Draw a character in every box; treat all fonts as if they were 16bit
  375.      * fonts.  Store the high eight bits in byte1 and the low eight bits in 
  376.      * byte2.
  377.      */
  378.     prevn = p->start_char + col + row * tcols;
  379.     startx = col * cw + p->internal_pad + p->grid_width;
  380.     for (j = 0,
  381.      y = row * ch + p->internal_pad + p->grid_width + p->text_font->ascent;
  382.      j < nrows; j++, y += ch) {
  383.     n = prevn;
  384.     for (i = 0, x = startx; i < ncols; i++, x += cw) {
  385.         XChar2b thechar;
  386.         int xoff = p->xoff, yoff = p->yoff;
  387.  
  388.         if (n > maxn) goto done;    /* no break out of nested */
  389.  
  390.         thechar.byte1 = (n >> 8);    /* high eight bits */
  391.         thechar.byte2 = (n & 255);    /* low eight bits */
  392.         if (p->box_chars || p->center_chars) {
  393.         XCharStruct metrics;
  394.         int direction, fontascent, fontdescent;
  395.  
  396.         XTextExtents16 (p->text_font, &thechar, 1, &direction,
  397.                 &fontascent, &fontdescent, &metrics);
  398.  
  399.         if (p->center_chars) {
  400.             /*
  401.              * We want to move the origin by enough to center the ink
  402.              * within the cell.  The left edge will then be at 
  403.              * (cell_width - (rbearing - lbearing)) / 2; so we subtract
  404.              * the lbearing to find the origin.  Ditto for vertical.
  405.              */
  406.             xoff = (((p->cell_width -
  407.                   (metrics.rbearing - metrics.lbearing)) / 2) -
  408.                 p->internal_pad - metrics.lbearing);
  409.             yoff = (((p->cell_height - 
  410.                   (metrics.descent + metrics.ascent)) / 2) -
  411.                 p->internal_pad -
  412.                 p->text_font->ascent + metrics.ascent);
  413.         }
  414.         if (p->box_chars) {
  415.             XDrawRectangle (dpy, wind, p->box_gc,
  416.                     x + xoff, y + yoff - p->text_font->ascent, 
  417.                     metrics.width - 1,
  418.                     fontascent + fontdescent - 1);
  419.         }
  420.         }
  421.         XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff,
  422.                &thechar, 1);
  423.         n++;
  424.     }
  425.     prevn += tcols;
  426.     }
  427.  
  428.   done:
  429.     return;
  430. }
  431.  
  432. /*ARGSUSED*/
  433. static Boolean SetValues (current, request, new, args, num_args)
  434.     Widget current, request, new;
  435.     ArgList args;
  436.     Cardinal *num_args;
  437. {
  438.     FontGridWidget curfg = (FontGridWidget) current;
  439.     FontGridWidget newfg = (FontGridWidget) new;
  440.     Boolean redisplay = FALSE;
  441.  
  442.     if (curfg->fontgrid.text_font != newfg->fontgrid.text_font ||
  443.     curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) {
  444.     newfg->fontgrid.cell_width = DefaultCellWidth (newfg);
  445.     newfg->fontgrid.cell_height = DefaultCellHeight (newfg);
  446.     redisplay = TRUE;
  447.     }
  448.  
  449.     if (curfg->fontgrid.foreground_pixel != newfg->fontgrid.foreground_pixel) {
  450.     XtReleaseGC (new, curfg->fontgrid.text_gc);
  451.     newfg->fontgrid.text_gc = get_gc (newfg,
  452.                       newfg->fontgrid.foreground_pixel);
  453.     redisplay = TRUE;
  454.     }
  455.  
  456.     if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) {
  457.     XtReleaseGC (new, curfg->fontgrid.text_gc);
  458.     newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel);
  459.     redisplay = TRUE;
  460.     }
  461.  
  462.     if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars ||
  463.     curfg->fontgrid.box_chars != newfg->fontgrid.box_chars)
  464.       redisplay = TRUE;
  465.  
  466.     if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) {
  467.     XFontStruct *fs = newfg->fontgrid.text_font;
  468.     unsigned maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2);
  469.  
  470.     if (newfg->fontgrid.start_char > maxn) 
  471.       newfg->fontgrid.start_char = (maxn + 1 - 
  472.                     (newfg->fontgrid.cell_cols * 
  473.                      newfg->fontgrid.cell_rows));
  474.  
  475.     redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char);
  476.     }
  477.  
  478.     return redisplay;
  479. }
  480.  
  481.  
  482. /* ARGSUSED */
  483. static void Notify (gw, event, params, nparams)
  484.     Widget gw;
  485.     XEvent *event;
  486.     String *params;
  487.     Cardinal *nparams;
  488. {
  489.     FontGridWidget fgw = (FontGridWidget) gw;
  490.     int x, y;                /* where the event happened */
  491.     FontGridCharRec rec;        /* callback data */
  492.  
  493.     /*
  494.      * only allow events with (x,y)
  495.      */
  496.     switch (event->type) {
  497.       case KeyPress:
  498.       case KeyRelease:
  499.     x = event->xkey.x;
  500.     y = event->xkey.y;
  501.     break;
  502.       case ButtonPress:
  503.       case ButtonRelease:
  504.     x = event->xbutton.x;
  505.     y = event->xbutton.y;
  506.     break;
  507.       case MotionNotify:
  508.     x = event->xmotion.x;
  509.     y = event->xmotion.y;
  510.     break;
  511.       default:
  512.     Bell (gw);
  513.     return;
  514.     }
  515.  
  516.     /*
  517.      * compute the callback data
  518.      */
  519.     {
  520.     int cw = fgw->fontgrid.cell_width, ch = fgw->fontgrid.cell_height;
  521.     unsigned n;
  522.  
  523.     if (x > (fgw->fontgrid.cell_cols * cw)) {
  524.         Bell (gw);
  525.         return;
  526.     }
  527.  
  528.     n= (fgw->fontgrid.start_char + 
  529.         ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw));
  530.  
  531.     rec.thefont = fgw->fontgrid.text_font;
  532.     rec.thechar.byte1 = (n >> 8);
  533.     rec.thechar.byte2 = (n & 255);
  534.     }
  535.  
  536.     XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec);
  537. }
  538.  
  539.