summaryrefslogtreecommitdiff
path: root/iup/srccontrols/matrix
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-11-04 11:56:41 -0800
committerPixel <pixel@nobis-crew.org>2009-11-04 11:59:33 -0800
commitd577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch)
tree590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /iup/srccontrols/matrix
Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux.
Diffstat (limited to 'iup/srccontrols/matrix')
-rwxr-xr-xiup/srccontrols/matrix/iupmat_aux.c480
-rwxr-xr-xiup/srccontrols/matrix/iupmat_aux.h37
-rwxr-xr-xiup/srccontrols/matrix/iupmat_cd.h25
-rwxr-xr-xiup/srccontrols/matrix/iupmat_colres.c182
-rwxr-xr-xiup/srccontrols/matrix/iupmat_colres.h24
-rwxr-xr-xiup/srccontrols/matrix/iupmat_def.h122
-rwxr-xr-xiup/srccontrols/matrix/iupmat_draw.c866
-rwxr-xr-xiup/srccontrols/matrix/iupmat_draw.h31
-rwxr-xr-xiup/srccontrols/matrix/iupmat_edit.c450
-rwxr-xr-xiup/srccontrols/matrix/iupmat_edit.h26
-rwxr-xr-xiup/srccontrols/matrix/iupmat_focus.c58
-rwxr-xr-xiup/srccontrols/matrix/iupmat_focus.h21
-rwxr-xr-xiup/srccontrols/matrix/iupmat_getset.c358
-rwxr-xr-xiup/srccontrols/matrix/iupmat_getset.h37
-rwxr-xr-xiup/srccontrols/matrix/iupmat_key.c229
-rwxr-xr-xiup/srccontrols/matrix/iupmat_key.h23
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mark.c720
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mark.h42
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mem.c319
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mem.h24
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mouse.c212
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mouse.h22
-rwxr-xr-xiup/srccontrols/matrix/iupmat_numlc.c495
-rwxr-xr-xiup/srccontrols/matrix/iupmat_numlc.h27
-rwxr-xr-xiup/srccontrols/matrix/iupmat_scroll.c495
-rwxr-xr-xiup/srccontrols/matrix/iupmat_scroll.h69
-rwxr-xr-xiup/srccontrols/matrix/iupmatrix.c980
27 files changed, 6374 insertions, 0 deletions
diff --git a/iup/srccontrols/matrix/iupmat_aux.c b/iup/srccontrols/matrix/iupmat_aux.c
new file mode 100755
index 0000000..f8b85bb
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_aux.c
@@ -0,0 +1,480 @@
+/** \file
+ * \brief iupmatrix control
+ * auxiliary functions
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_aux.h"
+#include "iupmat_getset.h"
+
+
+static int iMatrixAuxIsFullVisibleLast(Ihandle* ih, int m)
+{
+ int i, sum = 0;
+ ImatLinColData *p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ for(i = p->first; i <= p->last; i++)
+ sum += p->sizes[i];
+
+ if (sum > p->visible_size)
+ return 0;
+ else
+ return 1;
+}
+
+int iupMatrixAuxIsCellFullVisible(Ihandle* ih, int lin, int col)
+{
+ if(((lin >= ih->data->lines.first) &&
+ (lin <= ih->data->lines.last) &&
+ (col >= ih->data->columns.first) &&
+ (col <= ih->data->columns.last)))
+ {
+ if (col == ih->data->columns.last && !iMatrixAuxIsFullVisibleLast(ih, IMAT_PROCESS_COL))
+ return 0;
+ if (lin == ih->data->lines.last && !iMatrixAuxIsFullVisibleLast(ih, IMAT_PROCESS_LIN))
+ return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int iupMatrixAuxIsCellVisible(Ihandle* ih, int lin, int col)
+{
+ if(((lin >= ih->data->lines.first) &&
+ (lin <= ih->data->lines.last) &&
+ (col >= ih->data->columns.first) &&
+ (col <= ih->data->columns.last)))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+void iupMatrixAuxGetVisibleCellDim(Ihandle* ih, int lin, int col, int* x, int* y, int* w, int* h)
+{
+ int i;
+
+ /* find the position where the column starts */
+ *x = ih->data->columns.sizes[0];
+ for(i = ih->data->columns.first; i < col; i++)
+ *x += ih->data->columns.sizes[i];
+
+ /* find the column size */
+ *w = ih->data->columns.sizes[col] - 1;
+
+ /* find the position where the line starts */
+ *y = ih->data->lines.sizes[0];
+ for(i = ih->data->lines.first; i < lin; i++)
+ *y += ih->data->lines.sizes[i];
+
+ /* find the line size */
+ *h = ih->data->lines.sizes[lin] - 1;
+}
+
+/* Calculate the size, in pixels, of the invisible columns/lines,
+ the left/above of the first column/line.
+ In fact the start position of the visible area.
+ Depends on the first visible column/line.
+ -> m : choose will operate on lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixAuxUpdateVisiblePos(Ihandle* ih, int m)
+{
+ char* POS;
+ int i, sb, visible_pos;
+ ImatLinColData *p;
+
+ if (m == IMAT_PROCESS_LIN)
+ {
+ p = &(ih->data->lines);
+ sb = IUP_SB_VERT;
+ POS = "POSY";
+ }
+ else
+ {
+ p = &(ih->data->columns);
+ sb = IUP_SB_HORIZ;
+ POS = "POSX";
+ }
+
+ visible_pos = 0;
+ for(i = 1; i < p->first; i++)
+ visible_pos += p->sizes[i];
+
+ if (ih->data->canvas.sb & sb)
+ {
+ float pos;
+
+ if (p->total_size)
+ {
+ while ((visible_pos + p->visible_size > p->total_size) && p->first>1)
+ {
+ /* invalid position, must recalculate first */
+ p->first--;
+ visible_pos -= p->sizes[p->first];
+ }
+
+ pos = (float)visible_pos/(float)p->total_size;
+ }
+ else
+ pos = 0;
+
+ iupMatrixAuxUpdateLast(p);
+ IupSetfAttribute(ih, POS, "%.5f", (double)pos);
+ }
+ else
+ iupMatrixAuxUpdateLast(p);
+}
+
+/* Calculate which is the last visible column/line of the matrix.
+ Depends on the first visible column/line. */
+void iupMatrixAuxUpdateLast(ImatLinColData *p)
+{
+ int i, sum = 0;
+
+ if (p->visible_size > 0)
+ {
+ /* Find which is the last column/line
+ Start in the first visible and continue adding the widths
+ up to the visible size */
+ for(i = p->first; i < p->num; i++)
+ {
+ sum += p->sizes[i];
+ if(sum >= p->visible_size)
+ break;
+ }
+
+ if (i == p->num)
+ p->last = i-1;
+ else
+ p->last = i;
+ }
+ else
+ {
+ /* There is no space for any column, set the last column as 0 */
+ p->last = 0;
+ }
+}
+
+int iupMatrixAuxGetColumnWidth(Ihandle* ih, int col)
+{
+ int width = 0, pixels = 0;
+ char* str = iupStrGetMemory(100);
+ char* value;
+
+ /* can only be called for valid columns */
+
+ sprintf(str, "WIDTH%d", col);
+ value = iupAttribGet(ih, str);
+ if (!value)
+ {
+ sprintf(str, "RASTERWIDTH%d", col);
+ value = iupAttribGet(ih, str);
+ if (value)
+ pixels = 1;
+ }
+
+ if (!value)
+ {
+ /* Use the titles to define the size */
+ if (col == 0)
+ {
+ if (!ih->data->callback_mode || ih->data->use_title_size)
+ {
+ /* find the largest title */
+ int lin, max_width = 0;
+ for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, lin, 0);
+ if (title_value)
+ {
+ iupdrvFontGetMultiLineStringSize(ih, title_value, &width, NULL);
+ if (width > max_width)
+ max_width = width;
+ }
+ }
+ width = max_width;
+ }
+ }
+ else if (ih->data->use_title_size)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, 0, col);
+ if (title_value)
+ iupdrvFontGetMultiLineStringSize(ih, title_value, &width, NULL);
+ }
+ if (width)
+ return width + IMAT_PADDING_W + IMAT_FRAME_W;
+
+ if (col != 0)
+ value = iupAttribGetStr(ih, "WIDTHDEF");
+ }
+
+ if (iupStrToInt(value, &width))
+ {
+ if (width <= 0)
+ return 0;
+ else
+ {
+ if (pixels)
+ return width + IMAT_PADDING_W + IMAT_FRAME_W;
+ else
+ {
+ int charwidth;
+ iupdrvFontGetCharSize(ih, &charwidth, NULL);
+ return iupWIDTH2RASTER(width, charwidth) + IMAT_PADDING_W + IMAT_FRAME_W;
+ }
+ }
+ }
+ return 0;
+}
+
+int iupMatrixAuxGetLineHeight(Ihandle* ih, int lin)
+{
+ int height = 0, pixels = 0;
+ char* str = iupStrGetMemory(100);
+ char* value;
+
+ /* can only be called for valid lines */
+
+ sprintf(str, "HEIGHT%d", lin);
+ value = iupAttribGet(ih, str);
+ if(!value)
+ {
+ sprintf(str, "RASTERHEIGHT%d", lin);
+ value = iupAttribGet(ih, str);
+ if(value)
+ pixels = 1;
+ }
+
+ if (!value)
+ {
+ /* Use the titles to define the size */
+ if (lin == 0)
+ {
+ if (!ih->data->callback_mode || ih->data->use_title_size)
+ {
+ /* find the highest title */
+ int col, max_height = 0;
+ for(col = 0; col < ih->data->columns.num; col++)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, 0, col);
+ if (title_value && title_value[0])
+ {
+ iupdrvFontGetMultiLineStringSize(ih, title_value, NULL, &height);
+ if (height > max_height)
+ max_height = height;
+ }
+ }
+ height = max_height;
+ }
+ }
+ else if (ih->data->use_title_size)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, lin, 0);
+ if (title_value && title_value[0])
+ iupdrvFontGetMultiLineStringSize(ih, title_value, NULL, &height);
+ }
+ if (height)
+ return height + IMAT_PADDING_H + IMAT_FRAME_H;
+
+ if (lin != 0)
+ value = iupAttribGetStr(ih, "HEIGHTDEF");
+ }
+
+ if (iupStrToInt(value, &height))
+ {
+ if (height <= 0)
+ return 0;
+ else
+ {
+ if (pixels)
+ return height + IMAT_PADDING_H + IMAT_FRAME_H;
+ else
+ {
+ int charheight;
+ iupdrvFontGetCharSize(ih, NULL, &charheight);
+ return iupHEIGHT2RASTER(height, charheight) + IMAT_PADDING_H + IMAT_FRAME_H;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Fill the sizes vector with the width/heigh of all the columns/lines.
+ Calculate the value of total_size */
+static void iMatrixAuxFillSizeVec(Ihandle* ih, int m)
+{
+ int i;
+ ImatLinColData *p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ /* Calculate total width/height of the matrix and the width/height of each column */
+ p->total_size = 0;
+ for(i = 0; i < p->num; i++)
+ {
+ if (m == IMAT_PROCESS_LIN)
+ p->sizes[i] = iupMatrixAuxGetLineHeight(ih, i);
+ else
+ p->sizes[i] = iupMatrixAuxGetColumnWidth(ih, i);
+
+ if (i > 0)
+ p->total_size += p->sizes[i];
+ }
+}
+
+static void iMatrixAuxUpdateVisibleSize(Ihandle* ih, int m)
+{
+ char* D;
+ ImatLinColData *p;
+ int canvas_size;
+
+ if (m == IMAT_PROCESS_LIN)
+ {
+ D = "DY";
+ p = &(ih->data->lines);
+ canvas_size = ih->data->h;
+ }
+ else
+ {
+ D = "DX";
+ p = &(ih->data->columns);
+ canvas_size = ih->data->w;
+ }
+
+ /* Matrix useful area is the current size minus the title area */
+ p->visible_size = canvas_size - p->sizes[0];
+ if (p->visible_size > p->total_size)
+ p->visible_size = p->total_size;
+
+ if (p->total_size)
+ IupSetfAttribute(ih, D, "%f", (double)p->visible_size/(double)p->total_size);
+ else
+ IupSetAttribute(ih, D, "1.0");
+}
+
+void iupMatrixAuxCalcSizes(Ihandle* ih)
+{
+ iMatrixAuxFillSizeVec(ih, IMAT_PROCESS_COL);
+ iMatrixAuxFillSizeVec(ih, IMAT_PROCESS_LIN);
+
+ iMatrixAuxUpdateVisibleSize(ih, IMAT_PROCESS_COL);
+ iMatrixAuxUpdateVisibleSize(ih, IMAT_PROCESS_LIN);
+
+ /* when removing lines the first can be positioned after the last line */
+ if (ih->data->lines.first > ih->data->lines.num-1)
+ {
+ if (ih->data->lines.num==1)
+ ih->data->lines.first = 1;
+ else
+ ih->data->lines.first = ih->data->lines.num-1;
+ }
+ if (ih->data->columns.first > ih->data->columns.num-1)
+ {
+ if (ih->data->columns.num == 1)
+ ih->data->columns.first = 1;
+ else
+ ih->data->columns.first = ih->data->columns.num-1;
+ }
+
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ ih->data->need_calcsize = 0;
+}
+
+int iupMatrixAuxGetLinColFromXY(Ihandle* ih, int x, int y, int* l, int* c)
+{
+ int size, lin, col;
+
+ size = ih->data->columns.sizes[0]; /* always visible when non zero */
+ if (x < size)
+ col = 0; /* It is in the column of titles */
+ else
+ {
+ for(col = ih->data->columns.first; col <= ih->data->columns.last; col++) /* for all visible columns */
+ {
+ size += ih->data->columns.sizes[col];
+ if (x < size)
+ break;
+ }
+ if (col > ih->data->columns.last)
+ col = -1;
+ }
+
+ size = ih->data->lines.sizes[0]; /* always visible when non zero */
+ if (y < size)
+ lin = 0; /* It is in the line of titles */
+ else
+ {
+ for(lin = ih->data->lines.first; lin <= ih->data->lines.last; lin++) /* for all visible lines */
+ {
+ size += ih->data->lines.sizes[lin];
+ if (y < size)
+ break;
+ }
+ if(lin > ih->data->lines.last)
+ lin = -1;
+ }
+
+ if (col == -1 || lin == -1)
+ return 0;
+
+ *l = lin;
+ *c = col;
+ return 1;
+}
+
+int iupMatrixAuxCallLeaveCellCb(Ihandle* ih)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "LEAVEITEM_CB");
+ if(cb)
+ return cb(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ return IUP_DEFAULT;
+}
+
+void iupMatrixAuxCallEnterCellCb(Ihandle* ih)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "ENTERITEM_CB");
+ if (cb)
+ cb(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+}
+
+int iupMatrixAuxCallEditionCbLinCol(Ihandle* ih, int lin, int col, int mode, int update)
+{
+ IFniiii cb;
+
+ if (iupAttribGetBoolean(ih, "READONLY"))
+ return IUP_IGNORE;
+
+ cb = (IFniiii)IupGetCallback(ih, "EDITION_CB");
+ if(cb)
+ return cb(ih, lin, col, mode, update);
+ return IUP_DEFAULT;
+}
diff --git a/iup/srccontrols/matrix/iupmat_aux.h b/iup/srccontrols/matrix/iupmat_aux.h
new file mode 100755
index 0000000..296c1f5
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_aux.h
@@ -0,0 +1,37 @@
+/** \file
+ * \brief iupmatrix control
+ * auxiliary functions.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_AUX_H
+#define __IUPMAT_AUX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixAuxIsCellFullVisible(Ihandle* ih, int lin, int col);
+int iupMatrixAuxIsCellVisible(Ihandle* ih, int lin, int col);
+void iupMatrixAuxGetVisibleCellDim (Ihandle* ih, int lin, int col, int* x, int* y, int* w, int* h);
+
+void iupMatrixAuxCalcSizes(Ihandle* ih);
+
+void iupMatrixAuxUpdateVisiblePos(Ihandle* ih, int m);
+void iupMatrixAuxUpdateLast(ImatLinColData *p);
+
+int iupMatrixAuxGetColumnWidth(Ihandle* ih, int col);
+int iupMatrixAuxGetLineHeight (Ihandle* ih, int lin);
+
+int iupMatrixAuxGetLinColFromXY (Ihandle* ih, int x, int y, int* l, int* c);
+
+int iupMatrixAuxCallLeaveCellCb (Ihandle* ih);
+void iupMatrixAuxCallEnterCellCb (Ihandle* ih);
+int iupMatrixAuxCallEditionCbLinCol(Ihandle* ih, int lin, int col, int mode, int update);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_cd.h b/iup/srccontrols/matrix/iupmat_cd.h
new file mode 100755
index 0000000..1a10f2b
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_cd.h
@@ -0,0 +1,25 @@
+/** \file
+ * \brief iupmatrix. CD help macros.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_CD_H
+#define __IUPMAT_CD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IUPMAT_LINE(_ih,_x1,_y1,_x2,_y2) cdCanvasLine((_ih)->data->cddbuffer, (_x1), iupMatrixInvertYAxis(_ih, _y1), (_x2), iupMatrixInvertYAxis(_ih, _y2))
+#define IUPMAT_VERTEX(_ih,_x,_y) cdCanvasVertex((_ih)->data->cddbuffer, (_x), iupMatrixInvertYAxis(_ih, _y))
+#define IUPMAT_BOX(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasBox((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+#define IUPMAT_RECT(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasRect((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+#define IUPMAT_CLIPAREA(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasClipArea((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+#define IUPMAT_TEXT(_ih,_x,_y,_text) cdCanvasText((_ih)->data->cddbuffer, (_x), iupMatrixInvertYAxis(_ih, _y), (_text))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_colres.c b/iup/srccontrols/matrix/iupmat_colres.c
new file mode 100755
index 0000000..d44b7df
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_colres.c
@@ -0,0 +1,182 @@
+/** \file
+ * \brief iupmatrix column resize
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Interactive Column Resize Functions and WIDTH/HEIGHT change */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_colres.h"
+#include "iupmat_draw.h"
+
+
+#define IMAT_COLRES_TOL 3
+#define IMAT_RESIZE_COLOR 0x666666L
+
+
+/* Verify if the mouse is in the intersection between two of column titles,
+ if so the resize is started */
+int iupMatrixColResStart(Ihandle* ih, int x, int y)
+{
+ if (ih->data->lines.sizes[0] && y < ih->data->lines.sizes[0] && iupAttribGetBoolean(ih, "RESIZEMATRIX"))
+ {
+ int size, col;
+
+ /* Check if is the column of titles */
+ size = ih->data->columns.sizes[0];
+ if (abs(size-x) < IMAT_COLRES_TOL)
+ {
+ ih->data->colres_drag_col_start_x = 0;
+ ih->data->colres_dragging = 1;
+ ih->data->colres_drag_col_last_x = -1;
+ ih->data->colres_drag_col = 0;
+ return 1;
+ }
+ else
+ {
+ /* find the column */
+ for(col = ih->data->columns.first; col <= ih->data->columns.last; col++)
+ {
+ ih->data->colres_drag_col_start_x = size;
+ size += ih->data->columns.sizes[col];
+ if (abs(size-x) < IMAT_COLRES_TOL)
+ {
+ ih->data->colres_dragging = 1;
+ ih->data->colres_drag_col_last_x = -1;
+ ih->data->colres_drag_col = col;
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void iupMatrixColResFinish(Ihandle* ih, int x)
+{
+ char str[100];
+ int width = x - ih->data->colres_drag_col_start_x;
+ if (width < 0)
+ width = 0;
+
+ /* delete feedback */
+ if (ih->data->colres_drag_col_last_x != -1)
+ {
+ int y1 = ih->data->lines.sizes[0]; /* from the bottom of the line of titles */
+ int y2 = ih->data->h-1; /* to the bottom of the matrix */
+
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_XOR);
+ cdCanvasForeground(ih->data->cdcanvas, IMAT_RESIZE_COLOR);
+ cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y1),
+ ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y2));
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_REPLACE);
+ }
+
+ ih->data->colres_dragging = 0;
+
+ sprintf(str, "RASTERWIDTH%d", ih->data->colres_drag_col);
+ iupAttribSetInt(ih, str, width-IMAT_PADDING_W-IMAT_FRAME_W);
+ sprintf(str, "WIDTH%d", ih->data->colres_drag_col);
+ iupAttribSetStr(ih, str, NULL);
+
+ ih->data->need_calcsize = 1;
+ iupMatrixDraw(ih, 0);
+}
+
+/* Change the column width interactively, just change the line in the screen.
+ When the user finishes the drag, the iupMatrixColResFinish function is called
+ to truly change the column width. */
+void iupMatrixColResMove(Ihandle* ih, int x)
+{
+ int y1, y2;
+
+ int width = x - ih->data->colres_drag_col_start_x;
+ if (width < 0)
+ return;
+
+ y1 = ih->data->lines.sizes[0]; /* from the bottom of the line of titles */
+ y2 = ih->data->h-1; /* to the bottom of the matrix */
+
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_XOR);
+ cdCanvasForeground(ih->data->cdcanvas, IMAT_RESIZE_COLOR);
+
+ /* If it is not the first time, move old line */
+ if (ih->data->colres_drag_col_last_x != -1)
+ {
+ cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y1),
+ ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y2));
+ }
+
+ cdCanvasLine(ih->data->cdcanvas, x, iupMatrixInvertYAxis(ih, y1),
+ x, iupMatrixInvertYAxis(ih, y2));
+
+ ih->data->colres_drag_col_last_x = x;
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_REPLACE);
+}
+
+
+static void iMatrixColResResetMatrixCursor(Ihandle* ih)
+{
+ char *cursor = iupAttribGet(ih, "_IUPMAT_CURSOR");
+ if (cursor)
+ {
+ IupStoreAttribute(ih, "CURSOR", cursor);
+ iupAttribSetStr(ih, "_IUPMAT_CURSOR", NULL);
+ }
+}
+
+/* Change the cursor when it passes over a group of the column titles. */
+void iupMatrixColResCheckChangeCursor(Ihandle* ih, int x, int y)
+{
+ if(ih->data->lines.sizes[0] && y < ih->data->lines.sizes[0] && iupAttribGetBoolean(ih, "RESIZEMATRIX"))
+ {
+ /* It is in the column titles area and the resize mode is on */
+ int found = 0, size, col;
+
+ size = ih->data->columns.sizes[0];
+ if (abs(size - x) < IMAT_COLRES_TOL)
+ found = 1; /* line titles */
+ else
+ {
+ for(col = ih->data->columns.first; col <= ih->data->columns.last && !found; col++)
+ {
+ size += ih->data->columns.sizes[col];
+ if(abs(size - x) < IMAT_COLRES_TOL)
+ found = 1;
+ }
+ }
+
+ if (found)
+ {
+ if (!iupAttribGet(ih, "_IUPMAT_CURSOR"))
+ iupAttribStoreStr(ih, "_IUPMAT_CURSOR", IupGetAttribute(ih, "CURSOR"));
+ IupSetAttribute(ih, "CURSOR", "RESIZE_W");
+ }
+ else /* It is in the empty area after the last column */
+ iMatrixColResResetMatrixCursor(ih);
+ }
+ else
+ iMatrixColResResetMatrixCursor(ih);
+}
+
+int iupMatrixColResIsResizing(Ihandle* ih)
+{
+ return ih->data->colres_dragging;
+}
+
diff --git a/iup/srccontrols/matrix/iupmat_colres.h b/iup/srccontrols/matrix/iupmat_colres.h
new file mode 100755
index 0000000..ba7f23d
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_colres.h
@@ -0,0 +1,24 @@
+/** \file
+ * \brief iupmatrix column resize.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_COLRES_H
+#define __IUPMAT_COLRES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixColResStart (Ihandle* ih, int x, int y);
+void iupMatrixColResFinish (Ihandle* ih, int x);
+void iupMatrixColResMove (Ihandle* ih, int x);
+void iupMatrixColResCheckChangeCursor(Ihandle* ih, int x, int y);
+int iupMatrixColResIsResizing (Ihandle* ih);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_def.h b/iup/srccontrols/matrix/iupmat_def.h
new file mode 100755
index 0000000..d45acde
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_def.h
@@ -0,0 +1,122 @@
+/** \file
+ * \brief iupmatrix. definitions.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_DEF_H
+#define __IUPMAT_DEF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define IMAT_PROCESS_COL 1 /* Process the columns */
+#define IMAT_PROCESS_LIN 2 /* Process the lines */
+
+/***************************************************************************/
+/* Decoration size in pixels */
+/***************************************************************************/
+#define IMAT_PADDING_W 6
+#define IMAT_PADDING_H 6
+#define IMAT_FRAME_W 2
+#define IMAT_FRAME_H 2
+
+/* Cell flags */
+#define IUPMAT_FONT 1 /* Has FONTL:C attribute */
+#define IUPMAT_FGCOLOR 2 /* Has FGCOLORL:C attribute */
+#define IUPMAT_BGCOLOR 4 /* Has BGCOLORL:C attribute */
+#define IUPMAT_MARK 8 /* Is marked */
+#define IUPMAT_FRAMEHCOLOR 16 /* Has FRAMEHORIZCOLORL:C */
+#define IUPMAT_FRAMEVCOLOR 32 /* Has FRAMEVERTCOLORL:C */
+
+/***************************************************************************/
+/* Structures stored in each matrix */
+/***************************************************************************/
+typedef struct _ImatCell
+{
+ char *value; /* Cell value */
+ unsigned char flags;
+} ImatCell;
+
+
+typedef struct _ImatLinColData
+{
+ int* sizes; /* Width/height of the columns/lines (allocated after map) */
+ unsigned char* flags; /* Attribute flags for the columns/lines (allocated after map) */
+
+ int num; /* Number of columns/lines in the matrix, default/minimum=1, always includes the title */
+ int num_alloc; /* Number of columns/lines allocated, default=5 */
+
+ int first; /* First visible column/line */
+ int last; /* Last visible column/line */
+
+ /* used to configure the scrollbar */
+ int total_size; /* Sum of the widths/heights of the columns/lines, not including the title */
+ int visible_size; /* Width/height of the visible window, not including the title */
+
+ int focus_cell; /* index of the current cell */
+} ImatLinColData;
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ ImatCell** cells; /* Cell value, this will be NULL if in callback mode (allocated after map) */
+
+ Ihandle* texth; /* Text handle */
+ Ihandle* droph; /* Dropdown handle */
+ Ihandle* datah; /* Current active edition element, may be equal to texth or droph */
+
+ cdCanvas* cddbuffer;
+ cdCanvas* cdcanvas;
+
+ ImatLinColData lines;
+ ImatLinColData columns;
+
+ int has_focus;
+ int w, h; /* canvas size */
+ int callback_mode;
+ int use_title_size; /* use title contents when calculating cell size */
+ int need_calcsize;
+ int first_redraw;
+
+ /* attributes */
+ int mark_continuous, mark_mode, mark_multiple;
+ int checkframecolor;
+
+ /* Mouse and Keyboard AUX */
+ int leftpressed; /* left mouse button is pressed */
+ int homekeycount, endkeycount; /* numbers of times that key was pressed */
+
+ /* ColRes AUX */
+ int colres_dragging, /* indicates if it is being made a column resize */
+ colres_drag_col, /* column being resized */
+ colres_drag_col_start_x, /* position of the start of the column being resized */
+ colres_drag_col_last_x; /* previous position */
+
+ /* Mark AUX */
+ int mark_lin1, mark_col1, /* used to store the start cell when a block is being marked */
+ mark_lin2, mark_col2, /* used to store the end cell when a block was marked */
+ mark_full1, /* indicate if full lines or columns is being selected */
+ mark_full2;
+
+ /* Draw AUX, valid only after iupMatrixPrepareDrawData */
+ sIFnii font_cb;
+ IFniiIII fgcolor_cb;
+ IFniiIII bgcolor_cb;
+ char *bgcolor, *bgcolor_parent, *fgcolor, *font; /* not need to free */
+};
+
+
+int iupMatrixIsValid(Ihandle* ih, int check_cells);
+
+#define iupMatrixInvertYAxis(_ih, _y) ((_ih)->data->h-1 - (_y))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_draw.c b/iup/srccontrols/matrix/iupmat_draw.c
new file mode 100755
index 0000000..7c53fb5
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_draw.c
@@ -0,0 +1,866 @@
+/** \file
+ * \brief iupmatrix control
+ * draw functions
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef CD_NO_OLD_INTERFACE
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+#include "iup_image.h"
+
+#include "iupmat_def.h"
+#include "iupmat_cd.h"
+#include "iupmat_draw.h"
+#include "iupmat_aux.h"
+#include "iupmat_getset.h"
+#include "iupmat_mark.h"
+
+
+/* Color attenuation factor in a marked cell, 20% darker */
+#define IMAT_ATENUATION(_x) ((unsigned char)(((_x)*8)/10))
+
+/* Text alignment that will be draw. Used by iMatrixDrawCellValue */
+#define IMAT_T_CENTER 1
+#define IMAT_T_LEFT 2
+#define IMAT_T_RIGHT 3
+
+#define IMAT_CD_INACTIVE_FGCOLOR 0x666666L
+
+#define IMAT_COMBOBOX_W 16
+
+
+typedef int (*IFniiiiiiC)(Ihandle *h, int lin, int col,int x1, int x2, int y1, int y2, cdCanvas* cnv);
+
+
+/**************************************************************************/
+/* Private functions */
+/**************************************************************************/
+
+
+static int iMatrixDrawGetColAlignment(Ihandle* ih, int col, char* str)
+{
+ char* align;
+ sprintf(str, "ALIGNMENT%d", col);
+ align = iupAttribGet(ih, str);
+ if (!align)
+ {
+ if (col == 0)
+ return IMAT_T_LEFT;
+ else
+ return IMAT_T_CENTER;
+ }
+ else if (iupStrEqualNoCase(align, "ARIGHT"))
+ return IMAT_T_RIGHT;
+ else if(iupStrEqualNoCase(align, "ACENTER"))
+ return IMAT_T_CENTER;
+ else
+ return IMAT_T_LEFT;
+}
+
+static int iMatrixDrawCallDrawCB(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, IFniiiiiiC draw_cb)
+{
+ int ret;
+ cdCanvas* old_cnv;
+
+ IUPMAT_CLIPAREA(ih, x1, x2, y1, y2);
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
+
+ old_cnv = cdActiveCanvas();
+ if (old_cnv != ih->data->cddbuffer) /* backward compatibility code */
+ cdActivate(ih->data->cddbuffer);
+
+ ret = draw_cb(ih, lin, col, x1, x2, iupMatrixInvertYAxis(ih, y1), iupMatrixInvertYAxis(ih, y2), ih->data->cddbuffer);
+
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+
+ if (old_cnv && old_cnv != ih->data->cddbuffer) /* backward compatibility code */
+ {
+ cdActivate(old_cnv);
+ cdCanvasActivate(ih->data->cddbuffer);
+ }
+
+ if (ret == IUP_DEFAULT)
+ return 0;
+
+ return 1;
+}
+
+/* Change the CD foreground color, for the selected color to draw a cell with
+ its FOREGROUND COLOR. This involves checking if there is a color attribute
+ that cell. If no, uses a color attribute for the line, else if no for the
+ column, else if no for the entire matrix. Finally, if not find any of
+ these, use the default color.
+ -> lin, col - cell coordinates, in IUP format - i.e., l,l represents the left
+ top cell of the matrix; lin and col values = 0 represents the
+ title lines and columns.
+ -> mark - indicate if a cell is marked. If yes, its color is attenuated.
+*/
+static unsigned long iMatrixDrawSetFgColor(Ihandle* ih, int lin, int col, int mark)
+{
+ unsigned char r = 0, g = 0, b = 0;
+ iupMatrixGetFgRGB(ih, lin, col, &r, &g, &b);
+
+ if (mark)
+ {
+ r = IMAT_ATENUATION(r);
+ g = IMAT_ATENUATION(g);
+ b = IMAT_ATENUATION(b);
+ }
+
+ return cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(r, g, b));
+}
+
+/* Change the CD foreground color, for the selected color to draw a cell with
+ its BACKGROUND COLOR. This involves checking if there is a color attribute
+ that cell. If no, uses a color attribute for the line, else if no for the
+ column, else if no for the entire matrix. Finally, if not find any of
+ these, use the default color.
+ -> lin, col - cell coordinates, in IUP format - i.e., l,l represents the left
+ top cell of the matrix; lin and col values = 0 represents the
+ title lines and columns.
+ -> mark - indicate if a cell is marked. If yes, its color is attenuated.
+*/
+static unsigned long iMatrixDrawSetBgColor(Ihandle* ih, int lin, int col, int mark, int active)
+{
+ unsigned char r = 255, g = 255, b = 255;
+
+ iupMatrixGetBgRGB(ih, lin, col, &r, &g, &b);
+
+ if (mark)
+ {
+ r = IMAT_ATENUATION(r);
+ g = IMAT_ATENUATION(g);
+ b = IMAT_ATENUATION(b);
+ }
+
+ if (!active)
+ {
+ r = cdIupLIGTHER(r);
+ g = cdIupLIGTHER(g);
+ b = cdIupLIGTHER(b);
+ }
+
+ return cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(r, g, b));
+}
+
+static void iMatrixDrawFrameHorizLineCell(Ihandle* ih, int lin, int col, int x1, int x2, int y, long framecolor, char* str)
+{
+ if (ih->data->checkframecolor && (ih->data->callback_mode || ih->data->cells[lin][col].flags & IUPMAT_FRAMEHCOLOR))
+ {
+ unsigned char r,g,b;
+ sprintf(str, "FRAMEHORIZCOLOR%d:%d", lin, col);
+ if (iupStrToRGB(iupAttribGet(ih, str), &r, &g, &b))
+ framecolor = cdEncodeColor(r, g, b);
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+ IUPMAT_LINE(ih, x1, y, x2, y); /* bottom horizontal line */
+}
+
+static void iMatrixDrawFrameVertLineCell(Ihandle* ih, int lin, int col, int x, int y1, int y2, long framecolor, char* str)
+{
+ if (ih->data->checkframecolor && (ih->data->callback_mode || ih->data->cells[lin][col].flags & IUPMAT_FRAMEVCOLOR))
+ {
+ unsigned char r,g,b;
+ sprintf(str, "FRAMEVERTCOLOR%d:%d", lin, col);
+ if (iupStrToRGB(iupAttribGet(ih, str), &r, &g, &b))
+ framecolor = cdEncodeColor(r, g, b);
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+ IUPMAT_LINE(ih, x, y1, x, y2); /* right vertical line */
+}
+
+static void iMatrixDrawFrameRectTitle(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor, char* str)
+{
+ /* avoid drawing over the frame of the next cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ iMatrixDrawFrameVertLineCell(ih, lin, col, x2, y1, y2, framecolor, str); /* right vertical line */
+ if (col==0)
+ {
+ IUPMAT_LINE(ih, x1, y1, x1, y2); /* left vertical line, reuse Foreground */
+ x1++;
+ }
+ else if (col==1 && ih->data->columns.sizes[0] == 0)
+ {
+ /* If does not have line titles then draw the left line of the cell frame */
+ IUPMAT_LINE(ih, x1, y1, x1, y2-1);
+ x1++;
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); /* Titles have a white line near the frame */
+ IUPMAT_LINE(ih, x1, y1+1, x1, y2-1);
+
+ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2, y2, framecolor, str); /* bottom horizontal line */
+ if (lin==0)
+ {
+ IUPMAT_LINE(ih, x1, y1, x2, y1); /* top horizontal line, reuse Foreground */
+ y1++;
+ }
+ else if (lin==1 && ih->data->lines.sizes[0] == 0)
+ {
+ /* If does not have column titles then draw the top line of the cell frame */
+ IUPMAT_LINE(ih, x1, y1, x2-1, y1);
+ y1++;
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); /* Titles have a white line near the frame */
+ IUPMAT_LINE(ih, x1, y1, x2-1, y1);
+}
+
+static void iMatrixDrawFrameRectCell(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor, char* str)
+{
+ if (col==1 && ih->data->columns.sizes[0] == 0)
+ {
+ /* If does not have line titles then draw the left line of the cell frame */
+ iMatrixDrawFrameVertLineCell(ih, lin, col, x1, y1, y2-1-1, framecolor, str);
+ }
+
+ if (lin==1 && ih->data->lines.sizes[0] == 0)
+ {
+ /* If does not have column titles then draw the top line of the cell frame */
+ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2-1-1, y1, framecolor, str);
+ }
+
+ /* bottom line */
+ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2-1, y2-1, framecolor, str);
+
+ /* rigth line */
+ iMatrixDrawFrameVertLineCell(ih, lin, col, x2-1, y1, y2-1, framecolor, str);
+}
+
+static int iMatrixDrawSortSign(Ihandle* ih, int x2, int y1, int y2, int col, int active, char* str)
+{
+ int yc;
+ char* sort;
+
+ sprintf(str, "SORTSIGN%d", col);
+ sort = iupAttribGet(ih, str);
+ if (!sort || iupStrEqualNoCase(sort, "NO"))
+ return 0;
+
+ /* Remove the space between text and cell frame */
+ x2 -= IMAT_PADDING_W/2 + IMAT_FRAME_W/2;
+
+ /* Set the color used to draw the text */
+ if (active)
+ cdCanvasForeground(ih->data->cddbuffer, IMAT_CD_INACTIVE_FGCOLOR);
+ else
+ iMatrixDrawSetFgColor(ih, 0, col, 0);
+
+ yc = (int)( (y1 + y2 ) / 2.0 - .5);
+
+ cdCanvasBegin(ih->data->cddbuffer, CD_FILL);
+
+ if (iupStrEqualNoCase(sort, "DOWN"))
+ {
+ IUPMAT_VERTEX(ih, x2 - 5, yc + 2);
+ IUPMAT_VERTEX(ih, x2 - 1, yc - 2);
+ IUPMAT_VERTEX(ih, x2 - 9, yc - 2);
+ }
+ else
+ {
+ IUPMAT_VERTEX(ih, x2 - 1, yc + 2);
+ IUPMAT_VERTEX(ih, x2 - 9, yc + 2);
+ IUPMAT_VERTEX(ih, x2 - 5, yc - 2);
+ }
+
+ cdCanvasEnd(ih->data->cddbuffer);
+ return 1;
+}
+
+static void iMatrixDrawComboFeedback(Ihandle* ih, int x2, int y1, int y2, int active, long framecolor)
+{
+ int xh2, yh2, x1;
+
+ /* feedback area */
+ x2 -= IMAT_PADDING_W/2 + IMAT_FRAME_W/2;
+ x1 = x2 - IMAT_COMBOBOX_W;
+ y1 += IMAT_PADDING_H/2 + IMAT_FRAME_H/2;
+ y2 -= IMAT_PADDING_H/2 + IMAT_FRAME_H/2;
+
+ /* feedback background */
+ iMatrixDrawSetBgColor(ih, 0, 0, 0, active);
+ IUPMAT_BOX(ih, x1, x2, y1, y2);
+
+ /* feedback frame */
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+ IUPMAT_RECT(ih, x1, x2, y1, y2);
+
+ /* feedback arrow */
+ xh2 = x2 - IMAT_COMBOBOX_W / 2;
+ yh2 = y2 - (y2 - y1) / 2;
+
+ cdCanvasBegin(ih->data->cddbuffer, CD_FILL);
+ IUPMAT_VERTEX(ih, xh2, yh2 + 3);
+ IUPMAT_VERTEX(ih, xh2 + 4, yh2 - 1);
+ IUPMAT_VERTEX(ih, xh2 - 4, yh2 - 1);
+ cdCanvasEnd(ih->data->cddbuffer);
+}
+
+static void iMatrixDrawBackground(Ihandle* ih, int x1, int x2, int y1, int y2, int marked, int active, int lin, int col)
+{
+ /* avoid drawing over the frame of the next cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ iMatrixDrawSetBgColor(ih, lin, col, marked, active);
+ IUPMAT_BOX(ih, x1, x2, y1, y2);
+}
+
+/* Put the cell contents in the screen, using the specified color and alignment.
+ -> y1, y2 : vertical limits of the cell
+ -> x1, x2 : horizontal limits of the complete cell
+ -> alignment : alignment type (horizontal) assigned to the text. The options are:
+ [IMAT_T_CENTER,IMAT_T_LEFT,IMAT_T_RIGHT]
+ -> marked : mark state
+ -> lin, col - cell coordinates */
+static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, int alignment, int marked, int active, int lin, int col, IFniiiiiiC draw_cb)
+{
+ char *text;
+
+ /* avoid drawing over the frame of the next cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ /* avoid drawing over the frame of the cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ if (lin==0 || col==0)
+ {
+ /* avoid drawing over the frame of the cell */
+ x1 += IMAT_FRAME_W/2;
+ y1 += IMAT_FRAME_H/2;
+
+ if (col==0) x1 += IMAT_FRAME_W/2;
+ if (lin==0) y1 += IMAT_FRAME_H/2;
+ }
+ else if ((col==1 && ih->data->columns.sizes[0] == 0) || (lin==1 && ih->data->lines.sizes[0] == 0))
+ {
+ /* avoid drawing over the frame of the cell */
+ x1 += IMAT_FRAME_W/2;
+ y1 += IMAT_FRAME_H/2;
+ }
+
+ if (draw_cb && !iMatrixDrawCallDrawCB(ih, lin, col, x1, x2, y1, y2, draw_cb))
+ return;
+
+ text = iupMatrixCellGetValue(ih, lin, col);
+
+ /* Put the text */
+ if (text && *text)
+ {
+ int num_line, line_height, total_height;
+ int charheight, ypos;
+
+ num_line = iupStrLineCount(text);
+ iupdrvFontGetCharSize(ih, NULL, &charheight);
+
+ line_height = charheight;
+ total_height = (line_height + IMAT_PADDING_H/2) * num_line - IMAT_PADDING_H/2 - IMAT_FRAME_H/2;
+
+ if (lin==0)
+ {
+ int text_w;
+ iupdrvFontGetMultiLineStringSize(ih, text, &text_w, NULL);
+ if (text_w > x2 - x1 + 1 - IMAT_PADDING_W - IMAT_FRAME_W)
+ alignment = IMAT_T_LEFT;
+ }
+
+ /* Set the color used to draw the text */
+ if (!active)
+ cdCanvasForeground(ih->data->cddbuffer, IMAT_CD_INACTIVE_FGCOLOR);
+ else
+ iMatrixDrawSetFgColor(ih, lin, col, marked);
+
+ /* Set the clip area to the cell region informed, the text maybe greatter than the cell */
+ IUPMAT_CLIPAREA(ih, x1, x2, y1, y2);
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
+
+ cdCanvasNativeFont(ih->data->cddbuffer, iupMatrixGetFont(ih, lin, col));
+
+ /* Create an space between text and cell frame */
+ x1 += IMAT_PADDING_W/2; x2 -= IMAT_PADDING_W/2;
+ y1 += IMAT_PADDING_H/2; y2 -= IMAT_PADDING_H/2;
+
+ if (alignment == IMAT_T_CENTER)
+ cdCanvasTextAlignment(ih->data->cddbuffer, CD_CENTER);
+ else if(alignment == IMAT_T_LEFT)
+ cdCanvasTextAlignment(ih->data->cddbuffer, CD_WEST);
+ else
+ cdCanvasTextAlignment(ih->data->cddbuffer, CD_EAST);
+
+ if (num_line == 1)
+ {
+ ypos = (int)((y1 + y2) / 2.0 - 0.5);
+
+ /* Put the text */
+ if (alignment == IMAT_T_CENTER)
+ IUPMAT_TEXT(ih, (x1 + x2) / 2, ypos, text);
+ else if(alignment == IMAT_T_LEFT)
+ IUPMAT_TEXT(ih, x1, ypos, text);
+ else
+ IUPMAT_TEXT(ih, x2, ypos, text);
+ }
+ else
+ {
+ int i;
+ char *p, *q, *newtext;
+
+ newtext = iupStrDup(text);
+ p = newtext;
+
+ /* Get the position of the first text to be put in the screen */
+ ypos = (int)( (y1 + y2) / 2.0 - 0.5) - total_height/2 + line_height/2;
+
+ for(i = 0; i < num_line; i++)
+ {
+ q = strchr(p, '\n');
+ if (q) *q = 0; /* Cut the string to contain only one line */
+
+ /* Draw the text */
+ if(alignment == IMAT_T_CENTER)
+ IUPMAT_TEXT(ih, (x1 + x2) / 2, ypos, p);
+ else if(alignment == IMAT_T_LEFT)
+ IUPMAT_TEXT(ih, x1, ypos, p);
+ else
+ IUPMAT_TEXT(ih, x2, ypos, p);
+
+ /* Advance the string */
+ if (q) p = q + 1;
+
+ /* Advance a line */
+ ypos += line_height + IMAT_PADDING_H/2;
+ }
+
+ free(newtext);
+ }
+
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+ }
+}
+
+static void iMatrixDrawTitleCorner(Ihandle* ih)
+{
+ char str[100];
+ long framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ int active = iupdrvIsActive(ih);
+ IFniiiiiiC draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ iMatrixDrawBackground(ih, 0, ih->data->columns.sizes[0], 0, ih->data->lines.sizes[0], 0, active, 0, 0);
+
+ iMatrixDrawFrameRectTitle(ih, 0, 0, 0, ih->data->columns.sizes[0], 0, ih->data->lines.sizes[0], framecolor, str);
+
+ iMatrixDrawCellValue(ih, 0, ih->data->columns.sizes[0], 0, ih->data->lines.sizes[0], IMAT_T_CENTER, 0, active, 0, 0, draw_cb);
+}
+
+static void iMatrixDrawMatrix(Ihandle* ih)
+{
+ iupMatrixPrepareDrawData(ih);
+
+ /* fill the background because there will be empty cells */
+ if ((ih->data->lines.num == 1) || (ih->data->columns.num == 1))
+ {
+ cdCanvasBackground(ih->data->cddbuffer, cdIupConvertColor(ih->data->bgcolor_parent));
+ cdCanvasClear(ih->data->cddbuffer);
+ }
+
+ /* Draw the corner between line and column titles, if necessary */
+ if (ih->data->lines.sizes[0] && ih->data->columns.sizes[0])
+ iMatrixDrawTitleCorner(ih);
+
+ /* If there are columns, then draw their titles */
+ iupMatrixDrawColumnTitle(ih, ih->data->columns.first, ih->data->columns.last);
+
+ /* If there are lines, then draw their titles */
+ iupMatrixDrawLineTitle(ih, ih->data->lines.first, ih->data->lines.last);
+
+ /* If there are cells in the matrix, then draw them */
+ if ((ih->data->lines.num > 1) && (ih->data->columns.num > 1))
+ iupMatrixDrawCells(ih, ih->data->lines.first, ih->data->columns.first,
+ ih->data->lines.last, ih->data->columns.last);
+}
+
+static void iMatrixDrawFocus(Ihandle* ih)
+{
+ int x1, y1, x2, y2, dx, dy;
+
+ if (iupAttribGetBoolean(ih, "HIDEFOCUS"))
+ return;
+
+ if (!iupMatrixAuxIsCellVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ return;
+
+ iupMatrixAuxGetVisibleCellDim(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, &x1, &y1, &dx, &dy);
+
+ x2 = x1 + dx - 1;
+ y2 = y1 + dy - 1;
+
+ if (ih->data->columns.focus_cell == 1 && ih->data->columns.sizes[0] == 0)
+ x1++;
+ if (ih->data->lines.focus_cell == 1 && ih->data->lines.sizes[0] == 0)
+ y1++;
+
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, x1, iupMatrixInvertYAxis(ih, y1), x2, iupMatrixInvertYAxis(ih, y2));
+}
+
+
+/**************************************************************************/
+/* Exported functions */
+/**************************************************************************/
+
+
+/* Draw the line titles, visible, between lin and lastlin, include it.
+ Line titles marked will be draw with the appropriate feedback.
+ -> lin1 - First line to have its title drawn
+ -> lin2 - Last line to have its title drawn */
+void iupMatrixDrawLineTitle(Ihandle* ih, int lin1, int lin2)
+{
+ int x1, y1, x2, y2;
+ int lin, alignment, active;
+ char str[100];
+ long framecolor;
+ IFniiiiiiC draw_cb;
+
+ if (!ih->data->columns.sizes[0])
+ return;
+
+ if (lin1 > ih->data->lines.last ||
+ lin2 < ih->data->lines.first)
+ return;
+
+ if (lin1 < ih->data->lines.first)
+ lin1 = ih->data->lines.first;
+ if (lin2 > ih->data->lines.last)
+ lin2 = ih->data->lines.last;
+
+ /* Start the position of the line title */
+ x1 = 0;
+ x2 = ih->data->columns.sizes[0];
+
+ y1 = ih->data->lines.sizes[0];
+ for(lin = ih->data->lines.first; lin < lin1; lin++)
+ y1 += ih->data->lines.sizes[lin];
+
+ framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ active = iupdrvIsActive(ih);
+ draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ alignment = iMatrixDrawGetColAlignment(ih, 0, str);
+
+ /* Draw the titles */
+ for(lin = lin1; lin <= lin2; lin++)
+ {
+ /* If it is a hidden line (size = 0), don't draw the title */
+ if(ih->data->lines.sizes[lin] == 0)
+ continue;
+
+ y2 = y1 + ih->data->lines.sizes[lin];
+
+ /* If it doesn't have title, the loop just calculate the final position */
+ if (ih->data->columns.sizes[0])
+ {
+ int marked = iupMatrixLineIsMarked(ih, lin);
+
+ iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, lin, 0);
+
+ iMatrixDrawFrameRectTitle(ih, lin, 0, x1, x2, y1, y2, framecolor, str);
+
+ iMatrixDrawCellValue(ih, x1, x2, y1, y2, alignment, marked, active, lin, 0, draw_cb);
+ }
+
+ y1 = y2;
+ }
+}
+
+/* Draw the column titles, visible, between col and lastcol, include it.
+ Column titles marked will be draw with the appropriate feedback.
+ -> col1 - First column to have its title drawn
+ -> col2 - Last column to have its title drawn */
+void iupMatrixDrawColumnTitle(Ihandle* ih, int col1, int col2)
+{
+ int x1, y1, x2, y2;
+ int col, active;
+ char str[100];
+ long framecolor;
+ IFniiiiiiC draw_cb;
+
+ if (!ih->data->lines.sizes[0])
+ return;
+
+ if (col1 > ih->data->columns.last ||
+ col2 < ih->data->columns.first)
+ return;
+
+ if (col1 < ih->data->columns.first)
+ col1 = ih->data->columns.first;
+ if (col2 > ih->data->columns.last)
+ col2 = ih->data->columns.last;
+
+ /* Start the position of the first column title */
+ y1 = 0;
+ y2 = ih->data->lines.sizes[0];
+
+ x1 = ih->data->columns.sizes[0];
+ for(col = ih->data->columns.first; col < col1; col++)
+ x1 += ih->data->columns.sizes[col];
+
+ framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ active = iupdrvIsActive(ih);
+ draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ /* Draw the titles */
+ for(col = col1; col <= col2; col++)
+ {
+ /* If it is an hide column (size = 0), no draw the title */
+ if(ih->data->columns.sizes[col] == 0)
+ continue;
+
+ x2 = x1 + ih->data->columns.sizes[col];
+
+ /* If it doesn't have title, the loop just calculate the final position */
+ if (ih->data->lines.sizes[0])
+ {
+ int sort = 0;
+ int marked = iupMatrixColumnIsMarked(ih, col);
+
+ iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, 0, col);
+
+ iMatrixDrawFrameRectTitle(ih, 0, col, x1, x2, y1, y2, framecolor, str);
+
+ if (iMatrixDrawSortSign(ih, x2, y1, y2, col, active, str))
+ sort = IMAT_COMBOBOX_W; /* same space is used by the sort sign */
+
+ iMatrixDrawCellValue(ih, x1, x2-sort, y1, y2, IMAT_T_CENTER, marked, active, 0, col, draw_cb);
+ }
+
+ x1 = x2;
+ }
+}
+
+/* Redraw a block of cells of the matrix. Handle marked cells, change
+ automatically the background color of them.
+ - lin1, col1 : cell coordinates that mark the left top corner of the area to be redrawn
+ - lin2, col2 : cell coordinates that mark the right bottom corner of the area to be redrawn */
+void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+{
+ int x1, y1, x2, y2, old_x2, old_y1, old_y2;
+ int alignment, lin, col, active;
+ long framecolor, emptyarea_color = -1;
+ char str[100];
+ IFnii mark_cb;
+ IFnii dropcheck_cb;
+ IFniiiiiiC draw_cb;
+
+ x1 = 0;
+ x2 = ih->data->w-1;
+ y1 = 0;
+ y2 = ih->data->h-1;
+
+ old_x2 = x2;
+ old_y1 = y1;
+ old_y2 = y2;
+
+ if (col1 > ih->data->columns.last ||
+ col2 < ih->data->columns.first ||
+ lin1 > ih->data->lines.last ||
+ lin2 < ih->data->lines.first)
+ return;
+
+ if (col1 < ih->data->columns.first)
+ col1 = ih->data->columns.first;
+ if (col2 > ih->data->columns.last)
+ col2 = ih->data->columns.last;
+ if (lin1 < ih->data->lines.first)
+ lin1 = ih->data->lines.first;
+ if (lin2 > ih->data->lines.last)
+ lin2 = ih->data->lines.last;
+
+ /* Find the initial position of the first column */
+ x1 += ih->data->columns.sizes[0];
+ for(col = ih->data->columns.first; col < col1; col++)
+ x1 += ih->data->columns.sizes[col];
+
+ /* Find the final position of the last column */
+ x2 = x1;
+ for( ; col <= col2; col++)
+ x2 += ih->data->columns.sizes[col];
+
+ /* Find the initial position of the first line */
+ y1 += ih->data->lines.sizes[0];
+ for(lin = ih->data->lines.first; lin < lin1; lin++)
+ y1 += ih->data->lines.sizes[lin];
+
+ /* Find the final position of the last line */
+ y2 = y1;
+ for( ; lin <= lin2; lin++)
+ y2 += ih->data->lines.sizes[lin];
+
+ if ((col2 == ih->data->columns.num-1) && (old_x2 > x2))
+ {
+ emptyarea_color = cdIupConvertColor(ih->data->bgcolor_parent);
+ cdCanvasForeground(ih->data->cddbuffer, emptyarea_color);
+
+ /* If it was drawn until the last column and remains space in the right of it,
+ then delete this area with the the background color. */
+ IUPMAT_BOX(ih, x2, old_x2, old_y1, old_y2);
+ }
+
+ if ((lin2 == ih->data->lines.num-1) && (old_y2 > y2))
+ {
+ if (emptyarea_color == -1)
+ emptyarea_color = cdIupConvertColor(ih->data->bgcolor_parent);
+ cdCanvasForeground(ih->data->cddbuffer, emptyarea_color);
+
+ /* If it was drawn until the last line visible and remains space below it,
+ then delete this area with the the background color. */
+ IUPMAT_BOX(ih, 0, old_x2, y2, old_y2);
+ }
+
+ /***** Draw the cell values and frame */
+ old_y1 = y1;
+ framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ active = iupdrvIsActive(ih);
+
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ dropcheck_cb = (IFnii)IupGetCallback(ih, "DROPCHECK_CB");
+ draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ for(col = col1; col <= col2; col++) /* For all the columns in the region */
+ {
+ if (ih->data->columns.sizes[col] == 0)
+ continue;
+
+ alignment = iMatrixDrawGetColAlignment(ih, col, str);
+
+ x2 = x1 + ih->data->columns.sizes[col];
+
+ for(lin = lin1; lin <= lin2; lin++) /* For all lines in the region */
+ {
+ int drop = 0;
+ int marked = 0;
+
+ if (ih->data->lines.sizes[lin] == 0)
+ continue;
+
+ y2 = y1 + ih->data->lines.sizes[lin];
+
+ /* If the cell is marked, then draw it with attenuation color */
+ marked = iupMatrixMarkCellGet(ih, lin, col, mark_cb, str);
+
+ iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, lin, col);
+
+ iMatrixDrawFrameRectCell(ih, lin, col, x1, x2, y1, y2, framecolor, str);
+
+ if (dropcheck_cb && dropcheck_cb(ih, lin, col) == IUP_DEFAULT)
+ {
+ drop = IMAT_COMBOBOX_W;
+ iMatrixDrawComboFeedback(ih, x2, y1, y2, active, framecolor);
+ }
+
+ /* draw the cell contents */
+ iMatrixDrawCellValue(ih, x1, x2-drop, y1, y2, alignment, marked, active, lin, col, draw_cb);
+
+ y1 = y2;
+ }
+
+ x1 = x2;
+ y1 = old_y1; /* must reset also y */
+ }
+}
+
+void iupMatrixDraw(Ihandle* ih, int update)
+{
+ if (!ih->data->first_redraw)
+ return;
+
+ if (ih->data->need_calcsize)
+ iupMatrixAuxCalcSizes(ih);
+
+ iMatrixDrawMatrix(ih);
+
+ if (update)
+ iupMatrixDrawUpdate(ih);
+}
+
+void iupMatrixDrawUpdate(Ihandle* ih)
+{
+ cdCanvasFlush(ih->data->cddbuffer);
+
+ if (ih->data->has_focus)
+ iMatrixDrawFocus(ih);
+}
+
+int iupMatrixDrawSetRedrawAttrib(Ihandle* ih, const char* value)
+{
+ int type;
+
+ if (value == NULL)
+ type = 0;
+ else if(value[0] == 'L' || value[0] == 'l')
+ type = IMAT_PROCESS_LIN;
+ else if(value[0] == 'C' || value[0] == 'c')
+ type = IMAT_PROCESS_COL;
+ else
+ type = 0;
+
+ if (type)
+ {
+ int min = 0, max = 0;
+ value++;
+
+ if(iupStrToIntInt(value, &min, &max, ':') != 2)
+ max = min;
+
+ if (min > max)
+ return 0;
+
+ iupMatrixPrepareDrawData(ih);
+
+ if (ih->data->need_calcsize)
+ iupMatrixAuxCalcSizes(ih);
+
+ if (ih->data->lines.sizes[0] && ih->data->columns.sizes[0])
+ iMatrixDrawTitleCorner(ih);
+
+ if (type == IMAT_PROCESS_LIN)
+ {
+ iupMatrixDrawLineTitle(ih, min, max);
+ iupMatrixDrawCells(ih, min, ih->data->columns.first, max, ih->data->columns.last);
+ }
+ else
+ {
+ iupMatrixDrawColumnTitle(ih, min, max);
+ iupMatrixDrawCells(ih, ih->data->lines.first, min, ih->data->lines.last, max);
+ }
+ }
+ else
+ {
+ iupMatrixAuxCalcSizes(ih);
+ iMatrixDrawMatrix(ih);
+ }
+
+ iupMatrixDrawUpdate(ih);
+ return 0;
+}
diff --git a/iup/srccontrols/matrix/iupmat_draw.h b/iup/srccontrols/matrix/iupmat_draw.h
new file mode 100755
index 0000000..03337e7
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_draw.h
@@ -0,0 +1,31 @@
+/** \file
+ * \brief iupmatrix control
+ * draw functions.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_DRAW_H
+#define __IUPMAT_DRAW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2);
+void iupMatrixDrawColumnTitle(Ihandle* ih, int col1, int col2);
+void iupMatrixDrawLineTitle(Ihandle* ih, int lin1, int lin2);
+
+/* Render the visible cells and update display */
+void iupMatrixDraw(Ihandle* ih, int update);
+
+/* Update the display only */
+void iupMatrixDrawUpdate(Ihandle* ih);
+
+int iupMatrixDrawSetRedrawAttrib(Ihandle* ih, const char* value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_edit.c b/iup/srccontrols/matrix/iupmat_edit.c
new file mode 100755
index 0000000..a7e0a74
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_edit.c
@@ -0,0 +1,450 @@
+/** \file
+* \brief iupmatrix edit
+* Functions used to edit a node name in place.
+*
+* See Copyright Notice in "iup.h"
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupcontrols.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+#include "iup_childtree.h"
+
+#include "iupmat_def.h"
+#include "iupmat_scroll.h"
+#include "iupmat_aux.h"
+#include "iupmat_edit.h"
+#include "iupmat_key.h"
+#include "iupmat_getset.h"
+#include "iupmat_draw.h"
+
+
+static int iMatrixEditCallDropdownCb(Ihandle* ih, int lin, int col)
+{
+ IFnnii cb = (IFnnii)IupGetCallback(ih, "DROP_CB");
+ if(cb)
+ {
+ int ret;
+ char* value = iupMatrixCellGetValue(ih, lin, col);
+ if (!value) value = "";
+
+ iupAttribSetStr(ih->data->droph, "PREVIOUSVALUE", value);
+ IupSetAttribute(ih->data->droph, "VALUE", "1");
+
+ ret = cb(ih, ih->data->droph, lin, col);
+
+ /* check if the user set an invalid value */
+ if (IupGetInt(ih->data->droph, "VALUE") == 0)
+ IupSetAttribute(ih->data->droph, "VALUE", "1");
+
+ if(ret == IUP_DEFAULT)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int iMatrixEditDropDownAction_CB(Ihandle* ih, char* t, int i, int v)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniinsii cb = (IFniinsii)IupGetCallback(ih_matrix, "DROPSELECT_CB");
+ if(cb)
+ {
+ int ret = cb(ih_matrix, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, ih, t, i, v);
+
+ /* If the user returns IUP_CONTINUE in a dropselect_cb
+ the value is accepted and the matrix leaves edition mode. */
+ if (ret == IUP_CONTINUE)
+ {
+ iupMatrixEditHide(ih_matrix);
+ iupMatrixDrawUpdate(ih);
+ }
+ }
+
+ return IUP_DEFAULT;
+}
+
+static void iMatrixEditChooseElement(Ihandle* ih, int lin, int col)
+{
+ int drop = iMatrixEditCallDropdownCb(ih, lin, col);
+ if(drop)
+ ih->data->datah = ih->data->droph;
+ else
+ {
+ char* value;
+
+ ih->data->datah = ih->data->texth;
+
+ /* dropdown values are set by the user in DROP_CB.
+ text value is set here from cell contents. */
+ value = iupMatrixCellGetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (!value) value = "";
+ IupSetAttribute(ih->data->texth, "VALUE", value);
+ }
+}
+
+static int iMatrixEditCallEditionCb(Ihandle* ih, int mode, int update)
+{
+ int ret = iupMatrixAuxCallEditionCbLinCol(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, mode, update);
+
+ if (update && ret == IUP_DEFAULT && mode == 0) /* leaving edition mode */
+ iupMatrixCellUpdateValue(ih);
+
+ return ret;
+}
+
+static int iMatrixEditCancel(Ihandle* ih, int focus, int update, int ignore)
+{
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ {
+ int ret;
+
+ /* Avoid calling EDITION_CB twice. Usually because a killfocus. */
+ if (iupAttribGet(ih, "_IUPMAT_CALL_EDITION"))
+ return IUP_DEFAULT;
+
+ iupAttribSetStr(ih, "_IUPMAT_CALL_EDITION", "1");
+ ret = iMatrixEditCallEditionCb(ih, 0, update);
+ iupAttribSetStr(ih, "_IUPMAT_CALL_EDITION", NULL);
+
+ if (ret == IUP_IGNORE && ignore)
+ return IUP_IGNORE;
+
+ IupSetAttribute(ih->data->datah, "VISIBLE", "NO");
+ IupSetAttribute(ih->data->datah, "ACTIVE", "NO");
+
+ if (focus)
+ {
+ IupSetFocus(ih);
+ ih->data->has_focus = 1; /* set this so even if getfocus_cb is not called the focus is drawn */
+ }
+#ifdef SunOS
+ /* Usually when the edit control is hidden the matrix is automatically repainted by the system, except in SunOS. */
+ iupMatrixDrawUpdate(ih);
+#endif
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iMatrixEditKillFocus_CB(Ihandle* ih)
+{
+ Ihandle* ih_matrix = ih->parent;
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
+ {
+ if (iupAttribGet(ih_matrix, "_IUPMAT_DOUBLE_CLICK"))
+ return IUP_DEFAULT;
+ }
+
+ iupMatrixEditForceHidden(ih_matrix);
+ return IUP_DEFAULT;
+}
+
+int iupMatrixEditHide(Ihandle* ih)
+{
+ return iMatrixEditCancel(ih, 1, 1, 1); /* set focus + update + use ignore */
+}
+
+void iupMatrixEditForceHidden(Ihandle* ih)
+{
+ iMatrixEditCancel(ih, 0, 1, 0); /* no focus + update + no ignore */
+}
+
+int iupMatrixEditIsVisible(Ihandle* ih)
+{
+ if (!IupGetInt(ih, "ACTIVE"))
+ return 0;
+
+ if (!IupGetInt(ih->data->datah, "VISIBLE"))
+ return 0;
+
+ return 1;
+}
+
+int iupMatrixEditShow(Ihandle* ih)
+{
+ char* mask;
+ int w, h, x, y;
+
+ /* work around for Windows when using Multiline */
+ if (iupAttribGet(ih, "_IUPMAT_IGNORE_SHOW"))
+ {
+ iupAttribSetStr(ih, "_IUPMAT_IGNORE_SHOW", NULL);
+ return 0;
+ }
+
+ /* not active */
+ if(!IupGetInt(ih, "ACTIVE"))
+ return 0;
+
+ /* already visible */
+ if(IupGetInt(ih->data->datah, "VISIBLE"))
+ return 0;
+
+ /* notify application */
+ if (iMatrixEditCallEditionCb(ih, 1, 0) == IUP_IGNORE)
+ return 0;
+
+ /* select edit control */
+ iMatrixEditChooseElement(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+
+ /* position the cell to make it visible */
+ /* If the focus is not visible, a scroll is done for that the focus to be visible */
+ if (!iupMatrixAuxIsCellFullVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ iupMatrixScrollToVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+
+ /* set attributes */
+ iupMatrixPrepareDrawData(ih);
+ IupStoreAttribute(ih->data->datah, "BGCOLOR", iupMatrixGetBgColor(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ IupStoreAttribute(ih->data->datah, "FGCOLOR", iupMatrixGetFgColor(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ IupSetAttribute(ih->data->datah, "FONT", iupMatrixGetFont(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+
+ mask = IupMatGetAttribute(ih,"MASK", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (mask)
+ {
+ IupSetAttribute(ih->data->datah, "MASKCASEI", IupMatGetAttribute(ih,"MASKCASEI", ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ IupSetAttribute(ih->data->datah, "MASK", mask);
+ }
+ else
+ {
+ mask = IupMatGetAttribute(ih,"MASKINT", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (mask)
+ IupSetAttribute(ih->data->datah, "MASKINT", mask);
+ else
+ {
+ mask = IupMatGetAttribute(ih,"MASKFLOAT", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (mask)
+ IupSetAttribute(ih->data->datah, "MASKFLOAT", mask);
+ }
+ }
+
+ /* calc size */
+ iupMatrixAuxGetVisibleCellDim(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, &x, &y, &w, &h);
+
+ ih->data->datah->x = x;
+ ih->data->datah->y = y;
+ if (IupGetGlobal("GTKVERSION"))
+ {
+ /* In GTK, IupCanvas is not the actual container of the IupText/IupList */
+ ih->data->datah->x += ih->x;
+ ih->data->datah->y += ih->y;
+ }
+
+ ih->data->datah->currentwidth = w;
+ ih->data->datah->currentheight = h;
+ iupClassObjectLayoutUpdate(ih->data->datah);
+
+ /* activate and show */
+ IupSetAttribute(ih->data->datah, "ACTIVE", "YES");
+ IupSetAttribute(ih->data->datah, "VISIBLE", "YES");
+ IupSetFocus(ih->data->datah);
+
+ return 1;
+}
+
+static int iMatrixEditTextAction_CB(Ihandle* ih, int c, char* after)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniiiis cb = (IFniiiis) IupGetCallback(ih_matrix, "ACTION_CB");
+ if (cb && c!=0) /* only for valid characters */
+ {
+ int oldc = c;
+ c = cb(ih_matrix, c, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, 1, after);
+ if (c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if(c == IUP_DEFAULT)
+ c = oldc;
+ return c;
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iMatrixEditTextKeyAny_CB(Ihandle* ih, int c)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniiiis cb = (IFniiiis) IupGetCallback(ih_matrix, "ACTION_CB");
+ if (cb && c==0) /* only for other characters */
+ {
+ int oldc = c;
+ c = cb(ih_matrix, c, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, 1, IupGetAttribute(ih, "VALUE"));
+ if(c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if(c == IUP_DEFAULT)
+ c = oldc;
+ }
+
+ switch (c)
+ {
+ case K_cUP:
+ case K_cDOWN:
+ case K_cLEFT:
+ case K_cRIGHT:
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ break;
+ case K_UP:
+ if (IupGetInt(ih, "CARET") == 1)
+ {
+ /* if at the first line of the text */
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ break;
+ case K_DOWN:
+ {
+ char* value = IupGetAttribute(ih, "VALUE");
+ if (value)
+ {
+ /* if at the last line of the text */
+ if (iupStrLineCount(value) == IupGetInt(ih, "CARET"))
+ {
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ }
+ }
+ break;
+ case K_LEFT:
+ if (IupGetInt(ih, "CARETPOS") == 0)
+ {
+ /* if at the first character */
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ break;
+ case K_RIGHT:
+ {
+ char* value = IupGetAttribute(ih, "VALUE");
+ if (value)
+ {
+ /* if at the last character */
+ if ((int)strlen(value) == IupGetInt(ih, "CARETPOS"))
+ {
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ }
+ }
+ break;
+ case K_ESC:
+ iMatrixEditCancel(ih_matrix, 1, 0, 0); /* set focus + NO update + NO ignore */
+ return IUP_IGNORE;
+ case K_CR:
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Win32") && IupGetInt(ih, "MULTILINE"))
+ {
+ /* work around for Windows when using Multiline */
+ iupAttribSetStr(ih_matrix, "_IUPMAT_IGNORE_SHOW", "1");
+ }
+
+ if (iupMatrixAuxCallLeaveCellCb(ih_matrix) != IUP_IGNORE)
+ {
+ iupMatrixScrollKeyCr(ih_matrix);
+ iupMatrixAuxCallEnterCellCb(ih_matrix);
+ }
+ iupMatrixDrawUpdate(ih_matrix);
+ return IUP_IGNORE;
+ }
+ break;
+ }
+
+ return IUP_CONTINUE;
+}
+
+static int iMatrixEditDropDownKeyAny_CB(Ihandle* ih, int c)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniiiis cb = (IFniiiis)IupGetCallback(ih_matrix, "ACTION_CB");
+ if (cb)
+ {
+ int oldc = c;
+ c = cb(ih_matrix, c, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, 1, "");
+ if (c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if(c == IUP_DEFAULT)
+ c = oldc;
+ }
+
+ switch (c)
+ {
+ case K_CR:
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ if (iupMatrixAuxCallLeaveCellCb(ih_matrix) != IUP_IGNORE)
+ {
+ iupMatrixScrollKeyCr(ih_matrix);
+ iupMatrixAuxCallEnterCellCb(ih_matrix);
+ }
+ iupMatrixDrawUpdate(ih_matrix);
+ return IUP_IGNORE;
+ }
+ break;
+ case K_ESC:
+ iMatrixEditCancel(ih_matrix, 1, 0, 0); /* set focus + NO update + NO ignore */
+ return IUP_IGNORE;
+ }
+
+ return IUP_CONTINUE;
+}
+
+char* iupMatrixEditGetValue(Ihandle* ih)
+{
+ if (ih->data->datah == ih->data->droph)
+ return IupGetAttribute(ih->data->droph, IupGetAttribute(ih->data->droph, "VALUE"));
+ else
+ return IupGetAttribute(ih->data->texth, "VALUE");
+}
+
+void iupMatrixEditCreate(Ihandle* ih)
+{
+ /******** EDIT *************/
+ ih->data->texth = IupText(NULL);
+ iupChildTreeAppend(ih, ih->data->texth);
+
+ IupSetCallback(ih->data->texth, "ACTION", (Icallback)iMatrixEditTextAction_CB);
+ IupSetCallback(ih->data->texth, "K_ANY", (Icallback)iMatrixEditTextKeyAny_CB);
+ IupSetCallback(ih->data->texth, "KILLFOCUS_CB", (Icallback)iMatrixEditKillFocus_CB);
+ IupSetAttribute(ih->data->texth, "VALUE", "");
+ IupSetAttribute(ih->data->texth, "VISIBLE", "NO");
+ IupSetAttribute(ih->data->texth, "ACTIVE", "NO");
+
+
+ /******** DROPDOWN *************/
+ ih->data->droph = IupList(NULL);
+ iupChildTreeAppend(ih, ih->data->droph);
+
+ IupSetCallback(ih->data->droph, "ACTION", (Icallback)iMatrixEditDropDownAction_CB);
+ IupSetCallback(ih->data->droph, "KILLFOCUS_CB", (Icallback)iMatrixEditKillFocus_CB);
+ IupSetCallback(ih->data->droph, "K_ANY", (Icallback)iMatrixEditDropDownKeyAny_CB);
+ IupSetAttribute(ih->data->droph, "DROPDOWN", "YES");
+ IupSetAttribute(ih->data->droph, "MULTIPLE", "NO");
+ IupSetAttribute(ih->data->droph, "VISIBLE", "NO");
+ IupSetAttribute(ih->data->droph, "ACTIVE", "NO");
+}
diff --git a/iup/srccontrols/matrix/iupmat_edit.h b/iup/srccontrols/matrix/iupmat_edit.h
new file mode 100755
index 0000000..9a7815f
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_edit.h
@@ -0,0 +1,26 @@
+/** \file
+ * \brief iupmatrix.
+ * Functions used to edit a cell in place.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_EDIT_H
+#define __IUPMAT_EDIT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixEditIsVisible (Ihandle *ih);
+int iupMatrixEditShow (Ihandle* ih);
+int iupMatrixEditHide (Ihandle* ih);
+void iupMatrixEditForceHidden(Ihandle* ih);
+char* iupMatrixEditGetValue (Ihandle* ih);
+void iupMatrixEditCreate (Ihandle* ih);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_focus.c b/iup/srccontrols/matrix/iupmat_focus.c
new file mode 100755
index 0000000..3c000f8
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_focus.c
@@ -0,0 +1,58 @@
+/** \file
+ * \brief iupmatrix focus control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_aux.h"
+#include "iupmat_focus.h"
+#include "iupmat_draw.h"
+
+
+void iupMatrixFocusSet(Ihandle* ih, int lin, int col)
+{
+ ih->data->lines.focus_cell = lin;
+ ih->data->columns.focus_cell = col;
+}
+
+int iupMatrixFocus_CB(Ihandle* ih, int focus)
+{
+ int rc = IUP_DEFAULT;
+
+ if (!iupMatrixIsValid(ih, 1))
+ return IUP_DEFAULT;
+
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
+ {
+ if (focus && iupAttribGet(ih, "_IUPMAT_DOUBLE_CLICK"))
+ {
+ iupAttribSetStr(ih, "_IUPMAT_DOUBLE_CLICK", NULL);
+ return IUP_DEFAULT;
+ }
+ }
+
+ ih->data->has_focus = focus;
+ iupMatrixDrawUpdate(ih);
+
+ if (focus)
+ iupMatrixAuxCallEnterCellCb(ih);
+ else
+ iupMatrixAuxCallLeaveCellCb(ih);
+
+ return rc;
+}
+
+
diff --git a/iup/srccontrols/matrix/iupmat_focus.h b/iup/srccontrols/matrix/iupmat_focus.h
new file mode 100755
index 0000000..75f5894
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_focus.h
@@ -0,0 +1,21 @@
+/** \file
+ * \brief iupmatrix focus control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_FOCUS_H
+#define __IUPMAT_FOCUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixFocus_CB(Ihandle* ih, int focus);
+void iupMatrixFocusSet(Ihandle* ih, int lin, int col);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_getset.c b/iup/srccontrols/matrix/iupmat_getset.c
new file mode 100755
index 0000000..34947b6
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_getset.c
@@ -0,0 +1,358 @@
+/** \file
+ * \brief iupmatrix setget control
+ * attributes set and get
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_drvfont.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_childtree.h"
+
+#include "iupmat_def.h"
+#include "iupmat_getset.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+#include "iupmat_aux.h"
+
+
+int iupMatrixCheckCellPos(Ihandle* ih, int lin, int col)
+{
+ /* Check if the cell exists */
+ if ((lin < 0) || (col < 0) || (lin > ih->data->lines.num-1) || (col > ih->data->columns.num-1))
+ return 0;
+
+ return 1;
+}
+
+void iupMatrixCellSetValue(Ihandle* ih, int lin, int col, const char* value)
+{
+ if (ih->data->callback_mode)
+ return;
+
+ if (ih->data->cells[lin][col].value)
+ free(ih->data->cells[lin][col].value);
+
+ ih->data->cells[lin][col].value = iupStrDup(value);
+
+ if (lin==0 || col==0)
+ ih->data->need_calcsize = 1;
+}
+
+char* iupMatrixCellGetValue (Ihandle* ih, int lin, int col)
+{
+ if (!ih->handle)
+ {
+ char str[100];
+ sprintf(str, "%d:%d", lin, col);
+ return iupAttribGet(ih, str);
+ }
+ else
+ {
+ if (ih->data->callback_mode)
+ {
+ sIFnii value_cb = (sIFnii)IupGetCallback(ih, "VALUE_CB");
+ return value_cb(ih, lin, col);
+ }
+ else
+ return ih->data->cells[lin][col].value;
+ }
+}
+
+void iupMatrixCellSetFlag(Ihandle* ih, int lin, int col, unsigned char attr, int set)
+{
+ if (!ih->handle)
+ return;
+
+ if (lin==-1)
+ {
+ if ((col < 0) || (col > ih->data->columns.num-1))
+ return;
+
+ if (set)
+ ih->data->columns.flags[col] |= attr;
+ else
+ ih->data->columns.flags[col] &= ~attr;
+ }
+ else if (col == -1)
+ {
+ if ((lin < 0) || (lin > ih->data->lines.num-1))
+ return;
+
+ if (set)
+ ih->data->lines.flags[lin] |= attr;
+ else
+ ih->data->lines.flags[lin] &= ~attr;
+ }
+ else
+ {
+ if (!ih->data->callback_mode)
+ {
+ if ((lin < 0) || (col < 0) || (lin > ih->data->lines.num-1) || (col > ih->data->columns.num-1))
+ return;
+
+ if (set)
+ ih->data->cells[lin][col].flags |= attr;
+ else
+ ih->data->cells[lin][col].flags &= ~attr;
+ }
+ }
+}
+
+void iupMatrixCellUpdateValue(Ihandle* ih)
+{
+ IFniis value_edit_cb;
+ char *value = iupMatrixEditGetValue(ih);
+
+ iupMatrixCellSetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, value);
+
+ value_edit_cb = (IFniis)IupGetCallback(ih, "VALUE_EDIT_CB");
+ if (value_edit_cb)
+ value_edit_cb(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, value);
+
+ iupMatrixPrepareDrawData(ih);
+ iupMatrixDrawCells(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+}
+
+void iupMatrixPrepareDrawData(Ihandle* ih)
+{
+ /* FGCOLOR, BGCOLOR and FONT */
+ iupAttribStoreStr(ih, "_IUPMAT_BGCOLOR_PARENT", iupControlBaseGetParentBgColor(ih));
+ iupAttribStoreStr(ih, "_IUPMAT_BGCOLOR", IupGetAttribute(ih, "BGCOLOR"));
+ iupAttribStoreStr(ih, "_IUPMAT_FGCOLOR", IupGetAttribute(ih, "FGCOLOR"));
+ iupAttribStoreStr(ih, "_IUPMAT_FONT", IupGetAttribute(ih, "FONT"));
+
+ ih->data->bgcolor_parent = iupAttribGet(ih, "_IUPMAT_BGCOLOR_PARENT");
+ ih->data->bgcolor = iupAttribGet(ih, "_IUPMAT_BGCOLOR");
+ ih->data->fgcolor = iupAttribGet(ih, "_IUPMAT_FGCOLOR");
+ ih->data->font = iupAttribGet(ih, "_IUPMAT_FONT");
+
+ ih->data->font_cb = (sIFnii)IupGetCallback(ih, "FONT_CB");
+ ih->data->fgcolor_cb = (IFniiIII)IupGetCallback(ih, "FGCOLOR_CB");
+ ih->data->bgcolor_cb = (IFniiIII)IupGetCallback(ih, "BGCOLOR_CB");
+}
+
+static char* iMatrixGetCellAttrib(Ihandle* ih, unsigned char attr, int lin, int col, int native_parent)
+{
+ char* value = NULL;
+ char attrib_id[100];
+ const char* attrib = NULL;
+ char* attrib_global = NULL;
+
+ if (attr == IUPMAT_FONT)
+ {
+ attrib = "FONT";
+ attrib_global = ih->data->font;
+ }
+ else if (attr == IUPMAT_BGCOLOR)
+ {
+ attrib = "BGCOLOR";
+ attrib_global = ih->data->bgcolor;
+ }
+ else if (attr == IUPMAT_FGCOLOR)
+ {
+ attrib = "FGCOLOR";
+ attrib_global = ih->data->fgcolor;
+ }
+
+ /* 1 - check for this cell */
+ if (ih->data->callback_mode || ih->data->cells[lin][col].flags & attr)
+ {
+ sprintf(attrib_id, "%s%d:%d", attrib, lin, col);
+ value = iupAttribGet(ih, attrib_id);
+ }
+ if (!value)
+ {
+ /* 2 - check for this line, if not title col */
+ if (col != 0)
+ {
+ if (ih->data->lines.flags[lin] & attr)
+ {
+ sprintf(attrib_id, "%s%d:*", attrib, lin);
+ value = iupAttribGet(ih, attrib_id);
+ }
+ }
+
+ if (!value)
+ {
+ /* 3 - check for this column, if not title line */
+ if (lin != 0)
+ {
+ if (ih->data->columns.flags[col] & attr)
+ {
+ sprintf(attrib_id,"%s*:%d", attrib, col);
+ value = iupAttribGet(ih, attrib_id);
+ }
+ }
+
+ if (!value)
+ {
+ /* 4 - check for the matrix or native parent */
+ if (native_parent)
+ value = ih->data->bgcolor_parent;
+ else
+ value = attrib_global;
+ }
+ }
+ }
+
+ return value;
+}
+
+static int iMatrixCallColorCB(Ihandle* ih, IFniiIII cb, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ int ir, ig, ib, ret;
+ ret = cb(ih, lin, col, &ir, &ig, &ib);
+ *r = iupBYTECROP(ir);
+ *g = iupBYTECROP(ig);
+ *b = iupBYTECROP(ib);
+ return ret;
+}
+
+char* iupMatrixGetFgColor(Ihandle* ih, int lin, int col)
+{
+ unsigned char r = 0, g = 0, b = 0;
+ /* called from Edit only */
+ if (!ih->data->fgcolor_cb || (iMatrixCallColorCB(ih, ih->data->fgcolor_cb, lin, col, &r, &g, &b) == IUP_IGNORE))
+ {
+ char* fgcolor = iMatrixGetCellAttrib(ih, IUPMAT_FGCOLOR, lin, col, 0);
+ if (!fgcolor)
+ {
+ if (lin ==0 || col == 0)
+ fgcolor = IupGetGlobal("DLGFGCOLOR");
+ else
+ fgcolor = IupGetGlobal("TXTFGCOLOR");
+ }
+ return fgcolor;
+ }
+ else
+ {
+ char* buffer = iupStrGetMemory(30);
+ sprintf(buffer, "%d %d %d", r, g, b);
+ return buffer;
+ }
+}
+
+void iupMatrixGetFgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ /* called from Draw only */
+ if (!ih->data->fgcolor_cb || (iMatrixCallColorCB(ih, ih->data->fgcolor_cb, lin, col, r, g, b) == IUP_IGNORE))
+ {
+ char* fgcolor = iMatrixGetCellAttrib(ih, IUPMAT_FGCOLOR, lin, col, 0);
+ if (!fgcolor)
+ {
+ if (lin ==0 || col == 0)
+ fgcolor = IupGetGlobal("DLGFGCOLOR");
+ else
+ fgcolor = IupGetGlobal("TXTFGCOLOR");
+ }
+ iupStrToRGB(fgcolor, r, g, b);
+ }
+}
+
+char* iupMatrixGetBgColor(Ihandle* ih, int lin, int col)
+{
+ unsigned char r = 0, g = 0, b = 0;
+ /* called from Edit only */
+ if (!ih->data->bgcolor_cb || (iMatrixCallColorCB(ih, ih->data->bgcolor_cb, lin, col, &r, &g, &b) == IUP_IGNORE))
+ {
+ int native_parent = 0;
+ if (lin == 0 || col == 0)
+ native_parent = 1;
+ return iMatrixGetCellAttrib(ih, IUPMAT_BGCOLOR, lin, col, native_parent);
+ }
+ else
+ {
+ char* buffer = iupStrGetMemory(30);
+ sprintf(buffer, "%d %d %d", r, g, b);
+ return buffer;
+ }
+}
+
+#define IMAT_DARKER(_x) (((_x)*9)/10)
+
+void iupMatrixGetBgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ /* called from Draw only */
+ if (!ih->data->bgcolor_cb || (iMatrixCallColorCB(ih, ih->data->bgcolor_cb, lin, col, r, g, b) == IUP_IGNORE))
+ {
+ int native_parent = 0;
+ if (lin == 0 || col == 0)
+ native_parent = 1;
+ iupStrToRGB(iMatrixGetCellAttrib(ih, IUPMAT_BGCOLOR, lin, col, native_parent), r, g, b);
+ if (native_parent)
+ {
+ int ir = IMAT_DARKER(*r), ig=IMAT_DARKER(*g), ib=IMAT_DARKER(*b); /* use a darker version of the background by 10% */
+ *r = iupBYTECROP(ir);
+ *g = iupBYTECROP(ig);
+ *b = iupBYTECROP(ib);
+ }
+ }
+}
+
+char* iupMatrixGetFont(Ihandle* ih, int lin, int col)
+{
+ char* font = NULL;
+ /* called from Draw and Edit only */
+ if (ih->data->font_cb)
+ font = ih->data->font_cb(ih, lin, col);
+ if (!font)
+ font = iMatrixGetCellAttrib(ih, IUPMAT_FONT, lin, col, 0);
+ return font;
+}
+
+char *iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels)
+{
+ char* str;
+ int size;
+ ImatLinColData *lincol_data;
+
+ if(m == IMAT_PROCESS_LIN)
+ lincol_data = &(ih->data->lines);
+ else
+ lincol_data = &(ih->data->columns);
+
+ if (index < 0 || index > lincol_data->num-1)
+ return NULL;
+
+ if (m == IMAT_PROCESS_LIN)
+ size = iupMatrixAuxGetLineHeight(ih, index);
+ else
+ size = iupMatrixAuxGetColumnWidth(ih, index);
+
+ str = iupStrGetMemory(100);
+
+ if (size)
+ {
+ /* remove the decoration added in iupMatrixAuxGet */
+ if (m == IMAT_PROCESS_COL)
+ size -= IMAT_PADDING_W + IMAT_FRAME_W;
+ else
+ size -= IMAT_PADDING_H + IMAT_FRAME_H;
+
+ if (!pixels)
+ {
+ int charwidth, charheight;
+ iupdrvFontGetCharSize(ih, &charwidth, &charheight);
+ if (m == IMAT_PROCESS_COL)
+ size = iupRASTER2WIDTH(size, charwidth);
+ else
+ size = iupRASTER2HEIGHT(size, charheight);
+ }
+ }
+
+ sprintf(str, "%d", size);
+ return str;
+}
diff --git a/iup/srccontrols/matrix/iupmat_getset.h b/iup/srccontrols/matrix/iupmat_getset.h
new file mode 100755
index 0000000..9ae3d07
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_getset.h
@@ -0,0 +1,37 @@
+/** \file
+ * \brief iupmatrix control
+ * attributes set and get.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_GETSET_H
+#define __IUPMAT_GETSET_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void iupMatrixCellSetValue(Ihandle* ih, int lin, int col, const char* value);
+char* iupMatrixCellGetValue(Ihandle* ih, int lin, int col);
+
+void iupMatrixCellSetFlag(Ihandle* ih, int lin, int col, unsigned char attr, int set);
+
+void iupMatrixPrepareDrawData(Ihandle* ih);
+char* iupMatrixGetFgColor(Ihandle* ih, int lin, int col);
+char* iupMatrixGetBgColor(Ihandle* ih, int lin, int col);
+char* iupMatrixGetFont (Ihandle* ih, int lin, int col);
+void iupMatrixGetBgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b);
+void iupMatrixGetFgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b);
+
+void iupMatrixCellUpdateValue(Ihandle* ih);
+
+char* iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels);
+
+int iupMatrixCheckCellPos(Ihandle* ih, int lin, int col);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_key.c b/iup/srccontrols/matrix/iupmat_key.c
new file mode 100755
index 0000000..ae9ed55
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_key.c
@@ -0,0 +1,229 @@
+/** \file
+ * \brief iupmatrix control
+ * keyboard control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to control keys in the matrix and in the text edition */
+/**************************************************************************/
+
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_scroll.h"
+#include "iupmat_focus.h"
+#include "iupmat_aux.h"
+#include "iupmat_getset.h"
+#include "iupmat_key.h"
+#include "iupmat_mark.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+
+
+int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+{
+ int ret = IUP_IGNORE; /* default for processed keys */
+
+ /* If the focus is not visible, a scroll is done for that the focus to be visible */
+ if (!iupMatrixAuxIsCellFullVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ iupMatrixScrollToVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+
+ switch (c)
+ {
+ case K_cHOME:
+ case K_sHOME:
+ case K_HOME:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyHome(ih);
+ ih->data->homekeycount++;
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_cEND:
+ case K_sEND:
+ case K_END:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyEnd(ih);
+ ih->data->endkeycount++;
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_sTAB:
+ case K_TAB:
+ return IUP_CONTINUE; /* do not redraw */
+
+ case K_cLEFT:
+ case K_sLEFT:
+ case K_LEFT:
+ if (iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyLeft(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_cRIGHT:
+ case K_sRIGHT:
+ case K_RIGHT:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyRight(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_cUP:
+ case K_sUP:
+ case K_UP:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyUp(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break ;
+
+ case K_cDOWN:
+ case K_sDOWN:
+ case K_DOWN:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyDown(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_sPGUP:
+ case K_PGUP:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyPgUp(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_sPGDN:
+ case K_PGDN:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyPgDown(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_F2:
+ case K_SP:
+ case K_CR:
+ case K_sCR:
+ if (iupMatrixEditShow(ih))
+ return IUP_IGNORE; /* do not redraw */
+ break;
+
+ case K_sDEL:
+ case K_DEL:
+ {
+ int lin, col;
+ char str[100];
+ IFnii mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+
+ iupMatrixPrepareDrawData(ih);
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (iupMatrixMarkCellGet(ih, lin, col, mark_cb, str))
+ {
+ if (iupMatrixAuxCallEditionCbLinCol(ih, lin, col, 1, 1) != IUP_IGNORE)
+ {
+ IFniis value_edit_cb;
+
+ iupMatrixCellSetValue(ih, lin, col, NULL);
+
+ value_edit_cb = (IFniis)IupGetCallback(ih, "VALUE_EDIT_CB");
+ if (value_edit_cb)
+ value_edit_cb(ih, lin, col, NULL);
+
+ iupMatrixDrawCells(ih, lin, col, lin, col);
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ /* if a valid character is pressed enter edition mode */
+ if (iup_isprint(c))
+ {
+ if (iupMatrixEditShow(ih))
+ {
+ if (ih->data->datah == ih->data->texth)
+ {
+ char value[2] = {0,0};
+ value[0] = (char)c;
+ IupStoreAttribute(ih->data->datah, "VALUE", value);
+ IupSetAttribute(ih->data->datah, "CARET", "2");
+ }
+ return IUP_IGNORE; /* do not redraw */
+ }
+ }
+ ret = IUP_DEFAULT; /* unprocessed keys */
+ break;
+ }
+
+ iupMatrixDrawUpdate(ih);
+ return ret;
+}
+
+void iupMatrixKeyResetHomeEndCount(Ihandle* ih)
+{
+ ih->data->homekeycount = 0;
+ ih->data->endkeycount = 0;
+}
+
+int iupMatrixKeyPress_CB(Ihandle* ih, int c, int press)
+{
+ int oldc = c;
+ IFniiiis cb;
+
+ if (!iupMatrixIsValid(ih, 1))
+ return IUP_DEFAULT;
+
+ if (!press)
+ return IUP_DEFAULT;
+
+ cb = (IFniiiis)IupGetCallback(ih, "ACTION_CB");
+ if (cb)
+ {
+ if (iup_isprint(c))
+ {
+ char value[2]={0,0};
+ value[0] = (char)c;
+ c = cb(ih, c, ih->data->lines.focus_cell, ih->data->columns.focus_cell, 0, value);
+ }
+ else
+ {
+ c = cb(ih, c, ih->data->lines.focus_cell, ih->data->columns.focus_cell, 0,
+ iupMatrixCellGetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ }
+
+ if (c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if (c == IUP_DEFAULT)
+ c = oldc;
+ }
+
+ if (c != K_HOME && c != K_sHOME)
+ ih->data->homekeycount = 0;
+ if (c != K_END && c != K_sEND)
+ ih->data->endkeycount = 0;
+
+ return iupMatrixProcessKeyPress(ih, c);
+}
diff --git a/iup/srccontrols/matrix/iupmat_key.h b/iup/srccontrols/matrix/iupmat_key.h
new file mode 100755
index 0000000..1062dd0
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_key.h
@@ -0,0 +1,23 @@
+/** \file
+ * \brief iupmatrix. keyboard control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_KEY_H
+#define __IUPMAT_KEY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixKeyPress_CB(Ihandle* ih, int c, int press);
+int iupMatrixProcessKeyPress(Ihandle* ih, int c);
+
+void iupMatrixKeyResetHomeEndCount(Ihandle* ih);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_mark.c b/iup/srccontrols/matrix/iupmat_mark.c
new file mode 100755
index 0000000..99aad32
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mark.c
@@ -0,0 +1,720 @@
+/** \file
+ * \brief iupmatrix control
+ * cell selection
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to cell selection (mark) */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_mark.h"
+#include "iupmat_getset.h"
+#include "iupmat_draw.h"
+
+
+static void iMatrixMarkLinSet(Ihandle* ih, int lin, int mark)
+{
+ /* called when MARKMODE=LIN */
+ if (mark==-1)
+ mark = !(ih->data->lines.flags[lin] & IUPMAT_MARK);
+
+ if (mark)
+ ih->data->lines.flags[lin] |= IUPMAT_MARK;
+ else
+ ih->data->lines.flags[lin] &= ~IUPMAT_MARK;
+}
+
+static void iMatrixMarkColSet(Ihandle* ih, int col, int mark)
+{
+ /* called when MARKMODE=COL */
+ if (mark==-1)
+ mark = !(ih->data->columns.flags[col] & IUPMAT_MARK);
+
+ if (mark)
+ ih->data->columns.flags[col] |= IUPMAT_MARK;
+ else
+ ih->data->columns.flags[col] &= ~IUPMAT_MARK;
+}
+
+static void iMatrixMarkCellSet(Ihandle* ih, int lin, int col, int mark, IFniii markedit_cb, IFnii mark_cb, char* str)
+{
+ /* called only when MARKMODE=CELL */
+ if (mark == -1)
+ mark = !iupMatrixMarkCellGet(ih, lin, col, mark_cb, str);
+
+ if (ih->data->callback_mode)
+ {
+ if (markedit_cb)
+ markedit_cb(ih, lin, col, mark);
+ else
+ {
+ sprintf(str, "MARK%d:%d", lin, col);
+ if (mark)
+ iupAttribSetStr(ih, str, "1");
+ else
+ iupAttribSetStr(ih, str, NULL);
+ }
+ }
+ else
+ {
+ if (mark)
+ ih->data->cells[lin][col].flags |= IUPMAT_MARK;
+ else
+ ih->data->cells[lin][col].flags &= ~IUPMAT_MARK;
+ }
+}
+
+int iupMatrixMarkCellGet(Ihandle* ih, int lin, int col, IFnii mark_cb, char* str)
+{
+ /* called independent from MARKMODE */
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ if (ih->data->callback_mode)
+ {
+ if (mark_cb)
+ return mark_cb(ih, lin, col);
+ else
+ {
+ int mark = 0;
+ char* value;
+ sprintf(str, "MARK%d:%d", lin, col);
+ value = iupAttribGet(ih, str);
+ iupStrToInt(value, &mark);
+ return mark;
+ }
+ }
+ else
+ return ih->data->cells[lin][col].flags & IUPMAT_MARK;
+ }
+ else
+ {
+ if (ih->data->lines.flags[lin] & IUPMAT_MARK || ih->data->columns.flags[col] & IUPMAT_MARK)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static void iMatrixMarkItem(Ihandle* ih, int lin1, int col1, int mark, IFniii markedit_cb, IFnii mark_cb, char* str)
+{
+ int lin, col;
+
+ if (ih->data->mark_full1 == IMAT_PROCESS_LIN)
+ {
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for (col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkCellSet(ih, lin1, col, mark, markedit_cb, mark_cb, str);
+ }
+ else
+ {
+ iMatrixMarkLinSet(ih, lin1, mark);
+ iupMatrixDrawLineTitle(ih, lin1, lin1);
+ }
+
+ iupMatrixDrawCells(ih, lin1, 1, lin1, ih->data->columns.num-1);
+ }
+ else if (ih->data->mark_full1 == IMAT_PROCESS_COL)
+ {
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkCellSet(ih, lin, col1, mark, markedit_cb, mark_cb, str);
+ }
+ else
+ {
+ iMatrixMarkColSet(ih, col1, mark);
+ iupMatrixDrawColumnTitle(ih, col1, col1);
+ }
+
+ iupMatrixDrawCells(ih, 1, col1, ih->data->lines.num-1, col1);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ iMatrixMarkCellSet(ih, lin1, col1, mark, markedit_cb, mark_cb, str);
+ iupMatrixDrawCells(ih, lin1, col1, lin1, col1);
+ }
+}
+
+static void iMatrixMarkBlock(Ihandle* ih, int lin1, int col1, int lin2, int col2, int mark, IFniii markedit_cb, IFnii mark_cb, char* str)
+{
+ int lin, col;
+
+ if (lin1 > lin2) {int t = lin1; lin1 = lin2; lin2 = t;}
+ if (col1 > col2) {int t = col1; col1 = col2; col2 = t;}
+
+ if (ih->data->mark_full1 == IMAT_PROCESS_LIN)
+ {
+ for(lin=lin1; lin<=lin2; lin++)
+ iMatrixMarkItem(ih, lin, 0, mark, markedit_cb, mark_cb, str);
+ }
+ else if(ih->data->mark_full1 == IMAT_PROCESS_COL)
+ {
+ for(col=col1; col<=col2; col++)
+ iMatrixMarkItem(ih, 0, col, mark, markedit_cb, mark_cb, str);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(lin=lin1; lin<=lin2; lin++)
+ {
+ for(col=col1; col<=col2; col++)
+ iMatrixMarkItem(ih, lin, col, mark, markedit_cb, mark_cb, str);
+ }
+ }
+}
+
+void iupMatrixMarkMouseBlock(Ihandle* ih, int lin2, int col2)
+{
+ /* called only when "shift" is pressed and MARKMULTIPLE=YES */
+ IFniii markedit_cb = NULL;
+ IFnii mark_cb = NULL;
+ char str[100];
+
+ iupMatrixPrepareDrawData(ih);
+
+ ih->data->mark_full2 = 0;
+
+ if (lin2 == 0 && col2 == 0)
+ return;
+ /* If it was pointing for a column title... */
+ else if (lin2 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_COL)
+ ih->data->mark_full2 = IMAT_PROCESS_COL;
+ }
+ /* If it was pointing for a line title... */
+ else if (col2 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_LIN)
+ ih->data->mark_full2 = IMAT_PROCESS_LIN;
+ }
+
+ /* if new block is not the same, does nothing */
+ if (ih->data->mark_full1 != ih->data->mark_full2)
+ return;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL && ih->data->callback_mode)
+ {
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ }
+
+ /* Unmark previous block */
+ if (ih->data->mark_lin1 != -1 && ih->data->mark_lin2 != -1 &&
+ ih->data->mark_col1 != -1 && ih->data->mark_col2 != -1)
+ iMatrixMarkBlock(ih, ih->data->mark_lin1, ih->data->mark_col1, ih->data->mark_lin2, ih->data->mark_col2, 0, markedit_cb, mark_cb, str);
+
+ ih->data->mark_lin2 = lin2;
+ ih->data->mark_col2 = col2;
+
+ /* Unmark new block */
+ iMatrixMarkBlock(ih, ih->data->mark_lin1, ih->data->mark_col1, ih->data->mark_lin2, ih->data->mark_col2, 1, markedit_cb, mark_cb, str);
+}
+
+void iupMatrixMarkMouseReset(Ihandle* ih)
+{
+ ih->data->mark_lin1 = -1;
+ ih->data->mark_col1 = -1;
+ ih->data->mark_lin2 = -1;
+ ih->data->mark_col2 = -1;
+
+ ih->data->mark_full1 = 0;
+ ih->data->mark_full2 = 0;
+}
+
+void iupMatrixMarkMouseItem(Ihandle* ih, int ctrl, int lin1, int col1)
+{
+ int mark = 1, mark_full_all, lin, col;
+ IFniii markedit_cb = NULL;
+ IFnii mark_cb = NULL;
+ char str[100];
+
+ iupMatrixMarkMouseReset(ih);
+ iupMatrixPrepareDrawData(ih);
+
+ if (!ih->data->mark_multiple || ih->data->mark_continuous || !ctrl)
+ {
+ iupMatrixMarkClearAll(ih, 1);
+ iupMatrixDraw(ih, 0);
+ }
+ else
+ mark = -1; /* toggle mark state */
+
+ ih->data->mark_full1 = 0;
+ mark_full_all = 0;
+
+ if (lin1 == 0 && col1 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode == IMAT_MARK_COL ||
+ ih->data->mark_mode == IMAT_MARK_LIN)
+ mark_full_all = 1;
+ }
+ /* If it was pointing for a column title... */
+ else if (lin1 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_COL)
+ ih->data->mark_full1 = IMAT_PROCESS_COL;
+ }
+ /* If it was pointing for a line title... */
+ else if (col1 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_LIN)
+ ih->data->mark_full1 = IMAT_PROCESS_LIN;
+ }
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL && ih->data->callback_mode)
+ {
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ }
+
+ if (mark_full_all)
+ {
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ char str[100];
+ for (col = 1; col < ih->data->columns.num; col++)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, mark_cb, str);
+ }
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_LIN)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkLinSet(ih, lin, mark);
+
+ iupMatrixDrawLineTitle(ih, 1, ih->data->lines.num-1);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_COL)
+ {
+ for (col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkColSet(ih, col, mark);
+
+ iupMatrixDrawColumnTitle(ih, 1, ih->data->columns.num-1);
+ }
+
+ iupMatrixDrawCells(ih, 1, 1, ih->data->lines.num-1, ih->data->columns.num-1);
+ }
+ else
+ iMatrixMarkItem(ih, lin1, col1, mark, markedit_cb, mark_cb, str);
+
+ ih->data->mark_lin1 = lin1;
+ ih->data->mark_col1 = col1;
+}
+
+static void iMatrixMarkAllLinCol(ImatLinColData *p, int mark)
+{
+ int i;
+ for(i = 1; i < p->num; i++)
+ {
+ if (mark)
+ p->flags[i] |= IUPMAT_MARK;
+ else
+ p->flags[i] &= ~IUPMAT_MARK;
+ }
+}
+
+void iupMatrixMarkClearAll(Ihandle* ih, int check)
+{
+ /* "!check" is used to clear all marks independent from MARKMODE */
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL || !check)
+ {
+ int lin, col;
+ IFniii markedit_cb = NULL;
+ char str[100];
+
+ if (check)
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkCellSet(ih, lin, col, 0, markedit_cb, NULL, str);
+ }
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_LIN || !check)
+ iMatrixMarkAllLinCol(&(ih->data->lines), 0);
+
+ if (ih->data->mark_mode & IMAT_MARK_COL || !check)
+ iMatrixMarkAllLinCol(&(ih->data->columns), 0);
+}
+
+int iupMatrixColumnIsMarked(Ihandle* ih, int col)
+{
+ if (col == 0 || /* Line titles are never marked... */
+ !(ih->data->mark_mode & IMAT_MARK_COL))
+ return 0;
+
+ return ih->data->columns.flags[col] & IUPMAT_MARK;
+}
+
+int iupMatrixLineIsMarked(Ihandle* ih, int lin)
+{
+ if (lin == 0 || /* Column titles are never marked... */
+ !(ih->data->mark_mode & IMAT_MARK_LIN))
+ return 0;
+
+ return ih->data->lines.flags[lin] & IUPMAT_MARK;
+}
+
+int iupMatrixSetMarkedAttrib(Ihandle* ih, const char* value)
+{
+ int lin, col, mark;
+ char str[100];
+ IFniii markedit_cb;
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return 0;
+
+ if (!value)
+ iupMatrixMarkClearAll(ih, 1);
+ else if (*value == 'C' || *value == 'c') /* columns */
+ {
+ if (ih->data->mark_mode == IMAT_MARK_LIN)
+ return 0;
+
+ value++; /* skip C mark */
+ if ((int)strlen(value) != ih->data->columns.num-1)
+ return 0;
+
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (*value++ == '1')
+ mark = 1;
+ else
+ mark = 0;
+
+ /* mark all the cells for that column */
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, NULL, str);
+ }
+ else
+ iMatrixMarkColSet(ih, col, mark);
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_LIN)
+ iMatrixMarkAllLinCol(&(ih->data->lines), 0);
+ }
+ else if (*value == 'L' || *value == 'l') /* lines */
+ {
+ if (ih->data->mark_mode == IMAT_MARK_COL)
+ return 0;
+
+ value++; /* skip L mark */
+ if ((int)strlen(value) != ih->data->lines.num-1)
+ return 0;
+
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ if (*value++ == '1')
+ mark = 1;
+ else
+ mark = 0;
+
+ /* Mark all the cells for that line */
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, NULL, str);
+ }
+ else
+ iMatrixMarkLinSet(ih, lin, mark);
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_COL)
+ iMatrixMarkAllLinCol(&(ih->data->columns), 0);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_CELL) /* cells */
+ {
+ if ((int)strlen(value) != (ih->data->lines.num-1)*(ih->data->columns.num-1))
+ return 0;
+
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (*value++ == '1')
+ mark = 1;
+ else
+ mark = 0;
+
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, NULL, str);
+ }
+ }
+ }
+
+ if (ih->handle)
+ iupMatrixDraw(ih, 1);
+
+ return 0;
+}
+
+char* iupMatrixGetMarkedAttrib(Ihandle* ih)
+{
+ int lin, col, size;
+ IFnii mark_cb;
+ char str[100];
+ char* p, *value = NULL;
+ int exist_mark = 0; /* Show if there is someone marked */
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return NULL;
+
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ size = (ih->data->lines.num-1) * (ih->data->columns.num-1) + 1;
+ value = iupStrGetMemory(size);
+ p = value;
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (iupMatrixMarkCellGet(ih, lin, col, mark_cb, str))
+ {
+ exist_mark = 1;
+ *p++ = '1';
+ }
+ else
+ *p++ = '0';
+ }
+ }
+ *p = 0;
+ }
+ else
+ {
+ int marked_lines = 0, marked_cols = 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_LINCOL) /* must find which format to return */
+ {
+ /* look for a marked column */
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (ih->data->columns.flags[col] & IUPMAT_MARK)
+ {
+ marked_cols = 1; /* at least one column is marked */
+ break;
+ }
+ }
+
+ if (!marked_cols)
+ marked_lines = 1;
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_LIN)
+ marked_lines = 1;
+ else if (ih->data->mark_mode == IMAT_MARK_COL)
+ marked_cols = 1;
+
+ if (marked_lines)
+ {
+ size = 1 + (ih->data->lines.num-1) + 1;
+ value = iupStrGetMemory(size);
+ p = value;
+
+ *p++ = 'L';
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ if (ih->data->lines.flags[lin] & IUPMAT_MARK)
+ {
+ exist_mark = 1;
+ *p++ = '1';
+ }
+ else
+ *p++ = '0';
+ }
+ *p = 0;
+ }
+ else if (marked_cols)
+ {
+ size = 1 + (ih->data->columns.num-1) + 1;
+ value = iupStrGetMemory(size);
+ p = value;
+
+ *p++ = 'C';
+
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (ih->data->columns.flags[col] & IUPMAT_MARK)
+ {
+ exist_mark = 1;
+ *p++ = '1';
+ }
+ else
+ *p++ = '0';
+ }
+ *p = 0;
+ }
+ }
+
+ return exist_mark? value: NULL;
+}
+
+int iupMatrixSetMarkAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0, col = 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return 0;
+
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ int mark;
+
+ if (lin == 0 || col == 0) /* title can NOT have a mark */
+ return 0;
+
+ mark = iupStrBoolean(value);
+
+ if (ih->data->callback_mode)
+ {
+ IFniii markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+ if (markedit_cb)
+ markedit_cb(ih, lin, col, mark);
+ else if (mark)
+ return 1; /* store the attribute */
+ }
+ else
+ {
+ if (mark)
+ ih->data->cells[lin][col].flags |= IUPMAT_MARK;
+ else
+ ih->data->cells[lin][col].flags &= ~IUPMAT_MARK;
+ }
+
+ if (ih->handle)
+ {
+ /* This assumes that the matrix has been draw completely previously */
+ iupMatrixPrepareDrawData(ih);
+ iupMatrixDrawCells(ih, lin, col, lin, col);
+ }
+ }
+ else
+ {
+ int mark = iupStrBoolean(value);
+
+ if (ih->data->mark_mode & IMAT_MARK_LIN && lin!=0)
+ {
+ if (mark)
+ ih->data->lines.flags[lin] |= IUPMAT_MARK;
+ else
+ ih->data->lines.flags[lin] &= ~IUPMAT_MARK;
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_COL && col!=0)
+ {
+ if (mark)
+ ih->data->columns.flags[col] |= IUPMAT_MARK;
+ else
+ ih->data->columns.flags[col] &= ~IUPMAT_MARK;
+ }
+
+ if (ih->handle)
+ {
+ /* This assumes that the matrix has been draw completely previously */
+ iupMatrixPrepareDrawData(ih);
+ iupMatrixDrawCells(ih, lin, col, lin, col);
+ }
+ }
+ }
+
+ return 0;
+}
+
+char* iupMatrixGetMarkAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin = 0, col = 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return "0";
+
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return NULL;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ if (lin == 0 || col == 0) /* title can NOT have a mark */
+ return NULL;
+
+ if (ih->data->callback_mode)
+ {
+ IFnii mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ if (mark_cb)
+ {
+ if (mark_cb(ih, lin, col))
+ return "1";
+ else
+ return "0";
+ }
+ else
+ return NULL; /* let check the hash table */
+ }
+ else
+ {
+ if (ih->data->cells[lin][col].flags & IUPMAT_MARK)
+ return "1";
+ else
+ return "0";
+ }
+ }
+ else
+ {
+ if (ih->data->mark_mode & IMAT_MARK_LIN && lin!=0 && ih->data->lines.flags[lin] & IUPMAT_MARK)
+ return "1";
+
+ if (ih->data->mark_mode & IMAT_MARK_COL && col!=0 && ih->data->columns.flags[col] & IUPMAT_MARK)
+ return "1";
+
+ return "0";
+ }
+ }
+
+ return NULL;
+}
diff --git a/iup/srccontrols/matrix/iupmat_mark.h b/iup/srccontrols/matrix/iupmat_mark.h
new file mode 100755
index 0000000..819916e
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mark.h
@@ -0,0 +1,42 @@
+/** \file
+ * \brief iupmatrix. cell selection.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_MARK_H
+#define __IUPMAT_MARK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Used to mark (or not mark) cells */
+#define IMAT_MARK_NO 0
+#define IMAT_MARK_LIN 1
+#define IMAT_MARK_COL 2
+#define IMAT_MARK_LINCOL 3
+#define IMAT_MARK_CELL 4
+
+int iupMatrixSetMarkedAttrib(Ihandle* ih, const char* value);
+char* iupMatrixGetMarkedAttrib(Ihandle* ih);
+char* iupMatrixGetMarkAttrib(Ihandle* ih, const char* name_id);
+int iupMatrixSetMarkAttrib(Ihandle* ih, const char* name_id, const char* value);
+
+void iupMatrixMarkClearAll(Ihandle* ih, int check);
+
+int iupMatrixMarkCellGet(Ihandle* ih, int lin, int col, IFnii mark_cb, char* str);
+
+int iupMatrixColumnIsMarked(Ihandle* ih, int col);
+int iupMatrixLineIsMarked (Ihandle* ih, int lin);
+
+void iupMatrixMarkMouseBlock(Ihandle* ih, int lin2, int col2);
+void iupMatrixMarkMouseItem(Ihandle* ih, int ctrl, int lin1, int col1);
+void iupMatrixMarkMouseReset(Ihandle* ih);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_mem.c b/iup/srccontrols/matrix/iupmat_mem.c
new file mode 100755
index 0000000..eebea7a
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mem.c
@@ -0,0 +1,319 @@
+/** \file
+ * \brief iupmatrix control memory allocation
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to allocate memory */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_mem.h"
+
+
+static void iMatrixGetInitialValues(Ihandle* ih)
+{
+ int lin, col;
+ char* value;
+ char attr[100];
+
+ for (lin=0; lin<ih->data->lines.num; lin++)
+ {
+ for (col=0; col<ih->data->columns.num; col++)
+ {
+ sprintf(attr, "%d:%d", lin, col);
+ value = iupAttribGet(ih, attr);
+ if (value)
+ {
+ /* get the initial value and remove it from the hash table */
+
+ if (*value)
+ ih->data->cells[lin][col].value = iupStrDup(value);
+
+ iupAttribSetStr(ih, attr, NULL);
+ }
+ }
+ }
+}
+
+void iupMatrixMemAlloc(Ihandle* ih)
+{
+ ih->data->lines.num_alloc = ih->data->lines.num;
+ if (ih->data->lines.num_alloc == 1)
+ ih->data->lines.num_alloc = 5;
+
+ ih->data->columns.num_alloc = ih->data->columns.num;
+ if (ih->data->columns.num_alloc == 1)
+ ih->data->columns.num_alloc = 5;
+
+ if (!ih->data->callback_mode)
+ {
+ int lin;
+
+ ih->data->cells = (ImatCell**)calloc(ih->data->lines.num_alloc, sizeof(ImatCell*));
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++)
+ ih->data->cells[lin] = (ImatCell*)calloc(ih->data->columns.num_alloc, sizeof(ImatCell));
+
+ iMatrixGetInitialValues(ih);
+ }
+
+ ih->data->lines.flags = (unsigned char*)calloc(ih->data->lines.num_alloc, sizeof(unsigned char));
+ ih->data->columns.flags = (unsigned char*)calloc(ih->data->columns.num_alloc, sizeof(unsigned char));
+ ih->data->lines.sizes = (int*)calloc(ih->data->lines.num_alloc, sizeof(int));
+ ih->data->columns.sizes = (int*)calloc(ih->data->columns.num_alloc, sizeof(int));
+}
+
+void iupMatrixMemRelease(Ihandle* ih)
+{
+ if (ih->data->cells)
+ {
+ int lin, col;
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++)
+ {
+ for (col = 0; col < ih->data->columns.num_alloc; col++)
+ {
+ ImatCell* cell = &(ih->data->cells[lin][col]);
+ if (cell->value)
+ {
+ free(cell->value);
+ cell->value = NULL;
+ }
+ }
+ free(ih->data->cells[lin]);
+ ih->data->cells[lin] = NULL;
+ }
+ free(ih->data->cells);
+ ih->data->cells = NULL;
+ }
+
+ if (ih->data->columns.flags)
+ {
+ free(ih->data->columns.flags);
+ ih->data->columns.flags = NULL;
+ }
+
+ if (ih->data->lines.flags)
+ {
+ free(ih->data->lines.flags);
+ ih->data->lines.flags = NULL;
+ }
+
+ if (ih->data->columns.sizes)
+ {
+ free(ih->data->columns.sizes);
+ ih->data->columns.sizes = NULL;
+ }
+
+ if (ih->data->lines.sizes)
+ {
+ free(ih->data->lines.sizes);
+ ih->data->lines.sizes = NULL;
+ }
+}
+
+void iupMatrixMemReAllocLines(Ihandle* ih, int old_num, int num, int base)
+{
+ int lin, col, end, diff_num, shift_num;
+
+ /* base is the first line where the change started */
+
+ /* If it doesn't have enough lines allocated, then allocate more space */
+ if (num > ih->data->lines.num_alloc) /* this also implicates that num>old_num */
+ {
+ int old_alloc = ih->data->lines.num_alloc;
+ ih->data->lines.num_alloc = num;
+
+ if (!ih->data->callback_mode)
+ {
+ ih->data->cells = (ImatCell**)realloc(ih->data->cells, ih->data->lines.num_alloc*sizeof(ImatCell*));
+
+ /* new space are allocated at the end, later we need to move the old data and clear the available space */
+ for(lin = old_alloc; lin < num; lin++)
+ ih->data->cells[lin] = (ImatCell*)calloc(ih->data->columns.num_alloc, sizeof(ImatCell));
+ }
+
+ ih->data->lines.sizes = (int*)realloc(ih->data->lines.sizes, ih->data->lines.num_alloc*sizeof(int));
+ ih->data->lines.flags = (unsigned char*)realloc(ih->data->lines.flags, ih->data->lines.num_alloc*sizeof(unsigned char));
+ }
+
+ if (old_num==num)
+ return;
+
+ if (num>old_num) /* ADD */
+ {
+ diff_num = num-old_num; /* size of the openned space */
+ shift_num = old_num-base; /* size of the data to be moved (base maximum is old_num) */
+ end = base+diff_num;
+
+ /* shift the old data, opening space for new data, from base to end */
+ /* do it in reverse order to avoid overlapping */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = shift_num-1; lin >= 0; lin--) /* all columns, shift_num lines */
+ memmove(ih->data->cells[lin+end], ih->data->cells[lin+base], ih->data->columns.num_alloc*sizeof(ImatCell));
+ memmove(ih->data->lines.sizes+end, ih->data->lines.sizes+base, shift_num*sizeof(int));
+ memmove(ih->data->lines.flags+end, ih->data->lines.flags+base, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the new space starting at base */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < diff_num; lin++) /* all columns, diff_num lines */
+ memset(ih->data->cells[lin+base], 0, ih->data->columns.num_alloc*sizeof(ImatCell));
+ memset(ih->data->lines.sizes+base, 0, diff_num*sizeof(int));
+ memset(ih->data->lines.flags+base, 0, diff_num*sizeof(unsigned char));
+ }
+ else /* DEL */
+ {
+ diff_num = old_num-num; /* size of the openned space */
+ shift_num = num-base; /* size of the data to be moved */
+ end = base+diff_num;
+
+ /* release memory from the opened space */
+ if (!ih->data->callback_mode)
+ {
+ for(lin = base; lin < end; lin++) /* all columns, base-end lines */
+ {
+ for (col = 0; col < ih->data->columns.num_alloc; col++)
+ {
+ ImatCell* cell = &(ih->data->cells[lin][col]);
+ if (cell->value)
+ {
+ free(cell->value);
+ cell->value = NULL;
+ }
+ cell->flags = 0;
+ }
+ }
+ }
+
+ /* move the old data to opened space from end to base */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < shift_num; lin++) /* all columns, shift_num lines */
+ memmove(ih->data->cells[lin+base], ih->data->cells[lin+end], ih->data->columns.num_alloc*sizeof(ImatCell));
+ memmove(ih->data->lines.sizes+base, ih->data->lines.sizes+end, shift_num*sizeof(int));
+ memmove(ih->data->lines.flags+base, ih->data->lines.flags+end, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the remaining space starting at num */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < diff_num; lin++) /* all columns, diff_num lines */
+ memset(ih->data->cells[lin+num], 0, ih->data->columns.num_alloc*sizeof(ImatCell));
+ memset(ih->data->lines.sizes+num, 0, diff_num*sizeof(int));
+ memset(ih->data->lines.flags+num, 0, diff_num*sizeof(unsigned char));
+ }
+}
+
+void iupMatrixMemReAllocColumns(Ihandle* ih, int old_num, int num, int base)
+{
+ int lin, col, end, diff_num, shift_num;
+
+ /* base is the first column where the change started */
+
+ /* If it doesn't have enough columns allocated, then allocate more space */
+ if (num > ih->data->columns.num_alloc) /* this also implicates that also num>old_num */
+ {
+ ih->data->columns.num_alloc = num;
+
+ /* new space are allocated at the end, later we need to move the old data and clear the available space */
+
+ if (!ih->data->callback_mode)
+ {
+ for(lin = 0; lin < ih->data->lines.num_alloc; lin++)
+ ih->data->cells[lin] = (ImatCell*)realloc(ih->data->cells[lin], ih->data->columns.num_alloc*sizeof(ImatCell));
+ }
+
+ ih->data->columns.sizes = (int*)realloc(ih->data->columns.sizes, ih->data->columns.num_alloc*sizeof(int));
+ ih->data->columns.flags = (unsigned char*)realloc(ih->data->columns.flags, ih->data->columns.num_alloc*sizeof(unsigned char));
+ }
+
+ if (old_num==num)
+ return;
+
+ if (num>old_num) /* ADD */
+ {
+ /* even if (old_num-base)>(num-old_num) memmove will correctly copy the memory */
+ /* then clear the openned space starting at base */
+
+ diff_num = num-old_num; /* size of the openned space */
+ shift_num = old_num-base; /* size of the data to be moved (base maximum is old_num) */
+ end = base+diff_num;
+
+ /* shift the old data, opening space for new data, from base to end */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, shift_num columns */
+ memmove(ih->data->cells[lin]+end, ih->data->cells[lin]+base, shift_num*sizeof(ImatCell));
+ memmove(ih->data->columns.sizes+end, ih->data->columns.sizes+base, shift_num*sizeof(int));
+ memmove(ih->data->columns.flags+end, ih->data->columns.flags+base, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the openned space starting at base */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, diff_num columns */
+ memset(ih->data->cells[lin]+base, 0, diff_num*sizeof(ImatCell));
+ memset(ih->data->columns.sizes+base, 0, diff_num*sizeof(int));
+ memset(ih->data->columns.flags+base, 0, diff_num*sizeof(unsigned char));
+ }
+ else /* DEL */
+ {
+ diff_num = old_num-num; /* size of the openned space */
+ shift_num = num-base; /* size of the data to be moved */
+ end = base+diff_num;
+
+ /* release memory from the opened space */
+ if (!ih->data->callback_mode)
+ {
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, base-end columns */
+ {
+ for(col = base; col < end; col++)
+ {
+ ImatCell* cell = &(ih->data->cells[lin][col]);
+ if (cell->value)
+ {
+ free(cell->value);
+ cell->value = NULL;
+ }
+ cell->flags = 0;
+ }
+ }
+ }
+
+ /* move the old data to opened space from end to base */
+ /* even if (num-base)>(old_num-num) memmove will correctly copy the memory */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, shift_num columns */
+ memmove(ih->data->cells[lin]+base, ih->data->cells[lin]+end, shift_num*sizeof(ImatCell));
+ memmove(ih->data->columns.sizes+base, ih->data->columns.sizes+end, shift_num*sizeof(int));
+ memmove(ih->data->columns.flags+base, ih->data->columns.flags+end, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the remaining space starting at num */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, diff_num columns */
+ memset(ih->data->cells[lin]+num, 0, diff_num*sizeof(ImatCell));
+ memset(ih->data->columns.sizes+num, 0, diff_num*sizeof(int));
+ memset(ih->data->columns.flags+num, 0, diff_num*sizeof(unsigned char));
+ }
+}
diff --git a/iup/srccontrols/matrix/iupmat_mem.h b/iup/srccontrols/matrix/iupmat_mem.h
new file mode 100755
index 0000000..05a047b
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mem.h
@@ -0,0 +1,24 @@
+/** \file
+ * \brief iupmatrix control
+ * memory allocation.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_MEM_H
+#define __IUPMAT_MEM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void iupMatrixMemAlloc(Ihandle* ih);
+void iupMatrixMemRelease(Ihandle* ih);
+void iupMatrixMemReAllocLines (Ihandle* ih, int old_num, int num, int base);
+void iupMatrixMemReAllocColumns(Ihandle* ih, int old_num, int num, int base);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_mouse.c b/iup/srccontrols/matrix/iupmat_mouse.c
new file mode 100755
index 0000000..33b5fe7
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mouse.c
@@ -0,0 +1,212 @@
+/** \file
+ * \brief iupmatrix control
+ * mouse events
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to handle mouse events */
+/**************************************************************************/
+
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_colres.h"
+#include "iupmat_aux.h"
+#include "iupmat_focus.h"
+#include "iupmat_mouse.h"
+#include "iupmat_key.h"
+#include "iupmat_mark.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+#include "iupmat_scroll.h"
+
+
+#define IMAT_DRAG_SCROLL_DELTA 5
+
+static void iMatrixMouseCallMoveCb(Ihandle* ih, int lin, int col)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "MOUSEMOVE_CB");
+ if (cb)
+ cb(ih, lin, col);
+}
+
+static int iMatrixMouseCallClickCb(Ihandle* ih, int press, int lin, int col, char* r)
+{
+ IFniis cb;
+
+ if (press)
+ cb = (IFniis)IupGetCallback(ih, "CLICK_CB");
+ else
+ cb = (IFniis)IupGetCallback(ih, "RELEASE_CB");
+
+ if (cb)
+ return cb(ih, lin, col, r);
+
+ return IUP_DEFAULT;
+}
+
+static void iMatrixMouseLeftPress(Ihandle* ih, int lin, int col, int shift, int ctrl, int dclick)
+{
+ if (dclick)
+ {
+ iupMatrixMarkMouseReset(ih);
+
+ if (lin==0 || col==0)
+ return;
+
+ /* if a double click NOT in the current cell */
+ if (lin != ih->data->lines.focus_cell || col != ih->data->columns.focus_cell)
+ {
+ /* leave the previous cell if the matrix previously had the focus */
+ if (ih->data->has_focus && iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ return;
+
+ iupMatrixFocusSet(ih, lin, col);
+
+ iupMatrixAuxCallEnterCellCb(ih);
+ }
+
+ if (iupMatrixEditShow(ih))
+ {
+ if(ih->data->datah == ih->data->droph)
+ IupSetAttribute(ih->data->datah, "SHOWDROPDOWN", "YES");
+
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
+ if(atoi(IupGetGlobal("MOTIFNUMBER")) < 2203) /* since OpenMotif version 2.2.3 this is not necessary */
+ iupAttribSetStr(ih, "_IUPMAT_DOUBLE_CLICK", "1");
+ }
+ }
+ else /* single click */
+ {
+ if (shift && ih->data->mark_multiple && ih->data->mark_mode != IMAT_MARK_NO)
+ {
+ iupMatrixMarkMouseBlock(ih, lin, col);
+ }
+ else
+ {
+ ih->data->leftpressed = 1;
+
+ if (lin>0 && col>0)
+ {
+ if (iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ return;
+
+ iupMatrixFocusSet(ih, lin, col);
+
+ /* process mark before EnterCell */
+ if (ih->data->mark_mode != IMAT_MARK_NO)
+ iupMatrixMarkMouseItem(ih, ctrl, lin, col);
+
+ iupMatrixAuxCallEnterCellCb(ih);
+ }
+ else
+ {
+ /* only process marks if at titles */
+ if (ih->data->mark_mode != IMAT_MARK_NO)
+ iupMatrixMarkMouseItem(ih, ctrl, lin, col);
+ }
+ }
+ }
+}
+
+int iupMatrixMouseButton_CB(Ihandle* ih, int b, int press, int x, int y, char* r)
+{
+ int lin=-1, col=-1;
+
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+
+ /* reset press state */
+ ih->data->leftpressed = 0;
+
+ if (press)
+ {
+ /* The edit Focus callback is not called when the user clicks in the parent canvas.
+ so we have to compensate that. */
+ iupMatrixEditForceHidden(ih);
+ ih->data->has_focus = 1;
+ }
+
+ iupMatrixAuxGetLinColFromXY(ih, x, y, &lin, &col);
+
+ if (b == IUP_BUTTON1)
+ {
+ if (press)
+ {
+ iupMatrixKeyResetHomeEndCount(ih);
+
+ if (iupMatrixColResStart(ih, x, y))
+ return IUP_DEFAULT; /* Resize of the width a of a column was started */
+
+ if (lin!=-1 && col!=-1)
+ iMatrixMouseLeftPress(ih, lin, col, isshift(r), iscontrol(r), isdouble(r));
+ }
+ else
+ {
+ if (iupMatrixColResIsResizing(ih)) /* If it was made a column resize, finish it */
+ iupMatrixColResFinish(ih, x);
+ }
+ }
+ else
+ iupMatrixMarkMouseReset(ih);
+
+ if (lin!=-1 && col!=-1)
+ {
+ if (iMatrixMouseCallClickCb(ih, press, lin, col, r) == IUP_IGNORE)
+ return IUP_DEFAULT;
+ }
+
+ iupMatrixDrawUpdate(ih);
+ return IUP_DEFAULT;
+}
+
+int iupMatrixMouseMove_CB(Ihandle* ih, int x, int y)
+{
+ int lin, col;
+
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+
+ if (ih->data->leftpressed && ih->data->mark_multiple && ih->data->mark_mode != IMAT_MARK_NO)
+ {
+ if ((x < ih->data->columns.sizes[0] || x < IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.first > 1))
+ iupMatrixScrollLeft(ih);
+ else if ((x > ih->data->w - IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.last < ih->data->columns.num-1))
+ iupMatrixScrollRight(ih);
+
+ if ((y < ih->data->lines.sizes[0] || y < IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.first > 1))
+ iupMatrixScrollUp(ih);
+ else if ((y > ih->data->h - IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.last < ih->data->lines.num-1))
+ iupMatrixScrollDown(ih);
+
+ if (iupMatrixAuxGetLinColFromXY(ih, x, y, &lin, &col))
+ {
+ iupMatrixMarkMouseBlock(ih, lin, col);
+ iupMatrixDrawUpdate(ih);
+
+ iMatrixMouseCallMoveCb(ih, lin, col);
+ }
+ return IUP_DEFAULT;
+ }
+ else if(iupMatrixColResIsResizing(ih)) /* Make a resize in a column size */
+ iupMatrixColResMove(ih, x);
+ else /* Change cursor when it is passed on a join involving column titles */
+ iupMatrixColResCheckChangeCursor(ih, x, y);
+
+ if (iupMatrixAuxGetLinColFromXY(ih, x, y, &lin, &col))
+ iMatrixMouseCallMoveCb(ih, lin, col);
+
+ return IUP_DEFAULT;
+}
diff --git a/iup/srccontrols/matrix/iupmat_mouse.h b/iup/srccontrols/matrix/iupmat_mouse.h
new file mode 100755
index 0000000..17a09ec
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mouse.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief iMatrixrix control
+ * mouse events.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_MOUSE_H
+#define __IUPMAT_MOUSE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixMouseButton_CB (Ihandle* ih, int b, int press, int x, int y, char* r);
+int iupMatrixMouseMove_CB (Ihandle* ih, int x, int y);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_numlc.c b/iup/srccontrols/matrix/iupmat_numlc.c
new file mode 100755
index 0000000..e48720a
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_numlc.c
@@ -0,0 +1,495 @@
+/** \file
+ * \brief iupmatrix control
+ * change number of columns or lines
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to change the number of lines and columns of the matrix, */
+/* after it has been created. */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_edit.h"
+#include "iupmat_mem.h"
+#include "iupmat_numlc.h"
+#include "iupmat_draw.h"
+
+
+static void iMatrixUpdateLineAttributes(Ihandle* ih, int base, int count, int add)
+{
+#define IMAT_NUM_ATTRIB_LINE 6
+#define IMAT_ATTRIB_LINE_ONLY 3
+ char* attrib_format[IMAT_NUM_ATTRIB_LINE] = {
+ "BGCOLOR%d:*",
+ "FGCOLOR%d:*",
+ "FONT%d:*",
+ "BGCOLOR%d:%d",
+ "FGCOLOR%d:%d",
+ "FONT%d:%d"};
+ char* attrib = iupStrGetMemory(100);
+ int a, lin, col;
+ char* value;
+
+ if (add) /* ADD */
+ {
+ /* copy the attributes of the moved cells, from base+count to num */
+ /* do it in reverse order to avoid overlapping */
+ /* then clear the new space starting from base to base+count */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_LINE; a++)
+ {
+ for(lin = ih->data->lines.num-1; lin >= base+count; lin--)
+ {
+ /* Update the line attributes */
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin-count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update the cell attribute */
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin-count, col);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(lin = base; lin < base+count; lin++)
+ {
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+ else /* DEL */
+ {
+ /* copy the attributes of the moved cells from base+count to base */
+ /* then clear the remaining space starting at num */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_LINE; a++)
+ {
+ for(lin = base; lin < ih->data->lines.num; lin++)
+ {
+ /* Update the line attributes */
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin+count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update each cell attribute */
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin+count, col);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(lin = ih->data->lines.num; lin < ih->data->lines.num+count; lin++)
+ {
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+}
+
+static void iMatrixUpdateColumnAttributes(Ihandle* ih, int base, int count, int add)
+{
+#define IMAT_NUM_ATTRIB_COL 7
+#define IMAT_ATTRIB_COL_ONLY 4
+ char* attrib_format[IMAT_NUM_ATTRIB_COL] = {
+ "ALIGNMENT%d",
+ "BGCOLOR*:%d",
+ "FGCOLOR*:%d",
+ "FONT*:%d",
+ "BGCOLOR%d:%d",
+ "FGCOLOR%d:%d",
+ "FONT%d:%d"};
+ char* attrib = iupStrGetMemory(100);
+ int a, col, lin;
+ char* value;
+
+ if (add) /* ADD */
+ {
+ /* update the attributes of the moved cells, from base+count to num */
+ /* do it in reverse order to avoid overlapping */
+ /* then clear the new space starting from base to base+count */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_COL; a++)
+ {
+ for(col = ih->data->columns.num-1; col >= base+count; col--)
+ {
+ /* Update the column attributes */
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col-count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib,attrib_format[a],col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update the cell attributes */
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col-count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(col = base; col < base+count; col++)
+ {
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+ else /* DEL */
+ {
+ /* copy the attributes of the moved cells from base+count to base */
+ /* then clear the remaining space starting at num */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_COL; a++)
+ {
+ for(col = base; col < ih->data->columns.num; col++)
+ {
+ /* Update the column attributes */
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col+count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update the cell attributes */
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col+count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(col = ih->data->columns.num; col < ih->data->columns.num+count; col++)
+ {
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+}
+
+static int iMatrixGetStartEnd(const char* value, int *base, int *count, int max, int del)
+{
+ int ret;
+
+ if (!value)
+ return 0;
+
+ *base = 0;
+ *count = 1;
+
+ ret = sscanf(value, "%d-%d", base, count);
+ if (ret <= 0 || ret > 2)
+ return 0;
+ if (ret == 1)
+ *count = 1;
+
+ if (*count <= 0)
+ return 0;
+
+ if (del)
+ {
+ if (*base <= 0) /* the first valid element is always 1 */
+ *base = 1;
+
+ /* when del, base can be at the last element */
+ if (*base > max-1)
+ *base = max-1;
+
+ /* when del, count must be inside the existant range */
+ if (*base + *count > max)
+ *count = max - *base;
+ }
+ else
+ {
+ (*base)++; /* add after the given index, so increment to position the base */
+
+ if (*base <= 0) /* the first valid element is always 1 */
+ *base = 1;
+
+ /* when add, base can be just after the last element but not more */
+ if (*base > max)
+ *base = max;
+
+ /* when add, count can be any positive value */
+ }
+
+ return 1;
+}
+
+
+/**************************************************************************/
+/* Exported functions */
+/**************************************************************************/
+
+int iupMatrixSetAddLinAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, lines_num = ih->data->lines.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, lines_num, 0))
+ return 0;
+
+ /* if the focus cell is after the inserted area */
+ if (ih->data->lines.focus_cell >= base)
+ {
+ /* leave of the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* move it to the same cell */
+ ih->data->lines.focus_cell += count;
+ }
+
+ iupMatrixMemReAllocLines(ih, lines_num, lines_num+count, base);
+
+ ih->data->lines.num += count;
+ ih->data->need_calcsize = 1;
+
+ if (base < lines_num) /* If before the last line. */
+ iMatrixUpdateLineAttributes(ih, base, count, 1);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetDelLinAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, lines_num = ih->data->lines.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, lines_num, 1))
+ return 0;
+
+ /* if the focus cell is after the removed area */
+ if (ih->data->lines.focus_cell >= base)
+ {
+ /* leave of the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* if the focus cell is inside the removed area */
+ if (ih->data->lines.focus_cell <= base+count-1)
+ ih->data->lines.focus_cell = base; /* move it to the first existant cell */
+ else
+ ih->data->lines.focus_cell -= count; /* move it to the same cell */
+ }
+
+ iupMatrixMemReAllocLines(ih, lines_num, lines_num-count, base);
+
+ ih->data->lines.num -= count;
+ ih->data->need_calcsize = 1;
+
+ if (ih->data->lines.focus_cell >= ih->data->lines.num)
+ ih->data->lines.focus_cell = ih->data->lines.num-1;
+ if (ih->data->lines.focus_cell <= 0)
+ ih->data->lines.focus_cell = 1;
+
+ if (base < lines_num) /* If before the last line. (always true when deleting) */
+ iMatrixUpdateLineAttributes(ih, base, count, 0);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetAddColAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, columns_num = ih->data->columns.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, columns_num, 0))
+ return 0;
+
+ /* if the focus cell is after the inserted area */
+ if (ih->data->columns.focus_cell >= base)
+ {
+ /* leave the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* move it to the same cell */
+ ih->data->columns.focus_cell += count;
+ }
+
+ iupMatrixMemReAllocColumns(ih, columns_num, columns_num+count, base);
+
+ ih->data->columns.num += count;
+ ih->data->need_calcsize = 1;
+
+ if (base < columns_num) /* If before the last column. */
+ iMatrixUpdateColumnAttributes(ih, base, count, 1);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetDelColAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, columns_num = ih->data->columns.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, columns_num, 1))
+ return 0;
+
+ /* if the focus cell is after the removed area */
+ if (ih->data->columns.focus_cell >= base)
+ {
+ /* leave the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* if the focus cell is inside the removed area */
+ if (ih->data->columns.focus_cell <= base+count-1)
+ ih->data->columns.focus_cell = base; /* move it to the first existant cell */
+ else
+ ih->data->columns.focus_cell -= count; /* move it to the same cell */
+ }
+
+ iupMatrixMemReAllocColumns(ih, columns_num, columns_num-count, base);
+
+ ih->data->columns.num -= count;
+ ih->data->need_calcsize = 1;
+
+ if (ih->data->columns.focus_cell >= ih->data->columns.num)
+ ih->data->columns.focus_cell = ih->data->columns.num-1;
+ if (ih->data->columns.focus_cell <= 0)
+ ih->data->columns.focus_cell = 1;
+
+ if (base < columns_num) /* If before the last column. (always true when deleting) */
+ iMatrixUpdateColumnAttributes(ih, base, count, 0);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetNumLinAttrib(Ihandle* ih, const char* value)
+{
+ int num = 0;
+ if (iupStrToInt(value, &num))
+ {
+ if (num < 0) num = 0;
+
+ num++; /* add room for title line */
+
+ /* can be set before map */
+ if (ih->handle)
+ {
+ int base; /* base is after the end */
+ if (num >= ih->data->lines.num) /* add or alloc */
+ base = ih->data->lines.num;
+ else
+ base = num;
+ iupMatrixMemReAllocLines(ih, ih->data->lines.num, num, base);
+ }
+
+ ih->data->lines.num = num;
+ ih->data->need_calcsize = 1;
+
+ if (ih->handle)
+ iupMatrixDraw(ih, 1);
+ }
+
+ return 0;
+}
+
+int iupMatrixSetNumColAttrib(Ihandle* ih, const char* value)
+{
+ int num = 0;
+ if (iupStrToInt(value, &num))
+ {
+ if (num < 0) num = 0;
+
+ num++; /* add room for title column */
+
+ /* can be set before map */
+ if (ih->handle)
+ {
+ int base; /* base is after the end */
+ if (num >= ih->data->columns.num) /* add or alloc */
+ base = ih->data->columns.num;
+ else
+ base = num;
+ iupMatrixMemReAllocColumns(ih, ih->data->columns.num, num, base);
+ }
+
+ ih->data->columns.num = num;
+ ih->data->need_calcsize = 1;
+
+ if (ih->handle)
+ iupMatrixDraw(ih, 1);
+ }
+
+ return 0;
+}
diff --git a/iup/srccontrols/matrix/iupmat_numlc.h b/iup/srccontrols/matrix/iupmat_numlc.h
new file mode 100755
index 0000000..df5e16f
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_numlc.h
@@ -0,0 +1,27 @@
+/** \file
+ * \brief iupmatrix. change number of collumns or lines.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_NUMLC_H
+#define __IUPMAT_NUMLC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixSetAddLinAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetDelLinAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetAddColAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetDelColAttrib(Ihandle* ih, const char* value);
+
+int iupMatrixSetNumLinAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetNumColAttrib(Ihandle* ih, const char* value);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_scroll.c b/iup/srccontrols/matrix/iupmat_scroll.c
new file mode 100755
index 0000000..24bbef2
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_scroll.c
@@ -0,0 +1,495 @@
+/** \file
+ * \brief iupmatrix control
+ * scrolling
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_scroll.h"
+#include "iupmat_focus.h"
+#include "iupmat_aux.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+
+
+/* Macros used by "dir" parameter of the iMatrixScrollLine and iMatrixScrollColumn functions */
+#define IMAT_SCROLL_LEFT 0
+#define IMAT_SCROLL_RIGHT 1
+#define IMAT_SCROLL_UP 2
+#define IMAT_SCROLL_DOWN 3
+
+
+/**************************************************************************/
+/* Private functions */
+/**************************************************************************/
+
+
+static int iMatrixScrollIsFullVisibleLast(ImatLinColData *p)
+{
+ int i, sum = 0;
+
+ for(i = p->first; i <= p->last; i++)
+ sum += p->sizes[i];
+
+ if (sum > p->visible_size)
+ return 0;
+ else
+ return 1;
+}
+
+/* Scroll columns/lines in the left/top side of the matriz until the last column/line is FULLY visible.
+ -> m : Define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL] */
+static void iMatrixScrollToVisible(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (index < p->first)
+ {
+ p->first = index;
+ return;
+ }
+ else if (index > p->last)
+ {
+ /* Increment the first column/line until the index is visible */
+ while(index > p->last && p->last != (p->num - 1))
+ {
+ p->first++;
+ iupMatrixAuxUpdateLast(p);
+ }
+ }
+
+ if (index == p->last)
+ {
+ /* must increment util the last is fully visible */
+ while(index == p->last && p->last != (p->num - 1) && !iMatrixScrollIsFullVisibleLast(p))
+ {
+ p->first++;
+ iupMatrixAuxUpdateLast(p);
+ }
+ }
+}
+
+/* Callback to report to the user which visualization area of
+ the matrix changed. */
+static void iMatrixScrollCallScrollTopCb(Ihandle* ih)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "SCROLLTOP_CB");
+ if (cb)
+ cb(ih, ih->data->lines.first, ih->data->columns.first);
+}
+
+static int iMatrixScrollGetNextNonEmpty(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ while(index < p->num && p->sizes[index] == 0)
+ index++;
+
+ if (index > p->num-1)
+ {
+ if (p->num == 1)
+ return 1;
+ else
+ return p->num-1;
+ }
+ else
+ return index;
+}
+
+static int iMatrixScrollGetPrevNonEmpty(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ while(index > 0 && p->sizes[index] == 0)
+ index--;
+
+ if (index < 1)
+ return 1;
+ else
+ return index;
+}
+
+static void iMatrixScrollSetFocusScrollToVisible(Ihandle* ih, int m, int index)
+{
+ if (m == IMAT_PROCESS_COL)
+ iupMatrixFocusSet(ih, ih->data->lines.focus_cell, index);
+ else
+ iupMatrixFocusSet(ih, index, ih->data->columns.focus_cell);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+}
+
+/**************************************************************************/
+/* Exported functions */
+/**************************************************************************/
+
+
+/* Move using the cells of matrix.
+ Receive as a parameter a pointer to a function that will make the work,
+ in fact. This is done to avoid a test to each of the manipulation cursor
+ functions, verifying if it is necessary to call or not the scroll
+ callback. This is only done here.
+ -> func - pointer to the function that will make the movement
+ -> mode - parameter passed to func, specify if the movement request is of
+ the scrollbar or the keyboard
+ -> pos - parameter passed to func, that will be the handle position function
+ of the scrollbar, returning the scrollbar thumb position...
+ if func is other function, this parameter will be ignored
+ -> m - parameter passed to func, specify which is the mode of operation:
+ lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollMoveCursor(iupMatrixScrollMoveF func, Ihandle* ih, int mode, float pos, int m)
+{
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
+
+ iupMatrixEditForceHidden(ih);
+
+ func(ih, mode, pos, m);
+
+ if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
+ {
+ if (ih->data->columns.first != old_columns_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+
+ if (ih->data->lines.first != old_lines_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iMatrixScrollCallScrollTopCb(ih);
+
+ iupMatrixDraw(ih, 0);
+ }
+}
+
+void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col)
+{
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
+
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, col);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, lin);
+
+ if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
+ {
+ if (ih->data->columns.first != old_columns_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+
+ if (ih->data->lines.first != old_lines_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iMatrixScrollCallScrollTopCb(ih);
+
+ iupMatrixDraw(ih, 1);
+ }
+}
+
+/* This function is called when the "home" key is pressed.
+ In the first time, go to the beginning of the line.
+ In the second time, go to the beginning of the page.
+ In the third time, go to the beginning of the matrix.
+ -> mode and pos : DO NOT USED.
+*/
+void iupMatrixScrollHome(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ if(ih->data->homekeycount == 0) /* go to the beginning of the line */
+ {
+ ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+ iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.first);
+ }
+ else if(ih->data->homekeycount == 1) /* go to the beginning of the visible page */
+ {
+ iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+ else if(ih->data->homekeycount == 2) /* go to the beginning of the matrix 1:1 */
+ {
+ ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+ ih->data->lines.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_LIN, 1);
+
+ iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+}
+
+/* This function is called when the "end" key is pressed.
+ In the first time, go to the end of the line.
+ In the second time, go to the end of the page.
+ In the third time, go to the end of the matrix.
+ -> mode and pos : DO NOT USED.
+*/
+void iupMatrixScrollEnd(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ if(ih->data->endkeycount == 0) /* go to the end of the line */
+ {
+ int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+ iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, last_col);
+ }
+ else if(ih->data->endkeycount == 1) /* go to the end of the visible page */
+ {
+ iupMatrixFocusSet(ih, ih->data->lines.last, ih->data->columns.last);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+ else if(ih->data->endkeycount == 2) /* go to the end of the matrix */
+ {
+ int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+ int last_lin = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_LIN, ih->data->lines.num-1);
+
+ iupMatrixFocusSet(ih, last_lin, last_col);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+}
+
+/* This function is called to move a cell to the left or up.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollLeftUp(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell-1);
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first-1);
+ }
+}
+
+/* This function is called to move a cell to the right or down.
+ -> mode : indicate if the command from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollRightDown(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetNextNonEmpty(ih, m, p->focus_cell+1);
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetNextNonEmpty(ih, m, p->first+1);
+ }
+}
+
+/* This function is called to move a page to the left or up.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgLeft) or columns (PgUp) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPgLeftUp(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell - (p->last - p->first));
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first - (p->last - p->first));
+ }
+}
+
+/* This function is called to move a page to the right or down.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgDown) or columns (PgRight) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPgRightDown(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, p->focus_cell + (p->last - p->first));
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first + (p->last - p->first));
+ }
+}
+
+void iupMatrixScrollCr(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ int oldlin = ih->data->lines.focus_cell;
+ int oldcol = ih->data->columns.focus_cell;
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ /* try the normal processing of next cell down */
+ iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN);
+
+ if(ih->data->lines.focus_cell == oldlin && ih->data->columns.focus_cell == oldcol)
+ {
+ /* If focus was not changed, it was because it is in the last line of the column.
+ Go to the next column of the same line. */
+ iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL);
+ }
+}
+
+/* This function is called when a drag is performed in the scrollbar.
+ -> x : scrollbar thumb position, value between 0 and 1
+ -> mode : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPos(Ihandle* ih, int mode, float pos, int m)
+{
+ int scroll_pos, index, vp;
+ float d;
+ ImatLinColData* p;
+ (void)mode;
+
+ if (m == IMAT_PROCESS_LIN)
+ {
+ p = &(ih->data->lines);
+ d = IupGetFloat(ih, "DY");
+ }
+ else
+ {
+ p = &(ih->data->columns);
+ d = IupGetFloat(ih, "DX");
+ }
+
+ if (p->num == 1)
+ {
+ p->first = 1;
+ return;
+ }
+
+ scroll_pos = (int)(pos * p->total_size + 0.5);
+
+ vp = 0;
+ for(index = 1; index < p->num; index++)
+ {
+ vp += p->sizes[index];
+ if (vp > scroll_pos)
+ break;
+ }
+
+ if (index == p->num)
+ {
+ if (p->num == 1)
+ index = 1;
+ else
+ index = p->num-1;
+ }
+
+ p->first = index;
+}
+
+int iupMatrixScroll_CB(Ihandle* ih, int action, float x, float y)
+{
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+
+ switch(action)
+ {
+ case IUP_SBUP : iupMatrixScrollUp(ih); break;
+ case IUP_SBDN : iupMatrixScrollDown(ih); break;
+ case IUP_SBPGUP : iupMatrixScrollPgUp(ih); break;
+ case IUP_SBPGDN : iupMatrixScrollPgDown(ih); break;
+ case IUP_SBRIGHT : iupMatrixScrollRight(ih); break;
+ case IUP_SBLEFT : iupMatrixScrollLeft(ih); break;
+ case IUP_SBPGRIGHT : iupMatrixScrollPgRight(ih); break;
+ case IUP_SBPGLEFT : iupMatrixScrollPgLeft(ih); break;
+ case IUP_SBPOSV : iupMatrixScrollPosVer(ih,y); break;
+ case IUP_SBPOSH : iupMatrixScrollPosHor(ih,x); break;
+ case IUP_SBDRAGV : iupMatrixScrollPosVer(ih,y); break;
+ case IUP_SBDRAGH : iupMatrixScrollPosHor(ih,x); break;
+ }
+
+ iupMatrixDrawUpdate(ih);
+
+ return IUP_DEFAULT;
+}
diff --git a/iup/srccontrols/matrix/iupmat_scroll.h b/iup/srccontrols/matrix/iupmat_scroll.h
new file mode 100755
index 0000000..582442b
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_scroll.h
@@ -0,0 +1,69 @@
+/** \file
+ * \brief iupmatrix control
+ * scrolling.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_SCROLL_H
+#define __IUPMAT_SCROLL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixScroll_CB(Ihandle* ih, int action, float x, float y);
+
+void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col);
+
+typedef void (*iupMatrixScrollMoveF)(Ihandle* ih, int mode, float pos, int m);
+void iupMatrixScrollMoveCursor(iupMatrixScrollMoveF func, Ihandle* ih, int mode, float pos, int m);
+
+/* Used only by the macros bellow */
+void iupMatrixScrollHome (Ihandle* ih, int, float, int);
+void iupMatrixScrollEnd (Ihandle* ih, int, float, int);
+void iupMatrixScrollLeftUp (Ihandle* ih, int, float, int);
+void iupMatrixScrollRightDown (Ihandle* ih, int, float, int);
+void iupMatrixScrollPgLeftUp (Ihandle* ih, int, float, int);
+void iupMatrixScrollPgRightDown(Ihandle* ih, int, float, int);
+void iupMatrixScrollPos (Ihandle* ih, int, float, int);
+void iupMatrixScrollCr (Ihandle* ih, int, float, int);
+
+/* Mode used to "walk" inside the matrix.
+ It shows if the movement request was from the scrollbar or from a key.
+ Possible values for the "mode" parameter of the iupMatrixScrollMoveCursor function.
+ */
+#define IMAT_SCROLLBAR 0
+#define IMAT_SCROLLKEY 1
+
+/* Macros to help during the call of iupMatrixScrollMoveCursor function */
+
+/* used in the keyboard processing module */
+#define iupMatrixScrollKeyHome(ih) iupMatrixScrollMoveCursor(iupMatrixScrollHome , ih, IMAT_SCROLLKEY, 0, 0)
+#define iupMatrixScrollKeyEnd(ih) iupMatrixScrollMoveCursor(iupMatrixScrollEnd , ih, IMAT_SCROLLKEY, 0, 0)
+#define iupMatrixScrollKeyPgUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyPgDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollKeyUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollKeyCr(ih) iupMatrixScrollMoveCursor(iupMatrixScrollCr , ih, IMAT_SCROLLKEY, 0, 0)
+
+/* Used by the scrollbar callback only */
+#define iupMatrixScrollUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollPgUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollPgLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollPgDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollPgRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollPosVer(ih, y) iupMatrixScrollMoveCursor(iupMatrixScrollPos , ih, IMAT_SCROLLBAR, y, IMAT_PROCESS_LIN)
+#define iupMatrixScrollPosHor(ih, x) iupMatrixScrollMoveCursor(iupMatrixScrollPos , ih, IMAT_SCROLLBAR, x, IMAT_PROCESS_COL)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmatrix.c b/iup/srccontrols/matrix/iupmatrix.c
new file mode 100755
index 0000000..20d618d
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmatrix.c
@@ -0,0 +1,980 @@
+/** \file
+ * \brief IupMatrix control core
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupcontrols.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_register.h"
+
+#include "iupmat_def.h"
+#include "iupmat_getset.h"
+#include "iupmat_scroll.h"
+#include "iupmat_aux.h"
+#include "iupmat_mem.h"
+#include "iupmat_mouse.h"
+#include "iupmat_focus.h"
+#include "iupmat_key.h"
+#include "iupmat_numlc.h"
+#include "iupmat_colres.h"
+#include "iupmat_mark.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+
+
+int iupMatrixIsValid(Ihandle* ih, int check_cells)
+{
+ if (!ih->data->cddbuffer)
+ return 0;
+ if (check_cells && ((ih->data->columns.num == 0) || (ih->data->lines.num == 0)))
+ return 0;
+ return 1;
+}
+
+static int iMatrixSetOriginAttrib(Ihandle* ih, const char* value)
+{
+ int lin = -1, col = -1;
+
+ /* Get the parameters. The '*' indicates that want to keep the table in
+ the same line or column */
+ if (iupStrToIntInt(value, &lin, &col, ':') != 2)
+ {
+ if (lin != -1)
+ col = ih->data->columns.first;
+ else if (col != -1)
+ lin = ih->data->lines.first;
+ else
+ return 0;
+ }
+
+ /* Check if the cell exists */
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ /* Can not be a title */
+ if((lin < 1) || (col < 1))
+ return 0;
+
+ ih->data->columns.first = col;
+ ih->data->lines.first = lin;
+
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+static int iMatrixSetShowAttrib(Ihandle* ih, const char* value)
+{
+ int lin = -1, col = -1;
+
+ /* Get the parameters. The '*' indicates that want to keep the table in
+ the same line or column */
+ if (iupStrToIntInt(value, &lin, &col, ':') != 2)
+ {
+ if (lin != -1)
+ col = ih->data->columns.first;
+ else if (col != -1)
+ lin = ih->data->lines.first;
+ else
+ return 0;
+ }
+
+ /* Check if the cell exists */
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ /* Can not be a title */
+ if((lin < 1) || (col < 1))
+ return 0;
+
+ if (!iupMatrixAuxIsCellFullVisible(ih, lin, col))
+ iupMatrixScrollToVisible(ih, lin, col);
+
+ return 0;
+}
+
+static char* iMatrixGetOriginAttrib(Ihandle* ih)
+{
+ char* val = iupStrGetMemory(100);
+ sprintf(val, "%d:%d", ih->data->lines.first, ih->data->columns.first);
+ return val;
+}
+
+static int iMatrixSetFocusCellAttrib(Ihandle* ih, const char* value)
+{
+ int lin = 0, col = 0;
+ if (iupStrToIntInt(value, &lin, &col, ':') == 2)
+ {
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ if (lin <= 0 || col <= 0) /* title can NOT have the focus */
+ return 0;
+ if (lin >= ih->data->lines.num || col >= ih->data->columns.num)
+ return 0;
+
+ iupMatrixFocusSet(ih, lin, col);
+
+ if (ih->data->cddbuffer)
+ iupMatrixDrawUpdate(ih);
+ }
+
+ return 0;
+}
+
+static char* iMatrixGetFocusCellAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(100);
+ sprintf(str, "%d:%d", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ return str;
+}
+
+static int iMatrixSetUseTitleSizeAttrib(Ihandle* ih, const char* value)
+{
+ /* can be set only before map */
+ if (ih->handle)
+ return 0;
+
+ if (iupStrBoolean(value))
+ ih->data->use_title_size = 1;
+ else
+ ih->data->use_title_size = 0;
+
+ return 0;
+}
+
+static char* iMatrixGetUseTitleSizeAttrib(Ihandle* ih)
+{
+ if (ih->data->use_title_size)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iMatrixSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ IupStoreAttribute(ih->data->datah, "VALUE", value);
+ else
+ iupMatrixCellSetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, value);
+ return 0;
+}
+
+static char* iMatrixGetValueAttrib(Ihandle* ih)
+{
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ return iupMatrixEditGetValue(ih);
+ else
+ return iupMatrixCellGetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+}
+
+static int iMatrixSetCaretAttrib(Ihandle* ih, const char* value)
+{
+ IupStoreAttribute(ih->data->texth, "CARET", value);
+ return 1;
+}
+
+static char* iMatrixGetCaretAttrib(Ihandle* ih)
+{
+ return IupGetAttribute(ih->data->texth, "CARET");
+}
+
+static int iMatrixSetSelectionAttrib(Ihandle* ih, const char* value)
+{
+ IupStoreAttribute(ih->data->texth, "SELECTION", value);
+ return 1;
+}
+
+static char* iMatrixGetSelectionAttrib(Ihandle* ih)
+{
+ return IupGetAttribute(ih->data->texth, "SELECTION");
+}
+
+static int iMatrixSetMultilineAttrib(Ihandle* ih, const char* value)
+{
+ IupStoreAttribute(ih->data->texth, "MULTILINE", value);
+ if (iupStrBoolean(value))
+ IupSetAttribute(ih->data->texth, "SCROLLBAR", "NO");
+ return 1;
+}
+
+static char* iMatrixGetMultilineAttrib(Ihandle* ih)
+{
+ return IupGetAttribute(ih->data->texth, "MULTILINE");
+}
+
+static char* iMatrixGetNumLinAttrib(Ihandle* ih)
+{
+ char* num = iupStrGetMemory(100);
+ sprintf(num, "%d", ih->data->lines.num-1);
+ return num;
+}
+
+static char* iMatrixGetNumColAttrib(Ihandle* ih)
+{
+ char* num = iupStrGetMemory(100);
+ sprintf(num, "%d", ih->data->columns.num-1);
+ return num;
+}
+
+static int iMatrixSetMarkModeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "CELL"))
+ ih->data->mark_mode = IMAT_MARK_CELL;
+ else if (iupStrEqualNoCase(value, "LIN"))
+ ih->data->mark_mode = IMAT_MARK_LIN;
+ else if (iupStrEqualNoCase(value, "COL"))
+ ih->data->mark_mode = IMAT_MARK_COL;
+ else if(iupStrEqualNoCase(value, "LINCOL"))
+ ih->data->mark_mode = IMAT_MARK_LINCOL;
+ else
+ ih->data->mark_mode = IMAT_MARK_NO;
+
+ if (ih->handle)
+ {
+ iupMatrixMarkClearAll(ih, 0);
+ iupMatrixDraw(ih, 1);
+ }
+ return 0;
+}
+
+static char* iMatrixGetMarkModeAttrib(Ihandle* ih)
+{
+ char* mark2str[] = {"NO", "LIN", "COL", "LINCOL", "CELL"};
+ return mark2str[ih->data->mark_mode];
+}
+
+static int iMatrixSetMarkAreaAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NOT_CONTINUOUS"))
+ ih->data->mark_continuous = 0;
+ else
+ ih->data->mark_continuous = 1;
+
+ if (ih->handle)
+ {
+ iupMatrixMarkClearAll(ih, 0);
+ iupMatrixDraw(ih, 1);
+ }
+ return 0;
+}
+
+static char* iMatrixGetMarkAreaAttrib(Ihandle* ih)
+{
+ if (ih->data->mark_continuous)
+ return "CONTINUOUS";
+ else
+ return "NOT_CONTINUOUS";
+}
+
+static int iMatrixSetMarkMultipleAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ ih->data->mark_multiple = 1;
+ else
+ ih->data->mark_multiple = 0;
+
+ if (ih->handle)
+ {
+ iupMatrixMarkClearAll(ih, 0);
+ iupMatrixDraw(ih, 1);
+ }
+ return 0;
+}
+
+static char* iMatrixGetMarkMultipleAttrib(Ihandle* ih)
+{
+ if (ih->data->mark_multiple)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iMatrixSetEditModeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ iupMatrixEditShow(ih);
+ else
+ {
+ iupMatrixEditHide(ih);
+ iupMatrixDrawUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetEditModeAttrib(Ihandle* ih)
+{
+ if (iupMatrixEditIsVisible(ih))
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iMatrixSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ iupBaseSetActiveAttrib(ih, value);
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+static int iMatrixSetWidthAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int col = 0;
+ if (iupStrToInt(name_id, &col))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetWidthAttrib(Ihandle* ih, const char* name_id)
+{
+ int col;
+ if (iupStrToInt(name_id, &col))
+ return iupMatrixGetSize(ih, col, IMAT_PROCESS_COL, 0);
+ return NULL;
+}
+
+static int iMatrixSetHeightAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0;
+ if (iupStrToInt(name_id, &lin))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetHeightAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin;
+ if (iupStrToInt(name_id, &lin))
+ return iupMatrixGetSize(ih, lin, IMAT_PROCESS_LIN, 0);
+ return NULL;
+}
+
+static int iMatrixSetRasterWidthAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int col = 0;
+ if (iupStrToInt(name_id, &col))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetRasterWidthAttrib(Ihandle* ih, const char* name_id)
+{
+ int col;
+ if (iupStrToInt(name_id, &col))
+ return iupMatrixGetSize(ih, col, IMAT_PROCESS_COL, 1);
+ return NULL;
+}
+
+static int iMatrixSetRasterHeightAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0;
+ if (iupStrToInt(name_id, &lin))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetRasterHeightAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin;
+ if (iupStrToInt(name_id, &lin))
+ return iupMatrixGetSize(ih, lin, IMAT_PROCESS_LIN, 1);
+ return NULL;
+}
+
+static char* iMatrixGetAlignmentAttrib(Ihandle* ih, const char* name_id)
+{
+ char* align;
+ char str[50];
+ sprintf(str, "ALIGNMENT%s", name_id);
+ align = iupAttribGet(ih, str);
+ if (!align)
+ {
+ int col;
+ if (iupStrToInt(name_id, &col))
+ {
+ if (col == 0)
+ return "ALEFT";
+ else
+ return "ACENTER";
+ }
+ }
+
+ return NULL;
+}
+
+static int iMatrixSetIdValueAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0, col = 0;
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (iupMatrixCheckCellPos(ih, lin, col))
+ iupMatrixCellSetValue(ih, lin, col, value);
+ }
+ return 0;
+}
+
+static char* iMatrixGetIdValueAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin, col;
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (iupMatrixCheckCellPos(ih, lin, col))
+ return iupMatrixCellGetValue(ih, lin, col);
+ }
+ return NULL;
+}
+
+static int iMatrixSetFlagsAttrib(Ihandle* ih, const char* name_id, const char* value, unsigned char attr)
+{
+ if (name_id[0]==0)
+ return 1;
+ if (name_id[0]=='*' && name_id[1]==':')
+ {
+ int col;
+ name_id += 2; /* skip '*' and ':' */
+ if (iupStrToInt(name_id, &col))
+ iupMatrixCellSetFlag(ih, -1, col, attr, value!=NULL);
+ }
+ else if (name_id[strlen(name_id)-1]=='*')
+ {
+ int lin;
+ if (iupStrToInt(name_id, &lin))
+ iupMatrixCellSetFlag(ih, lin, -1, attr, value!=NULL);
+ }
+ else
+ {
+ int lin, col;
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ iupMatrixCellSetFlag(ih, lin, col, attr, value!=NULL);
+ }
+ return 1;
+}
+
+static int iMatrixSetBgColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_BGCOLOR);
+}
+
+static int iMatrixSetFgColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FGCOLOR);
+}
+
+static int iMatrixSetFontAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FONT);
+}
+
+static int iMatrixSetFrameHorizColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ ih->data->checkframecolor = value!=NULL;
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FRAMEHCOLOR);
+}
+
+static int iMatrixSetFrameVertColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ ih->data->checkframecolor = value!=NULL;
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FRAMEVCOLOR);
+}
+
+static char* iMatrixGetFontAttrib(Ihandle* ih, const char* name_id)
+{
+ if (name_id[0]==0)
+ return iupGetFontAttrib(ih);
+ return NULL;
+}
+
+static char* iMatrixGetBgColorAttrib(Ihandle* ih, const char* name_id)
+{
+ if (name_id[0]==0)
+ {
+ /* check the hash table */
+ char *color = iupAttribGet(ih, "BGCOLOR");
+
+ /* If not defined return the default for normal cells */
+ if (!color)
+ color = IupGetGlobal("TXTBGCOLOR");
+
+ return color;
+ }
+ return NULL;
+}
+
+static char* iMatrixGetNumColVisibleAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(50);
+ sprintf(buffer, "%d", ih->data->columns.last - ih->data->columns.first);
+ return buffer;
+}
+
+static char* iMatrixGetNumLinVisibleAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(50);
+ sprintf(buffer, "%d", ih->data->lines.last - ih->data->lines.first);
+ return buffer;
+}
+
+static char* iMatrixGetMaskDataAttrib(Ihandle* ih)
+{
+ /* Used only by the OLD iupmask API */
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ return IupGetAttribute(ih->data->datah,"OLD_MASK_DATA");
+ else
+ return NULL;
+}
+
+
+/*****************************************************************************/
+/* Callbacks registered to the Canvas */
+/*****************************************************************************/
+
+
+static int iMatrixResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ iupMatrixEditForceHidden(ih);
+
+ ih->data->need_calcsize = 1;
+ iupMatrixDraw(ih, 0);
+
+ return IUP_DEFAULT;
+}
+
+static int iMatrixRedraw_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ if (!ih->data->first_redraw)
+ {
+ ih->data->first_redraw = 1;
+ iupMatrixDraw(ih, 0);
+ }
+
+ iupMatrixDrawUpdate(ih);
+
+ return IUP_DEFAULT;
+}
+
+
+/***************************************************************************/
+
+
+static int iMatrixCreateMethod(Ihandle* ih, void **params)
+{
+ if (params && params[0])
+ {
+ char* action_cb = (char*)params[0];
+ iupAttribStoreStr(ih, "ACTION_CB", action_cb);
+ }
+
+ /* free the data allocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "SCROLLBAR", "YES");
+ iupAttribSetStr(ih, "BORDER", "NO");
+ iupAttribSetStr(ih, "CURSOR", "IupMatrixCrossCursor");
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "ACTION", (Icallback)iMatrixRedraw_CB);
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iMatrixResize_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iupMatrixMouseButton_CB);
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iupMatrixMouseMove_CB);
+ IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iupMatrixKeyPress_CB);
+ IupSetCallback(ih, "FOCUS_CB", (Icallback)iupMatrixFocus_CB);
+ IupSetCallback(ih, "SCROLL_CB", (Icallback)iupMatrixScroll_CB);
+
+ /* Create the edit fields */
+ iupMatrixEditCreate(ih);
+
+ /* defaults */
+ ih->data->datah = ih->data->texth;
+ ih->data->mark_continuous = 1;
+ ih->data->columns.num = 1;
+ ih->data->lines.num = 1;
+ ih->data->need_calcsize = 1;
+ ih->data->lines.first = 1;
+ ih->data->columns.first = 1;
+ ih->data->lines.focus_cell = 1;
+ ih->data->columns.focus_cell = 1;
+ ih->data->mark_lin1 = -1;
+ ih->data->mark_col1 = -1;
+ ih->data->mark_lin2 = -1;
+ ih->data->mark_col2 = -1;
+ ih->data->use_title_size = 0;
+
+ return IUP_NOERROR;
+}
+
+static int iMatrixMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ if (IupGetCallback(ih, "VALUE_CB"))
+ {
+ ih->data->callback_mode = 1;
+
+ if (!IupGetCallback(ih, "VALUE_EDIT_CB"))
+ iupAttribSetStr(ih, "READONLY", "YES");
+ }
+
+ iupMatrixMemAlloc(ih);
+
+ return IUP_NOERROR;
+}
+
+static void iMatrixUnMapMethod(Ihandle* ih)
+{
+ if(ih->data->cddbuffer)
+ {
+ cdKillCanvas(ih->data->cddbuffer);
+ ih->data->cddbuffer = NULL;
+ }
+
+ if(ih->data->cdcanvas)
+ {
+ cdKillCanvas(ih->data->cdcanvas);
+ ih->data->cdcanvas = NULL;
+ }
+
+ iupMatrixMemRelease(ih);
+}
+
+static int iMatrixGetNaturalWidth(Ihandle* ih)
+{
+ int width = 0, num, col;
+
+ num = iupAttribGetInt(ih, "NUMCOL_VISIBLE")+1; /* include the title column */
+
+ if (iupAttribGetInt(ih, "NUMCOL_VISIBLE_LAST"))
+ {
+ int start = ih->data->columns.num - (num-1); /* title is computed apart */
+ if (start<1) start=1;
+ width += iupMatrixAuxGetColumnWidth(ih, 0); /* compute title */
+ for(col = start; col < ih->data->columns.num; col++)
+ width += iupMatrixAuxGetColumnWidth(ih, col);
+ }
+ else
+ {
+ if (num > ih->data->columns.num)
+ num = ih->data->columns.num;
+ for(col = 0; col < num; col++)
+ width += iupMatrixAuxGetColumnWidth(ih, col);
+ }
+
+ return width;
+}
+
+static int iMatrixGetNaturalHeight(Ihandle* ih)
+{
+ int height = 0, num, lin;
+
+ num = iupAttribGetInt(ih, "NUMLIN_VISIBLE")+1; /* include the title line */
+
+ if (iupAttribGetInt(ih, "NUMLIN_VISIBLE_LAST"))
+ {
+ int start = ih->data->lines.num - (num-1); /* title is computed apart */
+ if (start<1) start=1;
+ height += iupMatrixAuxGetLineHeight(ih, 0); /* compute title */
+ for(lin = start; lin < ih->data->lines.num; lin++)
+ height += iupMatrixAuxGetLineHeight(ih, lin);
+ }
+ else
+ {
+ if (num > ih->data->lines.num)
+ num = ih->data->lines.num;
+ for(lin = 0; lin < num; lin++)
+ height += iupMatrixAuxGetLineHeight(ih, lin);
+ }
+
+ return height;
+}
+
+static void iMatrixComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+{
+ int natural_w = 0, natural_h = 0;
+ (void)expand; /* unset if not a container */
+
+ if (!ih->handle)
+ ih->data->canvas.sb = iupBaseGetScrollbar(ih);
+
+ /* add scrollbar */
+ if (ih->data->canvas.sb)
+ {
+ int sb_size = iupdrvGetScrollbarSize();
+ if (ih->data->canvas.sb & IUP_SB_HORIZ)
+ natural_w += sb_size;
+ if (ih->data->canvas.sb & IUP_SB_VERT)
+ natural_h += sb_size;
+ }
+
+ *w = natural_w + iMatrixGetNaturalWidth(ih);
+ *h = natural_h + iMatrixGetNaturalHeight(ih);
+}
+
+static void iMatrixCreateCursor(void)
+{
+ Ihandle *imgcursor;
+ unsigned char matrx_img_cur_excel[15*15] =
+ {
+ 0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 1,1,1,1,1,2,2,2,2,1,1,1,1,1,0,
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
+ 1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,
+ 0,1,1,1,1,2,2,2,2,1,1,1,1,1,1,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ };
+
+ imgcursor = IupImage(15, 15, matrx_img_cur_excel);
+ IupSetAttribute(imgcursor, "0", "BGCOLOR");
+ IupSetAttribute(imgcursor, "1", "0 0 0");
+ IupSetAttribute(imgcursor, "2", "255 255 255");
+ IupSetAttribute(imgcursor, "HOTSPOT", "7:7"); /* Centered Hotspot */
+ IupSetHandle("IupMatrixCrossCursor", imgcursor);
+ IupSetHandle("matrx_img_cur_excel", imgcursor); /* for backward compatibility */
+}
+
+Iclass* iupMatrixGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "matrix";
+ ic->format = "A"; /* one optional callback name */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+ ic->has_attrib_id = 1; /* has attributes with IDs that must be parsed */
+
+ /* Class functions */
+ ic->Create = iMatrixCreateMethod;
+ ic->Map = iMatrixMapMethod;
+ ic->UnMap = iMatrixUnMapMethod;
+ ic->ComputeNaturalSize = iMatrixComputeNaturalSizeMethod;
+
+ /* Do not need to set base attributes because they are inherited from IupCanvas */
+
+ /* IupMatrix Callbacks */
+ /* --- Interaction --- */
+ iupClassRegisterCallback(ic, "ACTION_CB", "iiiis");
+ iupClassRegisterCallback(ic, "CLICK_CB", "iis");
+ iupClassRegisterCallback(ic, "RELEASE_CB", "iis");
+ iupClassRegisterCallback(ic, "MOUSEMOVE_CB", "ii");
+ iupClassRegisterCallback(ic, "ENTERITEM_CB", "ii");
+ iupClassRegisterCallback(ic, "LEAVEITEM_CB", "ii");
+ iupClassRegisterCallback(ic, "SCROLLTOP_CB", "ii");
+ /* --- Drawing --- */
+ iupClassRegisterCallback(ic, "BGCOLOR_CB", "iiIII");
+ iupClassRegisterCallback(ic, "FGCOLOR_CB", "iiIII");
+ iupClassRegisterCallback(ic, "FONT_CB", "ii=s");
+ iupClassRegisterCallback(ic, "DRAW_CB", "iiiiii");
+ iupClassRegisterCallback(ic, "DROPCHECK_CB", "ii");
+ /* --- Editing --- */
+ iupClassRegisterCallback(ic, "DROP_CB", "nii");
+ iupClassRegisterCallback(ic, "DROPSELECT_CB", "iinsii");
+ iupClassRegisterCallback(ic, "EDITION_CB", "iii");
+ /* --- Callback Mode --- */
+ iupClassRegisterCallback(ic, "VALUE_CB", "ii=s");
+ iupClassRegisterCallback(ic, "VALUE_EDIT_CB", "iis");
+ iupClassRegisterCallback(ic, "MARK_CB", "ii");
+ iupClassRegisterCallback(ic, "MARKEDIT_CB", "iii");
+
+ /* IupMatrix Attributes - CELL */
+ iupClassRegisterAttributeId(ic, "IDVALUE", iMatrixGetIdValueAttrib, iMatrixSetIdValueAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FOCUS_CELL", iMatrixGetFocusCellAttrib, iMatrixSetFocusCellAttrib, IUPAF_SAMEASSYSTEM, "1:1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* can be NOT mapped */
+ iupClassRegisterAttribute(ic, "VALUE", iMatrixGetValueAttrib, iMatrixSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "FGCOLOR", NULL, iMatrixSetFgColorAttrib, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttributeId(ic, "FONT", iMatrixGetFontAttrib, iMatrixSetFontAttrib, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttributeId(ic, "FRAMEHORIZCOLOR", NULL, iMatrixSetFrameHorizColorAttrib, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttributeId(ic, "FRAMEVERTCOLOR", NULL, iMatrixSetFrameVertColorAttrib, IUPAF_NOT_MAPPED);
+
+ /* IupMatrix Attributes - COLUMN */
+ iupClassRegisterAttributeId(ic, "ALIGNMENT", iMatrixGetAlignmentAttrib, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "SORTSIGN", NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - SIZE */
+ iupClassRegisterAttribute(ic, "NUMLIN", iMatrixGetNumLinAttrib, iupMatrixSetNumLinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMCOL", iMatrixGetNumColAttrib, iupMatrixSetNumColAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMLIN_VISIBLE", iMatrixGetNumLinVisibleAttrib, NULL, IUPAF_SAMEASSYSTEM, "3", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMCOL_VISIBLE", iMatrixGetNumColVisibleAttrib, NULL, IUPAF_SAMEASSYSTEM, "4", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMLIN_VISIBLE_LAST", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMCOL_VISIBLE_LAST", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "WIDTHDEF", NULL, NULL, IUPAF_SAMEASSYSTEM, "80", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "HEIGHTDEF", NULL, NULL, IUPAF_SAMEASSYSTEM, "8", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "WIDTH", iMatrixGetWidthAttrib, iMatrixSetWidthAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "HEIGHT", iMatrixGetHeightAttrib, iMatrixSetHeightAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "RASTERWIDTH", iMatrixGetRasterWidthAttrib, iMatrixSetRasterWidthAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "RASTERHEIGHT", iMatrixGetRasterHeightAttrib, iMatrixSetRasterHeightAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - MARK */
+ iupClassRegisterAttribute(ic, "MARKED", iupMatrixGetMarkedAttrib, iupMatrixSetMarkedAttrib, NULL, NULL, IUPAF_NO_INHERIT); /* noticed that MARKED must be mapped */
+ iupClassRegisterAttributeId(ic, "MARK", iupMatrixGetMarkAttrib, iupMatrixSetMarkAttrib, IUPAF_NO_INHERIT); /* noticed that for MARK the matrix must be mapped */
+ iupClassRegisterAttribute(ic, "MARK_MODE", iMatrixGetMarkModeAttrib, iMatrixSetMarkModeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARKMODE", iMatrixGetMarkModeAttrib, iMatrixSetMarkModeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AREA", iMatrixGetMarkAreaAttrib, iMatrixSetMarkAreaAttrib, IUPAF_SAMEASSYSTEM, "CONTINUOUS", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARKAREA", iMatrixGetMarkAreaAttrib, iMatrixSetMarkAreaAttrib, IUPAF_SAMEASSYSTEM, "CONTINUOUS", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MULTIPLE", iMatrixGetMarkMultipleAttrib, iMatrixSetMarkMultipleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARKMULTIPLE", iMatrixGetMarkMultipleAttrib, iMatrixSetMarkMultipleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - ACTION (only mapped) */
+ iupClassRegisterAttribute(ic, "ADDLIN", NULL, iupMatrixSetAddLinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DELLIN", NULL, iupMatrixSetDelLinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ADDCOL", NULL, iupMatrixSetAddColAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DELCOL", NULL, iupMatrixSetDelColAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ORIGIN", iMatrixGetOriginAttrib, iMatrixSetOriginAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOW", NULL, iMatrixSetShowAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "EDIT_MODE", iMatrixGetEditModeAttrib, iMatrixSetEditModeAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "REDRAW", NULL, iupMatrixDrawSetRedrawAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - EDITION */
+ iupClassRegisterAttribute(ic, "CARET", iMatrixGetCaretAttrib, iMatrixSetCaretAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTION", iMatrixGetSelectionAttrib, iMatrixSetSelectionAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MULTILINE", iMatrixGetMultilineAttrib, iMatrixSetMultilineAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "MASK", NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - GENERAL */
+ iupClassRegisterAttribute(ic, "USETITLESIZE", iMatrixGetUseTitleSizeAttrib, iMatrixSetUseTitleSizeAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FRAMECOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "100 100 100", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "READONLY", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "RESIZEMATRIX", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "HIDEFOCUS", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iMatrixSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttributeId(ic, "BGCOLOR", iMatrixGetBgColorAttrib, iMatrixSetBgColorAttrib, IUPAF_NOT_MAPPED);
+
+ /* IupMatrix Attributes - MASK */
+ iupClassRegisterAttribute(ic, "OLD_MASK_DATA", iMatrixGetMaskDataAttrib, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ if (!IupGetHandle("IupMatrixCrossCursor"))
+ iMatrixCreateCursor();
+
+ return ic;
+}
+
+
+/*****************************************************************************************************/
+
+
+Ihandle* IupMatrix(const char* action)
+{
+ void *params[2];
+ params[0] = (void*)action;
+ params[1] = NULL;
+ return IupCreatev("matrix", params);
+}
+
+void IupMatSetAttribute(Ihandle* ih, const char* a, int l, int c, char* v)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ IupSetAttribute(ih, attr, v);
+}
+
+void IupMatStoreAttribute(Ihandle* ih, const char* a, int l, int c, char* v)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ IupStoreAttribute(ih, attr, v);
+}
+
+char* IupMatGetAttribute(Ihandle* ih, const char* a, int l, int c)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ return IupGetAttribute(ih, attr);
+}
+
+int IupMatGetInt(Ihandle* ih, const char* a, int l, int c)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ return IupGetInt(ih, attr);
+}
+
+float IupMatGetFloat(Ihandle* ih, const char* a, int l, int c)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ return IupGetFloat(ih, attr);
+}
+
+void IupMatSetfAttribute(Ihandle* ih, const char* a, int l, int c, char* f, ...)
+{
+ static char v[SHRT_MAX];
+ char* attr = iupStrGetMemory(100);
+ va_list arglist;
+ sprintf(attr, "%s%d:%d", a, l, c);
+ va_start(arglist, f);
+ vsprintf(v, f, arglist);
+ va_end(arglist);
+ IupStoreAttribute(ih, attr, v);
+}