1 #include <cdk_int.h>
2 
3 /*
4  * $Author: tom $
5  * $Date: 2016/12/10 15:18:01 $
6  * $Revision: 1.198 $
7  */
8 
9 /*
10  * Declare file local prototypes.
11  */
12 static void highlightCDKMatrixCell (CDKMATRIX *matrix);
13 static void CDKMatrixCallBack (CDKMATRIX *matrix, chtype input);
14 static void drawCDKMatrixCell (CDKMATRIX *matrix,
15 			       int srow, int scol,
16 			       int vrow, int vcol,
17 			       boolean Box);
18 static void drawCurCDKMatrixCell (CDKMATRIX *matrix);
19 static void drawEachCDKMatrixCell (CDKMATRIX *matrix);
20 static void drawEachColTitle (CDKMATRIX *matrix);
21 static void drawEachRowTitle (CDKMATRIX *matrix);
22 static void drawOldCDKMatrixCell (CDKMATRIX *matrix);
23 static void redrawTitles (CDKMATRIX *matrix, int row, int col);
24 
25 #define emptyString(s) ((s) == 0 || *(s) == '\0')
26 
27 #define CurMatrixCell(matrix) \
28 	    MATRIX_CELL (matrix, matrix->crow, matrix->ccol)
29 
30 #define CurMatrixInfo(matrix) \
31 	    MATRIX_INFO (matrix, \
32 	    matrix->trow + matrix->crow - 1, \
33 	    matrix->lcol + matrix->ccol - 1)
34 
35 DeclareCDKObjects (MATRIX, Matrix, setCdk, Int);
36 
37 #define WHOLE_BOX ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER
38 
39 #define TOP_C_BOX ACS_ULCORNER, ACS_URCORNER, ACS_LTEE,     ACS_RTEE
40 #define MID_C_BOX ACS_LTEE,     ACS_RTEE,     ACS_LTEE,     ACS_RTEE
41 #define BOT_C_BOX ACS_LTEE,     ACS_RTEE,     ACS_LLCORNER, ACS_LRCORNER
42 
43 #define LFT_R_BOX ACS_ULCORNER, ACS_TTEE,     ACS_LLCORNER, ACS_BTEE
44 #define MID_R_BOX ACS_TTEE,     ACS_TTEE,     ACS_BTEE,     ACS_BTEE
45 #define RGT_R_BOX ACS_TTEE,     ACS_URCORNER, ACS_BTEE,     ACS_LRCORNER
46 
47 #define LFT_T_BOX ACS_ULCORNER, ACS_TTEE,     ACS_LTEE,     ACS_PLUS
48 #define MID_T_BOX ACS_TTEE,     ACS_TTEE,     ACS_PLUS,     ACS_PLUS
49 #define RGT_T_BOX ACS_TTEE,     ACS_URCORNER, ACS_PLUS,     ACS_RTEE
50 
51 #define LFT_M_BOX ACS_LTEE,     ACS_PLUS,     ACS_LTEE,     ACS_PLUS
52 #define MID_M_BOX ACS_PLUS,     ACS_PLUS,     ACS_PLUS,     ACS_PLUS
53 #define RGT_M_BOX ACS_PLUS,     ACS_RTEE,     ACS_PLUS,     ACS_RTEE
54 
55 #define LFT_B_BOX ACS_LTEE,     ACS_PLUS,     ACS_LLCORNER, ACS_BTEE
56 #define MID_B_BOX ACS_PLUS,     ACS_PLUS,     ACS_BTEE,     ACS_BTEE
57 #define RGT_B_BOX ACS_PLUS,     ACS_RTEE,     ACS_BTEE,     ACS_LRCORNER
58 
59 #define MyBox(cell,what,attr) attrbox(cell, what, ACS_HLINE, ACS_VLINE, attr)
60 
61 /*
62  * This function creates the matrix widget.
63  */
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)64 CDKMATRIX *newCDKMatrix (CDKSCREEN *cdkscreen,
65 			 int xplace,
66 			 int yplace,
67 			 int rows,
68 			 int cols,
69 			 int vrows,
70 			 int vcols,
71 			 const char *title,
72 			 CDK_CSTRING2 rowtitles,
73 			 CDK_CSTRING2 coltitles,
74 			 int *colwidths,
75 			 int *colvalues,
76 			 int rspace,
77 			 int cspace,
78 			 chtype filler,
79 			 int dominant,
80 			 boolean Box,
81 			 boolean boxCell,
82 			 boolean shadow)
83 {
84    /* *INDENT-EQLS* */
85    CDKMATRIX *matrix    = 0;
86    int parentWidth      = getmaxx (cdkscreen->window);
87    int parentHeight     = getmaxy (cdkscreen->window);
88    int boxHeight        = 0;
89    int boxWidth         = 0;
90    int xpos             = xplace;
91    int ypos             = yplace;
92    int maxWidth;
93    int maxRowTitleWidth = 0;
94    int rowSpace         = MAXIMUM (0, rspace);
95    int colSpace         = MAXIMUM (0, cspace);
96    int begx             = 0;
97    int begy             = 0;
98    int cellWidth        = 0;
99    char **temp          = 0;
100    int x, y;
101    int borderw          = 0;
102    bool have_rowtitles  = FALSE;
103    bool have_coltitles  = FALSE;
104    /* *INDENT-OFF* */
105    static const struct { int from; int to; } bindings[] = {
106       { CDK_FORCHAR,	KEY_NPAGE },
107       { CDK_BACKCHAR,	KEY_PPAGE },
108    };
109    /* *INDENT-ON* */
110 
111    if ((matrix = newCDKObject (CDKMATRIX, &my_funcs)) == 0)
112    {
113       return (0);
114    }
115 
116    setCDKMatrixBox (matrix, Box);
117    borderw = (ObjOf (matrix)->box) ? 1 : 0;
118 
119    /* Make sure that the number of rows/cols/vrows/vcols is not zero. */
120    if (rows <= 0 || cols <= 0 || vrows <= 0 || vcols <= 0)
121    {
122       destroyCDKObject (matrix);
123       return (0);
124    }
125 #if NEW_CDKMATRIX
126    matrix->cell = typeCallocN (WINDOW *, (rows + 1) * (cols + 1));
127    matrix->info = typeCallocN (char *, (rows + 1) * (cols + 1));
128 #endif
129 
130    /*
131     * Make sure the number of virtual cells is not larger than
132     * the physical size.
133     */
134    vrows = (vrows > rows ? rows : vrows);
135    vcols = (vcols > cols ? cols : vcols);
136 
137    /* Set these early, since they are used in matrix index computations */
138    /* *INDENT-EQLS* */
139    matrix->rows        = rows;
140    matrix->cols        = cols;
141    /* columns */
142    matrix->colwidths   = typeCallocN (int, cols + 1);
143    matrix->colvalues   = typeCallocN (int, cols + 1);
144    matrix->coltitle    = typeCallocN (chtype *, cols + 1);
145    matrix->coltitleLen = typeCallocN (int, cols + 1);
146    matrix->coltitlePos = typeCallocN (int, cols + 1);
147    /* titles */
148    matrix->rowtitle    = typeCallocN (chtype *, rows + 1);
149    matrix->rowtitleLen = typeCallocN (int, rows + 1);
150    matrix->rowtitlePos = typeCallocN (int, rows + 1);
151 
152    /*
153     * Count the number of lines in the title (see setCdkTitle).
154     */
155    temp = CDKsplitString (title, '\n');
156    TitleLinesOf (matrix) = (int)CDKcountStrings ((CDK_CSTRING2)temp);
157    CDKfreeStrings (temp);
158 
159    /* Determine the height of the box. */
160    if (vrows == 1)
161    {
162       boxHeight = 6 + TitleLinesOf (matrix);
163    }
164    else
165    {
166       if (rowSpace == 0)
167       {
168 	 boxHeight = (6 + TitleLinesOf (matrix) +
169 		      ((vrows - 1) * 2));
170       }
171       else
172       {
173 	 boxHeight = (3 + TitleLinesOf (matrix) +
174 		      (vrows * 3) + ((vrows - 1) * (rowSpace - 1)));
175       }
176    }
177 
178    /* Determine the maximum row title width */
179    for (x = 1; x <= rows; x++)
180    {
181       if (rowtitles && !emptyString (rowtitles[x]))	/*VR */
182 	 have_rowtitles = TRUE;
183       matrix->rowtitle[x] = char2Chtype (rowtitles ? rowtitles[x] : 0,	/*VR */
184 					 &matrix->rowtitleLen[x],
185 					 &matrix->rowtitlePos[x]);
186       maxRowTitleWidth = MAXIMUM (maxRowTitleWidth, matrix->rowtitleLen[x]);
187    }
188 
189    if (have_rowtitles)
190    {
191       matrix->maxrt = maxRowTitleWidth + 2;
192 
193       /* We need to rejustify the row title cell info. */
194       for (x = 1; x <= rows; x++)
195       {
196 	 matrix->rowtitlePos[x] = justifyString (matrix->maxrt,
197 						 matrix->rowtitleLen[x],
198 						 matrix->rowtitlePos[x]);
199       }
200    }
201    else
202    {
203       matrix->maxrt = 0;
204    }
205 
206    /* Determine the width of the matrix. */
207    maxWidth = 2 + matrix->maxrt;
208    for (x = 1; x <= vcols; x++)
209    {
210       maxWidth += colwidths[x] + 2 + colSpace;
211    }
212    maxWidth -= (colSpace - 1);
213    boxWidth = MAXIMUM (maxWidth, boxWidth);
214 
215    boxWidth = setCdkTitle (ObjOf (matrix), title, boxWidth);
216 
217    /*
218     * Make sure the dimensions of the window didn't
219     * extend beyond the dimensions of the parent window.
220     */
221    boxWidth = (boxWidth > parentWidth ? parentWidth : boxWidth);
222    boxHeight = (boxHeight > parentHeight ? parentHeight : boxHeight);
223 
224    /* Rejustify the x and y positions if we need to. */
225    alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
226 
227    /* Make the pop-up window. */
228    matrix->win = newwin (boxHeight, boxWidth, ypos, xpos);
229 
230    if (matrix->win == 0)
231    {
232       destroyCDKObject (matrix);
233       return (0);
234    }
235 
236    /* Make the subwindows in the pop-up. */
237    begx = xpos;
238    begy = ypos + borderw + TitleLinesOf (matrix);
239 
240    /* Make the 'empty' 0x0 cell. */
241    MATRIX_CELL (matrix, 0, 0) = subwin (matrix->win, 3, matrix->maxrt, begy, begx);
242    begx += matrix->maxrt + 1;
243 
244    /* Copy the titles into the structure. */
245    for (x = 1; x <= cols; x++)
246    {
247       if (coltitles && !emptyString (coltitles[x]))	/*VR */
248 	 have_coltitles = TRUE;
249       matrix->coltitle[x] = char2Chtype (coltitles ? coltitles[x] : 0,	/*VR */
250 					 &matrix->coltitleLen[x],
251 					 &matrix->coltitlePos[x]);
252       matrix->coltitlePos[x] = (BorderOf (matrix) +
253 				justifyString (colwidths[x],
254 					       matrix->coltitleLen[x],
255 					       matrix->coltitlePos[x]));
256       matrix->colwidths[x] = colwidths[x];
257    }
258 
259    if (have_coltitles)
260    {
261       /* Make the column titles. */
262       for (x = 1; x <= vcols; x++)
263       {
264 	 cellWidth = colwidths[x] + 3;
265 	 MATRIX_CELL (matrix, 0, x) = subwin (matrix->win,
266 					      borderw,
267 					      cellWidth,
268 					      begy,
269 					      begx);
270 
271 	 if (MATRIX_CELL (matrix, 0, x) == 0)
272 	 {
273 	    destroyCDKObject (matrix);
274 	    return (0);
275 	 }
276 	 begx += cellWidth + colSpace - 1;
277       }
278       begy++;
279    }
280 
281    /* Make the main cell body */
282    for (x = 1; x <= vrows; x++)
283    {
284       if (have_rowtitles)
285       {
286 	 /* Make the row titles */
287 	 MATRIX_CELL (matrix, x, 0) = subwin (matrix->win,
288 					      3, matrix->maxrt,
289 					      begy, xpos + borderw);
290 
291 	 if (MATRIX_CELL (matrix, x, 0) == 0)
292 	 {
293 	    destroyCDKObject (matrix);
294 	    return (0);
295 	 }
296       }
297 
298       /* Set the start of the x position. */
299       begx = xpos + matrix->maxrt + borderw;
300 
301       /* Make the cells */
302       for (y = 1; y <= vcols; y++)
303       {
304 	 cellWidth = colwidths[y] + 3;
305 	 MATRIX_CELL (matrix, x, y) = subwin (matrix->win,
306 					      3, cellWidth,
307 					      begy, begx);
308 
309 	 if (MATRIX_CELL (matrix, x, y) == 0)
310 	 {
311 	    destroyCDKObject (matrix);
312 	    return (0);
313 	 }
314 	 begx += cellWidth + colSpace - 1;
315 	 keypad (MATRIX_CELL (matrix, x, y), TRUE);
316       }
317       begy += rowSpace + 2;
318    }
319    keypad (matrix->win, TRUE);
320 
321    /* *INDENT-EQLS* Keep the rest of the info. */
322    ScreenOf (matrix)            = cdkscreen;
323    ObjOf (matrix)->acceptsFocus = TRUE;
324    ObjOf (matrix)->inputWindow  = matrix->win;
325    matrix->parent               = cdkscreen->window;
326    matrix->vrows                = vrows;
327    matrix->vcols                = vcols;
328    matrix->boxWidth             = boxWidth;
329    matrix->boxHeight            = boxHeight;
330    matrix->rowSpace             = rowSpace;
331    matrix->colSpace             = colSpace;
332    matrix->filler               = filler;
333    matrix->dominant             = dominant;
334    matrix->row                  = 1;
335    matrix->col                  = 1;
336    matrix->crow                 = 1;
337    matrix->ccol                 = 1;
338    matrix->trow                 = 1;
339    matrix->lcol                 = 1;
340    matrix->oldcrow              = 1;
341    matrix->oldccol              = 1;
342    matrix->oldvrow              = 1;
343    matrix->oldvcol              = 1;
344    initExitType (matrix);
345    matrix->boxCell              = boxCell;
346    matrix->shadow               = shadow;
347    matrix->highlight            = A_REVERSE;
348    matrix->callbackfn           = CDKMatrixCallBack;
349 
350    /* Make room for the cell information. */
351    for (x = 1; x <= rows; x++)
352    {
353       for (y = 1; y <= cols; y++)
354       {
355 	 MATRIX_INFO (matrix, x, y) = typeCallocN (char, (colwidths[y] + 1));
356 	 matrix->colvalues[y] = colvalues[y];
357 	 matrix->colwidths[y] = colwidths[y];
358       }
359    }
360 
361    /* Do we want a shadow??? */
362    if (shadow)
363    {
364       matrix->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1);
365    }
366 
367    /* Setup the key bindings. */
368    for (x = 0; x < (int)SIZEOF (bindings); ++x)
369       bindCDKObject (vMATRIX, matrix,
370 		     (chtype)bindings[x].from,
371 		     getcCDKBind,
372 		     (void *)(long)bindings[x].to);
373 
374    /* Register this baby. */
375    registerCDKObject (cdkscreen, vMATRIX, matrix);
376 
377    /* Return the matrix pointer */
378    return (matrix);
379 }
380 
381 /*
382  * This activates the matrix.
383  */
activateCDKMatrix(CDKMATRIX * matrix,chtype * actions)384 int activateCDKMatrix (CDKMATRIX *matrix, chtype *actions)
385 {
386    int ret;
387 
388    /* Draw the matrix */
389    drawCDKMatrix (matrix, ObjOf (matrix)->box);
390 
391    if (actions == 0)
392    {
393       chtype input = 0;
394       boolean functionKey;
395 
396       for (;;)
397       {
398 	 ObjOf (matrix)->inputWindow = CurMatrixCell (matrix);
399 	 keypad (ObjOf (matrix)->inputWindow, TRUE);
400 	 input = (chtype)getchCDKObject (ObjOf (matrix), &functionKey);
401 
402 	 /* Inject the character into the widget. */
403 	 ret = injectCDKMatrix (matrix, input);
404 	 if (matrix->exitType != vEARLY_EXIT)
405 	 {
406 	    return ret;
407 	 }
408       }
409    }
410    else
411    {
412       int length = chlen (actions);
413       int x = 0;
414 
415       /* Inject each character one at a time. */
416       for (x = 0; x < length; x++)
417       {
418 	 ret = injectCDKMatrix (matrix, actions[x]);
419 	 if (matrix->exitType != vEARLY_EXIT)
420 	 {
421 	    return ret;
422 	 }
423       }
424    }
425 
426    /* Set the exit type and exit. */
427    setExitType (matrix, 0);
428    return -1;
429 }
430 
431 /*
432  * This injects a single character into the matrix widget.
433  */
_injectCDKMatrix(CDKOBJS * object,chtype input)434 static int _injectCDKMatrix (CDKOBJS *object, chtype input)
435 {
436    /* *INDENT-EQLS* */
437    CDKMATRIX *widget = (CDKMATRIX *)object;
438    int refreshCells  = FALSE;
439    int movedCell     = FALSE;
440    int charcount     = (int)strlen (MATRIX_INFO (widget, widget->row, widget->col));
441    int ppReturn      = 1;
442    int ret           = unknownInt;
443    bool complete     = FALSE;
444 
445    /* Set the exit type. */
446    setExitType (widget, 0);
447 
448    /* Move the cursor to the correct position within the cell. */
449    if (widget->colwidths[widget->ccol] == 1)
450    {
451       wmove (CurMatrixCell (widget), 1, 1);
452    }
453    else
454    {
455       wmove (CurMatrixCell (widget),
456 	     1,
457 	     (int)strlen (MATRIX_INFO (widget, widget->row, widget->col)) + 1);
458    }
459 
460    /* Put the focus on the current cell */
461    MyBox (CurMatrixCell (widget), WHOLE_BOX, A_BOLD);
462    wrefresh (CurMatrixCell (widget));
463    highlightCDKMatrixCell (widget);
464 
465    /* Check if there is a pre-process function to be called. */
466    if (PreProcessFuncOf (widget) != 0)
467    {
468       /* Call the pre-process function. */
469       ppReturn = PreProcessFuncOf (widget) (vMATRIX,
470 					    widget,
471 					    PreProcessDataOf (widget),
472 					    input);
473    }
474 
475    /* Should we continue? */
476    if (ppReturn != 0)
477    {
478       /* Check the key bindings. */
479       if (checkCDKObjectBind (vMATRIX, widget, input) != 0)
480       {
481 	 checkEarlyExit (widget);
482 	 complete = TRUE;
483       }
484       else
485       {
486 	 switch (input)
487 	 {
488 	 case CDK_TRANSPOSE:
489 	    break;
490 
491 	 case KEY_HOME:
492 	    break;
493 
494 	 case KEY_END:
495 	    break;
496 
497 	 case KEY_BACKSPACE:
498 	 case KEY_DC:
499 	    if (widget->colvalues[widget->col] == vVIEWONLY || charcount <= 0)
500 	    {
501 	       Beep ();
502 	    }
503 	    else
504 	    {
505 	       charcount--;
506 	       (void)mvwdelch (CurMatrixCell (widget), 1, charcount + 1);
507 	       (void)mvwinsch (CurMatrixCell (widget), 1, charcount + 1, widget->filler);
508 	       wrefresh (CurMatrixCell (widget));
509 	       MATRIX_INFO (widget, widget->row, widget->col)[charcount] = '\0';
510 	    }
511 	    break;
512 
513 	 case KEY_RIGHT:
514 	 case KEY_TAB:
515 	    if (widget->ccol != widget->vcols)
516 	    {
517 	       /* We are moving to the right... */
518 	       widget->col++;
519 	       widget->ccol++;
520 	       movedCell = TRUE;
521 	    }
522 	    else
523 	    {
524 	       /* We have to shift the columns to the right. */
525 	       if (widget->col != widget->cols)
526 	       {
527 		  widget->lcol++;
528 		  widget->col++;
529 
530 		  /* Redraw the column titles. */
531 		  if (widget->rows > widget->vrows)
532 		  {
533 		     redrawTitles (widget, FALSE, TRUE);
534 		  }
535 		  refreshCells = TRUE;
536 		  movedCell = TRUE;
537 	       }
538 	       else
539 	       {
540 		  /* We are at the far right column, we need  */
541 		  /* shift down one row, if we can. */
542 		  if (widget->row == widget->rows)
543 		  {
544 		     Beep ();
545 		  }
546 		  else
547 		  {
548 		     /* Set up the columns info. */
549 		     widget->col = 1;
550 		     widget->lcol = 1;
551 		     widget->ccol = 1;
552 
553 		     /* Shift the rows... */
554 		     if (widget->crow != widget->vrows)
555 		     {
556 			widget->row++;
557 			widget->crow++;
558 		     }
559 		     else
560 		     {
561 			widget->row++;
562 			widget->trow++;
563 		     }
564 		     redrawTitles (widget, TRUE, TRUE);
565 		     refreshCells = TRUE;
566 		     movedCell = TRUE;
567 		  }
568 	       }
569 	    }
570 	    break;
571 
572 	 case KEY_LEFT:
573 	 case KEY_BTAB:
574 	    if (widget->ccol != 1)
575 	    {
576 	       /* We are moving to the left... */
577 	       widget->col--;
578 	       widget->ccol--;
579 	       movedCell = TRUE;
580 	    }
581 	    else
582 	    {
583 	       /* Are we at the far left??? */
584 	       if (widget->lcol != 1)
585 	       {
586 		  widget->lcol--;
587 		  widget->col--;
588 
589 		  /* Redraw the column titles. */
590 		  if (widget->cols > widget->vcols)
591 		  {
592 		     redrawTitles (widget, FALSE, TRUE);
593 		  }
594 		  refreshCells = TRUE;
595 		  movedCell = TRUE;
596 	       }
597 	       else
598 	       {
599 		  /* Shift up one line if we can... */
600 		  if (widget->row == 1)
601 		  {
602 		     Beep ();
603 		  }
604 		  else
605 		  {
606 		     /* Set up the columns info. */
607 		     widget->col = widget->cols;
608 		     widget->lcol = widget->cols - widget->vcols + 1;
609 		     widget->ccol = widget->vcols;
610 
611 		     /* Shift the rows... */
612 		     if (widget->crow != 1)
613 		     {
614 			widget->row--;
615 			widget->crow--;
616 		     }
617 		     else
618 		     {
619 			widget->row--;
620 			widget->trow--;
621 		     }
622 		     redrawTitles (widget, TRUE, TRUE);
623 		     refreshCells = TRUE;
624 		     movedCell = TRUE;
625 		  }
626 	       }
627 	    }
628 	    break;
629 
630 	 case KEY_UP:
631 	    if (widget->crow != 1)
632 	    {
633 	       widget->row--;
634 	       widget->crow--;
635 	       movedCell = TRUE;
636 	    }
637 	    else
638 	    {
639 	       if (widget->trow != 1)
640 	       {
641 		  widget->trow--;
642 		  widget->row--;
643 
644 		  /* Redraw the row titles. */
645 		  if (widget->rows > widget->vrows)
646 		  {
647 		     redrawTitles (widget, TRUE, FALSE);
648 		  }
649 		  refreshCells = TRUE;
650 		  movedCell = TRUE;
651 	       }
652 	       else
653 	       {
654 		  Beep ();
655 	       }
656 	    }
657 	    break;
658 
659 	 case KEY_DOWN:
660 	    if (widget->crow != widget->vrows)
661 	    {
662 	       widget->row++;
663 	       widget->crow++;
664 	       movedCell = TRUE;
665 	    }
666 	    else
667 	    {
668 	       if ((widget->trow + widget->vrows - 1) != widget->rows)
669 	       {
670 		  widget->trow++;
671 		  widget->row++;
672 
673 		  /* Redraw the titles. */
674 		  if (widget->rows > widget->vrows)
675 		  {
676 		     redrawTitles (widget, TRUE, FALSE);
677 		  }
678 		  refreshCells = TRUE;
679 		  movedCell = TRUE;
680 	       }
681 	       else
682 	       {
683 		  Beep ();
684 	       }
685 	    }
686 	    break;
687 
688 	 case KEY_NPAGE:
689 	    if (widget->rows > widget->vrows)
690 	    {
691 	       if ((widget->trow + ((widget->vrows - 1) * 2)) <= widget->rows)
692 	       {
693 		  widget->trow += widget->vrows - 1;
694 		  widget->row += widget->vrows - 1;
695 		  redrawTitles (widget, TRUE, FALSE);
696 		  refreshCells = TRUE;
697 		  movedCell = TRUE;
698 	       }
699 	       else
700 	       {
701 		  Beep ();
702 	       }
703 	    }
704 	    else
705 	    {
706 	       Beep ();
707 	    }
708 	    break;
709 
710 	 case KEY_PPAGE:
711 	    if (widget->rows > widget->vrows)
712 	    {
713 	       if ((widget->trow - ((widget->vrows - 1) * 2)) >= 1)
714 	       {
715 		  widget->trow -= widget->vrows - 1;
716 		  widget->row -= widget->vrows - 1;
717 		  redrawTitles (widget, TRUE, FALSE);
718 		  refreshCells = TRUE;
719 		  movedCell = TRUE;
720 	       }
721 	       else
722 	       {
723 		  Beep ();
724 	       }
725 	    }
726 	    else
727 	    {
728 	       Beep ();
729 	    }
730 	    break;
731 
732 	 case CTRL ('G'):
733 	    jumpToCell (widget, -1, -1);
734 	    drawCDKMatrix (widget, ObjOf (widget)->box);
735 	    break;
736 
737 	 case CDK_PASTE:
738 	    if (GPasteBuffer == 0 ||
739 		(int)strlen (GPasteBuffer) > widget->colwidths[widget->ccol])
740 	    {
741 	       Beep ();
742 	    }
743 	    else
744 	    {
745 	       strcpy (CurMatrixInfo (widget), GPasteBuffer);
746 	       drawCurCDKMatrixCell (widget);
747 	    }
748 	    break;
749 
750 	 case CDK_COPY:
751 	    freeChar (GPasteBuffer);
752 	    GPasteBuffer = copyChar (CurMatrixInfo (widget));
753 	    break;
754 
755 	 case CDK_CUT:
756 	    freeChar (GPasteBuffer);
757 	    GPasteBuffer = copyChar (CurMatrixInfo (widget));
758 	    cleanCDKMatrixCell (widget,
759 				widget->trow + widget->crow - 1,
760 				widget->lcol + widget->ccol - 1);
761 	    drawCurCDKMatrixCell (widget);
762 	    break;
763 
764 	 case CDK_ERASE:
765 	    cleanCDKMatrixCell (widget,
766 				widget->trow + widget->crow - 1,
767 				widget->lcol + widget->ccol - 1);
768 	    drawCurCDKMatrixCell (widget);
769 	    break;
770 
771 	 case KEY_ENTER:
772 	    if (!widget->boxCell)
773 	    {
774 	       attrbox (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol),
775 			' ', ' ',
776 			' ', ' ',
777 			' ', ' ',
778 			A_NORMAL);
779 	    }
780 	    else
781 	    {
782 	       drawOldCDKMatrixCell (widget);
783 	    }
784 	    wrefresh (CurMatrixCell (widget));
785 	    setExitType (widget, input);
786 	    ret = 1;
787 	    complete = TRUE;
788 	    break;
789 
790 	 case KEY_ERROR:
791 	    setExitType (widget, input);
792 	    complete = TRUE;
793 	    break;
794 
795 	 case KEY_ESC:
796 	    if (!widget->boxCell)
797 	    {
798 	       attrbox (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol),
799 			' ', ' ',
800 			' ', ' ',
801 			' ', ' ',
802 			A_NORMAL);
803 	    }
804 	    else
805 	    {
806 	       drawOldCDKMatrixCell (widget);
807 	    }
808 	    wrefresh (CurMatrixCell (widget));
809 	    setExitType (widget, input);
810 	    complete = TRUE;
811 	    break;
812 
813 	 case CDK_REFRESH:
814 	    eraseCDKScreen (ScreenOf (widget));
815 	    refreshCDKScreen (ScreenOf (widget));
816 	    break;
817 
818 	 default:
819 	    (widget->callbackfn) (widget, input);
820 	    break;
821 	 }
822       }
823 
824       if (!complete)
825       {
826 	 /* Did we change cells? */
827 	 if (movedCell)
828 	 {
829 	    /* un-highlight the old box  */
830 	    if (!widget->boxCell)
831 	    {
832 	       attrbox (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol),
833 			' ', ' ',
834 			' ', ' ',
835 			' ', ' ',
836 			A_NORMAL);
837 	    }
838 	    else
839 	    {
840 	       drawOldCDKMatrixCell (widget);
841 	    }
842 	    wrefresh (MATRIX_CELL (widget, widget->oldcrow, widget->oldccol));
843 
844 	    /* Highlight the new cell. */
845 	    MyBox (CurMatrixCell (widget), WHOLE_BOX, A_BOLD);
846 	    wrefresh (CurMatrixCell (widget));
847 	    highlightCDKMatrixCell (widget);
848 	 }
849 
850 	 /* Redraw each cell. */
851 	 if (refreshCells)
852 	 {
853 	    drawEachCDKMatrixCell (widget);
854 
855 	    /* Highlight the current cell. */
856 	    MyBox (CurMatrixCell (widget), WHOLE_BOX, A_BOLD);
857 	    wrefresh (CurMatrixCell (widget));
858 	    highlightCDKMatrixCell (widget);
859 	 }
860 
861 	 /* Move to the correct position in the cell. */
862 	 if (refreshCells || movedCell)
863 	 {
864 	    if (widget->colwidths[widget->ccol] == 1)
865 	    {
866 	       wmove (CurMatrixCell (widget), 1, 1);
867 	    }
868 	    else
869 	    {
870 	       int infolen = (int)strlen (CurMatrixInfo (widget));
871 	       wmove (CurMatrixCell (widget), 1, infolen + 1);
872 	    }
873 	    wrefresh (CurMatrixCell (widget));
874 	 }
875 
876 	 /* Should we call a post-process? */
877 	 if (PostProcessFuncOf (widget) != 0)
878 	 {
879 	    PostProcessFuncOf (widget) (vMATRIX,
880 					widget,
881 					PostProcessDataOf (widget),
882 					input);
883 	 }
884       }
885    }
886 
887    if (!complete)
888    {
889       /* Set the variables we need. */
890       widget->oldcrow = widget->crow;
891       widget->oldccol = widget->ccol;
892       widget->oldvrow = widget->row;
893       widget->oldvcol = widget->col;
894 
895       /* Set the exit type and exit. */
896       setExitType (widget, 0);
897    }
898 
899    ResultOf (widget).valueInt = ret;
900    return (ret != unknownInt);
901 }
902 
903 /*
904  * This allows the programmer to define their own key mappings.
905  */
CDKMatrixCallBack(CDKMATRIX * matrix,chtype input)906 static void CDKMatrixCallBack (CDKMATRIX *matrix, chtype input)
907 {
908    EDisplayType disptype = (EDisplayType) matrix->colvalues[matrix->col];
909    int plainchar = filterByDisplayType (disptype, input);
910    int charcount = (int)strlen (MATRIX_INFO (matrix, matrix->row, matrix->col));
911 
912    if (plainchar == ERR)
913    {
914       Beep ();
915    }
916    else if (charcount == matrix->colwidths[matrix->col])
917    {
918       Beep ();
919    }
920    else
921    {
922       /* Update the screen. */
923       wmove (CurMatrixCell (matrix),
924 	     1,
925 	     (int)strlen (MATRIX_INFO (matrix, matrix->row, matrix->col)) + 1);
926       waddch (CurMatrixCell (matrix),
927 	      (chtype)((isHiddenDisplayType (disptype))
928 		       ? (int)matrix->filler
929 		       : plainchar));
930       wrefresh (CurMatrixCell (matrix));
931 
932       /* Update the character pointer. */
933       MATRIX_INFO (matrix, matrix->row, matrix->col)[charcount++] = (char)plainchar;
934       MATRIX_INFO (matrix, matrix->row, matrix->col)[charcount] = '\0';
935    }
936 }
937 
938 /*
939  * Highlight the new field.
940  */
highlightCDKMatrixCell(CDKMATRIX * matrix)941 static void highlightCDKMatrixCell (CDKMATRIX *matrix)
942 {
943    /* *INDENT-EQLS* */
944    EDisplayType disptype = (EDisplayType) matrix->colvalues[matrix->col];
945    chtype highlight      = matrix->highlight;
946    int x                 = 0;
947    int infolen           = (int)strlen (MATRIX_INFO (matrix, matrix->row, matrix->col));
948 
949    /*
950     * Given the dominance of the colors/attributes, we need to set the
951     * current cell attribute.
952     */
953    if (matrix->dominant == ROW)
954    {
955       highlight = matrix->rowtitle[matrix->crow][0] & A_ATTRIBUTES;
956    }
957    else if (matrix->dominant == COL)
958    {
959       highlight = matrix->coltitle[matrix->ccol][0] & A_ATTRIBUTES;
960    }
961 
962    /* If the column is only one char. */
963    for (x = 1; x <= matrix->colwidths[matrix->ccol]; x++)
964    {
965       chtype ch = (((x <= infolen) && !isHiddenDisplayType (disptype))
966 		   ? CharOf (MATRIX_INFO (matrix,
967 					  matrix->row,
968 					  matrix->col)[x - 1])
969 		   : matrix->filler);
970 
971       (void)mvwaddch (CurMatrixCell (matrix), 1, x, ch | highlight);
972    }
973    wmove (CurMatrixCell (matrix), 1, infolen + 1);
974    wrefresh (CurMatrixCell (matrix));
975 }
976 
977 /*
978  * This moves the matrix field to the given location.
979  */
_moveCDKMatrix(CDKOBJS * object,int xplace,int yplace,boolean relative,boolean refresh_flag)980 static void _moveCDKMatrix (CDKOBJS *object,
981 			    int xplace,
982 			    int yplace,
983 			    boolean relative,
984 			    boolean refresh_flag)
985 {
986    /* *INDENT-EQLS* */
987    CDKMATRIX *matrix = (CDKMATRIX *)object;
988    int currentX      = getbegx (matrix->win);
989    int currentY      = getbegy (matrix->win);
990    int xpos          = xplace;
991    int ypos          = yplace;
992    int xdiff         = 0;
993    int ydiff         = 0;
994    int x, y;
995 
996    /*
997     * If this is a relative move, then we will adjust where we want
998     * to move to.
999     */
1000    if (relative)
1001    {
1002       xpos = getbegx (matrix->win) + xplace;
1003       ypos = getbegy (matrix->win) + yplace;
1004    }
1005 
1006    /* Adjust the window if we need to. */
1007    alignxy (WindowOf (matrix), &xpos, &ypos, matrix->boxWidth, matrix->boxHeight);
1008 
1009    /* Get the difference. */
1010    xdiff = currentX - xpos;
1011    ydiff = currentY - ypos;
1012 
1013    /* Move the window to the new location. */
1014    moveCursesWindow (matrix->win, -xdiff, -ydiff);
1015 
1016    for (x = 0; x <= matrix->vrows; x++)
1017    {
1018       for (y = 0; y <= matrix->vcols; y++)
1019       {
1020 	 moveCursesWindow (MATRIX_CELL (matrix, x, y), -xdiff, -ydiff);
1021       }
1022    }
1023 
1024    moveCursesWindow (matrix->shadowWin, -xdiff, -ydiff);
1025 
1026    /* Touch the windows so they 'move'. */
1027    refreshCDKWindow (WindowOf (matrix));
1028 
1029    /* Redraw the window, if they asked for it. */
1030    if (refresh_flag)
1031    {
1032       drawCDKMatrix (matrix, ObjOf (matrix)->box);
1033    }
1034 }
1035 
1036 /*
1037  * This draws a cell within a matrix.
1038  */
drawCDKMatrixCell(CDKMATRIX * matrix,int row,int col,int vrow,int vcol,boolean Box)1039 static void drawCDKMatrixCell (CDKMATRIX *matrix,
1040 			       int row,
1041 			       int col,
1042 			       int vrow,
1043 			       int vcol,
1044 			       boolean Box)
1045 {
1046    /* *INDENT-EQLS* */
1047    WINDOW *cell         = MATRIX_CELL (matrix, row, col);
1048    EDisplayType disptype = (EDisplayType) matrix->colvalues[matrix->col];
1049    chtype highlight     = matrix->filler & A_ATTRIBUTES;
1050    int rows             = matrix->vrows;
1051    int cols             = matrix->vcols;
1052    int infolen          = (int)strlen (MATRIX_INFO (matrix, vrow, vcol));
1053    chtype attr          = A_NORMAL;
1054    int x;
1055 
1056    /*
1057     * Given the dominance of the colors/attributes, we need to set the
1058     * current cell attribute.
1059     */
1060    if (matrix->dominant == ROW)
1061    {
1062       highlight = matrix->rowtitle[row][0] & A_ATTRIBUTES;
1063    }
1064    else if (matrix->dominant == COL)
1065    {
1066       highlight = matrix->coltitle[col][0] & A_ATTRIBUTES;
1067    }
1068 
1069    /* Draw in the cell info. */
1070    for (x = 1; x <= matrix->colwidths[col]; x++)
1071    {
1072       chtype ch = (((x <= infolen) && !isHiddenDisplayType (disptype))
1073 		   ? (CharOf (MATRIX_INFO (matrix, vrow, vcol)[x - 1]) | highlight)
1074 		   : matrix->filler);
1075 
1076       (void)mvwaddch (cell, 1, x, ch | highlight);
1077    }
1078    wmove (cell, 1, infolen + 1);
1079    wrefresh (cell);
1080 
1081    /* Only draw the box iff the user asked for a box. */
1082    if (!Box)
1083    {
1084       return;
1085    }
1086 
1087    /*
1088     * If the value of the column spacing is greater than 0 then these
1089     * are independent boxes.
1090     */
1091    if (matrix->colSpace != 0)
1092    {
1093       if (matrix->rowSpace != 0)
1094       {
1095 	 MyBox (cell, WHOLE_BOX, attr);
1096       }
1097       else
1098       {
1099 	 if (row == 1)
1100 	 {
1101 	    MyBox (cell, TOP_C_BOX, attr);
1102 	 }
1103 	 else if (row > 1 && row < rows)
1104 	 {
1105 	    MyBox (cell, MID_C_BOX, attr);
1106 	 }
1107 	 else if (row == rows)
1108 	 {
1109 	    MyBox (cell, BOT_C_BOX, attr);
1110 	 }
1111       }
1112    }
1113    else if (matrix->rowSpace != 0)
1114    {
1115       if (col == 1)
1116       {
1117 	 MyBox (cell, LFT_R_BOX, attr);
1118       }
1119       else if (col > 1 && col < cols)
1120       {
1121 	 MyBox (cell, MID_R_BOX, attr);
1122       }
1123       else if (col == cols)
1124       {
1125 	 MyBox (cell, RGT_R_BOX, attr);
1126       }
1127    }
1128    else
1129    {
1130       if (row == 1)
1131       {
1132 	 if (col == 1)
1133 	 {
1134 	    MyBox (cell, LFT_T_BOX, attr);	/* top left corner */
1135 	 }
1136 	 else if (col > 1 && col < cols)
1137 	 {
1138 	    MyBox (cell, MID_T_BOX, attr);	/* top middle */
1139 	 }
1140 	 else if (col == cols)
1141 	 {
1142 	    MyBox (cell, RGT_T_BOX, attr);	/* top right corner */
1143 	 }
1144       }
1145       else if (row > 1 && row < rows)
1146       {
1147 	 if (col == 1)
1148 	 {
1149 	    MyBox (cell, LFT_M_BOX, attr);	/* middle left */
1150 	 }
1151 	 else if (col > 1 && col < cols)
1152 	 {
1153 	    MyBox (cell, MID_M_BOX, attr);	/* middle */
1154 	 }
1155 	 else if (col == cols)
1156 	 {
1157 	    MyBox (cell, RGT_M_BOX, attr);	/* middle right */
1158 	 }
1159       }
1160       else if (row == rows)
1161       {
1162 	 if (col == 1)
1163 	 {
1164 	    MyBox (cell, LFT_B_BOX, attr);	/* bottom left corner */
1165 	 }
1166 	 else if (col > 1 && col < cols)
1167 	 {
1168 	    MyBox (cell, MID_B_BOX, attr);	/* bottom middle */
1169 	 }
1170 	 else if (col == cols)
1171 	 {
1172 	    MyBox (cell, RGT_B_BOX, attr);	/* bottom right corner */
1173 	 }
1174       }
1175    }
1176 
1177    /* Highlight the current cell. */
1178    MyBox (CurMatrixCell (matrix), WHOLE_BOX, A_BOLD);
1179    wrefresh (CurMatrixCell (matrix));
1180    highlightCDKMatrixCell (matrix);
1181 }
1182 
drawEachColTitle(CDKMATRIX * matrix)1183 static void drawEachColTitle (CDKMATRIX *matrix)
1184 {
1185    int x;
1186 
1187    for (x = 1; x <= matrix->vcols; x++)
1188    {
1189       if (MATRIX_CELL (matrix, 0, x))
1190       {
1191 	 werase (MATRIX_CELL (matrix, 0, x));	/*VR */
1192 	 writeChtype (MATRIX_CELL (matrix, 0, x),
1193 		      matrix->coltitlePos[matrix->lcol + x - 1], 0,
1194 		      matrix->coltitle[matrix->lcol + x - 1],
1195 		      HORIZONTAL,
1196 		      0, matrix->coltitleLen[matrix->lcol + x - 1]);
1197 	 wrefresh (MATRIX_CELL (matrix, 0, x));
1198       }
1199    }
1200 }
1201 
drawEachRowTitle(CDKMATRIX * matrix)1202 static void drawEachRowTitle (CDKMATRIX *matrix)
1203 {
1204    int x;
1205 
1206    for (x = 1; x <= matrix->vrows; x++)
1207    {
1208       if (MATRIX_CELL (matrix, x, 0))
1209       {
1210 	 werase (MATRIX_CELL (matrix, x, 0));
1211 	 writeChtype (MATRIX_CELL (matrix, x, 0),
1212 		      matrix->rowtitlePos[matrix->trow + x - 1], 1,
1213 		      matrix->rowtitle[matrix->trow + x - 1],
1214 		      HORIZONTAL,
1215 		      0, matrix->rowtitleLen[matrix->trow + x - 1]);
1216 	 wrefresh (MATRIX_CELL (matrix, x, 0));
1217       }
1218    }
1219 }
1220 
drawEachCDKMatrixCell(CDKMATRIX * matrix)1221 static void drawEachCDKMatrixCell (CDKMATRIX *matrix)
1222 {
1223    int y, x;
1224 
1225    /* Fill in the cells. */
1226    for (x = 1; x <= matrix->vrows; x++)
1227    {
1228       for (y = 1; y <= matrix->vcols; y++)
1229       {
1230 	 drawCDKMatrixCell (matrix, x, y,
1231 			    matrix->trow + x - 1,
1232 			    matrix->lcol + y - 1,
1233 			    matrix->boxCell);
1234       }
1235    }
1236 }
1237 
drawCurCDKMatrixCell(CDKMATRIX * matrix)1238 static void drawCurCDKMatrixCell (CDKMATRIX *matrix)
1239 {
1240    drawCDKMatrixCell (matrix,
1241 		      matrix->crow,
1242 		      matrix->ccol,
1243 		      matrix->row,
1244 		      matrix->col,
1245 		      matrix->boxCell);
1246 }
1247 
drawOldCDKMatrixCell(CDKMATRIX * matrix)1248 static void drawOldCDKMatrixCell (CDKMATRIX *matrix)
1249 {
1250    drawCDKMatrixCell (matrix,
1251 		      matrix->oldcrow,
1252 		      matrix->oldccol,
1253 		      matrix->oldvrow,
1254 		      matrix->oldvcol,
1255 		      matrix->boxCell);
1256 }
1257 
1258 /*
1259  * This function draws the matrix widget.
1260  */
_drawCDKMatrix(CDKOBJS * object,boolean Box)1261 static void _drawCDKMatrix (CDKOBJS *object, boolean Box)
1262 {
1263    CDKMATRIX *matrix = (CDKMATRIX *)object;
1264 
1265    /* Did we ask for a shadow??? */
1266    if (matrix->shadowWin != 0)
1267    {
1268       drawShadow (matrix->shadowWin);
1269    }
1270 
1271    /* Should we box the matrix??? */
1272    if (Box)
1273    {
1274       drawObjBox (matrix->win, ObjOf (matrix));
1275    }
1276 
1277    drawCdkTitle (matrix->win, object);
1278 
1279    wrefresh (matrix->win);
1280 
1281    drawEachColTitle (matrix);
1282    drawEachRowTitle (matrix);
1283    drawEachCDKMatrixCell (matrix);
1284 
1285    /* Highlight the current cell. */
1286    MyBox (CurMatrixCell (matrix), WHOLE_BOX, A_BOLD);
1287    wrefresh (CurMatrixCell (matrix));
1288    highlightCDKMatrixCell (matrix);
1289 }
1290 
1291 /*
1292  * This function destroys the matrix widget.
1293  */
_destroyCDKMatrix(CDKOBJS * object)1294 static void _destroyCDKMatrix (CDKOBJS *object)
1295 {
1296    if (object != 0)
1297    {
1298       CDKMATRIX *matrix = (CDKMATRIX *)object;
1299       int x = 0;
1300       int y = 0;
1301 
1302       cleanCdkTitle (object);
1303 
1304       /* Clear out the col titles. */
1305       for (x = 1; x <= matrix->cols; x++)
1306       {
1307 	 freeChtype (matrix->coltitle[x]);
1308       }
1309 
1310       /* Clear out the row titles. */
1311       for (x = 1; x <= matrix->rows; x++)
1312       {
1313 	 freeChtype (matrix->rowtitle[x]);
1314       }
1315 
1316       /* Clear out the matrix cells. */
1317       for (x = 1; x <= matrix->rows; x++)
1318       {
1319 	 for (y = 1; y <= matrix->cols; y++)
1320 	 {
1321 	    freeChar (MATRIX_INFO (matrix, x, y));
1322 	 }
1323       }
1324 
1325       /* Clear the matrix windows. */
1326       deleteCursesWindow (MATRIX_CELL (matrix, 0, 0));
1327       for (x = 1; x <= matrix->vrows; x++)
1328       {
1329 	 deleteCursesWindow (MATRIX_CELL (matrix, x, 0));
1330       }
1331       for (x = 1; x <= matrix->vcols; x++)
1332       {
1333 	 deleteCursesWindow (MATRIX_CELL (matrix, 0, x));
1334       }
1335       for (x = 1; x <= matrix->vrows; x++)
1336       {
1337 	 for (y = 1; y <= matrix->vcols; y++)
1338 	 {
1339 	    deleteCursesWindow (MATRIX_CELL (matrix, x, y));
1340 	 }
1341       }
1342 
1343 #if NEW_CDKMATRIX
1344       freeChecked (matrix->cell);
1345       freeChecked (matrix->info);
1346 #endif
1347 
1348       freeChecked (matrix->colwidths);
1349       freeChecked (matrix->colvalues);
1350 
1351       freeChecked (matrix->coltitle);
1352       freeChecked (matrix->coltitleLen);
1353       freeChecked (matrix->coltitlePos);
1354 
1355       freeChecked (matrix->rowtitle);
1356       freeChecked (matrix->rowtitleLen);
1357       freeChecked (matrix->rowtitlePos);
1358 
1359       deleteCursesWindow (matrix->shadowWin);
1360       deleteCursesWindow (matrix->win);
1361 
1362       /* Clean the key bindings. */
1363       cleanCDKObjectBindings (vMATRIX, matrix);
1364 
1365       /* Unregister this object. */
1366       unregisterCDKObject (vMATRIX, matrix);
1367    }
1368 }
1369 
1370 /*
1371  * This function erases the matrix widget from the screen.
1372  */
_eraseCDKMatrix(CDKOBJS * object)1373 static void _eraseCDKMatrix (CDKOBJS *object)
1374 {
1375    if (validCDKObject (object))
1376    {
1377       CDKMATRIX *matrix = (CDKMATRIX *)object;
1378       int x = 0;
1379       int y = 0;
1380 
1381       /* Clear the matrix cells. */
1382       eraseCursesWindow (MATRIX_CELL (matrix, 0, 0));
1383       for (x = 1; x <= matrix->vrows; x++)
1384       {
1385 	 eraseCursesWindow (MATRIX_CELL (matrix, x, 0));
1386       }
1387       for (x = 1; x <= matrix->vcols; x++)
1388       {
1389 	 eraseCursesWindow (MATRIX_CELL (matrix, 0, x));
1390       }
1391       for (x = 1; x <= matrix->vrows; x++)
1392       {
1393 	 for (y = 1; y <= matrix->vcols; y++)
1394 	 {
1395 	    eraseCursesWindow (MATRIX_CELL (matrix, x, y));
1396 	 }
1397       }
1398       eraseCursesWindow (matrix->shadowWin);
1399       eraseCursesWindow (matrix->win);
1400    }
1401 }
1402 
1403 /*
1404  * Set the callback-function.
1405  */
setCDKMatrixCB(CDKMATRIX * widget,MATRIXCB callback)1406 void setCDKMatrixCB (CDKMATRIX *widget, MATRIXCB callback)
1407 {
1408    widget->callbackfn = callback;
1409 }
1410 
1411 /*
1412  * This function sets the values of the matrix widget.
1413  */
setCDKMatrixCells(CDKMATRIX * matrix,CDK_CSTRING2 info,int rows,int maxcols,int * subSize)1414 void setCDKMatrixCells (CDKMATRIX *matrix,
1415 			CDK_CSTRING2 info,
1416 			int rows,
1417 			int maxcols,
1418 			int *subSize)
1419 {
1420    int x = 0;
1421    int y = 0;
1422 
1423    if (rows > matrix->rows)
1424       rows = matrix->rows;
1425 
1426    /* Copy in the new info. */
1427    for (x = 1; x <= rows; x++)
1428    {
1429       for (y = 1; y <= matrix->cols; y++)
1430       {
1431 	 if (x <= rows && y <= subSize[x])
1432 	 {
1433 	    const char *source = info[(x * maxcols) + y];
1434 
1435 	    /* Copy in the new information. */
1436 	    if (source != 0)
1437 	    {
1438 	       char *target = MATRIX_INFO (matrix, x, y);
1439 
1440 	       if (target == 0)	/* this should not happen... */
1441 	       {
1442 		  target = typeCallocN (char, matrix->colwidths[y] + 1);
1443 		  MATRIX_INFO (matrix, x, y) = target;
1444 	       }
1445 	       strncpy (MATRIX_INFO (matrix, x, y),
1446 			source,
1447 			(size_t) matrix->colwidths[y]);
1448 	    }
1449 	 }
1450 	 else
1451 	    cleanCDKMatrixCell (matrix, x, y);
1452       }
1453    }
1454 }
1455 
1456 /*
1457  * This sets the widget's box attribute.
1458  */
setCDKMatrixBox(CDKMATRIX * matrix,boolean Box)1459 void setCDKMatrixBox (CDKMATRIX *matrix, boolean Box)
1460 {
1461    ObjOf (matrix)->box = Box;
1462    ObjOf (matrix)->borderSize = Box ? 1 : 0;
1463 }
getCDKMatrixBox(CDKMATRIX * matrix)1464 boolean getCDKMatrixBox (CDKMATRIX *matrix)
1465 {
1466    return ObjOf (matrix)->box;
1467 }
1468 
1469 /*
1470  * This cleans out the information cells in the matrix widget.
1471  */
cleanCDKMatrix(CDKMATRIX * matrix)1472 void cleanCDKMatrix (CDKMATRIX *matrix)
1473 {
1474    int x = 0;
1475    int y = 0;
1476 
1477    for (x = 1; x <= matrix->rows; x++)
1478    {
1479       for (y = 1; y <= matrix->cols; y++)
1480       {
1481 	 cleanCDKMatrixCell (matrix, x, y);
1482       }
1483    }
1484 }
1485 
1486 /*
1487  * This cleans one cell in the matrix widget.
1488  */
cleanCDKMatrixCell(CDKMATRIX * matrix,int row,int col)1489 void cleanCDKMatrixCell (CDKMATRIX *matrix, int row, int col)
1490 {
1491    if (row > 0 && row <= matrix->rows &&
1492        col > 0 && col <= matrix->cols)
1493       cleanChar (MATRIX_INFO (matrix, row, col), matrix->colwidths[col], '\0');
1494 }
1495 
1496 /*
1497  * This allows us to hyper-warp to a cell.
1498  */
jumpToCell(CDKMATRIX * matrix,int row,int col)1499 int jumpToCell (CDKMATRIX *matrix, int row, int col)
1500 {
1501    CDKSCALE *scale = 0;
1502    int newRow = row;
1503    int newCol = col;
1504 
1505    /*
1506     * Only create the row scale if needed.
1507     */
1508    if ((row == -1) || (row > matrix->rows))
1509    {
1510       /* Create the row scale widget. */
1511       scale = newCDKScale (ScreenOf (matrix),
1512 			   CENTER, CENTER,
1513 			   "<C>Jump to which row.",
1514 			   "</5/B>Row: ", A_NORMAL, 5,
1515 			   1, 1, matrix->rows, 1, 1, TRUE, FALSE);
1516 
1517       /* Activate the scale and get the row. */
1518       newRow = activateCDKScale (scale, 0);
1519       destroyCDKScale (scale);
1520    }
1521 
1522    /*
1523     * Only create the column scale if needed.
1524     */
1525    if ((col == -1) || (col > matrix->cols))
1526    {
1527       /* Create the column scale widget. */
1528       scale = newCDKScale (ScreenOf (matrix),
1529 			   CENTER, CENTER,
1530 			   "<C>Jump to which column",
1531 			   "</5/B>Col: ", A_NORMAL, 5,
1532 			   1, 1, matrix->cols, 1, 1, TRUE, FALSE);
1533 
1534       /* Activate the scale and get the column. */
1535       newCol = activateCDKScale (scale, 0);
1536       destroyCDKScale (scale);
1537    }
1538 
1539    /* Hyper-warp.... */
1540    if (newRow != matrix->row || newCol != matrix->col)
1541    {
1542       return (moveToCDKMatrixCell (matrix, newRow, newCol));
1543    }
1544    else
1545    {
1546       return 1;
1547    }
1548 }
1549 
1550 /*
1551  * This allows us to move to a given cell.
1552  */
moveToCDKMatrixCell(CDKMATRIX * matrix,int newrow,int newcol)1553 int moveToCDKMatrixCell (CDKMATRIX *matrix, int newrow, int newcol)
1554 {
1555    int rowShift = newrow - matrix->row;
1556    int colShift = newcol - matrix->col;
1557 
1558    /* Make sure we arent asking to move out of the matrix. */
1559    if (newrow > matrix->rows ||
1560        newcol > matrix->cols ||
1561        newrow <= 0 ||
1562        newcol <= 0)
1563    {
1564       return 0;
1565    }
1566 
1567    /* Did we move up/down???? */
1568    if (rowShift > 0)
1569    {
1570       /* We are moving down. */
1571       if (matrix->vrows == matrix->cols)
1572       {
1573 	 matrix->trow = 1;
1574 	 matrix->crow = newrow;
1575 	 matrix->row = newrow;
1576       }
1577       else
1578       {
1579 	 if ((rowShift + matrix->vrows) < matrix->rows)
1580 	 {
1581 	    /* Just shift down by rowShift... */
1582 	    matrix->trow += rowShift;
1583 	    matrix->crow = 1;
1584 	    matrix->row += rowShift;
1585 	 }
1586 	 else
1587 	 {
1588 	    /* We need to munge with the values... */
1589 	    matrix->trow = matrix->rows - matrix->vrows + 1;
1590 	    matrix->crow = ((rowShift + matrix->vrows) - matrix->rows) + 1;
1591 	    matrix->row = newrow;
1592 	 }
1593       }
1594    }
1595    else if (rowShift < 0)
1596    {
1597       /* We are moving up. */
1598       if (matrix->vrows == matrix->rows)
1599       {
1600 	 matrix->trow = 1;
1601 	 matrix->row = newrow;
1602 	 matrix->crow = newrow;
1603       }
1604       else
1605       {
1606 	 if ((rowShift + matrix->vrows) > 1)
1607 	 {
1608 	    /* Just shift up by rowShift... */
1609 	    matrix->trow += rowShift;
1610 	    matrix->row += rowShift;
1611 	    matrix->crow = 1;
1612 	 }
1613 	 else
1614 	 {
1615 	    /* We need to munge with the values... */
1616 	    matrix->trow = 1;
1617 	    matrix->crow = 1;
1618 	    matrix->row = 1;
1619 	 }
1620       }
1621    }
1622 
1623    /* Did we move left/right ???? */
1624    if (colShift > 0)
1625    {
1626       /* We are moving right. */
1627       if (matrix->vcols == matrix->cols)
1628       {
1629 	 matrix->lcol = 1;
1630 	 matrix->ccol = newcol;
1631 	 matrix->col = newcol;
1632       }
1633       else
1634       {
1635 	 if ((colShift + matrix->vcols) < matrix->cols)
1636 	 {
1637 	    matrix->lcol += colShift;
1638 	    matrix->ccol = 1;
1639 	    matrix->col += colShift;
1640 	 }
1641 	 else
1642 	 {
1643 	    /* We need to munge with the values... */
1644 	    matrix->lcol = matrix->cols - matrix->vcols + 1;
1645 	    matrix->ccol = ((colShift + matrix->vcols) - matrix->cols) + 1;
1646 	    matrix->col = newcol;
1647 	 }
1648       }
1649    }
1650    else if (colShift < 0)
1651    {
1652       /* We are moving left. */
1653       if (matrix->vcols == matrix->cols)
1654       {
1655 	 matrix->lcol = 1;
1656 	 matrix->col = newcol;
1657 	 matrix->ccol = newcol;
1658       }
1659       else
1660       {
1661 	 if ((colShift + matrix->vcols) > 1)
1662 	 {
1663 	    /* Just shift left by colShift... */
1664 	    matrix->lcol += colShift;
1665 	    matrix->col += colShift;
1666 	    matrix->ccol = 1;
1667 	 }
1668 	 else
1669 	 {
1670 	    matrix->lcol = 1;
1671 	    matrix->col = 1;
1672 	    matrix->ccol = 1;
1673 	 }
1674       }
1675    }
1676 
1677    /* Keep the 'old' values around for redrawing sake. */
1678    matrix->oldcrow = matrix->crow;
1679    matrix->oldccol = matrix->ccol;
1680    matrix->oldvrow = matrix->row;
1681    matrix->oldvcol = matrix->col;
1682 
1683    /* Lets ... */
1684    return 1;
1685 }
1686 
1687 /*
1688  * This redraws the titles indicated...
1689  */
redrawTitles(CDKMATRIX * matrix,int rowTitles,int colTitles)1690 static void redrawTitles (CDKMATRIX *matrix, int rowTitles, int colTitles)
1691 {
1692    /* Redraw the row titles. */
1693    if (rowTitles)
1694    {
1695       drawEachRowTitle (matrix);
1696    }
1697 
1698    /* Redraw the column titles. */
1699    if (colTitles)
1700    {
1701       drawEachColTitle (matrix);
1702    }
1703 }
1704 
1705 /*
1706  * This sets the value of a matrix cell.
1707  */
setCDKMatrixCell(CDKMATRIX * matrix,int row,int col,const char * value)1708 int setCDKMatrixCell (CDKMATRIX *matrix, int row, int col, const char *value)
1709 {
1710    /* Make sure the row/col combination is within the matrix. */
1711    if (row > matrix->rows || col > matrix->cols || row <= 0 || col <= 0)
1712    {
1713       return -1;
1714    }
1715 
1716    cleanCDKMatrixCell (matrix, row, col);
1717    strncpy (MATRIX_INFO (matrix, row, col),
1718 	    value,
1719 	    (size_t) matrix->colwidths[col]);
1720    return 1;
1721 }
1722 
1723 /*
1724  * This gets the value of a matrix cell.
1725  */
getCDKMatrixCell(CDKMATRIX * matrix,int row,int col)1726 char *getCDKMatrixCell (CDKMATRIX *matrix, int row, int col)
1727 {
1728    /* Make sure the row/col combination is within the matrix. */
1729    if (row > matrix->rows || col > matrix->cols || row <= 0 || col <= 0)
1730    {
1731       return 0;
1732    }
1733    return MATRIX_INFO (matrix, row, col);
1734 }
1735 
1736 /*
1737  * This returns the current row/col cell.
1738  */
getCDKMatrixCol(CDKMATRIX * matrix)1739 int getCDKMatrixCol (CDKMATRIX *matrix)
1740 {
1741    return matrix->col;
1742 }
getCDKMatrixRow(CDKMATRIX * matrix)1743 int getCDKMatrixRow (CDKMATRIX *matrix)
1744 {
1745    return matrix->row;
1746 }
1747 
1748 /*
1749  * This sets the background attribute of the widget.
1750  */
_setBKattrMatrix(CDKOBJS * object,chtype attrib)1751 static void _setBKattrMatrix (CDKOBJS *object, chtype attrib)
1752 {
1753    if (object != 0)
1754    {
1755       CDKMATRIX *widget = (CDKMATRIX *)object;
1756       int x, y;
1757 
1758       wbkgd (widget->win, attrib);
1759       for (x = 0; x <= widget->vrows; x++)
1760       {
1761 	 for (y = 0; y <= widget->vcols; y++)
1762 	 {
1763 	    wbkgd (MATRIX_CELL (widget, x, y), attrib);
1764 	 }
1765       }
1766    }
1767 }
1768 
_focusCDKMatrix(CDKOBJS * object)1769 static void _focusCDKMatrix (CDKOBJS *object)
1770 {
1771    CDKMATRIX *widget = (CDKMATRIX *)object;
1772 
1773    drawCDKMatrix (widget, ObjOf (widget)->box);
1774 }
1775 
_unfocusCDKMatrix(CDKOBJS * object)1776 static void _unfocusCDKMatrix (CDKOBJS *object)
1777 {
1778    CDKMATRIX *widget = (CDKMATRIX *)object;
1779 
1780    drawCDKMatrix (widget, ObjOf (widget)->box);
1781 }
1782 
1783 dummyRefreshData (Matrix)
1784 
1785 dummySaveData (Matrix)
1786