1246 lines
32 KiB
C
1246 lines
32 KiB
C
|
/** \file
|
||
|
* \brief iupmatrix setget control
|
||
|
* attributes set and get
|
||
|
*
|
||
|
* See Copyright Notice in "iup.h"
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <memory.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_childtree.h"
|
||
|
#include "iup_image.h"
|
||
|
#include "iup_assert.h"
|
||
|
|
||
|
#include "iup_controls.h"
|
||
|
#include "iup_cdutil.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 (!iupMATRIX_CHECK_COL(ih, col) ||
|
||
|
!iupMATRIX_CHECK_LIN(ih, lin))
|
||
|
return 0;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void iupMatrixModifyValue(Ihandle* ih, int lin, int col, const char* value)
|
||
|
{
|
||
|
/* Called when modifying multiple cells in a sequence.
|
||
|
It is useful to support READONLY
|
||
|
and cell read-only by returning IUP_IGNORE.
|
||
|
Here is the only place where both mode=1 and update=1.
|
||
|
*/
|
||
|
if (iupMatrixAuxCallEditionCbLinCol(ih, lin, col, 1, 1) != IUP_IGNORE)
|
||
|
iupMatrixSetValue(ih, lin, col, value, -1); /* call value_edit_cb, but NO numeric conversion */
|
||
|
}
|
||
|
|
||
|
static char* iMatrixSetValueNumeric(Ihandle* ih, int lin, int col, const char* value, int convert)
|
||
|
{
|
||
|
double number;
|
||
|
int ret = iupStrToDoubleLocale(value, &number, IupGetAttribute(ih, "NUMERICDECIMALSYMBOL")); /* this will also check for global "DEFAULTDECIMALSYMBOL" */
|
||
|
if (ret)
|
||
|
{
|
||
|
IFniid setvalue_cb;
|
||
|
|
||
|
if (convert && ih->data->numeric_columns[col].unit_shown != ih->data->numeric_columns[col].unit)
|
||
|
number = ih->data->numeric_convert_func(number, ih->data->numeric_columns[col].quantity,
|
||
|
ih->data->numeric_columns[col].unit_shown, /* from */
|
||
|
ih->data->numeric_columns[col].unit); /* to */
|
||
|
|
||
|
setvalue_cb = (IFniid)IupGetCallback(ih, "NUMERICSETVALUE_CB");
|
||
|
if (setvalue_cb)
|
||
|
{
|
||
|
setvalue_cb(ih, lin, col, number);
|
||
|
return NULL;
|
||
|
}
|
||
|
else if (ret == 2 || (convert && ih->data->numeric_columns[col].unit_shown != ih->data->numeric_columns[col].unit))
|
||
|
{
|
||
|
/* only use the number if locale was set or a conversion occurred */
|
||
|
sprintf(ih->data->numeric_buffer_set, IUP_DOUBLE2STR, number);
|
||
|
value = ih->data->numeric_buffer_set;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (char*)value;
|
||
|
}
|
||
|
|
||
|
void iupMatrixSetValue(Ihandle* ih, int lin, int col, const char* value, int user_edited)
|
||
|
{
|
||
|
/* NOTICE: this function is NOT called before map */
|
||
|
char* old_value = NULL;
|
||
|
|
||
|
if (ih->data->undo_redo) old_value = iupMatrixGetValue(ih, lin, col);
|
||
|
|
||
|
if (lin != 0 && ih->data->sort_has_index)
|
||
|
lin = ih->data->sort_line_index[lin];
|
||
|
|
||
|
if (ih->data->undo_redo) iupAttribSetClassObjectId2(ih, "UNDOPUSHCELL", lin, col, old_value);
|
||
|
|
||
|
if (value && ih->data->numeric_columns && ih->data->numeric_columns[col].flags & IMAT_IS_NUMERIC)
|
||
|
{
|
||
|
value = iMatrixSetValueNumeric(ih, lin, col, value, user_edited == 1); /* convert only if interactively edited */
|
||
|
if (!value)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!ih->data->callback_mode)
|
||
|
{
|
||
|
if (ih->data->cells[lin][col].value)
|
||
|
free(ih->data->cells[lin][col].value);
|
||
|
|
||
|
ih->data->cells[lin][col].value = iupStrDup(value);
|
||
|
}
|
||
|
|
||
|
if (user_edited)
|
||
|
{
|
||
|
/* value_edit_cb called when value is "interactively" edited.
|
||
|
This is NOT called when L:C or VALUE attributes are set.
|
||
|
It works in normal mode and in callback mode. */
|
||
|
IFniis value_edit_cb = (IFniis)IupGetCallback(ih, "VALUE_EDIT_CB");
|
||
|
if (value_edit_cb)
|
||
|
value_edit_cb(ih, lin, col, (char*)value);
|
||
|
}
|
||
|
|
||
|
ih->data->need_redraw = 1;
|
||
|
if (lin == 0 || col == 0)
|
||
|
ih->data->need_calcsize = 1;
|
||
|
}
|
||
|
|
||
|
static char* iMatrixGetValueText(Ihandle* ih, int lin, int col)
|
||
|
{
|
||
|
char* value;
|
||
|
|
||
|
if (lin != 0 && ih->data->sort_has_index)
|
||
|
lin = ih->data->sort_line_index[lin];
|
||
|
|
||
|
if (ih->data->callback_mode)
|
||
|
{
|
||
|
/* only called in callback mode */
|
||
|
sIFnii value_cb = (sIFnii)IupGetCallback(ih, "VALUE_CB");
|
||
|
if (value_cb)
|
||
|
value = value_cb(ih, lin, col);
|
||
|
else
|
||
|
value = NULL; /* application error!!!! value_cb must exist */
|
||
|
}
|
||
|
else
|
||
|
value = ih->data->cells[lin][col].value;
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
double iupMatrixGetValueNumeric(Ihandle* ih, int lin, int col)
|
||
|
{
|
||
|
sIFniis translate_cb;
|
||
|
double number;
|
||
|
|
||
|
/* here lin!=0 */
|
||
|
|
||
|
char* value = iMatrixGetValueText(ih, lin, col);
|
||
|
|
||
|
translate_cb = (sIFniis)IupGetCallback(ih, "TRANSLATEVALUE_CB");
|
||
|
if (translate_cb)
|
||
|
value = translate_cb(ih, lin, col, value);
|
||
|
|
||
|
if (!value)
|
||
|
{
|
||
|
dIFnii getvalue_cb = (dIFnii)IupGetCallback(ih, "NUMERICGETVALUE_CB");
|
||
|
if (getvalue_cb)
|
||
|
number = getvalue_cb(ih, lin, col);
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!iupStrToDouble(value, &number))
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (ih->data->numeric_columns[col].unit_shown != ih->data->numeric_columns[col].unit)
|
||
|
number = ih->data->numeric_convert_func(number, ih->data->numeric_columns[col].quantity,
|
||
|
ih->data->numeric_columns[col].unit, /* from */
|
||
|
ih->data->numeric_columns[col].unit_shown); /* to */
|
||
|
|
||
|
return number;
|
||
|
}
|
||
|
|
||
|
char* iupMatrixGetValue(Ihandle* ih, int lin, int col)
|
||
|
{
|
||
|
char* value = iMatrixGetValueText(ih, lin, col);
|
||
|
|
||
|
/* no translation here */
|
||
|
|
||
|
if (!value && lin != 0 && ih->data->numeric_columns && ih->data->numeric_columns[col].flags & IMAT_IS_NUMERIC)
|
||
|
{
|
||
|
dIFnii getvalue_cb = (dIFnii)IupGetCallback(ih, "NUMERICGETVALUE_CB");
|
||
|
if (getvalue_cb)
|
||
|
{
|
||
|
/* no formatting and no conversion here */
|
||
|
double number = getvalue_cb(ih, lin, col);
|
||
|
sprintf(ih->data->numeric_buffer_get, IUP_DOUBLE2STR, number); /* maximum precision */
|
||
|
return ih->data->numeric_buffer_get;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
char* iupMatrixGetNumericFormatDef(Ihandle* ih)
|
||
|
{
|
||
|
char* format = iupAttribGet(ih, "NUMERICFORMATDEF");
|
||
|
if (!format)
|
||
|
{
|
||
|
int prec = IupGetInt(NULL, "DEFAULTPRECISION");
|
||
|
if (prec == 2)
|
||
|
format = "%.2f";
|
||
|
else
|
||
|
{
|
||
|
static char f[30];
|
||
|
sprintf(f, "%%.%df", prec);
|
||
|
format = f;
|
||
|
}
|
||
|
}
|
||
|
return format;
|
||
|
}
|
||
|
|
||
|
static char* iMatrixGetValueNumericTitle(Ihandle* ih, int col, const char* value)
|
||
|
{
|
||
|
char *format = NULL;
|
||
|
|
||
|
/* here lin==0 */
|
||
|
|
||
|
if (ih->data->numeric_columns[col].flags & IMAT_HAS_FORMATTITLE)
|
||
|
format = iupAttribGetId(ih, "NUMERICFORMATTITLE", col);
|
||
|
|
||
|
if (format)
|
||
|
{
|
||
|
char* unit_symbol = IupGetAttributeId(ih, "NUMERICUNITSYMBOLSHOWN", col);
|
||
|
if (unit_symbol)
|
||
|
{
|
||
|
if (value)
|
||
|
sprintf(ih->data->numeric_buffer_get, format, value, unit_symbol);
|
||
|
else
|
||
|
sprintf(ih->data->numeric_buffer_get, format, unit_symbol);
|
||
|
return ih->data->numeric_buffer_get;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (char*)value;
|
||
|
}
|
||
|
|
||
|
static char* iMatrixGetValueNumericFormatted(Ihandle* ih, int lin, int col, const char* value)
|
||
|
{
|
||
|
char *format = NULL;
|
||
|
double number;
|
||
|
|
||
|
/* here lin!=0 */
|
||
|
|
||
|
if (!value)
|
||
|
{
|
||
|
dIFnii getvalue_cb = (dIFnii)IupGetCallback(ih, "NUMERICGETVALUE_CB");
|
||
|
if (getvalue_cb)
|
||
|
number = getvalue_cb(ih, lin, col);
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!iupStrToDouble(value, &number))
|
||
|
return (char*)value;
|
||
|
}
|
||
|
|
||
|
if (ih->data->numeric_columns[col].unit_shown != ih->data->numeric_columns[col].unit)
|
||
|
number = ih->data->numeric_convert_func(number, ih->data->numeric_columns[col].quantity,
|
||
|
ih->data->numeric_columns[col].unit, /* from */
|
||
|
ih->data->numeric_columns[col].unit_shown); /* to */
|
||
|
|
||
|
if (ih->data->numeric_columns[col].flags & IMAT_HAS_FORMAT)
|
||
|
format = iupAttribGetId(ih, "NUMERICFORMAT", col);
|
||
|
|
||
|
if (format == NULL)
|
||
|
format = iupMatrixGetNumericFormatDef(ih);
|
||
|
|
||
|
iupStrPrintfDoubleLocale(ih->data->numeric_buffer_get, format, number, IupGetAttribute(ih, "NUMERICDECIMALSYMBOL")); /* this will also check for global "DEFAULTDECIMALSYMBOL" */
|
||
|
return ih->data->numeric_buffer_get;
|
||
|
}
|
||
|
|
||
|
char* iupMatrixGetValueDisplay(Ihandle* ih, int lin, int col)
|
||
|
{
|
||
|
/* NOTICE: this function CAN BE called before map */
|
||
|
if (!ih->handle)
|
||
|
return iupAttribGetId2(ih, "", lin, col);
|
||
|
else
|
||
|
{
|
||
|
sIFniis translate_cb;
|
||
|
|
||
|
char* value = iMatrixGetValueText(ih, lin, col);
|
||
|
|
||
|
translate_cb = (sIFniis)IupGetCallback(ih, "TRANSLATEVALUE_CB");
|
||
|
if (translate_cb)
|
||
|
value = translate_cb(ih, lin, col, value);
|
||
|
|
||
|
if (ih->data->numeric_columns && ih->data->numeric_columns[col].flags & IMAT_IS_NUMERIC)
|
||
|
{
|
||
|
if (lin == 0)
|
||
|
return iMatrixGetValueNumericTitle(ih, col, value);
|
||
|
else
|
||
|
return iMatrixGetValueNumericFormatted(ih, lin, col, value);
|
||
|
}
|
||
|
else
|
||
|
return value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void iupMatrixSetCellFlag(Ihandle* ih, int lin, int col, unsigned char attr, int set)
|
||
|
{
|
||
|
if (!ih->handle)
|
||
|
return;
|
||
|
|
||
|
if (lin == IUP_INVALID_ID)
|
||
|
{
|
||
|
if (!iupMATRIX_CHECK_COL(ih, col))
|
||
|
return;
|
||
|
|
||
|
if (set)
|
||
|
ih->data->columns.dt[col].flags |= attr;
|
||
|
else
|
||
|
ih->data->columns.dt[col].flags &= ~attr;
|
||
|
}
|
||
|
else if (col == IUP_INVALID_ID)
|
||
|
{
|
||
|
if (!iupMATRIX_CHECK_LIN(ih, lin))
|
||
|
return;
|
||
|
|
||
|
if (set)
|
||
|
ih->data->lines.dt[lin].flags |= attr;
|
||
|
else
|
||
|
ih->data->lines.dt[lin].flags &= ~attr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!ih->data->callback_mode)
|
||
|
{
|
||
|
if (!iupMATRIX_CHECK_COL(ih, col) ||
|
||
|
!iupMATRIX_CHECK_LIN(ih, lin))
|
||
|
return;
|
||
|
|
||
|
if (set)
|
||
|
ih->data->cells[lin][col].flags |= attr;
|
||
|
else
|
||
|
ih->data->cells[lin][col].flags &= ~attr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void iupMatrixPrepareDrawData(Ihandle* ih)
|
||
|
{
|
||
|
/* FGCOLOR, BGCOLOR and FONT */
|
||
|
iupAttribSetStr(ih, "_IUPMAT_BGCOLOR_PARENT", iupControlBaseGetParentBgColor(ih));
|
||
|
iupAttribSetStr(ih, "_IUPMAT_BGCOLOR", IupGetAttribute(ih, "BGCOLOR"));
|
||
|
iupAttribSetStr(ih, "_IUPMAT_FGCOLOR", IupGetAttribute(ih, "FGCOLOR"));
|
||
|
iupAttribSetStr(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");
|
||
|
|
||
|
{
|
||
|
unsigned char bg_r, bg_g, bg_b;
|
||
|
iupStrToRGB(ih->data->bgcolor, &bg_r, &bg_g, &bg_b);
|
||
|
ih->data->bgcolor_cd = cdEncodeColor(bg_r, bg_g, bg_b);
|
||
|
}
|
||
|
|
||
|
ih->data->font_cb = (sIFnii)IupGetCallback(ih, "FONT_CB");
|
||
|
ih->data->type_cb = (sIFnii)IupGetCallback(ih, "TYPE_CB");
|
||
|
ih->data->fgcolor_cb = (IFniiIII)IupGetCallback(ih, "FGCOLOR_CB");
|
||
|
ih->data->bgcolor_cb = (IFniiIII)IupGetCallback(ih, "BGCOLOR_CB");
|
||
|
}
|
||
|
|
||
|
static char* iMatrixGetCellAttribute(Ihandle* ih, unsigned char attr, int lin, int col, int *native_parent)
|
||
|
{
|
||
|
char* value = NULL;
|
||
|
const char* attrib = NULL;
|
||
|
char* attrib_global = NULL;
|
||
|
|
||
|
if (attr == IMAT_HAS_FONT)
|
||
|
{
|
||
|
attrib = "FONT";
|
||
|
attrib_global = ih->data->font;
|
||
|
}
|
||
|
else if (attr == IMAT_HAS_BGCOLOR)
|
||
|
{
|
||
|
attrib = "BGCOLOR";
|
||
|
attrib_global = ih->data->bgcolor;
|
||
|
}
|
||
|
else if (attr == IMAT_HAS_FGCOLOR)
|
||
|
{
|
||
|
attrib = "FGCOLOR";
|
||
|
attrib_global = ih->data->fgcolor;
|
||
|
}
|
||
|
else if (attr == IMAT_HAS_TYPE)
|
||
|
{
|
||
|
attrib = "TYPE";
|
||
|
attrib_global = NULL;
|
||
|
}
|
||
|
|
||
|
if (!attrib) /* Internal error */
|
||
|
return NULL;
|
||
|
|
||
|
/* 1 - check for this cell */
|
||
|
if (ih->data->callback_mode || ih->data->cells[lin][col].flags & attr)
|
||
|
value = iupAttribGetId2(ih, attrib, lin, col);
|
||
|
if (!value)
|
||
|
{
|
||
|
/* 2 - check for this line, if not title col */
|
||
|
if (col != 0)
|
||
|
{
|
||
|
if (ih->data->lines.dt[lin].flags & attr)
|
||
|
value = iupAttribGetId2(ih, attrib, lin, IUP_INVALID_ID);
|
||
|
}
|
||
|
|
||
|
if (!value)
|
||
|
{
|
||
|
/* 3 - check for this column, if not title line */
|
||
|
if (lin != 0)
|
||
|
{
|
||
|
if (ih->data->columns.dt[col].flags & attr)
|
||
|
value = iupAttribGetId2(ih, attrib, IUP_INVALID_ID, col);
|
||
|
}
|
||
|
|
||
|
if (!value)
|
||
|
{
|
||
|
/* 4 - check for the matrix or native parent */
|
||
|
if (native_parent && *native_parent == 1)
|
||
|
{
|
||
|
*native_parent = 2;
|
||
|
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 = 0, ig = 0, ib = 0, ret;
|
||
|
ret = cb(ih, lin, col, &ir, &ig, &ib);
|
||
|
if (ret != IUP_IGNORE)
|
||
|
{
|
||
|
*r = iupBYTECROP(ir);
|
||
|
*g = iupBYTECROP(ig);
|
||
|
*b = iupBYTECROP(ib);
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
char* iupMatrixGetFgColorStr(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 = iMatrixGetCellAttribute(ih, IMAT_HAS_FGCOLOR, lin, col, NULL);
|
||
|
if (!fgcolor)
|
||
|
{
|
||
|
if (lin == 0 || col == 0)
|
||
|
fgcolor = IupGetGlobal("DLGFGCOLOR");
|
||
|
else
|
||
|
fgcolor = IupGetGlobal("TXTFGCOLOR");
|
||
|
}
|
||
|
return fgcolor;
|
||
|
}
|
||
|
else
|
||
|
return iupStrReturnRGB(r, g, b);
|
||
|
}
|
||
|
|
||
|
/* Color attenuation factor in a marked cell, 20% darker */
|
||
|
#define IMAT_ATENUATION(_x) ((unsigned char)(((_x)*8)/10))
|
||
|
|
||
|
static void iMatrixAddMarkedAttenuation(Ihandle* ih, unsigned char *r, unsigned char *g, unsigned char *b)
|
||
|
{
|
||
|
char* hlcolor = iupAttribGetStr(ih, "HLCOLOR");
|
||
|
unsigned char hl_r, hl_g, hl_b;
|
||
|
if (iupStrToRGB(hlcolor, &hl_r, &hl_g, &hl_b))
|
||
|
{
|
||
|
unsigned char a = (unsigned char)iupAttribGetInt(ih, "HLCOLORALPHA");
|
||
|
*r = iupALPHABLEND(*r, hl_r, a);
|
||
|
*g = iupALPHABLEND(*g, hl_g, a);
|
||
|
*b = iupALPHABLEND(*b, hl_b, a);
|
||
|
}
|
||
|
|
||
|
*r = IMAT_ATENUATION(*r);
|
||
|
*g = IMAT_ATENUATION(*g);
|
||
|
*b = IMAT_ATENUATION(*b);
|
||
|
}
|
||
|
|
||
|
void iupMatrixGetFgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b, int marked, int active)
|
||
|
{
|
||
|
/* called from Draw only */
|
||
|
if (!ih->data->fgcolor_cb || (iMatrixCallColorCB(ih, ih->data->fgcolor_cb, lin, col, r, g, b) == IUP_IGNORE))
|
||
|
{
|
||
|
char* fgcolor = iMatrixGetCellAttribute(ih, IMAT_HAS_FGCOLOR, lin, col, NULL);
|
||
|
if (!fgcolor)
|
||
|
{
|
||
|
if (lin == 0 || col == 0)
|
||
|
fgcolor = IupGetGlobal("DLGFGCOLOR");
|
||
|
else
|
||
|
fgcolor = IupGetGlobal("TXTFGCOLOR");
|
||
|
}
|
||
|
iupStrToRGB(fgcolor, r, g, b);
|
||
|
}
|
||
|
|
||
|
if (marked)
|
||
|
iMatrixAddMarkedAttenuation(ih, r, g, b);
|
||
|
|
||
|
if (!active)
|
||
|
{
|
||
|
unsigned char bg_r, bg_g, bg_b;
|
||
|
cdDecodeColor(ih->data->bgcolor_cd, &bg_r, &bg_g, &bg_b);
|
||
|
iupImageColorMakeInactive(r, g, b, bg_r, bg_g, bg_b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void iupMatrixGetTypeRGB(Ihandle* ih, const char* color, unsigned char *r, unsigned char *g, unsigned char *b, int marked, int active)
|
||
|
{
|
||
|
/* called from Draw only */
|
||
|
iupStrToRGB(color, r, g, b);
|
||
|
|
||
|
if (marked)
|
||
|
iMatrixAddMarkedAttenuation(ih, r, g, b);
|
||
|
|
||
|
if (!active)
|
||
|
{
|
||
|
unsigned char bg_r, bg_g, bg_b;
|
||
|
cdDecodeColor(ih->data->bgcolor_cd, &bg_r, &bg_g, &bg_b);
|
||
|
iupImageColorMakeInactive(r, g, b, bg_r, bg_g, bg_b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char* iupMatrixGetBgColorStr(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 iMatrixGetCellAttribute(ih, IMAT_HAS_BGCOLOR, lin, col, &native_parent);
|
||
|
}
|
||
|
else
|
||
|
return iupStrReturnRGB(r, g, b);
|
||
|
}
|
||
|
|
||
|
#define IMAT_DARKER(_x) (((_x)*9)/10)
|
||
|
|
||
|
void iupMatrixGetBgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b, int marked, int active)
|
||
|
{
|
||
|
/* 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(iMatrixGetCellAttribute(ih, IMAT_HAS_BGCOLOR, lin, col, &native_parent), r, g, b);
|
||
|
if (native_parent == 2)
|
||
|
{
|
||
|
/* use a darker version of the background by 10% if got it from parent */
|
||
|
int ir = IMAT_DARKER(*r),
|
||
|
ig = IMAT_DARKER(*g),
|
||
|
ib = IMAT_DARKER(*b);
|
||
|
*r = iupBYTECROP(ir);
|
||
|
*g = iupBYTECROP(ig);
|
||
|
*b = iupBYTECROP(ib);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (marked)
|
||
|
iMatrixAddMarkedAttenuation(ih, r, g, b);
|
||
|
|
||
|
if (!active)
|
||
|
{
|
||
|
unsigned char bg_r, bg_g, bg_b;
|
||
|
cdDecodeColor(ih->data->bgcolor_cd, &bg_r, &bg_g, &bg_b);
|
||
|
iupImageColorMakeInactive(r, g, b, bg_r, bg_g, bg_b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char* iupMatrixGetMaskStr(Ihandle* ih, const char* name, int lin, int col)
|
||
|
{
|
||
|
char* value = iupAttribGetId2(ih, name, lin, col);
|
||
|
if (!value)
|
||
|
{
|
||
|
value = iupAttribGetId2(ih, name, lin, IUP_INVALID_ID);
|
||
|
if (!value)
|
||
|
value = iupAttribGetId2(ih, name, IUP_INVALID_ID, col);
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
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 = iMatrixGetCellAttribute(ih, IMAT_HAS_FONT, lin, col, NULL);
|
||
|
return font;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetType(Ihandle* ih, int lin, int col)
|
||
|
{
|
||
|
char* type = NULL;
|
||
|
/* called from Draw only */
|
||
|
if (ih->data->type_cb)
|
||
|
type = ih->data->type_cb(ih, lin, col);
|
||
|
if (!type)
|
||
|
type = iMatrixGetCellAttribute(ih, IMAT_HAS_TYPE, lin, col, NULL);
|
||
|
if (!type)
|
||
|
return IMAT_TYPE_TEXT;
|
||
|
|
||
|
if (iupStrEqualNoCase(type, "COLOR"))
|
||
|
return IMAT_TYPE_COLOR;
|
||
|
if (iupStrEqualNoCase(type, "IMAGE"))
|
||
|
return IMAT_TYPE_IMAGE;
|
||
|
if (iupStrEqualNoCase(type, "FILL"))
|
||
|
return IMAT_TYPE_FILL;
|
||
|
|
||
|
return IMAT_TYPE_TEXT;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetFrameHorizColor(Ihandle* ih, int lin, int col, long *framecolor, int check_title)
|
||
|
{
|
||
|
if ((ih->data->callback_mode || ih->data->cells[lin][col].flags & IMAT_HAS_FRAMEHORIZCOLOR) ||
|
||
|
ih->data->lines.dt[lin].flags & IMAT_HAS_FRAMEHORIZCOLOR)
|
||
|
{
|
||
|
char* color = NULL;
|
||
|
unsigned char r, g, b;
|
||
|
if (check_title && lin == 0)
|
||
|
{
|
||
|
color = iupAttribGetId2(ih, "FRAMETITLEHORIZCOLOR", 0, col);
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMETITLEHORIZCOLOR", 0, IUP_INVALID_ID);
|
||
|
}
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMEHORIZCOLOR", lin, col);
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMEHORIZCOLOR", lin, IUP_INVALID_ID);
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMEHORIZCOLOR", IUP_INVALID_ID, col);
|
||
|
if (iupStrEqual(color, "BGCOLOR"))
|
||
|
return 1;
|
||
|
if (iupStrToRGB(color, &r, &g, &b))
|
||
|
*framecolor = cdEncodeColor(r, g, b);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetFrameVertColor(Ihandle* ih, int lin, int col, long *framecolor, int check_title)
|
||
|
{
|
||
|
if ((ih->data->callback_mode || ih->data->cells[lin][col].flags & IMAT_HAS_FRAMEVERTCOLOR) ||
|
||
|
ih->data->columns.dt[col].flags & IMAT_HAS_FRAMEVERTCOLOR)
|
||
|
{
|
||
|
char* color = NULL;
|
||
|
unsigned char r, g, b;
|
||
|
if (check_title && col == 0)
|
||
|
{
|
||
|
color = iupAttribGetId2(ih, "FRAMETITLEVERTCOLOR", lin, 0);
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMETITLEVERTCOLOR", IUP_INVALID_ID, 0);
|
||
|
}
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMEVERTCOLOR", lin, col);
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMEVERTCOLOR", IUP_INVALID_ID, col);
|
||
|
if (!color)
|
||
|
color = iupAttribGetId2(ih, "FRAMEVERTCOLOR", lin, IUP_INVALID_ID);
|
||
|
if (iupStrEqual(color, "BGCOLOR"))
|
||
|
return 1;
|
||
|
if (framecolor && iupStrToRGB(color, &r, &g, &b))
|
||
|
*framecolor = cdEncodeColor(r, g, b);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetColAlignmentLin0(Ihandle* ih)
|
||
|
{
|
||
|
char* align = iupAttribGetStr(ih, "ALIGNMENTLIN0");
|
||
|
if (!align)
|
||
|
return IMAT_ALIGN_CENTER;
|
||
|
else if (iupStrEqualNoCase(align, "ARIGHT"))
|
||
|
return IMAT_ALIGN_END;
|
||
|
else if (iupStrEqualNoCase(align, "ALEFT"))
|
||
|
return IMAT_ALIGN_START;
|
||
|
else
|
||
|
return IMAT_ALIGN_CENTER;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetColAlignment(Ihandle* ih, int col)
|
||
|
{
|
||
|
char* align = iupAttribGetId(ih, "ALIGNMENT", col);
|
||
|
if (!align)
|
||
|
align = iupAttribGet(ih, "ALIGNMENT");
|
||
|
if (!align)
|
||
|
{
|
||
|
if (col == 0)
|
||
|
return IMAT_ALIGN_START;
|
||
|
else
|
||
|
return IMAT_ALIGN_CENTER;
|
||
|
}
|
||
|
else if (iupStrEqualNoCase(align, "ARIGHT"))
|
||
|
return IMAT_ALIGN_END;
|
||
|
else if (iupStrEqualNoCase(align, "ACENTER"))
|
||
|
return IMAT_ALIGN_CENTER;
|
||
|
else
|
||
|
return IMAT_ALIGN_START;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetLinAlignment(Ihandle* ih, int lin)
|
||
|
{
|
||
|
char* align = iupAttribGetId(ih, "LINEALIGNMENT", lin);
|
||
|
if (!align)
|
||
|
align = iupAttribGet(ih, "LINEALIGNMENT");
|
||
|
if (!align)
|
||
|
return IMAT_ALIGN_CENTER;
|
||
|
else if (iupStrEqualNoCase(align, "ABOTTOM"))
|
||
|
return IMAT_ALIGN_END;
|
||
|
else if (iupStrEqualNoCase(align, "ATOP"))
|
||
|
return IMAT_ALIGN_START;
|
||
|
else
|
||
|
return IMAT_ALIGN_CENTER;
|
||
|
}
|
||
|
|
||
|
void iupMatrixGetCellAlign(Ihandle* ih, int lin, int col, int *col_alignment, int *lin_alignment)
|
||
|
{
|
||
|
char* align = iupAttribGetId2(ih, "ALIGN", lin, col);
|
||
|
if (align)
|
||
|
{
|
||
|
char col_align[30], lin_align[30];
|
||
|
if (iupStrToStrStr(align, lin_align, col_align, ':'))
|
||
|
{
|
||
|
if (iupStrEqualNoCase(col_align, "ARIGHT"))
|
||
|
*col_alignment = IMAT_ALIGN_END;
|
||
|
else if (iupStrEqualNoCase(col_align, "ACENTER"))
|
||
|
*col_alignment = IMAT_ALIGN_CENTER;
|
||
|
else if (iupStrEqualNoCase(col_align, "ALEFT"))
|
||
|
*col_alignment = IMAT_ALIGN_START;
|
||
|
|
||
|
if (iupStrEqualNoCase(col_align, "ABOTTOM"))
|
||
|
*lin_alignment = IMAT_ALIGN_END;
|
||
|
else if (iupStrEqualNoCase(col_align, "ACENTER"))
|
||
|
*lin_alignment = IMAT_ALIGN_CENTER;
|
||
|
else if (iupStrEqualNoCase(col_align, "ATOP"))
|
||
|
*lin_alignment = IMAT_ALIGN_START;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetColumnWidth(Ihandle* ih, int col, int use_value)
|
||
|
{
|
||
|
int width = 0, pixels = 0;
|
||
|
char* value;
|
||
|
|
||
|
/* can be called for invalid columns (col>numcol) */
|
||
|
|
||
|
value = iupAttribGetId(ih, "WIDTH", col);
|
||
|
if (!value)
|
||
|
{
|
||
|
value = iupAttribGetId(ih, "RASTERWIDTH", col);
|
||
|
if (value)
|
||
|
pixels = 1;
|
||
|
}
|
||
|
|
||
|
if (use_value && !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 = iupMatrixGetValueDisplay(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 && (col > 0 && col < ih->data->columns.num))
|
||
|
{
|
||
|
char* title_value = iupMatrixGetValueDisplay(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 iupMatrixGetLineHeight(Ihandle* ih, int lin, int use_value)
|
||
|
{
|
||
|
int height = 0, pixels = 0;
|
||
|
char* value;
|
||
|
|
||
|
/* can be called for invalid lines (lin>numlin) */
|
||
|
|
||
|
value = iupAttribGetId(ih, "HEIGHT", lin);
|
||
|
if (!value)
|
||
|
{
|
||
|
value = iupAttribGetId(ih, "RASTERHEIGHT", lin);
|
||
|
if (value)
|
||
|
pixels = 1;
|
||
|
}
|
||
|
|
||
|
if (use_value && !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 = iupMatrixGetValueDisplay(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 && (lin > 0 && lin < ih->data->lines.num))
|
||
|
{
|
||
|
char* title_value = iupMatrixGetValueDisplay(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;
|
||
|
}
|
||
|
|
||
|
char *iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels_unit)
|
||
|
{
|
||
|
int size;
|
||
|
ImatLinColData *p;
|
||
|
|
||
|
if (m == IMAT_PROCESS_LIN)
|
||
|
p = &(ih->data->lines);
|
||
|
else
|
||
|
p = &(ih->data->columns);
|
||
|
|
||
|
if (index < 0 || index > p->num - 1)
|
||
|
return NULL;
|
||
|
|
||
|
if (m == IMAT_PROCESS_LIN)
|
||
|
size = iupMatrixGetLineHeight(ih, index, 1);
|
||
|
else
|
||
|
size = iupMatrixGetColumnWidth(ih, index, 1);
|
||
|
|
||
|
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_unit)
|
||
|
{
|
||
|
int charwidth, charheight;
|
||
|
iupdrvFontGetCharSize(ih, &charwidth, &charheight);
|
||
|
if (m == IMAT_PROCESS_COL)
|
||
|
size = iupRASTER2WIDTH(size, charwidth);
|
||
|
else
|
||
|
size = iupRASTER2HEIGHT(size, charheight);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return iupStrReturnInt(size);
|
||
|
}
|
||
|
|
||
|
static int iMatrixGetOffset(int index, int *offset, ImatLinColData *p)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
*offset = 0;
|
||
|
|
||
|
/* check if the cell is not empty */
|
||
|
if (!p->dt[index].size)
|
||
|
return 0;
|
||
|
|
||
|
if (index < p->num_noscroll)
|
||
|
{
|
||
|
for (i = 0; i < index; i++)
|
||
|
*offset += p->dt[i].size;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (index < p->first ||
|
||
|
index > p->last)
|
||
|
return 0;
|
||
|
|
||
|
for (i = 0; i < p->num_noscroll; i++)
|
||
|
*offset += p->dt[i].size;
|
||
|
|
||
|
/* Find the initial position */
|
||
|
*offset -= p->first_offset; /* index is always greater or equal to first */
|
||
|
for (i = p->first; i < index; i++)
|
||
|
*offset += p->dt[i].size;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetCellOffset(Ihandle* ih, int lin, int col, int *x, int *y)
|
||
|
{
|
||
|
if (!iMatrixGetOffset(col, x, &(ih->data->columns)))
|
||
|
return 0;
|
||
|
|
||
|
if (!iMatrixGetOffset(lin, y, &(ih->data->lines)))
|
||
|
return 0;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int iMatrixGetIndexFromOffset(int pos, ImatLinColData *p)
|
||
|
{
|
||
|
int offset = 0, i;
|
||
|
|
||
|
if (pos < 0)
|
||
|
return -1; /* invalid */
|
||
|
|
||
|
for (i = 0; i < p->num_noscroll; i++) /* for all non scrollable cells */
|
||
|
{
|
||
|
offset += p->dt[i].size;
|
||
|
|
||
|
if (pos < offset)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pos >= offset)
|
||
|
{
|
||
|
for (i = p->first; i <= p->last; i++) /* for all visible cells */
|
||
|
{
|
||
|
offset += p->dt[i].size;
|
||
|
if (i == p->first)
|
||
|
offset -= p->first_offset;
|
||
|
|
||
|
if (pos < offset)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (i > p->last)
|
||
|
i = -1; /* invisible */
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetCellFromXY(Ihandle* ih, int x, int y, int* l, int* c)
|
||
|
{
|
||
|
int col = iMatrixGetIndexFromOffset(x, &(ih->data->columns));
|
||
|
int lin = iMatrixGetIndexFromOffset(y, &(ih->data->lines));
|
||
|
int merged = 0;
|
||
|
|
||
|
if (col < 0 || lin < 0)
|
||
|
return 0;
|
||
|
|
||
|
if (ih->data->merge_info_count)
|
||
|
merged = iupMatrixGetMerged(ih, lin, col);
|
||
|
|
||
|
if (merged)
|
||
|
{
|
||
|
int startLin, startCol;
|
||
|
iupMatrixGetMergedRect(ih, merged, &startLin, NULL, &startCol, NULL);
|
||
|
|
||
|
*l = startLin;
|
||
|
*c = startCol;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*l = lin;
|
||
|
*c = col;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int iMatrixGetCellDim(int index, int* offset, int* size, ImatLinColData *p)
|
||
|
{
|
||
|
int i, visible = 1;
|
||
|
|
||
|
*offset = 0;
|
||
|
if (index < p->num_noscroll)
|
||
|
{
|
||
|
for (i = 0; i < index; i++)
|
||
|
*offset += p->dt[i].size;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (i = 0; i < p->num_noscroll; i++)
|
||
|
*offset += p->dt[i].size;
|
||
|
|
||
|
for (i = p->first; i < index; i++)
|
||
|
{
|
||
|
*offset += p->dt[i].size;
|
||
|
|
||
|
if (i == p->first)
|
||
|
*offset -= p->first_offset; /* add only when index greater than first */
|
||
|
}
|
||
|
|
||
|
if (index < p->first)
|
||
|
visible = 0;
|
||
|
}
|
||
|
|
||
|
*size = p->dt[index].size;
|
||
|
if (index == p->first)
|
||
|
*size -= p->first_offset;
|
||
|
|
||
|
return visible;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetVisibleCellDim(Ihandle* ih, int lin, int col, int* x, int* y, int* w, int* h)
|
||
|
{
|
||
|
int visible = 1;
|
||
|
int merged = 0;
|
||
|
|
||
|
if (ih->data->merge_info_count)
|
||
|
merged = iupMatrixGetMerged(ih, lin, col);
|
||
|
|
||
|
if (merged)
|
||
|
{
|
||
|
int i, j;
|
||
|
int dummyX, dummyY;
|
||
|
int mergedW, mergedH;
|
||
|
int startLin, endLin, startCol, endCol;
|
||
|
|
||
|
iupMatrixGetMergedRect(ih, merged, &startLin, &endLin, &startCol, &endCol);
|
||
|
|
||
|
visible &= iMatrixGetCellDim(startCol, x, w, &(ih->data->columns));
|
||
|
visible &= iMatrixGetCellDim(startLin, y, h, &(ih->data->lines));
|
||
|
|
||
|
for (i = startLin+1; i <= endLin; i++)
|
||
|
{
|
||
|
iMatrixGetCellDim(i, &dummyY, &mergedH, &(ih->data->lines));
|
||
|
*h += mergedH;
|
||
|
}
|
||
|
|
||
|
for (j = startCol+1; j <= endCol; j++)
|
||
|
{
|
||
|
iMatrixGetCellDim(j, &dummyX, &mergedW, &(ih->data->columns));
|
||
|
*w += mergedW;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
visible &= iMatrixGetCellDim(col, x, w, &(ih->data->columns));
|
||
|
visible &= iMatrixGetCellDim(lin, y, h, &(ih->data->lines));
|
||
|
}
|
||
|
|
||
|
*w = *w - 1; /* do not include right frame line */
|
||
|
*h = *h - 1; /* do not include bottom frame line */
|
||
|
return visible;
|
||
|
}
|
||
|
|
||
|
int iupMatrixHasMerged(Ihandle* ih, int startLin, int endLin, int startCol, int endCol)
|
||
|
{
|
||
|
int lin, col, merged;
|
||
|
|
||
|
if (!ih->data->merge_info_count)
|
||
|
return 0;
|
||
|
|
||
|
for (lin = startLin; lin <= endLin; lin++)
|
||
|
{
|
||
|
for (col = startCol; col <= endCol; col++)
|
||
|
{
|
||
|
merged = iupMatrixGetMerged(ih, lin, col);
|
||
|
if (merged)
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int iMatrixMergeAddRange(Ihandle* ih, int startLin, int endLin, int startCol, int endCol)
|
||
|
{
|
||
|
int merged;
|
||
|
ImatMergedData* merged_data;
|
||
|
|
||
|
if (!ih->data->merge_info)
|
||
|
{
|
||
|
ih->data->merge_info_max = 10;
|
||
|
ih->data->merge_info = malloc(ih->data->merge_info_max * sizeof(ImatMergedData));
|
||
|
memset(ih->data->merge_info, 0, ih->data->merge_info_max * sizeof(ImatMergedData));
|
||
|
}
|
||
|
|
||
|
/* find an empty slot */
|
||
|
for (merged = 1; merged <= ih->data->merge_info_max; merged++)
|
||
|
{
|
||
|
if (ih->data->merge_info[merged - 1].used == 0)
|
||
|
{
|
||
|
merged_data = ih->data->merge_info + (merged - 1);
|
||
|
merged_data->start_lin = startLin;
|
||
|
merged_data->start_col = startCol;
|
||
|
merged_data->end_lin = endLin;
|
||
|
merged_data->end_col = endCol;
|
||
|
merged_data->used = 1;
|
||
|
|
||
|
ih->data->merge_info_count++;
|
||
|
|
||
|
return merged;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* add more room */
|
||
|
ih->data->merge_info_max += 10;
|
||
|
ih->data->merge_info = realloc(ih->data->merge_info, ih->data->merge_info_max * sizeof(ImatMergedData));
|
||
|
memset(ih->data->merge_info + ih->data->merge_info_max - 10, 0, 10 * sizeof(ImatMergedData));
|
||
|
|
||
|
merged_data = ih->data->merge_info + (merged - 1);
|
||
|
merged_data->start_lin = startLin;
|
||
|
merged_data->start_col = startCol;
|
||
|
merged_data->end_lin = endLin;
|
||
|
merged_data->end_col = endCol;
|
||
|
merged_data->used = 1;
|
||
|
|
||
|
ih->data->merge_info_count++;
|
||
|
|
||
|
return merged;
|
||
|
}
|
||
|
|
||
|
int iupMatrixGetMerged(Ihandle* ih, int lin, int col)
|
||
|
{
|
||
|
return iupAttribGetIntId2(ih, "MERGED", lin, col);
|
||
|
}
|
||
|
|
||
|
void iupMatrixMergeRange(Ihandle* ih, int startLin, int endLin, int startCol, int endCol)
|
||
|
{
|
||
|
int lin, col;
|
||
|
|
||
|
int merged = iMatrixMergeAddRange(ih, startLin, endLin, startCol, endCol);
|
||
|
|
||
|
for (lin = startLin; lin <= endLin; lin++)
|
||
|
{
|
||
|
for (col = startCol; col <= endCol; col++)
|
||
|
{
|
||
|
iupAttribSetIntId2(ih, "MERGED", lin, col, merged);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void iupMatrixMergeSplitRange(Ihandle* ih, int merged)
|
||
|
{
|
||
|
int lin, col;
|
||
|
int startLin, endLin, startCol, endCol;
|
||
|
|
||
|
iupMatrixGetMergedRect(ih, merged, &startLin, &endLin, &startCol, &endCol);
|
||
|
|
||
|
for (lin = startLin; lin <= endLin; lin++)
|
||
|
{
|
||
|
for (col = startCol; col <= endCol; col++)
|
||
|
{
|
||
|
iupAttribSetId2(ih, "MERGED", lin, col, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ih->data->merge_info[merged - 1].used = 0;
|
||
|
ih->data->merge_info_count--;
|
||
|
}
|
||
|
|
||
|
void iupMatrixGetMergedRect(Ihandle *ih, int merged, int *startLin, int *endLin, int *startCol, int *endCol)
|
||
|
{
|
||
|
ImatMergedData* merged_data = ih->data->merge_info + (merged - 1);
|
||
|
if (merged_data->used)
|
||
|
{
|
||
|
if (startLin) *startLin = merged_data->start_lin;
|
||
|
if (startCol) *startCol = merged_data->start_col;
|
||
|
if (endLin) *endLin = merged_data->end_lin;
|
||
|
if (endCol) *endCol = merged_data->end_col;
|
||
|
}
|
||
|
}
|