#include /* * $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, "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) { /* 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; }