/** \file * \brief iupmatrix setget control * attributes set and get * * See Copyright Notice in "iup.h" */ #include #include #include #include "iup.h" #include "iupcbs.h" #include #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; } }