This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/cdk-5.0-20161210/matrix.c
2017-03-20 21:40:32 +10:00

1786 lines
41 KiB
C

#include <cdk_int.h>
/*
* $Author: tom $
* $Date: 2016/12/10 15:18:01 $
* $Revision: 1.198 $
*/
/*
* Declare file local prototypes.
*/
static void highlightCDKMatrixCell (CDKMATRIX *matrix);
static void CDKMatrixCallBack (CDKMATRIX *matrix, chtype input);
static void drawCDKMatrixCell (CDKMATRIX *matrix,
int srow, int scol,
int vrow, int vcol,
boolean Box);
static void drawCurCDKMatrixCell (CDKMATRIX *matrix);
static void drawEachCDKMatrixCell (CDKMATRIX *matrix);
static void drawEachColTitle (CDKMATRIX *matrix);
static void drawEachRowTitle (CDKMATRIX *matrix);
static void drawOldCDKMatrixCell (CDKMATRIX *matrix);
static void redrawTitles (CDKMATRIX *matrix, int row, int col);
#define emptyString(s) ((s) == 0 || *(s) == '\0')
#define CurMatrixCell(matrix) \
MATRIX_CELL (matrix, matrix->crow, matrix->ccol)
#define CurMatrixInfo(matrix) \
MATRIX_INFO (matrix, \
matrix->trow + matrix->crow - 1, \
matrix->lcol + matrix->ccol - 1)
DeclareCDKObjects (MATRIX, Matrix, setCdk, Int);
#define WHOLE_BOX ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER
#define TOP_C_BOX ACS_ULCORNER, ACS_URCORNER, ACS_LTEE, ACS_RTEE
#define MID_C_BOX ACS_LTEE, ACS_RTEE, ACS_LTEE, ACS_RTEE
#define BOT_C_BOX ACS_LTEE, ACS_RTEE, ACS_LLCORNER, ACS_LRCORNER
#define LFT_R_BOX ACS_ULCORNER, ACS_TTEE, ACS_LLCORNER, ACS_BTEE
#define MID_R_BOX ACS_TTEE, ACS_TTEE, ACS_BTEE, ACS_BTEE
#define RGT_R_BOX ACS_TTEE, ACS_URCORNER, ACS_BTEE, ACS_LRCORNER
#define LFT_T_BOX ACS_ULCORNER, ACS_TTEE, ACS_LTEE, ACS_PLUS
#define MID_T_BOX ACS_TTEE, ACS_TTEE, ACS_PLUS, ACS_PLUS
#define RGT_T_BOX ACS_TTEE, ACS_URCORNER, ACS_PLUS, ACS_RTEE
#define LFT_M_BOX ACS_LTEE, ACS_PLUS, ACS_LTEE, ACS_PLUS
#define MID_M_BOX ACS_PLUS, ACS_PLUS, ACS_PLUS, ACS_PLUS
#define RGT_M_BOX ACS_PLUS, ACS_RTEE, ACS_PLUS, ACS_RTEE
#define LFT_B_BOX ACS_LTEE, ACS_PLUS, ACS_LLCORNER, ACS_BTEE
#define MID_B_BOX ACS_PLUS, ACS_PLUS, ACS_BTEE, ACS_BTEE
#define RGT_B_BOX ACS_PLUS, ACS_RTEE, ACS_BTEE, ACS_LRCORNER
#define MyBox(cell,what,attr) attrbox(cell, what, ACS_HLINE, ACS_VLINE, attr)
/*
* This function creates the matrix widget.
*/
CDKMATRIX *newCDKMatrix (CDKSCREEN *cdkscreen,
int xplace,
int yplace,
int rows,
int cols,
int vrows,
int vcols,
const char *title,
CDK_CSTRING2 rowtitles,
CDK_CSTRING2 coltitles,
int *colwidths,
int *colvalues,
int rspace,
int cspace,
chtype filler,
int dominant,
boolean Box,
boolean boxCell,
boolean shadow)
{
/* *INDENT-EQLS* */
CDKMATRIX *matrix = 0;
int parentWidth = getmaxx (cdkscreen->window);
int parentHeight = getmaxy (cdkscreen->window);
int boxHeight = 0;
int boxWidth = 0;
int xpos = xplace;
int ypos = yplace;
int maxWidth;
int maxRowTitleWidth = 0;
int rowSpace = MAXIMUM (0, rspace);
int colSpace = MAXIMUM (0, cspace);
int begx = 0;
int begy = 0;
int cellWidth = 0;
char **temp = 0;
int x, y;
int borderw = 0;
bool have_rowtitles = FALSE;
bool have_coltitles = FALSE;
/* *INDENT-OFF* */
static const struct { int from; int to; } bindings[] = {
{ CDK_FORCHAR, KEY_NPAGE },
{ CDK_BACKCHAR, KEY_PPAGE },
};
/* *INDENT-ON* */
if ((matrix = newCDKObject (CDKMATRIX, &my_funcs)) == 0)
{
return (0);
}
setCDKMatrixBox (matrix, Box);
borderw = (ObjOf (matrix)->box) ? 1 : 0;
/* Make sure that the number of rows/cols/vrows/vcols is not zero. */
if (rows <= 0 || cols <= 0 || vrows <= 0 || vcols <= 0)
{
destroyCDKObject (matrix);
return (0);
}
#if NEW_CDKMATRIX
matrix->cell = typeCallocN (WINDOW *, (rows + 1) * (cols + 1));
matrix->info = typeCallocN (char *, (rows + 1) * (cols + 1));
#endif
/*
* Make sure the number of virtual cells is not larger than
* the physical size.
*/
vrows = (vrows > rows ? rows : vrows);
vcols = (vcols > cols ? cols : vcols);
/* Set these early, since they are used in matrix index computations */
/* *INDENT-EQLS* */
matrix->rows = rows;
matrix->cols = cols;
/* columns */
matrix->colwidths = typeCallocN (int, cols + 1);
matrix->colvalues = typeCallocN (int, cols + 1);
matrix->coltitle = typeCallocN (chtype *, cols + 1);
matrix->coltitleLen = typeCallocN (int, cols + 1);
matrix->coltitlePos = typeCallocN (int, cols + 1);
/* titles */
matrix->rowtitle = typeCallocN (chtype *, rows + 1);
matrix->rowtitleLen = typeCallocN (int, rows + 1);
matrix->rowtitlePos = typeCallocN (int, rows + 1);
/*
* Count the number of lines in the title (see setCdkTitle).
*/
temp = CDKsplitString (title, '\n');
TitleLinesOf (matrix) = (int)CDKcountStrings ((CDK_CSTRING2)temp);
CDKfreeStrings (temp);
/* Determine the height of the box. */
if (vrows == 1)
{
boxHeight = 6 + TitleLinesOf (matrix);
}
else
{
if (rowSpace == 0)
{
boxHeight = (6 + TitleLinesOf (matrix) +
((vrows - 1) * 2));
}
else
{
boxHeight = (3 + TitleLinesOf (matrix) +
(vrows * 3) + ((vrows - 1) * (rowSpace - 1)));
}
}
/* Determine the maximum row title width */
for (x = 1; x <= rows; x++)
{
if (rowtitles && !emptyString (rowtitles[x])) /*VR */
have_rowtitles = TRUE;
matrix->rowtitle[x] = char2Chtype (rowtitles ? rowtitles[x] : 0, /*VR */
&matrix->rowtitleLen[x],
&matrix->rowtitlePos[x]);
maxRowTitleWidth = MAXIMUM (maxRowTitleWidth, matrix->rowtitleLen[x]);
}
if (have_rowtitles)
{
matrix->maxrt = maxRowTitleWidth + 2;
/* We need to rejustify the row title cell info. */
for (x = 1; x <= rows; x++)
{
matrix->rowtitlePos[x] = justifyString (matrix->maxrt,
matrix->rowtitleLen[x],
matrix->rowtitlePos[x]);
}
}
else
{
matrix->maxrt = 0;
}
/* Determine the width of the matrix. */
maxWidth = 2 + matrix->maxrt;
for (x = 1; x <= vcols; x++)
{
maxWidth += colwidths[x] + 2 + colSpace;
}
maxWidth -= (colSpace - 1);
boxWidth = MAXIMUM (maxWidth, boxWidth);
boxWidth = setCdkTitle (ObjOf (matrix), title, boxWidth);
/*
* Make sure the dimensions of the window didn't
* extend beyond the dimensions of the parent window.
*/
boxWidth = (boxWidth > parentWidth ? parentWidth : boxWidth);
boxHeight = (boxHeight > parentHeight ? parentHeight : boxHeight);
/* Rejustify the x and y positions if we need to. */
alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
/* Make the pop-up window. */
matrix->win = newwin (boxHeight, boxWidth, ypos, xpos);
if (matrix->win == 0)
{
destroyCDKObject (matrix);
return (0);
}
/* Make the subwindows in the pop-up. */
begx = xpos;
begy = ypos + borderw + TitleLinesOf (matrix);
/* Make the 'empty' 0x0 cell. */
MATRIX_CELL (matrix, 0, 0) = subwin (matrix->win, 3, matrix->maxrt, begy, begx);
begx += matrix->maxrt + 1;
/* Copy the titles into the structure. */
for (x = 1; x <= cols; x++)
{
if (coltitles && !emptyString (coltitles[x])) /*VR */
have_coltitles = TRUE;
matrix->coltitle[x] = char2Chtype (coltitles ? coltitles[x] : 0, /*VR */
&matrix->coltitleLen[x],
&matrix->coltitlePos[x]);
matrix->coltitlePos[x] = (BorderOf (matrix) +
justifyString (colwidths[x],
matrix->coltitleLen[x],
matrix->coltitlePos[x]));
matrix->colwidths[x] = colwidths[x];
}
if (have_coltitles)
{
/* Make the column titles. */
for (x = 1; x <= vcols; x++)
{
cellWidth = colwidths[x] + 3;
MATRIX_CELL (matrix, 0, x) = subwin (matrix->win,
borderw,
cellWidth,
begy,
begx);
if (MATRIX_CELL (matrix, 0, x) == 0)
{
destroyCDKObject (matrix);
return (0);
}
begx += cellWidth + colSpace - 1;
}
begy++;
}
/* Make the main cell body */
for (x = 1; x <= vrows; x++)
{
if (have_rowtitles)
{
/* Make the row titles */
MATRIX_CELL (matrix, x, 0) = subwin (matrix->win,
3, matrix->maxrt,
begy, xpos + borderw);
if (MATRIX_CELL (matrix, x, 0) == 0)
{
destroyCDKObject (matrix);
return (0);
}
}
/* Set the start of the x position. */
begx = xpos + matrix->maxrt + borderw;
/* Make the cells */
for (y = 1; y <= vcols; y++)
{
cellWidth = colwidths[y] + 3;
MATRIX_CELL (matrix, x, y) = subwin (matrix->win,
3, cellWidth,
begy, begx);
if (MATRIX_CELL (matrix, x, y) == 0)
{
destroyCDKObject (matrix);
return (0);
}
begx += cellWidth + colSpace - 1;
keypad (MATRIX_CELL (matrix, x, y), TRUE);
}
begy += rowSpace + 2;
}
keypad (matrix->win, TRUE);
/* *INDENT-EQLS* Keep the rest of the info. */
ScreenOf (matrix) = cdkscreen;
ObjOf (matrix)->acceptsFocus = TRUE;
ObjOf (matrix)->inputWindow = matrix->win;
matrix->parent = cdkscreen->window;
matrix->vrows = vrows;
matrix->vcols = vcols;
matrix->boxWidth = boxWidth;
matrix->boxHeight = boxHeight;
matrix->rowSpace = rowSpace;
matrix->colSpace = colSpace;
matrix->filler = filler;
matrix->dominant = dominant;
matrix->row = 1;
matrix->col = 1;
matrix->crow = 1;
matrix->ccol = 1;
matrix->trow = 1;
matrix->lcol = 1;
matrix->oldcrow = 1;
matrix->oldccol = 1;
matrix->oldvrow = 1;
matrix->oldvcol = 1;
initExitType (matrix);
matrix->boxCell = boxCell;
matrix->shadow = shadow;
matrix->highlight = A_REVERSE;
matrix->callbackfn = CDKMatrixCallBack;
/* Make room for the cell information. */
for (x = 1; x <= rows; x++)
{
for (y = 1; y <= cols; y++)
{
MATRIX_INFO (matrix, x, y) = typeCallocN (char, (colwidths[y] + 1));
matrix->colvalues[y] = colvalues[y];
matrix->colwidths[y] = colwidths[y];
}
}
/* Do we want a shadow??? */
if (shadow)
{
matrix->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1);
}
/* Setup the key bindings. */
for (x = 0; x < (int)SIZEOF (bindings); ++x)
bindCDKObject (vMATRIX, matrix,
(chtype)bindings[x].from,
getcCDKBind,
(void *)(long)bindings[x].to);
/* Register this baby. */
registerCDKObject (cdkscreen, vMATRIX, matrix);
/* Return the matrix pointer */
return (matrix);
}
/*
* This activates the matrix.
*/
int activateCDKMatrix (CDKMATRIX *matrix, chtype *actions)
{
int ret;
/* Draw the matrix */
drawCDKMatrix (matrix, ObjOf (matrix)->box);
if (actions == 0)
{
chtype input = 0;
boolean functionKey;
for (;;)
{
ObjOf (matrix)->inputWindow = CurMatrixCell (matrix);
keypad (ObjOf (matrix)->inputWindow, TRUE);
input = (chtype)getchCDKObject (ObjOf (matrix), &functionKey);
/* Inject the character into the widget. */
ret = injectCDKMatrix (matrix, input);
if (matrix->exitType != vEARLY_EXIT)
{
return ret;
}
}
}
else
{
int length = chlen (actions);
int x = 0;
/* Inject each character one at a time. */
for (x = 0; x < length; x++)
{
ret = injectCDKMatrix (matrix, actions[x]);
if (matrix->exitType != vEARLY_EXIT)
{
return ret;
}
}
}
/* Set the exit type and exit. */
setExitType (matrix, 0);
return -1;
}
/*
* This injects a single character into the matrix widget.
*/
static int _injectCDKMatrix (CDKOBJS *object, chtype input)
{
/* *INDENT-EQLS* */
CDKMATRIX *widget = (CDKMATRIX *)object;
int refreshCells = FALSE;
int movedCell = FALSE;
int charcount = (int)strlen (MATRIX_INFO (widget, widget->row, widget->col));
int ppReturn = 1;
int ret = unknownInt;
bool complete = FALSE;
/* Set the exit type. */
setExitType (widget, 0);
/* Move the cursor to the correct position within the cell. */
if (widget->colwidths[widget->ccol] == 1)
{
wmove (CurMatrixCell (widget), 1, 1);
}
else
{
wmove (CurMatrixCell (widget),
1,
(int)strlen (MATRIX_INFO (widget, widget->row, widget->col)) + 1);
}
/* Put the focus on the current cell */
MyBox (CurMatrixCell (widget), WHOLE_BOX, A_BOLD);
wrefresh (CurMatrixCell (widget));
highlightCDKMatrixCell (widget);
/* Check if there is a pre-process function to be called. */
if (PreProcessFuncOf (widget) != 0)
{
/* Call the pre-process function. */
ppReturn = PreProcessFuncOf (widget) (vMATRIX,
widget,
PreProcessDataOf (widget),
input);
}
/* Should we continue? */
if (ppReturn != 0)
{
/* Check the key bindings. */
if (checkCDKObjectBind (vMATRIX, widget, input) != 0)
{
checkEarlyExit (widget);
complete = TRUE;
}
else
{
switch (input)
{
case CDK_TRANSPOSE:
break;
case KEY_HOME:
break;
case KEY_END:
break;
case KEY_BACKSPACE:
case KEY_DC:
if (widget->colvalues[widget->col] == vVIEWONLY || charcount <= 0)
{
Beep ();
}
else
{
charcount--;
(void)mvwdelch (CurMatrixCell (widget), 1, charcount + 1);
(void)mvwinsch (CurMatrixCell (widget), 1, charcount + 1, widget->filler);
wrefresh (CurMatrixCell (widget));
MATRIX_INFO (widget, widget->row, widget->col)[charcount] = '\0';
}
break;
case KEY_RIGHT:
case KEY_TAB:
if (widget->ccol != widget->vcols)
{
/* We are moving to the right... */
widget->col++;
widget->ccol++;
movedCell = TRUE;
}
else
{
/* We have to shift the columns to the right. */
if (widget->col != widget->cols)
{
widget->lcol++;
widget->col++;
/* Redraw the column titles. */
if (widget->rows > widget->vrows)
{
redrawTitles (widget, FALSE, TRUE);
}
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
/* We are at the far right column, we need */
/* shift down one row, if we can. */
if (widget->row == widget->rows)
{
Beep ();
}
else
{
/* Set up the columns info. */
widget->col = 1;
widget->lcol = 1;
widget->ccol = 1;
/* Shift the rows... */
if (widget->crow != widget->vrows)
{
widget->row++;
widget->crow++;
}
else
{
widget->row++;
widget->trow++;
}
redrawTitles (widget, TRUE, TRUE);
refreshCells = TRUE;
movedCell = TRUE;
}
}
}
break;
case KEY_LEFT:
case KEY_BTAB:
if (widget->ccol != 1)
{
/* We are moving to the left... */
widget->col--;
widget->ccol--;
movedCell = TRUE;
}
else
{
/* Are we at the far left??? */
if (widget->lcol != 1)
{
widget->lcol--;
widget->col--;
/* Redraw the column titles. */
if (widget->cols > widget->vcols)
{
redrawTitles (widget, FALSE, TRUE);
}
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
/* Shift up one line if we can... */
if (widget->row == 1)
{
Beep ();
}
else
{
/* Set up the columns info. */
widget->col = widget->cols;
widget->lcol = widget->cols - widget->vcols + 1;
widget->ccol = widget->vcols;
/* Shift the rows... */
if (widget->crow != 1)
{
widget->row--;
widget->crow--;
}
else
{
widget->row--;
widget->trow--;
}
redrawTitles (widget, TRUE, TRUE);
refreshCells = TRUE;
movedCell = TRUE;
}
}
}
break;
case KEY_UP:
if (widget->crow != 1)
{
widget->row--;
widget->crow--;
movedCell = TRUE;
}
else
{
if (widget->trow != 1)
{
widget->trow--;
widget->row--;
/* Redraw the row titles. */
if (widget->rows > widget->vrows)
{
redrawTitles (widget, TRUE, FALSE);
}
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
Beep ();
}
}
break;
case KEY_DOWN:
if (widget->crow != widget->vrows)
{
widget->row++;
widget->crow++;
movedCell = TRUE;
}
else
{
if ((widget->trow + widget->vrows - 1) != widget->rows)
{
widget->trow++;
widget->row++;
/* Redraw the titles. */
if (widget->rows > widget->vrows)
{
redrawTitles (widget, TRUE, FALSE);
}
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
Beep ();
}
}
break;
case KEY_NPAGE:
if (widget->rows > widget->vrows)
{
if ((widget->trow + ((widget->vrows - 1) * 2)) <= widget->rows)
{
widget->trow += widget->vrows - 1;
widget->row += widget->vrows - 1;
redrawTitles (widget, TRUE, FALSE);
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
Beep ();
}
}
else
{
Beep ();
}
break;
case KEY_PPAGE:
if (widget->rows > widget->vrows)
{
if ((widget->trow - ((widget->vrows - 1) * 2)) >= 1)
{
widget->trow -= widget->vrows - 1;
widget->row -= widget->vrows - 1;
redrawTitles (widget, TRUE, FALSE);
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
Beep ();
}
}
else
{
Beep ();
}
break;
case CTRL ('G'):
jumpToCell (widget, -1, -1);
drawCDKMatrix (widget, ObjOf (widget)->box);
break;
case CDK_PASTE:
if (GPasteBuffer == 0 ||
(int)strlen (GPasteBuffer) > widget->colwidths[widget->ccol])
{
Beep ();
}
else
{
strcpy (CurMatrixInfo (widget), GPasteBuffer);
drawCurCDKMatrixCell (widget);
}
break;
case CDK_COPY:
freeChar (GPasteBuffer);
GPasteBuffer = copyChar (CurMatrixInfo (widget));
break;
case CDK_CUT:
freeChar (GPasteBuffer);
GPasteBuffer = copyChar (CurMatrixInfo (widget));
cleanCDKMatrixCell (widget,
widget->trow + widget->crow - 1,
widget->lcol + widget->ccol - 1);
drawCurCDKMatrixCell (widget);
break;
case CDK_ERASE:
cleanCDKMatrixCell (widget,
widget->trow + widget->crow - 1,
widget->lcol + widget->ccol - 1);
drawCurCDKMatrixCell (widget);
break;
case KEY_ENTER:
if (!widget->boxCell)
{
attrbox (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol),
' ', ' ',
' ', ' ',
' ', ' ',
A_NORMAL);
}
else
{
drawOldCDKMatrixCell (widget);
}
wrefresh (CurMatrixCell (widget));
setExitType (widget, input);
ret = 1;
complete = TRUE;
break;
case KEY_ERROR:
setExitType (widget, input);
complete = TRUE;
break;
case KEY_ESC:
if (!widget->boxCell)
{
attrbox (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol),
' ', ' ',
' ', ' ',
' ', ' ',
A_NORMAL);
}
else
{
drawOldCDKMatrixCell (widget);
}
wrefresh (CurMatrixCell (widget));
setExitType (widget, input);
complete = TRUE;
break;
case CDK_REFRESH:
eraseCDKScreen (ScreenOf (widget));
refreshCDKScreen (ScreenOf (widget));
break;
default:
(widget->callbackfn) (widget, input);
break;
}
}
if (!complete)
{
/* Did we change cells? */
if (movedCell)
{
/* un-highlight the old box */
if (!widget->boxCell)
{
attrbox (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol),
' ', ' ',
' ', ' ',
' ', ' ',
A_NORMAL);
}
else
{
drawOldCDKMatrixCell (widget);
}
wrefresh (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol));
/* Highlight the new cell. */
MyBox (CurMatrixCell (widget), WHOLE_BOX, A_BOLD);
wrefresh (CurMatrixCell (widget));
highlightCDKMatrixCell (widget);
}
/* Redraw each cell. */
if (refreshCells)
{
drawEachCDKMatrixCell (widget);
/* Highlight the current cell. */
MyBox (CurMatrixCell (widget), WHOLE_BOX, A_BOLD);
wrefresh (CurMatrixCell (widget));
highlightCDKMatrixCell (widget);
}
/* Move to the correct position in the cell. */
if (refreshCells || movedCell)
{
if (widget->colwidths[widget->ccol] == 1)
{
wmove (CurMatrixCell (widget), 1, 1);
}
else
{
int infolen = (int)strlen (CurMatrixInfo (widget));
wmove (CurMatrixCell (widget), 1, infolen + 1);
}
wrefresh (CurMatrixCell (widget));
}
/* Should we call a post-process? */
if (PostProcessFuncOf (widget) != 0)
{
PostProcessFuncOf (widget) (vMATRIX,
widget,
PostProcessDataOf (widget),
input);
}
}
}
if (!complete)
{
/* Set the variables we need. */
widget->oldcrow = widget->crow;
widget->oldccol = widget->ccol;
widget->oldvrow = widget->row;
widget->oldvcol = widget->col;
/* Set the exit type and exit. */
setExitType (widget, 0);
}
ResultOf (widget).valueInt = ret;
return (ret != unknownInt);
}
/*
* This allows the programmer to define their own key mappings.
*/
static void CDKMatrixCallBack (CDKMATRIX *matrix, chtype input)
{
EDisplayType disptype = (EDisplayType) matrix->colvalues[matrix->col];
int plainchar = filterByDisplayType (disptype, input);
int charcount = (int)strlen (MATRIX_INFO (matrix, matrix->row, matrix->col));
if (plainchar == ERR)
{
Beep ();
}
else if (charcount == matrix->colwidths[matrix->col])
{
Beep ();
}
else
{
/* Update the screen. */
wmove (CurMatrixCell (matrix),
1,
(int)strlen (MATRIX_INFO (matrix, matrix->row, matrix->col)) + 1);
waddch (CurMatrixCell (matrix),
(chtype)((isHiddenDisplayType (disptype))
? (int)matrix->filler
: plainchar));
wrefresh (CurMatrixCell (matrix));
/* Update the character pointer. */
MATRIX_INFO (matrix, matrix->row, matrix->col)[charcount++] = (char)plainchar;
MATRIX_INFO (matrix, matrix->row, matrix->col)[charcount] = '\0';
}
}
/*
* Highlight the new field.
*/
static void highlightCDKMatrixCell (CDKMATRIX *matrix)
{
/* *INDENT-EQLS* */
EDisplayType disptype = (EDisplayType) matrix->colvalues[matrix->col];
chtype highlight = matrix->highlight;
int x = 0;
int infolen = (int)strlen (MATRIX_INFO (matrix, matrix->row, matrix->col));
/*
* Given the dominance of the colors/attributes, we need to set the
* current cell attribute.
*/
if (matrix->dominant == ROW)
{
highlight = matrix->rowtitle[matrix->crow][0] & A_ATTRIBUTES;
}
else if (matrix->dominant == COL)
{
highlight = matrix->coltitle[matrix->ccol][0] & A_ATTRIBUTES;
}
/* If the column is only one char. */
for (x = 1; x <= matrix->colwidths[matrix->ccol]; x++)
{
chtype ch = (((x <= infolen) && !isHiddenDisplayType (disptype))
? CharOf (MATRIX_INFO (matrix,
matrix->row,
matrix->col)[x - 1])
: matrix->filler);
(void)mvwaddch (CurMatrixCell (matrix), 1, x, ch | highlight);
}
wmove (CurMatrixCell (matrix), 1, infolen + 1);
wrefresh (CurMatrixCell (matrix));
}
/*
* This moves the matrix field to the given location.
*/
static void _moveCDKMatrix (CDKOBJS *object,
int xplace,
int yplace,
boolean relative,
boolean refresh_flag)
{
/* *INDENT-EQLS* */
CDKMATRIX *matrix = (CDKMATRIX *)object;
int currentX = getbegx (matrix->win);
int currentY = getbegy (matrix->win);
int xpos = xplace;
int ypos = yplace;
int xdiff = 0;
int ydiff = 0;
int x, y;
/*
* If this is a relative move, then we will adjust where we want
* to move to.
*/
if (relative)
{
xpos = getbegx (matrix->win) + xplace;
ypos = getbegy (matrix->win) + yplace;
}
/* Adjust the window if we need to. */
alignxy (WindowOf (matrix), &xpos, &ypos, matrix->boxWidth, matrix->boxHeight);
/* Get the difference. */
xdiff = currentX - xpos;
ydiff = currentY - ypos;
/* Move the window to the new location. */
moveCursesWindow (matrix->win, -xdiff, -ydiff);
for (x = 0; x <= matrix->vrows; x++)
{
for (y = 0; y <= matrix->vcols; y++)
{
moveCursesWindow (MATRIX_CELL (matrix, x, y), -xdiff, -ydiff);
}
}
moveCursesWindow (matrix->shadowWin, -xdiff, -ydiff);
/* Touch the windows so they 'move'. */
refreshCDKWindow (WindowOf (matrix));
/* Redraw the window, if they asked for it. */
if (refresh_flag)
{
drawCDKMatrix (matrix, ObjOf (matrix)->box);
}
}
/*
* This draws a cell within a matrix.
*/
static void drawCDKMatrixCell (CDKMATRIX *matrix,
int row,
int col,
int vrow,
int vcol,
boolean Box)
{
/* *INDENT-EQLS* */
WINDOW *cell = MATRIX_CELL (matrix, row, col);
EDisplayType disptype = (EDisplayType) matrix->colvalues[matrix->col];
chtype highlight = matrix->filler & A_ATTRIBUTES;
int rows = matrix->vrows;
int cols = matrix->vcols;
int infolen = (int)strlen (MATRIX_INFO (matrix, vrow, vcol));
chtype attr = A_NORMAL;
int x;
/*
* Given the dominance of the colors/attributes, we need to set the
* current cell attribute.
*/
if (matrix->dominant == ROW)
{
highlight = matrix->rowtitle[row][0] & A_ATTRIBUTES;
}
else if (matrix->dominant == COL)
{
highlight = matrix->coltitle[col][0] & A_ATTRIBUTES;
}
/* Draw in the cell info. */
for (x = 1; x <= matrix->colwidths[col]; x++)
{
chtype ch = (((x <= infolen) && !isHiddenDisplayType (disptype))
? (CharOf (MATRIX_INFO (matrix, vrow, vcol)[x - 1]) | highlight)
: matrix->filler);
(void)mvwaddch (cell, 1, x, ch | highlight);
}
wmove (cell, 1, infolen + 1);
wrefresh (cell);
/* Only draw the box iff the user asked for a box. */
if (!Box)
{
return;
}
/*
* If the value of the column spacing is greater than 0 then these
* are independent boxes.
*/
if (matrix->colSpace != 0)
{
if (matrix->rowSpace != 0)
{
MyBox (cell, WHOLE_BOX, attr);
}
else
{
if (row == 1)
{
MyBox (cell, TOP_C_BOX, attr);
}
else if (row > 1 && row < rows)
{
MyBox (cell, MID_C_BOX, attr);
}
else if (row == rows)
{
MyBox (cell, BOT_C_BOX, attr);
}
}
}
else if (matrix->rowSpace != 0)
{
if (col == 1)
{
MyBox (cell, LFT_R_BOX, attr);
}
else if (col > 1 && col < cols)
{
MyBox (cell, MID_R_BOX, attr);
}
else if (col == cols)
{
MyBox (cell, RGT_R_BOX, attr);
}
}
else
{
if (row == 1)
{
if (col == 1)
{
MyBox (cell, LFT_T_BOX, attr); /* top left corner */
}
else if (col > 1 && col < cols)
{
MyBox (cell, MID_T_BOX, attr); /* top middle */
}
else if (col == cols)
{
MyBox (cell, RGT_T_BOX, attr); /* top right corner */
}
}
else if (row > 1 && row < rows)
{
if (col == 1)
{
MyBox (cell, LFT_M_BOX, attr); /* middle left */
}
else if (col > 1 && col < cols)
{
MyBox (cell, MID_M_BOX, attr); /* middle */
}
else if (col == cols)
{
MyBox (cell, RGT_M_BOX, attr); /* middle right */
}
}
else if (row == rows)
{
if (col == 1)
{
MyBox (cell, LFT_B_BOX, attr); /* bottom left corner */
}
else if (col > 1 && col < cols)
{
MyBox (cell, MID_B_BOX, attr); /* bottom middle */
}
else if (col == cols)
{
MyBox (cell, RGT_B_BOX, attr); /* bottom right corner */
}
}
}
/* Highlight the current cell. */
MyBox (CurMatrixCell (matrix), WHOLE_BOX, A_BOLD);
wrefresh (CurMatrixCell (matrix));
highlightCDKMatrixCell (matrix);
}
static void drawEachColTitle (CDKMATRIX *matrix)
{
int x;
for (x = 1; x <= matrix->vcols; x++)
{
if (MATRIX_CELL (matrix, 0, x))
{
werase (MATRIX_CELL (matrix, 0, x)); /*VR */
writeChtype (MATRIX_CELL (matrix, 0, x),
matrix->coltitlePos[matrix->lcol + x - 1], 0,
matrix->coltitle[matrix->lcol + x - 1],
HORIZONTAL,
0, matrix->coltitleLen[matrix->lcol + x - 1]);
wrefresh (MATRIX_CELL (matrix, 0, x));
}
}
}
static void drawEachRowTitle (CDKMATRIX *matrix)
{
int x;
for (x = 1; x <= matrix->vrows; x++)
{
if (MATRIX_CELL (matrix, x, 0))
{
werase (MATRIX_CELL (matrix, x, 0));
writeChtype (MATRIX_CELL (matrix, x, 0),
matrix->rowtitlePos[matrix->trow + x - 1], 1,
matrix->rowtitle[matrix->trow + x - 1],
HORIZONTAL,
0, matrix->rowtitleLen[matrix->trow + x - 1]);
wrefresh (MATRIX_CELL (matrix, x, 0));
}
}
}
static void drawEachCDKMatrixCell (CDKMATRIX *matrix)
{
int y, x;
/* Fill in the cells. */
for (x = 1; x <= matrix->vrows; x++)
{
for (y = 1; y <= matrix->vcols; y++)
{
drawCDKMatrixCell (matrix, x, y,
matrix->trow + x - 1,
matrix->lcol + y - 1,
matrix->boxCell);
}
}
}
static void drawCurCDKMatrixCell (CDKMATRIX *matrix)
{
drawCDKMatrixCell (matrix,
matrix->crow,
matrix->ccol,
matrix->row,
matrix->col,
matrix->boxCell);
}
static void drawOldCDKMatrixCell (CDKMATRIX *matrix)
{
drawCDKMatrixCell (matrix,
matrix->oldcrow,
matrix->oldccol,
matrix->oldvrow,
matrix->oldvcol,
matrix->boxCell);
}
/*
* This function draws the matrix widget.
*/
static void _drawCDKMatrix (CDKOBJS *object, boolean Box)
{
CDKMATRIX *matrix = (CDKMATRIX *)object;
/* Did we ask for a shadow??? */
if (matrix->shadowWin != 0)
{
drawShadow (matrix->shadowWin);
}
/* Should we box the matrix??? */
if (Box)
{
drawObjBox (matrix->win, ObjOf (matrix));
}
drawCdkTitle (matrix->win, object);
wrefresh (matrix->win);
drawEachColTitle (matrix);
drawEachRowTitle (matrix);
drawEachCDKMatrixCell (matrix);
/* Highlight the current cell. */
MyBox (CurMatrixCell (matrix), WHOLE_BOX, A_BOLD);
wrefresh (CurMatrixCell (matrix));
highlightCDKMatrixCell (matrix);
}
/*
* This function destroys the matrix widget.
*/
static void _destroyCDKMatrix (CDKOBJS *object)
{
if (object != 0)
{
CDKMATRIX *matrix = (CDKMATRIX *)object;
int x = 0;
int y = 0;
cleanCdkTitle (object);
/* Clear out the col titles. */
for (x = 1; x <= matrix->cols; x++)
{
freeChtype (matrix->coltitle[x]);
}
/* Clear out the row titles. */
for (x = 1; x <= matrix->rows; x++)
{
freeChtype (matrix->rowtitle[x]);
}
/* Clear out the matrix cells. */
for (x = 1; x <= matrix->rows; x++)
{
for (y = 1; y <= matrix->cols; y++)
{
freeChar (MATRIX_INFO (matrix, x, y));
}
}
/* Clear the matrix windows. */
deleteCursesWindow (MATRIX_CELL (matrix, 0, 0));
for (x = 1; x <= matrix->vrows; x++)
{
deleteCursesWindow (MATRIX_CELL (matrix, x, 0));
}
for (x = 1; x <= matrix->vcols; x++)
{
deleteCursesWindow (MATRIX_CELL (matrix, 0, x));
}
for (x = 1; x <= matrix->vrows; x++)
{
for (y = 1; y <= matrix->vcols; y++)
{
deleteCursesWindow (MATRIX_CELL (matrix, x, y));
}
}
#if NEW_CDKMATRIX
freeChecked (matrix->cell);
freeChecked (matrix->info);
#endif
freeChecked (matrix->colwidths);
freeChecked (matrix->colvalues);
freeChecked (matrix->coltitle);
freeChecked (matrix->coltitleLen);
freeChecked (matrix->coltitlePos);
freeChecked (matrix->rowtitle);
freeChecked (matrix->rowtitleLen);
freeChecked (matrix->rowtitlePos);
deleteCursesWindow (matrix->shadowWin);
deleteCursesWindow (matrix->win);
/* Clean the key bindings. */
cleanCDKObjectBindings (vMATRIX, matrix);
/* Unregister this object. */
unregisterCDKObject (vMATRIX, matrix);
}
}
/*
* This function erases the matrix widget from the screen.
*/
static void _eraseCDKMatrix (CDKOBJS *object)
{
if (validCDKObject (object))
{
CDKMATRIX *matrix = (CDKMATRIX *)object;
int x = 0;
int y = 0;
/* Clear the matrix cells. */
eraseCursesWindow (MATRIX_CELL (matrix, 0, 0));
for (x = 1; x <= matrix->vrows; x++)
{
eraseCursesWindow (MATRIX_CELL (matrix, x, 0));
}
for (x = 1; x <= matrix->vcols; x++)
{
eraseCursesWindow (MATRIX_CELL (matrix, 0, x));
}
for (x = 1; x <= matrix->vrows; x++)
{
for (y = 1; y <= matrix->vcols; y++)
{
eraseCursesWindow (MATRIX_CELL (matrix, x, y));
}
}
eraseCursesWindow (matrix->shadowWin);
eraseCursesWindow (matrix->win);
}
}
/*
* Set the callback-function.
*/
void setCDKMatrixCB (CDKMATRIX *widget, MATRIXCB callback)
{
widget->callbackfn = callback;
}
/*
* This function sets the values of the matrix widget.
*/
void setCDKMatrixCells (CDKMATRIX *matrix,
CDK_CSTRING2 info,
int rows,
int maxcols,
int *subSize)
{
int x = 0;
int y = 0;
if (rows > matrix->rows)
rows = matrix->rows;
/* Copy in the new info. */
for (x = 1; x <= rows; x++)
{
for (y = 1; y <= matrix->cols; y++)
{
if (x <= rows && y <= subSize[x])
{
const char *source = info[(x * maxcols) + y];
/* Copy in the new information. */
if (source != 0)
{
char *target = MATRIX_INFO (matrix, x, y);
if (target == 0) /* this should not happen... */
{
target = typeCallocN (char, matrix->colwidths[y] + 1);
MATRIX_INFO (matrix, x, y) = target;
}
strncpy (MATRIX_INFO (matrix, x, y),
source,
(size_t) matrix->colwidths[y]);
}
}
else
cleanCDKMatrixCell (matrix, x, y);
}
}
}
/*
* This sets the widget's box attribute.
*/
void setCDKMatrixBox (CDKMATRIX *matrix, boolean Box)
{
ObjOf (matrix)->box = Box;
ObjOf (matrix)->borderSize = Box ? 1 : 0;
}
boolean getCDKMatrixBox (CDKMATRIX *matrix)
{
return ObjOf (matrix)->box;
}
/*
* This cleans out the information cells in the matrix widget.
*/
void cleanCDKMatrix (CDKMATRIX *matrix)
{
int x = 0;
int y = 0;
for (x = 1; x <= matrix->rows; x++)
{
for (y = 1; y <= matrix->cols; y++)
{
cleanCDKMatrixCell (matrix, x, y);
}
}
}
/*
* This cleans one cell in the matrix widget.
*/
void cleanCDKMatrixCell (CDKMATRIX *matrix, int row, int col)
{
if (row > 0 && row <= matrix->rows &&
col > 0 && col <= matrix->cols)
cleanChar (MATRIX_INFO (matrix, row, col), matrix->colwidths[col], '\0');
}
/*
* This allows us to hyper-warp to a cell.
*/
int jumpToCell (CDKMATRIX *matrix, int row, int col)
{
CDKSCALE *scale = 0;
int newRow = row;
int newCol = col;
/*
* Only create the row scale if needed.
*/
if ((row == -1) || (row > matrix->rows))
{
/* Create the row scale widget. */
scale = newCDKScale (ScreenOf (matrix),
CENTER, CENTER,
"<C>Jump to which row.",
"</5/B>Row: ", A_NORMAL, 5,
1, 1, matrix->rows, 1, 1, TRUE, FALSE);
/* Activate the scale and get the row. */
newRow = activateCDKScale (scale, 0);
destroyCDKScale (scale);
}
/*
* Only create the column scale if needed.
*/
if ((col == -1) || (col > matrix->cols))
{
/* Create the column scale widget. */
scale = newCDKScale (ScreenOf (matrix),
CENTER, CENTER,
"<C>Jump to which column",
"</5/B>Col: ", A_NORMAL, 5,
1, 1, matrix->cols, 1, 1, TRUE, FALSE);
/* Activate the scale and get the column. */
newCol = activateCDKScale (scale, 0);
destroyCDKScale (scale);
}
/* Hyper-warp.... */
if (newRow != matrix->row || newCol != matrix->col)
{
return (moveToCDKMatrixCell (matrix, newRow, newCol));
}
else
{
return 1;
}
}
/*
* This allows us to move to a given cell.
*/
int moveToCDKMatrixCell (CDKMATRIX *matrix, int newrow, int newcol)
{
int rowShift = newrow - matrix->row;
int colShift = newcol - matrix->col;
/* Make sure we arent asking to move out of the matrix. */
if (newrow > matrix->rows ||
newcol > matrix->cols ||
newrow <= 0 ||
newcol <= 0)
{
return 0;
}
/* Did we move up/down???? */
if (rowShift > 0)
{
/* We are moving down. */
if (matrix->vrows == matrix->cols)
{
matrix->trow = 1;
matrix->crow = newrow;
matrix->row = newrow;
}
else
{
if ((rowShift + matrix->vrows) < matrix->rows)
{
/* Just shift down by rowShift... */
matrix->trow += rowShift;
matrix->crow = 1;
matrix->row += rowShift;
}
else
{
/* We need to munge with the values... */
matrix->trow = matrix->rows - matrix->vrows + 1;
matrix->crow = ((rowShift + matrix->vrows) - matrix->rows) + 1;
matrix->row = newrow;
}
}
}
else if (rowShift < 0)
{
/* We are moving up. */
if (matrix->vrows == matrix->rows)
{
matrix->trow = 1;
matrix->row = newrow;
matrix->crow = newrow;
}
else
{
if ((rowShift + matrix->vrows) > 1)
{
/* Just shift up by rowShift... */
matrix->trow += rowShift;
matrix->row += rowShift;
matrix->crow = 1;
}
else
{
/* We need to munge with the values... */
matrix->trow = 1;
matrix->crow = 1;
matrix->row = 1;
}
}
}
/* Did we move left/right ???? */
if (colShift > 0)
{
/* We are moving right. */
if (matrix->vcols == matrix->cols)
{
matrix->lcol = 1;
matrix->ccol = newcol;
matrix->col = newcol;
}
else
{
if ((colShift + matrix->vcols) < matrix->cols)
{
matrix->lcol += colShift;
matrix->ccol = 1;
matrix->col += colShift;
}
else
{
/* We need to munge with the values... */
matrix->lcol = matrix->cols - matrix->vcols + 1;
matrix->ccol = ((colShift + matrix->vcols) - matrix->cols) + 1;
matrix->col = newcol;
}
}
}
else if (colShift < 0)
{
/* We are moving left. */
if (matrix->vcols == matrix->cols)
{
matrix->lcol = 1;
matrix->col = newcol;
matrix->ccol = newcol;
}
else
{
if ((colShift + matrix->vcols) > 1)
{
/* Just shift left by colShift... */
matrix->lcol += colShift;
matrix->col += colShift;
matrix->ccol = 1;
}
else
{
matrix->lcol = 1;
matrix->col = 1;
matrix->ccol = 1;
}
}
}
/* Keep the 'old' values around for redrawing sake. */
matrix->oldcrow = matrix->crow;
matrix->oldccol = matrix->ccol;
matrix->oldvrow = matrix->row;
matrix->oldvcol = matrix->col;
/* Lets ... */
return 1;
}
/*
* This redraws the titles indicated...
*/
static void redrawTitles (CDKMATRIX *matrix, int rowTitles, int colTitles)
{
/* Redraw the row titles. */
if (rowTitles)
{
drawEachRowTitle (matrix);
}
/* Redraw the column titles. */
if (colTitles)
{
drawEachColTitle (matrix);
}
}
/*
* This sets the value of a matrix cell.
*/
int setCDKMatrixCell (CDKMATRIX *matrix, int row, int col, const char *value)
{
/* Make sure the row/col combination is within the matrix. */
if (row > matrix->rows || col > matrix->cols || row <= 0 || col <= 0)
{
return -1;
}
cleanCDKMatrixCell (matrix, row, col);
strncpy (MATRIX_INFO (matrix, row, col),
value,
(size_t) matrix->colwidths[col]);
return 1;
}
/*
* This gets the value of a matrix cell.
*/
char *getCDKMatrixCell (CDKMATRIX *matrix, int row, int col)
{
/* Make sure the row/col combination is within the matrix. */
if (row > matrix->rows || col > matrix->cols || row <= 0 || col <= 0)
{
return 0;
}
return MATRIX_INFO (matrix, row, col);
}
/*
* This returns the current row/col cell.
*/
int getCDKMatrixCol (CDKMATRIX *matrix)
{
return matrix->col;
}
int getCDKMatrixRow (CDKMATRIX *matrix)
{
return matrix->row;
}
/*
* This sets the background attribute of the widget.
*/
static void _setBKattrMatrix (CDKOBJS *object, chtype attrib)
{
if (object != 0)
{
CDKMATRIX *widget = (CDKMATRIX *)object;
int x, y;
wbkgd (widget->win, attrib);
for (x = 0; x <= widget->vrows; x++)
{
for (y = 0; y <= widget->vcols; y++)
{
wbkgd (MATRIX_CELL (widget, x, y), attrib);
}
}
}
}
static void _focusCDKMatrix (CDKOBJS *object)
{
CDKMATRIX *widget = (CDKMATRIX *)object;
drawCDKMatrix (widget, ObjOf (widget)->box);
}
static void _unfocusCDKMatrix (CDKOBJS *object)
{
CDKMATRIX *widget = (CDKMATRIX *)object;
drawCDKMatrix (widget, ObjOf (widget)->box);
}
dummyRefreshData (Matrix)
dummySaveData (Matrix)