v10i056: wcl -- Widget Creation Library, Part08/11
David E. Smyth
david at jpl-devvax.jpl.nasa.gov
Tue Dec 18 09:17:04 AEST 1990
Submitted-by: david at jpl-devvax.jpl.nasa.gov (David E. Smyth)
Posting-number: Volume 10, Issue 56
Archive-name: wcl/part08
# to unbundle, "sh" this file -- DO NOT use csh
# SHAR archive format. Archive created Fri Oct 19 09:33:11 PDT 1990
echo x - Table_m.c
sed 's/^X//' > Table_m.c <<'+FUNKY+STUFF+'
X/*LINTLIBRARY*/ /* -*-C-*- */
X/*
X * Table - Forms-based composite widget/geometry manager for the X Toolkit
X *
X * David Harrison
X * University of California, Berkeley
X * 1989
X *
X * This file contains the implementation for the Table widget.
X */
X
X/* Edit History
X
X08/07/90 5 nazgul Mon Aug 6 09:41:11 1990 patches from david at jpl-devvax.jpl.nasa.gov
X07/26/90 4 nazgul Removal of Xmu.h reference (Niels Mayer)
X07/25/90 3 nazgul Merged in latest patches from the net
X07/15/90 2 nazgul Now deal with XmText widgets reasonably
X
X*/
X
X#include "X11/IntrinsicP.h"
X#include "X11/StringDefs.h"
X
X#if defined(XtSpecificationRelease) && XtSpecificationRelease >= 4
X#include "X11/Xmu/Xmu.h"
X#else
X#include "X11/Xmu.h"
X#endif
X
X#include "Table_mP.h"
X
X#define INIT_TBL_SIZE 10
X#define TBL_CLASS_NAME "Table"
X
Xstatic caddr_t def = (caddr_t) 0;
X
Xstatic XtResource resources[] = {
X { XtNlayout, XtCLayout, XtRPointer, sizeof(caddr_t),
X XtOffset(TableWidget, table.init_layout), XtRPointer, (caddr_t) &def },
X { XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
X XtOffset(TableWidget, table.int_height), XtRImmediate, (caddr_t) 0 },
X { XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
X XtOffset(TableWidget, table.int_width), XtRImmediate, (caddr_t) 0 },
X
X { XtNcolumnSpacing, XtCSpacing, XtRDimension, sizeof(Dimension),
X XtOffset(TableWidget, table.col_spacing), XtRImmediate, (caddr_t) 0 },
X { XtNrowSpacing, XtCSpacing, XtRDimension, sizeof(Dimension),
X XtOffset(TableWidget, table.row_spacing), XtRImmediate, (caddr_t) 0 },
X/* If we want it more motif-like
X { XmNverticalSpacing, XmCSpacing, XtRDimension, sizeof(Dimension),
X XtOffset(TableWidget, table.col_spacing), XtRImmediate, (caddr_t) 0 },
X { XmNhorizontalSpacing, XmCSpacing, XtRDimension, sizeof(Dimension),
X XtOffset(TableWidget, table.row_spacing), XtRImmediate, (caddr_t) 0 },
X*/
X { XtNdefaultOptions, XtCOptions, XtROptions, sizeof(XtTblMask),
X XtOffset(TableWidget, table.def_options), XtRImmediate, (caddr_t) 0 }
X};
X
X/* Forward declarations */
Xstatic void TblClassInitialize();
Xstatic void TblExposeProc();
Xstatic void TblInitialize();
Xstatic void TblResize();
Xstatic XtGeometryResult TblQueryGeometry();
Xstatic void TblPositionChild();
Xstatic Boolean TblSetValues();
Xstatic XtGeometryResult TblGeometryManager();
Xstatic void TblChangeManaged();
Xstatic Boolean TblFindChild();
Xstatic void TblDestroy();
Xstatic XtTblMask ParseOpts();
X
X
X
X/*
X * Local structures
X */
X
Xtypedef struct _TableLoc {
X Position ax, ay; /* Position in array */
X Dimension h_span, v_span; /* Span size in array */
X XtTblMask options; /* Widget position options */
X} TableLoc, *TableLocPtr;
X
Xtypedef struct _TableLocEntry {
X Widget w;
X TableLoc loc;
X} TableLocEntry, *TableLocEntryPtr;
X
Xstruct _TableLocTbl {
X Cardinal n_layout; /* Number of layout widgets */
X Cardinal a_layout; /* Allocated space */
X TableLocEntryPtr locs; /* Widget locations */
X};
X
Xstruct _TableDefLoc {
X String w_name; /* Widget name */
X TableLoc loc; /* Widget information */
X};
X
Xtypedef unsigned long TableVecMask;
X#define VEC_MINIMIZE 0x01
X
Xstruct _TableVector {
X TableVecMask mask; /* Option mask */
X Cardinal value; /* Size of item */
X};
X
X
X
Xstatic XtActionsRec actionsList[] =
X{
X#if defined (MOTIF) && defined(MOTIF_MINOR) && MOTIF == 1 && MOTIF_MINOR == 0
X { "Enter", (XtActionProc) _XmManagerEnter },
X { "FocusIn", (XtActionProc) _XmBulletinBoardFocus },
X { "Arm", (XtActionProc) _XmBulletinBoardArm },
X { "Activate", (XtActionProc) _XmBulletinBoardActivate },
X { "Help", (XtActionProc) _XmBulletinBoardHelp },
X { "Return", (XtActionProc) _XmBulletinBoardReturn },
X#else
X { "Enter", (XtActionProc) _XmManagerEnter },
X { "FocusIn", (XtActionProc) _XmManagerFocusIn },
X { "FocusOut", (XtActionProc) _XmManagerFocusOut },
X { "Help", (XtActionProc) _XmManagerHelp },
X { "Return", (XtActionProc) _XmBulletinBoardReturn },
X#endif
X#if 0 /* smb */
X { "Unmap", (XtActionProc) _XmManagerUnmap },
X { "SizeUpdate", (XtActionProc) _XmBulletinBoardSizeUpdate },
X { "FocusMoved", (XtActionProc) _XmBulletinBoardFocusMoved },
X { "Cancel", (XtActionProc) _XmBulletinBoardCancel },
X { "SetDefaultShadow",
X (XtActionProc) _XmBulletinBoardSetDefaultShadow },
X { "SetDynDefaultButton",
X (XtActionProc) _XmBulletinBoardSetDynDefaultButton },
X#endif
X};
X
XTableClassRec tableClassRec = {
X { /* core_class fields */
X /* superclass */ (WidgetClass) &xmBulletinBoardClassRec,
X /* class_name */ TBL_CLASS_NAME,
X /* widget_size */ sizeof(TableRec),
X /* class_initialize */ TblClassInitialize,
X /* class_part_init */ NULL,
X /* class_inited */ FALSE,
X /* initialize */ TblInitialize,
X /* initialize_hook */ NULL,
X /* realize */ XtInheritRealize,
X /* actions */ actionsList,
X /* num_actions */ XtNumber(actionsList),
X /* resources */ resources,
X /* num_resources */ XtNumber(resources),
X /* xrm_class */ NULLQUARK,
X /* compress_motion */ False,
X /* compress_exposure */ TRUE,
X /* compress_enterleave*/ False,
X /* visible_interest */ FALSE,
X /* destroy */ TblDestroy,
X /* resize */ TblResize,
X /* expose */ _XmRedisplayGadgets,
X /* set_values */ TblSetValues,
X /* set_values_hook */ NULL,
X /* set_values_almost */ XtInheritSetValuesAlmost,
X /* get_values_hook */ NULL,
X /* accept_focus */ NULL,
X /* version */ XtVersion,
X /* callback_private */ NULL,
X /* tm_table */ XtInheritTranslations,
X /* query_geometry */ TblQueryGeometry,
X /* display_accelerator*/ /*XtInheritDisplayAccelerator,*/ NULL,
X /* extension */ NULL
X },
X { /* composite_class fields */
X /* geometry_manager */ TblGeometryManager,
X /* change_managed */ TblChangeManaged,
X /* insert_child */ XtInheritInsertChild,
X /* delete_child */ XtInheritDeleteChild,
X /* extension */ NULL
X },
X{ /* constraint_class fields */
X /* resource list */ NULL,
X /* num resources */ 0,
X /* constraint size */ 0,
X /* init proc */ NULL,
X /* destroy proc */ NULL,
X /* set values proc */ NULL,
X /* extension */ NULL
X },
X#if defined (MOTIF) && defined(MOTIF_MINOR) && MOTIF == 1 && MOTIF_MINOR == 0
X { /* manager_class */
X /* translations */ (XtTranslations) _XtInherit,
X /* get_resources */ NULL,
X /* num_get_resources */ 0,
X /* get_constraint_resources */ NULL,
X /* num_get_constraint_resources */ 0,
X /* extension */ NULL
X },
X#else
X { /* manager_class */
X /* translations */ XtInheritTranslations,
X /* syn_resources */ NULL,
X /* num_syn_resources */ 0,
X /* syn_constraint_resources */ NULL,
X /* num_syn_constraint_resources */ 0,
X /* parent_process */ XmInheritParentProcess,
X /* extension */ NULL
X },
X#endif
X{ /* Bulletin Board */
X /* always_install_accelerators */ False,
X /* extension */ NULL,
X },
X { /* table_class fields */
X /* position_child */ TblPositionChild,
X /* find_child */ TblFindChild,
X }
X};
X
XWidgetClass tableWidgetClass = (WidgetClass) &tableClassRec;
X
X
X
X/*ARGSUSED*/
Xstatic void cvtStrToDefLoc(args, num_args, from, to)
XXrmValue *args; /* Arguments to converter */
XCardinal *num_args; /* Number of arguments */
XXrmValue *from; /* From type */
XXrmValue *to; /* To type */
X/*
X * Converts a string representation into an array of TableDefLoc
X * structures.
X */
X{
X static caddr_t ptr;
X String layout_spec;
X
X if (*num_args != 0) {
X XtErrorMsg("cvtStrToDefLoc", "wrongParameters", "XtToolkitError",
X "String to layout takes no additional arguments",
X (String *) NULL, (Cardinal *) NULL);
X }
X
X layout_spec = (String) from->addr;
X to->size = sizeof(caddr_t);
X ptr = XtTblParseLayout(layout_spec);
X to->addr = (caddr_t) &ptr;
X}
X
X/*ARGSUSED*/
Xstatic void cvtStrToOpts(args, num_args, from, to)
XXrmValue *args; /* Arguments to converter */
XCardinal *num_args; /* Number of arguments */
XXrmValue *from; /* From type */
XXrmValue *to; /* To type */
X/*
X * Converts a string representation into a default options
X * mask (XtTblMask).
X */
X{
X static XtTblMask mask;
X String opt_spec;
X
X if (*num_args != 0) {
X XtErrorMsg("cvtStrToOpts", "wrongParameters", "XtToolkitError",
X "String to options takes no additional arguments",
X (String *) NULL, (Cardinal *) NULL);
X }
X
X opt_spec = (String) from->addr;
X to->size = sizeof(int);
X mask = ParseOpts(opt_spec);
X to->addr = (caddr_t) &mask;
X}
X
X
Xstatic void TblClassInitialize()
X/*
X * Adds an appropriate string-to-default widget location table
X * converter.
X */
X{
X XtAddConverter(XtRString, XtRPointer, cvtStrToDefLoc, NULL, 0);
X XtAddConverter(XtRString, XtROptions, cvtStrToOpts, NULL, 0);
X}
X
X
X
X
X/*
X * Table Management Functions
X *
X * Default table is a linear null terminated array, the location
X * array is a linear dynamic array. Both should be replaced
X * with hash tables.
X */
X
Xstatic Cardinal LenDefLoc(ptr)
XTableDefLocPtr ptr;
X/*
X * Returns the length of a DefLoc list.
X */
X{
X Cardinal i;
X
X for (i = 0; ptr && ptr[i].w_name; i++) {
X /* Null body */
X }
X return i;
X}
X
Xstatic TableDefLocPtr CopyDefLoc(ptr)
XTableDefLocPtr ptr;
X/*
X * Makes a dynamically allocated copy of `ptr'.
X */
X{
X TableDefLocPtr copy;
X Cardinal i, len;
X
X len = LenDefLoc(ptr);
X if (len) {
X copy = (TableDefLocPtr) XtCalloc(len+1, sizeof(struct _TableDefLoc));
X for (i = 0; i < len; i++) {
X copy[i] = ptr[i];
X }
X copy[i].w_name = (String) 0;
X } else {
X copy = (TableDefLocPtr) 0;
X }
X return copy;
X}
X
Xstatic TableDefLocPtr FindDefLoc(tbl, name)
XTableDefLocPtr tbl; /* Table to examine */
XString name; /* Widget name */
X/*
X * Scans through `tbl' looking for the name `name'. Returns
X * a pointer to the found value or NULL if not found.
X */
X{
X TableDefLocPtr idx;
X
X for (idx = tbl; idx && idx->w_name; idx++) {
X if (strcmp(idx->w_name, name) == 0) return idx;
X }
X return (TableDefLocPtr) 0;
X}
X
Xstatic TableDefLocPtr MergeDefLoc(source, dest)
XTableDefLocPtr source; /* Original table */
XTableDefLocPtr dest; /* Additional entries */
X/*
X * Returns a table where the entries in `dest' have been
X * merged with those in `source'. Similar entries in
X * `dest' override those in `source'. The returned
X * table is allocated.
X */
X{
X TableDefLocPtr result, update;
X Cardinal s_len, d_len;
X Cardinal i, j;
X
X s_len = LenDefLoc(source);
X d_len = LenDefLoc(dest);
X result = (TableDefLocPtr)
X XtCalloc(s_len + d_len + 1, sizeof(struct _TableDefLoc));
X for (i = 0; i < s_len; i++) {
X result[i] = source[i];
X }
X /* Add null termination */
X result[i].w_name = (String) 0;
X /* Now merge the results */
X for (j = 0; j < d_len; j++) {
X if (update = FindDefLoc(result, dest[j].w_name)) {
X update->loc = dest[j].loc;
X } else {
X /* Add to end */
X result[i].w_name = dest[j].w_name;
X result[i].loc = dest[j].loc;
X i += 1;
X result[i].w_name = (String) 0;
X }
X }
X return result;
X}
X
X
X
Xstatic TableLocTblPtr TblInitLocTbl()
X/*
X * Returns a newly allocated location table. This is implemented
X * at the moment as dynamic array. Eventually, a hash table
X * will be used.
X */
X{
X TableLocTblPtr rtn;
X
X rtn = (TableLocTblPtr) XtMalloc(sizeof(struct _TableLocTbl));
X rtn->n_layout = 0;
X rtn->a_layout = INIT_TBL_SIZE;
X rtn->locs = (TableLocEntryPtr)
X XtCalloc(INIT_TBL_SIZE, sizeof(TableLocEntry));
X return rtn;
X}
X
Xstatic void TblInsertLoc(tbl, w, locp)
XTableLocTblPtr tbl; /* Table for insertion */
XWidget w; /* Subwidget to place */
XTableLocPtr locp; /* Widget location information */
X/*
X * Inserts an item into the location table. If there is already
X * an entry for the widget, it is replaced by this one. If there
X * is no room, additional room is allocated.
X */
X{
X int i;
X
X for (i = 0; i < tbl->n_layout; i++) {
X if (tbl->locs[i].w == w) {
X tbl->locs[i].loc = *locp;
X return;
X }
X }
X /* Not in the table */
X if (tbl->n_layout >= tbl->a_layout) {
X /* Make more space */
X tbl->a_layout += tbl->a_layout;
X tbl->locs = (TableLocEntryPtr)
X XtRealloc(tbl->locs, tbl->a_layout * sizeof(TableLocEntry));
X }
X tbl->locs[tbl->n_layout].w = w;
X tbl->locs[tbl->n_layout].loc = *locp;
X tbl->n_layout += 1;
X}
X
Xstatic TableLocPtr TblLocLookup(tbl, w)
XTableLocTblPtr tbl; /* Table for lookup */
XWidget w; /* What widget to lookup */
X/*
X * Looks up widget `w' in the hard widget position table.
X * Returns NULL if it can't find the widget.
X */
X{
X int i;
X
X for (i = 0; i < tbl->n_layout; i++) {
X if (tbl->locs[i].w == w) {
X return &(tbl->locs[i].loc);
X }
X }
X return (TableLocPtr) 0;
X}
X
Xstatic void TblFreeLocTbl(tbl)
XTableLocTblPtr tbl; /* Table to free */
X/*
X * Frees memory resources of `tbl'.
X */
X{
X XtFree((char *) (tbl->locs));
X XtFree((char *) tbl);
X}
X
X
X
Xstatic void TblInitialize(request, new)
XWidget request; /* Values from resources */
XWidget new; /* Actual widget */
X/*
X * Intializes appropriate fields in instance record.
X */
X{
X TableWidget old = (TableWidget) request;
X TableWidget tw = (TableWidget) new;
X
X tw->table.init_layout = CopyDefLoc(old->table.init_layout);
X tw->table.layout_db = (TableDefLocPtr) 0;
X tw->table.real_layout = TblInitLocTbl();
X tw->table.vec_state = INVALID;
X tw->table.num_rows = tw->table.num_cols = 0;
X tw->table.rows = (TableVecPtr) 0;
X tw->table.cols = (TableVecPtr) 0;
X tw->table.vec_height = 0;
X tw->table.vec_width = 0;
X}
X
X
X
Xstatic TableLocTblPtr GetManaged(nw, wl)
XCardinal nw; /* Number of widgets */
XWidgetList wl; /* Widget list */
X/*
X * Returns those widgets in `wl' that are managed and looks
X * up their table postions. If no table position is found,
X * the widget is placed at 0,0 with a span of 1 with no options.
X */
X{
X TableLocTblPtr result;
X Cardinal i;
X
X result = TblInitLocTbl();
X for (i = 0; i < nw; i++) {
X if (XtIsManaged(wl[i])) {
X if (result->n_layout >= result->a_layout) {
X /* Make more space */
X result->a_layout += result->a_layout;
X result->locs = (TableLocEntryPtr)
X XtRealloc(result->locs,
X result->a_layout * sizeof(TableLocEntry));
X }
X result->locs[result->n_layout].w = wl[i];
X if (!TblFindChild(wl[i],
X &(result->locs[result->n_layout].loc.ax),
X &(result->locs[result->n_layout].loc.ay),
X &(result->locs[result->n_layout].loc.h_span),
X &(result->locs[result->n_layout].loc.v_span),
X &(result->locs[result->n_layout].loc.options))) {
X /* Can't find location -- make one up */
X result->locs[result->n_layout].loc.ax = 0;
X result->locs[result->n_layout].loc.ay = 0;
X result->locs[result->n_layout].loc.h_span = 1;
X result->locs[result->n_layout].loc.v_span = 1;
X result->locs[result->n_layout].loc.options = 0;
X }
X result->n_layout += 1;
X }
X }
X return result;
X}
X
X
Xstatic Cardinal VecSize(mw, val_func)
XTableLocTblPtr mw; /* List of managed widgets */
Xvoid (*val_func)(); /* Returns either row or column info */
X/*
X * Determines the vector size by examining locations of all
X * widgets in `mw'. Basically determines the maximum of loc+span.
X */
X{
X Cardinal i, loc, span;
X Cardinal result = 0;
X Boolean small_flag;
X
X for (i = 0; i < mw->n_layout; i++) {
X (*val_func)(&(mw->locs[i]), &loc, &span, &small_flag);
X if (result < loc+span) {
X result = loc+span;
X }
X }
X return result;
X}
X
X
X
Xstatic void SetVecOptions(mw, val_func, vec)
XTableLocTblPtr mw; /* Managed widget list */
Xvoid (*val_func)(); /* Row or col info */
XTableVecPtr vec; /* Spacing vector */
X/*
X * Steps through the list of widgets. If the widget is marked
X * as having the small flag set, it sets all corresponding
X * options in `vec'.
X */
X{
X Cardinal i, j;
X Cardinal loc, span;
X Boolean small_flag;
X
X for (i = 0; i < mw->n_layout; i++) {
X (*val_func)(&(mw->locs[i]), &loc, &span, &small_flag);
X if (small_flag) {
X for (j = loc; j < loc+span; j++) {
X vec[j].mask = VEC_MINIMIZE;
X }
X }
X }
X}
X
X
X/* Must be set before span_cmp works */
Xstatic void (*span_cmp_val_func)();
X
Xstatic int span_cmp(a, b)
Xchar *a, *b;
X/*
X * Compares items based on span.
X */
X{
X Cardinal loc_a, loc_b;
X Cardinal span_a, span_b;
X Boolean small_flag;
X
X (*span_cmp_val_func)((TableLocEntryPtr) a, &loc_a, &span_a, &small_flag);
X (*span_cmp_val_func)((TableLocEntryPtr) b, &loc_b, &span_b, &small_flag);
X return span_a - span_b;
X}
X
X
Xstatic Cardinal FindDistrib(loc, span, vec, result)
XCardinal loc, span; /* Widget loc and span */
XTableVecPtr vec; /* Spacing vector */
XCardinal *result; /* Result array */
X/*
X * This routine fills in `result' with a list of indices
X * into the spacing vector suitable for distributing required
X * space. Normally, it skips those items marked as
X * VEC_MINIMIZE. However, if there aren't any non-VEC_MINIMIZE
X * spaces, all of them become candidates.
X */
X{
X Cardinal i, count;
X
X count = 0;
X for (i = loc; i < loc+span; i++) {
X if (vec[i].mask & VEC_MINIMIZE) continue;
X result[count++] = i;
X }
X if (count == 0) {
X /* Add them all back in */
X for (i = loc; i < loc+span; i++) {
X result[count++] = i;
X }
X }
X return count;
X}
X
X
Xstatic void DoDistrib(n_dist, distrib, loc, span, vec, size, inter)
XCardinal n_dist; /* Number of distribution points */
XCardinal *distrib; /* Indicies into `vec' */
XCardinal loc, span; /* Widget location and span */
XTableVecPtr vec; /* Spacing vector */
XDimension size; /* Size of widget */
XDimension inter; /* inter {col,row} spacing */
X/*
X * If `size' is larger than the current sum of space in `vec'
X * specified by `loc' and `span', the difference in space
X * is evenly added to each vector entry given by `distrib'.
X */
X{
X Cardinal sum = 0;
X Cardinal i;
X int diff, amt;
X
X for (i = loc; i < loc+span; i++) {
X sum += vec[i].value;
X }
X if (span > 1)
X sum += (span-1) * inter;
X diff = size - sum;
X if (diff > 0) {
X /* Distribution required */
X amt = diff / n_dist;
X for (i = 0; i < n_dist-1; i++) {
X vec[distrib[i]].value += amt;
X diff -= amt;
X }
X /* Last one deincremented by remaining space */
X vec[distrib[i]].value += diff;
X }
X}
X
X
X
X
Xstatic Cardinal CompVector(mw, val_func, size_func, inter, result)
XTableLocTblPtr mw; /* List of managed widgets with locs */
Xvoid (*val_func)(); /* Returns either row or column info */
XDimension (*size_func)(); /* Returns desired size of subwidget */
XDimension inter; /* inter {row,col} spacing */
XTableVecPtr *result; /* Result vector */
X/*
X * This routine computes the values for either the row or column
X * spacing vector. The strategy is as follows:
X * 1. Scan mw and determine number of entrys in result and allocate
X * 2. Scan list and set appropriate vector flags.
X * 3. Sort the managed widgets in span order (low to high)
X * 4. For each item in sorted list:
X * A. Determine distribution locations.
X * B. Distribute any needed space to locations.
X * There are some inefficiencies here that could be overcome.
X */
X{
X Cardinal res_num, i;
X Cardinal n_dist, *distrib;
X Cardinal loc, span;
X Boolean small_flag;
X
X res_num = VecSize(mw, val_func);
X if (res_num) {
X *result = (TableVecPtr) XtCalloc(res_num, sizeof(struct _TableVector));
X for (i = 0; i < res_num; i++) {
X (*result)[i].mask = 0;
X (*result)[i].value = 0;
X }
X SetVecOptions(mw, val_func, *result);
X
X span_cmp_val_func = val_func;
X qsort((char *) mw->locs, (int) mw->n_layout,
X sizeof(TableLocEntry), span_cmp);
X
X distrib = (Cardinal *) XtCalloc(res_num, sizeof(Cardinal));
X for (i = 0; i < mw->n_layout; i++) {
X (*val_func)(&(mw->locs[i]), &loc, &span, &small_flag);
X n_dist = FindDistrib(loc, span, *result, distrib);
X DoDistrib(n_dist, distrib, loc, span, *result,
X (*size_func)(mw->locs[i].w), inter);
X }
X return res_num;
X } else {
X *result = (TableVecPtr) 0;
X return 0;
X }
X /*NOTREACHED*/
X}
X
X
Xstatic void ColValues(oneloc, loc, span, small_flag)
XTableLocEntryPtr oneloc; /* Widget data */
XCardinal *loc; /* Location in array */
XCardinal *span; /* Spanning distance */
XBoolean *small_flag; /* Whether locked */
X/*
X * This routine returns column data from `oneloc'. It is
X * passed to CompVector when computing the column spacing vector.
X */
X{
X *loc = oneloc->loc.ax;
X *span = oneloc->loc.h_span;
X *small_flag = oneloc->loc.options & TBL_SM_WIDTH;
X}
X
Xstatic void RowValues(oneloc, loc, span, small_flag)
XTableLocEntryPtr oneloc; /* Widget data */
XCardinal *loc; /* Location in array */
XCardinal *span; /* Spanning distance */
XBoolean *small_flag; /* Whether locked */
X/*
X * This routine returns row data from `oneloc'. It is
X * passed to CompVector when computing the row spacing vector.
X */
X{
X *loc = oneloc->loc.ay;
X *span = oneloc->loc.v_span;
X *small_flag = oneloc->loc.options & TBL_SM_HEIGHT;
X}
X
Xstatic Dimension ColSize(w)
XWidget w; /* Child widget */
X/*
X * This routine returns the desired width of the widget `w'.
X * It is used by CompVector when computing the column vector.
X */
X{
X Dimension r_size, r_border;
X XtWidgetGeometry child;
X
X r_size = w->core.width;
X r_border = w->core.border_width;
X (void) XtQueryGeometry(w, (XtWidgetGeometry *) 0, &child);
X if (child.request_mode & CWWidth) r_size = child.width;
X if (child.request_mode & CWBorderWidth) r_border = child.border_width;
X return r_size + r_border + r_border;
X}
X
Xstatic Dimension RowSize(w)
XWidget w; /* Child widget */
X/*
X * This routine returns the desired width of the widget `w'.
X * It is used by CompVector when computing the column vector.
X */
X{
X Dimension r_size, r_border;
X XtWidgetGeometry child;
X
X r_size = w->core.height;
X r_border = w->core.border_width;
X (void) XtQueryGeometry(w, (XtWidgetGeometry *) 0, &child);
X if (child.request_mode & CWHeight) r_size = child.height;
X if (child.request_mode & CWBorderWidth) r_border = child.border_width;
X return r_size + r_border + r_border;
X}
X
X
X
X/*ARGSUSED*/
Xstatic void TblRecompVectors(tw)
XTableWidget tw; /* Table widget */
X/*
X * Recomputes the size vectors in the table widget by
X * examining the preferred sizes of subwidgets. The
X * following fields are modified: num_rows, num_cols,
X * rows, cols, vec_height, and vec_width.
X */
X{
X TableLocTblPtr managed;
X Cardinal i;
X
X /* Free existing vectors */
X if (tw->table.cols) XtFree((char *) (tw->table.cols));
X tw->table.num_cols = 0;
X if (tw->table.rows) XtFree((char *) (tw->table.rows));
X tw->table.num_rows = 0;
X tw->table.vec_width = tw->table.vec_height = 0;
X
X /* Generate list of managed widgets with locations */
X managed = GetManaged(tw->composite.num_children, tw->composite.children);
X
X /* Handle columns */
X tw->table.num_cols = CompVector(managed, ColValues, ColSize,
X tw->table.col_spacing, &(tw->table.cols));
X for (i = 0; i < tw->table.num_cols; i++) {
X tw->table.vec_width += tw->table.cols[i].value;
X }
X
X
X /* Handle rows */
X tw->table.num_rows = CompVector(managed, RowValues, RowSize,
X tw->table.row_spacing, &(tw->table.rows));
X for (i = 0; i < tw->table.num_rows; i++) {
X tw->table.vec_height += tw->table.rows[i].value;
X }
X
X TblFreeLocTbl(managed);
X}
X
X
Xstatic void TblRequestResize(tw)
XTableWidget tw; /* Table widget */
X/*
X * Asks the parent to become the size given by the row and
X * column vectors. Precondition: vec_state must be MINIMUM.
X */
X{
X XtGeometryResult rtn;
X Dimension act_width, act_height;
X Dimension r_width, r_height;
X
X act_width = tw->table.vec_width + 2*tw->table.int_width +
X (tw->table.num_cols-1)*tw->table.col_spacing;
X act_height = tw->table.vec_height + 2*tw->table.int_height +
X (tw->table.num_rows-1)*tw->table.row_spacing;
X rtn = XtMakeResizeRequest((Widget) tw, act_width, act_height,
X &r_width, &r_height);
X switch (rtn) {
X case XtGeometryYes:
X case XtGeometryNo:
X /* Either case -- no action required */
X break;
X case XtGeometryAlmost:
X if ((r_width >= act_width) &&
X (r_height >= act_height)) {
X (void) XtMakeResizeRequest((Widget) tw, r_width, r_height,
X (Dimension *) 0, (Dimension *) 0);
X }
X break;
X }
X}
X
X
X
Xstatic void ExtraSpace(num, vec, size)
XCardinal num; /* Length of `vec' */
XTableVecPtr vec; /* Spacing vector */
XDimension size; /* Overall size */
X/*
X * If `size' is larger than the sum of all widths in `vec',
X * the extra space is distributed evenly among appropriate
X * candidates of `vec'.
X */
X{
X Cardinal i, ndist, sum = 0;
X Cardinal *dist;
X int diff, amt;
X
X for (i = 0; i < num; i++) sum += vec[i].value;
X diff = size - sum;
X if (diff != 0) {
X /* Have to distribute space */
X dist = (Cardinal *) XtCalloc(num, sizeof(Cardinal));
X ndist = FindDistrib(0, num, vec, dist);
X amt = diff/ndist;
X for (i = 0; i < ndist-1; i++) {
X vec[dist[i]].value += amt;
X diff -= amt;
X }
X vec[dist[i]].value += diff;
X XtFree((char *) dist);
X }
X}
X
X
Xstatic Dimension SumVec(loc, span, vec, start, inter, end)
XPosition loc, span; /* Start and length */
XTableVecPtr vec; /* Spacing vector */
XDimension start; /* Added before sum */
XDimension inter; /* Added between items */
XDimension end; /* Added after sum */
X/*
X * Returns the sum of the space in `vec' from `loc' for length `span'.
X * Adds in the appropriate padding given by `start', `inter' and `end'.
X */
X{
X Position i;
X Dimension sum = 0;
X
X for (i = loc; i < loc+span; i++) sum += vec[i].value;
X return sum + start + end + ((span >= 0) ? span*inter : 0);
X}
X
Xstatic void PlaceWidget(w, x, y, width, height, rw, rh, opt)
XWidget w; /* What widget to place */
XPosition x, y; /* Location of space */
XDimension width, height; /* Size of space */
XDimension rw, rh; /* Actual size */
XXtTblMask opt; /* Justification options */
X/*
X * This routine moves the widget `w' inside the space given
X * by x, y, width, height. Its location in this space
X * is determined by looking at the justification options of
X * `opt'.
X */
X{
X Position rx, ry;
X
X if (opt & TBL_LEFT) rx = x;
X else if (opt & TBL_RIGHT) rx = x + width - rw;
X else rx = x + (width-rw)/2;
X if (opt & TBL_TOP) ry = y;
X else if (opt & TBL_BOTTOM) ry = y + height - rh;
X else ry = y + (height-rh)/2;
X#ifdef NOTDEF
X rx += w->core.border_width;
X ry += w->core.border_width;
X#endif
X
X/* XtMoveWidget(w, rx, ry);*/
X _XmMoveObject((RectObj)w, rx, ry);
X}
X
X
Xstatic void DoPlace(managed, cvec, rvec, vp, hp, rs, cs)
XTableLocTblPtr managed; /* List of managed widgets with locs */
XTableVecPtr cvec, rvec; /* Column and row spacing vector */
XDimension vp, hp; /* Vertical and horizontal padding */
XDimension rs, cs; /* Row and column interspace */
X/*
X * This routine places each widget in `managed' according to the
X * spacing vectors `cvec' and `rvec' and the widget placement
X * options (justification and resizing). First, if allowed,
X * the routine will resize the widget to fit its allocated
X * space. Then it will place the widget paying attention
X * to the justification.
X */
X{
X Cardinal i;
X Position ax, ay;
X Dimension aw, ah;
X Dimension nw, nh;
X
X for (i = 0; i < managed->n_layout; i++) {
X ax = SumVec(0, managed->locs[i].loc.ax, cvec, hp, cs, 0);
X ay = SumVec(0, managed->locs[i].loc.ay, rvec, vp, rs, 0);
X aw = SumVec(managed->locs[i].loc.ax,
X (Position) managed->locs[i].loc.h_span, cvec, 0, cs, -cs);
X ah = SumVec(managed->locs[i].loc.ay,
X (Position) managed->locs[i].loc.v_span, rvec, 0, rs, -rs);
X nw = aw - 2*managed->locs[i].w->core.border_width;
X nh = ah - 2*managed->locs[i].w->core.border_width;
X if (managed->locs[i].loc.options & TBL_LK_WIDTH) {
X nw = managed->locs[i].w->core.width;
X }
X if (managed->locs[i].loc.options & TBL_LK_HEIGHT) {
X nh = managed->locs[i].w->core.height;
X }
X if (((nw != managed->locs[i].w->core.width) ||
X (nh != managed->locs[i].w->core.height)) &&
X (nw > 0) && (nh > 0)) {
X /* Resize widget */
X/* XtResizeWidget(managed->locs[i].w, nw, nh,
X managed->locs[i].w->core.border_width);*/
X _XmResizeObject((RectObj)managed->locs[i].w, nw, nh,
X managed->locs[i].w->core.border_width);
X }
X /* Now place */
X nw = managed->locs[i].w->core.width +
X 2*managed->locs[i].w->core.border_width;;
X nh = managed->locs[i].w->core.height +
X 2*managed->locs[i].w->core.border_width;;
X PlaceWidget(managed->locs[i].w, ax, ay, aw, ah, nw, nh,
X managed->locs[i].loc.options);
X }
X}
X
X
X
X/*ARGSUSED*/
Xstatic void TblPlacement(tw)
XTableWidget tw; /* Table widget */
X/*
X * Places the children of the table widget. There are several steps:
X * 1. Distribute any extra space into local copies of spacing vectors.
X * 2. If the option is set, any extra space is offered to each widget.
X * 3. The final placement is done according to the actual size of
X * each widget and the space allocated for it.
X */
X{
X Cardinal i;
X TableVecPtr lrows, lcols;
X TableLocTblPtr managed;
X Dimension real_width, real_height;
X
X if (tw->table.num_rows && tw->table.num_cols) {
X /* Make local copies of vectors */
X lrows = (TableVecPtr)
X XtCalloc(tw->table.num_rows, sizeof(struct _TableVector));
X for (i = 0; i < tw->table.num_rows; i++) {
X lrows[i] = tw->table.rows[i];
X }
X lcols = (TableVecPtr)
X XtCalloc(tw->table.num_cols, sizeof(struct _TableVector));
X for (i = 0; i < tw->table.num_cols; i++) {
X lcols[i] = tw->table.cols[i];
X }
X
X /* Add extra space to vector */
X real_width = tw->core.width - 2*tw->table.int_width -
X (tw->table.num_cols-1)*tw->table.col_spacing;
X real_height = tw->core.height - 2*tw->table.int_height -
X (tw->table.num_rows-1)*tw->table.row_spacing;
X ExtraSpace(tw->table.num_cols, lcols, real_width);
X ExtraSpace(tw->table.num_rows, lrows, real_height);
X
X /* Get list of managed widgets with locations */
X managed = GetManaged(tw->composite.num_children, tw->composite.children);
X DoPlace(managed, lcols, lrows, tw->table.int_height, tw->table.int_width,
X tw->table.row_spacing, tw->table.col_spacing);
X
X /* Free up resources */
X XtFree((char *) lcols);
X XtFree((char *) lrows);
X TblFreeLocTbl(managed);
X }
X}
X
X
X
X
Xstatic void TblResize(w)
XWidget w; /* Table widget */
X/*
X * This routine is called when the table widget itself is
X * resized. If needed, the vectors are recomputed and
X * placement is done.
X */
X{
X TableWidget tw = (TableWidget) w;
X
X if ((tw->core.width < tw->table.vec_width) ||
X (tw->core.height < tw->table.vec_height)) {
X TblRequestResize(tw);
X }
X if (tw->table.vec_state == INVALID) {
X TblRecompVectors(tw);
X tw->table.vec_state = MINIMUM;
X }
X TblPlacement(tw);
X}
X
X
X
Xstatic XtGeometryResult ExamineRequest(request)
XXtWidgetGeometry *request;
X/*
X * Examines the bits set in `request' and returns an appropriate
X * geometry manager result. Pure size changes are accepted
X * (XtGeometryYes), pure position changes are rejected
X * (XtGeometryNo), and combinations are conditionally
X * accepted (XtGeometryAlmost).
X */
X{
X if (request->request_mode & (CWWidth|CWHeight|CWBorderWidth)) {
X if (request->request_mode & (CWX|CWY|CWSibling|CWStackMode)) {
X return XtGeometryAlmost;
X } else {
X return XtGeometryYes;
X }
X } else {
X return XtGeometryNo;
X }
X}
X
X
X
Xstatic XtGeometryResult TblGeometryManager(w, request, reply)
XWidget w; /* Widget */
XXtWidgetGeometry *request; /* Requested geometry change */
XXtWidgetGeometry *reply; /* Actual reply to request */
X/*
X * This routine handles geometry requests from children. Width
X * and height changes are always accepted. Position changes
X * are always rejected. Combinations result in XtGeometryAlmost
X * with the requested widths filled in. Accepted changes cause
X * an immediate XtResizeWidget followed by a new placement.
X */
X{
X Widget parent;
X TableWidget tw = (TableWidget) w->core.parent;
X XtGeometryResult result;
X Dimension width, height, bdr;
X Dimension ow, oh;
X
X parent = w->core.parent;
X if (parent && (tableWidgetClass == parent->core.widget_class) ){
X result = ExamineRequest(request);
X switch (result) {
X case XtGeometryYes:
X if (request->request_mode & XtCWQueryOnly) {
X return XtGeometryYes;
X }
X if (request->request_mode & CWWidth) {
X width = request->width;
X } else {
X width = w->core.width;
X }
X if (request->request_mode & CWHeight) {
X height = request->height;
X } else {
X height = w->core.height;
X }
X
X if (height == request->height && width == request->width) {
X return XtGeometryDone;
X }
X
X bdr = w->core.border_width;
X if ((width > 0) && (height > 0))
X _XmResizeObject((RectObj)w, width, height, bdr);
X
X ow = tw->table.vec_width;
X oh = tw->table.vec_height;
X TblRecompVectors(tw);
X tw->table.vec_state = MINIMUM;
X if ((ow != tw->table.vec_width) || (oh != tw->table.vec_height))
X TblRequestResize(tw);
X TblPlacement(tw);
X
X return XtGeometryDone;
X /*NOTREACHED*/
X case XtGeometryNo:
X return result;
X case XtGeometryAlmost:
X *reply = *request;
X /* Turn off all but the size changes */
X reply->request_mode &= (CWWidth|CWHeight|CWBorderWidth);
X return XtGeometryAlmost;
X }
X /*NOTREACHED*/
X } else {
X XtErrorMsg("TblGeometryManager", "badParent", "XtToolkitError",
X "Parent of widget is not a tableClassWidget",
X (String *) NULL, (Cardinal *) NULL);
X return XtGeometryNo;
X }
X /*NOTREACHED*/
X}
X
X
X
X/*ARGSUSED*/
Xstatic Boolean TblSetValues(current, request, new)
XWidget current; /* Before call to XtSetValues */
XWidget request; /* After call to XtSetValues */
XWidget new; /* Final version of widget */
X/*
X * Checks for changes to `init_table'. If so, a recomputation
X * and replacement occurs. Always returns false.
X */
X{
X TableWidget old = (TableWidget) current;
X TableWidget tw = (TableWidget) new;
X Boolean recomp = False;
X
X if ((tw->table.init_layout) ||
X (old->table.int_width != tw->table.int_width) ||
X (old->table.int_height != tw->table.int_height) ||
X (old->table.row_spacing != tw->table.row_spacing) ||
X (old->table.col_spacing != tw->table.col_spacing)) {
X recomp = True;
X }
X if (recomp) {
X /* Causes complete recomputation and placement */
X TblRecompVectors(tw);
X tw->table.vec_state = MINIMUM;
X TblRequestResize(tw);
X TblPlacement(tw);
X }
X return FALSE;
X}
X
X
X
X
Xstatic void TblChangeManaged(w)
XWidget w; /* Table widget */
X/*
X * This routine is called when a change to the managed set of
X * children occurs. The current implementation simply refigures
X * the widget and repositions all widgets. Better implementations
X * may be able to examine the change and react accordingly.
X */
X{
X TableWidget tw = (TableWidget) w;
X XtWidgetGeometry g;
X
X/* if (_XmMakeGeometryRequest(tw, &g) == XtGeometryYes && XtIsRealized(tw))
X {
X*/
X TblRecompVectors(tw);
X tw->table.vec_state = MINIMUM;
X TblRequestResize(tw);
X TblPlacement(tw);
X/* }*/
X}
X
X
X
Xstatic XtGeometryResult TblQueryGeometry(w, request, geo_return)
XWidget w; /* Table widget */
XXtWidgetGeometry *request; /* Parent intended size */
XXtWidgetGeometry *geo_return; /* This widget's size */
X/*
X * This routine is called by a parent that wants a preferred
X * size for the widget. The `request' is the size (and/or position)
X * the parent intends to make the widget. The `geo_return' is the
X * preferred size of the widget. The preferred size of the
X * table widget is its vector size.
X */
X{
X TableWidget tw = (TableWidget) w;
X
X if (tw->table.vec_state == INVALID) {
X TblRecompVectors(tw);
X tw->table.vec_state = MINIMUM;
X }
X geo_return->request_mode = CWWidth|CWHeight;
X geo_return->width = tw->table.vec_width + 2*tw->table.int_width +
X (tw->table.num_cols-1)*tw->table.col_spacing;
X geo_return->height = tw->table.vec_height + 2*tw->table.int_height +
X (tw->table.num_rows-1)*tw->table.row_spacing;
X
X /* Now determine return code */
X if (((geo_return->request_mode & request->request_mode) !=
X geo_return->request_mode) ||
X (request->width < geo_return->width) ||
X (request->height < geo_return->height)) {
X return XtGeometryAlmost;
X } else if ((request->width == geo_return->width) &&
X (request->height == geo_return->height)) {
X return XtGeometryNo;
X } else {
X return XtGeometryYes;
X }
X /*NOTREACHED*/
X}
X
X
X
Xstatic void TblPositionChild(w, c, r, hspan, vspan, options)
XWidget w; /* Subwidget to place */
XPosition c, r; /* Position in array (column, row) */
XDimension hspan, vspan; /* Horizontal and vertical span */
XXtTblMask options; /* Widget placement options */
X/*
X * This routine registers the position of Widget w. The widget
X * must be a sub-widget of a Table class widget. The row and
X * column must be non-negative. The horizontal and vertical
X * span must be positive. The options are as follows:
X * TBL_LEFT Horizontally left justified.
X * TBL_RIGHT Horizontally right justified.
X * TBL_TOP Vertically top justified.
X * TBL_BOTTOM Vertically bottom justified.
X * TBL_SM_WIDTH Force the width to be as small as possible.
X * TBL_SM_HEIGHT Force the height to be as small as possible.
X * TBL_LK_WIDTH Don't try to expand the widget horizontally.
X * TBL_LK_HEIGHT Don't try to expand the widget vertically.
X * If `options' is equal to TBL_DEF_OPT, it is filled with
X * the default value for the table widget. The routine adds the
X * information into a table and recomputes position information.
X */
X{
X Widget parent;
X TableWidget tw;
X TableLoc loc;
X
X if ((c < 0) || (r < 0) || (hspan == 0) || (vspan == 0)) {
X /* Bad arguments */
X XtErrorMsg("TblPositionChild", "wrongParameters", "XtToolkitError",
X "Bad value for row, column, hspan, or vspan",
X (String *) NULL, (Cardinal *) NULL);
X }
X parent = w->core.parent;
X if (parent && (tableWidgetClass == parent->core.widget_class) ){
X /* The parent exists and is a TableWidget */
X tw = (TableWidget) parent;
X loc.ax = c;
X loc.ay = r;
X loc.h_span = hspan;
X loc.v_span = vspan;
X if (options == TBL_DEF_OPT) {
X loc.options = tw->table.def_options;
X } else {
X loc.options = options;
X }
X TblInsertLoc(tw->table.real_layout, w, &loc);
X tw->table.vec_state = INVALID;
X /* Full recomputation if realized */
X if (XtIsRealized(parent)) TblResize(parent);
X } else {
X XtErrorMsg("TblPositionChild", "badParent", "XtToolkitError",
X "Parent of widget is not a tableClassWidget",
X (String *) NULL, (Cardinal *) NULL);
X }
X}
X
X
X
Xstatic Boolean TblFindChild(w, c_r, r_r, hspan_r, vspan_r, opt_r)
XWidget w; /* Widget to locate */
XPosition *c_r, *r_r; /* Returned position */
XDimension *hspan_r, *vspan_r; /* Returned span */
XXtTblMask *opt_r; /* Returned options */
X/*
X * This routine looks up a child widget's location and span. The
X * parent must be a table widget. Only non-zero fields are filled
X * in. If the widget cannot be found, the routine returns False
X * and does not modify any of the passed in pointers. The routine
X * first looks in a table of widget positions defined by the
X * `position_child' class procedure. If not found there, it
X * searches the default table using the widget name. These
X * defaults are set by resources or XtSetValues().
X */
X{
X Widget parent;
X TableWidget tw;
X TableLocPtr locp;
X TableDefLocPtr temp;
X
X parent = w->core.parent;
X if (parent && (tableWidgetClass == parent->core.widget_class) ){
X tw = (TableWidget) parent;
X if (locp = TblLocLookup(tw->table.real_layout, w)) {
X if (c_r) *c_r = locp->ax;
X if (r_r) *r_r = locp->ay;
X if (hspan_r) *hspan_r = locp->h_span;
X if (vspan_r) *vspan_r = locp->v_span;
X if (opt_r) *opt_r = locp->options;
X return True;
X } else {
X if (tw->table.init_layout) {
X temp = MergeDefLoc(tw->table.layout_db, tw->table.init_layout);
X XtFree((char *) (tw->table.init_layout));
X tw->table.init_layout = (TableDefLocPtr) 0;
X XtFree((char *) (tw->table.layout_db));
X tw->table.layout_db = temp;
X }
X /* Attempt to look it up */
X if (temp = FindDefLoc(tw->table.layout_db, w->core.name)) {
X if (c_r) *c_r = temp->loc.ax;
X if (r_r) *r_r = temp->loc.ay;
X if (hspan_r) *hspan_r = temp->loc.h_span;
X if (vspan_r) *vspan_r = temp->loc.v_span;
X if (opt_r) *opt_r = temp->loc.options;
X return True;
X } else {
X return False;
X }
X }
X } else {
X XtErrorMsg("TblFindChild", "badParent", "XtToolkitError",
X "Parent of widget is not a tableClassWidget",
X (String *) NULL, (Cardinal *) NULL);
X }
X /*NOTREACHED*/
X}
X
X
X
Xstatic void TblDestroy(w)
XWidget w; /* Widget to destroy */
X/*
X * Called to free resources consumed by the widget.
X */
X{
X TableWidget tw = (TableWidget) w;
X
X XtFree((char *) (tw->table.init_layout));
X XtFree((char *) (tw->table.layout_db));
X TblFreeLocTbl(tw->table.real_layout);
X if (tw->table.rows) XtFree((char *) (tw->table.rows));
X if (tw->table.cols) XtFree((char *) (tw->table.cols));
X}
X
X
Xstatic Cardinal DefSpecLen(layout)
XString layout; /* Full layout specification string */
X/*
X * Examines `layout' and determines how many statements there are.
X * Basically counts semi-colons and adds one.
X */
X{
X extern String strchr();
X String idx = layout;
X Cardinal result = 0;
X
X while (idx && *idx) {
X idx = (char *)strchr(idx, ';');
X if (idx) {
X result++;
X idx++;
X }
X }
X return result+1;
X}
X
X#define MAX_FIELD 128
X#define NUM_FIELDS 6
X#define MAX_CHARS 255
X
Xstatic XtTblMask ParseOpts(spec)
XString spec; /* Option letters */
X/*
X * Parses the null-terminated string of option characters in `spec'.
X * Returns a mask that is the `or' of all options selected.
X */
X{
X static Boolean init = 0;
X static XtTblMask all_chars[MAX_CHARS];
X XtTblMask result = 0;
X String idx;
X
X if (!init) {
X Cardinal i;
X
X for (i = 0; i < MAX_CHARS; i++) all_chars[i] = 0;
X all_chars['l'] = TBL_LEFT;
X all_chars['r'] = TBL_RIGHT;
X all_chars['t'] = TBL_TOP;
X all_chars['b'] = TBL_BOTTOM;
X all_chars['w'] = TBL_LK_WIDTH;
X all_chars['h'] = TBL_LK_HEIGHT;
X all_chars['W'] = TBL_SM_WIDTH;
X all_chars['H'] = TBL_SM_HEIGHT;
X }
X for (idx = spec; *idx; idx++) {
X result |= all_chars[*idx];
X }
X return result;
X}
X
Xstatic void DefParse(spec, loc_spec)
XString spec; /* One specification statement */
XTableDefLocPtr loc_spec; /* Result location spec */
X/*
X * Parses a text specification statement into an internal
X * form given by `loc_spec'.
X *
X ******************* NOTE ********************
X * Assumes only called from cvtStrToDefLoc() *
X *********************************************
X */
X{
X#ifndef MAX_TABLE_CHILD_WIDGET_NAME_LEN
X#define MAX_TABLE_CHILD_WIDGET_NAME_LEN 128
X#endif
X static char buf[MAX_TABLE_CHILD_WIDGET_NAME_LEN];
X int i = 0;
X char* cp = spec;
X
X /* initial values, NOT the defaults */
X loc_spec->loc.ax = loc_spec->loc.ay = 0;
X loc_spec->loc.h_span = loc_spec->loc.v_span = 0;
X
X /* Now attempt to parse the string */
X while (*cp && *cp <= ' ') cp++; /* eat whitespace */
X
X while (' ' < *cp && i < MAX_TABLE_CHILD_WIDGET_NAME_LEN)
X buf[i++] = *cp++;
X buf[i] = '\0';
X if ( i )
X loc_spec->w_name = XtNewString(buf); /* widget name */
X else
X loc_spec->w_name = "No Name"; /* default name */
X
X while (*cp && *cp <= ' ') cp++; /* eat whitespace */
X
X while ('0' <= *cp && *cp <= '9')
X loc_spec->loc.ax = loc_spec->loc.ax * 10 + *cp++ - '0';
X
X while (*cp && *cp <= ' ') cp++; /* eat whitespace */
X
X while ('0' <= *cp && *cp <= '9')
X loc_spec->loc.ay = loc_spec->loc.ay * 10 + *cp++ - '0';
X
X while (*cp && *cp <= ' ') cp++; /* eat whitespace */
X
X while ('0' <= *cp && *cp <= '9')
X loc_spec->loc.h_span = loc_spec->loc.h_span * 10 + *cp++ - '0';
X if (loc_spec->loc.h_span == 0)
X loc_spec->loc.h_span = 1; /* default span */
X
X while (*cp && *cp <= ' ') cp++; /* eat whitespace */
X
X while ('0' <= *cp && *cp <= '9')
X loc_spec->loc.v_span = loc_spec->loc.v_span * 10 + *cp++ - '0';
X if (loc_spec->loc.v_span == 0)
X loc_spec->loc.v_span = 1; /* default span */
X
X while (*cp && *cp <= ' ') cp++; /* eat whitespace */
X
X i = 0;
X while (*cp && i < MAX_TABLE_CHILD_WIDGET_NAME_LEN &&
X *cp == 'l' || *cp == 'r' || *cp == 't' || *cp == 'b' ||
X *cp == 'w' || *cp == 'h' || *cp == 'W' || *cp == 'H' )
X buf[i++] = *cp++;
X buf[i] = '\0';
X if ( i )
X loc_spec->loc.options = ParseOpts(buf);
X else
X loc_spec->loc.options = 0; /* default */
X
X while (*cp && *cp <= ' ') cp++; /* eat whitespace */
X
X if (*cp )
X XtStringConversionWarning( spec,
X "layout component: name [col] [row] [h_span] [v_span] [lrtbwhWH]");
X}
X
Xstatic String GetSpec(spec_ptr)
XString *spec_ptr; /* Specification pointer */
X/*
X * This routine gets the next specification from the string
X * `spec_ptr' and updates the pointer appropriately.
X */
X{
X extern String strchr();
X String result;
X String semi;
X
X if (*spec_ptr && **spec_ptr) {
X semi = (char *)strchr(*spec_ptr, ';');
X if (semi) {
X *semi = '\0';
X result = *spec_ptr;
X *spec_ptr = semi+1;
X return result;
X } else {
X result = *spec_ptr;
X *spec_ptr += strlen(*spec_ptr);
X return result;
X }
X } else {
X return (String) 0;
X }
X}
X
X
X
X/**********************************************************************
X *
X * Public routines
X *
X **********************************************************************/
X
X
X/*ARGSUSED*/
Xcaddr_t XtTblParseLayout(layout)
XString layout; /* String layout specification */
X/*
X * Parses a string layout specification into an internal form
X * suitable for use in a call to XtSetValues(). The form is
X * a list of statements separated by semicolons. Each statement
X * has the form:
X * widget_name column row horizontal_span vertical_span opt_list
X * where the meaning of each field is:
X * widget_name Name of the widget as given to XtCreateWidget().
X * column Integer >= 0 descibing column in array
X * row Row >= 0 describing row in array
X * horizontal_span Integer >= 1 describing horizontal widget span
X * vertical_span Integer >= 1 describing vertical widget span
X * opt_list Series of characters each representing an option:
X * l: TBL_LEFT
X * r: TBL_RIGHT
X * t: TBL_TOP
X * b: TBL_BOTTOM
X * w: TBL_LK_WIDTH
X * h: TBL_LK_HEIGHT
X * W: TBL_SM_WIDTH
X * H: TBL_SM_HEIGHT
X * The options are as described in TblPostionChild(). The horizontal_span,
X * vertical_span, and opt_list are optional and will default to reasonable
X * values.
X */
X{
X TableDefLocPtr result, idx;
X Cardinal len;
X String spec;
X String orig;
X
X /* Make a copy for safety */
X if (layout && ((len = DefSpecLen(layout)) > 0)) {
X orig = layout = XtNewString(layout);
X result = (TableDefLocPtr) XtCalloc(len+1, sizeof(struct _TableDefLoc));
X idx = result;
X while (spec = GetSpec(&layout)) {
X DefParse(spec, idx);
X idx++;
X }
X /* null terminate */
X idx->w_name = (String) 0;
X XtFree(orig);
X return (caddr_t) result;
X } else {
X return (caddr_t) 0;
X }
X /*NOTREACHED*/
X}
X
Xvoid XtTblPosition(w, col, row)
XWidget w; /* Widget to position */
XPosition col, row; /* Position in array */
X/*
X * This routine positions a widget that has been created
X * under a widget of class tableWidgetClass. The widget
X * will be placed at column `col' and row `row'. If
X * the widget has never been placed before, it will
X * span only one space in each direction and its
X * options will be the defaults for the table widget.
X */
X{
X Position old_row, old_col;
X Dimension old_hspan, old_vspan;
X XtTblMask old_opts;
X
X if (TblFindChild(w, &old_col, &old_row, &old_hspan, &old_vspan, &old_opts)) {
X TblPositionChild(w, col, row, old_hspan, old_vspan, old_opts);
X } else {
X TblPositionChild(w, col, row, 1, 1, TBL_DEF_OPT);
X }
X}
X
Xvoid XtTblResize(w, h_span, v_span)
XWidget w; /* Widget to resize */
XDimension h_span, v_span; /* New widget span */
X/*
X * This routine changes the span of widget `w' to (`h_span', `v_span').
X * If the widget has never been placed before, it will be located
X * at (0,0) and its options will be the defaults for its
X * parent table widget.
X */
X{
X Position old_row, old_col;
X Dimension old_hspan, old_vspan;
X XtTblMask old_opts;
X
X if (TblFindChild(w, &old_col, &old_row, &old_hspan, &old_vspan, &old_opts)) {
X TblPositionChild(w, old_col, old_row, h_span, v_span, old_opts);
X } else {
X TblPositionChild(w, 0, 0, h_span, v_span, TBL_DEF_OPT);
X }
X}
X
Xvoid XtTblOptions(w, opt)
XWidget w; /* Widget to change */
XXtTblMask opt; /* New option mask */
X/*
X * This routine changes the options of widget `w' to `opt'. If
X * the widget has never been placed before, it will be located
X * and (0,0) with a span of (1,1) and its options will be the
X * default options for its parent table widget. The option
X * mask is as described for TblPositionChild.
X */
X{
X Position old_row, old_col;
X Dimension old_hspan, old_vspan;
X XtTblMask old_opts;
X
X if (TblFindChild(w, &old_col, &old_row, &old_hspan, &old_vspan, &old_opts)) {
X TblPositionChild(w, old_col, old_row, old_hspan, old_vspan, opt);
X } else {
X TblPositionChild(w, 0, 0, 1, 1, opt);
X }
X}
X
Xvoid XtTblConfig(w, col, row, h_span, v_span, opt)
XWidget w; /* Widget to position */
XPosition col, row; /* Position in array */
XDimension h_span, v_span; /* Horizonal and vertical span */
XXtTblMask opt; /* Widget placement options */
X/*
X * This routine positions a widget that has been created
X * under a widget of class tableWidgetClass. The widget
X * will be placed at column `col' and row `row'. The
X * widget will span the distances given by `h_span' and `v_span'.
X * The options argument is as described for TblPositionChild.
X */
X{
X TblPositionChild(w, col, row, h_span, v_span, opt);
X}
X
XWidget XtCreateTable(parent, name, arglist, argcount)
XWidget parent;
Xchar * name;
XArgList arglist;
XCardinal argcount;
X
X{
X return(XtCreateWidget(name, tableWidgetClass, parent, arglist, argcount));
X}
+FUNKY+STUFF+
echo '-rw-rw-r-- 1 david 50711 Oct 15 13:22 Table_m.c (as sent)'
chmod u=rw,g=rw,o=r Table_m.c
ls -l Table_m.c
echo x - Table_m.h
sed 's/^X//' > Table_m.h <<'+FUNKY+STUFF+'
X/*
X * Table - Forms-based composite widget/geometry manager for the X Toolkit
X *
X * David Harrison
X * University of California, Berkeley
X * 1989
X *
X * This file contains the Table public declarations.
X */
X
X#ifndef _Table_h
X#define _Table_h
X
X/*
X * Table Widget Parameters
X *
X * Name Class RepType Default Value
X *
X * background Background Pixel XtDefaultBackground
X * border BorderColor Pixel XtDefaultForeground
X * borderWidth BorderWidth Dimension 0
X * x Position Position 0
X * y Position Position 0
X * width Width Dimension (computed)
X * height Height Dimension (computed)
X * mappedWhenManaged MappedWhenManaged Boolean True
X * sensitive Sensitive Boolean True
X * layout Layout String NULL
X * internalHeight Height Dimension 0
X * internalWidth Width Dimension 0
X * columnSpacing Spacing Dimension 0
X * rowSpacing Spacing Dimension 0
X */
X
X#define XtNlayout "layout"
X#define XtNcolumnSpacing "columnSpacing"
X#define XtNrowSpacing "rowSpacing"
X#define XtNdefaultOptions "defaultOptions"
X
X#define XtCLayout "Layout"
X#ifndef XtCSpacing
X#define XtCSpacing "Spacing"
X#endif
X#define XtCOptions "Options"
X
X#define XtROptions "Options"
X
X/*
X * Option masks
X */
X#define TBL_LEFT (1<<0)
X#define TBL_RIGHT (1<<1)
X#define TBL_TOP (1<<2)
X#define TBL_BOTTOM (1<<3)
X#define TBL_SM_WIDTH (1<<4)
X#define TBL_SM_HEIGHT (1<<5)
X#define TBL_LK_WIDTH (1<<6)
X#define TBL_LK_HEIGHT (1<<7)
X
X#define TBL_DEF_OPT -1
X
Xtypedef int XtTblMask;
X
X/*
X * Opaque class and instance records
X */
X
Xtypedef struct _TableClassRec *TableWidgetClass;
Xtypedef struct _TableRec *TableWidget;
X
Xextern WidgetClass tableWidgetClass;
X
X/*
X * Public access routines
X */
X
Xextern caddr_t XtTblParseLayout();
X /* String layout; */
X
Xextern void XtTblPosition();
X /*
X * Widget w;
X * Position col, row;
X */
X
Xextern void XtTblResize();
X /*
X * Widget w;
X * Dimension h_span, v_span;
X */
X
Xextern void XtTblOptions();
X /*
X * Widget w;
X * XtTblMask opt;
X */
X
Xextern void XtTblConfig();
X /*
X * Widget w;
X * Position col, row;
X * Dimension h_span, v_span;
X * XtTblMask opt;
X */
X
Xextern Widget XtCreateTable();
X/*
XWidget parent;
Xchar * name;
XArgList arglist;
XCardinal argcount;
X*/
X
X#endif /* _Table_h */
X
+FUNKY+STUFF+
echo '-rw-rw-r-- 1 david 2227 Oct 15 13:05 Table_m.h (as sent)'
chmod u=rw,g=rw,o=r Table_m.h
ls -l Table_m.h
echo x - Table_mP.h
sed 's/^X//' > Table_mP.h <<'+FUNKY+STUFF+'
X/*
X * Table - Forms-based composite widget/geometry manager for the X Toolkit
X *
X * David Harrison
X * University of California, Berkeley
X * 1989
X *
X * This file contains the Table private declarations.
X */
X
X#ifndef _TableP_h
X#define _TableP_h
X
X#include "Table_m.h"
X#include <Xm/XmP.h>
X#include <Xm/BulletinBP.h>
X
X/*
X * Local definitions
X */
X
Xtypedef void (*XtTblRProc)();
X /*
X * Widget table;
X * Widget subwidget;
X * Position r, c;
X * Dimension hspan, vspan;
X * XtTblMask options;
X */
X
Xtypedef Boolean (*XtTblLProc)();
X /*
X * Widget w;
X * Position *r, *c;
X * Dimension *hspan, *vspan;
X * XtTblMask *options;
X */
X
Xtypedef struct _TableLocTbl *TableLocTblPtr;
X /*
X * Opaque reference to actual widget location table
X * defined in Table.c
X */
X
Xtypedef struct _TableDefLoc *TableDefLocPtr;
X /*
X * Opaque reference to default widget location table defined
X * in Table.c.
X */
X
Xtypedef struct _TableVector *TableVecPtr;
X /*
X * Opaque reference to vectors used for giving size of
X * each row and column.
X */
X
Xtypedef enum _TableVecState { INVALID, MINIMUM } TableVecState;
X
X/*
X * Information kept in class record
X */
X
Xtypedef struct {
X XtTblRProc position_child; /* Register location of some child widget */
X XtTblLProc find_child; /* Return information about a child widget */
X} TableClassPart;
X
X/*
X * Class hierarchy
X */
X
Xtypedef struct _TableClassRec {
X CoreClassPart core_class;
X CompositeClassPart composite_class;
X ConstraintClassPart constraint_class;
X XmManagerClassPart manager_class;
X XmBulletinBoardClassPart bulletin_class;
X TableClassPart table_class;
X} TableClassRec;
X
Xextern TableClassRec tableClassRec;
X
X/*
X * Information in instance record
X */
X
Xtypedef struct _TablePart {
X Dimension int_width; /* Inner horizontal padding */
X Dimension int_height; /* Inner vertical padding */
X Dimension row_spacing; /* Space between rows */
X Dimension col_spacing; /* Space between columns */
X XtTblMask def_options; /* Default layout options */
X TableDefLocPtr init_layout; /* Initial layout spec from resource */
X TableDefLocPtr layout_db; /* Merged table */
X TableLocTblPtr real_layout; /* Actual current layout information */
X TableVecState vec_state; /* Current state of vectors */
X Cardinal num_rows; /* Number of rows */
X TableVecPtr rows; /* Heights of each row */
X Cardinal num_cols; /* Number of columns */
X TableVecPtr cols; /* Widths of each column */
X Cardinal vec_height; /* Sum of current rows */
X Cardinal vec_width; /* Sum of current columns */
X} TablePart;
X
X/*
X * Instance hierarchy
X */
X
Xtypedef struct _TableRec {
X CorePart core;
X CompositePart composite;
X ConstraintPart constraint;
X XmManagerPart manager;
X XmBulletinBoardPart bulletin_board;
X TablePart table;
X} TableRec;
X
X#endif /* _TableP_h */
+FUNKY+STUFF+
echo '-rw-rw-r-- 1 david 3083 Oct 15 13:05 Table_mP.h (as sent)'
chmod u=rw,g=rw,o=r Table_mP.h
ls -l Table_mP.h
exit 0
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
--
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list