diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:53 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:53 +0000 |
commit | 961d4493f519b5b093581e111997f894b1675d48 (patch) | |
tree | a1aca760da761709d3cc83c37db8e9f3128d2e93 /grid.c |
R6.6 is the Xorg base-lineXORG-MAINXORG-STABLE
Diffstat (limited to 'grid.c')
-rw-r--r-- | grid.c | 555 |
1 files changed, 555 insertions, 0 deletions
@@ -0,0 +1,555 @@ +/* + * $Xorg: grid.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $ + * + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * * + * Author: Jim Fulton, MIT X Consortium + */ + + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/SimpleP.h> +#include <X11/Xmu/Converters.h> +#include "gridP.h" + +#ifdef XKB +#include <X11/extensions/XKBbells.h> +#else +#define XkbBI_MinorError 2 +#define XkbBI_Ignore 11 +#endif + +#ifdef XKB +#define Bell(w,n) XkbStdBell(XtDisplay(w), XtWindow(w), 50, n) +#else +#define Bell(w,n) XBell(XtDisplay(w), 0) +#endif + + +static void ClassInitialize(), Initialize(), Realize(), Redisplay(), Notify(); +static void Destroy(), Resize(), paint_grid(); +static Boolean SetValues(); + +#define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field) + +static XtResource resources[] = { + { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), + Offset(text_font), XtRString, (XtPointer) NULL }, + { XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int), + Offset(cell_cols), XtRImmediate, (XtPointer) 0 }, + { XtNcellRows, XtCCellRows, XtRInt, sizeof(int), + Offset(cell_rows), XtRImmediate, (XtPointer) 0 }, + { XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int), + Offset(cell_width), XtRImmediate, (XtPointer) 0 }, + { XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int), + Offset(cell_height), XtRImmediate, (XtPointer) 0 }, + { XtNstartChar, XtCStartChar, XtRDimension, sizeof(Dimension), + Offset(start_char), XtRImmediate, (XtPointer) 0xffff }, + { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground }, + { XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean), + Offset(center_chars), XtRImmediate, (XtPointer) FALSE }, + { XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean), + Offset(box_chars), XtRImmediate, (XtPointer) FALSE }, + { XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel), + Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground }, + { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + Offset(callbacks), XtRCallback, (XtPointer) NULL }, + { XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int), + Offset(internal_pad), XtRImmediate, (XtPointer) 4 }, + { XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int), + Offset(grid_width), XtRImmediate, (XtPointer) 1 }, +}; + +#undef Offset + +static char defaultTranslations[] = + "<ButtonPress>: notify()"; + +static XtActionsRec actions_list[] = { + { "notify", Notify }, +}; + +FontGridClassRec fontgridClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &simpleClassRec, + /* class_name */ "FontGrid", + /* widget_size */ sizeof(FontGridRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ actions_list, + /* num_actions */ XtNumber(actions_list), + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ Resize, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ defaultTranslations, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + } +}; + +WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec; + + +/* + * public routines + */ + +void GetFontGridCellDimensions (w, startp, ncolsp, nrowsp) + Widget w; + Dimension *startp; + int *ncolsp, *nrowsp; +{ + FontGridWidget fgw = (FontGridWidget) w; + *startp = (long)fgw->fontgrid.start_char; + *ncolsp = fgw->fontgrid.cell_cols; + *nrowsp = fgw->fontgrid.cell_rows; +} + + +void GetPrevNextStates (w, prevvalidp, nextvalidp) + Widget w; + Bool *prevvalidp, *nextvalidp; +{ + FontGridWidget fgw = (FontGridWidget) w; + + XFontStruct *fs = fgw->fontgrid.text_font; + long minn = (long) ((fs->min_byte1 << 0) | fs->min_char_or_byte2); + long maxn = (long) ((fs->max_byte1 << 8) | fs->max_char_or_byte2); + + *prevvalidp = ((long)fgw->fontgrid.start_char > minn); + *nextvalidp = (((long)fgw->fontgrid.start_char + + (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows)) + < maxn); +} + + + +/* + * private routines and methods + */ + + +static GC get_gc (fgw, fore) + FontGridWidget fgw; + Pixel fore; +{ + XtGCMask mask; + XGCValues gcv; + + mask = (GCForeground | GCBackground | GCFunction | GCFont); + gcv.foreground = fore; + gcv.background = fgw->core.background_pixel; + gcv.function = GXcopy; + gcv.font = fgw->fontgrid.text_font->fid; + gcv.cap_style = CapProjecting; + mask |= GCCapStyle; + if (fgw->fontgrid.grid_width > 0) { + mask |= GCLineWidth; + gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 : + fgw->fontgrid.grid_width); + } + return (XtGetGC ((Widget) fgw, mask, &gcv)); +} + + +static void ClassInitialize () +{ + XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0); +} + + +static void Initialize (request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + FontGridWidget reqfg = (FontGridWidget) request; + FontGridWidget newfg = (FontGridWidget) new; + XFontStruct *fs = newfg->fontgrid.text_font; + unsigned maxn; + + if (reqfg->fontgrid.cell_cols <= 0) + newfg->fontgrid.cell_cols = 16; + + if (reqfg->fontgrid.cell_rows <= 0) { + if (fs && fs->max_byte1 == 0) { + newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / + newfg->fontgrid.cell_cols) + 1; + if (newfg->fontgrid.cell_rows > 16) + newfg->fontgrid.cell_rows = 16; + } else + newfg->fontgrid.cell_rows = 16; + } + + if (reqfg->fontgrid.cell_width <= 0) + newfg->fontgrid.cell_width = (fs ? DefaultCellWidth (newfg) : 1); + if (reqfg->fontgrid.cell_height <= 0) + newfg->fontgrid.cell_height = (fs ? DefaultCellHeight (newfg) : 1); + + /* give a nice size that fits one screen full */ + if (newfg->core.width == 0) + newfg->core.width = (newfg->fontgrid.cell_width * + newfg->fontgrid.cell_cols + + newfg->fontgrid.grid_width * + (newfg->fontgrid.cell_cols + 1)); + + if (newfg->core.height == 0) + newfg->core.height = (newfg->fontgrid.cell_height * + newfg->fontgrid.cell_rows + + newfg->fontgrid.grid_width * + (newfg->fontgrid.cell_rows + 1)); + + /* + * select the first character + */ + + if (newfg->fontgrid.start_char == 0xffff) { + newfg->fontgrid.start_char = (fs ? (unsigned)(fs->min_byte1 << 8) : 0); + } + if (fs) { + maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2); + if (newfg->fontgrid.start_char > maxn) + newfg->fontgrid.start_char = (maxn + 1 - + (newfg->fontgrid.cell_cols * + newfg->fontgrid.cell_rows)); + } +} + +static void Realize (gw, valueMask, attributes) + Widget gw; + Mask *valueMask; + XSetWindowAttributes *attributes; +{ + FontGridWidget fgw = (FontGridWidget) gw; + FontGridPart *p = &fgw->fontgrid; + + p->text_gc = get_gc (fgw, p->foreground_pixel); + p->box_gc = get_gc (fgw, p->box_pixel); + Resize (gw); + + (*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes); + return; +} + + + +static void Destroy (gw) + Widget gw; +{ + FontGridWidget fgw = (FontGridWidget) gw; + + XtReleaseGC (gw, fgw->fontgrid.text_gc); + XtReleaseGC (gw, fgw->fontgrid.box_gc); +} + + +static void Resize (gw) + Widget gw; +{ + FontGridWidget fgw = (FontGridWidget) gw; + + /* recompute in case we've changed size */ + fgw->fontgrid.cell_width = CellWidth (fgw); + if (fgw->fontgrid.cell_width <= 0) + fgw->fontgrid.cell_width = 1; + fgw->fontgrid.cell_height = CellHeight (fgw); + if (fgw->fontgrid.cell_height <= 0) + fgw->fontgrid.cell_height = 1; + fgw->fontgrid.xoff = (fgw->fontgrid.cell_width - + DefaultCellWidth (fgw)) / 2; + fgw->fontgrid.yoff = (fgw->fontgrid.cell_height - + DefaultCellHeight (fgw)) / 2; + +} + + +/* ARGSUSED */ +static void Redisplay (gw, event, region) + Widget gw; + XEvent *event; + Region region; +{ + FontGridWidget fgw = (FontGridWidget) gw; + XRectangle rect; /* bounding rect for region */ + int left, right, top, bottom; /* which cells were damaged */ + int cw, ch; /* cell size */ + + if (!fgw->fontgrid.text_font) { + Bell (gw, XkbBI_BadValue); + return; + } + + /* + * compute the left, right, top, and bottom cells that were damaged + */ + XClipBox (region, &rect); + cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; + ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; + if ((left = (((int) rect.x) / cw)) < 0) left = 0; + right = (((int) (rect.x + rect.width - 1)) / cw); + if ((top = (((int) rect.y) / ch)) < 0) top = 0; + bottom = (((int) (rect.y + rect.height - 1)) / ch); + + paint_grid (fgw, left, top, right - left + 1, bottom - top + 1); +} + + +static void paint_grid (fgw, col, row, ncols, nrows) + FontGridWidget fgw; /* widget in which to draw */ + int col, row; /* where to start */ + int ncols, nrows; /* number of cells */ +{ + FontGridPart *p = &fgw->fontgrid; + int i, j; + Display *dpy = XtDisplay(fgw); + Window wind = XtWindow(fgw); + int cw = p->cell_width + p->grid_width; + int ch = p->cell_height + p->grid_width; + int tcols = p->cell_cols; + int trows = p->cell_rows; + int x1, y1, x2, y2, x, y; + unsigned maxn = ((p->text_font->max_byte1 << 8) | + p->text_font->max_char_or_byte2); + unsigned n, prevn; + int startx; + + if (col + ncols >= tcols) { + ncols = tcols - col; + if (ncols < 1) return; + } + + if (row + nrows >= trows) { + nrows = trows - row; + if (nrows < 1) return; + } + + /* + * paint the grid lines for the indicated rows + */ + if (p->grid_width > 0) { + int half_grid_width = p->grid_width >> 1; + x1 = col * cw + half_grid_width; + y1 = row * ch + half_grid_width; + x2 = x1 + ncols * cw; + y2 = y1 + nrows * ch; + for (i = 0, x = x1; i <= ncols; i++, x += cw) { + XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2); + } + for (i = 0, y = y1; i <= nrows; i++, y += ch) { + XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y); + } + } + + + /* + * Draw a character in every box; treat all fonts as if they were 16bit + * fonts. Store the high eight bits in byte1 and the low eight bits in + * byte2. + */ + prevn = p->start_char + col + row * tcols; + startx = col * cw + p->internal_pad + p->grid_width; + for (j = 0, + y = row * ch + p->internal_pad + p->grid_width + p->text_font->ascent; + j < nrows; j++, y += ch) { + n = prevn; + for (i = 0, x = startx; i < ncols; i++, x += cw) { + XChar2b thechar; + int xoff = p->xoff, yoff = p->yoff; + + if (n > maxn) goto done; /* no break out of nested */ + + thechar.byte1 = (n >> 8); /* high eight bits */ + thechar.byte2 = (n & 255); /* low eight bits */ + if (p->box_chars || p->center_chars) { + XCharStruct metrics; + int direction, fontascent, fontdescent; + + XTextExtents16 (p->text_font, &thechar, 1, &direction, + &fontascent, &fontdescent, &metrics); + + if (p->center_chars) { + /* + * We want to move the origin by enough to center the ink + * within the cell. The left edge will then be at + * (cell_width - (rbearing - lbearing)) / 2; so we subtract + * the lbearing to find the origin. Ditto for vertical. + */ + xoff = (((p->cell_width - + (metrics.rbearing - metrics.lbearing)) / 2) - + p->internal_pad - metrics.lbearing); + yoff = (((p->cell_height - + (metrics.descent + metrics.ascent)) / 2) - + p->internal_pad - + p->text_font->ascent + metrics.ascent); + } + if (p->box_chars) { + XDrawRectangle (dpy, wind, p->box_gc, + x + xoff, y + yoff - p->text_font->ascent, + metrics.width - 1, + fontascent + fontdescent - 1); + } + } + XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff, + &thechar, 1); + n++; + } + prevn += tcols; + } + + done: + return; +} + +/*ARGSUSED*/ +static Boolean SetValues (current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + FontGridWidget curfg = (FontGridWidget) current; + FontGridWidget newfg = (FontGridWidget) new; + Boolean redisplay = FALSE; + + if (curfg->fontgrid.text_font != newfg->fontgrid.text_font || + curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) { + newfg->fontgrid.cell_width = DefaultCellWidth (newfg); + newfg->fontgrid.cell_height = DefaultCellHeight (newfg); + redisplay = TRUE; + } + + if (curfg->fontgrid.foreground_pixel != newfg->fontgrid.foreground_pixel) { + XtReleaseGC (new, curfg->fontgrid.text_gc); + newfg->fontgrid.text_gc = get_gc (newfg, + newfg->fontgrid.foreground_pixel); + redisplay = TRUE; + } + + if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) { + XtReleaseGC (new, curfg->fontgrid.text_gc); + newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel); + redisplay = TRUE; + } + + if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars || + curfg->fontgrid.box_chars != newfg->fontgrid.box_chars) + redisplay = TRUE; + + if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) { + XFontStruct *fs = newfg->fontgrid.text_font; + unsigned maxn = ((fs->max_byte1 << 8) | fs->max_char_or_byte2); + + if (newfg->fontgrid.start_char > maxn) + newfg->fontgrid.start_char = (maxn + 1 - + (newfg->fontgrid.cell_cols * + newfg->fontgrid.cell_rows)); + + redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char); + } + + return redisplay; +} + + +/* ARGSUSED */ +static void Notify (gw, event, params, nparams) + Widget gw; + XEvent *event; + String *params; + Cardinal *nparams; +{ + FontGridWidget fgw = (FontGridWidget) gw; + int x, y; /* where the event happened */ + FontGridCharRec rec; /* callback data */ + + /* + * only allow events with (x,y) + */ + switch (event->type) { + case KeyPress: + case KeyRelease: + x = event->xkey.x; + y = event->xkey.y; + break; + case ButtonPress: + case ButtonRelease: + x = event->xbutton.x; + y = event->xbutton.y; + break; + case MotionNotify: + x = event->xmotion.x; + y = event->xmotion.y; + break; + default: + Bell (gw, XkbBI_Ignore); + return; + } + + /* + * compute the callback data + */ + { + int cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width; + int ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width; + unsigned n; + + if (x > (fgw->fontgrid.cell_cols * cw)) { + Bell (gw, XkbBI_InvalidLocation); + return; + } + + n= (fgw->fontgrid.start_char + + ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw)); + + rec.thefont = fgw->fontgrid.text_font; + rec.thechar.byte1 = (n >> 8); + rec.thechar.byte2 = (n & 255); + } + + XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec); +} + |