NetBSD/dist/cdk/matrix.c

1588 lines
36 KiB
C

#include <cdk.h>
/*
* $Author: garbled $
* $Date: 2001/01/09 18:41:53 $
* $Revision: 1.3 $
*/
/*
* 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,
chtype attr, boolean Box);
static void redrawTitles (CDKMATRIX *matrix, int row, int col);
/*
* Declare file local variables.
*/
extern char *GPasteBuffer;
DeclareCDKObjects(my_funcs,Matrix);
/*
* This function creates the matrix widget.
*/
CDKMATRIX *newCDKMatrix (CDKSCREEN *cdkscreen, int xplace, int yplace, int rows, int cols, int vrows, int vcols, char *title, char **rowtitles, char **coltitles, int *colwidths, int *colvalues, int rspace, int cspace, chtype filler, int dominant, boolean
Box, boolean boxCell, boolean shadow)
{
/* Declare local variables. */
CDKMATRIX *matrix = newCDKObject(CDKMATRIX, &my_funcs);
int parentWidth = getmaxx(cdkscreen->window);
int parentHeight = getmaxy(cdkscreen->window);
chtype *junk = 0;
int boxHeight = 0;
int boxWidth = 0;
int xpos = xplace;
int ypos = yplace;
int maxWidth = INT_MIN;
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, z, len, junk2;
/* Make sure that the number of rows/cols/vrows/vcols is not zero. */
if (rows == 0 || cols == 0 || vrows == 0 || vcols == 0)
{
/* Free up any used memory. */
free (matrix);
return (0);
}
/*
* Make sure the number of virtual cells is not larger than
* the physical size.
*/
vrows = (vrows > rows ? rows : vrows);
vcols = (vcols > cols ? cols : vcols);
/* We need to determine the width of the matrix box. */
if (title != 0)
{
temp = CDKsplitString (title, '\n');
matrix->titleLines = CDKcountStrings (temp);
for (x=0; x < matrix->titleLines; x++)
{
junk = char2Chtype (temp[x], &len, &junk2);
maxWidth = MAXIMUM (maxWidth, len);
freeChtype (junk);
}
CDKfreeStrings(temp);
}
else
{
/* No title? Set the required variables. */
matrix->titleLines = 0;
}
boxWidth = maxWidth;
/* Determine the height of the box. */
if (vrows == 1)
{
boxHeight = 6 + matrix->titleLines;
}
else
{
if (rowSpace == 0)
{
boxHeight = 6 + matrix->titleLines + ((vrows - 1) * 2);
}
else
{
boxHeight = 3 + matrix->titleLines + (vrows * 3) + ((vrows-1) * (rowSpace-1));
}
}
/* Determine the maximum row title width */
for (x=1; x <= rows; x++)
{
matrix->rowtitle[x] = char2Chtype (rowtitles[x], &matrix->rowtitleLen[x], &matrix->rowtitlePos[x]);
maxRowTitleWidth = MAXIMUM (maxRowTitleWidth, matrix->rowtitleLen[x]);
}
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]);
}
/* 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);
/* Translate the char * items to chtype * */
if (title != 0)
{
temp = CDKsplitString (title, '\n');
matrix->titleLines = CDKcountStrings (temp);
/* For each line in the title, convert from char * to chtype * */
for (x=0; x < matrix->titleLines; x++)
{
matrix->title[x] = char2Chtype (temp[x], &matrix->titleLen[x], &matrix->titlePos[x]);
matrix->titlePos[x] = justifyString (boxWidth, matrix->titleLen[x], matrix->titlePos[x]);
}
CDKfreeStrings(temp);
}
/*
* Make sure the dimensions of the window didn't
* extend beyond the dimensions of the parent window.
*/
boxWidth = MINIMUM (boxWidth, parentWidth);
boxHeight = MINIMUM (boxHeight, parentHeight);
/* 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 + !!shadow, boxWidth + !!shadow, ypos, xpos);
if (matrix->win == 0)
{
/* Free up any used memory. */
for (z=1; z <= rows; z++)
{
freeChtype (matrix->rowtitle[z]);
}
free (matrix);
return (0);
}
/* Make the subwindows in the pop-up. */
begx = xpos;
begy = ypos + 1 + matrix->titleLines;
/* Make the 'empty' 0x0 cell. */
matrix->cell[0][0] = subwin (matrix->win, 3, matrix->maxrt, begy, begx);
begx += matrix->maxrt + 1;
/* Make the column titles. */
for (x=1; x <= vcols; x++)
{
cellWidth = colwidths[x] + 3;
matrix->cell[0][x] = subwin (matrix->win, 1, cellWidth, begy, begx);
if (matrix->cell[0][x] == 0)
{
goto death;
}
begx += cellWidth + colSpace - 1;
}
begy++;
/* Make the main cell body */
for (x=1; x <= vrows; x++)
{
/* Make the row titles */
matrix->cell[x][0] = subwin (matrix->win, 3, matrix->maxrt, begy, xpos+1);
if (matrix->cell[x][0] == 0)
{
goto death;
}
/* Set the start of the x position. */
begx = xpos + matrix->maxrt + 1;
/* Make the cells */
for (y=1; y <= vcols; y++)
{
cellWidth = colwidths[y] + 3;
matrix->cell[x][y] = subwin (matrix->win, 3, cellWidth, begy, begx);
if (matrix->cell[x][y] == 0)
{
goto death;
}
begx += cellWidth + colSpace - 1;
keypad (matrix->cell[x][y], TRUE);
}
begy += rowSpace + 2;
}
keypad (matrix->win, TRUE);
/* Copy the titles into the structure. */
for (x=1; x <= cols; x++)
{
matrix->coltitle[x] = char2Chtype (coltitles[x], &matrix->coltitleLen[x], &matrix->coltitlePos[x]);
matrix->coltitlePos[x] = justifyString (colwidths[x], matrix->coltitleLen[x], matrix->coltitlePos[x]);
matrix->colwidths[x] = colwidths[x];
}
/* Make room for the cell information. */
for (x=1; x <= rows; x++)
{
for (y=1; y <= cols; y++)
{
matrix->info[x][y] = (char *)malloc (sizeof (char) * 256);
matrix->colvalues[y] = colvalues[y];
matrix->colwidths[y] = colwidths[y];
cleanChar (matrix->info[x][y], colwidths[y]+1, '\0');
}
}
/* Keep the rest of the info. */
ScreenOf(matrix) = cdkscreen;
ObjOf(matrix)->box = Box;
matrix->parent = cdkscreen->window;
matrix->rows = rows;
matrix->cols = cols;
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;
matrix->exitType = vNEVER_ACTIVATED;
matrix->boxCell = boxCell;
matrix->shadow = shadow;
matrix->highlight = A_REVERSE;
matrix->ULChar = ACS_ULCORNER;
matrix->URChar = ACS_URCORNER;
matrix->LLChar = ACS_LLCORNER;
matrix->LRChar = ACS_LRCORNER;
matrix->HChar = ACS_HLINE;
matrix->VChar = ACS_VLINE;
matrix->BoxAttrib = A_NORMAL;
matrix->callbackfn = (void *)&CDKMatrixCallBack;
matrix->preProcessFunction = 0;
matrix->preProcessData = 0;
matrix->postProcessFunction = 0;
matrix->postProcessData = 0;
/* Clean the key bindings. */
cleanCDKObjectBindings (vMATRIX, matrix);
/* Register this baby. */
registerCDKObject (cdkscreen, vMATRIX, matrix);
/* Return the matrix pointer */
return (matrix);
death:
/* Free up any used memory. */
for (y=1; y <= rows; y++)
{
freeChtype (matrix->rowtitle[y]);
}
/* We have to delete any windows created so far. */
deleteCursesWindow (matrix->win);
free (matrix);
return (0);
}
/*
* This activates the matrix.
*/
int activateCDKMatrix (CDKMATRIX *matrix, chtype *actions)
{
/* Declare local variables. */
int ret;
/* Draw the matrix */
drawCDKMatrix (matrix, ObjOf(matrix)->box);
if (actions == 0)
{
chtype input = 0;
for (;;)
{
/* Get the input. */
wrefresh (matrix->cell[matrix->crow][matrix->ccol]);
input = wgetch (matrix->cell[matrix->crow][matrix->ccol]);
/* 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. */
matrix->exitType = vEARLY_EXIT;
return -1;
}
/*
* This injects a single character into the matrix widget.
*/
int injectCDKMatrix (CDKMATRIX *matrix, chtype input)
{
/* Declare local variables. */
int refreshCells = FALSE;
int movedCell = FALSE;
int charcount = (int)strlen (matrix->info[matrix->row][matrix->col]);
int ppReturn = 1;
int x, y, diff;
/* Set the exit type. */
matrix->exitType = vEARLY_EXIT;
/* Put the focus on the current cell */
highlightCDKMatrixCell (matrix);
/* Check if there is a pre-process function to be called. */
if (matrix->preProcessFunction != 0)
{
/* Call the pre-process function. */
ppReturn = ((PROCESSFN)(matrix->preProcessFunction)) (vMATRIX, matrix, matrix->preProcessData, input);
}
/* Should we continue? */
if (ppReturn != 0)
{
/* Check the key bindings. */
if (checkCDKObjectBind (vMATRIX, matrix, input) != 0)
{
return -1;
}
else
{
switch (input)
{
case CDK_TRANSPOSE :
break;
case CDK_BEGOFLINE :
break;
case CDK_ENDOFLINE :
break;
case KEY_BACKSPACE :
case DELETE :
case CONTROL('H') :
case KEY_DC :
if (matrix->colvalues[matrix->col] == vVIEWONLY)
{
Beep();
}
else
{
if (charcount > 0)
{
charcount--;
mvwdelch (matrix->cell[matrix->crow][matrix->ccol], 1, charcount+1);
mvwinsch (matrix->cell[matrix->crow][matrix->ccol], 1, charcount+1, matrix->filler);
wnoutrefresh (matrix->cell[matrix->crow][matrix->ccol]);
matrix->info[matrix->row][matrix->col][charcount] = '\0';
}
else
{
Beep();
}
}
break;
case KEY_RIGHT :
case KEY_TAB :
if (matrix->ccol != matrix->vcols)
{
/* We are moving to the right... */
matrix->col++;
matrix->ccol++;
movedCell = TRUE;
}
else
{
/* We have to shift the columns to the right. */
if (matrix->col != matrix->cols)
{
matrix->lcol++;
matrix->col++;
redrawTitles (matrix, FALSE, TRUE);
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
/* We are at the far right column, we need */
/* shift down one row, if we can. */
if (matrix->row == matrix->rows)
{
Beep();
}
else
{
/* Set up the columns info. */
matrix->col = 1;
matrix->lcol = 1;
matrix->ccol = 1;
/* Shift the rows... */
if (matrix->crow != matrix->vrows)
{
matrix->row++;
matrix->crow++;
}
else
{
matrix->row++;
matrix->trow++;
redrawTitles (matrix, TRUE, TRUE);
refreshCells = TRUE;
}
movedCell = TRUE;
}
}
}
break;
case KEY_LEFT :
if (matrix->ccol != 1)
{
/* We are moving to the left... */
matrix->col--;
matrix->ccol--;
movedCell = TRUE;
}
else
{
/* Are we at the far left??? */
if (matrix->lcol != 1)
{
matrix->lcol--;
matrix->col--;
redrawTitles (matrix, FALSE, TRUE);
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
/* Shift up one line if we can... */
if (matrix->row == 1)
{
Beep();
}
else
{
/* Set up the columns info. */
matrix->col = matrix->cols;
matrix->lcol = matrix->cols - matrix->vcols + 1;
matrix->ccol = matrix->vcols;
/* Shift the rows... */
if (matrix->crow != 1)
{
matrix->row--;
matrix->crow--;
}
else
{
matrix->row--;
matrix->trow--;
redrawTitles (matrix, TRUE, TRUE);
refreshCells = TRUE;
}
movedCell = TRUE;
}
}
}
break;
case KEY_UP :
if (matrix->crow != 1)
{
matrix->row--;
matrix->crow--;
movedCell = TRUE;
}
else
{
diff = matrix->trow - 1;
if (diff > 0)
{
matrix->trow--;
matrix->row--;
redrawTitles (matrix, TRUE, FALSE);
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
Beep();
}
}
break;
case KEY_DOWN :
if (matrix->crow != matrix->vrows)
{
matrix->row++;
matrix->crow++;
movedCell = TRUE;
}
else
{
diff = matrix->rows - (matrix->trow + matrix->vrows - 1);
if (diff > 0)
{
matrix->trow++;
matrix->row++;
redrawTitles (matrix, TRUE, FALSE);
refreshCells = TRUE;
movedCell = TRUE;
}
else
{
Beep();
}
}
break;
case KEY_NPAGE :
case CONTROL('F') :
if (matrix->row < matrix->rows)
{
diff = matrix->rows - (matrix->trow + matrix->vrows - 1);
if (diff > 0)
{
matrix->trow += MINIMUM (diff, matrix->vrows - 1);
redrawTitles (matrix, TRUE, FALSE);
refreshCells = TRUE;
}
matrix->row = MINIMUM (matrix->row + matrix->vrows - 1,
matrix->rows);
matrix->crow = matrix->row - matrix->trow + 1;
movedCell = TRUE;
}
else
{
Beep();
}
break;
case KEY_PPAGE :
case CONTROL('B') :
if (matrix->row > 1)
{
diff = matrix->trow - 1;
if (diff > 0)
{
matrix->trow -= MINIMUM (diff, matrix->vrows - 1);
redrawTitles (matrix, TRUE, FALSE);
refreshCells = TRUE;
}
matrix->row = MAXIMUM (matrix->row - matrix->vrows + 1,
1);
matrix->crow = matrix->row - matrix->trow + 1;
movedCell = TRUE;
}
else
{
Beep();
}
break;
case CONTROL('G') :
jumpToCell (matrix, -1, -1);
drawCDKMatrix (matrix, ObjOf(matrix)->box);
break;
case CDK_PASTE :
if (GPasteBuffer == 0 || (int)strlen (GPasteBuffer) > matrix->colwidths[matrix->ccol])
{
Beep();
}
else
{
strcpy (matrix->info[matrix->trow+matrix->crow-1][matrix->lcol+matrix->ccol-1], GPasteBuffer);
drawCDKMatrixCell (matrix, matrix->crow, matrix->ccol, matrix->row, matrix->col, A_NORMAL, matrix->boxCell);
}
break;
case CDK_COPY :
freeChar (GPasteBuffer);
GPasteBuffer = copyChar (matrix->info[matrix->trow+matrix->crow-1][matrix->lcol+matrix->ccol-1]);
break;
case CDK_CUT :
freeChar (GPasteBuffer);
GPasteBuffer = copyChar (matrix->info[matrix->trow+matrix->crow-1][matrix->lcol+matrix->ccol-1]);
cleanChar (matrix->info[matrix->trow+matrix->crow-1][matrix->lcol+matrix->ccol-1], matrix->colwidths[matrix->lcol+matrix->ccol-1], '\0');
drawCDKMatrixCell (matrix, matrix->crow, matrix->ccol, matrix->row, matrix->col, A_NORMAL, matrix->boxCell);
break;
case CDK_ERASE :
cleanChar (matrix->info[matrix->trow+matrix->crow-1][matrix->lcol+matrix->ccol-1], matrix->colwidths[matrix->lcol+matrix->ccol-1], '\0');
drawCDKMatrixCell (matrix, matrix->crow, matrix->ccol, matrix->row, matrix->col, A_NORMAL, matrix->boxCell);
break;
case KEY_RETURN :
case KEY_ENTER :
case KEY_CR :
drawCDKMatrixCell (matrix,
matrix->oldcrow,
matrix->oldccol,
matrix->oldvrow,
matrix->oldvcol,
A_NORMAL,
matrix->boxCell);
wrefresh (matrix->cell[matrix->crow][matrix->ccol]);
matrix->exitType = vNORMAL;
return 0;
case KEY_ESC :
drawCDKMatrixCell (matrix,
matrix->oldcrow,
matrix->oldccol,
matrix->oldvrow,
matrix->oldvcol,
A_NORMAL,
matrix->boxCell);
wrefresh (matrix->cell[matrix->crow][matrix->ccol]);
matrix->exitType = vESCAPE_HIT;
return -1;
case CDK_REFRESH :
eraseCDKScreen (ScreenOf(matrix));
refreshCDKScreen (ScreenOf(matrix));
break;
default :
((MATRIXCB)matrix->callbackfn)(matrix, input);
break;
}
}
/* Did we change cells? */
if (movedCell && !refreshCells)
{
/* un-highlight the old box */
drawCDKMatrixCell (matrix,
matrix->oldcrow,
matrix->oldccol,
matrix->oldvrow,
matrix->oldvcol,
0,
matrix->boxCell);
}
/* Redraw each cell. */
if (refreshCells)
{
/* Fill in the cells. */
for (x=0; x < matrix->vrows; x++)
{
for (y=0; y < matrix->vcols; y++)
{
drawCDKMatrixCell (matrix, x+1, y+1,
matrix->trow + x,
matrix->lcol + y,
A_NORMAL,
matrix->boxCell);
}
}
}
/* Move to the correct position in the cell. */
if (refreshCells || movedCell)
{
/* Highlight the new cell. */
highlightCDKMatrixCell (matrix);
}
wnoutrefresh (matrix->win);
/* Should we call a post-process? */
if (matrix->postProcessFunction != 0)
{
((PROCESSFN)(matrix->postProcessFunction)) (vMATRIX, matrix, matrix->postProcessData, input);
}
}
/* Set the variables we need. */
matrix->oldcrow = matrix->crow;
matrix->oldccol = matrix->ccol;
matrix->oldvrow = matrix->row;
matrix->oldvcol = matrix->col;
/* Set the exit type and exit. */
matrix->exitType = vEARLY_EXIT;
return -1;
}
/*
* This allows the programmer to define their own key mappings.
*/
static void CDKMatrixCallBack (CDKMATRIX *matrix, chtype input)
{
/* Declare local variables. */
EDisplayType disptype = (EDisplayType)matrix->colvalues[matrix->col];
int charcount = (int)strlen (matrix->info[matrix->row][matrix->col]);
chtype newchar = 0;
/* Check the types */
if (disptype == vINT && !isdigit((int)input))
{
Beep();
}
else if ((disptype == vCHAR || disptype == vUCHAR ||
disptype == vLCHAR || disptype == vUHCHAR ||
disptype == vLHCHAR) && isdigit((int)input))
{
Beep();
}
else if (disptype == vVIEWONLY)
{
Beep();
}
else
{
/* Check the width of the string. */
if (charcount == matrix->colwidths[matrix->col])
{
Beep();
}
else
{
/* We will make any needed adjustments to the case of the character. */
newchar = input;
if ((disptype == vUCHAR || disptype == vUCHAR ||
disptype == vUMIXED || disptype == vUHMIXED)
&& !isdigit((int)input))
{
newchar = toupper(input);
}
else if ((disptype == vUCHAR || disptype == vUCHAR ||
disptype == vUMIXED || disptype == vUHMIXED) &&
!isdigit((int)input))
{
newchar = tolower(input);
}
/* Update the screen. */
wmove (matrix->cell[matrix->crow][matrix->ccol], 1, (int)strlen (matrix->info[matrix->row][matrix->col])+1);
waddch (matrix->cell[matrix->crow][matrix->ccol], newchar);
wrefresh (matrix->cell[matrix->crow][matrix->ccol]);
/* Update the character pointer. */
matrix->info[matrix->row][matrix->col][charcount++] = newchar;
matrix->info[matrix->row][matrix->col][charcount] = '\0';
}
}
}
/*
* Highlight the new field.
*/
static void highlightCDKMatrixCell (CDKMATRIX *matrix)
{
WINDOW *cell;
drawCDKMatrixCell (matrix, matrix->crow, matrix->ccol, matrix->row,
matrix->col, A_BOLD, TRUE);
/* Move the cursor to the correct position within the cell. */
cell = matrix->cell[matrix->crow][matrix->ccol];
if (matrix->colwidths[matrix->ccol] == 1)
{
wmove (cell, 1, 1);
}
else
{
wmove (cell, 1, (int)strlen (matrix->info[matrix->row][matrix->col])+1);
}
wnoutrefresh (cell);
}
/*
* This moves the matrix field to the given location.
*/
static void _moveCDKMatrix (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag)
{
CDKMATRIX *matrix = (CDKMATRIX *)object;
/*
* If this is a relative move, then we will adjust where we want
* to move to.
*/
if (relative)
{
xplace += getbegx(matrix->win);
yplace += getbegy(matrix->win);
}
/* Adjust the window if we need to. */
alignxy (WindowOf(matrix), &xplace, &yplace, matrix->boxWidth, matrix->boxHeight);
/* Move the window to the new location. */
moveCursesWindow(matrix->win, xplace, yplace);
/* 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, chtype attr, boolean Box)
{
/* Declare local variables. */
WINDOW *cell = matrix->cell[row][col];
chtype highlight;
int rows = matrix->vrows;
int cols = matrix->vcols;
int infolen = (int)strlen (matrix->info[vrow][vcol]);
/*
* 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;
}
else if (vrow == matrix->row && vcol == matrix->col)
{
highlight = matrix->highlight;
}
else
{
highlight = matrix->filler & A_ATTRIBUTES;
}
/* Draw in the cell info. */
mvwhline (cell, 1, 1,
matrix->filler | highlight, matrix->colwidths[col]);
writeCharAttrib (cell, 1, 1,
matrix->info[vrow][vcol], highlight, HORIZONTAL,
0, MINIMUM (matrix->colwidths[col], infolen));
wmove (cell, 1, infolen + 1);
/* Always box the current cell. */
if (vrow == matrix->row && vcol == matrix->col)
{
boxWindow (cell, A_BOLD);
}
/* If there is no box, draw blanks around the cell. */
else if (!Box)
{
attrbox (cell, ' ', ' ', ' ', ' ', ' ', ' ', A_NORMAL, FALSE);
}
/*
* If the value of the column spacing is greater than 0 then these
* are independent boxes.
*/
else if (matrix->colSpace != 0 && matrix->rowSpace != 0)
{
boxWindow (cell, attr);
}
else if (matrix->colSpace != 0 && matrix->rowSpace == 0)
{
if (row == 1)
{
attrbox (cell, ACS_ULCORNER, ACS_URCORNER,
ACS_LTEE, ACS_RTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (row > 1 && row < rows)
{
attrbox (cell, ACS_LTEE, ACS_RTEE,
ACS_LTEE, ACS_RTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (row == rows)
{
attrbox (cell, ACS_LTEE, ACS_RTEE,
ACS_LLCORNER, ACS_LRCORNER,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
}
else if (matrix->colSpace == 0 && matrix->rowSpace != 0)
{
if (col == 1)
{
attrbox (cell, ACS_ULCORNER, ACS_TTEE,
ACS_LLCORNER, ACS_BTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col > 1 && col < cols)
{
attrbox (cell, ACS_TTEE, ACS_TTEE,
ACS_BTEE, ACS_BTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col == cols)
{
attrbox (cell, ACS_TTEE, ACS_URCORNER,
ACS_BTEE, ACS_LRCORNER,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
}
/* Start drawing the matrix. */
else if (row == 1)
{
if (col == 1)
{
/* Draw the top left corner */
attrbox (cell, ACS_ULCORNER, ACS_TTEE,
ACS_LTEE, ACS_PLUS,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col > 1 && col < cols)
{
/* Draw the top middle box */
attrbox (cell, ACS_TTEE, ACS_TTEE,
ACS_PLUS, ACS_PLUS,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col == cols)
{
/* Draw the top right corner */
attrbox (cell, ACS_TTEE, ACS_URCORNER,
ACS_PLUS, ACS_RTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
}
else if (row > 1 && row < rows)
{
if (col == 1)
{
/* Draw the middle left box */
attrbox (cell, ACS_LTEE, ACS_PLUS,
ACS_LTEE, ACS_PLUS,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col > 1 && col < cols)
{
/* Draw the middle box */
attrbox (cell, ACS_PLUS, ACS_PLUS,
ACS_PLUS, ACS_PLUS,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col == cols)
{
/* Draw the middle right box */
attrbox (cell, ACS_PLUS, ACS_RTEE,
ACS_PLUS, ACS_RTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
}
else if (row == rows)
{
if (col == 1)
{
/* Draw the bottom left corner */
attrbox (cell, ACS_LTEE, ACS_PLUS,
ACS_LLCORNER, ACS_BTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col > 1 && col < cols)
{
/* Draw the bottom middle box */
attrbox (cell, ACS_PLUS, ACS_PLUS,
ACS_BTEE, ACS_BTEE,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
else if (col == cols)
{
/* Draw the bottom right corner */
attrbox (cell, ACS_PLUS, ACS_RTEE,
ACS_BTEE, ACS_LRCORNER,
ACS_HLINE, ACS_VLINE,
attr, FALSE);
}
}
wnoutrefresh (cell);
}
/*
* This function draws the matrix widget.
*/
static void _drawCDKMatrix (CDKOBJS *object, boolean Box)
{
CDKMATRIX *matrix = (CDKMATRIX *)object;
int x, y;
/* Should we box the matrix??? */
if (Box)
{
attrbox (matrix->win,
matrix->ULChar, matrix->URChar,
matrix->LLChar, matrix->LRChar,
matrix->HChar, matrix->VChar,
matrix->BoxAttrib,
matrix->shadow);
}
/* Draw in the title. */
for (x=0; x < matrix->titleLines; x++)
{
writeChtype (matrix->win,
matrix->titlePos[x],
x + 1,
matrix->title[x],
HORIZONTAL, 0,
matrix->titleLen[x]);
}
redrawTitles (matrix, TRUE, TRUE);
/* Draw in the cells.. */
for (x=0; x < matrix->vrows; x++)
{
for (y=0; y < matrix->vcols; y++)
{
drawCDKMatrixCell (matrix, x+1, y+1,
matrix->trow + x,
matrix->lcol + y,
A_NORMAL,
matrix->boxCell);
}
}
/* Highlight the new cell. */
highlightCDKMatrixCell (matrix);
/* Redraw the window. */
wnoutrefresh (matrix->win);
}
/*
* This function destroys the matrix widget.
*/
void destroyCDKMatrix (CDKMATRIX *matrix)
{
/* Declare local variables. */
int x = 0;
int y = 0;
/* Erase the object. */
eraseCDKMatrix (matrix);
/* Clear out the title. */
for (x=0; x < matrix->titleLines; x++)
{
freeChtype (matrix->title[x]);
}
/* 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[x][y]);
}
}
/* Clear the matrix windows. */
deleteCursesWindow (matrix->win);
/* Unregister this object. */
unregisterCDKObject (vMATRIX, matrix);
/* Finish cleaning up. */
free (matrix);
}
/*
* This function erases the matrix widget from the screen.
*/
static void _eraseCDKMatrix (CDKOBJS *object)
{
CDKMATRIX *matrix = (CDKMATRIX *)object;
eraseCursesWindow (matrix->win);
}
/*
* This function sets the values of the matrix widget.
*/
void setCDKMatrix (CDKMATRIX *matrix, char *info[MAX_MATRIX_ROWS][MAX_MATRIX_COLS], int rows, int *subSize)
{
/* Declare local variables. */
int x = 0;
int y = 0;
/* Clear out all the cells. */
for (x=1; x <= matrix->rows; x++)
{
for (y=1; y <= matrix->cols; y++)
{
/* Clean the old info, and copy in the new. */
if (matrix->info[x][y] != 0)
{
/* Clean the cell information. */
cleanChar (matrix->info[x][y], matrix->colwidths[y], '\0');
}
}
}
/* Copy in the new info. */
for (x=1; x <= rows; x++)
{
for (y=1; y <= subSize[x]; y++)
{
/* Copy in the new information. */
if (info[x][y] != 0)
{
strncpy (matrix->info[x][y], info[x][y], matrix->colwidths[y]);
}
}
}
}
/*
* This cleans out the information cells in the matrix widget.
*/
void cleanCDKMatrix (CDKMATRIX *matrix)
{
/* Declare local variables. */
int x = 0;
int y = 0;
for (x=1; x <= matrix->rows; x++)
{
for (y=1; y <= matrix->cols; y++)
{
cleanChar (matrix->info[x][y], matrix->colwidths[y], '\0');
}
}
}
/*
* This allows us to hyper-warp to a cell.
*/
int jumpToCell (CDKMATRIX *matrix, int row, int col)
{
/* Declare local variables. */
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)
{
/* Declare local variables. */
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)
{
/* Declare local variables. */
int x;
WINDOW *cell;
/* Redraw the row titles. */
if (rowTitles)
{
for (x=0; x < matrix->vrows; x++)
{
cell = matrix->cell[x+1][0];
werase (cell);
writeChtype (cell,
matrix->rowtitlePos[matrix->trow + x], 1,
matrix->rowtitle[matrix->trow + x],
HORIZONTAL,
0, matrix->rowtitleLen[matrix->trow + x]);
wnoutrefresh (cell);
}
}
/* Redraw the column titles. */
if (colTitles)
{
for (x=0; x < matrix->vcols; x++)
{
cell = matrix->cell[0][x+1];
werase (cell);
writeChtype (cell,
matrix->coltitlePos[matrix->lcol + x], 0,
matrix->coltitle[matrix->lcol + x],
HORIZONTAL,
0, matrix->coltitleLen[matrix->lcol + x]);
wnoutrefresh (cell);
}
}
}
/*
* This sets the value of a matrix cell.
*/
int setCDKMatrixCell (CDKMATRIX *matrix, int row, int col, 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;
}
/* Clean out the old value. */
cleanChar (matrix->info[row][col], matrix->colwidths[col]+1, '\0');
/* Copy the new version in and return. */
strncpy (matrix->info[row][col], value, 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[row][col];
}
/*
* This returns the current row/col cell.
*/
int getCDKMatrixCol (CDKMATRIX *matrix)
{
return matrix->col;
}
int getCDKMatrixRow (CDKMATRIX *matrix)
{
return matrix->row;
}
/*
* These functions set the drawing characters of the widget.
*/
void setCDKMatrixULChar (CDKMATRIX *matrix, chtype character)
{
matrix->ULChar = character;
}
void setCDKMatrixURChar (CDKMATRIX *matrix, chtype character)
{
matrix->URChar = character;
}
void setCDKMatrixLLChar (CDKMATRIX *matrix, chtype character)
{
matrix->LLChar = character;
}
void setCDKMatrixLRChar (CDKMATRIX *matrix, chtype character)
{
matrix->LRChar = character;
}
void setCDKMatrixVerticalChar (CDKMATRIX *matrix, chtype character)
{
matrix->VChar = character;
}
void setCDKMatrixHorizontalChar (CDKMATRIX *matrix, chtype character)
{
matrix->HChar = character;
}
void setCDKMatrixBoxAttribute (CDKMATRIX *matrix, chtype character)
{
matrix->BoxAttrib = character;
}
/*
* This sets the background color of the widget.
*/
void setCDKMatrixBackgroundColor (CDKMATRIX *matrix, char *color)
{
chtype *holder = 0;
int x, y, junk1, junk2;
if (color == 0)
{
return;
}
/* Convert the value of the environment variable to a chtype. */
holder = char2Chtype (color, &junk1, &junk2);
/* Set the widgets background color. */
wbkgd (matrix->win, holder[0]);
for (x=0; x <= matrix->vrows; x++)
{
for (y=0; y <= matrix->vcols; y++)
{
wbkgd (matrix->cell[x][y], holder[0]);
}
}
/* Clean up. */
freeChtype (holder);
}
/*
* This function sets the pre-process function.
*/
void setCDKMatrixPreProcess (CDKMATRIX *matrix, PROCESSFN callback, void *data)
{
matrix->preProcessFunction = callback;
matrix->preProcessData = data;
}
/*
* This function sets the post-process function.
*/
void setCDKMatrixPostProcess (CDKMATRIX *matrix, PROCESSFN callback, void *data)
{
matrix->postProcessFunction = callback;
matrix->postProcessData = data;
}