diff options
author | Pixel <pixel@nobis-crew.org> | 2009-11-04 11:56:41 -0800 |
---|---|---|
committer | Pixel <pixel@nobis-crew.org> | 2009-11-04 11:59:33 -0800 |
commit | d577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch) | |
tree | 590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /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')
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); +} |