#include <cdk_int.h>

/*
 * $Author: tom $
 * $Date: 2004/08/31 01:41:54 $
 * $Revision: 1.170 $
 */

/*
 * 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);

DeclareCDKObjects(MATRIX, Matrix, setCdk, Int);

/*
 * 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)
{
   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;

   static const struct { int from; int to; } bindings[] = {
		{ CDK_FORCHAR,	KEY_NPAGE },
		{ CDK_BACKCHAR,	KEY_PPAGE },
   };

   if ((matrix = newCDKObject(CDKMATRIX, &my_funcs)) == 0)
      return (0);

   setCDKMatrixBox (matrix, Box);

   /* 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.
    */
   matrix->rows			= rows;
   matrix->cols			= cols;

   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);

   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) = CDKcountStrings (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++)
   {
      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);

   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 + 1 + TitleLinesOf(matrix);

   /* Make the 'empty' 0x0 cell. */
   MATRIX_CELL(matrix,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(matrix,0,x) = subwin (matrix->win, 1, 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++)
   {
      /* Make the row titles */
      MATRIX_CELL(matrix,x,0) = subwin (matrix->win, 3, matrix->maxrt, begy, xpos+1);

      if (MATRIX_CELL(matrix,x,0) == 0)
      {
	 destroyCDKObject(matrix);
	 return (0);
      }

      /* 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(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);

   /* 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]	= BorderOf(matrix) + justifyString (colwidths[x], matrix->coltitleLen[x], matrix->coltitlePos[x]);
      matrix->colwidths[x]	= colwidths[x];
   }

   /* 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, 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;
      for (;;)
      {
	 ObjOf(matrix)->inputWindow = MATRIX_CELL(matrix, matrix->crow, matrix->ccol);
	 keypad(ObjOf(matrix)->inputWindow, TRUE);
	 input = getcCDKObject (ObjOf(matrix));

	 /* 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)
{
   CDKMATRIX *matrix = (CDKMATRIX *)object;
   int refreshCells	= FALSE;
   int movedCell	= FALSE;
   int charcount	= (int)strlen (MATRIX_INFO(matrix, matrix->row, matrix->col));
   int ppReturn		= 1;
   int x, y, infolen;
   int ret		= unknownInt;
   bool complete	= FALSE;

   /* Set the exit type. */
   setExitType(matrix, 0);

   /* Move the cursor to the correct position within the cell. */
   if (matrix->colwidths[matrix->ccol] == 1)
   {
      wmove (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, 1);
   }
   else
   {
      wmove (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1,
		(int)strlen (MATRIX_INFO(matrix, matrix->row, matrix->col))+1);
   }

   /* Put the focus on the current cell */
   attrbox (MATRIX_CELL(matrix, matrix->crow, matrix->ccol),
		ACS_ULCORNER,	ACS_URCORNER,
		ACS_LLCORNER,	ACS_LRCORNER,
		ACS_HLINE,	ACS_VLINE,
		A_BOLD);
   wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
   highlightCDKMatrixCell (matrix);

   /* Check if there is a pre-process function to be called. */
   if (PreProcessFuncOf(matrix) != 0)
   {
      /* Call the pre-process function. */
      ppReturn = PreProcessFuncOf(matrix) (vMATRIX, matrix, PreProcessDataOf(matrix), input);
   }

   /* Should we continue? */
   if (ppReturn != 0)
   {
      /* Check the key bindings. */
      if (checkCDKObjectBind (vMATRIX, matrix, input) != 0)
      {
	 checkEarlyExit(matrix);
	 complete = TRUE;
      }
      else
      {
	 switch (input)
	 {
	    case CDK_TRANSPOSE :
		 break;

	    case KEY_HOME :
		 break;

	    case KEY_END :
		 break;

	    case KEY_BACKSPACE : case KEY_DC :
		 if (matrix->colvalues[matrix->col] == vVIEWONLY)
		 {
		   Beep();
		 }
		 else
		 {
		    if (charcount > 0)
		    {
		       charcount--;
		       mvwdelch (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, charcount+1);
		       mvwinsch (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, charcount+1, matrix->filler);
		       wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
		       MATRIX_INFO(matrix, 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++;

		       /* Redraw the column titles. */
		       if (matrix->rows > matrix->vrows)
		       {
			  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 : case KEY_BTAB :
		 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--;

		       /* Redraw the column titles. */
		       if (matrix->cols > matrix->vcols)
		       {
			  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
		 {
		    if (matrix->trow != 1)
		    {
		       matrix->trow--;
		       matrix->row--;

		       /* Redraw the row titles. */
		       if (matrix->rows > matrix->vrows)
		       {
			  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
		 {
		    if ((matrix->trow + matrix->vrows - 1) != matrix->rows)
		    {
		       matrix->trow++;
		       matrix->row++;

		       /* Redraw the titles. */
		       if (matrix->rows > matrix->vrows)
		       {
			  redrawTitles (matrix, TRUE, FALSE);
		       }
		       refreshCells	= TRUE;
		       movedCell	= TRUE;
		    }
		    else
		    {
		       Beep();
		    }
		 }
		 break;

	    case KEY_NPAGE :
		 if (matrix->rows > matrix->vrows)
		 {
		    if ((matrix->trow + ((matrix->vrows - 1) * 2)) <= matrix->rows)
		    {
		       matrix->trow	+= matrix->vrows - 1;
		       matrix->row	+= matrix->vrows - 1;
		       redrawTitles (matrix, TRUE, FALSE);
		       refreshCells	= TRUE;
		       movedCell	= TRUE;
		    }
		    else
		    {
		       Beep();
		    }
		 }
		 else
		 {
		    Beep();
		 }
		 break;

	    case KEY_PPAGE :
		 if (matrix->rows > matrix->vrows)
		 {
		    if ((matrix->trow - ((matrix->vrows - 1) * 2)) >= 1)
		    {
		       matrix->trow	-= matrix->vrows - 1;
		       matrix->row	-= matrix->vrows - 1;
		       redrawTitles (matrix, TRUE, FALSE);
		       refreshCells	= TRUE;
		       movedCell	= TRUE;
		    }
		    else
		    {
		       Beep();
		    }
		 }
		 else
		 {
		    Beep();
		 }
		 break;

	 case CTRL('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, 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, matrix->trow+matrix->crow-1, matrix->lcol+matrix->ccol-1));
	      break;

	 case CDK_CUT :
	      freeChar (GPasteBuffer);
	      GPasteBuffer	= copyChar (MATRIX_INFO(matrix, matrix->trow+matrix->crow-1, matrix->lcol+matrix->ccol-1));
	      cleanCDKMatrixCell (matrix, matrix->trow + matrix->crow - 1, matrix->lcol + matrix->ccol - 1);
	      drawCDKMatrixCell (matrix, matrix->crow, matrix->ccol, matrix->row, matrix->col, A_NORMAL, matrix->boxCell);
	      break;

	 case CDK_ERASE :
	      cleanCDKMatrixCell (matrix, matrix->trow + matrix->crow - 1, matrix->lcol + matrix->ccol - 1);
	      drawCDKMatrixCell (matrix, matrix->crow, matrix->ccol, matrix->row, matrix->col, A_NORMAL, matrix->boxCell);
	      break;

	 case KEY_ENTER :
	      if (!matrix->boxCell)
	      {
		 attrbox (MATRIX_CELL(matrix, matrix->oldcrow, matrix->oldccol),
				' ',	' ',
				' ',	' ',
				' ',	' ',
				A_NORMAL);
	      }
	      else
	      {
		 drawCDKMatrixCell (matrix,
				matrix->oldcrow,
				matrix->oldccol,
				matrix->oldvrow,
				matrix->oldvcol,
				A_NORMAL,
				matrix->boxCell);
	      }
	      wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
	      setExitType(matrix, input);
	      ret = 1;
	      complete = TRUE;
	      break;

	 case KEY_ESC :
	      if (!matrix->boxCell)
	      {
		 attrbox (MATRIX_CELL(matrix, matrix->oldcrow, matrix->oldccol),
				' ',	' ',
				' ',	' ',
				' ',	' ',
				A_NORMAL);
	      }
	      else
	      {
		 drawCDKMatrixCell (matrix,
				matrix->oldcrow,
				matrix->oldccol,
				matrix->oldvrow,
				matrix->oldvcol,
				A_NORMAL,
				matrix->boxCell);
	      }
	      wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
	      setExitType(matrix, input);
	      complete = TRUE;
	      break;

	 case CDK_REFRESH :
	      eraseCDKScreen (ScreenOf(matrix));
	      refreshCDKScreen (ScreenOf(matrix));
	      break;

	 default :
	      (matrix->callbackfn)(matrix, input);
	      break;
	 }
      }

      if (!complete)
      {
	 /* Did we change cells? */
	 if (movedCell)
	 {
	    /* un-highlight the old box  */
	    if (!matrix->boxCell)
	    {
	       attrbox (MATRIX_CELL(matrix, matrix->oldcrow, matrix->oldccol),
			   ' ',	' ',
			   ' ',	' ',
			   ' ',	' ',
			   A_NORMAL);
	    }
	    else
	    {
	       drawCDKMatrixCell (matrix,
				   matrix->oldcrow,
				   matrix->oldccol,
				   matrix->oldvrow,
				   matrix->oldvcol,
				   0,
				   matrix->boxCell);
	    }
	    wrefresh (MATRIX_CELL(matrix, matrix->oldcrow, matrix->oldccol));

	    /* Highlight the new cell. */
	    attrbox (MATRIX_CELL(matrix, matrix->crow, matrix->ccol),
			   ACS_ULCORNER,	ACS_URCORNER,
			   ACS_LLCORNER,	ACS_LRCORNER,
			   ACS_HLINE,	ACS_VLINE,
			   A_BOLD);
	    wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
	    highlightCDKMatrixCell (matrix);
	 }

	 /* Redraw each cell. */
	 if (refreshCells)
	 {
	    /* 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,
					   0,
					   matrix->boxCell);
	       }
	    }

	    /* Highlight the current cell. */
	    attrbox (MATRIX_CELL(matrix, matrix->crow, matrix->ccol),
			   ACS_ULCORNER,	ACS_URCORNER,
			   ACS_LLCORNER,	ACS_LRCORNER,
			   ACS_HLINE,	ACS_VLINE,
			   A_BOLD);
	    wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
	    highlightCDKMatrixCell (matrix);
	 }

	 /* Move to the correct position in the cell. */
	 if (refreshCells || movedCell)
	 {
	    if (matrix->colwidths[matrix->ccol] == 1)
	    {
	       wmove (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, 1);
	    }
	    else
	    {
	       infolen = (int)strlen (MATRIX_INFO(matrix, matrix->trow+matrix->crow-1, matrix->lcol+matrix->ccol-1));
	       wmove (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, infolen+1);
	    }
	    wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
	 }

	 /* Should we call a post-process? */
	 if (PostProcessFuncOf(matrix) != 0)
	 {
	    PostProcessFuncOf(matrix) (vMATRIX, matrix, PostProcessDataOf(matrix), input);
	 }
      }
   }

   if (!complete) {
      /* 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. */
      setExitType(matrix, 0);
   }

   ResultOf(matrix).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 charcount		= (int)strlen (MATRIX_INFO(matrix, matrix->row, matrix->col));
   chtype newchar		= 0;

   /* Check the types */
   if (!isChar(input))
   {
      Beep();
   }
   else if (disptype == vINT && !isdigit(CharOf(input)))
   {
      Beep();
   }
   else if ((disptype == vCHAR || disptype == vUCHAR ||
		disptype == vLCHAR || disptype == vUHCHAR ||
		disptype == vLHCHAR) && isdigit(CharOf(input)))
   {
      Beep();
   }
   else if (disptype == vVIEWONLY)
   {
      Beep();
   }
   else 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(CharOf(input)))
      {
	 newchar = toupper(input);
      }
      else if ((disptype == vUCHAR || disptype == vUCHAR ||
		     disptype == vUMIXED || disptype == vUHMIXED) &&
		     !isdigit(CharOf(input)))
      {
	 newchar = tolower(input);
      }

      /* Update the screen. */
      wmove (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, (int)strlen (MATRIX_INFO(matrix, matrix->row, matrix->col))+1);
      waddch (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), newchar);
      wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));

      /* Update the character pointer. */
      MATRIX_INFO(matrix, matrix->row, matrix->col)[charcount++] = newchar;
      MATRIX_INFO(matrix, matrix->row, matrix->col)[charcount] = '\0';
   }
}

/*
 * Highlight the new field.
 */
static void highlightCDKMatrixCell (CDKMATRIX *matrix)
{
   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)
		? CharOf(MATRIX_INFO(matrix, matrix->row, matrix->col)[x-1])
		: matrix->filler;

      mvwaddch (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, x, ch | highlight);
   }
   wmove (MATRIX_CELL(matrix, matrix->crow, matrix->ccol), 1, infolen+1);
   wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
}

/*
 * 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;
   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, chtype attr, boolean Box)
{
   WINDOW *cell		= MATRIX_CELL(matrix, row, col);
   chtype highlight	= matrix->filler & A_ATTRIBUTES;
   int rows		= matrix->vrows;
   int cols		= matrix->vcols;
   int infolen		= (int)strlen (MATRIX_INFO(matrix, vrow, vcol));
   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)
		? (CharOf(MATRIX_INFO(matrix, vrow, vcol)[x-1]) | highlight)
		: matrix->filler;

      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 && matrix->rowSpace != 0)
   {
      attrbox (cell, ACS_ULCORNER, ACS_URCORNER,
		ACS_LLCORNER, ACS_LRCORNER,
		ACS_HLINE, ACS_VLINE,
		attr);
      return;
   }
   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);
	 return;
      }
      else if (row > 1 && row < rows)
      {
	 attrbox (cell, ACS_LTEE, ACS_RTEE,
			ACS_LTEE, ACS_RTEE,
			ACS_HLINE, ACS_VLINE,
			attr);
	 return;
      }
      else if (row == rows)
      {
	 attrbox (cell, ACS_LTEE, ACS_RTEE,
			ACS_LLCORNER, ACS_LRCORNER,
			ACS_HLINE, ACS_VLINE,
			attr);
	 return;
      }
   }
   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);
	 return;
      }
      else if (col > 1 && col < cols)
      {
	 attrbox (cell, ACS_TTEE, ACS_TTEE,
			ACS_BTEE, ACS_BTEE,
			ACS_HLINE, ACS_VLINE,
			attr);
	 return;
      }
      else if (col == cols)
      {
	 attrbox (cell, ACS_TTEE, ACS_URCORNER,
			ACS_BTEE, ACS_LRCORNER,
			ACS_HLINE, ACS_VLINE,
			attr);
	 return;
      }
   }

   /* Start drawing the matrix. */
   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);
      }
      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);
      }
      else if (col == cols)
      {
	 /* Draw the top right corner */
	 attrbox (cell, ACS_TTEE, ACS_URCORNER,
			ACS_PLUS, ACS_RTEE,
			ACS_HLINE, ACS_VLINE,
			attr);
      }
   }
   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);
      }
      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);
      }
      else if (col == cols)
      {
	 /* Draw the middle right box */
	 attrbox (cell, ACS_PLUS, ACS_RTEE,
			ACS_PLUS, ACS_RTEE,
			ACS_HLINE, ACS_VLINE,
			attr);
      }
   }
   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);
      }
      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);
      }
      else if (col == cols)
      {
	 /* Draw the bottom right corner */
	 attrbox (cell, ACS_PLUS, ACS_RTEE,
			ACS_BTEE, ACS_LRCORNER,
			ACS_HLINE, ACS_VLINE,
			attr);
      }
   }

   /* Highlight the current cell. */
   attrbox (MATRIX_CELL(matrix, matrix->crow, matrix->ccol),
		ACS_ULCORNER,	ACS_URCORNER,
		ACS_LLCORNER,	ACS_LRCORNER,
		ACS_HLINE,	ACS_VLINE,
		A_BOLD);
   wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
   highlightCDKMatrixCell (matrix);
}

/*
 * This function draws the matrix widget.
 */
static void _drawCDKMatrix (CDKOBJS *object, boolean Box)
{
   CDKMATRIX *matrix = (CDKMATRIX *)object;
   int x, y;

   /* 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);

   refreshCDKWindow (matrix->win);

   /* Draw in the column titles. */
   for (x=1; x <= matrix->vcols; x++)
   {
      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));
   }

   /* Fill in the rest of the matrix. */
   for (x=1; x <= matrix->vrows; x++)
   {
      /* Draw in the row titles */
      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));

      /* Draw in the cells.. */
      for (y=1; y <= matrix->vcols; y++)
      {
	 drawCDKMatrixCell (matrix, x, y,
				matrix->trow + x-1,
				matrix->lcol + y-1,
				A_NORMAL,
				matrix->boxCell);
      }
   }

   /* Highlight the current cell. */
   attrbox (MATRIX_CELL(matrix, matrix->crow, matrix->ccol),
		ACS_ULCORNER,	ACS_URCORNER,
		ACS_LLCORNER,	ACS_LRCORNER,
		ACS_HLINE,	ACS_VLINE,
		A_BOLD);
   wrefresh (MATRIX_CELL(matrix, matrix->crow, matrix->ccol));
   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);

      /* 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);
   }
}

/*
 * This function sets the values of the matrix widget.
 */
void setCDKMatrixCells (CDKMATRIX *matrix, char **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])
	 {
	    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, matrix->colwidths[y]);
	    }
	 }
	 else
	    cleanCDKMatrixCell(matrix, x, y);
      }
   }
}

/*
 * This sets the widget's box attribute.
 */
void setCDKMatrixBox (CDKMATRIX *matrix, boolean Box)
{
   ObjOf(matrix)->box = Box;
   ObjOf(matrix)->borderSize = Box ? 1 : 0;
}
boolean getCDKMatrixBox (CDKMATRIX *matrix)
{
   return ObjOf(matrix)->box;
}

/*
 * This cleans out the information cells in the matrix widget.
 */
void cleanCDKMatrix (CDKMATRIX *matrix)
{
   int x	= 0;
   int y	= 0;

   for (x=1; x <= matrix->rows; x++)
   {
      for (y=1; y <= matrix->cols; y++)
      {
	 cleanCDKMatrixCell (matrix, x, y);
      }
   }
}

/*
 * This cleans one cell in the matrix widget.
 */
void cleanCDKMatrixCell (CDKMATRIX *matrix, int row, int col)
{
   if (row > 0 && row <= matrix->rows
    && col > 0 && col <= matrix->cols)
      cleanChar (MATRIX_INFO(matrix, row, col), matrix->colwidths[col], '\0');
}

/*
 * This allows us to hyper-warp to a cell.
 */
int jumpToCell (CDKMATRIX *matrix, int row, int col)
{
   CDKSCALE *scale	= 0;
   int newRow		= row;
   int newCol		= col;

  /*
   * Only create the row scale if needed.
   */
   if ((row == -1) || (row > matrix->rows))
   {
      /* Create the row scale widget. */
      scale = newCDKScale (ScreenOf(matrix),
				CENTER, CENTER,
				"<C>Jump to which row.",
				"</5/B>Row: ", A_NORMAL, 5,
				1, 1, matrix->rows, 1, 1, TRUE, FALSE);

      /* Activate the scale and get the row. */
      newRow = activateCDKScale (scale, 0);
      destroyCDKScale (scale);
   }

  /*
   * Only create the column scale if needed.
   */
   if ((col == -1) || (col > matrix->cols))
   {
      /* Create the column scale widget. */
      scale = newCDKScale (ScreenOf(matrix),
				CENTER, CENTER,
				"<C>Jump to which column",
				"</5/B>Col: ", A_NORMAL, 5,
				1, 1, matrix->cols, 1, 1, TRUE, FALSE);

      /* Activate the scale and get the column. */
      newCol = activateCDKScale (scale, 0);
      destroyCDKScale (scale);
   }

   /* Hyper-warp.... */
   if (newRow != matrix->row || newCol != matrix->col)
   {
      return (moveToCDKMatrixCell (matrix, newRow, newCol));
   }
   else
   {
      return 1;
   }
}

/*
 * This allows us to move to a given cell.
 */
int moveToCDKMatrixCell (CDKMATRIX *matrix, int newrow, int newcol)
{
   int rowShift = newrow - matrix->row;
   int colShift = newcol - matrix->col;

   /* Make sure we arent asking to move out of the matrix. */
   if (newrow > matrix->rows || newcol > matrix->cols || newrow <= 0 || newcol <= 0)
   {
      return 0;
   }

   /* Did we move up/down???? */
   if (rowShift > 0)
   {
      /* We are moving down. */
      if (matrix->vrows == matrix->cols)
      {
	 matrix->trow	= 1;
	 matrix->crow	= newrow;
	 matrix->row	= newrow;
      }
      else
      {
	 if ((rowShift + matrix->vrows) < matrix->rows)
	 {
	    /* Just shift down by rowShift... */
	    matrix->trow	+= rowShift;
	    matrix->crow	= 1;
	    matrix->row		+= rowShift;
	 }
	 else
	 {
	    /* We need to munge with the values... */
	    matrix->trow	= matrix->rows - matrix->vrows + 1;
	    matrix->crow	= ((rowShift + matrix->vrows) - matrix->rows) + 1;
	    matrix->row		= newrow;
	 }
      }
   }
   else if (rowShift < 0)
   {
      /* We are moving up. */
      if (matrix->vrows == matrix->rows)
      {
	 matrix->trow	= 1;
	 matrix->row	= newrow;
	 matrix->crow	= newrow;
      }
      else
      {
	 if ((rowShift + matrix->vrows) > 1)
	 {
	    /* Just shift up by rowShift... */
	    matrix->trow	+= rowShift;
	    matrix->row		+= rowShift;
	    matrix->crow	= 1;
	 }
	 else
	 {
	    /* We need to munge with the values... */
	    matrix->trow	= 1;
	    matrix->crow	= 1;
	    matrix->row		= 1;
	 }
      }
   }

   /* Did we move left/right ???? */
   if (colShift > 0)
   {
      /* We are moving right. */
      if (matrix->vcols == matrix->cols)
      {
	 matrix->lcol	= 1;
	 matrix->ccol	= newcol;
	 matrix->col	= newcol;
      }
      else
      {
	 if ((colShift + matrix->vcols) < matrix->cols)
	 {
	    matrix->lcol	+= colShift;
	    matrix->ccol	= 1;
	    matrix->col		+= colShift;
	 }
	 else
	 {
	    /* We need to munge with the values... */
	    matrix->lcol	= matrix->cols - matrix->vcols + 1;
	    matrix->ccol	= ((colShift + matrix->vcols) - matrix->cols) + 1;
	    matrix->col		= newcol;
	 }
      }
   }
   else if (colShift < 0)
   {
      /* We are moving left. */
      if (matrix->vcols == matrix->cols)
      {
	    matrix->lcol	= 1;
	    matrix->col		= newcol;
	    matrix->ccol	= newcol;
      }
      else
      {
	 if ((colShift + matrix->vcols) > 1)
	 {
	    /* Just shift left by colShift... */
	    matrix->lcol	+= colShift;
	    matrix->col		+= colShift;
	    matrix->ccol	= 1;
	 }
	 else
	 {
	    matrix->lcol	= 1;
	    matrix->col		= 1;
	    matrix->ccol	= 1;
	 }
      }
   }

   /* Keep the 'old' values around for redrawing sake. */
   matrix->oldcrow	= matrix->crow;
   matrix->oldccol	= matrix->ccol;
   matrix->oldvrow	= matrix->row;
   matrix->oldvcol	= matrix->col;

   /* Lets ... */
   return 1;
}

/*
 * This redraws the titles indicated...
 */
static void redrawTitles (CDKMATRIX *matrix, int rowTitles, int colTitles)
{
   int x = 0;

   /* Redraw the row titles. */
   if (rowTitles)
   {
      for (x=1; x <= matrix->vrows; x++)
      {
	 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));
      }
   }

   /* Redraw the column titles. */
   if (colTitles)
   {
      for (x=1; x <=matrix->vcols; x++)
      {
	 werase (MATRIX_CELL(matrix, 0, x));
	 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));
      }
   }
}

/*
 * 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;
   }

   cleanCDKMatrixCell (matrix, row, col);
   strncpy (MATRIX_INFO(matrix, 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(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)


syntax highlighted by Code2HTML, v. 0.9.1