staden-lg/src/staden/Sheet.c

1223 lines
31 KiB
C

#include <X11/copyright.h>
/* $XConsortium: Sheet.c,v 1.2 88/10/25 17:40:25 swick Exp $ */
/* Copyright Massachusetts Institute of Technology 1987, 1988 */
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include "SheetP.h"
#include <stdio.h>
#include <sys/types.h>
/* ---- Forward declarations ---- */
static void Initialize(Widget request, Widget new,
ArgList args, Cardinal *num_args);
static void Destroy(Widget w);
static void Redisplay(Widget w, XEvent *event, Region region);
static void Resize(Widget w);
static void InputAction(Widget w, XEvent *event,
String *params,Cardinal *num_params);
static Boolean SetValues(Widget current, Widget request, Widget new,
ArgList args, Cardinal *num_args);
static void destroy_array(sheet_array a);
static sheet_array create_array (int r, int c, size_t s);
static void move_array (sheet_array a, sheet_array b);
static void extend_array (sheet_array *a, int r, int c);
static char *get_array_element(sheet_array a, int r, int c);
/* ---- Private data ---- */
static XtResource resources[] = {
#define offset(field) XtOffset(SheetWidget, field)
/* {name, class, type, size, offset, default_type, default_addr}, */
{ XtNcallback, XtCCallback, XtRCallback, (Cardinal)sizeof(XtCallbackList),
offset(sheet.input_callback), XtRCallback, NULL },
{ XtNexposeCallback, XtCCallback, XtRCallback,
(Cardinal)sizeof(XtCallbackList),
offset(sheet.expose_callback), XtRCallback, NULL },
{ XtNfont, XtCFont, XtRFontStruct, (Cardinal)sizeof(XFontStruct*),
offset(sheet.font), XtRString, XtDefaultFont },
{ XtNheight, XtCHeight, XtRDimension, (Cardinal)sizeof(Dimension),
offset(core.height), XtRImmediate, (caddr_t)1},
{ XtNwidth, XtCWidth, XtRDimension, (Cardinal)sizeof(Dimension),
offset(core.width), XtRImmediate, (caddr_t)1},
{ XtNresizeCallback, XtCCallback, XtRCallback,
(Cardinal)sizeof(XtCallbackList),
offset(sheet.resize_callback), XtRCallback, NULL },
{ XtNrows, XtCHeight, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.rows), XtRImmediate, (caddr_t)10},
{ XtNcolumns, XtCWidth, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.columns), XtRImmediate, (caddr_t)80},
{ XtNleftMargin, XtCMargin, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.margin.left), XtRImmediate, (caddr_t)4},
{ XtNrightMargin, XtCMargin, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.margin.right), XtRImmediate, (caddr_t)4},
{ XtNtopMargin, XtCMargin, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.margin.top), XtRImmediate, (caddr_t)4},
{ XtNbottomMargin, XtCMargin, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.margin.bottom), XtRImmediate, (caddr_t)4},
{XtNforeground, XtCForeground, XtRPixel, (Cardinal)sizeof (Pixel),
offset(sheet.foreground), XtRString, XtDefaultForeground},
{XtNbackground, XtCBackground, XtRPixel, (Cardinal)sizeof (Pixel),
offset(sheet.background), XtRString, XtDefaultBackground},
{XtNcursor, XtCCursor, XtRCursor, (Cardinal)sizeof(Cursor),
offset(simple.cursor), XtRString, "xterm"},
{XtNdisplayCursor, XtCOutput, XtRBoolean, (Cardinal)sizeof(Boolean),
offset(sheet.display_cursor), XtRImmediate, (caddr_t)False},
{XtNcursorRow, XtCWidth, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.cursor_row), XtRImmediate, (caddr_t)0},
{XtNcursorColumn, XtCHeight, XtRDimension, (Cardinal)sizeof(Dimension),
offset(sheet.cursor_column), XtRImmediate, (caddr_t)0},
#undef offset
};
static XtActionsRec actions[] =
{
/* {name, procedure}, */
{"input", InputAction},
};
static char translations[] =
"<Key>: input() \n\
<BtnDown>: input() \
";
SheetClassRec sheetClassRec = {
{ /* core fields initial values */
/* superclass */ (WidgetClass) &simpleClassRec,
/* class_name */ "Sheet",
/* widget_size */ (Cardinal)sizeof(SheetRec),
/* class_initialize */ NULL,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ actions,
/* num_actions */ XtNumber(actions),
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ XtExposeNoCompress,
/* compress_exposure XtExposeCompressMaximal, */
/* 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 */ translations,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ XtInheritDisplayAccelerator,
/* extension */ NULL
},
{ /* Simple class initial values */
/* change_sensitive */ XtInheritChangeSensitive
},
{ /* Sheet class initial values */
/* empty */ 0
}
};
WidgetClass sheetWidgetClass = (WidgetClass)&sheetClassRec;
/* ---- Private procedures --- */
int binary_op(int src, int dst, int op)
{
switch (op & HOP_MASK) {
case 0: return 0;
case 1: return ~ (src | dst);
case 2: return ~src & dst;
case 3: return ~src;
case 4: return src & ~dst;
case 5: return ~dst;
case 6: return src ^ dst;
case 7: return ~(src & dst);
case 8: return src & dst;
case 9: return ~src ^ ~dst;
case 10: return dst;
case 11: return ~src|dst;
case 12: return src;
case 13: return src|~dst;
case 14: return src|dst;
case 15: return 1;
}
}
#define GET_ARRAY_CELL(A,R,C)\
( &A->base[(R * A->cols + C)*A->size] )
static void destroy_array(sheet_array a)
{
XtFree (a->base);
XtFree ((char *)a);
}
static sheet_array create_array (int r, int c, size_t s)
{
sheet_array new = (sheet_array) XtCalloc (1,sizeof(sheet_array_struct));
if (new != NULL) {
new->base = (char *) XtCalloc (r*c,s);
if (new->base == NULL) {
XtFree ((char *)new);
new = NULL;
} else {
new->rows = r;
new->cols = c;
new->size = s;
}
}
return new;
}
#define min(A,B) ((A < B) ? A : B)
static void move_array (sheet_array a, sheet_array b)
{
size_t r,c;
int i;
c = min (a->cols*a->size, b->cols*b->size);
r = min (a->rows, b->rows);
for (i=0; i<r; i++)
memcpy(
(char *) GET_ARRAY_CELL(b,i,0),
(char *) GET_ARRAY_CELL(a,i,0),
c
);
}
#undef min
static void extend_array (sheet_array *a, int r, int c)
/*
** Extending stategy: For rows.
** Do rows really need extending?
** Yes:
** Will twice old rows do?
** Yes:
** Use twice old rows.
** No:
** Use new rows plus EXTEND_ROWS_GUESS (A wild quess that's enough)
** No:
** Don't extend
**
** Extending stategy: For columns.
** As for rows.
*/
{
int newr;
int newc;
sheet_array b;
#define EXTEND_ROWS_GUESS 5
#define EXTEND_COLS_GUESS 5
newr = (r<=(*a)->rows)
?(*a)->rows
:(r<=(*a)->rows*2)
?(*a)->rows*2
:r+EXTEND_ROWS_GUESS;
if (newr > SHEET_MAX_ROWS) newr= SHEET_MAX_ROWS;
newc = (c<=(*a)->cols)
?(*a)->cols
:(c<=(*a)->cols*2)
?(*a)->cols*2
:r+EXTEND_COLS_GUESS;
if (newc > SHEET_MAX_COLS) newc= SHEET_MAX_COLS;
if (newr!=(*a)->rows || newc!=(*a)->cols) {
b = create_array(newr,newc,(*a)->size);
move_array(*a,b);
destroy_array(*a);
*a = b;
}
}
/*
static char * get_array_element(sheet_array a, int r, int c)
{
if (r < 0 || c < 0)
return NULL;
if (a->rows > r || a->cols > c)
return NULL;
return GET_ARRAY_CELL(a,r,c);
}
*/
/* ---- Private Routines ---- */
#define fontWidth(F) ((F)->max_bounds.width)
#define fontHeight(F) ((F)->max_bounds.ascent + (F)->max_bounds.descent)
#define COL_TO_PIXEL(W,C) \
((W)->sheet.font->max_bounds.width * (C) + (W)->sheet.margin.left)
#define ROW_TO_BASELINE_PIXEL(W,R) \
(fontHeight((W)->sheet.font) * (R) + (W)->sheet.margin.top + (W)->sheet.font->max_bounds.ascent)
#define ROW_TO_PIXEL(W,R) \
(fontHeight((W)->sheet.font) * ((R)+1) + (W)->sheet.margin.top)
#define PIXEL_TO_COL(W,P) \
(((long)(P) - (long)(W)->sheet.margin.left) / (long)(W)->sheet.font->max_bounds.width)
#define PIXEL_WIDTH_TO_COLS(W,P) \
(((long)(P) - (long)(W)->sheet.margin.left - (long)(W)->sheet.margin.right) / (long)(W)->sheet.font->max_bounds.width)
#define COLS_TO_PIXEL_WIDTH(W,C) \
(((C) * (W)->sheet.font->max_bounds.width) + (W)->sheet.margin.left + (W)->sheet.margin.right)
#define BASELINE_PIXEL_TO_ROW(W,P) \
(((long)(P) - (long)(W)->sheet.margin.top - (long)(W)->sheet.font->max_bounds.ascent) / (long)fontHeight((W)->sheet.font) )
#define PIXEL_TO_ROW(W,P) \
(((long)(P) - (long)(W)->sheet.margin.top) / (long)fontHeight((W)->sheet.font) )
#define PIXEL_HEIGHT_TO_ROWS(W,P) \
(((long)(P) - (long)(W)->sheet.margin.top - (long)(W)->sheet.margin.bottom) / (long)fontHeight((W)->sheet.font) )
#define ROWS_TO_PIXEL_HEIGHT(W,R) \
(((R) * fontHeight((W)->sheet.font)) + (W)->sheet.margin.top + (W)->sheet.margin.bottom)
#define FONT_WIDTH(W) (fontWidth((W)->sheet.font))
#define FONT_HEIGHT(W) (fontHeight((W)->sheet.font))
static void setGC(SheetWidget sw, GC gc, sheet_ink ink_base)
{
if (ink_base->sh & sh_inverse) {
if (ink_base->sh&sh_bg)
XSetForeground(XtDisplay(sw),gc,ink_base->bg);
else
XSetForeground(XtDisplay(sw),gc,sw->sheet.background);
if (ink_base->sh&sh_fg)
XSetBackground(XtDisplay(sw),gc,ink_base->fg);
else
XSetBackground(XtDisplay(sw),gc,sw->sheet.foreground);
} else {
if (ink_base->sh&sh_fg)
XSetForeground(XtDisplay(sw),gc,ink_base->fg);
else
XSetForeground(XtDisplay(sw),gc,sw->sheet.foreground);
if (ink_base->sh&sh_bg)
XSetBackground(XtDisplay(sw),gc,ink_base->bg);
else
XSetBackground(XtDisplay(sw),gc,sw->sheet.background);
}
}
static void redrawCursor(SheetWidget sw, Boolean draw);
static void old_repaint(SheetWidget sw, int c, int r, int l, sheet_ink ink, char *s)
{
/*
int cursorZapped;
cursorZapped = (sw->sheet.display_cursor &&
sw->sheet.cursor_row >= r &&
sw->sheet.cursor_row < (r+l) &&
sw->sheet.cursor_column == c);
*/
if (ink->sh==sh_default) {
XDrawImageString(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.normgc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
} else {
if (ink->sh & sh_light) {
if (DisplayPlanes(XtDisplay(sw),DefaultScreen(XtDisplay(sw)))==1){
XFillRectangle(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.whitegc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_PIXEL(sw,r-1),
FONT_WIDTH(sw) * l,
FONT_HEIGHT(sw)
);
setGC(sw, sw->sheet.greygc, ink);
XDrawString(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.greygc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
} else {
sheet_ink_struct my_ink;
my_ink.sh = sh_fg;
my_ink.fg = sw->sheet.light;
setGC(sw, sw->sheet.sparegc, &my_ink);
XDrawImageString(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.sparegc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
}
} else {
if (DisplayPlanes(XtDisplay(sw),DefaultScreen(XtDisplay(sw)))==1){
XFillRectangle(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.greygc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_PIXEL(sw,r-1),
FONT_WIDTH(sw) * l,
FONT_HEIGHT(sw)
);
XDrawString(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.normgc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
} else {
setGC(sw, sw->sheet.sparegc, ink);
XDrawImageString(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.sparegc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
}
}
if (ink->sh & sh_select || ink->sh & sh_underline) {
setGC(sw, sw->sheet.sparegc, ink);
XDrawLine(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.sparegc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
(int) COL_TO_PIXEL(sw,c+l)-1,
(int) ROW_TO_BASELINE_PIXEL(sw,r)
);
}
}
/*
if (cursorZapped)
redrawCursor(sw,True);
*/
}
static void _repaint_colour(SheetWidget sw, int c, int r, int l, sheet_ink ink, char *s)
{
sheet_ink_struct my_ink;
my_ink = *ink;
if (ink->sh & sh_light) {
my_ink.sh = (my_ink.sh | sh_fg) & ~sh_bg;
my_ink.fg = sw->sheet.light;
}
setGC(sw, sw->sheet.sparegc, &my_ink);
XDrawImageString(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.sparegc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
if (ink->sh & sh_select || ink->sh & sh_underline) {
XDrawLine(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.sparegc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
(int) COL_TO_PIXEL(sw,c+l)-1,
(int) ROW_TO_BASELINE_PIXEL(sw,r)
);
}
}
static void _repaint_monochrome(SheetWidget sw, int c, int r, int l, sheet_ink ink, char *s)
{
GC fg_gc;
GC bg_gc;
#define L ( ink->sh & sh_light )
#define I ( ink->sh & sh_inverse )
#define BG ( ink->sh & (sh_bg | sh_fg) )
/*
** bg_determination
*/
bg_gc = ( I && !L ) ? sw->sheet.normgc :
(I || (!L && BG)) ? sw->sheet.greygc :
sw->sheet.whitegc;
/*
** fg_determination
*/
fg_gc = ( !I && !L ) ? sw->sheet.normgc :
(!I || (!L && BG)) ? sw->sheet.greygc :
sw->sheet.whitegc;
#undef L
#undef I
#undef BG
XFillRectangle(
XtDisplay(sw),
XtWindow(sw),
bg_gc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_PIXEL(sw,r-1),
FONT_WIDTH(sw) * l,
FONT_HEIGHT(sw)
);
XDrawString(
XtDisplay(sw),
XtWindow(sw),
fg_gc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
if (ink->sh & sh_select || ink->sh & sh_underline) {
setGC(sw, sw->sheet.sparegc, ink);
XDrawLine(
XtDisplay(sw),
XtWindow(sw),
fg_gc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
(int) COL_TO_PIXEL(sw,c+l)-1,
(int) ROW_TO_BASELINE_PIXEL(sw,r)
);
}
}
static void _repaint(SheetWidget sw, int c, int r, int l, sheet_ink ink, char *s)
{
if (ink->sh==sh_default) {
XDrawImageString(
XtDisplay(sw),
XtWindow(sw),
sw->sheet.normgc,
(int) COL_TO_PIXEL(sw,c),
(int) ROW_TO_BASELINE_PIXEL(sw,r),
s,
l);
} else {
if (DisplayPlanes(XtDisplay(sw),DefaultScreen(XtDisplay(sw)))==1)
_repaint_monochrome(sw,c,r,l,ink,s);
else
_repaint_colour(sw,c,r,l,ink,s);
}
}
static void redrawCursor(SheetWidget sw, Boolean draw)
{
XawSheetRow r = sw->sheet.cursor_row;
XawSheetColumn c = sw->sheet.cursor_column;
sheet_ink ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c);
sheet_paper paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
sheet_ink_struct ink;
int cursor_was;
/* check cursor is on screen */
if (r < 0 || r > sw->sheet.rows-1 ||
c < 0 || c > sw->sheet.columns-1 ) return;
ink.fg = ink_base->fg;
ink.bg = ink_base->bg;
if (draw)
ink.sh = ink_base->sh | sh_inverse;
else
ink.sh = ink_base->sh;
/*
cursor_was = sw->sheet.display_cursor;
sw->sheet.display_cursor = 0;
*/
_repaint(sw, c, r, 1, &ink, paper_base);
/*
sw->sheet.display_cursor = cursor_was;
*/
}
static void repaintText(SheetWidget sw, int c, int r, int l)
{
sheet_ink ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c);
sheet_ink ink_peek;
sheet_paper paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
sheet_paper paper_peek;
XawSheetColumn c_peek;
int i;
while (l > 0) {
/* find stretch where all hilight the same */
ink_peek = ink_base;
ink_peek++;
paper_peek = paper_base;
paper_peek++;
c_peek = c;
c_peek++;
i = 1;
l--;
#define implies(A,B) ((B)|!(A))
while ( (l > 0) &&
(ink_peek->sh == ink_base->sh) &&
implies(ink_base->sh&sh_fg,ink_peek->fg==ink_base->fg) &&
implies(ink_base->sh&sh_bg,ink_peek->bg==ink_base->bg) ) {
ink_peek++;
paper_peek++;
c_peek++;
i++;
l--;
}
_repaint(sw, c, r, i, ink_base, paper_base);
paper_base = paper_peek;
ink_base = ink_peek;
c = c_peek;
}
}
static void redisplayRegion(Widget w, XRectangle *expose)
{
SheetWidget sw = (SheetWidget) w;
sheet_ink cell;
int tlc,brc,c;
int tlr,brr,r;
tlc = PIXEL_TO_COL(sw,expose->x);
tlr = PIXEL_TO_ROW(sw,expose->y);
brc = PIXEL_TO_COL(sw,expose->x+expose->width-1)+1;
brr = PIXEL_TO_ROW(sw,expose->y+expose->height-1)+1;
if (tlc < 0) tlc = 0;
if (tlr < 0) tlr = 0;
if (brc < 0) brc = 0;
if (brr < 0) brr = 0;
if (tlc >= sw->sheet.columns) tlc = sw->sheet.columns-1;
if (tlr >= sw->sheet.rows) tlr = sw->sheet.rows-1;
if (brc >= sw->sheet.columns) brc = sw->sheet.columns-1;
if (brr >= sw->sheet.rows) brr = sw->sheet.rows-1;
for (r=tlr;r<=brr;r++) {
repaintText(sw, tlc, r, brc-tlc+1);
}
if (sw->sheet.display_cursor &&
sw->sheet.cursor_row >= tlr &&
sw->sheet.cursor_row <= brr &&
sw->sheet.cursor_column >= tlc &&
sw->sheet.cursor_column <= brc)
{
/* better redraw cursor */
redrawCursor(sw,True);
}
}
/* ---- Exported procedures ---- */
void XawSheetPutText(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l, String s)
/*
** Put plain text
*/
{
SheetWidget sw = (SheetWidget) w;
int i;
sheet_ink ink_base;
sheet_paper paper_base;
String sp;
if (r>=0 && r<sw->sheet.rows &&
c+l>0 && c<sw->sheet.columns &&
l > 0) {
if (c<0) { l += c; s -= c; c = 0; }
if (c+l>sw->sheet.columns) l = sw->sheet.columns - c;
for (
i = 0, sp = s,
ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c),
paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
i < l;
i++, ink_base++, paper_base++, sp++) {
ink_base->sh = sh_default;
*paper_base = *sp;
}
if (XtIsRealized(w)) {
_repaint(sw, c, r, l, (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c), s);
if (sw->sheet.display_cursor &&
sw->sheet.cursor_row == r &&
sw->sheet.cursor_column >= c &&
sw->sheet.cursor_column < c+l)
{
/* better redraw cursor */
redrawCursor(sw,True);
}
}
}
}
void XawSheetPutJazzyText(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l, String s, XawSheetInk *ink_list)
/*
** Put multi-coloured text
*/
{
SheetWidget sw = (SheetWidget) w;
int i;
sheet_ink ink_base;
sheet_paper paper_base;
String sp;
if (r>=0 && r<sw->sheet.rows &&
c+l>0 && c<sw->sheet.columns &&
l > 0) {
if (c<0) { l += c; s -= c; c = 0; }
if (c+l>sw->sheet.columns) l = sw->sheet.columns - c;
for (
i = 0, sp = s,
ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c),
paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
i < l;
i++, ink_base++, ink_list++, paper_base++, sp++) {
ink_base->fg = ink_list->fg;
ink_base->bg = ink_list->bg;
ink_base->sh = ink_list->sh;
*paper_base = *sp;
}
if (XtIsRealized(w)) {
repaintText(sw, c, r, l);
if (sw->sheet.display_cursor &&
sw->sheet.cursor_row == r &&
sw->sheet.cursor_column >= c &&
sw->sheet.cursor_column < c+l)
{
/* better redraw cursor */
redrawCursor(sw,True);
}
}
}
}
void XawSheetPutHilightText(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l, String s)
/*
** Put text using default hilights
*/
{
SheetWidget sw = (SheetWidget) w;
int i;
sheet_ink ink_base;
sheet_paper paper_base;
String sp;
if (r>=0 && r<sw->sheet.rows &&
c+l>0 && c<sw->sheet.columns &&
l > 0) {
if (c<0) { l += c; s -= c; c = 0; }
if (c+l>sw->sheet.columns) l = sw->sheet.columns - c;
for (
i = 0, sp = s,
ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c),
paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
i < l;
i++, ink_base++, paper_base++, sp++) {
ink_base->sh = sw->sheet.default_sh;
ink_base->fg = sw->sheet.default_fg;
ink_base->bg = sw->sheet.default_bg;
*paper_base = *sp;
}
if (XtIsRealized(w)) {
_repaint(sw, c, r, l, (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c), s);
if (sw->sheet.display_cursor &&
sw->sheet.cursor_row == r &&
sw->sheet.cursor_column >= c &&
sw->sheet.cursor_column < c+l)
{
/* better redraw cursor */
redrawCursor(sw,True);
}
}
}
}
void XawSheetHilightText(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l, Pixel fg, Pixel bg, XawSheetHilight h)
/*
** Hilight already draw text
*/
{
SheetWidget sw = (SheetWidget) w;
sheet_ink ink_base;
sheet_paper paper_base;
/*
Hilights currently supported:
sh_default yes
sh_fg yes
sh_bg yes
sh_underline yes
sh_inverse yes
sh_light no
sh_tick no
sh_bold no
sh_italic no
*/
if (r>=0 && r<sw->sheet.rows &&
c+l>0 && c<sw->sheet.columns &&
l > 0) {
int i;
if (c<0) { l += c; c = 0; }
if (c+l>sw->sheet.columns) l = sw->sheet.columns - c;
for (
i = 0,
ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c),
paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
i < l;
i++, ink_base++, paper_base++)
{
if (h==sh_default) {
ink_base->sh = sh_default;
} else {
if (h & sh_fg) ink_base->fg = fg;
if (h & sh_bg) ink_base->bg = bg;
ink_base->sh |= h;
}
}
repaintText(sw, (int)c, (int)r, (int)l);
}
}
void XawSheetUnhilightText(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l, Pixel fg, Pixel bg, XawSheetHilight h)
/*
** Remove hilighting from text
*/
{
SheetWidget sw = (SheetWidget) w;
sheet_ink ink_base;
sheet_paper paper_base;
if (r>=0 && r<sw->sheet.rows &&
c+l>0 && c<sw->sheet.columns &&
l > 0) {
int i;
if (c<0) { l += c; c = 0; }
if (c+l>sw->sheet.columns) l = sw->sheet.columns - c;
for (
i = 0,
ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c),
paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
i < l;
i++, ink_base++, paper_base++)
{
if (h==sh_default) {
} else {
if (h & sh_fg) ink_base->fg = fg;
if (h & sh_bg) ink_base->bg = bg;
ink_base->sh &= !h&sh_mask;
}
}
repaintText(sw, (int)c, (int)r, (int)l);
}
}
void XawSheetOpHilightText(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l, XawSheetHilight h, int op)
/*
** Perform boolean operations on text
*/
{
SheetWidget sw = (SheetWidget) w;
sheet_ink ink_base;
sheet_paper paper_base;
if (r>=0 && r<sw->sheet.rows &&
c+l>0 && c<sw->sheet.columns &&
l > 0) {
int i;
if (c<0) { l += c; c = 0; }
if (c+l>sw->sheet.columns) l = sw->sheet.columns - c;
for (
i = 0,
ink_base = (sheet_ink) GET_ARRAY_CELL(sw->sheet.ink,r,c),
paper_base = (sheet_paper) GET_ARRAY_CELL(sw->sheet.paper,r,c);
i < l;
i++, ink_base++, paper_base++)
{
ink_base->sh = binary_op(h,ink_base->sh,op)&sh_mask;
}
repaintText(sw, (int)c, (int)r, (int)l);
if (sw->sheet.display_cursor &&
sw->sheet.cursor_row == r &&
sw->sheet.cursor_column >= c &&
sw->sheet.cursor_column < c+l)
{
/* better redraw cursor */
redrawCursor(sw,True);
}
}
}
void XawSheetPositionCursor(Widget w, XawSheetColumn c, XawSheetRow r)
{
SheetWidget sw = (SheetWidget) w;
if (XtIsRealized(w) && sw->sheet.display_cursor)
redrawCursor(sw,False);
sw->sheet.cursor_column = c;
sw->sheet.cursor_row = r;
if (XtIsRealized(w) && sw->sheet.display_cursor)
redrawCursor(sw,True);
}
void XawSheetDisplayCursor(Widget w, Boolean b)
{
SheetWidget sw = (SheetWidget) w;
if (sw->sheet.display_cursor^b) {/*state change*/
sw->sheet.display_cursor = b;
if (XtIsRealized(w)) redrawCursor(sw, b);
}
}
Pixel XawSheetColourNameToPixel(Widget w, String c)
{
XColor rgb_db_def, hardware_def;
Colormap cmap;
Status s;
cmap = DefaultColormap(XtDisplay(w),DefaultScreen(XtDisplay(w)));
s = XAllocNamedColor(XtDisplay(w), cmap, c, &rgb_db_def, &hardware_def);
return hardware_def.pixel;
}
void XawSheetSetHilight(Widget w, Pixel fg, Pixel bg, XawSheetHilight h)
{
SheetWidget sw = (SheetWidget) w;
if (h & sh_fg) sw->sheet.default_fg = fg;
if (h & sh_bg) sw->sheet.default_bg = bg;
sw->sheet.default_sh = h;
}
void XawSheetSetRows(Widget w, XawSheetRow r)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetSetColumns(Widget w, XawSheetColumn c)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetDeleteRow(Widget w, XawSheetRow r)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetDeleteColumn(Widget w, XawSheetColumn c)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetInsertRow(Widget w, XawSheetRow r)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetInsertColumn(Widget w, XawSheetColumn c)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetInsert(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetDelete(Widget w, XawSheetColumn c, XawSheetRow r, Dimension l)
{
SheetWidget sw = (SheetWidget) w;
}
void XawSheetClearSheet(Widget w)
{
SheetWidget sw = (SheetWidget) w;
}
/* ---- Private procedures -- Class Methods ---- */
static Pixel ColourNameToPixel(Widget w, String c)
{
XColor rgb_db_def, hardware_def;
Colormap cmap;
Status s;
cmap = DefaultColormap(XtDisplay(w),DefaultScreen(XtDisplay(w)));
s = XAllocNamedColor(XtDisplay(w), cmap, c, &rgb_db_def, &hardware_def);
return hardware_def.pixel;
}
static void Initialize(Widget request, Widget new,
ArgList args, Cardinal *num_args)
{ SheetWidget sw = (SheetWidget)new;
Display *display;
int screen;
display = XtDisplay(request);
screen = DefaultScreen(display);
if (DisplayPlanes(display,screen)==1)
{ /* We are on a one-plane monochrome display.
Use dashes to make lines distinguishable.
*/
}
else
{ /* Some sort of multi-plane display.
*/
}
sw->sheet.paper = create_array(sw->sheet.rows,sw->sheet.columns, sizeof(sheet_paper_struct));
sw->sheet.ink = create_array(sw->sheet.rows,sw->sheet.columns, sizeof(sheet_ink_struct));
sw->sheet.cursor.row = 0;
sw->sheet.cursor.column = 0;
sw->sheet.cursor.visible = False;
sw->sheet.default_sh = sh_default;
/* get font details */
sw->sheet.width_in_pixels = COLS_TO_PIXEL_WIDTH(sw,sw->sheet.columns);
sw->sheet.height_in_pixels = ROWS_TO_PIXEL_HEIGHT(sw,sw->sheet.rows);
sw->core.width = sw->sheet.width_in_pixels;
sw->core.height = sw->sheet.height_in_pixels;
/* GCs and things */
{
XtGCMask valuemask = (GCFont |
GCGraphicsExposures | GCForeground | GCBackground );
XGCValues values;
values.font = sw->sheet.font->fid;
values.graphics_exposures = (Bool) FALSE;
values.foreground = sw->sheet.foreground;
values.background = sw->sheet.background;
sw->sheet.normgc = XtGetGC((Widget)sw, valuemask, &values);
values.foreground = sw->sheet.background;
values.background = sw->sheet.background;
sw->sheet.sparegc = XtGetGC((Widget)sw, valuemask, &values);
values.foreground = sw->sheet.foreground;
values.background = sw->sheet.background;
sw->sheet.greygc = XCreateGC(XtDisplayOfObject((Widget)sw),
RootWindowOfScreen(XtScreenOfObject(
(Widget)sw)),
valuemask, &values);
values.foreground = sw->sheet.background;
values.background = sw->sheet.foreground;
sw->sheet.whitegc = XtGetGC((Widget)sw, valuemask, &values);
if (DisplayPlanes(XtDisplay(sw),DefaultScreen(XtDisplay(sw)))==1){
#define grey_width 2
#define grey_height 2
static char grey_bits[] = { 0x01 , 0x02 };
sw->sheet.grey_stipple =
XCreateBitmapFromData(XtDisplay(sw),
RootWindowOfScreen(XtScreenOfObject(
(Widget)sw)),
grey_bits,
grey_width,
grey_height);
XSetFillStyle(XtDisplay(sw),sw->sheet.greygc,FillOpaqueStippled);
XSetStipple(XtDisplay(sw),sw->sheet.greygc,sw->sheet.grey_stipple);
} else {
sw->sheet.light = ColourNameToPixel((Widget)sw,"lightGray");
}
}
}
static void Destroy (Widget w)
{
SheetWidget sw = (SheetWidget) w;
destroy_array(sw->sheet.paper);
destroy_array(sw->sheet.ink);
}
/* ARGSUSED */
static void Redisplay(Widget w, XEvent *event, Region region)
{
SheetWidget sw = (SheetWidget) w;
XRectangle expose, cursor;
if (!XtIsRealized(w))
return;
if (event->type == Expose) {
expose.x = event->xexpose.x;
expose.y = event->xexpose.y;
expose.width = event->xexpose.width;
expose.height = event->xexpose.height;
}
else { /* Graphics Expose. */
expose.x = event->xgraphicsexpose.x;
expose.y = event->xgraphicsexpose.y;
expose.width = event->xgraphicsexpose.width;
expose.height = event->xgraphicsexpose.height;
}
redisplayRegion((Widget)sw, &expose);
}
static void Resize(Widget w)
{
SheetWidget sw = (SheetWidget) w;
int newRows, newCols;
newRows = PIXEL_HEIGHT_TO_ROWS(sw,sw->core.height);
newCols = PIXEL_WIDTH_TO_COLS(sw,sw->core.width);
if (newRows > SHEET_MAX_ROWS) {
newRows = SHEET_MAX_ROWS;
sw->sheet.height_in_pixels = ROWS_TO_PIXEL_HEIGHT(sw,newRows);
/*
sw->core.height = sw->sheet.height_in_pixels;
*/
}
sw->sheet.rows = newRows;
if (newCols > SHEET_MAX_COLS) {
newCols = SHEET_MAX_COLS;
sw->sheet.width_in_pixels = COLS_TO_PIXEL_WIDTH(sw,newCols);
/*
sw->core.width = sw->sheet.width_in_pixels;
*/
}
sw->sheet.columns = newCols;
extend_array (
&sw->sheet.paper,
newRows,
newCols
);
extend_array (
&sw->sheet.ink,
newRows,
newCols
);
}
static void InputAction(Widget w, XEvent *event,
String *params,Cardinal *num_params)
{
SheetWidget sw = (SheetWidget) w;
}
static Boolean SetValues(Widget current, Widget request, Widget new,
ArgList args, Cardinal *num_args)
{
SheetWidget oldsw = (SheetWidget) current;
SheetWidget newsw = (SheetWidget) new;
Boolean redisplay;
Boolean resize;
redisplay = FALSE;
resize = FALSE;
if (oldsw->sheet.rows != newsw->sheet.rows) {
if (newsw->sheet.rows < 1 ||
newsw->sheet.rows >= SHEET_MAX_ROWS)
newsw->sheet.rows = oldsw->sheet.rows;
if (oldsw->sheet.rows != newsw->sheet.rows) {
redisplay = TRUE;
resize = TRUE;
newsw->sheet.height_in_pixels = ROWS_TO_PIXEL_HEIGHT(newsw,newsw->sheet.rows);
newsw->core.height = newsw->sheet.height_in_pixels;
}
}
if (oldsw->sheet.columns != newsw->sheet.columns) {
if (newsw->sheet.columns < 1 ||
newsw->sheet.columns >= SHEET_MAX_COLS)
newsw->sheet.columns = oldsw->sheet.columns;
if (oldsw->sheet.columns != newsw->sheet.columns) {
redisplay = TRUE;
resize = TRUE;
newsw->sheet.width_in_pixels = COLS_TO_PIXEL_WIDTH(newsw,newsw->sheet.columns);
newsw->core.width = newsw->sheet.width_in_pixels;
}
}
if (resize) {
extend_array (
&newsw->sheet.paper,
newsw->sheet.rows,
newsw->sheet.columns
);
extend_array (
&newsw->sheet.ink,
newsw->sheet.rows,
newsw->sheet.columns
);
}
return (redisplay && XtIsRealized((Widget)oldsw));
}