#include /* * $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, "Jump to which row.", "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, "Jump to which column", "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)