iup-stack/iup/srccontrols/matrix/iupmat_getset.c

1246 lines
32 KiB
C
Executable File

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