summaryrefslogtreecommitdiff
path: root/iup/srccontrols
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-11-04 11:56:41 -0800
committerPixel <pixel@nobis-crew.org>2009-11-04 11:59:33 -0800
commitd577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch)
tree590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /iup/srccontrols
Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux.
Diffstat (limited to 'iup/srccontrols')
-rwxr-xr-xiup/srccontrols/Makefile6
-rwxr-xr-xiup/srccontrols/color/iup_colorbrowser.c849
-rwxr-xr-xiup/srccontrols/color/iup_colorbrowserdlg.c1120
-rwxr-xr-xiup/srccontrols/color/iup_colorhsi.c358
-rwxr-xr-xiup/srccontrols/color/iup_colorhsi.h44
-rwxr-xr-xiup/srccontrols/config.mak48
-rwxr-xr-xiup/srccontrols/iup_cdutil.c153
-rwxr-xr-xiup/srccontrols/iup_cdutil.h35
-rwxr-xr-xiup/srccontrols/iup_cells.c974
-rwxr-xr-xiup/srccontrols/iup_colorbar.c1082
-rwxr-xr-xiup/srccontrols/iup_controls.c56
-rwxr-xr-xiup/srccontrols/iup_controls.h33
-rwxr-xr-xiup/srccontrols/iup_dial.c864
-rwxr-xr-xiup/srccontrols/iup_gauge.c435
-rwxr-xr-xiup/srccontrols/iup_oldmask.c208
-rwxr-xr-xiup/srccontrols/iup_oldtabs.c2616
-rwxr-xr-xiup/srccontrols/iup_oldval.c809
-rwxr-xr-xiup/srccontrols/iupcontrols.def35
-rw-r--r--iup/srccontrols/iupcontrols.dep173
-rwxr-xr-xiup/srccontrols/make_uname3
-rwxr-xr-xiup/srccontrols/make_uname.bat4
-rwxr-xr-xiup/srccontrols/matrix/iupmat_aux.c480
-rwxr-xr-xiup/srccontrols/matrix/iupmat_aux.h37
-rwxr-xr-xiup/srccontrols/matrix/iupmat_cd.h25
-rwxr-xr-xiup/srccontrols/matrix/iupmat_colres.c182
-rwxr-xr-xiup/srccontrols/matrix/iupmat_colres.h24
-rwxr-xr-xiup/srccontrols/matrix/iupmat_def.h122
-rwxr-xr-xiup/srccontrols/matrix/iupmat_draw.c866
-rwxr-xr-xiup/srccontrols/matrix/iupmat_draw.h31
-rwxr-xr-xiup/srccontrols/matrix/iupmat_edit.c450
-rwxr-xr-xiup/srccontrols/matrix/iupmat_edit.h26
-rwxr-xr-xiup/srccontrols/matrix/iupmat_focus.c58
-rwxr-xr-xiup/srccontrols/matrix/iupmat_focus.h21
-rwxr-xr-xiup/srccontrols/matrix/iupmat_getset.c358
-rwxr-xr-xiup/srccontrols/matrix/iupmat_getset.h37
-rwxr-xr-xiup/srccontrols/matrix/iupmat_key.c229
-rwxr-xr-xiup/srccontrols/matrix/iupmat_key.h23
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mark.c720
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mark.h42
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mem.c319
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mem.h24
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mouse.c212
-rwxr-xr-xiup/srccontrols/matrix/iupmat_mouse.h22
-rwxr-xr-xiup/srccontrols/matrix/iupmat_numlc.c495
-rwxr-xr-xiup/srccontrols/matrix/iupmat_numlc.h27
-rwxr-xr-xiup/srccontrols/matrix/iupmat_scroll.c495
-rwxr-xr-xiup/srccontrols/matrix/iupmat_scroll.h69
-rwxr-xr-xiup/srccontrols/matrix/iupmatrix.c980
48 files changed, 16279 insertions, 0 deletions
diff --git a/iup/srccontrols/Makefile b/iup/srccontrols/Makefile
new file mode 100755
index 0000000..d02bbc3
--- /dev/null
+++ b/iup/srccontrols/Makefile
@@ -0,0 +1,6 @@
+
+.PHONY: do_all iupcontrols
+do_all: iupcontrols
+
+iupcontrols:
+ @$(MAKE) --no-print-directory -f ../tecmake_compact.mak
diff --git a/iup/srccontrols/color/iup_colorbrowser.c b/iup/srccontrols/color/iup_colorbrowser.c
new file mode 100755
index 0000000..82b4a88
--- /dev/null
+++ b/iup/srccontrols/color/iup_colorbrowser.c
@@ -0,0 +1,849 @@
+/** \file
+* \brief ColorBrowser Control.
+*
+* See Copyright Notice in "iup.h"
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cdirgb.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+
+#include "iup_colorhsi.h"
+
+
+#ifndef min
+#define min(a, b) ( (a < b) ? (a) : (b) )
+#endif
+
+#define ICB_DEG2RAD 0.01745329252f /* degrees to radians (rad = ICB_DEG2RAD * deg) */
+#define ICB_DEFAULTSIZE 181 /* default size */
+#define ICB_SPACE 4 /* size of the spacing */
+#define ICB_HUEWIDTH 18 /* width of the hue ring */
+#define ICB_MARKSIZE 6 /* size of the cursor mark */
+enum {ICB_INSIDE_NONE, ICB_INSIDE_HUE, ICB_INSIDE_SI};
+
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ /* mouse interaction state */
+ int h_down,
+ si_down;
+
+ /* cursor positioning */
+ int h_x, h_y,
+ si_x, si_y;
+
+ /* HSI-XY coordinate convertion */
+ int xc, yc, /* center */
+ R, /* maximum radius available inside the size of the control */
+ Ix, /* x coordinate where S is 0 */
+ Iy1, /* y coordinate where I is 0 */
+ Iy2, /* y coordinate where I is 1 */
+ SxMax; /* x coordinate where S is 1 and I = 0.5 */
+
+ /* visual appearance control */
+ int w, h;
+ int has_focus;
+ long bgcolor;
+
+ /* attributes */
+ float hue, /* 0<=H<=359 */
+ saturation, /* 0<=S<=1 */
+ intensity; /* 0<=I<=1 */
+ unsigned char red, green, blue; /* 0<=x<=255 */
+
+ cdCanvas *cddbuffer;
+ cdCanvas *cdcanvas;
+};
+
+
+static float iColorBrowserSXmax(Ihandle* ih, int y)
+{
+ if (y == ih->data->yc)
+ return (float)(ih->data->SxMax - ih->data->Ix);
+ else if (y < ih->data->yc)
+ {
+ float D2 = (ih->data->Iy2 - ih->data->Iy1)/2.0f;
+ return ((float)(ih->data->SxMax - ih->data->Ix)*(y-ih->data->yc + D2))/D2;
+ }
+ else
+ {
+ float D2 = (ih->data->Iy2 - ih->data->Iy1)/2.0f;
+ return -((float)(ih->data->SxMax - ih->data->Ix)*(y-ih->data->yc - D2))/D2;
+ }
+}
+
+static float iColorBrowserCalcIntensity(Ihandle* ih, int y)
+{
+ return (float)(y - ih->data->Iy1)/(float)(ih->data->Iy2 - ih->data->Iy1);
+}
+
+static float iColorBrowserCalcSaturation(Ihandle* ih, int x, float sx_max)
+{
+ if (sx_max == 0)
+ return 0;
+ else
+ return (float)(x - ih->data->Ix)/sx_max;
+}
+
+/* Rotate points of 60 degrees */
+static void iColorBrowserRotatePoints(float *x1, float *y1, float *x2, float *y2, int xc, int yc)
+{
+ float xt, yt;
+ float nxt, nyt;
+ static const float s60 = 0.8660254f;
+ static const float c60 = 0.5f;
+
+ xt = *x1 - xc;
+ yt = *y1 - yc;
+ nxt = xt * c60 - yt * s60;
+ nyt = xt * s60 + yt * c60;
+ *x1 = nxt + xc;
+ *y1 = nyt + yc;
+
+ xt = *x2 - xc;
+ yt = *y2 - yc;
+ nxt = xt * c60 - yt * s60;
+ nyt = xt * s60 + yt * c60;
+ *x2 = nxt + xc;
+ *y2 = nyt + yc;
+}
+
+static void iColorBrowserRenderImageHue(Ihandle* ih)
+{
+ int x, y, active = 1;
+ unsigned char *red, *green, *blue;
+ unsigned char bg_red, bg_green, bg_blue;
+ if (!ih->data->cddbuffer)
+ return;
+
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+
+ if (!iupdrvIsActive(ih))
+ active = 0;
+
+ if (ih->data->has_focus)
+ cdDrawFocusRect(ih->data->cddbuffer, 0, 0, ih->data->w-1, ih->data->h-1);
+
+ red = cdRedImage(ih->data->cddbuffer);
+ green = cdGreenImage(ih->data->cddbuffer);
+ blue = cdBlueImage(ih->data->cddbuffer);
+
+ cdDecodeColor(ih->data->bgcolor, &bg_red, &bg_green, &bg_blue);
+
+ for (y = 0; y < ih->data->h; y++)
+ {
+ float sx_max = iColorBrowserSXmax(ih, y);
+
+ for (x = 0; x < ih->data->w; x++)
+ {
+ int xl, yl;
+ float radius, diff1, diff2;
+
+ if (y > ih->data->Iy1 &&
+ y < ih->data->Iy2 &&
+ x > ih->data->Ix &&
+ x < ih->data->Ix+(int)sx_max)
+ continue;
+
+ xl = x - ih->data->xc;
+ yl = y - ih->data->yc;
+ radius = sqrtf(xl*xl + yl*yl);
+
+ diff1 = radius - (ih->data->R-ICB_SPACE-ICB_HUEWIDTH);
+ diff2 = (ih->data->R-ICB_SPACE) - radius;
+
+ if (diff1>0 && diff2>0)
+ {
+ float h, s, i;
+ int offset = y*ih->data->w + x;
+ unsigned char* r = red + offset;
+ unsigned char* g = green + offset;
+ unsigned char* b = blue + offset;
+
+ h = atan2f(yl, xl);
+ h = (float)(h * CD_RAD2DEG);
+ s = 1.0f; /* maximum saturation */
+ i = 0.5f; /* choose I where S is maximum */
+
+ iupColorHSI2RGB(h, s, i, r, g, b);
+
+ if (diff1<1 || diff2<1) /* anti-aliasing */
+ {
+ float diff = (float)(diff1<1? diff1: diff2);
+ *r = (unsigned char)((*r)*diff + bg_red*(1.0f-diff));
+ *g = (unsigned char)((*g)*diff + bg_green*(1.0f-diff));
+ *b = (unsigned char)((*b)*diff + bg_blue*(1.0f-diff));
+ }
+
+ if (!active)
+ {
+ *r = cdIupLIGTHER(*r);
+ *g = cdIupLIGTHER(*g);
+ *b = cdIupLIGTHER(*b);
+ }
+ }
+ }
+ }
+
+ if (active)
+ {
+ float x1, x2, y1, y2;
+ unsigned char shade_lr, shade_lg, shade_lb,
+ shade_dr, shade_dg, shade_db;
+ shade_dr = (unsigned char)((2 * bg_red) / 3);
+ shade_dg = (unsigned char)((2 * bg_green) / 3);
+ shade_db = (unsigned char)((2 * bg_blue) / 3);
+ shade_lr = (unsigned char)((255 + bg_red) / 2);
+ shade_lg = (unsigned char)((255 + bg_green) / 2);
+ shade_lb = (unsigned char)((255 + bg_blue) / 2);
+ cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(shade_dr, shade_dg, shade_db));
+ x1 = (float)(ih->data->xc-ih->data->R+ICB_SPACE); y1 = (float)ih->data->yc; x2 = (float)(x1+ICB_HUEWIDTH/2); y2 = (float)ih->data->yc;
+ cdCanvasLine(ih->data->cddbuffer, (int) x1, (int) y1, (int) x2, (int) y2);
+ iColorBrowserRotatePoints(&x1, &y1, &x2, &y2, ih->data->xc, ih->data->yc);
+ cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(shade_lr, shade_lg, shade_lb));
+ cdCanvasLine(ih->data->cddbuffer, (int) x1, (int) y1, (int) x2, (int) y2);
+ iColorBrowserRotatePoints(&x1, &y1, &x2, &y2, ih->data->xc, ih->data->yc);
+ cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(shade_dr, shade_dg, shade_db));
+ cdCanvasLine(ih->data->cddbuffer, (int) x1, (int) y1, (int) x2, (int) y2);
+ iColorBrowserRotatePoints(&x1, &y1, &x2, &y2, ih->data->xc, ih->data->yc);
+ cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(shade_lr, shade_lg, shade_lb));
+ cdCanvasLine(ih->data->cddbuffer, (int) x1, (int) y1, (int) x2, (int) y2);
+ iColorBrowserRotatePoints(&x1, &y1, &x2, &y2, ih->data->xc, ih->data->yc);
+ cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(shade_dr, shade_dg, shade_db));
+ cdCanvasLine(ih->data->cddbuffer, (int) x1, (int) y1, (int) x2, (int) y2);
+ iColorBrowserRotatePoints(&x1, &y1, &x2, &y2, ih->data->xc, ih->data->yc);
+ cdCanvasLine(ih->data->cddbuffer, (int) x1, (int) y1, (int) x2, (int) y2);
+ }
+}
+
+static void iColorBrowserRenderImageSI(Ihandle* ih)
+{
+ int x, y, active = 1;
+ unsigned char *red, *green, *blue;
+ unsigned char bg_red, bg_green, bg_blue;
+ float angle, cos_angle, sin_angle;
+ if (!ih->data->cddbuffer)
+ return;
+
+ if (!iupdrvIsActive(ih))
+ active = 0;
+
+ red = cdRedImage(ih->data->cddbuffer);
+ green = cdGreenImage(ih->data->cddbuffer);
+ blue = cdBlueImage(ih->data->cddbuffer);
+
+ cdDecodeColor(ih->data->bgcolor, &bg_red, &bg_green, &bg_blue);
+
+ angle = ih->data->hue * ICB_DEG2RAD;
+ cos_angle = cosf(angle);
+ sin_angle = sinf(angle);
+
+ for (y = 0; y < ih->data->h; y++)
+ {
+ float sx_max, i;
+
+ if (y < ih->data->Iy1)
+ continue;
+ else if (y > ih->data->Iy2)
+ continue;
+
+ sx_max = iColorBrowserSXmax(ih, y);
+ i = iColorBrowserCalcIntensity(ih, y);
+
+ for (x = 0; x < ih->data->w; x++)
+ {
+ if (x < ih->data->Ix)
+ continue;
+ else if (x > ih->data->Ix+(int)sx_max)
+ continue;
+
+ {
+ int offset = y*ih->data->w + x;
+ unsigned char* r = red + offset;
+ unsigned char* g = green + offset;
+ unsigned char* b = blue + offset;
+ float s, diff;
+
+ s = iColorBrowserCalcSaturation(ih, x, sx_max);
+
+ iupColorHSI2RGB(ih->data->hue, s, i, r, g, b);
+
+ diff = sx_max - (float)(x - ih->data->Ix);
+ if (diff<1.0f) /* anti-aliasing */
+ {
+ *r = (unsigned char)((*r)*diff + bg_red*(1.0f-diff));
+ *g = (unsigned char)((*g)*diff + bg_green*(1.0f-diff));
+ *b = (unsigned char)((*b)*diff + bg_blue*(1.0f-diff));
+ }
+
+ if (!active)
+ {
+ *r = cdIupLIGTHER(*r);
+ *g = cdIupLIGTHER(*g);
+ *b = cdIupLIGTHER(*b);
+ }
+ }
+ }
+ }
+}
+
+static void iColorBrowserUpdateCursorSI(Ihandle* ih)
+{
+ int x;
+ int y = (int)(ih->data->intensity*(ih->data->Iy2 - ih->data->Iy1)) + ih->data->Iy1;
+ ih->data->si_y = iupROUND(y);
+ x = (int)(ih->data->saturation*iColorBrowserSXmax(ih, ih->data->si_y)) + ih->data->Ix;
+ ih->data->si_x = iupROUND(x);
+}
+
+static void iColorBrowserSetCursorSI(Ihandle* ih, int x, int y)
+{
+ float sx_max;
+
+ if (y < ih->data->Iy1)
+ ih->data->si_y = ih->data->Iy1;
+ else if (y > ih->data->Iy2)
+ ih->data->si_y = ih->data->Iy2;
+ else
+ ih->data->si_y = y;
+
+ sx_max = iColorBrowserSXmax(ih, ih->data->si_y);
+
+ if (x < ih->data->Ix)
+ ih->data->si_x = ih->data->Ix;
+ else if (x > ih->data->Ix+sx_max)
+ ih->data->si_x = ih->data->Ix+(int)sx_max;
+ else
+ ih->data->si_x = x;
+
+ ih->data->intensity = iColorBrowserCalcIntensity(ih, ih->data->si_y);
+ ih->data->saturation = iColorBrowserCalcSaturation(ih, ih->data->si_x, sx_max);
+
+ if (ih->data->saturation == -0.0f)
+ ih->data->saturation = 0;
+ if (ih->data->intensity == -0.0f)
+ ih->data->intensity = 0;
+}
+
+static void iColorBrowserUpdateCursorHue(Ihandle* ih)
+{
+ int rc = ih->data->R-ICB_SPACE-ICB_HUEWIDTH/2;
+ float angle = ih->data->hue * ICB_DEG2RAD;
+ float cos_angle = cosf(angle);
+ float sin_angle = sinf(angle);
+ float x = rc*cos_angle + ih->data->xc;
+ float y = rc*sin_angle + ih->data->yc;
+ ih->data->h_x = iupROUND(x);
+ ih->data->h_y = iupROUND(y);
+}
+
+static void iColorBrowserSetCursorHue(Ihandle* ih, int x, int y)
+{
+ int xl = x - ih->data->xc;
+ int yl = y - ih->data->yc;
+ ih->data->hue = (float)(atan2f(yl, xl) * CD_RAD2DEG);
+ ih->data->hue = fmodf(ih->data->hue, 360.0f);
+ if (ih->data->hue < 0.0f)
+ ih->data->hue += 360.0f;
+
+ iColorBrowserUpdateCursorHue(ih);
+}
+
+static int iColorBrowserCheckInside(Ihandle* ih, int x, int y)
+{
+ int xl = x - ih->data->xc;
+ int yl = y - ih->data->yc;
+ float radius = sqrtf(xl*xl + yl*yl);
+
+ if (radius < ih->data->R-ICB_SPACE-ICB_HUEWIDTH-ICB_SPACE)
+ return ICB_INSIDE_SI;
+
+ if (radius > ih->data->R-ICB_SPACE-ICB_HUEWIDTH &&
+ radius < ih->data->R-ICB_SPACE)
+ return ICB_INSIDE_HUE;
+
+ return ICB_INSIDE_NONE;
+}
+
+static void iColorBrowserHSI2RGB(Ihandle* ih)
+{
+ iupColorHSI2RGB(ih->data->hue, ih->data->saturation, ih->data->intensity,
+ &(ih->data->red), &(ih->data->green), &(ih->data->blue));
+}
+
+static void iColorBrowserRGB2HSI(Ihandle* ih)
+{
+ iupColorRGB2HSI(ih->data->red, ih->data->green, ih->data->blue,
+ &(ih->data->hue), &(ih->data->saturation), &(ih->data->intensity));
+}
+
+static void iColorBrowserUpdateDisplay(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return;
+
+ cdCanvasFlush(ih->data->cddbuffer); /* swap the RGB to the display canvas */
+
+ if (iupdrvIsActive(ih))
+ {
+ cdCanvasForeground(ih->data->cdcanvas, CD_GRAY);
+ cdCanvasArc(ih->data->cdcanvas, ih->data->h_x+1, ih->data->h_y, ICB_MARKSIZE, ICB_MARKSIZE, 0, 360);
+ cdCanvasArc(ih->data->cdcanvas, ih->data->si_x+1, ih->data->si_y, ICB_MARKSIZE, ICB_MARKSIZE, 0, 360);
+ cdCanvasForeground(ih->data->cdcanvas, CD_WHITE);
+ cdCanvasArc(ih->data->cdcanvas, ih->data->h_x, ih->data->h_y, ICB_MARKSIZE, ICB_MARKSIZE, 0, 360);
+ cdCanvasArc(ih->data->cdcanvas, ih->data->si_x, ih->data->si_y, ICB_MARKSIZE, ICB_MARKSIZE, 0, 360);
+ }
+ else
+ {
+ cdCanvasForeground(ih->data->cdcanvas, CD_DARK_GRAY);
+ cdCanvasSector(ih->data->cdcanvas, ih->data->h_x, ih->data->h_y, ICB_MARKSIZE+1, ICB_MARKSIZE+1, 0, 360);
+ cdCanvasSector(ih->data->cdcanvas, ih->data->si_x, ih->data->si_y, ICB_MARKSIZE+1, ICB_MARKSIZE+1, 0, 360);
+ }
+}
+
+static void iColorBrowserCallChangeCb(Ihandle* ih)
+{
+ IFnccc change_cb = (IFnccc) IupGetCallback(ih, "CHANGE_CB");
+ if (change_cb)
+ change_cb(ih, ih->data->red, ih->data->green, ih->data->blue);
+
+ iupBaseCallValueChangedCb(ih);
+}
+
+static void iColorBrowserCallDragCb(Ihandle* ih)
+{
+ IFnccc drag_cb = (IFnccc) IupGetCallback(ih, "DRAG_CB");
+ if (drag_cb)
+ drag_cb(ih, ih->data->red, ih->data->green, ih->data->blue);
+
+ iupBaseCallValueChangedCb(ih);
+}
+
+static int iColorBrowserHmouse(Ihandle* ih, int x, int y, int drag)
+{
+ iColorBrowserSetCursorHue(ih, x, y);
+ iColorBrowserHSI2RGB(ih);
+ /* must update the Si area */
+ iColorBrowserRenderImageSI(ih);
+ iColorBrowserUpdateDisplay(ih);
+
+ if (drag)
+ iColorBrowserCallDragCb(ih);
+ else
+ iColorBrowserCallChangeCb(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserSImouse(Ihandle* ih, int x, int y, int drag)
+{
+ iColorBrowserSetCursorSI(ih, x, y);
+ iColorBrowserHSI2RGB(ih);
+ iColorBrowserUpdateDisplay(ih);
+
+ if (drag)
+ iColorBrowserCallDragCb(ih);
+ else
+ iColorBrowserCallChangeCb(ih);
+
+ return IUP_DEFAULT;
+}
+
+
+/******************************************************************/
+
+
+static int iColorBrowserButton_CB(Ihandle* ih, int b, int press, int x, int y)
+{
+ if (b != IUP_BUTTON1)
+ return IUP_DEFAULT;
+
+ cdCanvasUpdateYAxis(ih->data->cdcanvas, &y);
+
+ if (press)
+ {
+ int inside = iColorBrowserCheckInside(ih, x, y);
+
+ if (!ih->data->h_down && inside==ICB_INSIDE_HUE)
+ {
+ iColorBrowserHmouse(ih, x, y, 1);
+ ih->data->h_down = 1;
+ }
+
+ if (!ih->data->si_down && inside==ICB_INSIDE_SI)
+ {
+ iColorBrowserSImouse(ih, x, y, 1);
+ ih->data->si_down = 1;
+ }
+ }
+ else
+ {
+ if (ih->data->h_down)
+ {
+ iColorBrowserHmouse(ih, x, y, 0);
+ ih->data->h_down = 0;
+ }
+
+ if (ih->data->si_down)
+ {
+ iColorBrowserSImouse(ih, x, y, 0);
+ ih->data->si_down = 0;
+ }
+ }
+
+ return IUP_DEFAULT;
+}
+
+/* Callback for the mouse motion in the canvas */
+static int iColorBrowserMotion_CB(Ihandle* ih, int x, int y, char *status)
+{
+ if (!iup_isbutton1(status))
+ {
+ ih->data->h_down = 0;
+ ih->data->si_down = 0;
+ return IUP_DEFAULT;
+ }
+
+ if (ih->data->h_down)
+ {
+ cdCanvasUpdateYAxis(ih->data->cdcanvas, &y);
+ iColorBrowserHmouse(ih, x, y, 1);
+ }
+ else if (ih->data->si_down)
+ {
+ cdCanvasUpdateYAxis(ih->data->cdcanvas, &y);
+ iColorBrowserSImouse(ih, x, y, 1);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserFocus_CB(Ihandle* ih, int focus)
+{
+ ih->data->has_focus = focus;
+ iColorBrowserRenderImageHue(ih);
+ iColorBrowserRenderImageSI(ih);
+ iColorBrowserUpdateDisplay(ih);
+ return IUP_DEFAULT;
+}
+
+static void iColorBrowserUpdateSize(Ihandle* ih)
+{
+ int T, D;
+
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ ih->data->R = min(ih->data->w, ih->data->h)/2;
+ ih->data->xc = ih->data->w/2;
+ ih->data->yc = ih->data->h/2;
+ T = ih->data->R-ICB_SPACE-ICB_HUEWIDTH-ICB_SPACE;
+ ih->data->Ix = ih->data->xc - T/2; /* cos(60)=0.5 */
+ D = (int)(2*T*0.866); /* sin(60)=0.866 */
+ ih->data->Iy1 = ih->data->yc - D/2;
+ ih->data->Iy2 = ih->data->Iy1 + D;
+ ih->data->SxMax = ih->data->xc + T;
+}
+
+static int iColorBrowserResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFERRGB, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update size */
+ iColorBrowserUpdateSize(ih);
+
+ iColorBrowserUpdateCursorHue(ih);
+ iColorBrowserUpdateCursorSI(ih);
+
+ /* update render */
+ iColorBrowserRenderImageHue(ih);
+ iColorBrowserRenderImageSI(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserRedraw_CB(Ihandle* ih)
+{
+ iColorBrowserUpdateDisplay(ih);
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserWheel_CB(Ihandle* ih, float delta)
+{
+ ih->data->hue += delta;
+
+ iColorBrowserUpdateCursorHue(ih);
+ iColorBrowserHSI2RGB(ih);
+ /* must update the Si area */
+ iColorBrowserRenderImageSI(ih);
+ iColorBrowserUpdateDisplay(ih);
+ iColorBrowserCallChangeCb(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserKeypress_CB(Ihandle* ih, int c, int press)
+{
+ int x, y, changing_hue = 0;
+
+ if (!press)
+ return IUP_DEFAULT;
+
+ x = ih->data->si_x;
+ y = ih->data->si_y;
+
+ switch (c)
+ {
+ case K_UP:
+ y++;
+ break;
+ case K_DOWN:
+ y--;
+ break;
+ case K_RIGHT:
+ x++;
+ break;
+ case K_LEFT:
+ x--;
+ break;
+ case K_PGUP:
+ ih->data->hue += 1.0f;
+ changing_hue = 1;
+ break;
+ case K_PGDN:
+ ih->data->hue -= 1.0f;
+ changing_hue = 1; break;
+ case K_HOME:
+ ih->data->hue = 0.0f;
+ changing_hue = 1;
+ break;
+ case K_END:
+ ih->data->hue = 180.0f;
+ changing_hue = 1;
+ break;
+ default:
+ return IUP_DEFAULT;
+ }
+
+ if (changing_hue)
+ {
+ iColorBrowserUpdateCursorHue(ih);
+ /* must update the Si area */
+ iColorBrowserRenderImageSI(ih);
+ }
+ else
+ iColorBrowserSetCursorSI(ih, x, y);
+
+ iColorBrowserHSI2RGB(ih);
+
+ iColorBrowserUpdateDisplay(ih);
+ iColorBrowserCallChangeCb(ih);
+
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+}
+
+
+/*********************************************************************************/
+
+
+static char* iColorBrowserGetHSIAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ sprintf(buffer, "%f %f %f", (double)ih->data->hue, (double)ih->data->saturation, (double)ih->data->intensity);
+ return buffer;
+}
+
+static int iColorBrowserSetHSIAttrib(Ihandle* ih, const char* value)
+{
+ float old_hue = ih->data->hue,
+ old_saturation = ih->data->saturation,
+ old_intensity = ih->data->intensity;
+
+ if (!iupStrToHSI(value, &ih->data->hue, &ih->data->saturation, &ih->data->intensity))
+ return 0;
+
+ if (ih->data->cddbuffer)
+ {
+ if (old_hue != ih->data->hue)
+ iColorBrowserUpdateCursorHue(ih);
+ if (old_saturation != ih->data->saturation || old_intensity != ih->data->intensity)
+ iColorBrowserUpdateCursorSI(ih);
+ iColorBrowserHSI2RGB(ih);
+ iColorBrowserRenderImageSI(ih);
+ iColorBrowserUpdateDisplay(ih);
+ }
+
+ return 0;
+}
+
+static char* iColorBrowserGetRGBAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(20);
+ sprintf(buffer, "%d %d %d", (int) ih->data->red, (int) ih->data->green, (int) ih->data->blue);
+ return buffer;
+}
+
+static int iColorBrowserSetRGBAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char r, g, b;
+ if (!iupStrToRGB(value, &r, &g, &b))
+ return 0;
+
+ ih->data->red = r;
+ ih->data->green = g;
+ ih->data->blue = b;
+ iColorBrowserRGB2HSI(ih);
+
+ if (ih->data->cddbuffer)
+ {
+ iColorBrowserUpdateCursorHue(ih);
+ iColorBrowserUpdateCursorSI(ih);
+ iColorBrowserRenderImageSI(ih);
+ iColorBrowserUpdateDisplay(ih);
+ }
+
+ return 0;
+}
+
+static int iColorBrowserSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = iupControlBaseGetParentBgColor(ih);
+ ih->data->bgcolor = cdIupConvertColor(value);
+
+ if (ih->data->cddbuffer)
+ {
+ iColorBrowserRenderImageHue(ih);
+ iColorBrowserRenderImageSI(ih);
+ iColorBrowserUpdateDisplay(ih);
+ }
+ return 1;
+}
+
+static int iColorBrowserSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ iupBaseSetActiveAttrib(ih, value);
+ iColorBrowserUpdateDisplay(ih);
+ return 0; /* do not store value in hash table */
+}
+
+
+/****************************************************************************/
+
+
+static int iColorBrowserMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFERRGB, ih->data->cdcanvas);
+
+ if (ih->data->cddbuffer)
+ iColorBrowserUpdateSize(ih);
+
+ return IUP_NOERROR;
+}
+
+static void iColorBrowserUnMapMethod(Ihandle* ih)
+{
+ if (ih->data->cddbuffer)
+ cdKillCanvas(ih->data->cddbuffer);
+
+ if (ih->data->cdcanvas)
+ cdKillCanvas(ih->data->cdcanvas);
+}
+
+static int iColorBrowserCreateMethod(Ihandle* ih, void **params)
+{
+ (void)params;
+
+ /* free the data allocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ IupSetfAttribute(ih, "RASTERSIZE", "%dx%d", ICB_DEFAULTSIZE, ICB_DEFAULTSIZE);
+ iupAttribSetStr(ih, "BORDER", "NO");
+ ih->expand = IUP_EXPAND_NONE;
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "ACTION", (Icallback)iColorBrowserRedraw_CB);
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iColorBrowserResize_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iColorBrowserButton_CB);
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iColorBrowserMotion_CB);
+ IupSetCallback(ih, "FOCUS_CB", (Icallback)iColorBrowserFocus_CB);
+ IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iColorBrowserKeypress_CB);
+ IupSetCallback(ih, "WHEEL_CB", (Icallback)iColorBrowserWheel_CB);
+
+ return IUP_NOERROR;
+}
+
+Iclass* iupColorBrowserGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "colorbrowser";
+ ic->format = NULL; /* no parameters */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+
+ /* Class functions */
+ ic->Create = iColorBrowserCreateMethod;
+ ic->Map = iColorBrowserMapMethod;
+ ic->UnMap = iColorBrowserUnMapMethod;
+
+ /* IupColorBrowser Callbacks */
+ iupClassRegisterCallback(ic, "DRAG_CB", "ccc");
+ iupClassRegisterCallback(ic, "CHANGE_CB", "ccc");
+ iupClassRegisterCallback(ic, "VALUECHANGED_CB", "");
+
+ /* IupColorBrowser only */
+ iupClassRegisterAttribute(ic, "RGB", iColorBrowserGetRGBAttrib, iColorBrowserSetRGBAttrib, "255 0 0", NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* force new default value */
+ iupClassRegisterAttribute(ic, "HSI", iColorBrowserGetHSIAttrib, iColorBrowserSetHSIAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iColorBrowserSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupControlBaseGetBgColorAttrib, iColorBrowserSetBgColorAttrib, NULL, "255 255 255", IUPAF_NO_INHERIT); /* overwrite canvas implementation, set a system default to force a new default */
+
+ return ic;
+}
+
+Ihandle *IupColorBrowser(void)
+{
+ return IupCreate("colorbrowser");
+}
diff --git a/iup/srccontrols/color/iup_colorbrowserdlg.c b/iup/srccontrols/color/iup_colorbrowserdlg.c
new file mode 100755
index 0000000..65e4d37
--- /dev/null
+++ b/iup/srccontrols/color/iup_colorbrowserdlg.c
@@ -0,0 +1,1120 @@
+/** \file
+ * \brief IupColorDlg pre-defined dialog control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+#include "iupcontrols.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+#include <cdirgb.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_strmessage.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+#include "iup_register.h"
+#include "iup_register.h"
+#include "iup_image.h"
+#include "iup_colorhsi.h"
+#include "iup_childtree.h"
+
+
+const char* default_colortable_cells[20] =
+{
+ "0 0 0", "64 64 64", "128 128 128", "144 144 144", "0 128 128", "128 0 128", "128 128 0", "128 0 0", "0 128 0", "0 0 128",
+ "255 255 255", "240 240 240", "224 224 224", "192 192 192", "0 255 255", "255 0 255", "255 255 0", "255 0 0", "0 255 0", "0 0 255"
+};
+
+typedef struct _IcolorDlgData
+{
+ int status;
+
+ long previous_color, color;
+
+ float hue, saturation, intensity;
+ unsigned char red, green, blue, alpha;
+
+ Ihandle *red_txt, *green_txt, *blue_txt, *alpha_txt;
+ Ihandle *hue_txt, *intensity_txt, *saturation_txt;
+ Ihandle *color_browser, *color_cnv, *colorhex_txt;
+ Ihandle *colortable_cbar, *alpha_val;
+ Ihandle *help_bt;
+
+ cdCanvas* color_cdcanvas, *color_cddbuffer;
+} IcolorDlgData;
+
+
+static void iColorBrowserDlgColorCnvRepaint(IcolorDlgData* colordlg_data)
+{
+ int x, y, w, h, width, height, box_size = 10;
+
+ if (!colordlg_data->color_cddbuffer)
+ return;
+
+ cdCanvasGetSize(colordlg_data->color_cddbuffer, &width, &height, NULL, NULL);
+
+ cdCanvasBackground(colordlg_data->color_cddbuffer, CD_WHITE);
+ cdCanvasClear(colordlg_data->color_cddbuffer);
+
+ w = (width+box_size-1)/box_size;
+ h = (height+box_size-1)/box_size;
+
+ cdCanvasForeground(colordlg_data->color_cddbuffer, CD_GRAY);
+
+ for (y = 0; y < h; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ if (((x%2) && (y%2)) || (((x+1)%2) && ((y+1)%2)))
+ {
+ int xmin, xmax, ymin, ymax;
+
+ xmin = x*box_size;
+ xmax = xmin+box_size;
+ ymin = y*box_size;
+ ymax = ymin+box_size;
+
+ cdCanvasBox(colordlg_data->color_cddbuffer, xmin, xmax, ymin, ymax);
+ }
+ }
+ }
+
+ cdCanvasForeground(colordlg_data->color_cddbuffer, colordlg_data->previous_color);
+ cdCanvasBox(colordlg_data->color_cddbuffer, 0, width/2, 0, height);
+
+ cdCanvasForeground(colordlg_data->color_cddbuffer, colordlg_data->color);
+ cdCanvasBox(colordlg_data->color_cddbuffer, width/2+1, width, 0, height);
+
+ cdCanvasFlush(colordlg_data->color_cddbuffer);
+}
+
+static void iColorBrowserDlgHSI2RGB(IcolorDlgData* colordlg_data)
+{
+ iupColorHSI2RGB(colordlg_data->hue, colordlg_data->saturation, colordlg_data->intensity,
+ &colordlg_data->red, &colordlg_data->green, &colordlg_data->blue);
+}
+
+static void iColorBrowserDlgRGB2HSI(IcolorDlgData* colordlg_data)
+{
+ iupColorRGB2HSI(colordlg_data->red, colordlg_data->green, colordlg_data->blue,
+ &(colordlg_data->hue), &(colordlg_data->saturation), &(colordlg_data->intensity));
+}
+
+static void iColorBrowserDlgHex_TXT_Update(IcolorDlgData* colordlg_data)
+{
+ IupSetfAttribute(colordlg_data->colorhex_txt, "VALUE", "#%02X%02X%02X", (int)colordlg_data->red, (int)colordlg_data->green, (int)colordlg_data->blue);
+}
+
+static int iupStrHexToRGB(const char *str, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ unsigned int ri = 0, gi = 0, bi = 0;
+ if (!str) return 0;
+ if (sscanf(str, "#%2X%2X%2X", &ri, &gi, &bi) != 3) return 0;
+ if (ri > 255 || gi > 255 || bi > 255) return 0;
+ *r = (unsigned char)ri;
+ *g = (unsigned char)gi;
+ *b = (unsigned char)bi;
+ return 1;
+}
+
+/*************************************************\
+* Updates text fields with the current HSI values *
+\*************************************************/
+static void iColorBrowserDlgHSI_TXT_Update(IcolorDlgData* colordlg_data)
+{
+ IupSetfAttribute(colordlg_data->hue_txt, "VALUE", "%d", iupROUND(colordlg_data->hue));
+ IupSetfAttribute(colordlg_data->saturation_txt, "VALUE", "%d", iupROUND(colordlg_data->saturation * 100));
+ IupSetfAttribute(colordlg_data->intensity_txt, "VALUE", "%d", iupROUND(colordlg_data->intensity * 100));
+}
+
+/*************************************************\
+* Updates text fields with the current RGB values *
+\*************************************************/
+static void iColorBrowserDlgRGB_TXT_Update(IcolorDlgData* colordlg_data)
+{
+ IupSetfAttribute(colordlg_data->red_txt, "VALUE", "%d", (int) colordlg_data->red);
+ IupSetfAttribute(colordlg_data->green_txt, "VALUE", "%d", (int) colordlg_data->green);
+ IupSetfAttribute(colordlg_data->blue_txt, "VALUE", "%d", (int) colordlg_data->blue);
+}
+
+static void iColorBrowserDlgBrowserRGB_Update(IcolorDlgData* colordlg_data)
+{
+ IupSetfAttribute(colordlg_data->color_browser, "RGB", "%d %d %d", colordlg_data->red, colordlg_data->green, colordlg_data->blue);
+}
+
+static void iColorBrowserDlgBrowserHSI_Update(IcolorDlgData* colordlg_data)
+{
+ IupSetfAttribute(colordlg_data->color_browser, "HSI", "%f %f %f", (double)colordlg_data->hue, (double)colordlg_data->saturation, (double)colordlg_data->intensity);
+}
+
+/*****************************************\
+* Sets the RGB color in the Color Canvas *
+\*****************************************/
+static void iColorBrowserDlgColor_Update(IcolorDlgData* colordlg_data)
+{
+ colordlg_data->color = cdEncodeColor(colordlg_data->red, colordlg_data->green, colordlg_data->blue);
+ colordlg_data->color = cdEncodeAlpha(colordlg_data->color, colordlg_data->alpha);
+ iColorBrowserDlgColorCnvRepaint(colordlg_data);
+}
+
+static void iColorBrowserDlgHSIChanged(IcolorDlgData* colordlg_data)
+{
+ iColorBrowserDlgHSI2RGB(colordlg_data);
+ iColorBrowserDlgBrowserHSI_Update(colordlg_data);
+ iColorBrowserDlgHex_TXT_Update(colordlg_data);
+ iColorBrowserDlgRGB_TXT_Update(colordlg_data);
+ iColorBrowserDlgColor_Update(colordlg_data);
+}
+
+static void iColorBrowserDlgRGBChanged(IcolorDlgData* colordlg_data)
+{
+ iColorBrowserDlgRGB2HSI(colordlg_data);
+ iColorBrowserDlgBrowserRGB_Update(colordlg_data);
+ iColorBrowserDlgHex_TXT_Update(colordlg_data);
+ iColorBrowserDlgHSI_TXT_Update(colordlg_data);
+ iColorBrowserDlgColor_Update(colordlg_data);
+}
+
+/***********************************************\
+* Initializes the default values to the element *
+\***********************************************/
+static void iColorBrowserDlgInit_Defaults(IcolorDlgData* colordlg_data)
+{
+ char* str = iupStrGetMemory(100);
+ Ihandle* box;
+ int i;
+
+ IupSetAttribute(colordlg_data->color_browser, "RGB", "0 0 0");
+
+ IupSetAttribute(colordlg_data->red_txt, "VALUE", "0");
+ IupSetAttribute(colordlg_data->green_txt, "VALUE", "0");
+ IupSetAttribute(colordlg_data->blue_txt, "VALUE", "0");
+
+ IupSetAttribute(colordlg_data->hue_txt, "VALUE", "0");
+ IupSetAttribute(colordlg_data->saturation_txt, "VALUE", "0");
+ IupSetAttribute(colordlg_data->intensity_txt, "VALUE", "0");
+
+ IupSetAttribute(colordlg_data->colorhex_txt, "VALUE", "#000000");
+
+ colordlg_data->alpha = 255;
+ IupSetAttribute(colordlg_data->alpha_val, "VALUE", "255");
+ IupSetAttribute(colordlg_data->alpha_txt, "VALUE", "255");
+
+ box = IupGetParent(colordlg_data->alpha_val);
+ IupSetAttribute(box, "FLOATING", "YES");
+ IupSetAttribute(box, "VISIBLE", "NO");
+
+ box = IupGetParent(colordlg_data->colortable_cbar);
+ IupSetAttribute(box, "FLOATING", "YES");
+ IupSetAttribute(box, "VISIBLE", "NO");
+
+ box = IupGetParent(colordlg_data->colorhex_txt);
+ IupSetAttribute(box, "FLOATING", "YES");
+ IupSetAttribute(box, "VISIBLE", "NO");
+
+ for(i = 0; i < 20; i++)
+ {
+ sprintf(str, "CELL%d", i);
+ IupSetAttribute(colordlg_data->colortable_cbar, str, default_colortable_cells[i]);
+ }
+}
+
+
+/**************************************************************************************************************/
+/* Internal Callbacks */
+/**************************************************************************************************************/
+
+
+static int iColorBrowserDlgButtonOK_CB(Ihandle* ih)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ colordlg_data->status = 1;
+ return IUP_CLOSE;
+}
+
+static int iColorBrowserDlgButtonCancel_CB(Ihandle* ih)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ colordlg_data->status = 0;
+ return IUP_CLOSE;
+}
+
+static int iColorBrowserDlgButtonHelp_CB(Ihandle* ih)
+{
+ Icallback cb = IupGetCallback(IupGetDialog(ih), "HELP_CB");
+ if (cb && cb(ih) == IUP_CLOSE)
+ {
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ colordlg_data->status = 0;
+ return IUP_CLOSE;
+ }
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgColorCnvRedraw_CB(Ihandle* ih)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ if (!colordlg_data->color_cddbuffer)
+ return IUP_DEFAULT;
+
+ cdCanvasActivate(colordlg_data->color_cddbuffer);
+
+ iColorBrowserDlgColorCnvRepaint(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgRedAction_CB(Ihandle* ih, int c, char *value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int vi;
+
+ if (iupStrToInt(value, &vi))
+ {
+ colordlg_data->red = (unsigned char)vi;
+ iColorBrowserDlgRGBChanged(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgRedSpin_CB(Ihandle* ih, int vi)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->red = (unsigned char)vi;
+ iColorBrowserDlgRGBChanged(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgGreenAction_CB(Ihandle* ih, int c, char *value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int vi;
+
+ if (iupStrToInt(value, &vi))
+ {
+ colordlg_data->green = (unsigned char)vi;
+ iColorBrowserDlgRGBChanged(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgGreenSpin_CB(Ihandle* ih, int vi)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->green = (unsigned char)vi;
+ iColorBrowserDlgRGBChanged(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgBlueAction_CB(Ihandle* ih, int c, char *value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int vi;
+
+ if (iupStrToInt(value, &vi))
+ {
+ colordlg_data->blue = (unsigned char)vi;
+ iColorBrowserDlgRGBChanged(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgBlueSpin_CB(Ihandle* ih, int vi)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->blue = (unsigned char)vi;
+ iColorBrowserDlgRGBChanged(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgHueAction_CB(Ihandle* ih, int c, char *value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int vi;
+
+ if (iupStrToInt(value, &vi))
+ {
+ colordlg_data->hue = (float)vi;
+ iColorBrowserDlgHSIChanged(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgHueSpin_CB(Ihandle* ih, int vi)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->hue = (float)vi;
+ iColorBrowserDlgHSIChanged(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgSaturationAction_CB(Ihandle* ih, int c, char *value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int vi;
+
+ if (iupStrToInt(value, &vi))
+ {
+ colordlg_data->saturation = (float)vi/100.0f;
+ iColorBrowserDlgHSIChanged(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgSaturationSpin_CB(Ihandle* ih, int vi)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->saturation = (float)vi/100.0f;
+ iColorBrowserDlgHSIChanged(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgIntensityAction_CB(Ihandle* ih, int c, char *value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int vi;
+
+ if (iupStrToInt(value, &vi))
+ {
+ colordlg_data->intensity = (float)vi/100.0f;
+ iColorBrowserDlgHSIChanged(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgIntensitySpin_CB(Ihandle* ih, int vi)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->intensity = (float)vi/100.0f;
+ iColorBrowserDlgHSIChanged(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgHexAction_CB(Ihandle* ih, int c, char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ if (iupStrHexToRGB(value, &colordlg_data->red, &colordlg_data->green, &colordlg_data->blue))
+ {
+ iColorBrowserDlgRGB2HSI(colordlg_data);
+ iColorBrowserDlgBrowserRGB_Update(colordlg_data);
+ iColorBrowserDlgHSI_TXT_Update(colordlg_data);
+ iColorBrowserDlgRGB_TXT_Update(colordlg_data);
+ iColorBrowserDlgColor_Update(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgColorSelDrag_CB(Ihandle* ih, unsigned char r, unsigned char g, unsigned char b)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->red = r;
+ colordlg_data->green = g;
+ colordlg_data->blue = b;
+
+ iColorBrowserDlgRGB2HSI(colordlg_data);
+ iColorBrowserDlgHex_TXT_Update(colordlg_data);
+ iColorBrowserDlgHSI_TXT_Update(colordlg_data);
+ iColorBrowserDlgRGB_TXT_Update(colordlg_data);
+
+ colordlg_data->color = cdEncodeColor(colordlg_data->red,colordlg_data->green,colordlg_data->blue);
+ colordlg_data->color = cdEncodeAlpha(colordlg_data->color, colordlg_data->alpha);
+ iColorBrowserDlgColorCnvRepaint(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgAlphaVal_CB(Ihandle* ih, double val)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->alpha = (unsigned char)val;
+ IupSetfAttribute(colordlg_data->alpha_txt, "VALUE", "%d", (int)colordlg_data->alpha);
+
+ colordlg_data->color = cdEncodeAlpha(colordlg_data->color, colordlg_data->alpha);
+ iColorBrowserDlgColorCnvRepaint(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgAlphaAction_CB(Ihandle* ih, int c, char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int vi;
+
+ if (iupStrToInt(value, &vi))
+ {
+ colordlg_data->alpha = (unsigned char)vi;
+ IupSetfAttribute(colordlg_data->alpha_val, "VALUE", "%d", (int)colordlg_data->alpha);
+
+ colordlg_data->color = cdEncodeAlpha(colordlg_data->color, colordlg_data->alpha);
+ iColorBrowserDlgColorCnvRepaint(colordlg_data);
+ }
+
+ (void)c;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgAlphaSpin_CB(Ihandle* ih, int vi)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ colordlg_data->alpha = (unsigned char)vi;
+ IupSetfAttribute(colordlg_data->alpha_val, "VALUE", "%d", (int)colordlg_data->alpha);
+
+ colordlg_data->color = cdEncodeAlpha(colordlg_data->color, colordlg_data->alpha);
+ iColorBrowserDlgColorCnvRepaint(colordlg_data);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgColorTableSelect_CB(Ihandle* ih, int cell, int type)
+{
+ char* str = iupStrGetMemory(30);
+
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ sprintf(str, "CELL%d", cell);
+ iupStrToRGB(IupGetAttribute(ih, str), &colordlg_data->red, &colordlg_data->green, &colordlg_data->blue);
+
+ iColorBrowserDlgRGB_TXT_Update(colordlg_data);
+ iColorBrowserDlgRGBChanged(colordlg_data);
+
+ (void)type;
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgColorCnvButton_CB(Ihandle* ih, int b, int press, int x, int y)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int width;
+ (void)y;
+
+ if (b != IUP_BUTTON1 || !press || !colordlg_data->color_cddbuffer)
+ return IUP_DEFAULT;
+
+ cdCanvasGetSize(colordlg_data->color_cddbuffer, &width, NULL, NULL, NULL);
+
+ if (x < width/2)
+ {
+ /* reset color to previous */
+ colordlg_data->red = cdRed(colordlg_data->previous_color);
+ colordlg_data->green = cdGreen(colordlg_data->previous_color);
+ colordlg_data->blue = cdBlue(colordlg_data->previous_color);
+ colordlg_data->alpha = cdAlpha(colordlg_data->previous_color);
+
+ IupSetfAttribute(colordlg_data->alpha_txt, "VALUE", "%d", (int)colordlg_data->alpha);
+ IupSetfAttribute(colordlg_data->alpha_val, "VALUE", "%d", (int)colordlg_data->alpha);
+
+ iColorBrowserDlgRGB_TXT_Update(colordlg_data);
+ iColorBrowserDlgRGBChanged(colordlg_data);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgColorCnvMap_CB(Ihandle* ih)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ /* Create Canvas */
+ colordlg_data->color_cdcanvas = cdCreateCanvas(CD_IUP, colordlg_data->color_cnv);
+
+ if (!colordlg_data->color_cdcanvas)
+ return IUP_DEFAULT;
+
+ /* this can fail if canvas size is zero */
+ colordlg_data->color_cddbuffer = cdCreateCanvas(CD_DBUFFERRGB, colordlg_data->color_cdcanvas);
+ return IUP_DEFAULT;
+}
+
+static int iColorBrowserDlgColorCnvUnMap_CB(Ihandle* ih)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ if (colordlg_data->color_cddbuffer)
+ cdKillCanvas(colordlg_data->color_cddbuffer);
+
+ if (colordlg_data->color_cdcanvas)
+ cdKillCanvas(colordlg_data->color_cdcanvas);
+
+ return IUP_DEFAULT;
+}
+
+
+/**************************************************************************************************************/
+/* Attributes */
+/**************************************************************************************************************/
+
+
+static char* iColorBrowserDlgGetStatusAttrib(Ihandle* ih)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ if (colordlg_data->status)
+ return "1";
+ else
+ return NULL;
+}
+
+static int iColorBrowserDlgSetShowHelpAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ IupSetAttribute(colordlg_data->help_bt, "VISIBLE", iupStrBoolean(value)? "YES": "NO");
+ return 1;
+}
+
+static int iColorBrowserDlgSetShowHexAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ /* valid only before map */
+ if (ih->handle)
+ return 1;
+
+ if (iupStrBoolean(value))
+ {
+ Ihandle* box = IupGetParent(colordlg_data->colorhex_txt);
+ IupSetAttribute(box, "FLOATING", NULL);
+ IupSetAttribute(box, "VISIBLE", "YES");
+ }
+
+ return 1;
+}
+
+static int iColorBrowserDlgSetShowColorTableAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ /* valid only before map */
+ if (ih->handle)
+ return 1;
+
+ if (iupStrBoolean(value))
+ {
+ Ihandle* box = IupGetParent(colordlg_data->colortable_cbar);
+ IupSetAttribute(box, "FLOATING", NULL);
+ IupSetAttribute(box, "VISIBLE", "YES");
+ }
+
+ return 1;
+}
+
+static int iColorBrowserDlgSetShowAlphaAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ /* valid only before map */
+ if (ih->handle)
+ return 1;
+
+ if (iupStrBoolean(value))
+ {
+ Ihandle* box = IupGetParent(colordlg_data->alpha_val);
+ IupSetAttribute(box, "FLOATING", NULL);
+ IupSetAttribute(box, "VISIBLE", "YES");
+ }
+
+ return 1;
+}
+
+static int iColorBrowserDlgSetAlphaAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int alpha;
+ if (iupStrToInt(value, &alpha))
+ {
+ colordlg_data->alpha = (unsigned char)alpha;
+ IupSetfAttribute(colordlg_data->alpha_txt, "VALUE", "%d", (int)colordlg_data->alpha);
+ IupSetfAttribute(colordlg_data->alpha_val, "VALUE", "%d", (int)colordlg_data->alpha);
+
+ colordlg_data->color = cdEncodeAlpha(colordlg_data->color, colordlg_data->alpha);
+ colordlg_data->previous_color = cdEncodeAlpha(colordlg_data->previous_color, colordlg_data->alpha);
+ iColorBrowserDlgColorCnvRepaint(colordlg_data);
+
+ if (!ih->handle) /* do it only before map */
+ IupSetAttribute(ih, "SHOWALPHA", "YES");
+ }
+
+ return 1;
+}
+
+static char* iColorBrowserDlgGetAlphaAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ sprintf(buffer, "%d", (int)colordlg_data->alpha);
+ return buffer;
+}
+
+static int iColorBrowserDlgSetValueAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int ret = iupStrToRGBA(value, &colordlg_data->red, &colordlg_data->green, &colordlg_data->blue, &colordlg_data->alpha);
+ if (!ret)
+ return 0;
+
+ colordlg_data->previous_color = cdEncodeColor(colordlg_data->red, colordlg_data->green, colordlg_data->blue);
+ colordlg_data->previous_color = cdEncodeAlpha(colordlg_data->previous_color, colordlg_data->alpha);
+
+ if (ret == 4)
+ {
+ IupSetfAttribute(colordlg_data->alpha_txt, "VALUE", "%d", (int)colordlg_data->alpha);
+ IupSetfAttribute(colordlg_data->alpha_val, "VALUE", "%d", (int)colordlg_data->alpha);
+
+ if (!ih->handle) /* do it only before map */
+ IupSetAttribute(ih, "SHOWALPHA", "YES");
+ }
+
+ iColorBrowserDlgRGB_TXT_Update(colordlg_data);
+ iColorBrowserDlgRGBChanged(colordlg_data);
+
+ return 0;
+}
+
+static char* iColorBrowserDlgGetValueAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ if (iupAttribGetBoolean(ih, "SHOWALPHA"))
+ sprintf(buffer, "%d %d %d %d", (int)colordlg_data->red, (int)colordlg_data->green, (int)colordlg_data->blue, (int)colordlg_data->alpha);
+ else
+ sprintf(buffer, "%d %d %d", (int)colordlg_data->red, (int)colordlg_data->green, (int)colordlg_data->blue);
+ return buffer;
+}
+
+static int iupStrToHSI_Int(const char *str, int *h, int *s, int *i)
+{
+ int fh, fs, fi;
+ if (!str) return 0;
+ if (sscanf(str, "%d %d %d", &fh, &fs, &fi) != 3) return 0;
+ if (fh > 359 || fs > 100 || fi > 100) return 0;
+ if (fh < 0 || fs < 0 || fi < 0) return 0;
+ *h = fh;
+ *s = fs;
+ *i = fi;
+ return 1;
+}
+
+static int iColorBrowserDlgSetValueHSIAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ int hue, saturation, intensity;
+
+ if (!iupStrToHSI_Int(value, &hue, &saturation, &intensity))
+ return 0;
+
+ colordlg_data->hue = (float)hue;
+ colordlg_data->saturation = (float)saturation/100.0f;
+ colordlg_data->intensity = (float)intensity/100.0f;
+
+ iColorBrowserDlgHSI2RGB(colordlg_data);
+ colordlg_data->previous_color = cdEncodeColor(colordlg_data->red, colordlg_data->green, colordlg_data->blue);
+ colordlg_data->previous_color = cdEncodeAlpha(colordlg_data->previous_color, colordlg_data->alpha);
+
+ iColorBrowserDlgHSIChanged(colordlg_data);
+ return 0;
+}
+
+static char* iColorBrowserDlgGetValueHSIAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ sprintf(buffer, "%d %d %d", (int)colordlg_data->hue, (int)(colordlg_data->saturation*100), (int)(colordlg_data->intensity*100));
+ return buffer;
+}
+
+static int iColorBrowserDlgSetValueHexAttrib(Ihandle* ih, const char* value)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ if (!iupStrHexToRGB(value, &colordlg_data->red, &colordlg_data->green, &colordlg_data->blue))
+ return 0;
+
+ colordlg_data->previous_color = cdEncodeColor(colordlg_data->red, colordlg_data->green, colordlg_data->blue);
+ colordlg_data->previous_color = cdEncodeAlpha(colordlg_data->previous_color, colordlg_data->alpha);
+
+ iColorBrowserDlgRGB2HSI(colordlg_data);
+ iColorBrowserDlgBrowserRGB_Update(colordlg_data);
+ iColorBrowserDlgHSI_TXT_Update(colordlg_data);
+ iColorBrowserDlgRGB_TXT_Update(colordlg_data);
+ iColorBrowserDlgColor_Update(colordlg_data);
+ return 0;
+}
+
+static char* iColorBrowserDlgGetValueHexAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ sprintf(buffer, "#%02X%02X%02X", (int)colordlg_data->red, (int)colordlg_data->green, (int)colordlg_data->blue);
+ return buffer;
+}
+
+static char* iColorBrowserDlgGetColorTableAttrib(Ihandle* ih)
+{
+ int i, inc, off = 0;
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ char* color_str, attrib_str[30];
+ char* str = iupStrGetMemory(300);
+ for (i=0; i < 20; i++)
+ {
+ sprintf(attrib_str, "CELL%d", i);
+ color_str = IupGetAttribute(colordlg_data->colortable_cbar, attrib_str);
+ inc = strlen(color_str);
+ memcpy(str+off, color_str, inc);
+ memcpy(str+off+inc, ";", 1);
+ off += inc+1;
+ }
+ str[off-1] = 0; /* remove last separator */
+ return str;
+}
+
+static int iColorBrowserDlgSetColorTableAttrib(Ihandle* ih, const char* value)
+{
+ int i = 0;
+ unsigned char r, g, b;
+ char str[30];
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+
+ if (!ih->handle) /* do it only before map */
+ iColorBrowserDlgSetShowColorTableAttrib(ih, "YES");
+
+ while (value && *value && i < 20)
+ {
+ if (iupStrToRGB(value, &r, &g, &b))
+ {
+ sprintf(str, "CELL%d", i);
+ IupSetfAttribute(colordlg_data->colortable_cbar, str, "%d %d %d", (int)r, (int)g, (int)b);
+ }
+
+ value = strchr(value, ';');
+ if (value) value++;
+ i++;
+ }
+
+ return 1;
+}
+
+
+/**************************************************************************************************************/
+/* Methods */
+/**************************************************************************************************************/
+
+static int iColorBrowserDlgMapMethod(Ihandle* ih)
+{
+ if (!IupGetCallback(ih, "HELP_CB"))
+ {
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ IupSetAttribute(colordlg_data->help_bt, "VISIBLE", "NO");
+ }
+
+ return IUP_NOERROR;
+}
+
+static void iColorBrowserDlgDestroyMethod(Ihandle* ih)
+{
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ free(colordlg_data);
+}
+
+static int iColorBrowserDlgCreateMethod(Ihandle* ih, void** params)
+{
+ Ihandle *ok_bt, *cancel_bt;
+ Ihandle *rgb_vb, *hsi_vb, *clr_vb;
+ Ihandle *lin1, *lin2, *col1, *col2;
+
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)malloc(sizeof(IcolorDlgData));
+ memset(colordlg_data, 0, sizeof(IcolorDlgData));
+ iupAttribSetStr(ih, "_IUP_GC_DATA", (char*)colordlg_data);
+
+ /* ======================================================================= */
+ /* BUTTONS ============================================================= */
+ /* ======================================================================= */
+ ok_bt = IupButton("OK", NULL); /* Ok Button */
+ IupSetAttribute(ok_bt, "PADDING", "20x0");
+ IupSetCallback (ok_bt, "ACTION", (Icallback)iColorBrowserDlgButtonOK_CB);
+ IupSetAttributeHandle(ih, "DEFAULTENTER", ok_bt);
+
+ cancel_bt = IupButton(iupStrMessageGet("IUP_CANCEL"), NULL); /* Cancel Button */
+ IupSetAttribute(cancel_bt, "PADDING", "20x0");
+ IupSetCallback (cancel_bt, "ACTION", (Icallback)iColorBrowserDlgButtonCancel_CB);
+ IupSetAttributeHandle(ih, "DEFAULTESC", cancel_bt);
+
+ colordlg_data->help_bt = IupButton(iupStrMessageGet("IUP_HELP"), NULL); /* Help Button */
+ IupSetAttribute(colordlg_data->help_bt, "PADDING", "20x0");
+ IupSetCallback (colordlg_data->help_bt, "ACTION", (Icallback)iColorBrowserDlgButtonHelp_CB);
+
+ /* ======================================================================= */
+ /* COLOR =============================================================== */
+ /* ======================================================================= */
+ colordlg_data->color_browser = IupColorBrowser();
+ IupSetAttribute(colordlg_data->color_browser, "EXPAND", "YES");
+ IupSetCallback(colordlg_data->color_browser, "DRAG_CB", (Icallback)iColorBrowserDlgColorSelDrag_CB);
+ IupSetCallback(colordlg_data->color_browser, "CHANGE_CB", (Icallback)iColorBrowserDlgColorSelDrag_CB);
+
+ colordlg_data->color_cnv = IupCanvas(NULL); /* Canvas of the color */
+ IupSetAttribute(colordlg_data->color_cnv, "SIZE", "x12");
+ IupSetAttribute(colordlg_data->color_cnv, "CANFOCUS", "NO");
+ IupSetAttribute(colordlg_data->color_cnv, "EXPAND", "HORIZONTAL");
+ IupSetCallback (colordlg_data->color_cnv, "ACTION", (Icallback)iColorBrowserDlgColorCnvRedraw_CB);
+ IupSetCallback (colordlg_data->color_cnv, "MAP_CB", (Icallback)iColorBrowserDlgColorCnvMap_CB);
+ IupSetCallback (colordlg_data->color_cnv, "UNMAP_CB", (Icallback)iColorBrowserDlgColorCnvUnMap_CB);
+ IupSetCallback (colordlg_data->color_cnv, "BUTTON_CB", (Icallback)iColorBrowserDlgColorCnvButton_CB);
+
+ colordlg_data->colorhex_txt = IupText(NULL); /* Hex of the color */
+ IupSetAttribute(colordlg_data->colorhex_txt, "VISIBLECOLUMNS", "7");
+ IupSetCallback (colordlg_data->colorhex_txt, "ACTION", (Icallback)iColorBrowserDlgHexAction_CB);
+ IupSetAttribute(colordlg_data->colorhex_txt, "MASK", "#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]");
+
+ /* ======================================================================= */
+ /* ALPHA TRANSPARENCY ================================================== */
+ /* ======================================================================= */
+ colordlg_data->alpha_val = IupVal("HORIZONTAL");
+ IupSetAttribute(colordlg_data->alpha_val, "EXPAND", "HORIZONTAL");
+ IupSetAttribute(colordlg_data->alpha_val, "MIN", "0");
+ IupSetAttribute(colordlg_data->alpha_val, "MAX", "255");
+ IupSetAttribute(colordlg_data->alpha_val, "VALUE", "255");
+ IupSetAttribute(colordlg_data->alpha_val, "SIZE", "80x12");
+ IupSetCallback (colordlg_data->alpha_val, "MOUSEMOVE_CB", (Icallback)iColorBrowserDlgAlphaVal_CB);
+ IupSetCallback (colordlg_data->alpha_val, "BUTTON_PRESS_CB", (Icallback)iColorBrowserDlgAlphaVal_CB);
+ IupSetCallback (colordlg_data->alpha_val, "BUTTON_RELEASE_CB", (Icallback)iColorBrowserDlgAlphaVal_CB);
+
+ colordlg_data->alpha_txt = IupText(NULL); /* Alpha value */
+ IupSetAttribute(colordlg_data->alpha_txt, "VISIBLECOLUMNS", "3");
+ IupSetAttribute(colordlg_data->alpha_txt, "SPIN", "YES");
+ IupSetAttribute(colordlg_data->alpha_txt, "SPINMIN", "0");
+ IupSetAttribute(colordlg_data->alpha_txt, "SPINMAX", "255");
+ IupSetAttribute(colordlg_data->alpha_txt, "SPININC", "1");
+ IupSetCallback (colordlg_data->alpha_txt, "ACTION", (Icallback)iColorBrowserDlgAlphaAction_CB);
+ IupSetCallback (colordlg_data->alpha_txt, "SPIN_CB", (Icallback)iColorBrowserDlgAlphaSpin_CB);
+ IupSetAttribute(colordlg_data->alpha_txt, "MASKINT", "0:255");
+
+ /* ======================================================================= */
+ /* COLOR TABLE ========================================================= */
+ /* ======================================================================= */
+ colordlg_data->colortable_cbar = IupColorbar();
+ IupSetAttribute(colordlg_data->colortable_cbar, "ORIENTATION", "HORIZONTAL");
+ IupSetAttribute(colordlg_data->colortable_cbar, "NUM_PARTS", "2");
+ IupSetAttribute(colordlg_data->colortable_cbar, "NUM_CELLS", "20");
+ IupSetAttribute(colordlg_data->colortable_cbar, "SHOW_PREVIEW", "NO");
+ IupSetAttribute(colordlg_data->colortable_cbar, "SIZE", "138x22");
+ IupSetAttribute(colordlg_data->colortable_cbar, "SQUARED", "NO");
+ IupSetCallback (colordlg_data->colortable_cbar, "SELECT_CB", (Icallback)iColorBrowserDlgColorTableSelect_CB);
+
+ /* ======================================================================= */
+ /* RGB TEXT FIELDS ===================================================== */
+ /* ======================================================================= */
+ colordlg_data->red_txt = IupText(NULL); /* Red value */
+ IupSetAttribute(colordlg_data->red_txt, "VISIBLECOLUMNS", "3");
+ IupSetAttribute(colordlg_data->red_txt, "SPIN", "YES");
+ IupSetAttribute(colordlg_data->red_txt, "SPINMIN", "0");
+ IupSetAttribute(colordlg_data->red_txt, "SPINMAX", "255");
+ IupSetAttribute(colordlg_data->red_txt, "SPININC", "1");
+ IupSetCallback (colordlg_data->red_txt, "ACTION", (Icallback)iColorBrowserDlgRedAction_CB);
+ IupSetCallback (colordlg_data->red_txt, "SPIN_CB", (Icallback)iColorBrowserDlgRedSpin_CB);
+ IupSetAttribute(colordlg_data->red_txt, "MASKINT", "0:255");
+
+ colordlg_data->green_txt = IupText(NULL); /* Green value */
+ IupSetAttribute(colordlg_data->green_txt, "VISIBLECOLUMNS", "3");
+ IupSetAttribute(colordlg_data->green_txt, "SPIN", "YES");
+ IupSetAttribute(colordlg_data->green_txt, "SPINMIN", "0");
+ IupSetAttribute(colordlg_data->green_txt, "SPINMAX", "255");
+ IupSetAttribute(colordlg_data->green_txt, "SPININC", "1");
+ IupSetCallback (colordlg_data->green_txt, "ACTION", (Icallback)iColorBrowserDlgGreenAction_CB);
+ IupSetCallback (colordlg_data->green_txt, "SPIN_CB", (Icallback)iColorBrowserDlgGreenSpin_CB);
+ IupSetAttribute(colordlg_data->green_txt, "MASKINT", "0:255");
+
+ colordlg_data->blue_txt = IupText(NULL); /* Blue value */
+ IupSetAttribute(colordlg_data->blue_txt, "VISIBLECOLUMNS", "3");
+ IupSetAttribute(colordlg_data->blue_txt, "SPIN", "YES");
+ IupSetAttribute(colordlg_data->blue_txt, "SPINMIN", "0");
+ IupSetAttribute(colordlg_data->blue_txt, "SPINMAX", "255");
+ IupSetAttribute(colordlg_data->blue_txt, "SPININC", "1");
+ IupSetCallback (colordlg_data->blue_txt, "ACTION", (Icallback)iColorBrowserDlgBlueAction_CB);
+ IupSetCallback (colordlg_data->blue_txt, "SPIN_CB", (Icallback)iColorBrowserDlgBlueSpin_CB);
+ IupSetAttribute(colordlg_data->blue_txt, "MASKINT", "0:255");
+
+ /* ======================================================================= */
+ /* HSI TEXT FIELDS ===================================================== */
+ /* ======================================================================= */
+ colordlg_data->hue_txt = IupText(NULL); /* Hue value */
+ IupSetAttribute(colordlg_data->hue_txt, "VISIBLECOLUMNS", "3");
+ IupSetAttribute(colordlg_data->hue_txt, "SPIN", "YES");
+ IupSetAttribute(colordlg_data->hue_txt, "SPINMIN", "0");
+ IupSetAttribute(colordlg_data->hue_txt, "SPINMAX", "359");
+ IupSetAttribute(colordlg_data->hue_txt, "SPINWRAP", "YES");
+ IupSetAttribute(colordlg_data->hue_txt, "SPININC", "1");
+ IupSetCallback(colordlg_data->hue_txt, "ACTION", (Icallback)iColorBrowserDlgHueAction_CB);
+ IupSetCallback(colordlg_data->hue_txt, "SPIN_CB", (Icallback)iColorBrowserDlgHueSpin_CB);
+ IupSetAttribute(colordlg_data->hue_txt, "MASKINT", "0:359");
+
+ colordlg_data->saturation_txt = IupText(NULL); /* Saturation value */
+ IupSetAttribute(colordlg_data->saturation_txt, "VISIBLECOLUMNS", "3");
+ IupSetAttribute(colordlg_data->saturation_txt, "SPIN", "YES");
+ IupSetAttribute(colordlg_data->saturation_txt, "SPINMIN", "0");
+ IupSetAttribute(colordlg_data->saturation_txt, "SPINMAX", "100");
+ IupSetAttribute(colordlg_data->saturation_txt, "SPININC", "1");
+ IupSetCallback(colordlg_data->saturation_txt, "ACTION", (Icallback)iColorBrowserDlgSaturationAction_CB);
+ IupSetCallback(colordlg_data->saturation_txt, "SPIN_CB", (Icallback)iColorBrowserDlgSaturationSpin_CB);
+ IupSetAttribute(colordlg_data->saturation_txt, "MASKINT", "0:100");
+
+ colordlg_data->intensity_txt = IupText(NULL); /* Intensity value */
+ IupSetAttribute(colordlg_data->intensity_txt, "VISIBLECOLUMNS", "3");
+ IupSetAttribute(colordlg_data->intensity_txt, "SPIN", "YES");
+ IupSetAttribute(colordlg_data->intensity_txt, "SPINMIN", "0");
+ IupSetAttribute(colordlg_data->intensity_txt, "SPINMAX", "100");
+ IupSetAttribute(colordlg_data->intensity_txt, "SPININC", "1");
+ IupSetCallback(colordlg_data->intensity_txt, "ACTION", (Icallback)iColorBrowserDlgIntensityAction_CB);
+ IupSetCallback(colordlg_data->intensity_txt, "SPIN_CB", (Icallback)iColorBrowserDlgIntensitySpin_CB);
+ IupSetAttribute(colordlg_data->intensity_txt, "MASKINT", "0:100");
+
+ /* =================== */
+ /* 1st line = Controls */
+ /* =================== */
+
+ col1 = IupVbox(colordlg_data->color_browser, IupSetAttributes(IupHbox(colordlg_data->color_cnv, NULL), "MARGIN=30x0"),NULL);
+
+ hsi_vb = IupVbox(IupSetAttributes(IupHbox(IupLabel(iupStrMessageGet("IUP_HUE")),
+ colordlg_data->hue_txt,
+ NULL), "ALIGNMENT=ACENTER"),
+ IupSetAttributes(IupHbox(IupLabel(iupStrMessageGet("IUP_SATURATION")),
+ colordlg_data->saturation_txt,
+ NULL), "ALIGNMENT=ACENTER"),
+ IupSetAttributes(IupHbox(IupLabel(iupStrMessageGet("IUP_INTENSITY")),
+ colordlg_data->intensity_txt,
+ NULL), "ALIGNMENT=ACENTER"),
+ NULL);
+ IupSetAttribute(hsi_vb, "GAP", "5");
+
+ rgb_vb = IupVbox(IupSetAttributes(IupHbox(IupLabel(iupStrMessageGet("IUP_RED")),
+ colordlg_data->red_txt,
+ NULL), "ALIGNMENT=ACENTER"),
+ IupSetAttributes(IupHbox(IupLabel(iupStrMessageGet("IUP_GREEN")),
+ colordlg_data->green_txt,
+ NULL), "ALIGNMENT=ACENTER"),
+ IupSetAttributes(IupHbox(IupLabel(iupStrMessageGet("IUP_BLUE")),
+ colordlg_data->blue_txt,
+ NULL), "ALIGNMENT=ACENTER"),
+ NULL);
+ IupSetAttribute(rgb_vb, "GAP", "5");
+
+ clr_vb = IupVbox(IupSetAttributes(IupHbox(IupLabel(iupStrMessageGet("IUP_OPACITY")),
+ colordlg_data->alpha_txt, colordlg_data->alpha_val,
+ NULL), "ALIGNMENT=ACENTER"),
+ IupSetAttributes(IupHbox(IupLabel("He&xa:"),
+ colordlg_data->colorhex_txt,
+ NULL), "ALIGNMENT=ACENTER"),
+ IupSetAttributes(IupVbox(IupLabel(iupStrMessageGet("IUP_PALETTE")),
+ colordlg_data->colortable_cbar,
+ NULL), "GAP=3"),
+ NULL);
+ IupSetAttribute(clr_vb, "GAP", "5");
+ IupSetAttribute(clr_vb, "EXPAND", "YES");
+
+ IupDestroy(IupSetAttributes(IupNormalizer(IupGetChild(IupGetChild(hsi_vb, 0), 0), /* Hue Label */
+ IupGetChild(IupGetChild(hsi_vb, 1), 0), /* Saturation Label */
+ IupGetChild(IupGetChild(hsi_vb, 2), 0), /* Intensity Label */
+ IupGetChild(IupGetChild(clr_vb, 0), 0), /* Opacity Label */
+ IupGetChild(IupGetChild(clr_vb, 1), 0), /* Hexa Label */
+ NULL), "NORMALIZE=HORIZONTAL"));
+
+ IupDestroy(IupSetAttributes(IupNormalizer(IupGetChild(IupGetChild(rgb_vb, 0), 0), /* Red Label */
+ IupGetChild(IupGetChild(rgb_vb, 1), 0), /* Green Label */
+ IupGetChild(IupGetChild(rgb_vb, 2), 0), /* Blue Label */
+ NULL), "NORMALIZE=HORIZONTAL"));
+
+ col2 = IupVbox(IupSetAttributes(IupHbox(hsi_vb, IupFill(), rgb_vb, NULL), "EXPAND=YES"),
+ IupSetAttributes(IupLabel(NULL), "SEPARATOR=HORIZONTAL"),
+ clr_vb,
+ NULL);
+ IupSetAttributes(col2, "EXPAND=NO, GAP=10");
+
+ lin1 = IupHbox(col1, col2, NULL);
+ IupSetAttribute(lin1, "GAP", "10");
+ IupSetAttribute(lin1, "MARGIN", "0x0");
+
+ /* ================== */
+ /* 2nd line = Buttons */
+ /* ================== */
+
+ lin2 = IupHbox(IupFill(), ok_bt, cancel_bt, colordlg_data->help_bt, NULL);
+ IupSetAttribute(lin2, "GAP", "5");
+ IupSetAttribute(lin2, "MARGIN", "0x0");
+ IupSetAttribute(lin2, "NORMALIZESIZE", "HORIZONTAL");
+
+ /* Do not use IupAppend because we set childtype=IUP_CHILDNONE */
+ iupChildTreeAppend(ih, IupSetAttributes(IupVbox(lin1, IupSetAttributes(IupLabel(NULL), "SEPARATOR=HORIZONTAL"), lin2, NULL), "MARGIN=10x10, GAP=10"));
+
+ iColorBrowserDlgInit_Defaults(colordlg_data);
+
+ (void)params;
+ return IUP_NOERROR;
+}
+
+Iclass* iupColorBrowserDlgGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupDialogGetClass());
+
+ ic->Create = iColorBrowserDlgCreateMethod;
+ ic->Destroy = iColorBrowserDlgDestroyMethod;
+ ic->Map = iColorBrowserDlgMapMethod;
+
+ ic->name = "colordlg"; /* this will hide the GTK and Windows implementations */
+ ic->nativetype = IUP_TYPEDIALOG;
+ ic->is_interactive = 1;
+ ic->childtype = IUP_CHILDNONE;
+
+ iupClassRegisterAttribute(ic, "COLORTABLE", iColorBrowserDlgGetColorTableAttrib, iColorBrowserDlgSetColorTableAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "STATUS", iColorBrowserDlgGetStatusAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUE", iColorBrowserDlgGetValueAttrib, iColorBrowserDlgSetValueAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ALPHA", iColorBrowserDlgGetAlphaAttrib, iColorBrowserDlgSetAlphaAttrib, IUPAF_SAMEASSYSTEM, "255", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUEHSI", iColorBrowserDlgGetValueHSIAttrib, iColorBrowserDlgSetValueHSIAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUEHEX", iColorBrowserDlgGetValueHexAttrib, iColorBrowserDlgSetValueHexAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWALPHA", NULL, iColorBrowserDlgSetShowAlphaAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWCOLORTABLE", NULL, iColorBrowserDlgSetShowColorTableAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWHEX", NULL, iColorBrowserDlgSetShowHexAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWHELP", NULL, iColorBrowserDlgSetShowHelpAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ return ic;
+}
diff --git a/iup/srccontrols/color/iup_colorhsi.c b/iup/srccontrols/color/iup_colorhsi.c
new file mode 100755
index 0000000..ce5e71f
--- /dev/null
+++ b/iup/srccontrols/color/iup_colorhsi.c
@@ -0,0 +1,358 @@
+/** \file
+ * \brief HSI Color Manipulation
+ * Copied and adapted from IM
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include "iup_colorhsi.h"
+
+static const float rad60 = 1.0471975f;
+static const float rad120 = 2.0943951f;
+static const float rad180 = 3.1415926f;
+static const float rad240 = 4.1887902f;
+static const float rad300 = 5.2359877f;
+static const float rad360 = 6.2831853f;
+static const float sqrt3 = 1.7320508f;
+static const float rad2deg = 57.2957795131f;
+
+static float costab[361];
+static float sintab[361];
+static int init_tab = 0;
+
+static void iColorBuildTables(void)
+{
+ int theta;
+ for (theta=0; theta<=360; theta++)
+ {
+ float th = ((float)theta)/rad2deg;
+ costab[theta] = cosf(th);
+ sintab[theta] = sinf(th);
+ }
+ init_tab = 1;
+}
+
+static void iColorSinCos(float H, float *sinH, float *cosH)
+{
+ int theta;
+
+ H *= rad2deg;
+ theta = (int)(H + 0.5f); /* Round */
+
+ if (!init_tab)
+ iColorBuildTables();
+
+ if (theta<0) theta = 0;
+ if (theta>360) theta = 360;
+
+ *cosH = costab[theta];
+ *sinH = sintab[theta];
+}
+
+static float iColorNormHue(float H)
+{
+ while (H < 0.0f)
+ H += rad360;
+
+ if (H > rad360)
+ H = fmodf(H, rad360);
+
+ return H;
+}
+
+static unsigned char iColorQuantize(float value)
+{
+ if (value >= 1.0f) return 255;
+ if (value <= 0.0f) return 0;
+ return (unsigned char)(value*256);
+}
+
+static float iColorReconstruct(unsigned char value)
+{
+ if (value <= 0) return 0.0f;
+ if (value >= 255) return 1.0f;
+ return (((float)value + 0.5f)/256.0f);
+}
+
+static void iColorSmax01(float h, float hr, float hb, float hg, float *h0, float *h1)
+{
+ if (h < rad60)
+ {
+ *h0 = hb;
+ *h1 = hr;
+ }
+ else if (h < rad120)
+ {
+ *h0 = hb;
+ *h1 = hg;
+ }
+ else if (h < rad180)
+ {
+ *h0 = hr;
+ *h1 = hg;
+ }
+ else if (h < rad240)
+ {
+ *h0 = hr;
+ *h1 = hb;
+ }
+ else if (h < rad300)
+ {
+ *h0 = hg;
+ *h1 = hb;
+ }
+ else
+ {
+ *h0 = hg;
+ *h1 = hr;
+ }
+}
+
+/* Given H and I, returns S max, but s is in u,v space. */
+static float iColorHSI_Smax(float h, float cosH, float sinH, float i)
+{
+ float hr, hb, hg, imax, h0, h1;
+
+ /* i here is normalized between 0-1 */
+
+ if (i == 0.0f || i == 1.0f)
+ return 0.0f;
+
+ /* Making r=0, g=0, b=0, r=1, g=1 or b=1 in the parametric equations and
+ writting s in function of H and I. */
+
+ /* at bottom */
+ if (i <= 1.0f/3.0f)
+ {
+ /* face B=0 */
+ if (h < rad120)
+ {
+ hb = (cosH + sinH*sqrt3)/3.0f;
+ return i/hb;
+ }
+
+ /* face R=0 */
+ if (h < rad240)
+ {
+ hr = -cosH/1.5f;
+ return i/hr;
+ }
+
+ /* face G=0 (h < rad360) */
+ {
+ hg = (cosH - sinH*sqrt3)/3.0f;
+ return i/hg;
+ }
+ }
+
+ /* at top */
+ if (i >= 2.0f/3.0f)
+ {
+ /* face R=1 */
+ if (h < rad60 || h > rad300)
+ {
+ hr = cosH/1.5f;
+ return (1.0f-i)/hr;
+ }
+
+ /* face G=1 */
+ if (h < rad180)
+ {
+ hg = (-cosH + sinH*sqrt3)/3.0f;
+ return (1.0f-i)/hg;
+ }
+
+ /* face B=1 (h > rad180 && h < rad300) */
+ {
+ hb = (-cosH - sinH*sqrt3)/3.0f;
+ return (1.0f-i)/hb;
+ }
+ }
+
+ /* in the middle */
+ hr = cosH/1.5f;
+ hg = (-cosH + sinH*sqrt3)/3.0f;
+ hb = (-cosH - sinH*sqrt3)/3.0f;
+
+ iColorSmax01(h, hr, hb, hg, &h0, &h1);
+
+ if (h == 0.0f || h == rad120 || h == rad240)
+ imax = 1.0f/3.0f;
+ else if (h == rad60 || h == rad180 || h == rad300)
+ imax = 2.0f/3.0f;
+ else
+ imax = h0/(h0 - h1);
+
+ if (i < imax)
+ return -i/h0;
+ else
+ return (1.0f-i)/h1;
+}
+
+/* Given H, returns I where S is max,
+ BUT the maximum S here is 1 at the corners of the cube. */
+static float iColorHSI_ImaxS(float h, float cosH, float sinH)
+{
+ float i, h0, h1;
+ float hr, hb, hg;
+
+ /* i here is normalized between 0-1 */
+
+ if (h == 0.0f || h == rad120 || h == rad240)
+ return 1.0f/3.0f;
+
+ if (h == rad60 || h == rad180 || h == rad300)
+ return 2.0f/3.0f;
+
+ hr = cosH/1.5f;
+ hg = (-cosH + sinH*sqrt3)/3.0f;
+ hb = (-cosH - sinH*sqrt3)/3.0f;
+
+ iColorSmax01(h, hr, hb, hg, &h0, &h1);
+
+ i = h0/(h0 - h1);
+
+ return i;
+}
+
+static void iColorRGB2HSI(float r, float g, float b, float *h, float *s, float *i)
+{
+ float v, u, ImaxS;
+
+ /* Parametric equations */
+ v = r - (g + b)/2.0f;
+ u = (g - b) * (sqrt3/2.0f);
+
+ *i = (r + g + b)/3; /* already normalized to 0-1 */
+
+ *s = sqrtf(v*v + u*u); /* s is between 0-1, BUT it is linear in the cube and it is in u,v space. */
+
+ if (*s == 0.0f)
+ {
+ /* *h = <any> (left unchanged) */
+ ImaxS = 1.0f/3.0f;
+ }
+ else
+ {
+ float Smax;
+ float H, cosH, sinH;
+
+ H = atan2f(u, v);
+ H = iColorNormHue(H);
+ *h = H * rad2deg;
+
+ iColorSinCos(H, &sinH, &cosH);
+
+ /* must scale S from 0-Smax to 0-1 */
+ Smax = iColorHSI_Smax(H, cosH, sinH, *i);
+ if (Smax == 0.0f)
+ *s = 0.0f;
+ else
+ {
+ if (*s > Smax) /* because of round problems when calculating s and Smax */
+ *s = Smax;
+ *s /= Smax;
+ }
+
+ ImaxS = iColorHSI_ImaxS((float)H, cosH, sinH);
+ }
+
+ /* must convert I from linear scale to non-linear scale. USED ONLY FOR THE COLORBROWSER */
+ if (*i < 0.5f) /* half I is I=ImaxS, not I=0.5 */
+ *i = ((*i)*0.5f)/ImaxS;
+ else
+ *i = (((*i) - ImaxS)*0.5f)/(1.0f - ImaxS) + 0.5f;
+}
+
+static void iColorHSI2RGB(float h, float s, float i, float *r, float *g, float *b)
+{
+ float cosH, sinH, H, v, u;
+ float Smax, ImaxS;
+
+ if (i < 0) i = 0;
+ else if (i > 1) i = 1;
+
+ if (s < 0) s = 0;
+ else if (s > 1) s = 1;
+
+ if (s == 0.0f || i == 1.0f || i == 0.0f || (int)h == 360)
+ {
+ *r = i;
+ *g = i;
+ *b = i;
+ return;
+ }
+
+ H = h/rad2deg;
+ H = iColorNormHue(H);
+
+ iColorSinCos(H, &sinH, &cosH);
+
+ /* must convert I from non-linear scale to linear scale. USED ONLY FOR THE COLORBROWSER */
+ ImaxS = iColorHSI_ImaxS(H, cosH, sinH);
+ if (i < 0.5f) /* half I is I=ImaxS, not I=0.5 */
+ i = ImaxS * (i / 0.5f);
+ else
+ i = (1.0f - ImaxS) * (i - 0.5f)/0.5f + ImaxS;
+
+ /* must scale S from 0-1 to 0-Smax */
+ Smax = iColorHSI_Smax(H, cosH, sinH, i);
+ s *= Smax;
+ if (s > 1.0f) /* because of round problems when calculating s and Smax */
+ s = 1.0f;
+
+ v = s * cosH;
+ u = s * sinH;
+
+ /* Inverse of the Parametric equations, using i normalized to 0-1 */
+ *r = i + v/1.5f;
+ *g = i - (v - u*sqrt3)/3.0f;
+ *b = i - (v + u*sqrt3)/3.0f;
+
+ /* fix round errors */
+ if (*r < 0.0f) *r = 0;
+ if (*g < 0.0f) *g = 0;
+ if (*b < 0.0f) *b = 0;
+
+ if (*r > 1.0f) *r = 1.0f;
+ if (*g > 1.0f) *g = 1.0f;
+ if (*b > 1.0f) *b = 1.0f;
+}
+
+/*********************************************************************************************/
+
+void iupColorRGB2HSI(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *i)
+{
+ float fr = iColorReconstruct(r);
+ float fg = iColorReconstruct(g);
+ float fb = iColorReconstruct(b);
+
+ iColorRGB2HSI(fr, fg, fb, h, s, i);
+}
+
+void iupColorHSI2RGB(float h, float s, float i, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ float fr, fg, fb;
+
+ iColorHSI2RGB(h, s, i, &fr, &fg, &fb);
+
+ *r = iColorQuantize(fr);
+ *g = iColorQuantize(fg);
+ *b = iColorQuantize(fb);
+}
+
+int iupStrToHSI(const char *str, float *h, float *s, float *i)
+{
+ float fh, fs, fi;
+ if (!str) return 0;
+ if (sscanf(str, "%f %f %f", &fh, &fs, &fi) != 3) return 0;
+ if (fh > 359 || fs > 1 || fi > 1) return 0;
+ if (fh < 0 || fs < 0 || fi < 0) return 0;
+ *h = fh;
+ *s = fs;
+ *i = fi;
+ return 1;
+}
diff --git a/iup/srccontrols/color/iup_colorhsi.h b/iup/srccontrols/color/iup_colorhsi.h
new file mode 100755
index 0000000..b29ea48
--- /dev/null
+++ b/iup/srccontrols/color/iup_colorhsi.h
@@ -0,0 +1,44 @@
+/** \file
+ * \brief HSI Color Manipulation
+ * Copied and adapted from IM
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUP_COLORHSI_H
+#define __IUP_COLORHSI_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* 0<=H<=359 */
+/* 0<=S<=1 */
+/* 0<=I<=1 */
+
+
+/* Converts from RGB to HSI.
+ */
+void iupColorRGB2HSI(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *i);
+
+/* Converts from HSI to RGB.
+ */
+void iupColorHSI2RGB(float h, float s, float i, unsigned char *r, unsigned char *g, unsigned char *b);
+
+int iupStrToHSI(const char *str, float *h, float *s, float *i);
+
+#ifdef IUP_DEFMATHFLOAT
+#define atan2f(_X, _Y) ((float)atan2((double)_X, (double)_Y))
+#define cosf(_X) ((float)cos((double)_X))
+#define fmodf(_X, _Y) ((float)fmod((double)_X, (double)_Y))
+#define sinf(_X) ((float)sin((double)_X))
+#define sqrtf(_X) ((float)sqrt((double)_X))
+#endif
+
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/config.mak b/iup/srccontrols/config.mak
new file mode 100755
index 0000000..394d607
--- /dev/null
+++ b/iup/srccontrols/config.mak
@@ -0,0 +1,48 @@
+PROJNAME = iup
+LIBNAME = iupcontrols
+OPT = YES
+
+INCLUDES = ../include ../src .
+
+SRCCOLOR = iup_colorbrowser.c iup_colorhsi.c iup_colorbrowserdlg.c
+SRCCOLOR := $(addprefix color/, $(SRCCOLOR))
+
+SRCMATRIX = iupmat_key.c iupmat_mark.c iupmat_aux.c iupmat_mem.c iupmat_mouse.c iupmat_numlc.c \
+ iupmat_colres.c iupmat_draw.c iupmat_focus.c iupmat_getset.c iupmatrix.c \
+ iupmat_scroll.c iupmat_edit.c
+SRCMATRIX := $(addprefix matrix/, $(SRCMATRIX))
+
+SRC = iup_cdutil.c iup_gauge.c iup_cells.c iup_colorbar.c iup_controls.c \
+ iup_dial.c iup_oldtabs.c iup_oldval.c iup_oldmask.c \
+ $(SRCCOLOR) $(SRCMATRIX)
+
+LIBS = iup iupcd
+LDIR = ../lib/$(TEC_UNAME)
+USE_CD = Yes
+
+# force the definition of math functions using float
+# Some compilers do not define them
+ifeq ($(TEC_UNAME), dll)
+ DEFINES += IUP_DEFMATHFLOAT
+endif
+ifeq ($(TEC_UNAME), vc6)
+ DEFINES += IUP_DEFMATHFLOAT
+endif
+ifeq ($(TEC_UNAME), dll7)
+ DEFINES += IUP_DEFMATHFLOAT
+endif
+ifeq ($(TEC_UNAME), vc7)
+ DEFINES += IUP_DEFMATHFLOAT
+endif
+ifneq ($(findstring ow, $(TEC_UNAME)), )
+ DEFINES += IUP_DEFMATHFLOAT
+endif
+ifneq ($(findstring bc, $(TEC_UNAME)), )
+ DEFINES += IUP_DEFMATHFLOAT
+endif
+ifneq ($(findstring AIX, $(TEC_UNAME)), )
+ DEFINES += IUP_DEFMATHFLOAT
+endif
+ifneq ($(findstring SunOS, $(TEC_UNAME)), )
+ DEFINES += IUP_DEFMATHFLOAT
+endif
diff --git a/iup/srccontrols/iup_cdutil.c b/iup/srccontrols/iup_cdutil.c
new file mode 100755
index 0000000..3ffb15b
--- /dev/null
+++ b/iup/srccontrols/iup_cdutil.c
@@ -0,0 +1,153 @@
+/** \file
+ * \brief cdiuputil. CD and IUP utilities for the IupControls
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <cd.h>
+
+#include "iup.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_cdutil.h"
+
+
+long cdIupConvertColor(const char *color)
+{
+ unsigned char r, g, b;
+ if (iupStrToRGB(color, &r, &g, &b))
+ return cdEncodeColor(r, g, b);
+ else
+ return 0;
+}
+
+void cdIupCalcShadows(long bgcolor, long *light_shadow, long *mid_shadow, long *dark_shadow)
+{
+ int r, bg_r = cdRed(bgcolor);
+ int g, bg_g = cdGreen(bgcolor);
+ int b, bg_b = cdBlue(bgcolor);
+
+ /* light_shadow */
+
+ int max = bg_r;
+ if (bg_g > max) max = bg_g;
+ if (bg_b > max) max = bg_b;
+
+ if (255-max < 64)
+ {
+ r = 255;
+ g = 255;
+ b = 255;
+ }
+ else
+ {
+ /* preserve some color information */
+ if (bg_r == max) r = 255;
+ else r = bg_r + (255-max);
+ if (bg_g == max) g = 255;
+ else g = bg_g + (255-max);
+ if (bg_b == max) b = 255;
+ else b = bg_b + (255-max);
+ }
+
+ if (light_shadow) *light_shadow = cdEncodeColor((unsigned char)r, (unsigned char)g, (unsigned char)b);
+
+ /* dark_shadow */
+ r = bg_r - 128;
+ g = bg_g - 128;
+ b = bg_b - 128;
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+
+ if (dark_shadow) *dark_shadow = cdEncodeColor((unsigned char)r, (unsigned char)g, (unsigned char)b);
+
+ /* mid_shadow = (dark_shadow+bgcolor)/2 */
+ if (mid_shadow) *mid_shadow = cdEncodeColor((unsigned char)((bg_r+r)/2), (unsigned char)((bg_g+g)/2), (unsigned char)((bg_b+b)/2));
+}
+
+void cdIupDrawSunkenRect(cdCanvas *canvas, int x1, int y1, int x2, int y2, long light_shadow, long mid_shadow, long dark_shadow)
+{
+ cdCanvasForeground(canvas, mid_shadow);
+ cdCanvasLine(canvas, x1, y1+1, x1, y2);
+ cdCanvasLine(canvas, x1, y2, x2-1, y2);
+
+ cdCanvasForeground(canvas, dark_shadow);
+ cdCanvasLine(canvas, x1+1, y1+2, x1+1, y2-1);
+ cdCanvasLine(canvas, x1+1, y2-1, x2-2, y2-1);
+
+ cdCanvasForeground(canvas, light_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, y1);
+ cdCanvasLine(canvas, x2, y1, x2, y2);
+}
+
+void cdIupDrawRaisenRect(cdCanvas *canvas, int x1, int y1, int x2, int y2, long light_shadow, long mid_shadow, long dark_shadow)
+{
+ cdCanvasForeground(canvas, light_shadow);
+ cdCanvasLine(canvas, x1, y1+1, x1, y2);
+ cdCanvasLine(canvas, x1, y2, x2-1, y2);
+
+ cdCanvasForeground(canvas, dark_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, y1);
+ cdCanvasLine(canvas, x2, y1, x2, y2);
+
+ cdCanvasForeground(canvas, mid_shadow);
+ cdCanvasLine(canvas, x1+1, y1+1, x2-1, y1+1);
+ cdCanvasLine(canvas, x2-1, y1+2, x2-1, y2-1);
+}
+
+void cdIupDrawVertSunkenMark(cdCanvas *canvas, int x, int y1, int y2, long light_shadow, long dark_shadow)
+{
+ cdCanvasForeground(canvas, dark_shadow);
+ cdCanvasLine(canvas, x-1, y1, x-1, y2);
+ cdCanvasForeground(canvas, light_shadow);
+ cdCanvasLine(canvas, x, y1, x, y2);
+}
+
+void cdIupDrawHorizSunkenMark(cdCanvas *canvas, int x1, int x2, int y, long light_shadow, long dark_shadow)
+{
+ cdCanvasForeground(canvas, dark_shadow);
+ cdCanvasLine(canvas, x1, y+1, x2, y+1);
+ cdCanvasForeground(canvas, light_shadow);
+ cdCanvasLine(canvas, x1, y, x2, y);
+}
+
+void cdIupDrawFocusRect(Ihandle* ih, cdCanvas *canvas, int x1, int y1, int x2, int y2)
+{
+ int y, x, w, h;
+#ifdef WIN32
+ void* gc = cdCanvasGetAttribute(canvas, "HDC");
+#else
+ void* gc = cdCanvasGetAttribute(canvas, "GC");
+#endif
+
+ cdCanvasUpdateYAxis(canvas, &y1);
+ cdCanvasUpdateYAxis(canvas, &y2);
+ y = y1;
+ if (y2<y1) y = y2;
+ x = x1;
+ if (x2<x1) x = x2;
+
+ w = abs(x2-x1)+1;
+ h = abs(y2-y1)+1;
+
+ iupdrvDrawFocusRect(ih, gc, x, y, w, h);
+}
+
+void cdDrawFocusRect(cdCanvas *canvas, int x1, int y1, int x2, int y2)
+{
+ int old_linestyle = cdCanvasLineStyle(canvas, CD_DOTTED);
+ int old_foreground = cdCanvasForeground(canvas, CD_WHITE);
+ int old_writemode = cdCanvasWriteMode(canvas, CD_XOR);
+
+ cdCanvasRect(canvas, x1, x2, y1, y2);
+
+ cdCanvasWriteMode(canvas, old_writemode);
+ cdCanvasForeground(canvas, old_foreground);
+ cdCanvasLineStyle(canvas, old_linestyle);
+}
diff --git a/iup/srccontrols/iup_cdutil.h b/iup/srccontrols/iup_cdutil.h
new file mode 100755
index 0000000..73ad3b4
--- /dev/null
+++ b/iup/srccontrols/iup_cdutil.h
@@ -0,0 +1,35 @@
+/** \file
+ * \brief cdiuputil. CD and IUP utilities for the IupControls
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUP_CDUTIL_H
+#define __IUP_CDUTIL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cdIupCalcShadows(long bgcolor, long *light_shadow, long *mid_shadow, long *dark_shadow);
+long cdIupConvertColor(const char *color);
+void cdIupDrawSunkenRect(cdCanvas *canvas, int x1, int y1, int x2, int y2,
+ long light_shadow, long mid_shadow, long dark_shadow);
+void cdIupDrawRaisenRect(cdCanvas *canvas, int x1, int y1, int x2, int y2,
+ long light_shadow, long mid_shadow, long dark_shadow);
+void cdIupDrawVertSunkenMark(cdCanvas *canvas, int x, int y1, int y2, long light_shadow, long dark_shadow);
+void cdIupDrawHorizSunkenMark(cdCanvas *canvas, int x1, int x2, int y, long light_shadow, long dark_shadow);
+void cdIupDrawFocusRect(Ihandle* ih, cdCanvas *canvas, int x1, int y1, int x2, int y2);
+
+void cdDrawFocusRect(cdCanvas *canvas, int x1, int y1, int x2, int y2);
+
+#define cdIupInvertYAxis(_y, _h) ((_h) - (_y) - 1);
+
+#define cdIupLIGTHER(_x) ((unsigned char)(((_x)+ 192)/2))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/iup_cells.c b/iup/srccontrols/iup_cells.c
new file mode 100755
index 0000000..d9a7fe4
--- /dev/null
+++ b/iup/srccontrols/iup_cells.c
@@ -0,0 +1,974 @@
+/** \file
+ * \brief Cells Control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef CD_NO_OLD_INTERFACE
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+
+
+#define ICELLS_OUT -999
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ cdCanvas* cdcanvas; /* cd canvas for drawing */
+ cdCanvas* cddbuffer; /* image canvas for double buffering */
+ int w; /* control width (pixels) */
+ int h; /* control height (pixels) */
+ int clipped; /* cells bounding box clipping activated */
+ int boxed; /* draw cells bounding box activated */
+ int bufferize; /* bufferize on */
+ int non_scrollable_lins; /* number of non-scrollable lines */
+ int non_scrollable_cols; /* number of non-scrollable columns */
+ long int bgcolor; /* Empty area color and bgcolor */
+};
+
+
+/* Function to inquire application cell data (line height) */
+static int iCellsGetHeight(Ihandle* ih, int i)
+{
+ int size;
+
+ IFni cb = (IFni)IupGetCallback(ih, "HEIGHT_CB");
+ if (!cb)
+ return 30; /* default value */
+
+ size = cb(ih, i);
+ if (size < 0)
+ size = 0;
+
+ return size;
+}
+
+/* Function to inquire application cell data (column width) */
+static int iCellsGetWidth(Ihandle* ih, int j)
+{
+ int size;
+
+ IFni cb = (IFni)IupGetCallback(ih, "WIDTH_CB");
+ if (!cb)
+ return 60; /* default value */
+
+ size = cb(ih, j);
+ if (size < 0)
+ size = 0;
+
+ return size;
+}
+
+/* Function used to calculate a cell limits */
+static int iCellsGetLimits(Ihandle* ih, int i, int j, int* xmin, int* xmax, int* ymin, int* ymax)
+{
+ int result = 1;
+ int xmin_sum = 0;
+ int ymin_sum = 0;
+ int w = ih->data->w;
+ int h = ih->data->h;
+ int _xmin, _xmax, _ymin, _ymax;
+
+ /* Adjusting the inital position according to the cell's type. If it
+ * is non-scrollable, the origin is always zero, otherwise the origin
+ * is the scrollbar position */
+ int posx = (j <= ih->data->non_scrollable_cols)? 0: IupGetInt(ih, "POSX");
+ int posy = (i <= ih->data->non_scrollable_lins)? 0: IupGetInt(ih, "POSY");
+ int idx;
+
+ /* Adding to the origin, the cells' width and height */
+ for (idx = 1; idx < j; idx++)
+ xmin_sum += iCellsGetWidth(ih, idx);
+
+ for (idx = 1; idx < i; idx++)
+ ymin_sum += iCellsGetHeight(ih, idx);
+
+ /* Finding the cell origin */
+ _xmin = xmin_sum - posx;
+ _ymax = h - (ymin_sum - posy) - 1;
+
+ /* Computing the cell limit, based on its origin and size */
+ _xmax = _xmin + iCellsGetWidth(ih, j);
+ _ymin = _ymax - iCellsGetHeight(ih, i);
+
+ /* Checking if the cell is visible */
+ if (_xmax < 0 || _xmin > w || _ymin > h || _ymax < 0)
+ result = 0;
+
+ if (xmin != NULL)
+ *xmin = _xmin;
+
+ if (xmax != NULL)
+ *xmax = _xmax;
+
+ if (ymin != NULL)
+ *ymin = _ymin;
+
+ if (ymax != NULL)
+ *ymax = _ymax;
+
+ return result;
+}
+
+/* Function to inquire application cell data (vertical span) */
+static int iCellsGetVspan(Ihandle* ih, int i, int j)
+{
+ int result = 1; /* default value */
+
+ IFnii cb = (IFnii)IupGetCallback(ih, "VSPAN_CB");
+ if (cb)
+ result = cb(ih, i, j);
+
+ if (result < 0)
+ result = 1;
+
+ return result;
+}
+
+/* Function to inquire application cell data (horizontal span) */
+static int iCellsGetHspan(Ihandle* ih, int i, int j)
+{
+ int result = 1; /* default value */
+
+ IFnii cb = (IFnii)IupGetCallback(ih, "HSPAN_CB");
+ if (cb)
+ result = cb(ih, i, j);
+
+ if (result < 0)
+ result = 1;
+
+ return result;
+}
+
+/* Function to inquire application cell data (#columns) */
+static int iCellsGetNCols(Ihandle* ih)
+{
+ int result = 10; /* default value */
+
+ Icallback cb = IupGetCallback(ih, "NCOLS_CB");
+ if (cb)
+ result = cb(ih);
+
+ if (result < 0)
+ result = 0;
+
+ return result;
+}
+
+/* Function to inquire application cell data (# lines) */
+static int iCellsGetNLines(Ihandle* ih)
+{
+ int result = 10; /* default value */
+
+ Icallback cb = IupGetCallback(ih, "NLINES_CB");
+ if (cb)
+ result = cb(ih);
+
+ if (result < 0)
+ result = 0;
+
+ return result;
+}
+
+/* Recalculation of first visible line */
+static int iCellsGetFirstLine(Ihandle* ih)
+{
+ int i, j;
+ int nlines = iCellsGetNLines(ih);
+ int ncols = iCellsGetNCols(ih);
+
+ if (ih->data->non_scrollable_lins >= nlines)
+ return 1;
+
+ /* Looping the lines until a visible one is found */
+ for (i = 1; i <= nlines; i++) {
+ for (j = 1; j <= ncols; j++) {
+ if (iCellsGetLimits(ih, i, j, NULL, NULL, NULL, NULL))
+ return i;
+ }
+ }
+ return ICELLS_OUT;
+}
+
+/* Recalculation of first visible column */
+static int iCellsGetFirstCol(Ihandle* ih)
+{
+ int i, j;
+ int ncols = iCellsGetNCols(ih);
+ int nlines = iCellsGetNLines(ih);
+
+ if (ih->data->non_scrollable_cols >= ncols)
+ return 1;
+
+ /* Looping the columns until a visible one is found */
+ for (j = 1; j <= ncols; j++) {
+ for (i = 1; i <= nlines; i++) {
+ if (iCellsGetLimits(ih, i, j, NULL, NULL, NULL, NULL))
+ return j;
+ }
+ }
+ return ICELLS_OUT;
+}
+
+/* Function used to get the cells groups virtual size */
+static void iCellsGetVirtualSize(Ihandle* ih, int* wi, int* he)
+{
+ int i, j;
+ *wi = 0; *he = 0;
+
+ /* Looping through all lines and columns, adding its width and heights
+ * to the return values. So, the cells virtual size is computed */
+ for (i = 1; i <= iCellsGetNLines(ih); i++)
+ *he = *he + iCellsGetHeight(ih, i);
+ for (j = 1; j <= iCellsGetNCols(ih); j++)
+ *wi = *wi + iCellsGetWidth(ih, j);
+}
+
+/* Function used to calculate a group of columns height */
+static int iCellsGetRangedHeight(Ihandle* ih, int from, int to)
+{
+ int i;
+ int result = 0;
+
+ /* Looping through a column adding the line height */
+ for (i = from; i <= to; i++)
+ result += iCellsGetHeight(ih, i);
+
+ return result;
+}
+
+/* Function used to calculate a group of lines width */
+static int iCellsGetRangedWidth(Ihandle* ih, int from, int to)
+{
+ int j;
+ int result = 0;
+
+ /* Looping through a column adding the column width */
+ for (j = from; j <= to; j++)
+ result += iCellsGetWidth(ih, j);
+
+ return result;
+}
+
+/* Function used to turn a cell visible */
+static void iCellsSetFullVisible(Ihandle* ih, int i, int j)
+{
+ int xmin, xmax, ymin, ymax;
+ int posx = IupGetInt(ih, "POSX");
+ int posy = IupGetInt(ih, "POSY");
+ int dx = 0;
+ int dy = 0;
+
+ /* Getting the frontiers positions for the visible cell */
+ int min_x = iCellsGetRangedWidth(ih, 1, ih->data->non_scrollable_cols);
+ int max_y = ih->data->h - iCellsGetRangedHeight(ih, 1, ih->data->non_scrollable_lins);
+
+ /* Getting the cell's area limit */
+ iCellsGetLimits(ih, i, j, &xmin, &xmax, &ymin, &ymax);
+
+ /* Adjusting the diference of the scrollbars' position (horizontal) */
+ if (xmax > ih->data->w)
+ dx = xmax - ih->data->w;
+
+ /* Giving priority to xmin position. This can be seen by the usage
+ * of dx at the left part of the expression (using the last dx).
+ * This is the case wher the cell cannot be fitted. */
+ if (xmin - dx < min_x)
+ dx = - (min_x - xmin);
+
+ /* Adjusting the diference of the scrollbars' position (horizontal) */
+ if (ymax > max_y)
+ dy = - (ymax - max_y);
+ if (ymin < 0)
+ dy = -ymin;
+
+ /* Adding the diference to scrollbars' position */
+ posx += dx;
+ posy += dy;
+
+ /* Setting iup scrollbars' attributes */
+ IupSetfAttribute(ih, "POSX", "%d", posx);
+ IupSetfAttribute(ih, "POSY", "%d", posy);
+}
+
+/* Function used to make a cell the first visible one */
+static void iCellsAdjustOrigin(Ihandle* ih, int lin, int col)
+{
+ int xmin_sum, ymin_sum;
+
+ /* If the origin line is a non-scrollable one, the scrollbar position is
+ * set to zero. Otherwise, the sum of the previous widths will be
+ * set to the scrollbar position. This algorithm is applied to both
+ * scrollbars */
+ if (lin <= ih->data->non_scrollable_lins)
+ {
+ IupSetAttribute(ih, "POSY", "0");
+ }
+ else if (lin <= iCellsGetNLines(ih))
+ {
+ ymin_sum = iCellsGetRangedHeight(ih, ih->data->non_scrollable_lins+1, lin-1);
+ IupSetfAttribute(ih, "POSY", "%d", ymin_sum);
+ }
+
+ /* As said before... */
+ if (col <= ih->data->non_scrollable_cols)
+ {
+ IupSetAttribute(ih, "POSX", "0");
+ }
+ else if (col <= iCellsGetNCols(ih))
+ {
+ xmin_sum = iCellsGetRangedWidth(ih, ih->data->non_scrollable_cols+1, col-1);
+ IupSetfAttribute(ih, "POSX", "%d", xmin_sum);
+ }
+}
+
+/* Function used for the scrollbar's update; usually needed when the
+ * object has modified its size or the cells sizes has changed. */
+static void iCellsAdjustScrolls(Ihandle* ih)
+{
+ int virtual_height, virtual_width;
+
+ /* Getting the virtual size */
+ iCellsGetVirtualSize(ih, &virtual_width, &virtual_height);
+
+ IupSetfAttribute(ih, "YMAX", "%d", virtual_height-1);
+ IupSetfAttribute(ih, "XMAX", "%d", virtual_width-1);
+
+ /* Setting the object scrollbar position */
+ IupSetfAttribute(ih, "DY", "%d", ih->data->h);
+ IupSetfAttribute(ih, "DX", "%d", ih->data->w);
+}
+
+/* Function used to call the client; is used when a cell must be repainted. */
+static void iCellsCallDrawCb(Ihandle* ih, int xmin, int xmax, int ymin, int ymax, int i, int j)
+{
+ int cxmin, cxmax, cymin, cymax;
+ int oldxmin, oldxmax, oldymin, oldymax, oldclip;
+ int w = ih->data->w;
+ int h = ih->data->h;
+ IFniiiiii draw_cb;
+ cdCanvas* old_cnv = cdActiveCanvas();
+
+ /* Getting clipping area for post restore */
+ oldclip = cdCanvasClip(ih->data->cddbuffer, CD_QUERY);
+ cdCanvasGetClipArea(ih->data->cddbuffer, &oldxmin, &oldxmax, &oldymin, &oldymax);
+
+ if (ih->data->clipped) /* Clipping the cell area */
+ {
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
+ cxmin = xmin < 0 ? 0 : xmin;
+ cymin = ymin < 0 ? 0 : ymin;
+ cxmax = xmax > w ? w : xmax;
+ cymax = ymax > h ? h : ymax;
+ cdCanvasClipArea(ih->data->cddbuffer, xmin, xmax, ymin, ymax);
+ }
+
+ draw_cb = (IFniiiiii)IupGetCallback(ih, "DRAW_CB");
+ if (draw_cb)
+ {
+ if (old_cnv != ih->data->cddbuffer) /* backward compatibility code */
+ cdActivate(ih->data->cddbuffer);
+
+ draw_cb(ih, i, j, xmin, xmax, ymin, ymax);
+
+ if (old_cnv && old_cnv != ih->data->cddbuffer)
+ {
+ cdActivate(old_cnv);
+ cdCanvasActivate(ih->data->cddbuffer);
+ }
+ }
+
+ cdCanvasClip(ih->data->cddbuffer, oldclip);
+ cdCanvasClipArea(ih->data->cddbuffer, oldxmin, oldxmax, oldymin, oldymax);
+}
+
+/* Render function for one cell in a given coordinate. */
+static void iCellsRenderCellIn(Ihandle* ih, int i, int j, int xmin, int xmax, int ymin, int ymax)
+{
+ int k;
+ int w = ih->data->w;
+ int h = ih->data->h;
+ int hspan = 1;
+ int vspan = 1;
+
+ /* Checking if the cells is out of range. (no span will affect it!) */
+ if (xmin > w || ymax < 0)
+ return;
+
+ /* Calculating cell spans */
+ hspan = iCellsGetHspan(ih, i, j);
+ vspan = iCellsGetVspan(ih, i, j);
+
+ /* if any span is set to zero, then another cell invaded its space and
+ * the cell does not need to draw itself */
+ if (hspan == 0 || vspan == 0)
+ return;
+
+ /* Increasing cell's width and height according to its spans */
+ for(k = 1; k < hspan; k++)
+ xmax += iCellsGetWidth(ih, j+k);
+ for(k = 1; k < vspan; k++)
+ ymin -= iCellsGetHeight(ih, i+k);
+
+ /* Checking if the cell expanded enough to appear inside the canvas */
+ if (xmax < 0 || ymin > h)
+ return;
+
+ /* Calling application's draw callback */
+ iCellsCallDrawCb(ih, xmin, xmax, ymin, ymax, i, j);
+
+ /* Drawing a box in cell's area */
+ if (ih->data->boxed)
+ {
+ cdCanvasForeground(ih->data->cddbuffer, CD_BLACK);
+ cdCanvasRect(ih->data->cddbuffer, xmin, xmax, ymin, ymax);
+ }
+}
+
+/* Repaint function for all cells in a given range */
+static void iCellsRenderRangedCells(Ihandle* ih, int linfrom, int linto, int colfrom, int colto)
+{
+ int i, j;
+ int xmin, xmax, ymin, ymax;
+ int refxmin, refxmax;
+
+ /* Getting first cell limits: this function is slow to be called everytime */
+ iCellsGetLimits(ih, linfrom, colfrom, &xmin, &xmax, &ymin, &ymax);
+
+ /* Initializing current reference position */
+ refxmin = xmin;
+ refxmax = xmax;
+
+ /* Looping through the cells adding next cell width and height */
+ for (i = linfrom; i <= linto; i++)
+ {
+ xmin = refxmin;
+ xmax = refxmax;
+ for (j = colfrom; j <= colto; j++)
+ {
+ iCellsRenderCellIn(ih, i, j, xmin, xmax, ymin, ymax);
+ xmin = xmax;
+ xmax = xmin + (j == colto ? 0 : iCellsGetWidth(ih, j+1));
+ }
+ ymax = ymin;
+ ymin = ymax - (i == linto ? 0 : iCellsGetHeight(ih, i+1));
+ }
+}
+
+/* Repaint function for all cells */
+static void iCellsRenderCells(Ihandle* ih)
+{
+ int sline = ih->data->non_scrollable_lins;
+ int scol = ih->data->non_scrollable_cols;
+ int nlines = iCellsGetNLines(ih);
+ int ncols = iCellsGetNCols(ih);
+
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+
+ /* Repainting the four parts of the cells: common cells, non-scrollable
+ * columns, non-scrollable lines, and non-scrollable margin
+ * (line and column) */
+ iCellsRenderRangedCells(ih, sline+1, nlines, scol+1, ncols);
+ iCellsRenderRangedCells(ih, sline+1, nlines, 1, scol);
+ iCellsRenderRangedCells(ih, 1, sline, scol+1, ncols);
+ iCellsRenderRangedCells(ih, 1, sline, 1, scol);
+}
+
+static void iCellsRepaint(Ihandle* ih)
+{
+ if (ih->data->cddbuffer == NULL)
+ return;
+
+ /* If object is buffering, it will not be drawn */
+ if (ih->data->bufferize == 1)
+ return;
+
+ /* update render */
+ iCellsRenderCells(ih);
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+}
+
+static int iCellsRedraw_CB(Ihandle* ih)
+{
+ if (ih->data->cddbuffer == NULL)
+ return IUP_DEFAULT;
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ return IUP_DEFAULT;
+}
+
+/* Function used to calculate the cell coordinates limited by a hint */
+static int iCellsGetRangedCoord(Ihandle* ih, int x, int y, int* lin, int* col, int linfrom, int linto, int colfrom, int colto)
+{
+ int i, j, k;
+ int hspan, vspan;
+ int rxmax, rymin;
+ int xmin, xmax, ymin, ymax;
+ int refxmin, refxmax;
+ int w = ih->data->w;
+
+ /* Getting the first cell's limit -- based on the range */
+ iCellsGetLimits(ih, linfrom, colfrom, &xmin, &xmax, &ymin, &ymax);
+
+ /* Initializing reference position */
+ refxmin = xmin;
+ refxmax = xmax;
+
+ /* Looping through the cells adding next cell width and height */
+ for (i = linfrom; i <= linto; i++)
+ {
+ xmin = refxmin;
+ xmax = refxmax;
+ if (!(ymax < 0))
+ {
+ for (j = colfrom; j <= colto; j++)
+ {
+ hspan = 1;
+ vspan = 1;
+ if (!(xmin > w))
+ {
+ hspan = iCellsGetHspan(ih, i, j);
+ vspan = iCellsGetVspan(ih, i, j);
+ if (hspan != 0 && vspan != 0)
+ {
+ rxmax = xmax;
+ rymin = ymin;
+ for(k = 1; k < hspan; k++)
+ rxmax += iCellsGetWidth(ih, j+k);
+ for(k = 1; k < vspan; k++)
+ rymin -= iCellsGetHeight(ih, i+k);
+
+ /* A cell was found */
+ if (x >= xmin && x <= rxmax && y >= rymin && y <= ymax)
+ {
+ *lin = i;
+ *col = j;
+ return 1;
+ }
+ }
+ xmin = xmax;
+ xmax = xmin + (j == colto ? 0 : iCellsGetWidth(ih, j+1));
+ }
+ }
+ }
+ ymax = ymin;
+ ymin = ymax - (i == linto ? 0 : iCellsGetHeight(ih, i+1));
+ }
+
+ /* No cell selected... */
+ *lin = ICELLS_OUT;
+ *col = ICELLS_OUT;
+ return 0;
+}
+
+/* Function used to calculate the cell coordinates */
+static int iCellsGetCoord(Ihandle* ih, int x, int y, int* lin, int* col)
+{
+ int pck = 0;
+ int sline = ih->data->non_scrollable_lins;
+ int scol = ih->data->non_scrollable_cols;
+ int nlines = iCellsGetNLines(ih);
+ int ncols = iCellsGetNCols(ih);
+
+ /* Trying to pick a cell (raster coordinates) at the four
+ * parts of the cells (reverse order of the repainting):
+ * non-scrollable margin (line and column), non-scrollable
+ * columns, non-scrollable lines, and common cells. */
+ pck = iCellsGetRangedCoord(ih, x, y, lin, col, 1, sline, 1, scol);
+ if (pck)
+ return 1;
+
+ pck = iCellsGetRangedCoord(ih, x, y, lin, col, 1, sline, scol+1, ncols);
+ if (pck)
+ return 1;
+
+ pck = iCellsGetRangedCoord(ih, x, y, lin, col, sline+1, nlines, 1, scol);
+ if (pck)
+ return 1;
+
+ pck = iCellsGetRangedCoord(ih, x, y, lin, col, 1, nlines, 1, ncols);
+ return pck;
+}
+
+static int iCellsScroll_CB(Ihandle* ih)
+{
+ IFnii cb;
+ int ret = IUP_DEFAULT;
+ int fline = -999;
+ int fcol = -999;
+
+ fline = iCellsGetFirstLine(ih);
+ fcol = iCellsGetFirstCol(ih);
+
+ /* Checking the existence of a scroll bar callback. If the application
+ * has set one, it will be called now. If the application returns
+ * IUP_DEFAULT, the cells will be repainted. */
+ cb = (IFnii)IupGetCallback(ih, "SCROLLING_CB");
+ if (cb)
+ ret = cb(ih, fline, fcol);
+
+ if (ret == IUP_DEFAULT)
+ iCellsRepaint(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iCellsMotion_CB(Ihandle* ih, int x, int y, char* r)
+{
+ int i, j;
+
+ /* Checking the existence of a motion bar callback. If the application
+ * has set one, it will be called now. However, before calling the
+ * callback, we need to find out which cell is under the mouse
+ * position. */
+ IFniiiis cb = (IFniiiis)IupGetCallback(ih, "MOUSEMOTION_CB");
+ if (!cb)
+ return IUP_DEFAULT;
+
+ iCellsGetCoord(ih, x, y, &i, &j);
+ return cb(ih, i, j, x, y, r);
+}
+
+static int iCellsResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ /* recalculate scrollbars positions and size */
+ iCellsAdjustScrolls(ih);
+
+ /* update render */
+ iCellsRenderCells(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iCellsButton_CB(Ihandle* ih, int b, int m, int x, int y, char* r)
+{
+ int i, j;
+ IFniiiiiis cb;
+
+ y = cdIupInvertYAxis(y, ih->data->h);
+
+ /* Treating the button event. The application will receive
+ * a button press callback. */
+ cb = (IFniiiiiis)IupGetCallback(ih, "MOUSECLICK_CB");
+ if (!cb)
+ return IUP_DEFAULT;
+
+ iCellsGetCoord(ih, x, y, &i, &j);
+ return cb(ih, b, m, i, j, x, y, r);
+}
+
+static char* iCellsGetImageCanvasAttrib(Ihandle* ih)
+{
+ return (char*)ih->data->cddbuffer;
+}
+
+static char* iCellsGetCanvasAttrib(Ihandle* ih)
+{
+ return (char*)ih->data->cdcanvas;
+}
+
+static char* iCellsGetFirstLineAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(80);
+ sprintf( buffer, "%d", iCellsGetFirstLine(ih) );
+ return buffer;
+}
+
+static char* iCellsGetFirstColAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(80);
+ sprintf(buffer, "%d", iCellsGetFirstCol(ih) );
+ return buffer;
+}
+
+static char* iCellsGetLimitsAttrib(Ihandle* ih, const char* name_id)
+{
+ char* buffer = iupStrGetMemory(80);
+ int xmin, xmax, ymin, ymax;
+ int i, j;
+
+ if (iupStrToIntInt(name_id, &i, &j, ':') != 2)
+ return NULL;
+
+ iCellsGetLimits(ih, i, j, &xmin, &xmax, &ymin, &ymax);
+ sprintf(buffer, "%d:%d:%d:%d", xmin, xmax, ymin, ymax);
+ return buffer;
+}
+
+static int iCellsSetBufferizeAttrib(Ihandle* ih, const char* value)
+{
+ if (value == NULL || iupStrEqualNoCase(value, "NO"))
+ {
+ ih->data->bufferize = 0;
+ iCellsAdjustScrolls(ih);
+ iCellsRepaint(ih);
+ }
+ else
+ ih->data->bufferize = 1;
+
+ return 0;
+}
+
+static char* iCellsGetBufferizeAttrib(Ihandle* ih)
+{
+ if (ih->data->bufferize)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iCellsSetRepaintAttrib(Ihandle* ih, const char* value)
+{
+ (void)value; /* not used */
+ ih->data->bufferize = 0;
+ iCellsAdjustScrolls(ih);
+ iCellsRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static int iCellsSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = iupControlBaseGetParentBgColor(ih);
+
+ ih->data->bgcolor = cdIupConvertColor(value);
+
+ iCellsRepaint(ih);
+ return 1;
+}
+
+static int iCellsSetOriginAttrib(Ihandle* ih, const char* value)
+{
+ int lin = -9;
+ int col = -9;
+ iupStrToIntInt(value, &lin, &col, ':');
+ iCellsAdjustOrigin(ih, lin, col);
+ iCellsRepaint(ih);
+ return 1;
+}
+
+static int iCellsSetNonScrollableColsAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrToInt(value, &ih->data->non_scrollable_cols))
+ iCellsRepaint(ih);
+ return 0;
+}
+
+static char* iCellsGetNonScrollableColsAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(80);
+ sprintf(buffer, "%d", ih->data->non_scrollable_cols);
+ return buffer;
+}
+
+static int iCellsSetNonScrollableLinesAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrToInt(value, &ih->data->non_scrollable_lins))
+ iCellsRepaint(ih);
+ return 0;
+}
+
+static char* iCellsGetNonScrollableLinesAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(80);
+ sprintf(buffer, "%d", ih->data->non_scrollable_lins);
+ return buffer;
+}
+
+static int iCellsSetBoxedAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NO"))
+ ih->data->boxed = 0;
+ else
+ ih->data->boxed = 1;
+
+ iCellsRepaint(ih);
+ return 0;
+}
+
+static char* iCellsGetBoxedAttrib(Ihandle* ih)
+{
+ if (ih->data->boxed)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iCellsSetClippedAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NO"))
+ ih->data->clipped = 0;
+ else
+ ih->data->clipped = 1;
+
+ iCellsRepaint(ih);
+ return 0;
+}
+
+static char* iCellsGetClippedAttrib(Ihandle* ih)
+{
+ if (ih->data->clipped)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iCellsSetFullVisibleAttrib(Ihandle* ih, const char* value)
+{
+ int i, j;
+ if (iupStrToIntInt(value, &i, &j, ':') != 2)
+ return 0;
+
+ iCellsSetFullVisible(ih, i, j);
+ iCellsRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+
+/****************************************************************************/
+
+
+static int iCellsMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ return IUP_NOERROR;
+}
+
+static void iCellsUnMapMethod(Ihandle* ih)
+{
+ if (ih->data->cddbuffer)
+ cdKillCanvas(ih->data->cddbuffer);
+
+ if (ih->data->cdcanvas)
+ cdKillCanvas(ih->data->cdcanvas);
+}
+
+static int iCellsCreateMethod(Ihandle* ih, void **params)
+{
+ (void)params;
+
+ /* free the data allocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "SCROLLBAR", "YES");
+ iupAttribSetStr(ih, "BORDER", "NO");
+
+ /* default values */
+ ih->data->boxed = 1;
+ ih->data->clipped = 1;
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iCellsResize_CB);
+ IupSetCallback(ih, "ACTION", (Icallback)iCellsRedraw_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iCellsButton_CB);
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iCellsMotion_CB);
+ IupSetCallback(ih, "SCROLL_CB", (Icallback)iCellsScroll_CB);
+
+ return IUP_NOERROR;
+}
+
+Iclass* iupCellsGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "cells";
+ ic->format = NULL; /* no parameters */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+ ic->has_attrib_id = 1; /* has attributes with IDs that must be parsed */
+
+ /* Class functions */
+ ic->Create = iCellsCreateMethod;
+ ic->Map = iCellsMapMethod;
+ ic->UnMap = iCellsUnMapMethod;
+
+ /* Do not need to set base attributes because they are inherited from IupCanvas */
+
+ /* IupCells Callbacks */
+ iupClassRegisterCallback(ic, "SCROLLING_CB", "ii");
+ iupClassRegisterCallback(ic, "MOUSEMOTION_CB", "iiiis");
+ iupClassRegisterCallback(ic, "MOUSECLICK_CB", "iiiiiis");
+ iupClassRegisterCallback(ic, "DRAW_CB", "iiiiiiv");
+ iupClassRegisterCallback(ic, "VSPAN_CB", "ii");
+ iupClassRegisterCallback(ic, "HSPAN_CB", "ii");
+ iupClassRegisterCallback(ic, "NCOLS_CB", "");
+ iupClassRegisterCallback(ic, "NLINES_CB", "");
+ iupClassRegisterCallback(ic, "HEIGHT_CB", "i");
+ iupClassRegisterCallback(ic, "WIDTH_CB", "i");
+
+ /* IupCells only */
+ iupClassRegisterAttribute(ic, "BOXED", iCellsGetBoxedAttrib, iCellsSetBoxedAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "CLIPPED", iCellsGetClippedAttrib, iCellsSetClippedAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "NON_SCROLLABLE_LINES", iCellsGetNonScrollableLinesAttrib, iCellsSetNonScrollableLinesAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "NON_SCROLLABLE_COLS", iCellsGetNonScrollableColsAttrib, iCellsSetNonScrollableColsAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "NO_COLOR", iupControlBaseGetBgColorAttrib, iCellsSetBgColorAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "BUFFERIZE", iCellsGetBufferizeAttrib, iCellsSetBufferizeAttrib, NULL, NULL, IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "ORIGIN", NULL, iCellsSetOriginAttrib, NULL, NULL, IUPAF_DEFAULT);
+
+ iupClassRegisterAttribute(ic, "FULL_VISIBLE", NULL, iCellsSetFullVisibleAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "REPAINT", NULL, iCellsSetRepaintAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "LIMITS", iCellsGetLimitsAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FIRST_COL", iCellsGetFirstColAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FIRST_LINE", iCellsGetFirstLineAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGE_CANVAS", iCellsGetImageCanvasAttrib, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CANVAS", iCellsGetCanvasAttrib, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_READONLY|IUPAF_NO_INHERIT);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupControlBaseGetBgColorAttrib, iCellsSetBgColorAttrib, NULL, "255 255 255", IUPAF_NO_INHERIT); /* overwrite canvas implementation, set a system default to force a new default */
+
+ return ic;
+}
+
+Ihandle* IupCells(void)
+{
+ return IupCreate("cells");
+}
diff --git a/iup/srccontrols/iup_colorbar.c b/iup/srccontrols/iup_colorbar.c
new file mode 100755
index 0000000..72e717c
--- /dev/null
+++ b/iup/srccontrols/iup_colorbar.c
@@ -0,0 +1,1082 @@
+/** \file
+ * \brief Colorbar Control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcontrols.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_image.h"
+#include "iup_cdutil.h"
+
+
+#define ICOLORBAR_DEFAULT_NUM_CELLS 16 /* default number of cells */
+#define ICOLORBAR_NO_COLOR 0xff000000 /* no color */
+#define ICOLORBAR_DELTA 5 /* preview margin */
+#define ICOLORBAR_RENDER_ALL -1
+#define ICOLORBAR_RENDER_NONE -2
+
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ int w; /* size of the canvas - width */
+ int h; /* size of the canvas - height */
+ cdCanvas* cdcanvas; /* cd canvas for drawing */
+ cdCanvas* cddbuffer; /* image canvas for double buffering */
+ long int colors[256]; /* CD color vector */
+ int num_cells; /* number of cells at the widgets */
+ int num_parts; /* number of sections used to split the colors cells area */
+ int vertical; /* vertical orientation flag */
+ int squared; /* square cells attribute flag */
+ int shadowed; /* 3D shadowed attribute flag */
+ long bgcolor; /* control background color */
+ long light_shadow; /* } */
+ long mid_shadow; /* } 3D shadowed color */
+ long dark_shadow; /* } */
+ int bufferize; /* bufferation flag */
+ long int transparency; /* transparency color */
+ int show_secondary; /* secondary color selction flag */
+ int preview_size; /* preview size (pixels) 0=disabled, -1=automatic */
+ int fgcolor_idx; /* current primary index selected */
+ int bgcolor_idx; /* current secondary index selected */
+ int focus_cell; /* cell with focus */
+ int has_focus; /* 1 if the control has the focus, else 0 */
+};
+
+/* Default colors used for a widget */
+static struct {
+ unsigned int r;
+ unsigned int g;
+ unsigned int b;
+} default_colors[ICOLORBAR_DEFAULT_NUM_CELLS] = {
+ { 0, 0, 0 }, { 128, 0, 0 }, { 0, 128, 0 }, { 128, 128, 0 },
+ { 0, 0, 128 }, { 128, 0, 128 }, { 0, 128, 128 }, { 192, 192, 192 },
+ { 128, 128, 128 }, { 255, 0, 0 }, { 0, 255, 0 }, { 255, 255, 0 },
+ { 0, 0, 255 }, { 255, 0, 255 }, { 0, 255, 255 }, { 255, 255, 255 }
+};
+
+
+/* This function draw the 3D cell effect. */
+static void iColorbarDrawSunken(Ihandle* ih, int xmin, int xmax, int ymin, int ymax)
+{
+ if (!ih->data->shadowed) return;
+ cdIupDrawSunkenRect(ih->data->cddbuffer, xmin, ymin, xmax, ymax, ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+}
+
+/* This function is used to draw a box for a cell. */
+static void iColorbarDrawBox(Ihandle* ih, int xmin, int xmax, int ymin, int ymax, int idx)
+{
+ long int color = ih->data->colors[idx];
+ cdCanvasInteriorStyle(ih->data->cddbuffer, CD_SOLID);
+
+ if (color == ih->data->transparency)
+ {
+ int xm = (xmin+xmax)/2;
+ int ym = (ymin+ymax)/2;
+ cdCanvasForeground(ih->data->cddbuffer,0xeeeeee);
+ cdCanvasBox(ih->data->cddbuffer,xmin, xm, ymin, ym);
+ cdCanvasBox(ih->data->cddbuffer,xm, xmax, ym, ymax);
+ cdCanvasForeground(ih->data->cddbuffer,0xcccccc);
+ cdCanvasBox(ih->data->cddbuffer,xmin, xm, ym, ymax);
+ cdCanvasBox(ih->data->cddbuffer,xm, xmax, ymin, ym);
+ }
+ else
+ {
+ if (!iupdrvIsActive(ih))
+ {
+ unsigned char r, g, b, bg_r, bg_g, bg_b;
+ cdDecodeColor(color, &r, &g, &b);
+ cdDecodeColor(ih->data->bgcolor, &bg_r, &bg_g, &bg_b);
+ iupImageColorMakeInactive(&r, &g, &b, bg_r, bg_g, bg_b);
+ color = cdEncodeColor(r, g, b);
+ }
+ cdCanvasForeground(ih->data->cddbuffer,color);
+ cdCanvasBegin(ih->data->cddbuffer,CD_FILL);
+ cdCanvasVertex(ih->data->cddbuffer,xmin, ymin); cdCanvasVertex(ih->data->cddbuffer,xmin, ymax);
+ cdCanvasVertex(ih->data->cddbuffer,xmax, ymax); cdCanvasVertex(ih->data->cddbuffer,xmax, ymin);
+ cdCanvasEnd(ih->data->cddbuffer);
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer,CD_BLACK);
+ cdCanvasBegin(ih->data->cddbuffer,CD_CLOSED_LINES);
+ cdCanvasVertex(ih->data->cddbuffer,xmin, ymin); cdCanvasVertex(ih->data->cddbuffer,xmin, ymax);
+ cdCanvasVertex(ih->data->cddbuffer,xmax, ymax); cdCanvasVertex(ih->data->cddbuffer,xmax, ymin);
+ cdCanvasEnd(ih->data->cddbuffer);
+}
+
+/* This function is used to get the largest square of a cell bounding box. */
+static void iColorbarFitSquare(int* xmin, int* xmax, int* ymin, int* ymax)
+{
+ int mx = (*xmax + *xmin) / 2;
+ int my = (*ymax + *ymin) / 2;
+ int dx = (*xmax - *xmin) / 2;
+ int dy = (*ymax - *ymin) / 2;
+
+ if (dx < dy)
+ {
+ *ymin = my - dx;
+ *ymax = my + dx;
+ }
+ else
+ {
+ *xmin = mx - dy;
+ *xmax = mx + dy;
+ }
+}
+
+/* This function is used to get the preview area bounding box. */
+static void iColorbarGetPreviewLimit(Ihandle* ih, int* xmin, int* xmax, int* ymin, int* ymax)
+{
+ int num_itens = ih->data->num_cells / ih->data->num_parts + 1; /* include space for preview area */
+
+ *xmin = 0; *ymin = 0;
+ if (ih->data->vertical)
+ {
+ *xmax = ih->data->w;
+ if (ih->data->preview_size > 0)
+ *ymax = *ymin + ih->data->preview_size;
+ else
+ *ymax = ih->data->h / num_itens;
+ }
+ else
+ {
+ *ymax = ih->data->h;
+ if (ih->data->preview_size > 0)
+ *xmax = *xmin + ih->data->preview_size;
+ else
+ *xmax = ih->data->w / num_itens;
+ }
+ if (ih->data->squared)
+ iColorbarFitSquare(xmin, xmax, ymin, ymax);
+}
+
+/* This function is used to get a cell bounding box. */
+static void iColorbarGetCellLimit(Ihandle* ih, int idx, int* xmin, int* xmax, int* ymin, int* ymax)
+{
+ int delta, dummy;
+ int wcell, hcell;
+ int px = 0, py = 0;
+ int posx, posy;
+ int num_itens = ih->data->num_cells / ih->data->num_parts;
+
+ if (ih->data->preview_size != 0)
+ iColorbarGetPreviewLimit(ih, &dummy, &px, &dummy, &py);
+
+ if (ih->data->vertical) /* Vertical orientation */
+ {
+ wcell = ih->data->w / ih->data->num_parts;
+ hcell = (ih->data->h - py) / num_itens;
+ posx = idx / num_itens;
+ posy = idx % num_itens;
+ if (ih->data->squared)
+ {
+ wcell = wcell < hcell ? wcell : hcell;
+ hcell = wcell;
+ }
+ delta = (ih->data->w - (ih->data->num_parts*wcell)) / 2;
+ *xmin = delta + (posx+0)*wcell;
+ *xmax = delta + (posx+1)*wcell;
+ *ymin = py + (posy+0)*hcell;
+ *ymax = py + (posy+1)*hcell;
+ }
+ else /* Horizontal orientation */
+ {
+ hcell = ih->data->h / ih->data->num_parts;
+ wcell = (ih->data->w - px) / num_itens;
+ posx = idx % num_itens;
+ posy = idx / num_itens;
+ if (ih->data->squared)
+ {
+ wcell = wcell < hcell ? wcell : hcell;
+ hcell = wcell;
+ }
+ delta = (ih->data->h - (ih->data->num_parts * hcell)) / 2;
+ *xmin = px + (posx + 0) * wcell;
+ *xmax = px + (posx + 1) * wcell;
+ *ymin = delta + (posy + 0) * hcell;
+ *ymax = delta + (posy + 1) * hcell;
+ }
+}
+
+/* This function is used to get the index color of a canvas coordinate. */
+static int iColorbarGetIndexColor(Ihandle* ih, int x, int y)
+{
+ int i;
+ int xmin, ymin;
+ int xmax, ymax;
+ int result = -9;
+
+ for (i = 0; i < ih->data->num_cells; i++)
+ {
+ iColorbarGetCellLimit(ih, i, &xmin, &xmax, &ymin, &ymax);
+ if (x > xmin && x < xmax && y > ymin && y < ymax)
+ {
+ result = i;
+ break;
+ }
+ }
+ return result;
+}
+
+/* This function is used to repaint the preview area. */
+static void iColorbarRenderPreview(Ihandle* ih)
+{
+ int delta = ICOLORBAR_DELTA;
+ int xmin, ymin;
+ int xmax, ymax;
+ int xhalf, yhalf;
+ int bg = ih->data->bgcolor_idx;
+ int fg = ih->data->fgcolor_idx;
+
+ if (ih->data->preview_size == 0)
+ return;
+
+ iColorbarGetPreviewLimit(ih, &xmin, &xmax, &ymin, &ymax);
+
+ if (xmax-xmin < delta || ymax-ymin < delta)
+ delta = 0;
+
+ if (ih->data->show_secondary)
+ {
+ xhalf = 2 * (xmax - xmin - 2 * delta) / 3 + delta;
+ yhalf = 2 * (ymax - ymin - 2 * delta) / 3 + delta;
+
+ iColorbarDrawBox(ih, xmax - xhalf, xmax - delta, ymin + delta, ymin + yhalf, bg);
+ iColorbarDrawBox(ih, xmin + delta, xmin + xhalf, ymax - yhalf, ymax - delta, fg);
+ }
+ else
+ {
+ iColorbarDrawBox(ih, xmin + delta, xmax - delta, ymin + delta, ymax - delta, fg);
+ }
+}
+
+static void iColorbarDrawFocusCell(Ihandle* ih)
+{
+ int delta = 4;
+ int xmin, ymin;
+ int xmax, ymax;
+
+ iColorbarGetCellLimit(ih, ih->data->focus_cell, &xmin, &xmax, &ymin, &ymax);
+ xmin += delta;
+ xmax -= delta;
+ ymin += delta;
+ ymax -= delta;
+
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, xmin, ymin, xmax, ymax);
+}
+
+/* This function is used to repaint a cell. */
+static void iColorbarRenderCell(Ihandle* ih, int idx)
+{
+ int delta = 2;
+ int xmin, ymin;
+ int xmax, ymax;
+
+ iColorbarGetCellLimit(ih, idx, &xmin, &xmax, &ymin, &ymax);
+ xmin += delta;
+ xmax -= delta;
+ ymin += delta;
+ ymax -= delta;
+
+ iColorbarDrawBox(ih, xmin, xmax, ymin, ymax, idx);
+ iColorbarDrawSunken(ih, xmin, xmax, ymin, ymax);
+}
+
+/* This function loops all cells, repainting them. */
+static void iColorbarRenderCells(Ihandle* ih)
+{
+ int i;
+ for (i = 0; i < ih->data->num_cells; i++)
+ iColorbarRenderCell(ih, i);
+}
+
+static void iColorbarRepaint(Ihandle* ih)
+{
+ /* Checking errors or not initialized conditions */
+ if (ih->data->cddbuffer == NULL)
+ return;
+
+ /* If object is buffering, it will be not drawn */
+ if (ih->data->bufferize == 1)
+ return;
+
+ /* update render */
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+ iColorbarRenderPreview(ih);
+ iColorbarRenderCells(ih);
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ iColorbarDrawFocusCell(ih);
+}
+
+static int iColorbarCheckPreview(Ihandle* ih, int x, int y)
+{
+ int xmin, ymin;
+ int xmax, ymax;
+ int xhalf, yhalf;
+ int delta = ICOLORBAR_DELTA;
+
+ iColorbarGetPreviewLimit(ih, &xmin, &xmax, &ymin, &ymax);
+
+ if (ih->data->show_secondary)
+ {
+ xhalf = 2 * (xmax - xmin - 2 * delta) / 3 + delta;
+ yhalf = 2 * (ymax - ymin - 2 * delta) / 3 + delta;
+
+ if (x > xmin+delta && x < xmin+xhalf && y > ymax-yhalf && y < ymax-delta)
+ return IUP_PRIMARY;
+ if (x > xmax-xhalf && x < xmax-delta && y > ymin+delta && y < ymin+yhalf)
+ return IUP_SECONDARY;
+ if (x > xmin && x < xmax && y > ymin && y < ymax)
+ return 1; /* switch */
+ }
+ else
+ {
+ if (x > xmin+delta && x < xmax-delta && y > ymin+delta && y < ymax-delta)
+ return IUP_PRIMARY;
+ }
+
+ return 0;
+}
+
+static int iColorbarSetNumPartsAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrToInt(value, &ih->data->num_parts))
+ iColorbarRepaint(ih);
+ return 0;
+}
+
+static char* iColorbarGetNumPartsAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ sprintf(buffer, "%d", ih->data->num_parts);
+ return buffer;
+}
+
+static int iColorbarSetPrimaryCellAttrib(Ihandle* ih, const char* value)
+{
+ int new_val;
+ if (iupStrToInt(value, &new_val))
+ {
+ if (new_val > 0 && new_val < ih->data->num_cells)
+ {
+ ih->data->fgcolor_idx = new_val;
+ iColorbarRepaint(ih);
+ }
+ }
+ return 0;
+}
+
+static char* iColorbarGetPrimaryCellAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ sprintf(buffer, "%d", ih->data->fgcolor_idx);
+ return buffer;
+}
+
+static int iColorbarSetSecondaryCellAttrib(Ihandle* ih, const char* value)
+{
+ int new_val;
+ if (iupStrToInt(value, &new_val))
+ {
+ if (new_val > 0 && new_val < ih->data->num_cells)
+ {
+ ih->data->bgcolor_idx = new_val;
+ iColorbarRepaint(ih);
+ }
+ }
+
+ return 0;
+}
+
+static char* iColorbarGetSecondaryCellAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ sprintf(buffer, "%d", ih->data->bgcolor_idx);
+ return buffer;
+}
+
+static int iColorbarSetBufferizeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NO"))
+ {
+ ih->data->bufferize = 0;
+ iColorbarRepaint(ih);
+ }
+ else
+ ih->data->bufferize = 1;
+
+ return 0;
+}
+
+static char* iColorbarGetBufferizeAttrib(Ihandle* ih)
+{
+ if (ih->data->bufferize)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iColorbarSetNumCellsAttrib(Ihandle* ih, const char* value)
+{
+ int new_val;
+ if (iupStrToInt(value, &new_val))
+ {
+ if (new_val > 0 && new_val <= 256)
+ {
+ ih->data->num_cells = new_val;
+
+ if (ih->data->fgcolor_idx >= ih->data->num_cells)
+ ih->data->fgcolor_idx = ih->data->num_cells - 1;
+
+ if (ih->data->bgcolor_idx >= ih->data->num_cells)
+ ih->data->bgcolor_idx = ih->data->num_cells - 1;
+
+ iColorbarRepaint(ih);
+ }
+ }
+ return 0;
+}
+
+static char* iColorbarGetNumCellsAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(100);
+ sprintf(buffer, "%d", ih->data->num_cells);
+ return buffer;
+}
+
+static int iColorbarSetOrientationAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "HORIZONTAL"))
+ ih->data->vertical = 0;
+ else
+ ih->data->vertical = 1;
+
+ iColorbarRepaint(ih);
+ return 0;
+}
+
+static char* iColorbarGetOrientationAttrib(Ihandle* ih)
+{
+ if (ih->data->vertical)
+ return "VERTICAL";
+ else
+ return "HORIZONTAL";
+}
+
+static int iColorbarSetSquaredAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NO"))
+ ih->data->squared = 0;
+ else
+ ih->data->squared = 1;
+
+ iColorbarRepaint(ih);
+ return 0;
+}
+
+static char* iColorbarGetSquaredAttrib(Ihandle* ih)
+{
+ if (ih->data->squared)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iColorbarSetShadowedAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NO"))
+ ih->data->shadowed = 0;
+ else
+ ih->data->shadowed = 1;
+
+ iColorbarRepaint(ih);
+ return 0;
+}
+
+static char* iColorbarGetShadowedAttrib(Ihandle* ih)
+{
+ if (ih->data->shadowed)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iColorbarSetShowSecondaryAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NO"))
+ ih->data->show_secondary = 0;
+ else
+ ih->data->show_secondary = 1;
+
+ iColorbarRepaint(ih);
+ return 0;
+}
+
+static char* iColorbarGetShowSecondaryAttrib(Ihandle* ih)
+{
+ if (ih->data->show_secondary)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iColorbarSetShowPreviewAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NO"))
+ ih->data->preview_size = 0;
+ else
+ ih->data->preview_size = -1; /* reset to automatic */
+
+ iColorbarRepaint(ih);
+ return 1;
+}
+
+static int iColorbarSetPreviewSizeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrToInt(value, &ih->data->preview_size))
+ iColorbarRepaint(ih);
+ return 0;
+}
+
+static char* iColorbarGetPreviewSizeAttrib(Ihandle* ih)
+{
+ if (ih->data->preview_size == -1) /* automatic */
+ return NULL;
+ else
+ {
+ char* buffer = iupStrGetMemory(100);
+ sprintf(buffer, "%d", ih->data->preview_size);
+ return buffer;
+ }
+}
+
+static int iColorbarSetCellAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int idx = -1;
+ iupStrToInt(name_id, &idx);
+ if (idx >= 0 || idx < ih->data->num_cells)
+ {
+ ih->data->colors[idx] = cdIupConvertColor(value);
+ iColorbarRepaint(ih);
+ }
+
+ return 0;
+}
+
+static char* iColorbarGetCellAttrib(Ihandle* ih, const char* name_id)
+{
+ char* buffer = iupStrGetMemory(100);
+ int idx = -1;
+ long color;
+
+ iupStrToInt(name_id, &idx);
+ if (idx < 0 || idx >= ih->data->num_cells)
+ return NULL;
+
+ color = ih->data->colors[idx];
+ sprintf(buffer, "%d %d %d", cdRed(color), cdGreen(color), cdBlue(color));
+ return buffer;
+}
+
+static int iColorbarSetTransparencyAttrib(Ihandle* ih, const char* value)
+{
+ if (value == NULL)
+ ih->data->transparency = ICOLORBAR_NO_COLOR;
+ else
+ ih->data->transparency = cdIupConvertColor(value);
+
+ iColorbarRepaint(ih);
+ return 0;
+}
+
+static char* iColorbarGetTransparencyAttrib(Ihandle* ih)
+{
+ if (ih->data->transparency == ICOLORBAR_NO_COLOR)
+ return NULL;
+ else
+ {
+ char* buffer = iupStrGetMemory(100);
+ sprintf(buffer, "%d %d %d", cdRed(ih->data->transparency), cdGreen(ih->data->transparency), cdBlue(ih->data->transparency));
+ return buffer;
+ }
+}
+
+static int iColorbarSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = iupControlBaseGetParentBgColor(ih);
+
+ ih->data->bgcolor = cdIupConvertColor(value);
+
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+ if (!iupdrvIsActive(ih))
+ ih->data->light_shadow = ih->data->mid_shadow;
+
+ iColorbarRepaint(ih);
+ return 1;
+}
+
+static int iColorbarSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ iupBaseSetActiveAttrib(ih, value);
+
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+ if (!iupdrvIsActive(ih))
+ ih->data->light_shadow = ih->data->mid_shadow;
+
+ iColorbarRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static int iColorbarRedraw_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ iColorbarDrawFocusCell(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iColorbarResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ /* update render */
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+ iColorbarRenderPreview(ih);
+ iColorbarRenderCells(ih);
+
+ return IUP_DEFAULT;
+}
+
+static void iColorbarRenderPartsRepaint(Ihandle* ih, int preview, int idx)
+{
+ /* update render */
+ if (preview)
+ iColorbarRenderPreview(ih);
+
+ if (idx != ICOLORBAR_RENDER_NONE)
+ {
+ if (idx == ICOLORBAR_RENDER_ALL)
+ iColorbarRenderCells(ih);
+ else
+ iColorbarRenderCell(ih, idx);
+ }
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ iColorbarDrawFocusCell(ih);
+}
+
+static int iColorbarFocus_CB(Ihandle* ih, int focus)
+{
+ ih->data->has_focus = focus;
+
+ if (ih->data->cddbuffer)
+ {
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ iColorbarDrawFocusCell(ih);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static void iColorbarCallExtentedCb(Ihandle* ih, int idx)
+{
+ IFni extended_cb = (IFni)IupGetCallback(ih, "EXTENDED_CB");
+ if (!extended_cb)
+ return;
+
+ if (extended_cb(ih, idx) == IUP_IGNORE)
+ return;
+
+ iColorbarRenderPartsRepaint(ih, 1, ICOLORBAR_RENDER_ALL); /* the preview and all the cells are rendered */
+}
+
+static void iColorbarCallSelectCb(Ihandle* ih, int idx, int type)
+{
+ IFnii select_cb;
+
+ if (type == IUP_SECONDARY && !ih->data->show_secondary)
+ return;
+
+ select_cb = (IFnii)IupGetCallback(ih, "SELECT_CB");
+ if (!select_cb)
+ return;
+
+ if (select_cb(ih, idx, type) == IUP_IGNORE)
+ return;
+
+ if (type == IUP_PRIMARY)
+ ih->data->fgcolor_idx = idx;
+ else
+ ih->data->bgcolor_idx = idx;
+
+ iColorbarRenderPartsRepaint(ih, 1, ICOLORBAR_RENDER_NONE); /* only the preview area is rendered */
+}
+
+static void iColorbarCallCellCb(Ihandle* ih, int idx)
+{
+ char* returned;
+ sIFni cell_cb = (sIFni)IupGetCallback(ih, "CELL_CB");
+ if (!cell_cb)
+ return;
+
+ returned = cell_cb(ih, idx); /* the application can change the color */
+ if (returned)
+ {
+ int preview = 0;
+ /* check if the preview area should be rendered */
+ if (idx == ih->data->fgcolor_idx || idx == ih->data->bgcolor_idx)
+ preview = 1;
+
+ ih->data->colors[idx] = cdIupConvertColor(returned);
+ iColorbarRenderPartsRepaint(ih, preview, idx); /* the preview and the cell are rendered */
+ }
+}
+
+static int iColorbarKeyPress_CB(Ihandle* ih, int c, int press)
+{
+ if (c != K_LEFT && c != K_UP && c != K_RIGHT && c != K_DOWN &&
+ c != K_HOME && c != K_END &&
+ c != K_SP && c != K_sCR && c != K_sSP && c != K_cSP)
+ return IUP_DEFAULT;
+
+ if (!press || !ih->data->has_focus)
+ return IUP_DEFAULT;
+
+ switch(c)
+ {
+ case K_LEFT:
+ if (ih->data->vertical)
+ {
+ int cells_per_line = ih->data->num_cells / ih->data->num_parts;
+ if (ih->data->focus_cell > cells_per_line)
+ ih->data->focus_cell -= cells_per_line;
+ }
+ else
+ {
+ if (ih->data->focus_cell > 0)
+ ih->data->focus_cell--;
+ }
+ break;
+ case K_DOWN:
+ if (ih->data->vertical)
+ {
+ if (ih->data->focus_cell > 0)
+ ih->data->focus_cell--;
+ }
+ else
+ {
+ int cells_per_line = ih->data->num_cells / ih->data->num_parts;
+ if (ih->data->focus_cell > cells_per_line)
+ ih->data->focus_cell -= cells_per_line;
+ }
+ break;
+ case K_RIGHT:
+ if (ih->data->vertical)
+ {
+ int cells_per_line = ih->data->num_cells / ih->data->num_parts;
+ if (ih->data->focus_cell+cells_per_line < ih->data->num_cells-1)
+ ih->data->focus_cell += cells_per_line;
+ }
+ else
+ {
+ if (ih->data->focus_cell < ih->data->num_cells-1)
+ ih->data->focus_cell++;
+ }
+ break;
+ case K_UP:
+ if (ih->data->vertical)
+ {
+ if (ih->data->focus_cell < ih->data->num_cells-1)
+ ih->data->focus_cell++;
+ }
+ else
+ {
+ int cells_per_line = ih->data->num_cells / ih->data->num_parts;
+ if (ih->data->focus_cell+cells_per_line < ih->data->num_cells-1)
+ ih->data->focus_cell += cells_per_line;
+ }
+ break;
+ case K_HOME:
+ ih->data->focus_cell = 0;
+ break;
+ case K_END:
+ ih->data->focus_cell = ih->data->num_cells-1;
+ break;
+ case K_sCR:
+ iColorbarCallCellCb(ih, ih->data->focus_cell);
+ return IUP_DEFAULT;
+ case K_SP:
+ iColorbarCallSelectCb(ih, ih->data->focus_cell, IUP_PRIMARY);
+ return IUP_DEFAULT;
+ case K_cSP:
+ iColorbarCallSelectCb(ih, ih->data->focus_cell, IUP_SECONDARY);
+ return IUP_DEFAULT;
+ case K_sSP:
+ iColorbarCallExtentedCb(ih, ih->data->focus_cell);
+ return IUP_DEFAULT;
+ }
+
+ if (ih->data->cddbuffer)
+ {
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ iColorbarDrawFocusCell(ih);
+ }
+
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+}
+
+static int iColorbarButton_CB(Ihandle* ih, int b, int m, int x, int y, char* r)
+{
+ int idx;
+
+ if (m == 0)
+ return IUP_DEFAULT;
+
+ y = cdIupInvertYAxis(y, ih->data->h);
+
+ if (b == IUP_BUTTON1 && iup_isdouble(r))
+ {
+ idx = iColorbarGetIndexColor(ih, x, y);
+ if (idx < 0 || idx >= ih->data->num_cells)
+ {
+ int ret = iColorbarCheckPreview(ih, x, y);
+ if (ret)
+ {
+ if (ret == 1)
+ {
+ IFnii switch_cb = (IFnii)IupGetCallback(ih, "SWITCH_CB");
+
+ if (!ih->data->show_secondary)
+ return IUP_DEFAULT;
+
+ if (switch_cb && switch_cb(ih, ih->data->fgcolor_idx, ih->data->bgcolor_idx) == IUP_IGNORE)
+ return IUP_DEFAULT;
+
+ /* the application allow to switch the indices */
+ idx = ih->data->fgcolor_idx;
+ ih->data->fgcolor_idx = ih->data->bgcolor_idx;
+ ih->data->bgcolor_idx = idx;
+
+ iColorbarRenderPartsRepaint(ih, 1, ICOLORBAR_RENDER_NONE); /* only the preview area is rendered */
+ }
+ else
+ {
+ if (ret == IUP_PRIMARY)
+ idx = ih->data->fgcolor_idx;
+ else
+ idx = ih->data->bgcolor_idx;
+
+ iColorbarCallCellCb(ih, idx);
+ }
+ }
+
+ return IUP_DEFAULT;
+ }
+
+ ih->data->focus_cell = idx;
+
+ iColorbarCallCellCb(ih, idx);
+ }
+ else if (b == IUP_BUTTON1)
+ {
+ idx = iColorbarGetIndexColor(ih, x, y);
+ if (idx < 0 || idx >= ih->data->num_cells)
+ return IUP_DEFAULT;
+
+ ih->data->focus_cell = idx;
+
+ iColorbarCallSelectCb(ih, idx, IUP_PRIMARY);
+ }
+ else if (b == IUP_BUTTON3 && iup_isshift(r))
+ {
+ idx = iColorbarGetIndexColor(ih, x, y);
+ if (idx < 0 || idx >= ih->data->num_cells)
+ return IUP_DEFAULT;
+
+ ih->data->focus_cell = idx;
+
+ iColorbarCallExtentedCb(ih, idx);
+ }
+ else if (b == IUP_BUTTON3)
+ {
+ idx = iColorbarGetIndexColor(ih, x, y);
+ if (idx < 0 || idx >= ih->data->num_cells)
+ return IUP_DEFAULT;
+
+ ih->data->focus_cell = idx;
+
+ iColorbarCallSelectCb(ih, idx, IUP_SECONDARY);
+ }
+
+ return IUP_DEFAULT;
+}
+
+
+/****************************************************************************/
+
+
+static int iColorbarMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ return IUP_NOERROR;
+}
+
+static void iColorbarUnMapMethod(Ihandle* ih)
+{
+ if (ih->data->cddbuffer)
+ cdKillCanvas(ih->data->cddbuffer);
+
+ if (ih->data->cdcanvas)
+ cdKillCanvas(ih->data->cdcanvas);
+}
+
+static int iColorbarCreateMethod(Ihandle* ih, void **params)
+{
+ int i;
+ (void)params;
+
+ /* free the data allocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "BORDER", "NO");
+
+ /* default values */
+ ih->data->num_cells = 16;
+ ih->data->num_parts = 1;
+ ih->data->vertical = 1;
+ ih->data->squared = 1;
+ ih->data->shadowed = 1;
+ ih->data->focus_cell = 0;
+ ih->data->preview_size = -1; /* automatic */
+ ih->data->fgcolor_idx = 0; /* black */
+ ih->data->bgcolor_idx = 15; /* white */
+ ih->data->transparency = ICOLORBAR_NO_COLOR;
+ ih->data->light_shadow = CD_WHITE;
+ ih->data->mid_shadow = CD_GRAY;
+ ih->data->dark_shadow = CD_DARK_GRAY;
+
+ /* Initialization of the color vector */
+ for (i = 0; i < ICOLORBAR_DEFAULT_NUM_CELLS; i++)
+ {
+ ih->data->colors[i] = cdEncodeColor((unsigned char)default_colors[i].r,
+ (unsigned char)default_colors[i].g,
+ (unsigned char)default_colors[i].b);
+ }
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iColorbarResize_CB);
+ IupSetCallback(ih, "ACTION", (Icallback)iColorbarRedraw_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iColorbarButton_CB);
+ IupSetCallback(ih, "FOCUS_CB", (Icallback)iColorbarFocus_CB);
+ IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iColorbarKeyPress_CB);
+
+ return IUP_NOERROR;
+}
+
+Iclass* iupColorbarGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "colorbar";
+ ic->format = NULL; /* no parameters */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+ ic->has_attrib_id = 1; /* has attributes with IDs that must be parsed */
+
+ /* Class functions */
+ ic->Create = iColorbarCreateMethod;
+ ic->Map = iColorbarMapMethod;
+ ic->UnMap = iColorbarUnMapMethod;
+
+ /* Do not need to set base attributes because they are inherited from IupCanvas */
+
+ /* IupColorbar Callbacks */
+ iupClassRegisterCallback(ic, "CELL_CB", "i=s");
+ iupClassRegisterCallback(ic, "SWITCH_CB", "ii");
+ iupClassRegisterCallback(ic, "SELECT_CB", "ii");
+ iupClassRegisterCallback(ic, "EXTENDED_CB", "i");
+
+ /* IupColorbar only */
+ iupClassRegisterAttributeId(ic, "CELL", iColorbarGetCellAttrib, iColorbarSetCellAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUM_CELLS", iColorbarGetNumCellsAttrib, iColorbarSetNumCellsAttrib, IUPAF_SAMEASSYSTEM, "16", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUM_PARTS", iColorbarGetNumPartsAttrib, iColorbarSetNumPartsAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "PREVIEW_SIZE", iColorbarGetPreviewSizeAttrib, iColorbarSetPreviewSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "PRIMARY_CELL", iColorbarGetPrimaryCellAttrib, iColorbarSetPrimaryCellAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SECONDARY_CELL", iColorbarGetSecondaryCellAttrib, iColorbarSetSecondaryCellAttrib, IUPAF_SAMEASSYSTEM, "15", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "BUFFERIZE", iColorbarGetBufferizeAttrib, iColorbarSetBufferizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "ORIENTATION", iColorbarGetOrientationAttrib, iColorbarSetOrientationAttrib, IUPAF_SAMEASSYSTEM, "VERTICAL", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "TRANSPARENCY", iColorbarGetTransparencyAttrib, iColorbarSetTransparencyAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "SHOW_PREVIEW", NULL, iColorbarSetShowPreviewAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "SHOW_SECONDARY", iColorbarGetShowSecondaryAttrib, iColorbarSetShowSecondaryAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "SQUARED", iColorbarGetSquaredAttrib, iColorbarSetSquaredAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "SHADOWED", iColorbarGetShadowedAttrib, iColorbarSetShadowedAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iColorbarSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupControlBaseGetBgColorAttrib, iColorbarSetBgColorAttrib, NULL, "255 255 255", IUPAF_NO_INHERIT); /* overwrite canvas implementation, set a system default to force a new default */
+
+ return ic;
+}
+
+Ihandle *IupColorbar(void)
+{
+ return IupCreate("colorbar");
+}
diff --git a/iup/srccontrols/iup_controls.c b/iup/srccontrols/iup_controls.c
new file mode 100755
index 0000000..e60bd91
--- /dev/null
+++ b/iup/srccontrols/iup_controls.c
@@ -0,0 +1,56 @@
+/** \file
+ * \brief initializes the additional controls.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+
+#include "iup.h"
+#include "iupcontrols.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_register.h"
+#include "iup_controls.h"
+#include "iup_attrib.h"
+
+
+int IupControlsOpen(void)
+{
+ if (IupGetGlobal("_IUP_CONTROLS_OPEN"))
+ return IUP_OPENED;
+
+ iupRegisterClass(iupDialGetClass());
+ iupRegisterClass(iupCellsGetClass());
+ iupRegisterClass(iupColorbarGetClass());
+ iupRegisterClass(iupColorBrowserGetClass());
+ iupRegisterClass(iupMatrixGetClass());
+ iupRegisterClass(iupGaugeGetClass());
+ iupRegisterClass(iupColorBrowserDlgGetClass());
+
+ IupSetGlobal("_IUP_CONTROLS_OPEN", "1");
+
+ return IUP_NOERROR;
+}
+
+void IupControlsClose(void) /* for backward compatibility */
+{
+}
+
+char *iupControlBaseGetParentBgColor(Ihandle* ih)
+{
+ return IupGetAttribute(iupChildTreeGetNativeParent(ih), "BGCOLOR");
+}
+
+char *iupControlBaseGetBgColorAttrib(Ihandle* ih)
+{
+ /* check the hash table */
+ char *color = iupAttribGet(ih, "BGCOLOR");
+
+ /* If not defined check native definition from parent */
+ if (!color)
+ color = iupControlBaseGetParentBgColor(ih);
+
+ return color;
+}
+
diff --git a/iup/srccontrols/iup_controls.h b/iup/srccontrols/iup_controls.h
new file mode 100755
index 0000000..bb26963
--- /dev/null
+++ b/iup/srccontrols/iup_controls.h
@@ -0,0 +1,33 @@
+/** \file
+ * \brief Additional Controls Class Initialization functions.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUP_CONTROLS_H
+#define __IUP_CONTROLS_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+Iclass* iupDialGetClass(void);
+Iclass* iupCellsGetClass(void);
+Iclass* iupColorbarGetClass(void);
+Iclass* iupColorBrowserGetClass(void);
+Iclass* iupMatrixGetClass(void);
+Iclass* iupGaugeGetClass(void);
+Iclass* iupTabsGetClass(void);
+Iclass* iupColorBrowserDlgGetClass(void);
+
+char *iupControlBaseGetParentBgColor (Ihandle* ih);
+char *iupControlBaseGetBgColorAttrib(Ihandle* ih);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/iup_dial.c b/iup/srccontrols/iup_dial.c
new file mode 100755
index 0000000..1dd2d0f
--- /dev/null
+++ b/iup/srccontrols/iup_dial.c
@@ -0,0 +1,864 @@
+/** \file
+ * \brief Dial Control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define IDIAL_SPACE 3
+#define IDIAL_NCOLORS 10
+#define IDIAL_DEFAULT_DENSITY 0.2
+#define IDIAL_DEFAULT_DENSITY_STR "0.2"
+#define IDIAL_DEFAULT_FGCOLOR "64 64 64"
+#define IDIAL_DEFAULT_FGCOLOR_COMP 64
+
+enum{IDIAL_VERTICAL, IDIAL_HORIZONTAL, IDIAL_CIRCULAR};
+
+#define dialmin(a,b) ((a)<(b)?(a):(b))
+
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ /* attributes */
+ double angle;
+ int type;
+ double unit;
+ double density;
+
+ /* mouse interaction control */
+ int px;
+ int py;
+ int pressing;
+
+ /* visual appearance control */
+ void (*Draw)(Ihandle* ih);
+ int w, h;
+ int has_focus;
+ int num_div; /* number of sections in the dial wheel */
+ double radius; /* radius size of the dial wheel */
+ long fgcolor[IDIAL_NCOLORS+1];
+ long bgcolor,
+ light_shadow,
+ mid_shadow,
+ dark_shadow;
+
+ /* drawing canvas */
+ cdCanvas *cddbuffer;
+ cdCanvas *cdcanvas;
+};
+
+
+static long int iDialGetFgColor(Ihandle* ih, double a, double amin)
+{
+ double nu = fabs(a - 0.5 * M_PI);
+ double de = fabs(0.5 * M_PI - amin);
+ double fr = nu / de;
+ int i = (int)(IDIAL_NCOLORS * fr);
+ return ih->data->fgcolor[IDIAL_NCOLORS - i];
+}
+
+static void iDialDrawVerticalBackground(Ihandle* ih, double amin, double amax, int *ymin, int *ymax)
+{
+ double delta = (0.5 * M_PI - amin) / IDIAL_NCOLORS;
+ double a, yc = ih->data->h / 2.0;
+ *ymin = *ymax = ih->data->h / 2;
+ for (a = amin; a < 0.5 * M_PI; a += delta) /* shading */
+ {
+ int y0 = (int)(yc - ih->data->radius * cos(a));
+ int y1 = (int)(yc - ih->data->radius * cos(a+delta));
+ cdCanvasForeground(ih->data->cddbuffer, iDialGetFgColor(ih, a, amin));
+ cdCanvasBox(ih->data->cddbuffer, IDIAL_SPACE+1, ih->data->w-1-IDIAL_SPACE-2, y0, y1);
+
+ if (y0 < *ymin) *ymin = y0;
+
+ if (abs(y1-y0) < 2)
+ continue;
+ }
+ for (a = 0.5 * M_PI; a < amax; a += delta)
+ {
+ int y0 = (int)(yc + ih->data->radius * fabs(cos(a)));
+ int y1 = (int)(yc + ih->data->radius * fabs(cos(a+delta)));
+ cdCanvasForeground(ih->data->cddbuffer, iDialGetFgColor(ih, a, amin));
+ cdCanvasBox(ih->data->cddbuffer, IDIAL_SPACE+1, ih->data->w-1-IDIAL_SPACE-2, y0, y1);
+
+ if (y1 > *ymax) *ymax = y1;
+
+ if (abs(y1-y0) < 2)
+ continue;
+ }
+}
+
+static void iDialDrawVertical(Ihandle* ih)
+{
+ double delta = 2 * M_PI / ih->data->num_div;
+ double a, amin, amax;
+ int ymin, ymax;
+
+ ih->data->radius = (ih->data->h - 2 * IDIAL_SPACE - 2) / 2.0;
+
+ amin = 0.0;
+ amax = M_PI;
+ if(ih->data->angle < amin)
+ {
+ for (a = ih->data->angle; a < amin; a += delta)
+ ;
+ }
+ else
+ {
+ for (a = ih->data->angle; a > amin; a -= delta)
+ ;
+ a += delta;
+ }
+
+ iDialDrawVerticalBackground(ih, amin, amax, &ymin, &ymax);
+
+ cdIupDrawRaisenRect(ih->data->cddbuffer, IDIAL_SPACE, ymin, ih->data->w-1-IDIAL_SPACE, ymax,
+ ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+
+ for ( ; a < amax; a += delta) /* graduation */
+ {
+ int y;
+ if (a < 0.5 * M_PI) y = (int)(ih->data->h / 2.0 - ih->data->radius * cos(a));
+ else y = (int)(ih->data->h / 2.0 + ih->data->radius * fabs(cos(a)));
+
+ if (abs(y-ymin) < 3 || abs(ymax-y) < 3)
+ continue;
+
+ cdIupDrawHorizSunkenMark(ih->data->cddbuffer, IDIAL_SPACE+1, ih->data->w-1-IDIAL_SPACE-2, y, ih->data->light_shadow, ih->data->dark_shadow);
+ }
+}
+
+static void iDialDrawHorizontalBackground(Ihandle* ih,double amin,double amax, int *xmin, int *xmax)
+{
+ double delta = (0.5 * M_PI - amin) / IDIAL_NCOLORS;
+ double a, xc = ih->data->w / 2.0;
+ *xmin = *xmax = ih->data->w / 2;
+ for (a = amin; a < 0.5 * M_PI; a += delta)
+ {
+ int x0=(int)(xc - ih->data->radius * cos(a));
+ int x1=(int)(xc - ih->data->radius * cos(a + delta));
+ cdCanvasForeground(ih->data->cddbuffer,iDialGetFgColor(ih, a, amin));
+ cdCanvasBox(ih->data->cddbuffer, x0, x1, IDIAL_SPACE+2, ih->data->h-1-IDIAL_SPACE-1);
+
+ if (x0 < *xmin) *xmin = x0;
+
+ if (abs(x1 - x0) < 2)
+ continue;
+ }
+ for (a = 0.5 * M_PI; a < amax; a += delta)
+ {
+ int x0 =(int)(xc + ih->data->radius * fabs(cos(a)));
+ int x1 =(int)(xc + ih->data->radius * fabs(cos(a + delta)));
+ cdCanvasForeground(ih->data->cddbuffer, iDialGetFgColor(ih, a, amin));
+ cdCanvasBox(ih->data->cddbuffer, x0, x1, IDIAL_SPACE+2, ih->data->h-1-IDIAL_SPACE-1);
+
+ if (x1 > *xmax) *xmax = x1;
+
+ if (abs(x1-x0) < 2)
+ continue;
+ }
+}
+
+static void iDialDrawHorizontal(Ihandle* ih)
+{
+ double delta = 2 * M_PI / ih->data->num_div;
+ int x;
+ double a, amin, amax;
+ int xmin, xmax;
+ ih->data->radius = (ih->data->w - 2 * IDIAL_SPACE - 2) / 2.0;
+ amin = 0.0;
+ amax = M_PI;
+ if(ih->data->angle < amin)
+ {
+ for (a = ih->data->angle; a < amin; a += delta) ;
+ }
+ else
+ {
+ for (a = ih->data->angle; a > amin; a-= delta) ;
+ a += delta;
+ }
+
+ iDialDrawHorizontalBackground(ih, amin, amax, &xmin, &xmax);
+
+ cdIupDrawRaisenRect(ih->data->cddbuffer, xmin, IDIAL_SPACE, xmax, ih->data->h-1-IDIAL_SPACE,
+ ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+
+ for ( ; a < amax; a += delta)
+ {
+ if (a < 0.5 * M_PI) x = (int)(ih->data->w / 2.0 - ih->data->radius * cos(a));
+ else x = (int)(ih->data->w / 2.0 + ih->data->radius * fabs(cos(a)));
+
+ if (abs(x - xmin) < 3 || abs(xmax - x) < 3)
+ continue;
+
+ cdIupDrawVertSunkenMark(ih->data->cddbuffer, x, IDIAL_SPACE+2, ih->data->h-1-IDIAL_SPACE-1, ih->data->light_shadow, ih->data->dark_shadow);
+ }
+}
+
+static void iDialDrawCircularMark(Ihandle* ih, int x1, int y1)
+{
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasBox(ih->data->cddbuffer,x1, x1+4, y1, y1+4);
+
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->light_shadow);
+ cdCanvasLine(ih->data->cddbuffer, x1, y1+1, x1, y1+3);
+ cdCanvasLine(ih->data->cddbuffer, x1+1, y1+4, x1+3, y1+4);
+
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->mid_shadow);
+ cdCanvasLine(ih->data->cddbuffer, x1+1, y1, x1+4, y1);
+ cdCanvasLine(ih->data->cddbuffer, x1+4, y1, x1+4, y1+3);
+
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->dark_shadow);
+ cdCanvasLine(ih->data->cddbuffer, x1+2, y1, x1+3, y1);
+ cdCanvasLine(ih->data->cddbuffer, x1+4, y1+1, x1+4, y1+2);
+}
+
+static void iDialDrawCircular(Ihandle* ih)
+{
+ double delta = 2 * M_PI / ih->data->num_div, a = ih->data->angle;
+ int i, xc = ih->data->w / 2, yc = ih->data->h / 2, wide;
+ ih->data->radius = dialmin(ih->data->w, ih->data->h) / 2 - 2 * IDIAL_SPACE;
+
+ wide = (int)(2 * ih->data->radius);
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->mid_shadow);
+ cdCanvasLineWidth(ih->data->cddbuffer, 2);
+ cdCanvasArc(ih->data->cddbuffer, xc, yc, wide-1, wide-1, -135, 45.0);
+ cdCanvasLineWidth(ih->data->cddbuffer, 1);
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasSector(ih->data->cddbuffer, xc, yc, wide-2, wide-2, 0.0, 360.0);
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->light_shadow);
+ cdCanvasArc(ih->data->cddbuffer, xc, yc, wide, wide, 45, 225);
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->dark_shadow);
+ cdCanvasArc(ih->data->cddbuffer, xc, yc, wide, wide, -135, 45);
+
+ for (i = 0; i < ih->data->num_div; ++i)
+ {
+ int x2 = (int)(xc + (ih->data->radius - 6) * cos(a));
+ int y2 = (int)(yc + (ih->data->radius - 6) * sin(a));
+
+ if (i == 0)
+ {
+ cdCanvasForeground(ih->data->cddbuffer, CD_BLACK);
+ cdCanvasLine(ih->data->cddbuffer, xc, yc, x2, y2);
+ }
+
+ iDialDrawCircularMark(ih, x2-2, y2-2);
+ a += delta;
+ }
+
+ iDialDrawCircularMark(ih, xc-2, yc-2);
+}
+
+static void iDialRepaint(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return;
+
+ /* update render */
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+ ih->data->Draw(ih);
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, 0, 0, ih->data->w-1, ih->data->h-1);
+}
+
+static void iDialUpdateFgColors(Ihandle* ih, unsigned char r, unsigned char g, unsigned char b)
+{
+ int i, max, deltar, deltag, deltab;
+
+ /* this function is also called before mapping */
+ max = (ih->handle && iupdrvIsActive(ih))? 255 : 192;
+ deltar = (max-r) / IDIAL_NCOLORS;
+ deltag = (max-g) / IDIAL_NCOLORS;
+ deltab = (max-b) / IDIAL_NCOLORS;
+
+ for (i=0; i<=IDIAL_NCOLORS; i++)
+ {
+ ih->data->fgcolor[i] = cdEncodeColor(r, g, b);
+ r = (unsigned char)(r + deltar);
+ g = (unsigned char)(g + deltag);
+ b = (unsigned char)(b + deltab);
+ }
+}
+
+static int iDialButtonPress(Ihandle* ih, int button, int x, int y)
+{
+ IFn cb;
+
+ if (button!=IUP_BUTTON1)
+ return IUP_DEFAULT;
+
+ y = cdIupInvertYAxis(y, ih->data->h);
+ ih->data->px = x;
+ ih->data->py = y;
+
+ if (ih->data->type != IDIAL_CIRCULAR)
+ ih->data->angle=0;
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ cb(ih);
+ else
+ {
+ IFnd cb_old = (IFnd) IupGetCallback(ih, "BUTTON_PRESS_CB");
+ if (cb_old)
+ cb_old(ih, ih->data->angle * ih->data->unit);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iDialButtonRelease(Ihandle* ih, int button)
+{
+ IFn cb;
+
+ if (button!=IUP_BUTTON1)
+ return IUP_DEFAULT;
+
+ iDialRepaint(ih);
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ cb(ih);
+ else
+ {
+ IFnd cb_old = (IFnd) IupGetCallback(ih, "BUTTON_RELEASE_CB");
+ if (cb_old)
+ cb_old(ih, ih->data->angle * ih->data->unit);
+ }
+
+ return IUP_DEFAULT;
+}
+
+
+/******************************************************************/
+
+
+static int iDialMotionVertical_CB(Ihandle* ih, int x, int y, char *status)
+{
+ IFn cb;
+ (void)x; /* not used */
+
+ if (!iup_isbutton1(status))
+ return IUP_DEFAULT;
+
+ y = cdIupInvertYAxis(y, ih->data->h);
+ ih->data->angle += (double)(y-ih->data->py) / ih->data->radius;
+ ih->data->py = y;
+
+ iDialRepaint(ih);
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ cb(ih);
+ else
+ {
+ IFnd cb_old = (IFnd) IupGetCallback(ih, "MOUSEMOVE_CB");
+ if (cb_old)
+ cb_old(ih, ih->data->angle * ih->data->unit);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iDialMotionHorizontal_CB(Ihandle* ih, int x, int y, char *status)
+{
+ IFn cb;
+
+ if (!iup_isbutton1(status))
+ return IUP_DEFAULT;
+
+ y = cdIupInvertYAxis(y, ih->data->h);
+ ih->data->angle += (double)(x-ih->data->px) / ih->data->radius;
+ ih->data->px = x;
+
+ iDialRepaint(ih);
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ cb(ih);
+ else
+ {
+ IFnd cb_old = (IFnd) IupGetCallback(ih, "MOUSEMOVE_CB");
+ if (cb_old)
+ cb_old(ih, ih->data->angle * ih->data->unit);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iDialMotionCircular_CB(Ihandle* ih, int x, int y, char *status)
+{
+ int cx = ih->data->w / 2;
+ int cy = ih->data->h / 2;
+ double vet, xa, ya, xb, yb, ma, mb, ab;
+ IFn cb;
+
+ if (!iup_isbutton1(status))
+ return IUP_DEFAULT;
+
+ y = cdIupInvertYAxis(y, ih->data->h);
+
+ xa = ih->data->px-cx;
+ ya = ih->data->py-cy;
+ ma = sqrt(xa * xa + ya * ya);
+
+ xb = x - cx;
+ yb = y - cy;
+ mb = sqrt(xb * xb + yb * yb);
+
+ ab = xa * xb + ya * yb;
+ vet = xa * yb - xb * ya;
+
+ ab = ab / (ma * mb);
+
+ /* if the mouse is in the center of the dial, ignore it */
+ if (ma == 0 || mb == 0 || ab < -1 || ab > 1)
+ return IUP_DEFAULT;
+
+ if (vet>0) ih->data->angle += acos(ab);
+ else ih->data->angle -= acos(ab);
+
+ iDialRepaint(ih);
+ ih->data->px = x;
+ ih->data->py = y;
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ cb(ih);
+ else
+ {
+ IFnd cb_old = (IFnd) IupGetCallback(ih, "MOUSEMOVE_CB");
+ if (cb_old)
+ cb_old(ih, ih->data->angle * ih->data->unit);
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iDialButton_CB(Ihandle* ih, int button, int pressed, int x, int y)
+{
+ if (pressed)
+ return iDialButtonPress(ih, button, x, y);
+ else
+ return iDialButtonRelease(ih, button);
+}
+
+static int iDialResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ /* update number of divisions */
+ switch(ih->data->type)
+ {
+ case IDIAL_VERTICAL:
+ ih->data->num_div = (int)((ih->data->h-2 * IDIAL_SPACE-2) * ih->data->density);
+ break;
+
+ case IDIAL_HORIZONTAL:
+ ih->data->num_div = (int)((ih->data->w-2 * IDIAL_SPACE-2) * ih->data->density);
+ break;
+
+ case IDIAL_CIRCULAR:
+ ih->data->num_div = (int)((dialmin(ih->data->w, ih->data->h)-2 * IDIAL_SPACE-2) * ih->data->density);
+ break;
+ }
+
+ /* update render */
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+ ih->data->Draw(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iDialRedraw_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, 0, 0, ih->data->w-1, ih->data->h-1);
+
+ return IUP_DEFAULT;
+}
+
+static int iDialFocus_CB(Ihandle* ih, int focus)
+{
+ ih->data->has_focus = focus;
+ iDialRepaint(ih);
+ return IUP_DEFAULT;
+}
+
+static int iDialKeyPress_CB(Ihandle* ih, int c, int press)
+{
+ IFn cb;
+ char* cb_name;
+
+ if (c != K_LEFT && c != K_UP &&
+ c != K_sLEFT && c != K_sUP &&
+ c != K_RIGHT && c != K_DOWN &&
+ c != K_sRIGHT && c != K_sDOWN &&
+ c != K_HOME)
+ return IUP_DEFAULT;
+
+ if (press && ih->data->pressing)
+ {
+ switch(c)
+ {
+ case K_sLEFT:
+ case K_sDOWN:
+ ih->data->angle -= M_PI / 100.0;
+ break;
+ case K_LEFT:
+ case K_DOWN:
+ ih->data->angle -= M_PI / 10.0;
+ break;
+ case K_sRIGHT:
+ case K_sUP:
+ ih->data->angle += M_PI / 100.0;
+ break;
+ case K_RIGHT:
+ case K_UP:
+ ih->data->angle += M_PI / 10.0;
+ break;
+ }
+ }
+
+ if (c == K_HOME)
+ ih->data->angle = 0;
+
+ if (press)
+ {
+ if (ih->data->pressing)
+ {
+ cb_name = "MOUSEMOVE_CB";
+ }
+ else
+ {
+ ih->data->pressing = 1;
+ if (ih->data->type != IDIAL_CIRCULAR)
+ ih->data->angle = 0;
+ cb_name = "BUTTON_PRESS_CB";
+ }
+ }
+ else
+ {
+ ih->data->pressing = 0;
+ cb_name = "RELEASE_CB";
+ }
+
+ iDialRepaint(ih);
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ cb(ih);
+ else
+ {
+ IFnd cb_old = (IFnd) IupGetCallback(ih, cb_name);
+ if (cb_old)
+ cb_old(ih, ih->data->angle * ih->data->unit);
+ }
+
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+}
+
+static int iDialWheel_CB(Ihandle* ih, float delta)
+{
+ IFn cb;
+
+ ih->data->angle += ((double)delta) * (M_PI / 10.0);
+
+ if (fabs(ih->data->angle) < M_PI / 10.1)
+ ih->data->angle = 0;
+
+ iDialRepaint(ih);
+
+ cb = (IFn)IupGetCallback(ih, "VALUECHANGED_CB");
+ if (cb)
+ cb(ih);
+ else
+ {
+ IFnd cb_old = (IFnd) IupGetCallback(ih, "MOUSEMOVE_CB");
+ if (cb_old)
+ cb_old(ih, ih->data->angle * ih->data->unit);
+ }
+
+ return IUP_DEFAULT;
+}
+
+
+/*********************************************************************************/
+
+
+static char* iDialGetValueAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%f", ih->data->angle);
+ return str;
+}
+
+static int iDialSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (!value) /* reset to default */
+ ih->data->angle = 0;
+ else
+ ih->data->angle = atof(value);
+
+ iDialRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static int iDialSetDensityAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->density = atof(value);
+ iDialRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iDialGetDensityAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%f", ih->data->density);
+ return str;
+}
+
+static int iDialSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = iupControlBaseGetParentBgColor(ih);
+
+ ih->data->bgcolor = cdIupConvertColor(value);
+
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+ if (!iupdrvIsActive(ih))
+ ih->data->light_shadow = ih->data->mid_shadow;
+
+ iDialRepaint(ih);
+ return 1;
+}
+
+static int iDialSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char r, g, b;
+
+ if (!iupStrToRGB(value, &r, &g, &b))
+ return 0;
+ iDialUpdateFgColors(ih, r, g, b);
+
+ iDialRepaint(ih);
+ return 1;
+}
+
+static int iDialSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char r, g, b;
+
+ iupBaseSetActiveAttrib(ih, value);
+
+ value = iupAttribGetStr(ih, "FGCOLOR");
+ if (!iupStrToRGB(value, &r, &g, &b))
+ return 0;
+ iDialUpdateFgColors(ih, r, g, b);
+
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+ if (!iupdrvIsActive(ih))
+ ih->data->light_shadow = ih->data->mid_shadow;
+
+ iDialRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static int iDialSetUnitAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->unit = iupStrEqualNoCase(value, "DEGREES")? CD_RAD2DEG : 1.0;
+ return 1;
+}
+
+static int iDialSetTypeAttrib(Ihandle* ih, const char* value)
+{
+ /* valid only before map */
+ if (ih->handle)
+ return 0;
+
+ if (iupStrEqualNoCase(value, "VERTICAL"))
+ {
+ ih->data->Draw = iDialDrawVertical;
+ ih->data->type = IDIAL_VERTICAL;
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iDialMotionVertical_CB);
+ IupSetAttribute(ih, "SIZE", "16x80");
+ }
+ else if (iupStrEqualNoCase(value, "CIRCULAR"))
+ {
+ ih->data->Draw = iDialDrawCircular;
+ ih->data->type = IDIAL_CIRCULAR;
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iDialMotionCircular_CB);
+ IupSetAttribute(ih, "SIZE", "40x36");
+ }
+ else /* "HORIZONTAL" */
+ {
+ ih->data->Draw = iDialDrawHorizontal;
+ ih->data->type = IDIAL_HORIZONTAL;
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iDialMotionHorizontal_CB);
+ IupSetAttribute(ih, "SIZE", "80x16");
+ }
+ return 0; /* do not store value in hash table */
+}
+
+static char* iDialGetTypeAttrib(Ihandle* ih)
+{
+ if (ih->data->type == IDIAL_HORIZONTAL)
+ return "HORIZONTAL";
+ else if (ih->data->type == IDIAL_VERTICAL)
+ return "VERTICAL";
+ else /* (ih->data->type == IDIAL_CIRCULAR) */
+ return "CIRCULAR";
+}
+
+
+/****************************************************************************/
+
+
+static int iDialMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ return IUP_NOERROR;
+}
+
+static void iDialUnMapMethod(Ihandle* ih)
+{
+ if (ih->data->cddbuffer)
+ cdKillCanvas(ih->data->cddbuffer);
+
+ if (ih->data->cdcanvas)
+ cdKillCanvas(ih->data->cdcanvas);
+}
+
+static int iDialCreateMethod(Ihandle* ih, void **params)
+{
+ char* type = "HORIZONTAL";
+ if (params && params[0])
+ type = params[0];
+
+ /* free the data allocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "BORDER", "NO");
+ ih->expand = IUP_EXPAND_NONE;
+
+ /* default values */
+ iDialSetTypeAttrib(ih, type);
+ ih->data->density = IDIAL_DEFAULT_DENSITY;
+ ih->data->unit = 1.0; /* RADIANS */
+ iDialUpdateFgColors(ih, IDIAL_DEFAULT_FGCOLOR_COMP, IDIAL_DEFAULT_FGCOLOR_COMP, IDIAL_DEFAULT_FGCOLOR_COMP);
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "ACTION", (Icallback)iDialRedraw_CB);
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iDialResize_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iDialButton_CB);
+ IupSetCallback(ih, "FOCUS_CB", (Icallback)iDialFocus_CB);
+ IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iDialKeyPress_CB);
+ IupSetCallback(ih, "WHEEL_CB", (Icallback)iDialWheel_CB);
+
+ return IUP_NOERROR;
+}
+
+Iclass* iupDialGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "dial";
+ ic->format = "S"; /* one optional string */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+
+ /* Class functions */
+ ic->Create = iDialCreateMethod;
+ ic->Map = iDialMapMethod;
+ ic->UnMap = iDialUnMapMethod;
+
+ /* Do not need to set base attributes because they are inherited from IupCanvas */
+
+ /* IupDial Callbacks */
+ iupClassRegisterCallback(ic, "MOUSEMOVE_CB", "d");
+ iupClassRegisterCallback(ic, "BUTTON_PRESS_CB", "d");
+ iupClassRegisterCallback(ic, "BUTTON_RELEASE_CB", "d");
+ iupClassRegisterCallback(ic, "VALUECHANGED_CB", "");
+
+ /* IupDial only */
+ iupClassRegisterAttribute(ic, "VALUE", iDialGetValueAttrib, iDialSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TYPE", iDialGetTypeAttrib, iDialSetTypeAttrib, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "DENSITY", iDialGetDensityAttrib, iDialSetDensityAttrib, IDIAL_DEFAULT_DENSITY_STR, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iDialSetFgColorAttrib, IDIAL_DEFAULT_FGCOLOR, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "UNIT", NULL, iDialSetUnitAttrib, IUPAF_SAMEASSYSTEM, "RADIANS", IUPAF_NOT_MAPPED);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iDialSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupControlBaseGetBgColorAttrib, iDialSetBgColorAttrib, NULL, "255 255 255", IUPAF_NO_INHERIT); /* overwrite canvas implementation, set a system default to force a new default */
+
+ return ic;
+}
+
+Ihandle* IupDial(const char* type)
+{
+ void *params[2];
+ params[0] = (void*)type;
+ params[1] = NULL;
+ return IupCreatev("dial", params);
+}
diff --git a/iup/srccontrols/iup_gauge.c b/iup/srccontrols/iup_gauge.c
new file mode 100755
index 0000000..8732eee
--- /dev/null
+++ b/iup/srccontrols/iup_gauge.c
@@ -0,0 +1,435 @@
+/** \file
+ * \brief Gauge control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+
+#define IGAUGE_DEFAULTCOLOR "64 96 192"
+#define IGAUGE_DEFAULTSIZE "120x14"
+
+#define IGAUGE_GAP 3
+#define IGAUGE_BLOCKS 20
+
+#define gaugeround(_) ((int)((_)+.5))
+
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ int w;
+ int h;
+
+ int show_text;
+ int dashed;
+ int horiz_padding, vert_padding; /* internal margin */
+
+ long bgcolor;
+ long fgcolor;
+ long light_shadow;
+ long mid_shadow;
+ long dark_shadow;
+
+ double value; /* min<=value<max */
+ double vmin;
+ double vmax;
+
+ char* text;
+
+ cdCanvas *cddbuffer;
+ cdCanvas *cdcanvas;
+};
+
+
+static void iGaugeDrawText(Ihandle* ih, int xmid)
+{
+ int x, y, xmin, xmax, ymin, ymax;
+ char* text = ih->data->text;
+
+ cdCanvasNativeFont(ih->data->cddbuffer, IupGetAttribute(ih, "FONT"));
+ cdCanvasTextAlignment(ih->data->cddbuffer, CD_CENTER);
+ cdCanvasBackOpacity(ih->data->cddbuffer, CD_TRANSPARENT);
+
+ x = (int)(0.5 * ih->data->w);
+ y = (int)(0.5 * ih->data->h);
+
+ if(text == NULL)
+ {
+ char* m = iupStrGetMemory(30);
+ sprintf(m, "%.1f%%", 100 * (ih->data->value - ih->data->vmin) / (ih->data->vmax - ih->data->vmin));
+ text = m;
+ }
+
+ cdCanvasGetTextBox(ih->data->cddbuffer, x, y, text, &xmin, &xmax, &ymin, &ymax);
+
+ if(xmid < xmin)
+ {
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->fgcolor);
+ cdCanvasText(ih->data->cddbuffer, x, y, text);
+ }
+ else if(xmid > xmax)
+ {
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasText(ih->data->cddbuffer, x, y, text);
+ }
+ else
+ {
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
+ cdCanvasClipArea(ih->data->cddbuffer, xmin, xmid, ymin, ymax);
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasText(ih->data->cddbuffer, x, y, text);
+
+ cdCanvasClipArea(ih->data->cddbuffer, xmid, xmax, ymin, ymax);
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->fgcolor);
+ cdCanvasText(ih->data->cddbuffer, x, y, text);
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+ }
+}
+
+static void iGaugeDrawGauge(Ihandle* ih)
+{
+ int border = 3; /* includes the pixel used to draw the 3D border */
+ int xstart = ih->data->horiz_padding+border;
+ int ystart = ih->data->vert_padding+border;
+ int xend = ih->data->w-1 - (ih->data->horiz_padding+border);
+ int yend = ih->data->h-1 - (ih->data->vert_padding+border);
+
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+
+ cdIupDrawSunkenRect(ih->data->cddbuffer, 0, 0, ih->data->w-1, ih->data->h-1,
+ ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->fgcolor);
+
+ if (ih->data->dashed)
+ {
+ float step = (xend - xstart + 1) / (float)IGAUGE_BLOCKS;
+ float boxw = step - IGAUGE_GAP;
+ float vx = (float)((xend-xstart + 1) * (ih->data->value - ih->data->vmin) / (ih->data->vmax - ih->data->vmin));
+ int intvx = (int)(100 * vx);
+ float i = 0;
+
+ if(ih->data->value == ih->data->vmin)
+ return;
+
+ while(gaugeround(100*(i + boxw)) <= intvx)
+ {
+ cdCanvasBox(ih->data->cddbuffer, xstart + gaugeround(i),
+ xstart + gaugeround(i + boxw) - 1, ystart, yend);
+ i += step;
+ }
+ }
+ else
+ {
+ int xmid = xstart + gaugeround((xend-xstart + 1) * (ih->data->value - ih->data->vmin) / (ih->data->vmax - ih->data->vmin));
+
+ if(ih->data->value != ih->data->vmin)
+ cdCanvasBox(ih->data->cddbuffer, xstart, xmid, ystart, yend );
+
+ if(ih->data->show_text)
+ iGaugeDrawText(ih, xmid);
+ }
+}
+
+static int iGaugeResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer,&ih->data->w,&ih->data->h,NULL,NULL);
+
+ /* update render */
+ iGaugeDrawGauge(ih);
+
+ return IUP_DEFAULT;
+}
+
+static void iGaugeRepaint(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return;
+
+ /* update render */
+ iGaugeDrawGauge(ih);
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+}
+
+static int iGaugeRedraw_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ return IUP_DEFAULT;
+}
+
+static void iGaugeCropValue(Ihandle* ih)
+{
+ if(ih->data->value>ih->data->vmax)
+ ih->data->value = ih->data->vmax;
+ else if(ih->data->value<ih->data->vmin)
+ ih->data->value = ih->data->vmin;
+}
+
+static int iGaugeSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->fgcolor = cdIupConvertColor(value);
+ iGaugeRepaint(ih);
+ return 1;
+}
+
+static int iGaugeSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = iupControlBaseGetParentBgColor(ih);
+
+ ih->data->bgcolor = cdIupConvertColor(value);
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+
+ iGaugeRepaint(ih);
+ return 1;
+}
+
+static int iGaugeSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if(value == NULL)
+ ih->data->value = 0;
+ else
+ ih->data->value = atof(value);
+ iGaugeCropValue(ih);
+
+ iGaugeRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iGaugeGetValueAttrib(Ihandle* ih)
+{
+ char* value = iupStrGetMemory(30);
+ sprintf(value, "%g", ih->data->value);
+ return value;
+}
+
+static int iGaugeSetMinAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->vmin = atof(value);
+ iGaugeCropValue(ih);
+
+ iGaugeRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iGaugeGetMinAttrib(Ihandle* ih)
+{
+ char* value = iupStrGetMemory(30);
+ sprintf(value, "%g", ih->data->vmin);
+ return value;
+}
+
+static int iGaugeSetMaxAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->vmax = atof(value);
+ iGaugeCropValue(ih);
+ iGaugeRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iGaugeGetMaxAttrib(Ihandle* ih)
+{
+ char* value = iupStrGetMemory(30);
+ sprintf(value, "%g", ih->data->vmax);
+ return value;
+}
+
+static int iGaugeSetShowTextAttrib(Ihandle* ih, const char* value)
+{
+ if(iupStrEqualNoCase(value, "YES"))
+ ih->data->show_text = 1;
+ else if(iupStrEqualNoCase(value, "NO"))
+ ih->data->show_text = 0;
+
+ iGaugeRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iGaugeGetShowTextAttrib(Ihandle* ih)
+{
+ if(ih->data->show_text)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iGaugeSetPaddingAttrib(Ihandle* ih, const char* value)
+{
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ iGaugeRepaint(ih);
+ return 0;
+}
+
+static char* iGaugeGetPaddingAttrib(Ihandle* ih)
+{
+ char *str = iupStrGetMemory(50);
+ sprintf(str, "%dx%d", ih->data->horiz_padding, ih->data->vert_padding);
+ return str;
+}
+
+static int iGaugeSetDashedAttrib(Ihandle* ih, const char* value)
+{
+ if(iupStrEqualNoCase(value, "YES"))
+ ih->data->dashed = 1;
+ else if(iupStrEqualNoCase(value, "NO"))
+ ih->data->dashed = 0;
+
+ iGaugeRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iGaugeGetDashedAttrib(Ihandle* ih)
+{
+ if(ih->data->dashed)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iGaugeSetTextAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->text)
+ free(ih->data->text);
+
+ ih->data->text = iupStrDup(value);
+
+ iGaugeRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iGaugeGetTextAttrib(Ihandle* ih)
+{
+ return ih->data->text;
+}
+
+static void iGaugeUnMapMethod(Ihandle* ih)
+{
+ if (ih->data->cddbuffer)
+ cdKillCanvas(ih->data->cddbuffer);
+
+ if (ih->data->cdcanvas)
+ cdKillCanvas(ih->data->cdcanvas);
+}
+
+static int iGaugeMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ return IUP_NOERROR;
+}
+
+static int iGaugeCreateMethod(Ihandle* ih, void **params)
+{
+ (void)params;
+
+ /* free the data allocated by IupCanvas */
+ if (ih->data)
+ free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "BORDER", "NO");
+ IupSetAttribute(ih, "SIZE", IGAUGE_DEFAULTSIZE);
+ ih->expand = IUP_EXPAND_NONE;
+
+ /* default values */
+ iupAttribSetStr(ih, "FGCOLOR", IGAUGE_DEFAULTCOLOR);
+ ih->data->fgcolor = cdIupConvertColor(IGAUGE_DEFAULTCOLOR);
+ ih->data->vmax = 1;
+ ih->data->bgcolor = CD_GRAY;
+ ih->data->light_shadow = CD_WHITE;
+ ih->data->mid_shadow = CD_GRAY;
+ ih->data->dark_shadow = CD_DARK_GRAY;
+ ih->data->show_text = 1;
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iGaugeResize_CB);
+ IupSetCallback(ih, "ACTION", (Icallback)iGaugeRedraw_CB);
+
+ return IUP_NOERROR;
+}
+
+Iclass* iupGaugeGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "gauge";
+ ic->format = NULL; /* no parameters */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 0;
+
+ /* Class functions */
+ ic->Create = iGaugeCreateMethod;
+ ic->Map = iGaugeMapMethod;
+ ic->UnMap = iGaugeUnMapMethod;
+
+ /* Do not need to set base attributes because they are inherited from IupCanvas */
+
+ /* IupGauge only */
+ iupClassRegisterAttribute(ic, "MIN", iGaugeGetMinAttrib, iGaugeSetMinAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MAX", iGaugeGetMaxAttrib, iGaugeSetMaxAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUE", iGaugeGetValueAttrib, iGaugeSetValueAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DASHED", iGaugeGetDashedAttrib, iGaugeSetDashedAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "PADDING", iGaugeGetPaddingAttrib, iGaugeSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "TEXT", iGaugeGetTextAttrib, iGaugeSetTextAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOW_TEXT", iGaugeGetShowTextAttrib, iGaugeSetShowTextAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iGaugeSetFgColorAttrib, IGAUGE_DEFAULTCOLOR, NULL, IUPAF_NOT_MAPPED);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupControlBaseGetBgColorAttrib, iGaugeSetBgColorAttrib, NULL, "255 255 255", IUPAF_NO_INHERIT); /* overwrite canvas implementation, set a system default to force a new default */
+
+ return ic;
+}
+
+Ihandle *IupGauge(void)
+{
+ return IupCreate("gauge");
+}
diff --git a/iup/srccontrols/iup_oldmask.c b/iup/srccontrols/iup_oldmask.c
new file mode 100755
index 0000000..fec10f3
--- /dev/null
+++ b/iup/srccontrols/iup_oldmask.c
@@ -0,0 +1,208 @@
+/** \file
+ * \brief OLD mask pattern matching
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "iup.h"
+#include "iupcontrols.h"
+#include "iupmask.h"
+
+#include "iup_mask.h"
+#include "iup_str.h"
+
+
+void iupmaskRemove(Ihandle *ih)
+{
+ IupSetAttribute(ih,"MASK", NULL);
+}
+
+void iupmaskMatRemove(Ihandle *ih, int lin, int col)
+{
+ IupMatSetAttribute(ih,"MASK", lin, col, NULL);
+}
+
+int iupmaskSetInt(Ihandle *ih, int autofill, int min, int max)
+{
+ (void)autofill;
+ IupSetfAttribute(ih,"MASKINT", "%d:%d", min, max);
+ return 1;
+}
+
+int iupmaskMatSetInt(Ihandle *ih, int autofill, int min, int max, int lin, int col)
+{
+ (void)autofill;
+ IupMatSetfAttribute(ih,"MASKINT", lin, col, "%d:%d", min, max);
+ return 1;
+}
+
+int iupmaskSetFloat(Ihandle* ih, int autofill, float min, float max)
+{
+ (void)autofill;
+ IupSetfAttribute(ih,"MASKFLOAT", "%f:%f", min, max);
+ return 1;
+}
+
+int iupmaskMatSetFloat(Ihandle* ih, int autofill, float min, float max, int lin, int col)
+{
+ (void)autofill;
+ IupMatSetfAttribute(ih,"MASKFLOAT", lin, col, "%f:%f", min, max);
+ return 0;
+}
+
+int iupmaskSet(Ihandle* ih, const char* mask_str, int autofill, int casei)
+{
+ (void)autofill;
+ IupSetAttribute(ih,"MASKCASEI", casei?"YES":"NO");
+ IupStoreAttribute(ih,"MASK", mask_str);
+ if (iupStrEqual(mask_str, IupGetAttribute(ih,"MASK")))
+ return 1;
+ else
+ return 0;
+}
+
+int iupmaskMatSet(Ihandle* ih, const char* mask_str, int autofill, int casei, int lin, int col)
+{
+ (void)autofill;
+ IupMatSetAttribute(ih,"MASKCASEI", lin, col, casei?"YES":"NO");
+ IupMatSetAttribute(ih,"MASK", lin, col, (char*)mask_str);
+ if (iupStrEqual(mask_str, IupMatGetAttribute(ih,"MASK", lin, col)))
+ return 1;
+ else
+ return 0;
+}
+
+int iupmaskCheck(Ihandle* ih)
+{
+ char *val = IupGetAttribute(ih,"VALUE");
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+ return iupMaskCheck(mask,val)==1;
+}
+
+int iupmaskMatCheck(Ihandle *ih, int lin, int col)
+{
+ char *val = IupMatGetAttribute(ih,"",lin,col);
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+ return iupMaskCheck(mask,val)==1;
+}
+
+int iupmaskGet(Ihandle *ih, char **sval)
+{
+ char *val = IupGetAttribute(ih,"VALUE");
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if (iupMaskCheck(mask,val)==1)
+ {
+ *sval = val;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int iupmaskMatGet(Ihandle *ih, char **sval, int lin, int col)
+{
+ char *val = IupMatGetAttribute(ih,"",lin,col);
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if (iupMaskCheck(mask,val)==1)
+ {
+ *sval = val;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int iupmaskGetDouble(Ihandle *ih, double *dval)
+{
+ char *val = IupGetAttribute(ih,"VALUE");
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if(iupMaskCheck(mask,val)==1)
+ {
+ *dval = 0.0;
+ sscanf(val,"%lf",dval);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int iupmaskMatGetDouble(Ihandle *ih, double *dval, int lin, int col)
+{
+ char *val = IupMatGetAttribute(ih,"",lin,col);
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if(iupMaskCheck(mask,val)==1)
+ {
+ *dval = 0.0;
+ sscanf(val,"%lf",dval);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int iupmaskGetFloat(Ihandle *ih, float *fval)
+{
+ char *val = IupGetAttribute(ih,"VALUE");
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if(iupMaskCheck(mask,val)==1)
+ {
+ *fval = 0.0F;
+ sscanf(val,"%f",fval);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int iupmaskMatGetFloat(Ihandle *ih, float *fval, int lin, int col)
+{
+ char *val = IupMatGetAttribute(ih,"",lin,col);
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if (iupMaskCheck(mask,val)==1)
+ {
+ *fval = 0.0F;
+ sscanf(val,"%f",fval);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int iupmaskGetInt(Ihandle *ih, int *ival)
+{
+ char *val = IupGetAttribute(ih,"VALUE");
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if (iupMaskCheck(mask,val)==1)
+ {
+ *ival = 0;
+ sscanf(val,"%d",ival);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int iupmaskMatGetInt(Ihandle *ih, int *ival, int lin, int col)
+{
+ char *val = IupMatGetAttribute(ih,"",lin,col);
+ Imask* mask = (Imask*)IupGetAttribute(ih,"OLD_MASK_DATA");
+
+ if(iupMaskCheck(mask,val)==1)
+ {
+ *ival = 0;
+ sscanf(val,"%d",ival);
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/iup/srccontrols/iup_oldtabs.c b/iup/srccontrols/iup_oldtabs.c
new file mode 100755
index 0000000..43b0c57
--- /dev/null
+++ b/iup/srccontrols/iup_oldtabs.c
@@ -0,0 +1,2616 @@
+/** \file
+ * \brief iuptabs control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_register.h"
+#include "iup_layout.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+
+
+/* Constants */
+static const int ITABS_BORDER = 1;
+static const int ITABS_MARGIN = 10;
+static const int ITABS_SPACING = 2;
+static const int ITABS_SCROLL_LENGTH = 51; /* the length of the scroll control in any direction */
+static const int ITABS_SCROLL_THICK = 17;
+static const int ITABS_SCROLL_SPACING = 7;
+static const int ITABS_BROKEN_TAB = 8;
+static const int ITABS_CURRENT_EXTRA_PIXELS = 1;
+
+/* Enum's */
+typedef enum
+{
+ ITABS_TOP, ITABS_BOTTOM, ITABS_LEFT, ITABS_RIGHT
+} ItabsType;
+
+typedef enum
+{
+ ITABS_FALSE, ITABS_TRUE
+} ItabsBool;
+
+typedef enum
+{
+ ITABS_BROKEN_NONE,
+ ITABS_BROKEN_START,
+ ITABS_BROKEN_END,
+ ITABS_BROKEN_CENTER
+} ItabsBrokenType;
+
+typedef enum
+{
+ ITABS_HORIZONTAL, ITABS_VERTICAL
+} ItabsOrientation;
+
+typedef enum
+{
+ ITABS_BUTTON_NONE,
+ ITABS_BUTTONPRESS_FORWARD, ITABS_BUTTONPRESS_MENU, ITABS_BUTTONPRESS_BACKWARD, /* can not change order because of "+= 3" */
+ ITABS_BUTTONRELEASE_FORWARD, ITABS_BUTTONRELEASE_MENU, ITABS_BUTTONRELEASE_BACKWARD
+} ItabsButtonState;
+
+typedef enum
+{
+ ITABS_RENDER_PLANE_ALIGN, ITABS_RENDER_PLANE_NORMAL
+} ItabsTextRender;
+
+/* Info about how to draw each tab */
+typedef struct _tagTabsDrawInfo
+{
+ Ihandle* ihandle; /* child handle */
+ int text_w, /* width of the text of this Tab */
+ tab_len; /* len */
+} ItabsDrawInfo;
+
+typedef struct _tagTabsLine
+{
+ /* Visible tabs (start and end interval) */
+ int start_tab, end_tab;
+
+ /* Shows if any button is pressed */
+ ItabsButtonState button;
+
+ /* Info about how to draw each tab */
+ ItabsDrawInfo* tabs_info;
+
+ /* Shows if all the tabs are visible */
+ ItabsBool scroll_visible,
+ broken_start_visible,
+ broken_end_visible;
+
+ /* Shows if the current tab is visible, when
+ there are other tabs to the left or right */
+ ItabsBool broken_center_visible;
+
+ /* Available space to the broken tabs */
+ int broken_tab_space,
+ broken_space_start,
+ broken_space_end;
+
+ /* Tabs line size */
+ int line_thick,
+ line_length;
+
+ /* Point to thick and length according to render */
+ int* line_w;
+ int* line_h;
+
+ /* Tabs scroll size */
+ int scroll_len, /* the scroll space in the tabs line length direction */
+ scroll_thick,
+ scroll_x,
+ scroll_y,
+ scroll_w,
+ scroll_h;
+
+ int text_h; /* height of the text (all texts have the same height) */
+} ItabsLine;
+
+/* Control context */
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ /* tabs type */
+ ItabsType tabs_type;
+ ItabsOrientation tabs_orientation;
+ ItabsTextRender tabs_render; /* tabs line render (depends on
+ tabs type and orientation) */
+
+ cdCanvas* cdcanvas; /* CD canvas for drawing */
+ cdCanvas* cddbuffer; /* image canvas for double buffering */
+ Ihandle* zbox; /* Handle "zbox" is a child of Tabs */
+
+ int number_of_tabs; /* number of tabs */
+ int current_tab; /* current tab */
+ ItabsLine tabs_line; /* data from a queue of tabs */
+
+ /* data from width and weight */
+ int w, h;
+ int* max_line_length; /* pointer to w or h */
+
+ /* Used colors */
+ long bgcolor;
+ long fgcolor;
+ long light_shadow;
+ long mid_shadow;
+ long dark_shadow;
+
+ int has_focus,
+ focus_x1,
+ focus_x2,
+ focus_y1,
+ focus_y2;
+
+ char* font_active;
+ char* font_inactive;
+};
+
+static void iTabsUpdateRender(Ihandle* ih)
+{
+ if (ih->data->tabs_orientation == ITABS_VERTICAL)
+ {
+ if (ih->data->tabs_type == ITABS_LEFT || ih->data->tabs_type == ITABS_RIGHT)
+ ih->data->tabs_render = ITABS_RENDER_PLANE_ALIGN;
+ else
+ ih->data->tabs_render = ITABS_RENDER_PLANE_NORMAL;
+ }
+ else
+ {
+ if (ih->data->tabs_type == ITABS_LEFT || ih->data->tabs_type == ITABS_RIGHT)
+ ih->data->tabs_render = ITABS_RENDER_PLANE_NORMAL;
+ else
+ ih->data->tabs_render = ITABS_RENDER_PLANE_ALIGN;
+ }
+
+ if (ih->data->tabs_type == ITABS_LEFT || ih->data->tabs_type == ITABS_RIGHT)
+ {
+ ih->data->tabs_line.line_w = &ih->data->tabs_line.line_thick;
+ ih->data->tabs_line.line_h = &ih->data->tabs_line.line_length;
+ ih->data->max_line_length = &ih->data->h;
+ }
+ else
+ {
+ ih->data->tabs_line.line_w = &ih->data->tabs_line.line_length;
+ ih->data->tabs_line.line_h = &ih->data->tabs_line.line_thick;
+ ih->data->max_line_length = &ih->data->w;
+ }
+
+ if (ih->data->tabs_render == ITABS_RENDER_PLANE_NORMAL)
+ {
+ ih->data->tabs_line.scroll_len = ITABS_SCROLL_THICK;
+ ih->data->tabs_line.scroll_thick = ITABS_SCROLL_LENGTH;
+ }
+ else
+ {
+ ih->data->tabs_line.scroll_len = ITABS_SCROLL_LENGTH;
+ ih->data->tabs_line.scroll_thick = ITABS_SCROLL_THICK;
+ }
+
+ if (ih->data->tabs_orientation == ITABS_HORIZONTAL)
+ {
+ ih->data->tabs_line.scroll_w = ITABS_SCROLL_LENGTH;
+ ih->data->tabs_line.scroll_h = ITABS_SCROLL_THICK;
+ }
+ else
+ {
+ ih->data->tabs_line.scroll_w = ITABS_SCROLL_THICK;
+ ih->data->tabs_line.scroll_h = ITABS_SCROLL_LENGTH;
+ }
+}
+
+static void iTabsSetCDFont(Ihandle* ih, char* tab_font, int bold)
+{
+ if (tab_font)
+ cdCanvasNativeFont(ih->data->cddbuffer, tab_font);
+ else
+ cdCanvasNativeFont(ih->data->cddbuffer, IupGetAttribute(ih, "FONT"));
+
+ if (bold)
+ cdCanvasFont(ih->data->cddbuffer, NULL, CD_BOLD, 0);
+}
+
+/* Gets the associated name of the tab */
+static Ihandle* iTabsGetTabIhandle(Ihandle* ih, int number)
+{
+ return ih->data->tabs_line.tabs_info[number].ihandle;
+}
+
+/* ========================================================================= */
+/* Drawing functions */
+/* ========================================================================= */
+
+/* Fills the draw area */
+static void iTabsFillArea(cdCanvas* canvas, int x1, int y1, int x2, int y2,
+ int x3, int y3, int x4, int y4)
+{
+ cdCanvasBegin(canvas, CD_FILL);
+ cdCanvasVertex(canvas, x1, y1);
+ cdCanvasVertex(canvas, x2, y2);
+ cdCanvasVertex(canvas, x3, y3);
+ cdCanvasVertex(canvas, x4, y4);
+ cdCanvasEnd(canvas);
+
+ cdCanvasBegin(canvas, CD_CLOSED_LINES);
+ cdCanvasVertex(canvas, x1, y1);
+ cdCanvasVertex(canvas, x2, y2);
+ cdCanvasVertex(canvas, x3, y3);
+ cdCanvasVertex(canvas, x4, y4);
+ cdCanvasEnd(canvas);
+}
+
+/* Draws the broken borders */
+static void iTabsDrawBrokenBorder(Ihandle* ih, ItabsType type, int x1, int y1, int x2, int y2)
+{
+ cdCanvas* canvas = ih->data->cddbuffer;
+ double step_x = (x2 - x1) / 5;
+ double step_y = (y2 - y1) / 5;
+ int old_color = cdCanvasForeground(canvas, CD_QUERY);
+
+ switch(type)
+ {
+ case ITABS_TOP:
+ cdCanvasForeground(canvas, ih->data->mid_shadow);
+ cdCanvasLine(canvas, (int)(x1 + step_x * 3.), y1, (int)(x1 + 4. * step_x), y2);
+ cdCanvasLine(canvas, (int)(x1 + step_x), y1, (int)(x1 + 2. * step_x), y2);
+
+ cdCanvasForeground(canvas, ih->data->dark_shadow);
+ cdCanvasLine(canvas, x1, y1, (int)(x1 + step_x), y2);
+ cdCanvasLine(canvas, (int)(x1 + step_x), y1 - 1, (int)(x1 + 2. * step_x), y2 - 1);
+ cdCanvasLine(canvas, (int)(x1 + step_x * 2.), y1, (int)(x1 + 3. * step_x), y2);
+ cdCanvasLine(canvas, (int)(x1 + step_x * 3.), y1 + 1, (int)(x1 + 4. * step_x), y2 + 1);
+ cdCanvasLine(canvas, (int)(x1 + step_x * 4.), y1, x2, y2);
+ break;
+
+ case ITABS_BOTTOM:
+ cdCanvasForeground(canvas, ih->data->mid_shadow);
+ cdCanvasLine(canvas, (int)(x1 + step_x * 3.), y1, (int)(x1 + 4. * step_x), y2);
+ cdCanvasLine(canvas, (int)(x1 + step_x), y1, (int)(x1 + 2. * step_x), y2);
+
+ cdCanvasForeground(canvas, ih->data->dark_shadow);
+ cdCanvasLine(canvas, x1, y1, (int)(x1 + step_x), y2);
+ cdCanvasLine(canvas, (int)(x1 + step_x), y1 - 1, (int)(x1 + 2. * step_x), y2 - 1);
+ cdCanvasLine(canvas, (int)(x1 + step_x * 2.), y1, (int)(x1 + 3. * step_x), y2);
+ cdCanvasLine(canvas, (int)(x1 + step_x * 3.), y1 + 1, (int)(x1 + 4. * step_x), y2 + 1);
+ cdCanvasLine (canvas, (int)(x1 + step_x * 4.), y1, x2, y2);
+ break;
+
+ case ITABS_LEFT:
+ cdCanvasForeground(canvas, ih->data->mid_shadow);
+ cdCanvasLine(canvas, x1, (int)(y1 + 3. * step_y), x2, (int)(y1 + step_y * 4.));
+ cdCanvasLine(canvas, x1, (int)(y1 + step_y), x2, (int)(y1 + step_y * 2.));
+
+ cdCanvasForeground(canvas, ih->data->dark_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, (int)(y1 + step_y));
+ cdCanvasLine(canvas, x1 - 1, (int)(y1 + step_y), x2 - 1, (int)(y1 + step_y * 2.));
+ cdCanvasLine(canvas, x1, (int)(y1 + step_y * 2.), x2, (int)(y1 + step_y * 3.));
+ cdCanvasLine(canvas, x1 + 1, (int)(y1 + 3. * step_y), x2 + 1, (int)(y1 + step_y * 4.));
+ cdCanvasLine(canvas, x1, (int)(y1 + 4. * step_y), x2, y2);
+ break;
+
+ case ITABS_RIGHT:
+ cdCanvasForeground(canvas, ih->data->mid_shadow);
+ cdCanvasLine(canvas, x1, (int)(y1 + 3. * step_y), x2, (int)(y1 + step_y * 4.));
+ cdCanvasLine(canvas, x1, (int)(y1 + step_y), x2, (int)(y1 + step_y * 2.));
+
+ cdCanvasForeground(canvas, ih->data->dark_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, (int)(y1 + step_y));
+ cdCanvasLine(canvas, x1 - 1, (int)(y1 + step_y), x2 - 1, (int)(y1 + step_y * 2.));
+ cdCanvasLine(canvas, x1, (int)(y1 + step_y * 2.), x2, (int)(y1 + step_y * 3.));
+ cdCanvasLine(canvas, x1 + 1, (int)(y1 + 3. * step_y), x2 + 1, (int)(y1 + step_y * 4.));
+ cdCanvasLine(canvas, x1, (int)(y1 + 4. * step_y), x2, y2);
+ break;
+ }
+
+ cdCanvasForeground (canvas, old_color);
+}
+
+/* Draws the borders */
+static void iTabsDrawBorder(Ihandle* ih, ItabsType type, int x1, int y1, int x2, int y2)
+{
+ cdCanvas* canvas = ih->data->cddbuffer;
+
+ switch(type)
+ {
+ case ITABS_TOP:
+ cdCanvasForeground(canvas, ih->data->light_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, y2);
+ break;
+
+ case ITABS_LEFT:
+ cdCanvasForeground(canvas, ih->data->light_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, y2);
+ break;
+
+ case ITABS_BOTTOM:
+ cdCanvasForeground(canvas, ih->data->dark_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, y2);
+ cdCanvasForeground(canvas, ih->data->mid_shadow);
+ if (x1 > x2)
+ cdCanvasLine(canvas, x2+1, y1+1, x1-1, y2+1);
+ else
+ cdCanvasLine(canvas, x1+1, y1+1, x2-1, y2+1);
+ break;
+
+ case ITABS_RIGHT:
+ cdCanvasForeground(canvas, ih->data->dark_shadow);
+ cdCanvasLine(canvas, x1, y1, x2, y2);
+ cdCanvasForeground(canvas, ih->data->mid_shadow);
+ if (y1 > y2)
+ cdCanvasLine(canvas, x1-1, y2+1, x2-1, y1-1);
+ else
+ cdCanvasLine(canvas, x1-1, y1+1, x2-1, y2-1);
+ break;
+ }
+}
+
+/* Draws a tab corner */
+static void iTabsDrawCorner(Ihandle* ih, int color, int x1, int y1, int x2, int y2)
+{
+ cdCanvas* canvas = ih->data->cddbuffer;
+
+ cdCanvasForeground(canvas, ih->data->bgcolor);
+ cdCanvasLine(canvas, x1, y1, x2, y1);
+ cdCanvasLine(canvas, x1, y1, x1, y2);
+ cdCanvasForeground(canvas,color);
+ cdCanvasLine(canvas, x1, y2, x2, y1);
+}
+
+/* Draws a tab */
+static void iTabsDrawTab(Ihandle* ih, int tab_index, int offset)
+{
+ cdCanvas* canvas = ih->data->cddbuffer;
+ int x1, y1, x2, y2, x3, y3, x4, y4, x1a, y1a, x4a, y4a;
+ int tab_w, tab_h;
+ int x_text = 0, y_text = 0;
+ int line_thick, tab_len, full_tab_len;
+ ItabsType types[3];
+ ItabsBool beforeCurrent, afterCurrent;
+ int extraHeight = (tab_index == ih->data->current_tab) ? 0 : 1;
+ ItabsBrokenType type;
+
+ /* there is an error in visible tabs that happen when you change the tab configuration dynamically */
+ if (tab_index < 0 || tab_index > ih->data->number_of_tabs-1)
+ return;
+
+ /* Defines what type of tab that will be drawn and sets the length */
+ full_tab_len = ih->data->tabs_line.tabs_info[tab_index].tab_len;
+
+ if (tab_index == (ih->data->tabs_line.end_tab + 1))
+ {
+ type = ITABS_BROKEN_END;
+ tab_len = ih->data->tabs_line.broken_space_end;
+ }
+ else if (tab_index == (ih->data->tabs_line.start_tab - 1))
+ {
+ type = ITABS_BROKEN_START;
+ tab_len = ih->data->tabs_line.broken_space_start;
+ }
+ else if (ih->data->tabs_line.broken_center_visible == ITABS_TRUE)
+ {
+ type = ITABS_BROKEN_CENTER;
+ tab_len = ih->data->tabs_line.broken_tab_space;
+ }
+ else
+ {
+ type = ITABS_BROKEN_NONE;
+ tab_len = full_tab_len;
+ }
+
+ if (tab_len > full_tab_len)
+ tab_len = full_tab_len;
+
+ /* If the selected tab is not the first, and this tab is visible,
+ * subtracts one pixel from him and advances the tab on one pixel,
+ * to prevent the side of tab is confused with the border control. */
+ if (ih->data->current_tab != 0 &&
+ ((ih->data->tabs_line.start_tab == 0 && tab_index == 0) ||
+ (ih->data->tabs_line.start_tab > 0 && tab_index == (ih->data->tabs_line.start_tab - 1))))
+ {
+ offset += 1;
+ tab_len--;
+ full_tab_len--;
+ }
+
+ line_thick = ih->data->tabs_line.line_thick;
+
+ if (tab_index != ih->data->current_tab)
+ line_thick -= ITABS_CURRENT_EXTRA_PIXELS;
+
+ if (ih->data->tabs_type == ITABS_LEFT || ih->data->tabs_type == ITABS_RIGHT)
+ {
+ tab_w = line_thick;
+ tab_h = tab_len;
+ }
+ else
+ {
+ tab_w = tab_len;
+ tab_h = line_thick;
+ }
+
+ /* Calculates the border of tabs, text position and the sides will be drawn */
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ x1 = x1a = offset;
+ y1 = ih->data->h - *(ih->data->tabs_line.line_h) - 1;
+ y1a = y1 + extraHeight;
+ x2 = x1;
+ y2 = y1 + tab_h - 1;
+ x3 = x2 + tab_w - 1;
+ y3 = y2;
+ x4 = x3;
+ y4 = y1;
+ x4a = x3;
+ y4a = y1;
+
+ /* defines the order to draw */
+ types[0] = ITABS_LEFT;
+ types[1] = ITABS_TOP;
+ types[2] = ITABS_RIGHT;
+
+ break;
+
+ case ITABS_BOTTOM:
+ x1 = x1a = offset;
+ y1 = *(ih->data->tabs_line.line_h) - 1;
+ y1a = y1 - extraHeight;
+ x2 = x1;
+ y2 = y1 - tab_h + 1;
+ x3 = x2 + tab_w - 1;
+ y3 = y2;
+ x4 = x3;
+ y4 = y1;
+ x4a = x3;
+ y4a = y1;
+
+ types[0] = ITABS_LEFT;
+ types[1] = ITABS_BOTTOM;
+ types[2] = ITABS_RIGHT;
+
+ break;
+
+ case ITABS_LEFT:
+ x1 = *(ih->data->tabs_line.line_w) - 1;
+ x1a = x1 - extraHeight;
+ y1 = y1a = ih->data->h - offset - 1;
+ x2 = x1 - tab_w + 1;
+ y2 = y1;
+ x3 = x2;
+ y3 = y1 - tab_h + 1;
+ x4 = x1;
+ y4 = y3;
+ x4a = x1a;
+ y4a = y3;
+
+ types[0] = ITABS_TOP;
+ types[1] = ITABS_LEFT;
+ types[2] = ITABS_BOTTOM;
+
+ break;
+
+ case ITABS_RIGHT:
+ x1 = ih->data->w - ih->data->tabs_line.line_thick - 1;
+ x1a = x1 + extraHeight;
+ y1 = y1a = ih->data->h - offset - 1;
+ x2 = x1 + tab_w - 1;
+ y2 = y1;
+ x3 = x2;
+ y3 = y1 - tab_h + 1;
+ x4 = x1;
+ y4 = y3;
+ x4a = x1a;
+ y4a = y3;
+
+ types[0] = ITABS_TOP;
+ types[1] = ITABS_RIGHT;
+ types[2] = ITABS_BOTTOM;
+
+ break;
+
+ default:
+ return;
+ }
+
+ if (tab_index == (ih->data->current_tab - 1))
+ {
+ beforeCurrent = ITABS_TRUE;
+ afterCurrent = ITABS_FALSE;
+ }
+ else if (tab_index == (ih->data->current_tab + 1))
+ {
+ beforeCurrent = ITABS_FALSE;
+ afterCurrent = ITABS_TRUE;
+ }
+ else
+ {
+ beforeCurrent = ITABS_FALSE;
+ afterCurrent = ITABS_FALSE;
+ }
+
+ /* Draws the square of tab*/
+ cdCanvasForeground(canvas, ih->data->bgcolor);
+
+ /* Fills the square of tab */
+ iTabsFillArea(canvas, x1, y1, x2, y2, x3, y3, x4, y4);
+
+ /* Draws the border on the top */
+ iTabsDrawBorder(ih, types[1], x2, y2, x3, y3);
+
+ switch(type)
+ {
+ case ITABS_BROKEN_END:
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ cdCanvasClipArea(canvas, x1, x3 - ITABS_BORDER - 1, y1, y3);
+ break;
+ case ITABS_BOTTOM:
+ cdCanvasClipArea(canvas, x2, x4 - ITABS_BORDER - 1, y2, y4);
+ break;
+ case ITABS_LEFT:
+ cdCanvasClipArea(canvas, x3, x1, y3 + ITABS_BORDER + 1, y1);
+ break;
+ case ITABS_RIGHT:
+ cdCanvasClipArea(canvas, x4, x2, y4 + ITABS_BORDER + 1, y2);
+ break;
+ }
+
+ if (beforeCurrent == ITABS_TRUE)
+ iTabsDrawBrokenBorder(ih, types[0], x1a, y1a, x2, y2);
+ else if (afterCurrent == ITABS_TRUE)
+ iTabsDrawBrokenBorder(ih, types[2], x3, y3, x4a, y4a);
+ else
+ {
+ iTabsDrawBorder(ih, types[0], x1a, y1a, x2, y2);
+ iTabsDrawBrokenBorder(ih, types[2], x3, y3, x4a, y4a);
+ }
+
+ if (types[1] == ITABS_TOP)
+ iTabsDrawCorner(ih, ih->data->light_shadow, x1 + ITABS_BORDER - 1, y3 + ITABS_BORDER - 1,
+ x1 + ITABS_BORDER + 1, y3 + ITABS_BORDER - 3);
+
+ if (types[1] == ITABS_BOTTOM)
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x2 + ITABS_BORDER - 1, y2 + ITABS_BORDER - 1,
+ x2 + ITABS_BORDER + 1, y2 + ITABS_BORDER + 1);
+ break;
+
+ case ITABS_BROKEN_START:
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ cdCanvasClipArea(canvas, x1 + ITABS_BORDER + 1, x3, y1, y3);
+ break;
+ case ITABS_BOTTOM:
+ cdCanvasClipArea(canvas, x2 + ITABS_BORDER + 1, x4, y2, y4);
+ break;
+ case ITABS_LEFT:
+ cdCanvasClipArea(canvas, x3, x1, y3, y1 - ITABS_BORDER - 1);
+ break;
+ case ITABS_RIGHT:
+ cdCanvasClipArea(canvas, x4, x2, y4, y2 - ITABS_BORDER - 1);
+ break;
+ }
+
+ if (beforeCurrent == ITABS_TRUE)
+ iTabsDrawBrokenBorder(ih, types[0], x1a, y1a, x2, y2);
+ else if (afterCurrent == ITABS_TRUE)
+ iTabsDrawBrokenBorder(ih, types[2], x3, y3, x4a, y4a);
+ else
+ {
+ iTabsDrawBrokenBorder(ih, types[0], x1a, y1a, x2, y2);
+ iTabsDrawBorder(ih, types[2], x3, y3, x4a, y4a);
+ }
+
+ if (types[1] == ITABS_TOP)
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x3 + ITABS_BORDER - 1, y3 + ITABS_BORDER - 1,
+ x3 + ITABS_BORDER - 3, y3 + ITABS_BORDER - 3);
+
+ if (types[1] == ITABS_BOTTOM)
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x4 + ITABS_BORDER - 1, y2 + ITABS_BORDER - 1,
+ x4 + ITABS_BORDER - 3, y2 + ITABS_BORDER + 1);
+ break;
+
+ case ITABS_BROKEN_CENTER:
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ cdCanvasClipArea (canvas, x1 + ITABS_BORDER + 1, x3 - ITABS_BORDER - 1,
+ y1 + ITABS_BORDER + 1, y3 - ITABS_BORDER - 1);
+ break;
+ case ITABS_BOTTOM:
+ cdCanvasClipArea (canvas, x2 + ITABS_BORDER + 1, x4 - ITABS_BORDER - 1,
+ y2 + ITABS_BORDER + 1, y4 - ITABS_BORDER - 1);
+ break;
+ case ITABS_LEFT:
+ cdCanvasClipArea (canvas, x3 + ITABS_BORDER + 1, x1 - ITABS_BORDER - 1,
+ y3 + ITABS_BORDER + 1, y1 - ITABS_BORDER - 1);
+ break;
+ case ITABS_RIGHT:
+ cdCanvasClipArea (canvas, x4 + ITABS_BORDER + 1, x2 - ITABS_BORDER - 1,
+ y4 + ITABS_BORDER + 1, y2 - ITABS_BORDER - 1);
+ break;
+ }
+
+ iTabsDrawBrokenBorder(ih, types[0], x1, y1, x2, y2);
+ iTabsDrawBrokenBorder(ih, types[2], x3, y3, x4, y4);
+ break;
+
+ case ITABS_BROKEN_NONE:
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ cdCanvasClipArea (canvas, x1 + ITABS_BORDER + 1, x3 - ITABS_BORDER - 1,
+ y1 + ITABS_BORDER + 1, y3 - ITABS_BORDER - 1);
+ break;
+ case ITABS_BOTTOM:
+ cdCanvasClipArea (canvas, x2 + ITABS_BORDER + 1, x4 - ITABS_BORDER - 1,
+ y2 + ITABS_BORDER + 1, y4 - ITABS_BORDER - 1);
+ break;
+ case ITABS_LEFT:
+ cdCanvasClipArea (canvas, x3 + ITABS_BORDER + 1, x1 - ITABS_BORDER - 1,
+ y3 + ITABS_BORDER + 1, y1 - ITABS_BORDER - 1);
+ break;
+ case ITABS_RIGHT:
+ cdCanvasClipArea (canvas, x4 + ITABS_BORDER + 1, x2 - ITABS_BORDER - 1,
+ y4 + ITABS_BORDER + 1, y2 - ITABS_BORDER - 1);
+ break;
+ }
+
+ if (beforeCurrent == ITABS_TRUE)
+ iTabsDrawBorder(ih, types[0], x1a, y1a, x2, y2);
+ else if (afterCurrent == ITABS_TRUE)
+ iTabsDrawBorder(ih, types[2], x3, y3, x4a, y4a);
+ else
+ {
+ iTabsDrawBorder(ih, types[0], x1a, y1a, x2, y2);
+ iTabsDrawBorder(ih, types[2], x3, y3, x4a, y4a);
+ }
+
+ if (types[1] == ITABS_TOP)
+ {
+ iTabsDrawCorner(ih, ih->data->light_shadow, x1 + ITABS_BORDER - 1, y3 + ITABS_BORDER - 1,
+ x1 + ITABS_BORDER + 1, y3 + ITABS_BORDER - 3);
+
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x3 + ITABS_BORDER - 1, y3 + ITABS_BORDER - 1,
+ x3 + ITABS_BORDER - 3, y3 + ITABS_BORDER - 3);
+ }
+
+ if (types[1] == ITABS_BOTTOM)
+ {
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x2 + ITABS_BORDER - 1, y2 + ITABS_BORDER - 1,
+ x2 + ITABS_BORDER + 1, y2 + ITABS_BORDER + 1);
+
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x4 + ITABS_BORDER - 1, y2 + ITABS_BORDER - 1,
+ x4 + ITABS_BORDER - 3, y2 + ITABS_BORDER + 1);
+ }
+
+ if (types[1] == ITABS_LEFT)
+ {
+ iTabsDrawCorner(ih, ih->data->light_shadow, x3 + ITABS_BORDER - 1, y1 + ITABS_BORDER - 1,
+ x3 + ITABS_BORDER + 1, y1 + ITABS_BORDER - 3);
+
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x3 + ITABS_BORDER - 1, y3 + ITABS_BORDER - 1,
+ x3 + ITABS_BORDER + 1, y3 + ITABS_BORDER + 1);
+ }
+
+ if (types[1] == ITABS_RIGHT)
+ {
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x2 + ITABS_BORDER - 1, y2 + ITABS_BORDER - 1,
+ x2 + ITABS_BORDER - 3, y2 + ITABS_BORDER - 3);
+
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x2 + ITABS_BORDER - 1, y4 + ITABS_BORDER - 1,
+ x2 + ITABS_BORDER - 3, y4 + ITABS_BORDER + 1);
+ }
+
+ break;
+ }
+
+ if (ih->data->tabs_type == ITABS_LEFT || ih->data->tabs_type == ITABS_RIGHT)
+ tab_h = full_tab_len;
+ else
+ tab_w = full_tab_len;
+
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ x_text = x1 + tab_w / 2;
+ y_text = y1 + tab_h / 2;
+ break;
+ case ITABS_BOTTOM:
+ x_text = x2 + tab_w / 2;
+ y_text = y2 + tab_h / 2;
+ break;
+ case ITABS_LEFT:
+ x_text = x1 - tab_w / 2;
+ y_text = y1 - tab_h / 2;
+ break;
+ case ITABS_RIGHT:
+ x_text = x2 - tab_w / 2;
+ y_text = y2 - tab_h / 2;
+ break;
+ }
+ cdCanvasTextAlignment (canvas, CD_CENTER);
+
+ /* Draws the text */
+ cdCanvasForeground (canvas, ih->data->fgcolor);
+
+ if (ih->data->tabs_orientation == ITABS_VERTICAL)
+ cdCanvasTextOrientation(canvas, 90);
+ else
+ cdCanvasTextOrientation(canvas, 0);
+
+ {
+ char* tab_font = NULL;
+ int bold = 0;
+
+ if (iupdrvIsActive(ih) && IupGetInt(ih->data->tabs_line.tabs_info[tab_index].ihandle, "ACTIVE"))
+ {
+ if (tab_index == ih->data->current_tab)
+ {
+ tab_font = ih->data->font_active;
+ bold = 1;
+ }
+ }
+ else
+ {
+ cdCanvasForeground(canvas, CD_DARK_GRAY);
+ tab_font = ih->data->font_inactive;
+ }
+
+ iTabsSetCDFont(ih, tab_font, bold);
+ }
+
+ cdCanvasClip(canvas, CD_CLIPAREA);
+
+ {
+ char* text = iupAttribGet(ih->data->tabs_line.tabs_info[tab_index].ihandle, "TABTITLE");
+ if (!text) text = " ";
+
+ if (ih->data->has_focus && (tab_index == ih->data->current_tab))
+ {
+ int x1, y1, x2, y2;
+ cdCanvasGetTextBox(canvas, x_text, y_text, text, &x1, &x2, &y1, &y2);
+ if (ih->data->tabs_orientation == ITABS_VERTICAL)
+ {y1-=2; y2+=2;}
+ else
+ {x1-=2; x2+=2;}
+ ih->data->focus_x1 = x1;
+ ih->data->focus_x2 = x2;
+ ih->data->focus_y1 = y1;
+ ih->data->focus_y2 = y2;
+ }
+
+ cdCanvasText(canvas, x_text, y_text, text);
+ }
+
+ cdCanvasClip (canvas, CD_CLIPOFF);
+}
+
+/* Draws the lower border of the tab labels */
+static void iTabsDrawLabelLowerBorder(Ihandle* ih, int start, int end)
+{
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ iTabsDrawBorder(ih, ITABS_TOP, start, ih->data->h - *(ih->data->tabs_line.line_h) - 1 - 1,
+ end, ih->data->h - *(ih->data->tabs_line.line_h) - 1 - 1);
+ break;
+
+ case ITABS_LEFT:
+ if (!start)
+ iTabsDrawBorder(ih, ITABS_LEFT, *(ih->data->tabs_line.line_w) - 1 + 1, ih->data->h - 1 - start,
+ *(ih->data->tabs_line.line_w) - 1 + 1, ih->data->h - 1 - end);
+ else
+ iTabsDrawBorder(ih, ITABS_LEFT, *(ih->data->tabs_line.line_w) - 1 + 1, ih->data->h - 1 - start,
+ *(ih->data->tabs_line.line_w) - 1 + 1, 0);
+ break;
+
+ case ITABS_BOTTOM:
+ iTabsDrawBorder(ih, ITABS_BOTTOM, start, *(ih->data->tabs_line.line_h) - 1 + 1,
+ end, *(ih->data->tabs_line.line_h) - 1 + 1);
+ break;
+
+ case ITABS_RIGHT:
+ if (!start)
+ iTabsDrawBorder(ih, ITABS_RIGHT, ih->data->w - *(ih->data->tabs_line.line_w) - 1 - 1, ih->data->h - 1 - start,
+ ih->data->w - *(ih->data->tabs_line.line_w) - 1 - 1, ih->data->h - 1 - end);
+ else
+ iTabsDrawBorder(ih, ITABS_RIGHT, ih->data->w - *(ih->data->tabs_line.line_w) - 1 - 1, ih->data->h - 1 - start,
+ ih->data->w - *(ih->data->tabs_line.line_w) - 1 - 1, 0);
+ break;
+ }
+}
+
+/* Draws a normal button */
+static void iTabsDrawButton(Ihandle* ih, int x, int y, int width, int height)
+{
+ cdCanvas* canvas = ih->data->cddbuffer;
+ int old_color = cdCanvasForeground(canvas, ih->data->bgcolor);
+
+ cdCanvasBegin(canvas, CD_FILL);
+ cdCanvasVertex(canvas, x, y);
+ cdCanvasVertex(canvas, x + width - 1, y);
+ cdCanvasVertex(canvas, x + width - 1, y + height - 1);
+ cdCanvasVertex(canvas, x, y + height - 1);
+ cdCanvasEnd(canvas);
+
+ cdCanvasForeground (canvas, old_color);
+
+ iTabsDrawBorder(ih, ITABS_TOP, x + width - 1, y + height - 1, x, y + height - 1);
+ iTabsDrawBorder(ih, ITABS_LEFT, x, y + height - 1, x, y);
+ iTabsDrawBorder(ih, ITABS_BOTTOM, x, y, x + width - 1, y);
+ iTabsDrawBorder(ih, ITABS_RIGHT, x + width - 1, y, x + width - 1, y + height - 1);
+}
+
+/* Draws arrows
+*
+* x, y ..........: lower border of the bounding box
+* width, height .: dimensions of the bounding box
+* type ..........: ITABS_LEFT, ITABS_RIGHT, ITABS_TOP, ITABS_BOTTOM
+*/
+static void iTabsDrawArrow(Ihandle* ih, int x, int y, int width, int height, int type)
+{
+ cdCanvas* canvas = ih->data->cddbuffer;
+ long old_color;
+
+ if (iupdrvIsActive(ih))
+ old_color = cdCanvasForeground(canvas, CD_BLACK);
+ else
+ old_color = cdCanvasForeground(canvas, CD_DARK_GRAY);
+
+ cdCanvasBegin(canvas, CD_CLOSED_LINES);
+ switch(type)
+ {
+ case ITABS_LEFT:
+ cdCanvasVertex(canvas, x + 4, y + height / 2);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + 4);
+ break;
+
+ case ITABS_RIGHT:
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + height / 2);
+ cdCanvasVertex(canvas, x + 4, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + 4, y + 4);
+ break;
+
+ case ITABS_TOP:
+ cdCanvasVertex(canvas, x + 4, y + 4);
+ cdCanvasVertex(canvas, x + width / 2, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + 4);
+ break;
+
+ case ITABS_BOTTOM:
+ cdCanvasVertex(canvas, x + 4, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + width / 2, y + 4);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + height - 1 - 4);
+ break;
+ }
+ cdCanvasEnd(canvas);
+
+ cdCanvasBegin(canvas, CD_FILL);
+ switch(type)
+ {
+ case ITABS_LEFT:
+ cdCanvasVertex(canvas, x + 4, y + height / 2);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + 4);
+ break;
+
+ case ITABS_RIGHT:
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + height / 2);
+ cdCanvasVertex(canvas, x + 4, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + 4, y + 4);
+ break;
+
+ case ITABS_TOP:
+ cdCanvasVertex(canvas, x + 4, y + 4);
+ cdCanvasVertex(canvas, x + width / 2, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + 4);
+ break;
+
+ case ITABS_BOTTOM:
+ cdCanvasVertex(canvas, x + 4, y + height - 1 - 4);
+ cdCanvasVertex(canvas, x + width / 2, y + 4);
+ cdCanvasVertex(canvas, x + width - 1 - 4, y + height - 1 - 4);
+ break;
+ }
+ cdCanvasEnd(canvas);
+
+ cdCanvasForeground(canvas, old_color);
+}
+
+/* Draws dots "..." */
+static void iTabsDrawDots(Ihandle* ih, int x, int y, int width, int height)
+{
+ x -= 1;
+ y += height / 3 - 1;
+ cdCanvasRect(ih->data->cddbuffer, x + 3, x + 4, y + 3, y + 4);
+ cdCanvasRect(ih->data->cddbuffer, x + width / 2, x+ width / 2 + 1 , y + 3, y + 4);
+ cdCanvasRect(ih->data->cddbuffer, x + width - 1 - 3, x + width - 1 - 2, y + 3, y + 4);
+}
+
+/* Draws the scroll_visible with the dots button "..." */
+static void iTabsDrawScroll(Ihandle* ih)
+{
+ int x = ih->data->tabs_line.scroll_x,
+ y = ih->data->tabs_line.scroll_y,
+ w = ih->data->tabs_line.scroll_w,
+ h = ih->data->tabs_line.scroll_h;
+ int scroll_updown;
+
+ if (ih->data->tabs_type == ITABS_TOP ||
+ ih->data->tabs_type == ITABS_BOTTOM)
+ scroll_updown = 0;
+ else
+ scroll_updown = 1;
+
+ if (ih->data->tabs_orientation == ITABS_HORIZONTAL)
+ {
+ int x3 = w / 3;
+
+ iTabsDrawButton(ih, x, y, x3, h);
+ iTabsDrawArrow (ih, x, y, x3, h, scroll_updown ? ITABS_TOP : ITABS_LEFT);
+
+ iTabsDrawButton(ih, x + x3, y, x3, h);
+ iTabsDrawDots (ih, x + x3, y, x3, h);
+
+ iTabsDrawButton(ih, x + 2 * x3, y, x3, h );
+ iTabsDrawArrow (ih, x + 2 * x3, y, x3, h, scroll_updown ? ITABS_BOTTOM : ITABS_RIGHT);
+ }
+ else
+ {
+ int y3 = h / 3;
+
+ iTabsDrawButton(ih, x, y, w, y3);
+ iTabsDrawArrow (ih, x, y, w, y3, scroll_updown ? ITABS_BOTTOM : ITABS_RIGHT);
+
+ iTabsDrawButton(ih, x, y + y3, w, y3);
+ iTabsDrawDots (ih, x, y + y3, w, y3);
+
+ iTabsDrawButton(ih, x, y + 2 * y3, w, y3);
+ iTabsDrawArrow (ih, x, y + 2 * y3, w, y3, scroll_updown ? ITABS_TOP : ITABS_LEFT);
+ }
+
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x + w - 1, y + h - 1, x + w - 3, y + h - 3);
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x + w - 1, y, x + w - 3, y + 2);
+ iTabsDrawCorner(ih, ih->data->light_shadow, x, y + h - 1, x + 2, y + h - 3);
+ iTabsDrawCorner(ih, ih->data->dark_shadow, x, y, x + 2, y + 2);
+}
+
+/* Clear tab background */
+static void iTabsDrawBackground(Ihandle* ih)
+{
+ int x1, y1, x2, y2, x3, y3, x4, y4;
+ cdCanvas* canvas = ih->data->cddbuffer;
+
+ cdCanvasBackground(canvas, cdIupConvertColor(iupControlBaseGetParentBgColor(ih)));
+ cdCanvasClear(canvas);
+
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ x1 = 0;
+ y1 = ih->data->h - *(ih->data->tabs_line.line_h) - 1 - 1;
+ x2 = x1;
+ y2 = 0;
+ x3 = ih->data->w - 1;
+ y3 = y2;
+ x4 = x3;
+ y4 = y1;
+ break;
+
+ case ITABS_BOTTOM:
+ x1 = 0;
+ y1 = *(ih->data->tabs_line.line_h) - 1 + 1;
+ x2 = x1;
+ y2 = ih->data->h - 1;
+ x3 = ih->data->w - 1;
+ y3 = y2;
+ x4 = x3;
+ y4 = y1;
+ break;
+
+ case ITABS_LEFT:
+ x1 = *(ih->data->tabs_line.line_w) - 1 + 1;
+ y1 = ih->data->h - 1;
+ x2 = ih->data->w - 1;
+ y2 = y1;
+ x3 = x2;
+ y3 = 0;
+ x4 = x1;
+ y4 = y3;
+ break;
+
+ case ITABS_RIGHT:
+ x1 = ih->data->w - *(ih->data->tabs_line.line_w) - 1 - 1;
+ y1 = ih->data->h - 1;
+ x2 = 0;
+ y2 = y1;
+ x3 = x2;
+ y3 = 0;
+ x4 = x1;
+ y4 = y3;
+ break;
+
+ default:
+ return;
+ }
+
+ /* Foreground color */
+ cdCanvasForeground(canvas, ih->data->bgcolor);
+
+ cdCanvasBegin(canvas, CD_FILL);
+ cdCanvasVertex(canvas, x1, y1);
+ cdCanvasVertex(canvas, x2, y2);
+ cdCanvasVertex(canvas, x3, y3);
+ cdCanvasVertex(canvas, x4, y4);
+ cdCanvasEnd(canvas);
+
+ cdCanvasBegin(canvas, CD_CLOSED_LINES);
+ cdCanvasVertex(canvas, x1, y1);
+ cdCanvasVertex(canvas, x2, y2);
+ cdCanvasVertex(canvas, x3, y3);
+ cdCanvasVertex(canvas, x4, y4);
+ cdCanvasEnd(canvas);
+}
+
+/* Draws tab borders */
+static void iTabsDrawTabsBorders(Ihandle* ih)
+{
+ int x1, y1, x2, y2, x3, y3, x4, y4;
+ ItabsType types[3];
+
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ x1 = 0;
+ y1 = ih->data->h - *(ih->data->tabs_line.line_h) - 1 - 1;
+ x2 = x1;
+ y2 = 0;
+ x3 = ih->data->w - 1;
+ y3 = y2;
+ x4 = x3;
+ y4 = y1;
+
+ /* defines the order to draw */
+ types[0] = ITABS_LEFT;
+ types[1] = ITABS_BOTTOM;
+ types[2] = ITABS_RIGHT;
+ break;
+
+ case ITABS_BOTTOM:
+ x1 = 0;
+ y1 = *(ih->data->tabs_line.line_h) - 1 + 1;
+ x2 = x1;
+ y2 = ih->data->h - 1;
+ x3 = ih->data->w - 1;
+ y3 = y2;
+ x4 = x3;
+ y4 = y1;
+
+ /* defines the order to draw */
+ types[0] = ITABS_LEFT;
+ types[1] = ITABS_TOP;
+ types[2] = ITABS_RIGHT;
+ break;
+
+ case ITABS_LEFT:
+ x1 = *(ih->data->tabs_line.line_w) - 1 + 1;
+ y1 = ih->data->h - 1;
+ x2 = ih->data->w - 1;
+ y2 = y1;
+ x3 = x2;
+ y3 = 0;
+ x4 = x1;
+ y4 = y3;
+
+ /* defines the order to draw */
+ types[0] = ITABS_TOP;
+ types[1] = ITABS_RIGHT;
+ types[2] = ITABS_BOTTOM;
+ break;
+
+ case ITABS_RIGHT:
+ x1 = ih->data->w - *(ih->data->tabs_line.line_w) - 1 - 1;
+ y1 = ih->data->h - 1;
+ x2 = 0;
+ y2 = y1;
+ x3 = x2;
+ y3 = 0;
+ x4 = x1;
+ y4 = y3;
+
+ /* defines the order to draw */
+ types[0] = ITABS_TOP;
+ types[1] = ITABS_LEFT;
+ types[2] = ITABS_BOTTOM;
+ break;
+
+ default:
+ return;
+ }
+
+ iTabsDrawBorder(ih, types[0], x1, y1, x2, y2);
+ iTabsDrawBorder(ih, types[1], x2, y2, x3, y3);
+ iTabsDrawBorder(ih, types[2], x3, y3, x4, y4);
+}
+
+/* Draws all the tabs and the scroll_visible, if it exists */
+static void iTabsDrawLineOfTabs(Ihandle* ih)
+{
+ int offset = 0;
+ int c = 0;
+
+ /* draws decorations, when necessary */
+ if (ih->data->tabs_line.broken_start_visible == ITABS_TRUE)
+ {
+ iTabsDrawTab(ih, ih->data->tabs_line.start_tab - 1, offset);
+ offset += ih->data->tabs_line.broken_space_start;
+ }
+
+ if (ih->data->tabs_line.broken_center_visible == ITABS_FALSE)
+ {
+ for(c = ih->data->tabs_line.start_tab; c <= ih->data->tabs_line.end_tab; c++)
+ {
+ if (c != ih->data->current_tab)
+ {
+ iTabsDrawTab(ih, c, offset);
+ offset += ih->data->tabs_line.tabs_info[c].tab_len;
+ }
+ else
+ {
+ if (ih->data->current_tab != 0)
+ iTabsDrawLabelLowerBorder(ih, 0, offset);
+
+ iTabsDrawTab(ih, c, offset);
+ offset += ih->data->tabs_line.tabs_info[c].tab_len;
+ iTabsDrawLabelLowerBorder(ih, offset - 1, ih->data->w);
+ }
+ }
+ }
+ else
+ {
+ if (ih->data->current_tab != 0)
+ iTabsDrawLabelLowerBorder(ih, 0, offset);
+
+ iTabsDrawTab(ih, ih->data->current_tab, offset);
+ offset += ih->data->tabs_line.broken_tab_space;
+ iTabsDrawLabelLowerBorder(ih, offset, ih->data->w);
+ }
+
+ if (ih->data->tabs_line.broken_end_visible)
+ {
+ iTabsDrawTab(ih, ih->data->tabs_line.end_tab + 1, offset);
+ offset += ih->data->tabs_line.broken_space_end;
+ }
+
+ if (ih->data->tabs_line.scroll_visible == ITABS_TRUE)
+ iTabsDrawScroll(ih);
+}
+
+/* Calls the user callback to change of tab */
+static int iTabsCallTabChangeCb(Ihandle* ih, Ihandle* new_tab, Ihandle* old_tab)
+{
+ IFnnn cb = NULL;
+
+ if (!IupGetInt(new_tab, "ACTIVE"))
+ return IUP_IGNORE;
+
+ cb = (IFnnn)IupGetCallback(ih, "TABCHANGE_CB");
+ if (!cb)
+ return IUP_DEFAULT;
+
+ return cb(ih, new_tab, old_tab);
+}
+
+/* ========================================================================= */
+/* Functions to calculate the tab sizes and the tab visibilities */
+/* ========================================================================= */
+
+/* Calculates the box size that involves the text of the tabs */
+static void iTabsCalcTextSize(Ihandle* ih)
+{
+ char* title;
+ int t, text_w, size, tabsize;
+ int text_width, text_height;
+
+ iupdrvFontGetCharSize(ih, NULL, &text_height);
+ ih->data->tabs_line.text_h = text_height;
+
+ /* Get the global size of tab */
+ size = iupAttribGetInt(ih, "TABSIZE");
+
+ for(t = 0; t < ih->data->number_of_tabs; t++)
+ {
+ Ihandle* tab_child = ih->data->tabs_line.tabs_info[t].ihandle;
+
+ title = iupAttribGet(tab_child, "TABTITLE");
+ if (!title) title = " ";
+
+ /* Get the size of an specific tab */
+ tabsize = iupAttribGetInt(tab_child, "TABSIZE");
+ text_width = iupdrvFontGetStringWidth(ih, title);
+
+ /* Uses the specific size if the value is larger than the minimum size */
+ if (tabsize > text_width)
+ text_w = tabsize;
+ else
+ {
+ /* Else, uses the tab size if the value is larger than the minimum size */
+ if (size > text_width)
+ text_w = size;
+ else /* otherwise, uses the minimum size */
+ text_w = text_width;
+ }
+
+ ih->data->tabs_line.tabs_info[t].text_w = text_w;
+ }
+}
+
+static void iTabsCalcTabSize(Ihandle* ih)
+{
+ int t, tab_len, tab_thick;
+
+ iTabsCalcTextSize(ih);
+
+ ih->data->tabs_line.line_thick = 0;
+ ih->data->tabs_line.line_length = 0;
+
+ for(t = 0; t < ih->data->number_of_tabs; t++)
+ {
+ /* initialize with the text size */
+ if (ih->data->tabs_render == ITABS_RENDER_PLANE_ALIGN)
+ {
+ tab_len = ih->data->tabs_line.tabs_info[t].text_w;
+ tab_thick = ih->data->tabs_line.text_h;
+ }
+ else
+ {
+ tab_len = ih->data->tabs_line.text_h;
+ tab_thick = ih->data->tabs_line.tabs_info[t].text_w;
+ }
+
+ /* add the borders */
+ if (abs(ih->data->current_tab - t) == 1) /* if neighbor of the current tab */
+ tab_len += ITABS_BORDER;
+ else if (t == ih->data->current_tab) /* if tab is the current tab */
+ {
+ if (ih->data->current_tab == 0 || ih->data->current_tab == (ih->data->number_of_tabs - 1))
+ tab_len += 2 * ITABS_BORDER;
+ else
+ tab_len += 3 * ITABS_BORDER;
+ }
+ else
+ tab_len += 2 * ITABS_BORDER;
+
+ /* add margins */
+ if (ih->data->tabs_render == ITABS_RENDER_PLANE_ALIGN)
+ tab_len += 2 * ITABS_MARGIN;
+ else
+ tab_len += 2 * ITABS_SPACING;
+
+ ih->data->tabs_line.tabs_info[t].tab_len = tab_len;
+
+ ih->data->tabs_line.line_length += tab_len; /* is always the sum on the lengths */
+
+ if (tab_thick > ih->data->tabs_line.line_thick) /* is always the maximum thickness */
+ ih->data->tabs_line.line_thick = tab_thick;
+ }
+
+ if (ih->data->tabs_render == ITABS_RENDER_PLANE_ALIGN)
+ ih->data->tabs_line.line_thick += 2 * ITABS_SPACING + 2 * ITABS_BORDER;
+ else
+ ih->data->tabs_line.line_thick += 2 * ITABS_MARGIN + 2 * ITABS_BORDER;
+
+ if (ih->data->tabs_line.line_thick < ih->data->tabs_line.scroll_thick)
+ ih->data->tabs_line.line_thick = ih->data->tabs_line.scroll_thick;
+
+ /* extra pixels of the selected tab */
+ ih->data->tabs_line.line_thick += ITABS_CURRENT_EXTRA_PIXELS;
+}
+
+static void iTabsCalcScrollPos(Ihandle* ih)
+{
+ int x1=0, y1=0, x2=0, y2=0;
+
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ ih->data->tabs_line.scroll_x = ih->data->w - ih->data->tabs_line.scroll_w - 2;
+ ih->data->tabs_line.scroll_y = ih->data->h - *(ih->data->tabs_line.line_h);
+ y1=0; y2=*(ih->data->tabs_line.line_h);
+ x1=0; x2=ih->data->w-1;
+ break;
+ case ITABS_BOTTOM:
+ ih->data->tabs_line.scroll_x = ih->data->w - ih->data->tabs_line.scroll_w - 2;
+ ih->data->tabs_line.scroll_y = *(ih->data->tabs_line.line_h) - 2 - ih->data->tabs_line.scroll_h + 1;
+ y1=ih->data->h - *(ih->data->tabs_line.line_h); y2=ih->data->h-1;
+ x1=0; x2=ih->data->w-1;
+ break;
+ case ITABS_LEFT:
+ ih->data->tabs_line.scroll_x = *(ih->data->tabs_line.line_w) - 2 - ih->data->tabs_line.scroll_w + 1;
+ ih->data->tabs_line.scroll_y = 0;
+ x1=0; x2=*(ih->data->tabs_line.line_w);
+ y1=0; y2=ih->data->h-1;
+ break;
+ case ITABS_RIGHT:
+ ih->data->tabs_line.scroll_x = ih->data->w - *(ih->data->tabs_line.line_w);
+ ih->data->tabs_line.scroll_y = 0;
+ x1=ih->data->w-*(ih->data->tabs_line.line_w); x2=ih->data->w-1;
+ y1=0; y2=ih->data->h-1;
+ break;
+ }
+
+ iupAttribSetStrf(ih, "TIPRECT", "%d %d %d %d", x1, y1, x2, y2);
+}
+
+/* Calculates the visibility of tabs */
+static void iTabsCalcVisibleTabs(Ihandle* ih)
+{
+ int line_length = *ih->data->max_line_length;
+ int old_line_length;
+ int t, t_aux = 0;
+
+ /* Verifies if all the tabs are visible */
+ if (*ih->data->max_line_length > ih->data->tabs_line.line_length)
+ {
+ /* All the tabs are visible */
+ ih->data->tabs_line.scroll_visible = ITABS_FALSE;
+ ih->data->tabs_line.broken_start_visible = ITABS_FALSE;
+ ih->data->tabs_line.broken_end_visible = ITABS_FALSE;
+ ih->data->tabs_line.broken_center_visible = ITABS_FALSE;
+
+ ih->data->tabs_line.start_tab = 0;
+ ih->data->tabs_line.end_tab = ih->data->number_of_tabs - 1;
+
+ return;
+ }
+
+ /* Subtracts space of scroll */
+ line_length -= ih->data->tabs_line.scroll_len + ITABS_SCROLL_SPACING;
+
+ ih->data->tabs_line.scroll_visible = ITABS_TRUE;
+
+ /* Verifies if current tab is smaller than start tab, adjusting if necessary */
+ if (ih->data->current_tab < ih->data->tabs_line.start_tab)
+ ih->data->tabs_line.start_tab = ih->data->current_tab;
+
+ /* Processes tabs in sequence, until the total length overcome the virtual length */
+ t = ih->data->tabs_line.start_tab;
+ old_line_length = line_length;
+
+ while(1)
+ {
+ do
+ {
+ while (ih->data->tabs_line.start_tab < ih->data->current_tab)
+ {
+ if (ih->data->tabs_line.tabs_info[ih->data->tabs_line.start_tab].tab_len <= line_length)
+ break;
+ ih->data->tabs_line.start_tab++;
+ }
+
+ for(t = ih->data->tabs_line.start_tab, t_aux = 0;
+ t < ih->data->number_of_tabs; t++, t_aux++)
+ {
+ if (ih->data->tabs_line.tabs_info[t].tab_len > line_length)
+ {
+ if ((t - 1) < ih->data->current_tab)
+ {
+ while (t_aux > 0)
+ {
+ line_length +=
+ ih->data->tabs_line.tabs_info[t - t_aux].tab_len;
+
+ if (ih->data->tabs_line.start_tab == 0)
+ {
+ line_length -= ITABS_BROKEN_TAB;
+ ih->data->tabs_line.broken_start_visible = ITABS_TRUE;
+ }
+
+ ih->data->tabs_line.start_tab++;
+
+ if (ih->data->tabs_line.tabs_info[t].tab_len <= line_length)
+ break;
+
+ t_aux--;
+ }
+
+ if (ih->data->tabs_line.tabs_info[t].tab_len > line_length)
+ {
+ /* no success */
+ ih->data->tabs_line.broken_center_visible = ITABS_TRUE;
+ break; /* break two loops */
+ }
+ }
+ else
+ {
+ t--;
+ break; /* break two loops */
+ }
+ }
+
+ line_length -= ih->data->tabs_line.tabs_info[t].tab_len;
+ ih->data->tabs_line.broken_center_visible = ITABS_FALSE;
+ }
+
+ if (t == ih->data->number_of_tabs)
+ t--;
+ }
+ while (t < ih->data->current_tab);
+
+ if (ih->data->tabs_line.start_tab > 0 &&
+ ih->data->tabs_line.broken_center_visible != ITABS_TRUE)
+ {
+ if (ih->data->tabs_line.tabs_info[ih->data->tabs_line.start_tab - 1].tab_len <
+ (line_length - ITABS_BROKEN_TAB))
+ {
+ ih->data->tabs_line.start_tab--;
+ line_length = old_line_length;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ if (ih->data->tabs_line.start_tab > 0)
+ {
+ t = ih->data->tabs_line.start_tab;
+ line_length = old_line_length;
+ line_length -= ITABS_BROKEN_TAB;
+ ih->data->tabs_line.broken_start_visible = ITABS_TRUE;
+
+ while(1)
+ {
+ do
+ {
+ while (ih->data->tabs_line.start_tab < ih->data->current_tab)
+ {
+ if (ih->data->tabs_line.tabs_info[ih->data->tabs_line.start_tab].tab_len <= line_length)
+ break;
+ ih->data->tabs_line.start_tab++;
+ }
+
+ for(t = ih->data->tabs_line.start_tab, t_aux = 0;
+ t < ih->data->number_of_tabs; t++, t_aux++)
+ {
+ if (ih->data->tabs_line.tabs_info[t].tab_len > line_length)
+ {
+ if ((t - 1) < ih->data->current_tab)
+ {
+ while (t_aux > 0)
+ {
+ line_length +=
+ ih->data->tabs_line.tabs_info[t - t_aux].tab_len;
+
+ if (ih->data->tabs_line.start_tab == 0)
+ {
+ line_length -= ITABS_BROKEN_TAB;
+ ih->data->tabs_line.broken_start_visible = ITABS_TRUE;
+ }
+
+ ih->data->tabs_line.start_tab++;
+
+ if (ih->data->tabs_line.tabs_info[t].tab_len <= line_length)
+ break;
+
+ t_aux--;
+ }
+
+ if (ih->data->tabs_line.tabs_info[t].tab_len > line_length)
+ {
+ /* no success */
+ ih->data->tabs_line.broken_center_visible = ITABS_TRUE;
+ break; /* break two loops */
+ }
+ }
+ else
+ {
+ t--;
+ break; /* break two loops */
+ }
+ }
+
+ line_length -= ih->data->tabs_line.tabs_info[t].tab_len;
+ ih->data->tabs_line.broken_center_visible = ITABS_FALSE;
+ }
+
+ if (t == ih->data->number_of_tabs)
+ t--;
+ }
+ while (t < ih->data->current_tab);
+
+ if (ih->data->tabs_line.start_tab > 0 &&
+ ih->data->tabs_line.broken_center_visible != ITABS_TRUE)
+ {
+ if (ih->data->tabs_line.tabs_info[ih->data->tabs_line.start_tab - 1].tab_len <
+ (line_length - ITABS_BROKEN_TAB))
+ {
+ ih->data->tabs_line.start_tab--;
+ line_length = old_line_length;
+ continue;
+ }
+ }
+
+ break;
+ }
+ }
+ else
+ ih->data->tabs_line.broken_start_visible = ITABS_FALSE;
+
+ /* space not occupied by tabs is destined for the broken tabs */
+ ih->data->tabs_line.broken_tab_space = line_length;
+
+ if (ih->data->tabs_line.broken_start_visible == ITABS_TRUE)
+ ih->data->tabs_line.broken_tab_space += ITABS_BROKEN_TAB;
+
+ if (ih->data->tabs_line.broken_center_visible == ITABS_TRUE &&
+ ih->data->tabs_line.start_tab == t)
+ {
+ /* If there is one visible tab and more tabs to the right,
+ it must be clipped */
+ ih->data->tabs_line.end_tab = ih->data->tabs_line.start_tab;
+ ih->data->tabs_line.broken_end_visible = ITABS_FALSE;
+ ih->data->tabs_line.broken_start_visible = ITABS_FALSE;
+ }
+ else
+ {
+ ih->data->tabs_line.end_tab = t;
+ ih->data->tabs_line.broken_center_visible = ITABS_FALSE;
+
+ /* If the last tab is not visible, it must be included the
+ right broken tab, and delete one of tabs, when necessary */
+ if (ih->data->tabs_line.end_tab < (ih->data->number_of_tabs - 1))
+ {
+ ih->data->tabs_line.broken_end_visible = ITABS_TRUE;
+
+ if (line_length < ITABS_BROKEN_TAB)
+ {
+ if (ih->data->tabs_line.start_tab == ih->data->tabs_line.end_tab)
+ {
+ /* no space to broken tabs */
+ ih->data->tabs_line.broken_center_visible = ITABS_TRUE;
+ ih->data->tabs_line.broken_end_visible = ITABS_FALSE;
+ ih->data->tabs_line.broken_start_visible = ITABS_FALSE;
+
+ ih->data->tabs_line.broken_tab_space +=
+ ih->data->tabs_line.tabs_info[ih->data->tabs_line.start_tab].tab_len;
+ }
+ else if (ih->data->current_tab == ih->data->tabs_line.end_tab)
+ {
+ ih->data->tabs_line.broken_tab_space +=
+ ih->data->tabs_line.tabs_info[ih->data->tabs_line.start_tab].tab_len;
+ ih->data->tabs_line.start_tab++;
+ ih->data->tabs_line.broken_start_visible = ITABS_TRUE;
+ }
+ else
+ {
+ ih->data->tabs_line.broken_tab_space +=
+ ih->data->tabs_line.tabs_info[ih->data->tabs_line.end_tab].tab_len;
+ ih->data->tabs_line.end_tab--;
+ }
+ }
+ }
+ else
+ ih->data->tabs_line.broken_end_visible = ITABS_FALSE;
+ }
+
+ if (ih->data->tabs_line.broken_start_visible == ITABS_TRUE &&
+ ih->data->tabs_line.broken_end_visible == ITABS_TRUE)
+ {
+ ih->data->tabs_line.broken_space_start = (int)
+ ceil((double) ih->data->tabs_line.broken_tab_space / 2);
+ ih->data->tabs_line.broken_space_end = (int)
+ floor((double) ih->data->tabs_line.broken_tab_space / 2);
+ }
+ else if (ih->data->tabs_line.broken_start_visible == ITABS_TRUE)
+ {
+ ih->data->tabs_line.broken_space_start = ih->data->tabs_line.broken_tab_space;
+ ih->data->tabs_line.broken_space_end = 0;
+ }
+ else if (ih->data->tabs_line.broken_end_visible == ITABS_TRUE)
+ {
+ ih->data->tabs_line.broken_space_end = ih->data->tabs_line.broken_tab_space;
+ ih->data->tabs_line.broken_space_start = 0;
+ }
+ else
+ {
+ ih->data->tabs_line.broken_space_end = 0;
+ ih->data->tabs_line.broken_space_start = 0;
+ }
+
+ if (ih->data->tabs_line.start_tab == 0)
+ ih->data->tabs_line.broken_start_visible = ITABS_FALSE;
+}
+
+static void iTabsGetDecorOffset(Ihandle* ih, int *x, int *y)
+{
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ *x = ITABS_MARGIN;
+ *y = *(ih->data->tabs_line.line_h) + ITABS_MARGIN;
+ break;
+
+ case ITABS_LEFT:
+ *x = *(ih->data->tabs_line.line_w) + ITABS_MARGIN;
+ *y = ITABS_MARGIN;
+ break;
+
+ case ITABS_RIGHT:
+ case ITABS_BOTTOM:
+ default:
+ *x = ITABS_MARGIN;
+ *y = ITABS_MARGIN;
+ break;
+ }
+}
+
+static void iTabsGetDecorSize(Ihandle* ih, int *w, int *h)
+{
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ *w = 2 * ITABS_MARGIN;
+ *h = *(ih->data->tabs_line.line_h) + 2 * ITABS_MARGIN;
+ break;
+
+ case ITABS_BOTTOM:
+ *w = 2 * ITABS_MARGIN;
+ *h = *(ih->data->tabs_line.line_h) + 2 * ITABS_MARGIN;
+ break;
+
+ case ITABS_LEFT:
+ *w = *(ih->data->tabs_line.line_w) + 2 * ITABS_MARGIN;
+ *h = 2 * ITABS_MARGIN;
+ break;
+
+ case ITABS_RIGHT:
+ *w = *(ih->data->tabs_line.line_w) + 2 * ITABS_MARGIN;
+ *h = 2 * ITABS_MARGIN;
+ break;
+ }
+}
+
+/* Changes the zbox value and redraws the tabs */
+static void iTabsSetNewCurrentTab(Ihandle* ih, int tab)
+{
+ char* next_tab_name = IupGetName(iTabsGetTabIhandle(ih, tab));
+ if (next_tab_name == NULL)
+ return;
+
+ ih->data->current_tab = tab;
+ IupSetAttribute(ih->data->zbox, "VALUE", next_tab_name);
+
+ iTabsCalcVisibleTabs(ih); /* calculates the visibility of tabs (depends on the sizes calculated and on the current tab) */
+
+ IupUpdate(ih);
+}
+
+
+/* ========================================================================= */
+/* IupCanvas Callbacks */
+/* ========================================================================= */
+
+
+static int iTabsFocus_CB(Ihandle* ih, int focus)
+{
+ ih->data->has_focus = focus;
+ IupUpdate(ih);
+ return IUP_DEFAULT;
+}
+
+static int iTabsResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ iTabsCalcTabSize(ih); /* calculates sizes of Tab line (depends on the TABTITLE of all children and on FONT) */
+ iTabsCalcScrollPos(ih); /* calculates the position of the scroll (depends on the sizes calculated) */
+ iTabsCalcVisibleTabs(ih); /* calculates the visibility of tabs (depends on the sizes calculated and on the current tab) */
+
+ return IUP_DEFAULT;
+}
+
+static int iTabsRedraw_CB(Ihandle* ih)
+{
+ char* clip_rect;
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* Paints the background and draws the border */
+ iTabsDrawBackground(ih);
+ iTabsDrawTabsBorders(ih);
+
+ /* Draws tabs and decorations */
+ iTabsDrawLineOfTabs(ih);
+
+ clip_rect = iupAttribGet(ih, "CLIPRECT");
+ if (clip_rect)
+ {
+ int x1, x2, y1, y2;
+ sscanf(clip_rect, "%d %d %d %d", &x1, &y1, &x2, &y2);
+ y1 = cdIupInvertYAxis(y1, ih->data->h);
+ y2 = cdIupInvertYAxis(y2, ih->data->h);
+ cdCanvasClipArea(ih->data->cdcanvas, x1, x2, y1, y2);
+ cdCanvasClip(ih->data->cdcanvas, CD_CLIPAREA);
+ }
+
+ /* Ends the draw process */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, ih->data->focus_x1, ih->data->focus_y1, ih->data->focus_x2, ih->data->focus_y2);
+
+ if (clip_rect)
+ cdCanvasClip(ih->data->cdcanvas, CD_CLIPOFF);
+
+ return IUP_DEFAULT;
+}
+
+/* Callback to popup menu, with the tabs list */
+static int iTabsMenu_CB(Ihandle* ih)
+{
+ char* number = iupAttribGet(ih, "_IUPTABS_ID");
+ int tab_number = 0;
+ int result;
+
+ sscanf (number, "%d", &tab_number);
+
+ if (ih->data->current_tab != tab_number)
+ {
+ result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, tab_number),
+ iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, tab_number);
+ }
+
+ return IUP_DEFAULT;
+}
+
+/* Creates a menu with all the tab labels */
+static Ihandle* iTabsMakeMenuFromTabs(Ihandle* ih)
+{
+ int c = 0;
+ Ihandle* menu = IupMenu(NULL);
+ Ihandle* item = NULL;
+
+ for(c = 0; c < ih->data->number_of_tabs; c++)
+ {
+ char* title = iupAttribGet(ih->data->tabs_line.tabs_info[c].ihandle, "TABTITLE");
+ if (!title) title = " ";
+
+ item = IupItem(title, NULL);
+ IupSetCallback(item, "ACTION", (Icallback) iTabsMenu_CB);
+
+ iupAttribSetStrf(item, "_IUPTABS_ID", "%4d", c);
+
+ if (c == ih->data->current_tab)
+ IupSetAttribute(item, "VALUE", "ON");
+
+ IupAppend(menu, item);
+ }
+
+ return menu;
+}
+
+static int iTabsGetNextTab(Ihandle* ih)
+{
+ int next_tab;
+
+ if (ih->data->current_tab < (ih->data->number_of_tabs - 1))
+ next_tab = ih->data->current_tab + 1;
+ else
+ next_tab = 0;
+
+ /* find the next active tab */
+ while(next_tab != ih->data->current_tab &&
+ !IupGetInt(iTabsGetTabIhandle(ih, next_tab), "ACTIVE"))
+ {
+ if (next_tab < (ih->data->number_of_tabs - 1))
+ next_tab = next_tab + 1;
+ else
+ next_tab = 0;
+ }
+
+ if (next_tab == ih->data->current_tab)
+ return -1;
+
+ return next_tab;
+}
+
+static int iTabsGetPreviousTab(Ihandle* ih)
+{
+ int previous_tab;
+ if (ih->data->current_tab > 0)
+ previous_tab = ih->data->current_tab - 1;
+ else
+ previous_tab = ih->data->number_of_tabs - 1;
+
+ /* find the previous active tab */
+ while(previous_tab != ih->data->current_tab &&
+ !IupGetInt(iTabsGetTabIhandle(ih, previous_tab), "ACTIVE"))
+ {
+ if (previous_tab > 0)
+ previous_tab = previous_tab - 1;
+ else
+ previous_tab = ih->data->number_of_tabs - 1;
+ }
+
+ if (previous_tab == ih->data->current_tab)
+ return -1;
+
+ return previous_tab;
+}
+
+/* Key press Callback */
+static int iTabsKeyPress_CB(Ihandle* ih, int c, int press)
+{
+ if (press == 0)
+ return IUP_DEFAULT;
+
+ if (((c == K_RIGHT || c == K_sRIGHT) && (ih->data->tabs_type == ITABS_TOP || ih->data->tabs_type == ITABS_BOTTOM)) ||
+ ((c == K_DOWN || c == K_sDOWN) && (ih->data->tabs_type == ITABS_LEFT || ih->data->tabs_type == ITABS_RIGHT)))
+ {
+ int result;
+ int next_tab = iTabsGetNextTab(ih);
+ if (next_tab == -1)
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+
+ result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, next_tab),
+ iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, next_tab);
+
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+ }
+ else if (((c == K_LEFT || c == K_sLEFT) && (ih->data->tabs_type == ITABS_TOP || ih->data->tabs_type == ITABS_BOTTOM)) ||
+ ((c == K_UP || c == K_sUP) && (ih->data->tabs_type == ITABS_LEFT || ih->data->tabs_type == ITABS_RIGHT)))
+ {
+ int result;
+ int previous_tab = iTabsGetPreviousTab(ih);
+ if (previous_tab == -1)
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+
+ result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, previous_tab),
+ iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, previous_tab);
+
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+ }
+
+ return IUP_DEFAULT;
+}
+
+/* Button press Callback of IUP Canvas */
+static int iTabsButton_CB (Ihandle* ih, int b, int press, int mx, int my)
+{
+ static int last_tab_press = -1;
+ int* virtual_width = NULL;
+ int* virtual_height = NULL;
+ int width = 0, height = 0, offset = 0;
+ int* virtual_mx = NULL;
+ int* virtual_my = NULL;
+ int click_x = mx, click_y = ih->data->h-1 - my;
+ int count = 0;
+
+ /* Only events of the left button are handled */
+ if (b != IUP_BUTTON1)
+ return IUP_DEFAULT;
+
+ /* Calculates the bounding box size of the tabs queue */
+ switch(ih->data->tabs_type)
+ {
+ case ITABS_TOP:
+ width = ih->data->w;
+ height = ih->data->tabs_line.line_thick;
+ virtual_width = &width;
+ virtual_height = &height;
+ virtual_mx = &mx;
+ virtual_my = &my;
+ *virtual_my = -(*virtual_my - (ih->data->tabs_line.line_thick - 1));
+ break;
+
+ case ITABS_BOTTOM:
+ width = ih->data->w;
+ height = ih->data->tabs_line.line_thick;
+ virtual_width = &width;
+ virtual_height = &height;
+ virtual_mx = &mx;
+ virtual_my = &my;
+ *virtual_my = *virtual_my - ih->data->h + ih->data->tabs_line.line_thick;
+ break;
+
+ case ITABS_LEFT:
+ width = ih->data->tabs_line.line_thick;
+ height = ih->data->h;
+ virtual_width = &height;
+ virtual_height = &width;
+ virtual_mx = &my;
+ virtual_my = &mx;
+ *virtual_my = -(*virtual_my - (ih->data->tabs_line.line_thick - 1));
+ break;
+
+ case ITABS_RIGHT:
+ width = ih->data->tabs_line.line_thick;
+ height = ih->data->h;
+ virtual_width = &height;
+ virtual_height = &width;
+ virtual_mx = &my;
+ virtual_my = &mx;
+ *virtual_my = *virtual_my - ih->data->w + ih->data->tabs_line.line_thick;
+ break;
+ }
+
+ /* Adjusts the offset when the first tab is not selected */
+ if (ih->data->current_tab != 0)
+ offset = 1;
+
+ /* Checks if the mouse is on the tabs area */
+ if ((*virtual_mx > (*virtual_width - 1)) ||
+ (*virtual_my > (*virtual_height - 1)) ||
+ (*virtual_mx < 0) || (*virtual_my < 0))
+ {
+ /* If a button release or any scroll_visible button are pressed, they'll are released */
+ if (!press && ih->data->tabs_line.button != ITABS_BUTTON_NONE)
+ ih->data->tabs_line.button = ITABS_BUTTON_NONE;
+
+ return IUP_DEFAULT;
+ }
+
+ if (!press && ih->data->tabs_line.button != ITABS_BUTTON_NONE)
+ ih->data->tabs_line.button += 3; /* increment from BUTPRESS_* to BUTRELEASE_* */
+
+ /* If there is a scroll_visible, verifies if the click was on one of buttons */
+ if (ih->data->tabs_line.scroll_visible == ITABS_TRUE)
+ {
+ int scroll_pos, scroll_space;
+
+ if (ih->data->tabs_orientation == ITABS_HORIZONTAL)
+ {
+ scroll_space = ih->data->tabs_line.scroll_w;
+ scroll_pos = click_x - ih->data->tabs_line.scroll_x;
+ }
+ else
+ {
+ scroll_space = ih->data->tabs_line.scroll_h;
+ scroll_pos = click_y - ih->data->tabs_line.scroll_y;
+
+ /* the controls are inverted when text is vertical */
+ scroll_pos = scroll_space - scroll_pos;
+ }
+
+ if (click_y > ih->data->tabs_line.scroll_y && click_x > ih->data->tabs_line.scroll_x &&
+ click_y < ih->data->tabs_line.scroll_y+ih->data->tabs_line.scroll_h && click_x < ih->data->tabs_line.scroll_x+ih->data->tabs_line.scroll_w)
+ {
+ /* Verifies which button was pressed by user */
+ if (scroll_pos > 2 * scroll_space / 3) /* forward button*/
+ {
+ /* If press, to draw it pressed */
+ if (press)
+ {
+ ih->data->tabs_line.button = ITABS_BUTTONPRESS_FORWARD ;
+ }
+ else if (ih->data->tabs_line.button == ITABS_BUTTONRELEASE_FORWARD)
+ /* else, change the tab */
+ {
+ int result;
+ int next_tab = iTabsGetNextTab(ih);
+ if (next_tab == -1)
+ return IUP_DEFAULT;
+
+ result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, next_tab), iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, next_tab);
+ }
+ }
+ else if (scroll_pos > scroll_space / 3) /* menu button*/
+ {
+ /* If press, to draw it pressed */
+ if (press)
+ {
+ ih->data->tabs_line.button = ITABS_BUTTONPRESS_MENU ;
+ }
+ else if (ih->data->tabs_line.button == ITABS_BUTTONRELEASE_MENU)
+ /* else, change the tab */
+ {
+ Ihandle* menu = iTabsMakeMenuFromTabs (ih);
+ IupPopup(menu, IUP_MOUSEPOS, IUP_MOUSEPOS);
+ IupDestroy(menu);
+ }
+ }
+ else /* backward button*/
+ {
+ /* If press, to draw it pressed */
+ if (press)
+ {
+ ih->data->tabs_line.button = ITABS_BUTTONPRESS_BACKWARD ;
+ }
+ else if (ih->data->tabs_line.button == ITABS_BUTTONRELEASE_BACKWARD)
+ /* else, change the tab */
+ {
+ int result;
+ int previous_tab = iTabsGetPreviousTab(ih);
+ if (previous_tab == -1)
+ return IUP_DEFAULT;
+
+ result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, previous_tab),
+ iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, previous_tab);
+ }
+ }
+
+ return IUP_DEFAULT;
+ }
+ }
+
+ /* If there is any scroll_visible button pressed, it will be released */
+ if (!press && ih->data->tabs_line.button != ITABS_BUTTON_NONE)
+ {
+ ih->data->tabs_line.button = ITABS_BUTTON_NONE;
+ IupUpdate(ih);
+ return IUP_DEFAULT;
+ }
+
+ /* Checks when the click was on the left broken tab */
+ if (ih->data->tabs_line.broken_start_visible == ITABS_TRUE)
+ {
+ if (*virtual_mx >= offset &&
+ *virtual_mx <= (offset + ih->data->tabs_line.broken_space_start - 1) &&
+ *virtual_my <= (ih->data->tabs_line.line_thick - ITABS_CURRENT_EXTRA_PIXELS - 1))
+ {
+ if (press)
+ last_tab_press = ih->data->tabs_line.start_tab-1;
+ else if (last_tab_press == ih->data->tabs_line.start_tab-1)
+ {
+ int result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, last_tab_press),
+ iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, last_tab_press);
+ }
+
+ return IUP_DEFAULT;
+ }
+ else
+ offset += ih->data->tabs_line.broken_space_start;
+ }
+
+ /* Checks when the click was on one of tabs */
+ for(count = ih->data->tabs_line.start_tab; count <= ih->data->tabs_line.end_tab; count++)
+ {
+ if (*virtual_mx >= offset &&
+ *virtual_mx <= (offset + ih->data->tabs_line.tabs_info[count].tab_len - 1))
+ {
+ if (count != ih->data->current_tab)
+ {
+ if (*virtual_my <= (ih->data->tabs_line.line_thick - ITABS_CURRENT_EXTRA_PIXELS - 1))
+ {
+ if (press)
+ last_tab_press = count;
+ else if (last_tab_press == count)
+ {
+ int result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, last_tab_press),
+ iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, last_tab_press);
+ }
+
+ return IUP_DEFAULT;
+ }
+ }
+ }
+
+ offset += ih->data->tabs_line.tabs_info[count].tab_len;
+ }
+
+ /* Checks when the click was on the right broken tab */
+ if (ih->data->tabs_line.broken_end_visible == ITABS_TRUE)
+ {
+ if (*virtual_mx >= offset &&
+ *virtual_mx <= (offset + ih->data->tabs_line.broken_space_end - 1) &&
+ *virtual_my <= (ih->data->tabs_line.line_thick - ITABS_CURRENT_EXTRA_PIXELS - 1))
+ {
+ if (press)
+ last_tab_press = ih->data->tabs_line.end_tab + 1;
+ else if (last_tab_press == ih->data->tabs_line.end_tab + 1)
+ {
+ int result = iTabsCallTabChangeCb(ih, iTabsGetTabIhandle(ih, last_tab_press),
+ iTabsGetTabIhandle(ih, ih->data->current_tab));
+ if (result != IUP_IGNORE)
+ iTabsSetNewCurrentTab(ih, last_tab_press);
+ }
+
+ return IUP_DEFAULT;
+ }
+ else
+ offset += ih->data->tabs_line.broken_space_end;
+ }
+
+ return IUP_DEFAULT;
+}
+
+static void iTabsRefreshTabs(Ihandle* ih)
+{
+ int t, old_number_of_tabs = ih->data->number_of_tabs;
+ Ihandle* child, *old_current_tab_handle = NULL;
+
+ if (ih->data->tabs_line.tabs_info)
+ old_current_tab_handle = ih->data->tabs_line.tabs_info[ih->data->current_tab].ihandle;
+
+ ih->data->number_of_tabs = 0;
+ child = ih->data->zbox->firstchild;
+ while(child)
+ {
+ if (IupGetName(child) == NULL)
+ iupAttribSetHandleName(child);
+
+ ih->data->number_of_tabs++;
+ child = child->brother;
+ }
+
+ if (old_number_of_tabs < ih->data->number_of_tabs)
+ ih->data->tabs_line.tabs_info = (ItabsDrawInfo*)realloc(ih->data->tabs_line.tabs_info, ih->data->number_of_tabs * sizeof (ItabsDrawInfo));
+
+ t = 0;
+ child = ih->data->zbox->firstchild;
+ while (child)
+ {
+ ih->data->tabs_line.tabs_info[t].ihandle = child;
+
+ if (child == old_current_tab_handle)
+ ih->data->current_tab = t; /* current tab was moved */
+
+ child = child->brother;
+ t++;
+ }
+
+ if (old_current_tab_handle &&
+ old_current_tab_handle != ih->data->tabs_line.tabs_info[ih->data->current_tab].ihandle)
+ {
+ /* current tab was removed, reset to first child */
+ ih->data->current_tab = 0;
+ }
+}
+
+
+/* ========================================================================= */
+/* Attributes */
+/* ========================================================================= */
+
+
+static int iTabsSetAlignmentAttrib(Ihandle* ih, const char* value)
+{
+ int inherit;
+ return iupClassObjectSetAttribute(ih->data->zbox, "ALIGNMENT", value, &inherit);
+}
+
+static char* iTabsGetAlignmentAttrib(Ihandle* ih)
+{
+ int inherit;
+ char *def_value;
+ return iupClassObjectGetAttribute(ih->data->zbox, "ALIGNMENT", &def_value, &inherit);
+}
+
+static int iTabsSetTabOrientationAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "VERTICAL"))
+ ih->data->tabs_orientation = ITABS_VERTICAL;
+ else
+ ih->data->tabs_orientation = ITABS_HORIZONTAL;
+
+ iTabsUpdateRender(ih);
+
+ return 0; /* do not store value in hash table */
+}
+
+static char* iTabsGetTabOrientationAttrib(Ihandle* ih)
+{
+ if (ih->data->tabs_orientation == ITABS_VERTICAL)
+ return "VERTICAL";
+ else
+ return "HORIZONTAL";
+}
+
+static int iTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "BOTTOM"))
+ ih->data->tabs_type = ITABS_BOTTOM;
+ else if (iupStrEqualNoCase(value, "LEFT"))
+ ih->data->tabs_type = ITABS_LEFT;
+ else if (iupStrEqualNoCase(value, "RIGHT"))
+ ih->data->tabs_type = ITABS_RIGHT;
+ else /* "TOP" */
+ ih->data->tabs_type = ITABS_TOP;
+
+ iTabsUpdateRender(ih);
+
+ return 0; /* do not store value in hash table */
+}
+
+static char* iTabsGetTabTypeAttrib(Ihandle* ih)
+{
+ if (ih->data->tabs_type == ITABS_BOTTOM)
+ return "BOTTOM";
+ else if (ih->data->tabs_type == ITABS_LEFT)
+ return "LEFT";
+ else if (ih->data->tabs_type == ITABS_RIGHT)
+ return "RIGHT";
+ else /* ITABS_TOP */
+ return "TOP";
+}
+
+static int iTabsSetRepaintAttrib(Ihandle* ih, const char* value)
+{
+ (void)value;
+
+ iTabsCalcTabSize(ih); /* calculate sizes of Tab line (depends on the TABTITLE of all children) */
+ iTabsCalcScrollPos(ih); /* calculates the position of the scroll (depends on the sizes calculated) */
+ iTabsCalcVisibleTabs(ih); /* calculates the visibility of tabs (depends on the sizes calculated and on the current tab) */
+
+ IupUpdate(ih);
+
+ return 0; /* do not store value in hash table */
+}
+
+static int iTabsSetFontActiveAttrib(Ihandle* ih, const char* value)
+{
+ char* native = IupMapFont(value);
+ if (!native) native = (char*)value;
+
+ if (native)
+ {
+ if (ih->data->font_active)
+ free(ih->data->font_active);
+
+ ih->data->font_active = iupStrDup(native);
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static int iTabsSetFontInactiveAttrib(Ihandle* ih, const char* value)
+{
+ char* native = IupMapFont(value);
+ if (!native) native = (char*)value;
+
+ if (native)
+ {
+ if (ih->data->font_inactive)
+ free(ih->data->font_inactive);
+
+ ih->data->font_inactive = iupStrDup(native);
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static int iTabsSetFgColorAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->fgcolor = cdIupConvertColor(value);
+ IupUpdate(ih);
+ return 1;
+}
+
+static int iTabsSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = iupControlBaseGetParentBgColor(ih);
+
+ ih->data->bgcolor = cdIupConvertColor(value);
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+
+ IupUpdate(ih);
+ return 1;
+}
+
+static int iTabsSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ iupBaseSetActiveAttrib(ih, value);
+ IupUpdate(ih); /* post repaint so children is activated/deactivated */
+ return 0; /* do not store value in hash table */
+}
+
+static int iTabsSetValueAttrib(Ihandle* ih, const char* value)
+{
+ int c;
+ Ihandle* new_tab = IupGetHandle(value);
+
+ if (new_tab == NULL)
+ return 0;
+
+ for(c = 0; c < ih->data->number_of_tabs; c++)
+ {
+ if (ih->data->tabs_line.tabs_info[c].ihandle == new_tab)
+ {
+ iTabsSetNewCurrentTab(ih, c);
+ break;
+ }
+ }
+ return 0; /* do not store value in hash table */
+}
+
+static char* iTabsGetValueAttrib(Ihandle* ih)
+{
+ return IupGetAttribute(ih->data->zbox, "VALUE");
+}
+
+static int iTabsSetValuePosAttrib(Ihandle* ih, const char* value)
+{
+ int pos;
+
+ if (!iupStrToInt(value, &pos))
+ return 0;
+
+ if (pos<0) pos=0;
+ if (pos>ih->data->number_of_tabs-1) pos=ih->data->number_of_tabs-1;
+
+ iTabsSetNewCurrentTab(ih, pos);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iTabsGetValuePosAttrib(Ihandle* ih)
+{
+ char *str = iupStrGetMemory(50);
+ sprintf(str, "%d", ih->data->current_tab);
+ return str;
+}
+
+static char* iTabsGetClientSizeAttrib(Ihandle* ih)
+{
+ int width, height, decorwidth, decorheight;
+ char* str = iupStrGetMemory(20);
+ width = ih->currentwidth;
+ height = ih->currentheight;
+ iTabsGetDecorSize(ih, &decorwidth, &decorheight);
+ width -= decorwidth;
+ height -= decorheight;
+ if (width < 0) width = 0;
+ if (height < 0) height = 0;
+ sprintf(str, "%dx%d", width, height);
+ return str;
+}
+
+
+/* ========================================================================= */
+/* Methods */
+/* ========================================================================= */
+
+
+static Ihandle* iTabsGetInnerContainerMethod(Ihandle* ih)
+{
+ return ih->data->zbox;
+}
+
+static void iTabsComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+{
+ int decorwidth, decorheight;
+ Ihandle* child = ih->data->zbox; /* zbox is always non NULL */
+
+ iTabsCalcTabSize(ih); /* make sure that decoration is updated, even if UPDATE has not been set after other changes */
+ iTabsGetDecorSize(ih, &decorwidth, &decorheight);
+
+ /* update child natural size first */
+ iupBaseComputeNaturalSize(child);
+
+ *expand = child->expand;
+ *w = child->naturalwidth + decorwidth;
+ *h = child->naturalheight + decorheight;
+}
+
+static void iTabsSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink)
+{
+ int width, height, decorwidth, decorheight;
+
+ iTabsGetDecorSize(ih, &decorwidth, &decorheight);
+
+ width = ih->currentwidth-decorwidth;
+ height = ih->currentheight-decorheight;
+ if (width < 0) width = 0;
+ if (height < 0) height = 0;
+
+ iupBaseSetCurrentSize(ih->data->zbox, width, height, shrink);
+}
+
+static void iTabsSetChildrenPositionMethod(Ihandle* ih, int x, int y)
+{
+ /* IupTabs is the native parent of its children,
+ so the position is restarted at (0,0) */
+ iTabsGetDecorOffset(ih, &x, &y);
+
+ /* Child coordinates are relative to client left-top corner. */
+ iupBaseSetPosition(ih->data->zbox, x, y);
+}
+
+static void iTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+{
+ (void)child;
+ iTabsRefreshTabs(ih); /* update the list of tabs */
+}
+
+static void iTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
+{
+ (void)child;
+ iTabsRefreshTabs(ih); /* update the list of tabs */
+}
+
+static int iTabsMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ return IUP_NOERROR;
+}
+
+static void iTabsUnMapMethod(Ihandle* ih)
+{
+ if (ih->data->cddbuffer)
+ cdKillCanvas(ih->data->cddbuffer);
+
+ if (ih->data->cdcanvas)
+ cdKillCanvas(ih->data->cdcanvas);
+}
+
+static void iTabsDestroyMethod(Ihandle* ih)
+{
+ if (ih->data->font_inactive)
+ free(ih->data->font_inactive);
+
+ if (ih->data->font_inactive)
+ free(ih->data->font_inactive);
+
+ free(ih->data->tabs_line.tabs_info);
+}
+
+static int iTabsCreateMethod(Ihandle* ih, void **params)
+{
+ /* free the data allocated by IupCanvas */
+ if (ih->data)
+ free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "BORDER", "NO");
+
+ ih->data->zbox = IupZbox(NULL);
+ ih->firstchild = ih->data->zbox; /* zbox is actually the only child of Tabs */
+ ih->data->zbox->parent = ih;
+
+ /* add children */
+ if (params)
+ {
+ Ihandle** iparams = (Ihandle**)params;
+ while (*iparams)
+ {
+ IupAppend(ih, *iparams); /* this in fact will add the child to the zbox */
+ iparams++;
+ }
+ }
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iTabsResize_CB);
+ IupSetCallback(ih, "ACTION", (Icallback)iTabsRedraw_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iTabsButton_CB);
+ IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iTabsKeyPress_CB);
+ IupSetCallback(ih, "FOCUS_CB", (Icallback)iTabsFocus_CB);
+
+ /* initialize colors */
+ ih->data->bgcolor = -1;
+ ih->data->fgcolor = CD_BLACK;
+ ih->data->light_shadow = CD_WHITE;
+ ih->data->mid_shadow = CD_GRAY;
+ ih->data->dark_shadow = CD_DARK_GRAY;
+
+ /* Context initialize with values related to type of tabs */
+ ih->data->tabs_type = ITABS_TOP;
+ ih->data->tabs_orientation = ITABS_HORIZONTAL;
+
+ /* No button is pressed */
+ ih->data->tabs_line.button = ITABS_BUTTON_NONE ;
+
+ iTabsUpdateRender(ih);
+
+ return IUP_NOERROR;
+}
+
+static Iclass* iTabsGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "tabs";
+ ic->format = "g"; /* array of Ihandle */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILD_ONE;
+ ic->is_interactive = 1;
+
+ /* Class functions */
+ ic->Create = iTabsCreateMethod;
+ ic->Destroy = iTabsDestroyMethod;
+ ic->Map = iTabsMapMethod;
+ ic->UnMap = iTabsUnMapMethod;
+
+ ic->ComputeNaturalSize = iTabsComputeNaturalSizeMethod;
+ ic->SetChildrenCurrentSize = iTabsSetChildrenCurrentSizeMethod;
+ ic->SetChildrenPosition = iTabsSetChildrenPositionMethod;
+
+ ic->GetInnerContainer = iTabsGetInnerContainerMethod;
+ ic->ChildAdded = iTabsChildAddedMethod;
+ ic->ChildRemoved = iTabsChildRemovedMethod;
+
+ /* Do not need to set base attributes because they are inherited from IupCanvas */
+
+ /* IupTabs Callbacks */
+ iupClassRegisterCallback(ic, "TABCHANGE_CB", "nn");
+
+ /* IupTabs only */
+ iupClassRegisterAttribute(ic, "ALIGNMENT", iTabsGetAlignmentAttrib, iTabsSetAlignmentAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TABTYPE", iTabsGetTabTypeAttrib, iTabsSetTabTypeAttrib, IUPAF_SAMEASSYSTEM, "TOP", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TABORIENTATION", iTabsGetTabOrientationAttrib, iTabsSetTabOrientationAttrib, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "REPAINT", NULL, iTabsSetRepaintAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FONT_ACTIVE", NULL, iTabsSetFontActiveAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FONT_INACTIVE", NULL, iTabsSetFontInactiveAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUE", iTabsGetValueAttrib, iTabsSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUEPOS", iTabsGetValuePosAttrib, iTabsSetValuePosAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "TABTITLE", NULL, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TABSIZE", NULL, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, iTabsSetFgColorAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iTabsSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupControlBaseGetBgColorAttrib, iTabsSetBgColorAttrib, NULL, "255 255 255", IUPAF_DEFAULT); /* overwrite canvas implementation, set a system default to force a new default */
+
+ /* Base Container */
+ iupClassRegisterAttribute(ic, "EXPAND", iupBaseContainerGetExpandAttrib, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CLIENTSIZE", iTabsGetClientSizeAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* overwrite canvas default */
+
+ return ic;
+}
+
+void IupOldTabsOpen(void)
+{
+ iupRegisterClass(iTabsGetClass());
+}
diff --git a/iup/srccontrols/iup_oldval.c b/iup/srccontrols/iup_oldval.c
new file mode 100755
index 0000000..50dae8a
--- /dev/null
+++ b/iup/srccontrols/iup_oldval.c
@@ -0,0 +1,809 @@
+/** \file
+ * \brief Valuator Control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupcontrols.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+#include "iup_register.h"
+
+
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ /* mouse interaction control */
+ int moving;
+
+ /* visual appearance control */
+ int w,h;
+ long bgcolor,
+ light_shadow,
+ mid_shadow,
+ dark_shadow;
+ int has_focus;
+
+ /* attributes */
+ int type;
+ int show_ticks;
+ double val,
+ step,
+ pagestep,
+ vmin,
+ vmax;
+
+ unsigned char* himage;
+ int himage_w;
+ int himage_h;
+ long int* himage_colors;
+ int himage_numcolors;
+
+ unsigned char* himageinactive;
+ int himageinactive_w;
+ int himageinactive_h;
+ long int* himageinactive_colors;
+ int himageinactive_numcolors;
+
+ /* drawing canvas */
+ cdCanvas *cddbuffer;
+ cdCanvas *cdcanvas;
+
+ /* Internal methods */
+ void (*Draw)(Ihandle* ih);
+ void (*CalcPosition)(Ihandle*,int,int);
+};
+
+#define IVAL_HANDLER_LONG 22 /* handler long side */
+#define IVAL_HANDLER_SHORT 16 /* handler short side */
+#define IVAL_TRAIL 4 /* with of the trail */
+#define IVAL_TICK 3 /* size of the tick mark */
+#define IVAL_TRAIL_START (IVAL_HANDLER_LONG/2+1)
+#define IVAL_TRAIL_END(_s) (_s-1-IVAL_HANDLER_LONG/2-1)
+#define IVAL_TRAIL_LONG(_s) (_s-1-IVAL_HANDLER_LONG-1)
+
+enum {IVAL_VERTICAL, IVAL_HORIZONTAL};
+
+static void iValUpdateImageBgColor(long int* colors, int num_colors, long bgcolor)
+{
+ int c;
+ for (c = 0; c < num_colors; c++)
+ {
+ if (*colors == -1)
+ *colors = bgcolor;
+ colors++;
+ }
+
+}
+
+static void iValSetImage(const char* name, unsigned char** image_out, long int** color_out,
+ int* w_out, int* h_out, int* numcolors_out)
+{
+ int x, y, c, width, height, max_color = 0;
+ unsigned char* image_data;
+ Ihandle *img = IupGetHandle(name);
+
+ *w_out = width = img->currentwidth;
+ *h_out = height = img->currentheight;
+ image_data = (unsigned char*)IupGetAttribute(img, "WID");
+
+ *image_out = (unsigned char*) realloc(*image_out, width*height*sizeof(unsigned char));
+ *color_out = (long int*) realloc(*color_out, 256*sizeof(long int));
+
+ for(y = height-1 ; y >=0 ; y--)
+ {
+ for(x = 0 ; x < width ; x++)
+ {
+ (*image_out)[x+width*y] = *image_data;
+ if (*image_data > max_color)
+ max_color = *image_data;
+ image_data++;
+ }
+ }
+
+ max_color++;
+ *numcolors_out = max_color;
+
+ for(c = 0 ; c < max_color; c++)
+ {
+ char colorstr[30];
+ char *value;
+ sprintf(colorstr, "%d", c);
+ value = iupAttribGet(img, colorstr);
+ if (iupStrEqualNoCase(value, "BGCOLOR"))
+ (*color_out)[c] = -1;
+ else
+ (*color_out)[c] = cdIupConvertColor(value);
+ }
+}
+
+static void iValRepaint(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return;
+
+ /* update render */
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+ ih->data->Draw(ih);
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, 0, 0, ih->data->w-1, ih->data->h-1);
+}
+
+static void iValDrawVerticalTick(Ihandle* ih, int y)
+{
+ cdIupDrawHorizSunkenMark(ih->data->cddbuffer, 1, 1+IVAL_TICK, y, ih->data->light_shadow, ih->data->dark_shadow);
+ cdIupDrawHorizSunkenMark(ih->data->cddbuffer, ih->data->w-2-IVAL_TICK, ih->data->w-2, y, ih->data->light_shadow, ih->data->dark_shadow);
+}
+
+static void iValDrawHorizontalTick(Ihandle* ih, int x)
+{
+
+ cdIupDrawVertSunkenMark(ih->data->cddbuffer, x, 1, 1+IVAL_TICK, ih->data->light_shadow, ih->data->dark_shadow);
+ cdIupDrawVertSunkenMark(ih->data->cddbuffer, x, ih->data->h-2-IVAL_TICK, ih->data->h-2, ih->data->light_shadow, ih->data->dark_shadow);
+}
+
+static void iValDrawVerticalTicks(Ihandle* ih)
+{
+ int i;
+ for (i = 0; i < ih->data->show_ticks-1; i++)
+ {
+ iValDrawVerticalTick(ih, (i*(IVAL_TRAIL_LONG(ih->data->h)-2))/(ih->data->show_ticks-1) + IVAL_TRAIL_START+1);
+ }
+
+ iValDrawVerticalTick(ih, IVAL_TRAIL_END(ih->data->h));
+}
+
+static void iValDrawHorizontalTicks(Ihandle* ih)
+{
+ int i;
+ for (i = 0; i < ih->data->show_ticks-1; i++)
+ {
+ iValDrawHorizontalTick(ih, (i*(IVAL_TRAIL_LONG(ih->data->w)-2))/(ih->data->show_ticks-1) + IVAL_TRAIL_START+1);
+ }
+
+ iValDrawHorizontalTick(ih, IVAL_TRAIL_END(ih->data->w));
+}
+
+static void iValDrawVertical(Ihandle* ih)
+{
+ int y, x = (ih->data->w-IVAL_TRAIL)/2;
+ double vn = (ih->data->val-ih->data->vmin)/(ih->data->vmax-ih->data->vmin);
+
+ /* trail */
+ cdIupDrawSunkenRect(ih->data->cddbuffer, x, IVAL_TRAIL_START, x+IVAL_TRAIL-1, IVAL_TRAIL_END(ih->data->h)+1,
+ ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+
+ if (ih->data->show_ticks > 2)
+ iValDrawVerticalTicks(ih);
+
+ if (iupdrvIsActive(ih) && ih->data->himage)
+ {
+ x = (ih->data->w - ih->data->himage_w)/2;
+ y = (int)(vn*(IVAL_TRAIL_LONG(ih->data->h)-2) + IVAL_TRAIL_START+1);
+ cdCanvasPutImageRectMap(ih->data->cddbuffer,ih->data->himage_w, ih->data->himage_h, ih->data->himage, ih->data->himage_colors,
+ x, y-ih->data->himage_h/2, 0,0,0,0,0,0);
+ }
+ else if (!iupdrvIsActive(ih) && ih->data->himageinactive)
+ {
+ x = (ih->data->w - ih->data->himageinactive_w)/2;
+ y = (int)(vn*(IVAL_TRAIL_LONG(ih->data->h)-2) + IVAL_TRAIL_START+1);
+ cdCanvasPutImageRectMap(ih->data->cddbuffer,ih->data->himageinactive_w, ih->data->himageinactive_h, ih->data->himageinactive,
+ ih->data->himageinactive_colors, x, y-ih->data->himageinactive_h/2, 0,0,0,0,0,0);
+ }
+ else
+ {
+ /* handler border */
+ x = (ih->data->w-IVAL_HANDLER_SHORT)/2;
+ y = (int)(vn*(IVAL_TRAIL_LONG(ih->data->h)-2) + IVAL_TRAIL_START+1);
+ cdIupDrawRaisenRect(ih->data->cddbuffer, x, y-IVAL_HANDLER_LONG/2-1, x+IVAL_HANDLER_SHORT-1, y+IVAL_HANDLER_LONG/2,
+ ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+
+ /* handler background */
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->bgcolor );
+ cdCanvasBox(ih->data->cddbuffer,x+1, x+IVAL_HANDLER_SHORT-1-2, y-IVAL_HANDLER_LONG/2+1, y+IVAL_HANDLER_LONG/2-1);
+
+ /* handler sunken mark */
+ cdIupDrawHorizSunkenMark(ih->data->cddbuffer, x+2, x+IVAL_HANDLER_SHORT-4, y, ih->data->light_shadow, ih->data->dark_shadow);
+ }
+}
+
+static void iValDrawHorizontal(Ihandle* ih)
+{
+ int x, y = (ih->data->h-IVAL_TRAIL)/2;
+ double vn = (ih->data->val-ih->data->vmin)/(ih->data->vmax-ih->data->vmin);
+
+ /* trail */
+ cdIupDrawSunkenRect(ih->data->cddbuffer, IVAL_TRAIL_START, y, IVAL_TRAIL_END(ih->data->w)+1, y+IVAL_TRAIL-1,
+ ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+
+ if (ih->data->show_ticks > 2)
+ iValDrawHorizontalTicks(ih);
+
+ if (iupdrvIsActive(ih) && ih->data->himage)
+ {
+ y = (ih->data->h - ih->data->himage_h)/2+1;
+ x = (int)(vn*(IVAL_TRAIL_LONG(ih->data->w)-2) + IVAL_TRAIL_START+1);
+ cdCanvasPutImageRectMap(ih->data->cddbuffer,ih->data->himage_w, ih->data->himage_h, ih->data->himage, ih->data->himage_colors,
+ x-ih->data->himage_w/2, y, 0,0,0,0,0,0);
+ }
+ else if (!iupdrvIsActive(ih) && ih->data->himageinactive)
+ {
+ y = (ih->data->h - ih->data->himageinactive_h)/2+1;
+ x = (int)(vn*(IVAL_TRAIL_LONG(ih->data->w)-2) + IVAL_TRAIL_START+1);
+ cdCanvasPutImageRectMap(ih->data->cddbuffer,ih->data->himageinactive_w, ih->data->himageinactive_h, ih->data->himageinactive, ih->data->himageinactive_colors,
+ x-ih->data->himageinactive_w/2, y, 0,0,0,0,0,0);
+ }
+ else
+ {
+ /* handler border */
+ y = (ih->data->h-IVAL_HANDLER_SHORT)/2;
+ x = (int)(vn*(IVAL_TRAIL_LONG(ih->data->w)-2) + IVAL_TRAIL_START+1);
+ cdIupDrawRaisenRect(ih->data->cddbuffer, x-IVAL_HANDLER_LONG/2-1, y, x+IVAL_HANDLER_LONG/2, y+IVAL_HANDLER_SHORT-1,
+ ih->data->light_shadow, ih->data->mid_shadow, ih->data->dark_shadow);
+
+ /* handler background */
+ cdCanvasForeground(ih->data->cddbuffer, ih->data->bgcolor );
+ cdCanvasBox(ih->data->cddbuffer,x-IVAL_HANDLER_LONG/2, x+IVAL_HANDLER_LONG/2-2, y+1, y+IVAL_HANDLER_SHORT-1-2);
+
+ /* handler sunken mark */
+ cdIupDrawVertSunkenMark(ih->data->cddbuffer, x, y+3, y+IVAL_HANDLER_SHORT-3, ih->data->light_shadow, ih->data->dark_shadow);
+ }
+}
+
+static void iValCropValue(Ihandle* ih)
+{
+ if (ih->data->val > ih->data->vmax)
+ ih->data->val = ih->data->vmax;
+ else if (ih->data->val < ih->data->vmin)
+ ih->data->val = ih->data->vmin;
+}
+
+static void iValSetVerticalPosition(Ihandle* ih, int x, int y)
+{
+ double vn;
+ (void)x;
+ y = cdIupInvertYAxis(y, ih->data->h);
+ vn = ((double)(y-IVAL_TRAIL_START))/((double)IVAL_TRAIL_LONG(ih->data->h));
+ ih->data->val = vn*(ih->data->vmax-ih->data->vmin) + ih->data->vmin;
+ iValCropValue(ih);
+ iValRepaint(ih);
+}
+
+static void iValSetHorizontalPosition(Ihandle* ih, int x, int y)
+{
+ double vn;
+ (void)y;
+ vn = ((double)(x-IVAL_TRAIL_START))/((double)IVAL_TRAIL_LONG(ih->data->w));
+ ih->data->val = vn*(ih->data->vmax-ih->data->vmin) + ih->data->vmin;
+ iValCropValue(ih);
+ iValRepaint(ih);
+}
+
+static int iValMotion_CB(Ihandle *ih,int x,int y,char *r)
+{
+ IFnd cb;
+
+ if (!iup_isbutton1(r)) return IUP_DEFAULT;
+ if (!ih->data->moving) return IUP_DEFAULT;
+
+ ih->data->CalcPosition(ih,x,y);
+
+ cb = (IFnd) IupGetCallback(ih, "MOUSEMOVE_CB");
+ if (cb) cb(ih,ih->data->val);
+
+ return IUP_DEFAULT;
+}
+
+static int iValButton_CB(Ihandle *ih,int b,int m,int x,int y)
+{
+ char* cb_name;
+ IFnd cb;
+ if (b!=IUP_BUTTON1) return IUP_DEFAULT;
+
+ if (m)
+ {
+ ih->data->CalcPosition(ih, x, y);
+ ih->data->moving = 1;
+ cb_name = "BUTTON_PRESS_CB";
+ }
+ else
+ {
+ if (!ih->data->moving) return IUP_DEFAULT;
+
+ iValRepaint(ih);
+ ih->data->moving = 0;
+
+ cb_name = "BUTTON_RELEASE_CB";
+ }
+
+ cb = (IFnd) IupGetCallback(ih, cb_name);
+ if (cb) cb(ih,ih->data->val);
+
+ return IUP_DEFAULT;
+}
+
+static int iValResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ /* update render */
+ cdCanvasBackground(ih->data->cddbuffer, ih->data->bgcolor);
+ cdCanvasClear(ih->data->cddbuffer);
+ ih->data->Draw(ih);
+
+ return IUP_DEFAULT;
+}
+
+static int iValRedraw_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update display */
+ cdCanvasFlush(ih->data->cddbuffer);
+ if (ih->data->has_focus)
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, 0, 0, ih->data->w-1, ih->data->h-1);
+
+ return IUP_DEFAULT;
+}
+
+static int iValFocus_CB (Ihandle* ih, int focus)
+{
+ ih->data->has_focus = focus;
+ iValRepaint(ih);
+ return IUP_DEFAULT;
+}
+
+static int iValKeypress_CB(Ihandle *ih, int c, int press)
+{
+ char* cb_name;
+ IFnd cb;
+
+ if (c != K_LEFT && c != K_UP &&
+ c != K_PGDN && c != K_PGUP &&
+ c != K_RIGHT && c != K_DOWN &&
+ c != K_END && c != K_HOME &&
+ c != K_sLEFT && c != K_sUP &&
+ c != K_sPGDN && c != K_sPGUP &&
+ c != K_sRIGHT && c != K_sDOWN &&
+ c != K_sEND && c != K_sHOME)
+ return IUP_DEFAULT;
+
+ if (press)
+ {
+ switch(c)
+ {
+ case K_sHOME:
+ case K_HOME:
+ ih->data->val = ih->data->vmax;
+ break;
+ case K_sEND:
+ case K_END:
+ ih->data->val = ih->data->vmin;
+ break;
+ case K_sLEFT:
+ case K_sDOWN:
+ case K_LEFT:
+ case K_DOWN:
+ ih->data->val -= ih->data->step*(ih->data->vmax-ih->data->vmin);
+ iValCropValue(ih);
+ break;
+ case K_sRIGHT:
+ case K_sUP:
+ case K_RIGHT:
+ case K_UP:
+ ih->data->val += ih->data->step*(ih->data->vmax-ih->data->vmin);
+ iValCropValue(ih);
+ break;
+ case K_sPGDN:
+ case K_PGDN:
+ ih->data->val -= ih->data->pagestep*(ih->data->vmax-ih->data->vmin);
+ iValCropValue(ih);
+ break;
+ case K_sPGUP:
+ case K_PGUP:
+ ih->data->val += ih->data->pagestep*(ih->data->vmax-ih->data->vmin);
+ iValCropValue(ih);
+ break;
+ }
+
+ if (fabs(ih->data->val-ih->data->vmin) < 0.9*ih->data->step*(ih->data->vmax-ih->data->vmin))
+ ih->data->val = ih->data->vmin;
+
+ if (ih->data->moving)
+ cb_name = "MOUSEMOVE_CB";
+ else
+ {
+ ih->data->moving = 1;
+ cb_name = "BUTTON_PRESS_CB";
+ }
+ }
+ else
+ {
+ ih->data->moving = 0;
+ cb_name = "BUTTON_RELEASE_CB";
+ }
+
+ iValRepaint(ih);
+
+ cb = (IFnd) IupGetCallback(ih, cb_name);
+ if (cb) cb(ih,ih->data->val);
+
+ return IUP_IGNORE; /* to avoid arrow keys being processed by the system */
+}
+
+static int iValWheel_CB(Ihandle *ih, float delta)
+{
+ IFnd cb;
+
+ ih->data->val += ((double)delta)*ih->data->step*(ih->data->vmax-ih->data->vmin);
+ iValCropValue(ih);
+
+ if (fabs(ih->data->val-ih->data->vmin) < 0.9*ih->data->step*(ih->data->vmax-ih->data->vmin))
+ ih->data->val = ih->data->vmin;
+
+ iValRepaint(ih);
+
+ cb = (IFnd) IupGetCallback(ih, "BUTTON_PRESS_CB");
+ if (cb) cb(ih,ih->data->val);
+
+ cb = (IFnd) IupGetCallback(ih, "BUTTON_RELEASE_CB");
+ if (cb) cb(ih,ih->data->val);
+
+ return IUP_DEFAULT;
+}
+
+
+/*******************************************************************************/
+
+
+static int iValSetTypeAttrib(Ihandle* ih, const char *value)
+{
+ /* valid only before map */
+ if (ih->handle)
+ return 0;
+
+ if (iupStrEqualNoCase(value, "VERTICAL"))
+ {
+ IupSetAttribute(ih, "RASTERSIZE", "28x124");
+
+ ih->data->Draw = iValDrawVertical;
+ ih->data->CalcPosition = iValSetVerticalPosition;
+ ih->data->type = IVAL_VERTICAL;
+ }
+ else /* "HORIZONTAL" */
+ {
+ IupSetAttribute(ih, "RASTERSIZE", "124x28");
+
+ ih->data->Draw = iValDrawHorizontal;
+ ih->data->CalcPosition = iValSetHorizontalPosition;
+ ih->data->type = IVAL_HORIZONTAL;
+ }
+
+ return 0; /* do not store value in hash table */
+}
+
+static char* iValGetTypeAttrib(Ihandle* ih)
+{
+ if (ih->data->type == IVAL_HORIZONTAL)
+ return "HORIZONTAL";
+ else /* (ih->data->type == IVAL_VERTICAL) */
+ return "VERTICAL";
+}
+
+static char* iValGetValueAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%f", ih->data->val);
+ return str;
+}
+
+static int iValSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ ih->data->val = 0;
+ else
+ ih->data->val = atof(value);
+ iValCropValue(ih);
+ iValRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static int iValSetShowTicksAttrib(Ihandle* ih, const char* showticks)
+{
+ int i;
+ if (iupStrToInt(showticks, &i))
+ {
+ ih->data->show_ticks = i;
+ iValRepaint(ih);
+ }
+ return 0; /* do not store value in hash table */
+}
+
+static char* iValGetShowTicksAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%d", ih->data->show_ticks);
+ return str;
+}
+
+static int iValSetStepAttrib(Ihandle* ih, const char* step)
+{
+ ih->data->step = atof(step);
+ iValRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iValGetStepAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%f", ih->data->step);
+ return str;
+}
+
+static int iValSetPageStepAttrib(Ihandle* ih, const char* pagestep)
+{
+ ih->data->step = atof(pagestep);
+ iValRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iValGetPageStepAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%f", ih->data->pagestep);
+ return str;
+}
+
+static int iValSetMaxAttrib(Ihandle* ih, const char* max)
+{
+ ih->data->vmax = atof(max);
+ iValCropValue(ih);
+ iValRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iValGetMaxAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%f", ih->data->vmax);
+ return str;
+}
+
+static int iValSetMinAttrib(Ihandle* ih, const char* min)
+{
+ ih->data->vmin = atof(min);
+ iValCropValue(ih);
+ iValRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+static char* iValGetMinAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ sprintf(str, "%f", ih->data->vmin);
+ return str;
+}
+
+static int iValSetHandlerImageAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ {
+ if (ih->data->himage)
+ {
+ free(ih->data->himage);
+ free(ih->data->himage_colors);
+ ih->data->himage = NULL;
+ ih->data->himage_colors = NULL;
+ }
+ }
+ else
+ {
+ iValSetImage(value, &(ih->data->himage), &(ih->data->himage_colors),
+ &(ih->data->himage_w), &(ih->data->himage_h), &(ih->data->himage_numcolors));
+ }
+
+ iValRepaint(ih);
+ return 1;
+}
+
+static int iValSetHandlerImageInactiveAttrib(Ihandle* ih, const char* value)
+{
+ if (value==NULL)
+ {
+ if (ih->data->himageinactive)
+ {
+ free(ih->data->himageinactive);
+ free(ih->data->himageinactive_colors);
+ ih->data->himageinactive = NULL;
+ ih->data->himageinactive_colors = NULL;
+ }
+ }
+ else
+ {
+ iValSetImage(value, &(ih->data->himageinactive), &(ih->data->himageinactive_colors),
+ &(ih->data->himageinactive_w), &(ih->data->himageinactive_h), &(ih->data->himageinactive_numcolors));
+ }
+
+ iValRepaint(ih);
+ return 1;
+}
+
+static int iValSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ value = iupControlBaseGetParentBgColor(ih);
+
+ ih->data->bgcolor = cdIupConvertColor(value);
+
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+ if (!iupdrvIsActive(ih) && !ih->data->himage)
+ ih->data->light_shadow = ih->data->mid_shadow;
+
+ if (ih->data->himage)
+ iValUpdateImageBgColor(ih->data->himage_colors, ih->data->himage_numcolors, ih->data->bgcolor);
+ if (ih->data->himageinactive)
+ iValUpdateImageBgColor(ih->data->himageinactive_colors, ih->data->himageinactive_numcolors, ih->data->bgcolor);
+
+ iValRepaint(ih);
+ return 1;
+}
+
+static int iValSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ iupBaseSetActiveAttrib(ih, value);
+
+ cdIupCalcShadows(ih->data->bgcolor, &ih->data->light_shadow, &ih->data->mid_shadow, &ih->data->dark_shadow);
+ if (!iupdrvIsActive(ih) && !ih->data->himage)
+ ih->data->light_shadow = ih->data->mid_shadow;
+
+ iValRepaint(ih);
+ return 0; /* do not store value in hash table */
+}
+
+
+/************************************************************************************/
+
+
+static int iValMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ return IUP_NOERROR;
+}
+
+static void iValUnMapMethod(Ihandle* ih)
+{
+ if (ih->data->cddbuffer)
+ cdKillCanvas(ih->data->cddbuffer);
+
+ if (ih->data->cdcanvas)
+ cdKillCanvas(ih->data->cdcanvas);
+}
+
+static void iValDestroyMethod(Ihandle* ih)
+{
+ if (ih->data->himage) free(ih->data->himage);
+ if (ih->data->himage_colors) free(ih->data->himage_colors);
+ if (ih->data->himageinactive) free(ih->data->himageinactive);
+ if (ih->data->himageinactive_colors) free(ih->data->himageinactive_colors);
+}
+
+static int iValCreateMethod(Ihandle* ih, void **params)
+{
+ if (params && params[0])
+ iupAttribStoreStr(ih, "TYPE", params[0]);
+
+ /* free the data alocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "BORDER", "NO");
+ ih->expand = IUP_EXPAND_NONE;
+
+ /* default values */
+ iValSetTypeAttrib(ih, "HORIZONTAL");
+ ih->data->vmax = 1;
+ ih->data->step = 0.01;
+ ih->data->pagestep = 0.1;
+
+ IupSetCallback(ih,"RESIZE_CB",(Icallback)iValResize_CB);
+ IupSetCallback(ih,"ACTION",(Icallback)iValRedraw_CB);
+ IupSetCallback(ih,"BUTTON_CB",(Icallback)iValButton_CB);
+ IupSetCallback(ih,"MOTION_CB",(Icallback)iValMotion_CB);
+ IupSetCallback(ih,"FOCUS_CB",(Icallback)iValFocus_CB);
+ IupSetCallback(ih,"WHEEL_CB",(Icallback)iValWheel_CB);
+ IupSetCallback(ih,"KEYPRESS_CB",(Icallback)iValKeypress_CB);
+
+ return IUP_NOERROR;
+}
+
+static Iclass* iValGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "val";
+ ic->format = "S"; /* one optional string */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+
+ /* Class functions */
+ ic->Create = iValCreateMethod;
+ ic->Destroy = iValDestroyMethod;
+ ic->Map = iValMapMethod;
+ ic->UnMap = iValUnMapMethod;
+
+ /* IupVal Callbacks */
+ iupClassRegisterCallback(ic, "MOUSEMOVE_CB", "d");
+ iupClassRegisterCallback(ic, "BUTTON_PRESS_CB", "d");
+ iupClassRegisterCallback(ic, "BUTTON_RELEASE_CB", "d");
+
+ /* IupVal only */
+ iupClassRegisterAttribute(ic, "VALUE", iValGetValueAttrib, iValSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TYPE", iValGetTypeAttrib, iValSetTypeAttrib, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "SHOWTICKS", iValGetShowTicksAttrib, iValSetShowTicksAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "STEP", iValGetStepAttrib, iValSetStepAttrib, IUPAF_SAMEASSYSTEM, "0.01", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "PAGESTEP", iValGetPageStepAttrib, iValSetPageStepAttrib, IUPAF_SAMEASSYSTEM, "0.1", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "MAX", iValGetMaxAttrib, iValSetMaxAttrib, IUPAF_SAMEASSYSTEM, "1.0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "MIN", iValGetMinAttrib, iValSetMinAttrib, IUPAF_SAMEASSYSTEM, "0.0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "HANDLER_IMAGE", NULL, iValSetHandlerImageAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "HANDLER_IMAGE_INACTIVE", NULL, iValSetHandlerImageInactiveAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iValSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", iupControlBaseGetBgColorAttrib, iValSetBgColorAttrib, NULL, "255 255 255", IUPAF_NO_INHERIT); /* overwrite canvas implementation, set a system default to force a new default */
+
+ return ic;
+}
+
+void IupOldValOpen(void)
+{
+ iupRegisterClass(iValGetClass());
+}
diff --git a/iup/srccontrols/iupcontrols.def b/iup/srccontrols/iupcontrols.def
new file mode 100755
index 0000000..06c8f6f
--- /dev/null
+++ b/iup/srccontrols/iupcontrols.def
@@ -0,0 +1,35 @@
+EXPORTS
+IupColorbar
+IupColorBrowser
+IupDial
+IupGauge
+IupCells
+IupMatrix
+IupMatSetAttribute
+IupMatStoreAttribute
+IupMatGetAttribute
+IupMatGetInt
+IupMatGetFloat
+IupMatSetfAttribute
+
+IupControlsOpen
+IupControlsClose
+
+iupmaskSet
+iupmaskSetInt
+iupmaskSetFloat
+iupmaskCheck
+iupmaskGet
+iupmaskGetFloat
+iupmaskGetDouble
+iupmaskGetInt
+iupmaskMatSet
+iupmaskMatSetInt
+iupmaskMatSetFloat
+iupmaskMatCheck
+iupmaskMatGet
+iupmaskMatGetFloat
+iupmaskMatGetDouble
+iupmaskMatGetInt
+iupmaskRemove
+iupmaskMatRemove
diff --git a/iup/srccontrols/iupcontrols.dep b/iup/srccontrols/iupcontrols.dep
new file mode 100644
index 0000000..773616a
--- /dev/null
+++ b/iup/srccontrols/iupcontrols.dep
@@ -0,0 +1,173 @@
+$(OBJDIR)/iup_cdutil.o: iup_cdutil.c ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../src/iup_attrib.h ../src/iup_str.h \
+ ../src/iup_drv.h iup_cdutil.h
+$(OBJDIR)/iup_gauge.o: iup_gauge.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../../cd/include/cdiup.h \
+ ../../cd/include/cddbuf.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_drv.h ../src/iup_stdcontrols.h \
+ iup_controls.h iup_cdutil.h
+$(OBJDIR)/iup_cells.o: iup_cells.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../../cd/include/cdiup.h \
+ ../../cd/include/cddbuf.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_drv.h ../src/iup_stdcontrols.h \
+ iup_controls.h iup_cdutil.h
+$(OBJDIR)/iup_colorbar.o: iup_colorbar.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcontrols.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h \
+ ../../cd/include/cdiup.h ../../cd/include/cddbuf.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_drv.h \
+ ../src/iup_stdcontrols.h iup_controls.h ../src/iup_image.h iup_cdutil.h
+$(OBJDIR)/iup_controls.o: iup_controls.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcontrols.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_childtree.h ../src/iup_register.h iup_controls.h \
+ ../src/iup_attrib.h
+$(OBJDIR)/iup_dial.o: iup_dial.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../../cd/include/cdiup.h \
+ ../../cd/include/cddbuf.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_drv.h ../src/iup_stdcontrols.h \
+ iup_controls.h iup_cdutil.h
+$(OBJDIR)/iup_oldtabs.o: iup_oldtabs.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../../cd/include/cdiup.h \
+ ../../cd/include/cddbuf.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_drv.h ../src/iup_drvfont.h \
+ ../src/iup_stdcontrols.h ../src/iup_register.h ../src/iup_layout.h \
+ iup_controls.h iup_cdutil.h
+$(OBJDIR)/iup_oldval.o: iup_oldval.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../include/iupcontrols.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h \
+ ../../cd/include/cdiup.h ../../cd/include/cddbuf.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_drv.h \
+ ../src/iup_stdcontrols.h iup_controls.h iup_cdutil.h \
+ ../src/iup_register.h
+$(OBJDIR)/iup_oldmask.o: iup_oldmask.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcontrols.h ../include/iupmask.h \
+ ../src/iup_mask.h ../src/iup_str.h
+$(OBJDIR)/iup_colorbrowser.o: color/iup_colorbrowser.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h \
+ ../../cd/include/cdiup.h ../../cd/include/cdirgb.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_drv.h \
+ ../src/iup_stdcontrols.h iup_controls.h iup_cdutil.h \
+ color/iup_colorhsi.h
+$(OBJDIR)/iup_colorhsi.o: color/iup_colorhsi.c color/iup_colorhsi.h
+$(OBJDIR)/iup_colorbrowserdlg.o: color/iup_colorbrowserdlg.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../include/iupcontrols.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../../cd/include/cdiup.h \
+ ../../cd/include/cddbuf.h ../../cd/include/cdirgb.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_strmessage.h \
+ ../src/iup_drv.h ../src/iup_stdcontrols.h iup_controls.h iup_cdutil.h \
+ ../src/iup_register.h ../src/iup_image.h color/iup_colorhsi.h \
+ ../src/iup_childtree.h
+$(OBJDIR)/iupmat_key.o: matrix/iupmat_key.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_stdcontrols.h matrix/iupmat_def.h matrix/iupmat_scroll.h \
+ matrix/iupmat_focus.h matrix/iupmat_aux.h matrix/iupmat_getset.h \
+ matrix/iupmat_key.h matrix/iupmat_mark.h matrix/iupmat_edit.h \
+ matrix/iupmat_draw.h
+$(OBJDIR)/iupmat_mark.o: matrix/iupmat_mark.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_stdcontrols.h matrix/iupmat_def.h \
+ matrix/iupmat_mark.h matrix/iupmat_getset.h matrix/iupmat_draw.h
+$(OBJDIR)/iupmat_aux.o: matrix/iupmat_aux.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_drvfont.h ../src/iup_stdcontrols.h \
+ matrix/iupmat_def.h matrix/iupmat_aux.h matrix/iupmat_getset.h
+$(OBJDIR)/iupmat_mem.o: matrix/iupmat_mem.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_stdcontrols.h matrix/iupmat_def.h \
+ matrix/iupmat_mem.h
+$(OBJDIR)/iupmat_mouse.o: matrix/iupmat_mouse.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_stdcontrols.h \
+ matrix/iupmat_def.h matrix/iupmat_colres.h matrix/iupmat_aux.h \
+ matrix/iupmat_focus.h matrix/iupmat_mouse.h matrix/iupmat_key.h \
+ matrix/iupmat_mark.h matrix/iupmat_edit.h matrix/iupmat_draw.h \
+ matrix/iupmat_scroll.h
+$(OBJDIR)/iupmat_numlc.o: matrix/iupmat_numlc.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_stdcontrols.h \
+ matrix/iupmat_def.h matrix/iupmat_edit.h matrix/iupmat_mem.h \
+ matrix/iupmat_numlc.h matrix/iupmat_draw.h
+$(OBJDIR)/iupmat_colres.o: matrix/iupmat_colres.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_stdcontrols.h \
+ matrix/iupmat_def.h matrix/iupmat_colres.h matrix/iupmat_draw.h
+$(OBJDIR)/iupmat_draw.o: matrix/iupmat_draw.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../../cd/include/cd.h \
+ ../../cd/include/cd_old.h ../src/iup_object.h ../src/iup_class.h \
+ ../src/iup_table.h ../src/iup_classbase.h ../src/iup_attrib.h \
+ ../src/iup_str.h ../src/iup_drv.h ../src/iup_drvfont.h \
+ ../src/iup_stdcontrols.h iup_controls.h iup_cdutil.h ../src/iup_image.h \
+ matrix/iupmat_def.h matrix/iupmat_cd.h matrix/iupmat_draw.h \
+ matrix/iupmat_aux.h matrix/iupmat_getset.h matrix/iupmat_mark.h
+$(OBJDIR)/iupmat_focus.o: matrix/iupmat_focus.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_stdcontrols.h \
+ matrix/iupmat_def.h matrix/iupmat_aux.h matrix/iupmat_focus.h \
+ matrix/iupmat_draw.h
+$(OBJDIR)/iupmat_getset.o: matrix/iupmat_getset.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_drvfont.h ../src/iup_str.h \
+ ../src/iup_stdcontrols.h iup_controls.h ../src/iup_childtree.h \
+ matrix/iupmat_def.h matrix/iupmat_getset.h matrix/iupmat_edit.h \
+ matrix/iupmat_draw.h matrix/iupmat_aux.h
+$(OBJDIR)/iupmatrix.o: matrix/iupmatrix.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../include/iupcontrols.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h \
+ ../../cd/include/cdiup.h ../../cd/include/cddbuf.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_drv.h \
+ ../src/iup_drvfont.h ../src/iup_stdcontrols.h iup_controls.h \
+ ../src/iup_register.h matrix/iupmat_def.h matrix/iupmat_getset.h \
+ matrix/iupmat_scroll.h matrix/iupmat_aux.h matrix/iupmat_mem.h \
+ matrix/iupmat_mouse.h matrix/iupmat_focus.h matrix/iupmat_key.h \
+ matrix/iupmat_numlc.h matrix/iupmat_colres.h matrix/iupmat_mark.h \
+ matrix/iupmat_edit.h matrix/iupmat_draw.h
+$(OBJDIR)/iupmat_scroll.o: matrix/iupmat_scroll.c ../include/iup.h \
+ ../include/iupkey.h ../include/iupdef.h ../include/iupcbs.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_stdcontrols.h matrix/iupmat_def.h matrix/iupmat_scroll.h \
+ matrix/iupmat_focus.h matrix/iupmat_aux.h matrix/iupmat_edit.h \
+ matrix/iupmat_draw.h
+$(OBJDIR)/iupmat_edit.o: matrix/iupmat_edit.c ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../include/iupcontrols.h \
+ ../../cd/include/cd.h ../../cd/include/cd_old.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_table.h ../src/iup_classbase.h \
+ ../src/iup_attrib.h ../src/iup_str.h ../src/iup_stdcontrols.h \
+ ../src/iup_childtree.h matrix/iupmat_def.h matrix/iupmat_scroll.h \
+ matrix/iupmat_aux.h matrix/iupmat_edit.h matrix/iupmat_key.h \
+ matrix/iupmat_getset.h matrix/iupmat_draw.h
diff --git a/iup/srccontrols/make_uname b/iup/srccontrols/make_uname
new file mode 100755
index 0000000..cc4b881
--- /dev/null
+++ b/iup/srccontrols/make_uname
@@ -0,0 +1,3 @@
+#This builds all the libraries of the folder for 1 uname
+
+tecmake $1 $2 $3 $4 $5 $6 $7
diff --git a/iup/srccontrols/make_uname.bat b/iup/srccontrols/make_uname.bat
new file mode 100755
index 0000000..f0a0722
--- /dev/null
+++ b/iup/srccontrols/make_uname.bat
@@ -0,0 +1,4 @@
+@echo off
+REM This builds all the libraries of the folder for 1 uname
+
+call tecmake %1 %2 %3 %4 %5 %6
diff --git a/iup/srccontrols/matrix/iupmat_aux.c b/iup/srccontrols/matrix/iupmat_aux.c
new file mode 100755
index 0000000..f8b85bb
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_aux.c
@@ -0,0 +1,480 @@
+/** \file
+ * \brief iupmatrix control
+ * auxiliary functions
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_aux.h"
+#include "iupmat_getset.h"
+
+
+static int iMatrixAuxIsFullVisibleLast(Ihandle* ih, int m)
+{
+ int i, sum = 0;
+ ImatLinColData *p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ for(i = p->first; i <= p->last; i++)
+ sum += p->sizes[i];
+
+ if (sum > p->visible_size)
+ return 0;
+ else
+ return 1;
+}
+
+int iupMatrixAuxIsCellFullVisible(Ihandle* ih, int lin, int col)
+{
+ if(((lin >= ih->data->lines.first) &&
+ (lin <= ih->data->lines.last) &&
+ (col >= ih->data->columns.first) &&
+ (col <= ih->data->columns.last)))
+ {
+ if (col == ih->data->columns.last && !iMatrixAuxIsFullVisibleLast(ih, IMAT_PROCESS_COL))
+ return 0;
+ if (lin == ih->data->lines.last && !iMatrixAuxIsFullVisibleLast(ih, IMAT_PROCESS_LIN))
+ return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int iupMatrixAuxIsCellVisible(Ihandle* ih, int lin, int col)
+{
+ if(((lin >= ih->data->lines.first) &&
+ (lin <= ih->data->lines.last) &&
+ (col >= ih->data->columns.first) &&
+ (col <= ih->data->columns.last)))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+void iupMatrixAuxGetVisibleCellDim(Ihandle* ih, int lin, int col, int* x, int* y, int* w, int* h)
+{
+ int i;
+
+ /* find the position where the column starts */
+ *x = ih->data->columns.sizes[0];
+ for(i = ih->data->columns.first; i < col; i++)
+ *x += ih->data->columns.sizes[i];
+
+ /* find the column size */
+ *w = ih->data->columns.sizes[col] - 1;
+
+ /* find the position where the line starts */
+ *y = ih->data->lines.sizes[0];
+ for(i = ih->data->lines.first; i < lin; i++)
+ *y += ih->data->lines.sizes[i];
+
+ /* find the line size */
+ *h = ih->data->lines.sizes[lin] - 1;
+}
+
+/* Calculate the size, in pixels, of the invisible columns/lines,
+ the left/above of the first column/line.
+ In fact the start position of the visible area.
+ Depends on the first visible column/line.
+ -> m : choose will operate on lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixAuxUpdateVisiblePos(Ihandle* ih, int m)
+{
+ char* POS;
+ int i, sb, visible_pos;
+ ImatLinColData *p;
+
+ if (m == IMAT_PROCESS_LIN)
+ {
+ p = &(ih->data->lines);
+ sb = IUP_SB_VERT;
+ POS = "POSY";
+ }
+ else
+ {
+ p = &(ih->data->columns);
+ sb = IUP_SB_HORIZ;
+ POS = "POSX";
+ }
+
+ visible_pos = 0;
+ for(i = 1; i < p->first; i++)
+ visible_pos += p->sizes[i];
+
+ if (ih->data->canvas.sb & sb)
+ {
+ float pos;
+
+ if (p->total_size)
+ {
+ while ((visible_pos + p->visible_size > p->total_size) && p->first>1)
+ {
+ /* invalid position, must recalculate first */
+ p->first--;
+ visible_pos -= p->sizes[p->first];
+ }
+
+ pos = (float)visible_pos/(float)p->total_size;
+ }
+ else
+ pos = 0;
+
+ iupMatrixAuxUpdateLast(p);
+ IupSetfAttribute(ih, POS, "%.5f", (double)pos);
+ }
+ else
+ iupMatrixAuxUpdateLast(p);
+}
+
+/* Calculate which is the last visible column/line of the matrix.
+ Depends on the first visible column/line. */
+void iupMatrixAuxUpdateLast(ImatLinColData *p)
+{
+ int i, sum = 0;
+
+ if (p->visible_size > 0)
+ {
+ /* Find which is the last column/line
+ Start in the first visible and continue adding the widths
+ up to the visible size */
+ for(i = p->first; i < p->num; i++)
+ {
+ sum += p->sizes[i];
+ if(sum >= p->visible_size)
+ break;
+ }
+
+ if (i == p->num)
+ p->last = i-1;
+ else
+ p->last = i;
+ }
+ else
+ {
+ /* There is no space for any column, set the last column as 0 */
+ p->last = 0;
+ }
+}
+
+int iupMatrixAuxGetColumnWidth(Ihandle* ih, int col)
+{
+ int width = 0, pixels = 0;
+ char* str = iupStrGetMemory(100);
+ char* value;
+
+ /* can only be called for valid columns */
+
+ sprintf(str, "WIDTH%d", col);
+ value = iupAttribGet(ih, str);
+ if (!value)
+ {
+ sprintf(str, "RASTERWIDTH%d", col);
+ value = iupAttribGet(ih, str);
+ if (value)
+ pixels = 1;
+ }
+
+ if (!value)
+ {
+ /* Use the titles to define the size */
+ if (col == 0)
+ {
+ if (!ih->data->callback_mode || ih->data->use_title_size)
+ {
+ /* find the largest title */
+ int lin, max_width = 0;
+ for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, lin, 0);
+ if (title_value)
+ {
+ iupdrvFontGetMultiLineStringSize(ih, title_value, &width, NULL);
+ if (width > max_width)
+ max_width = width;
+ }
+ }
+ width = max_width;
+ }
+ }
+ else if (ih->data->use_title_size)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, 0, col);
+ if (title_value)
+ iupdrvFontGetMultiLineStringSize(ih, title_value, &width, NULL);
+ }
+ if (width)
+ return width + IMAT_PADDING_W + IMAT_FRAME_W;
+
+ if (col != 0)
+ value = iupAttribGetStr(ih, "WIDTHDEF");
+ }
+
+ if (iupStrToInt(value, &width))
+ {
+ if (width <= 0)
+ return 0;
+ else
+ {
+ if (pixels)
+ return width + IMAT_PADDING_W + IMAT_FRAME_W;
+ else
+ {
+ int charwidth;
+ iupdrvFontGetCharSize(ih, &charwidth, NULL);
+ return iupWIDTH2RASTER(width, charwidth) + IMAT_PADDING_W + IMAT_FRAME_W;
+ }
+ }
+ }
+ return 0;
+}
+
+int iupMatrixAuxGetLineHeight(Ihandle* ih, int lin)
+{
+ int height = 0, pixels = 0;
+ char* str = iupStrGetMemory(100);
+ char* value;
+
+ /* can only be called for valid lines */
+
+ sprintf(str, "HEIGHT%d", lin);
+ value = iupAttribGet(ih, str);
+ if(!value)
+ {
+ sprintf(str, "RASTERHEIGHT%d", lin);
+ value = iupAttribGet(ih, str);
+ if(value)
+ pixels = 1;
+ }
+
+ if (!value)
+ {
+ /* Use the titles to define the size */
+ if (lin == 0)
+ {
+ if (!ih->data->callback_mode || ih->data->use_title_size)
+ {
+ /* find the highest title */
+ int col, max_height = 0;
+ for(col = 0; col < ih->data->columns.num; col++)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, 0, col);
+ if (title_value && title_value[0])
+ {
+ iupdrvFontGetMultiLineStringSize(ih, title_value, NULL, &height);
+ if (height > max_height)
+ max_height = height;
+ }
+ }
+ height = max_height;
+ }
+ }
+ else if (ih->data->use_title_size)
+ {
+ char* title_value = iupMatrixCellGetValue(ih, lin, 0);
+ if (title_value && title_value[0])
+ iupdrvFontGetMultiLineStringSize(ih, title_value, NULL, &height);
+ }
+ if (height)
+ return height + IMAT_PADDING_H + IMAT_FRAME_H;
+
+ if (lin != 0)
+ value = iupAttribGetStr(ih, "HEIGHTDEF");
+ }
+
+ if (iupStrToInt(value, &height))
+ {
+ if (height <= 0)
+ return 0;
+ else
+ {
+ if (pixels)
+ return height + IMAT_PADDING_H + IMAT_FRAME_H;
+ else
+ {
+ int charheight;
+ iupdrvFontGetCharSize(ih, NULL, &charheight);
+ return iupHEIGHT2RASTER(height, charheight) + IMAT_PADDING_H + IMAT_FRAME_H;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Fill the sizes vector with the width/heigh of all the columns/lines.
+ Calculate the value of total_size */
+static void iMatrixAuxFillSizeVec(Ihandle* ih, int m)
+{
+ int i;
+ ImatLinColData *p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ /* Calculate total width/height of the matrix and the width/height of each column */
+ p->total_size = 0;
+ for(i = 0; i < p->num; i++)
+ {
+ if (m == IMAT_PROCESS_LIN)
+ p->sizes[i] = iupMatrixAuxGetLineHeight(ih, i);
+ else
+ p->sizes[i] = iupMatrixAuxGetColumnWidth(ih, i);
+
+ if (i > 0)
+ p->total_size += p->sizes[i];
+ }
+}
+
+static void iMatrixAuxUpdateVisibleSize(Ihandle* ih, int m)
+{
+ char* D;
+ ImatLinColData *p;
+ int canvas_size;
+
+ if (m == IMAT_PROCESS_LIN)
+ {
+ D = "DY";
+ p = &(ih->data->lines);
+ canvas_size = ih->data->h;
+ }
+ else
+ {
+ D = "DX";
+ p = &(ih->data->columns);
+ canvas_size = ih->data->w;
+ }
+
+ /* Matrix useful area is the current size minus the title area */
+ p->visible_size = canvas_size - p->sizes[0];
+ if (p->visible_size > p->total_size)
+ p->visible_size = p->total_size;
+
+ if (p->total_size)
+ IupSetfAttribute(ih, D, "%f", (double)p->visible_size/(double)p->total_size);
+ else
+ IupSetAttribute(ih, D, "1.0");
+}
+
+void iupMatrixAuxCalcSizes(Ihandle* ih)
+{
+ iMatrixAuxFillSizeVec(ih, IMAT_PROCESS_COL);
+ iMatrixAuxFillSizeVec(ih, IMAT_PROCESS_LIN);
+
+ iMatrixAuxUpdateVisibleSize(ih, IMAT_PROCESS_COL);
+ iMatrixAuxUpdateVisibleSize(ih, IMAT_PROCESS_LIN);
+
+ /* when removing lines the first can be positioned after the last line */
+ if (ih->data->lines.first > ih->data->lines.num-1)
+ {
+ if (ih->data->lines.num==1)
+ ih->data->lines.first = 1;
+ else
+ ih->data->lines.first = ih->data->lines.num-1;
+ }
+ if (ih->data->columns.first > ih->data->columns.num-1)
+ {
+ if (ih->data->columns.num == 1)
+ ih->data->columns.first = 1;
+ else
+ ih->data->columns.first = ih->data->columns.num-1;
+ }
+
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ ih->data->need_calcsize = 0;
+}
+
+int iupMatrixAuxGetLinColFromXY(Ihandle* ih, int x, int y, int* l, int* c)
+{
+ int size, lin, col;
+
+ size = ih->data->columns.sizes[0]; /* always visible when non zero */
+ if (x < size)
+ col = 0; /* It is in the column of titles */
+ else
+ {
+ for(col = ih->data->columns.first; col <= ih->data->columns.last; col++) /* for all visible columns */
+ {
+ size += ih->data->columns.sizes[col];
+ if (x < size)
+ break;
+ }
+ if (col > ih->data->columns.last)
+ col = -1;
+ }
+
+ size = ih->data->lines.sizes[0]; /* always visible when non zero */
+ if (y < size)
+ lin = 0; /* It is in the line of titles */
+ else
+ {
+ for(lin = ih->data->lines.first; lin <= ih->data->lines.last; lin++) /* for all visible lines */
+ {
+ size += ih->data->lines.sizes[lin];
+ if (y < size)
+ break;
+ }
+ if(lin > ih->data->lines.last)
+ lin = -1;
+ }
+
+ if (col == -1 || lin == -1)
+ return 0;
+
+ *l = lin;
+ *c = col;
+ return 1;
+}
+
+int iupMatrixAuxCallLeaveCellCb(Ihandle* ih)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "LEAVEITEM_CB");
+ if(cb)
+ return cb(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ return IUP_DEFAULT;
+}
+
+void iupMatrixAuxCallEnterCellCb(Ihandle* ih)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "ENTERITEM_CB");
+ if (cb)
+ cb(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+}
+
+int iupMatrixAuxCallEditionCbLinCol(Ihandle* ih, int lin, int col, int mode, int update)
+{
+ IFniiii cb;
+
+ if (iupAttribGetBoolean(ih, "READONLY"))
+ return IUP_IGNORE;
+
+ cb = (IFniiii)IupGetCallback(ih, "EDITION_CB");
+ if(cb)
+ return cb(ih, lin, col, mode, update);
+ return IUP_DEFAULT;
+}
diff --git a/iup/srccontrols/matrix/iupmat_aux.h b/iup/srccontrols/matrix/iupmat_aux.h
new file mode 100755
index 0000000..296c1f5
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_aux.h
@@ -0,0 +1,37 @@
+/** \file
+ * \brief iupmatrix control
+ * auxiliary functions.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_AUX_H
+#define __IUPMAT_AUX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixAuxIsCellFullVisible(Ihandle* ih, int lin, int col);
+int iupMatrixAuxIsCellVisible(Ihandle* ih, int lin, int col);
+void iupMatrixAuxGetVisibleCellDim (Ihandle* ih, int lin, int col, int* x, int* y, int* w, int* h);
+
+void iupMatrixAuxCalcSizes(Ihandle* ih);
+
+void iupMatrixAuxUpdateVisiblePos(Ihandle* ih, int m);
+void iupMatrixAuxUpdateLast(ImatLinColData *p);
+
+int iupMatrixAuxGetColumnWidth(Ihandle* ih, int col);
+int iupMatrixAuxGetLineHeight (Ihandle* ih, int lin);
+
+int iupMatrixAuxGetLinColFromXY (Ihandle* ih, int x, int y, int* l, int* c);
+
+int iupMatrixAuxCallLeaveCellCb (Ihandle* ih);
+void iupMatrixAuxCallEnterCellCb (Ihandle* ih);
+int iupMatrixAuxCallEditionCbLinCol(Ihandle* ih, int lin, int col, int mode, int update);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_cd.h b/iup/srccontrols/matrix/iupmat_cd.h
new file mode 100755
index 0000000..1a10f2b
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_cd.h
@@ -0,0 +1,25 @@
+/** \file
+ * \brief iupmatrix. CD help macros.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_CD_H
+#define __IUPMAT_CD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IUPMAT_LINE(_ih,_x1,_y1,_x2,_y2) cdCanvasLine((_ih)->data->cddbuffer, (_x1), iupMatrixInvertYAxis(_ih, _y1), (_x2), iupMatrixInvertYAxis(_ih, _y2))
+#define IUPMAT_VERTEX(_ih,_x,_y) cdCanvasVertex((_ih)->data->cddbuffer, (_x), iupMatrixInvertYAxis(_ih, _y))
+#define IUPMAT_BOX(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasBox((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+#define IUPMAT_RECT(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasRect((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+#define IUPMAT_CLIPAREA(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasClipArea((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+#define IUPMAT_TEXT(_ih,_x,_y,_text) cdCanvasText((_ih)->data->cddbuffer, (_x), iupMatrixInvertYAxis(_ih, _y), (_text))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_colres.c b/iup/srccontrols/matrix/iupmat_colres.c
new file mode 100755
index 0000000..d44b7df
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_colres.c
@@ -0,0 +1,182 @@
+/** \file
+ * \brief iupmatrix column resize
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Interactive Column Resize Functions and WIDTH/HEIGHT change */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_colres.h"
+#include "iupmat_draw.h"
+
+
+#define IMAT_COLRES_TOL 3
+#define IMAT_RESIZE_COLOR 0x666666L
+
+
+/* Verify if the mouse is in the intersection between two of column titles,
+ if so the resize is started */
+int iupMatrixColResStart(Ihandle* ih, int x, int y)
+{
+ if (ih->data->lines.sizes[0] && y < ih->data->lines.sizes[0] && iupAttribGetBoolean(ih, "RESIZEMATRIX"))
+ {
+ int size, col;
+
+ /* Check if is the column of titles */
+ size = ih->data->columns.sizes[0];
+ if (abs(size-x) < IMAT_COLRES_TOL)
+ {
+ ih->data->colres_drag_col_start_x = 0;
+ ih->data->colres_dragging = 1;
+ ih->data->colres_drag_col_last_x = -1;
+ ih->data->colres_drag_col = 0;
+ return 1;
+ }
+ else
+ {
+ /* find the column */
+ for(col = ih->data->columns.first; col <= ih->data->columns.last; col++)
+ {
+ ih->data->colres_drag_col_start_x = size;
+ size += ih->data->columns.sizes[col];
+ if (abs(size-x) < IMAT_COLRES_TOL)
+ {
+ ih->data->colres_dragging = 1;
+ ih->data->colres_drag_col_last_x = -1;
+ ih->data->colres_drag_col = col;
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void iupMatrixColResFinish(Ihandle* ih, int x)
+{
+ char str[100];
+ int width = x - ih->data->colres_drag_col_start_x;
+ if (width < 0)
+ width = 0;
+
+ /* delete feedback */
+ if (ih->data->colres_drag_col_last_x != -1)
+ {
+ int y1 = ih->data->lines.sizes[0]; /* from the bottom of the line of titles */
+ int y2 = ih->data->h-1; /* to the bottom of the matrix */
+
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_XOR);
+ cdCanvasForeground(ih->data->cdcanvas, IMAT_RESIZE_COLOR);
+ cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y1),
+ ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y2));
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_REPLACE);
+ }
+
+ ih->data->colres_dragging = 0;
+
+ sprintf(str, "RASTERWIDTH%d", ih->data->colres_drag_col);
+ iupAttribSetInt(ih, str, width-IMAT_PADDING_W-IMAT_FRAME_W);
+ sprintf(str, "WIDTH%d", ih->data->colres_drag_col);
+ iupAttribSetStr(ih, str, NULL);
+
+ ih->data->need_calcsize = 1;
+ iupMatrixDraw(ih, 0);
+}
+
+/* Change the column width interactively, just change the line in the screen.
+ When the user finishes the drag, the iupMatrixColResFinish function is called
+ to truly change the column width. */
+void iupMatrixColResMove(Ihandle* ih, int x)
+{
+ int y1, y2;
+
+ int width = x - ih->data->colres_drag_col_start_x;
+ if (width < 0)
+ return;
+
+ y1 = ih->data->lines.sizes[0]; /* from the bottom of the line of titles */
+ y2 = ih->data->h-1; /* to the bottom of the matrix */
+
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_XOR);
+ cdCanvasForeground(ih->data->cdcanvas, IMAT_RESIZE_COLOR);
+
+ /* If it is not the first time, move old line */
+ if (ih->data->colres_drag_col_last_x != -1)
+ {
+ cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y1),
+ ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y2));
+ }
+
+ cdCanvasLine(ih->data->cdcanvas, x, iupMatrixInvertYAxis(ih, y1),
+ x, iupMatrixInvertYAxis(ih, y2));
+
+ ih->data->colres_drag_col_last_x = x;
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_REPLACE);
+}
+
+
+static void iMatrixColResResetMatrixCursor(Ihandle* ih)
+{
+ char *cursor = iupAttribGet(ih, "_IUPMAT_CURSOR");
+ if (cursor)
+ {
+ IupStoreAttribute(ih, "CURSOR", cursor);
+ iupAttribSetStr(ih, "_IUPMAT_CURSOR", NULL);
+ }
+}
+
+/* Change the cursor when it passes over a group of the column titles. */
+void iupMatrixColResCheckChangeCursor(Ihandle* ih, int x, int y)
+{
+ if(ih->data->lines.sizes[0] && y < ih->data->lines.sizes[0] && iupAttribGetBoolean(ih, "RESIZEMATRIX"))
+ {
+ /* It is in the column titles area and the resize mode is on */
+ int found = 0, size, col;
+
+ size = ih->data->columns.sizes[0];
+ if (abs(size - x) < IMAT_COLRES_TOL)
+ found = 1; /* line titles */
+ else
+ {
+ for(col = ih->data->columns.first; col <= ih->data->columns.last && !found; col++)
+ {
+ size += ih->data->columns.sizes[col];
+ if(abs(size - x) < IMAT_COLRES_TOL)
+ found = 1;
+ }
+ }
+
+ if (found)
+ {
+ if (!iupAttribGet(ih, "_IUPMAT_CURSOR"))
+ iupAttribStoreStr(ih, "_IUPMAT_CURSOR", IupGetAttribute(ih, "CURSOR"));
+ IupSetAttribute(ih, "CURSOR", "RESIZE_W");
+ }
+ else /* It is in the empty area after the last column */
+ iMatrixColResResetMatrixCursor(ih);
+ }
+ else
+ iMatrixColResResetMatrixCursor(ih);
+}
+
+int iupMatrixColResIsResizing(Ihandle* ih)
+{
+ return ih->data->colres_dragging;
+}
+
diff --git a/iup/srccontrols/matrix/iupmat_colres.h b/iup/srccontrols/matrix/iupmat_colres.h
new file mode 100755
index 0000000..ba7f23d
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_colres.h
@@ -0,0 +1,24 @@
+/** \file
+ * \brief iupmatrix column resize.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_COLRES_H
+#define __IUPMAT_COLRES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixColResStart (Ihandle* ih, int x, int y);
+void iupMatrixColResFinish (Ihandle* ih, int x);
+void iupMatrixColResMove (Ihandle* ih, int x);
+void iupMatrixColResCheckChangeCursor(Ihandle* ih, int x, int y);
+int iupMatrixColResIsResizing (Ihandle* ih);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_def.h b/iup/srccontrols/matrix/iupmat_def.h
new file mode 100755
index 0000000..d45acde
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_def.h
@@ -0,0 +1,122 @@
+/** \file
+ * \brief iupmatrix. definitions.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_DEF_H
+#define __IUPMAT_DEF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define IMAT_PROCESS_COL 1 /* Process the columns */
+#define IMAT_PROCESS_LIN 2 /* Process the lines */
+
+/***************************************************************************/
+/* Decoration size in pixels */
+/***************************************************************************/
+#define IMAT_PADDING_W 6
+#define IMAT_PADDING_H 6
+#define IMAT_FRAME_W 2
+#define IMAT_FRAME_H 2
+
+/* Cell flags */
+#define IUPMAT_FONT 1 /* Has FONTL:C attribute */
+#define IUPMAT_FGCOLOR 2 /* Has FGCOLORL:C attribute */
+#define IUPMAT_BGCOLOR 4 /* Has BGCOLORL:C attribute */
+#define IUPMAT_MARK 8 /* Is marked */
+#define IUPMAT_FRAMEHCOLOR 16 /* Has FRAMEHORIZCOLORL:C */
+#define IUPMAT_FRAMEVCOLOR 32 /* Has FRAMEVERTCOLORL:C */
+
+/***************************************************************************/
+/* Structures stored in each matrix */
+/***************************************************************************/
+typedef struct _ImatCell
+{
+ char *value; /* Cell value */
+ unsigned char flags;
+} ImatCell;
+
+
+typedef struct _ImatLinColData
+{
+ int* sizes; /* Width/height of the columns/lines (allocated after map) */
+ unsigned char* flags; /* Attribute flags for the columns/lines (allocated after map) */
+
+ int num; /* Number of columns/lines in the matrix, default/minimum=1, always includes the title */
+ int num_alloc; /* Number of columns/lines allocated, default=5 */
+
+ int first; /* First visible column/line */
+ int last; /* Last visible column/line */
+
+ /* used to configure the scrollbar */
+ int total_size; /* Sum of the widths/heights of the columns/lines, not including the title */
+ int visible_size; /* Width/height of the visible window, not including the title */
+
+ int focus_cell; /* index of the current cell */
+} ImatLinColData;
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+
+ ImatCell** cells; /* Cell value, this will be NULL if in callback mode (allocated after map) */
+
+ Ihandle* texth; /* Text handle */
+ Ihandle* droph; /* Dropdown handle */
+ Ihandle* datah; /* Current active edition element, may be equal to texth or droph */
+
+ cdCanvas* cddbuffer;
+ cdCanvas* cdcanvas;
+
+ ImatLinColData lines;
+ ImatLinColData columns;
+
+ int has_focus;
+ int w, h; /* canvas size */
+ int callback_mode;
+ int use_title_size; /* use title contents when calculating cell size */
+ int need_calcsize;
+ int first_redraw;
+
+ /* attributes */
+ int mark_continuous, mark_mode, mark_multiple;
+ int checkframecolor;
+
+ /* Mouse and Keyboard AUX */
+ int leftpressed; /* left mouse button is pressed */
+ int homekeycount, endkeycount; /* numbers of times that key was pressed */
+
+ /* ColRes AUX */
+ int colres_dragging, /* indicates if it is being made a column resize */
+ colres_drag_col, /* column being resized */
+ colres_drag_col_start_x, /* position of the start of the column being resized */
+ colres_drag_col_last_x; /* previous position */
+
+ /* Mark AUX */
+ int mark_lin1, mark_col1, /* used to store the start cell when a block is being marked */
+ mark_lin2, mark_col2, /* used to store the end cell when a block was marked */
+ mark_full1, /* indicate if full lines or columns is being selected */
+ mark_full2;
+
+ /* Draw AUX, valid only after iupMatrixPrepareDrawData */
+ sIFnii font_cb;
+ IFniiIII fgcolor_cb;
+ IFniiIII bgcolor_cb;
+ char *bgcolor, *bgcolor_parent, *fgcolor, *font; /* not need to free */
+};
+
+
+int iupMatrixIsValid(Ihandle* ih, int check_cells);
+
+#define iupMatrixInvertYAxis(_ih, _y) ((_ih)->data->h-1 - (_y))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_draw.c b/iup/srccontrols/matrix/iupmat_draw.c
new file mode 100755
index 0000000..7c53fb5
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_draw.c
@@ -0,0 +1,866 @@
+/** \file
+ * \brief iupmatrix control
+ * draw functions
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef CD_NO_OLD_INTERFACE
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_cdutil.h"
+#include "iup_image.h"
+
+#include "iupmat_def.h"
+#include "iupmat_cd.h"
+#include "iupmat_draw.h"
+#include "iupmat_aux.h"
+#include "iupmat_getset.h"
+#include "iupmat_mark.h"
+
+
+/* Color attenuation factor in a marked cell, 20% darker */
+#define IMAT_ATENUATION(_x) ((unsigned char)(((_x)*8)/10))
+
+/* Text alignment that will be draw. Used by iMatrixDrawCellValue */
+#define IMAT_T_CENTER 1
+#define IMAT_T_LEFT 2
+#define IMAT_T_RIGHT 3
+
+#define IMAT_CD_INACTIVE_FGCOLOR 0x666666L
+
+#define IMAT_COMBOBOX_W 16
+
+
+typedef int (*IFniiiiiiC)(Ihandle *h, int lin, int col,int x1, int x2, int y1, int y2, cdCanvas* cnv);
+
+
+/**************************************************************************/
+/* Private functions */
+/**************************************************************************/
+
+
+static int iMatrixDrawGetColAlignment(Ihandle* ih, int col, char* str)
+{
+ char* align;
+ sprintf(str, "ALIGNMENT%d", col);
+ align = iupAttribGet(ih, str);
+ if (!align)
+ {
+ if (col == 0)
+ return IMAT_T_LEFT;
+ else
+ return IMAT_T_CENTER;
+ }
+ else if (iupStrEqualNoCase(align, "ARIGHT"))
+ return IMAT_T_RIGHT;
+ else if(iupStrEqualNoCase(align, "ACENTER"))
+ return IMAT_T_CENTER;
+ else
+ return IMAT_T_LEFT;
+}
+
+static int iMatrixDrawCallDrawCB(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, IFniiiiiiC draw_cb)
+{
+ int ret;
+ cdCanvas* old_cnv;
+
+ IUPMAT_CLIPAREA(ih, x1, x2, y1, y2);
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
+
+ old_cnv = cdActiveCanvas();
+ if (old_cnv != ih->data->cddbuffer) /* backward compatibility code */
+ cdActivate(ih->data->cddbuffer);
+
+ ret = draw_cb(ih, lin, col, x1, x2, iupMatrixInvertYAxis(ih, y1), iupMatrixInvertYAxis(ih, y2), ih->data->cddbuffer);
+
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+
+ if (old_cnv && old_cnv != ih->data->cddbuffer) /* backward compatibility code */
+ {
+ cdActivate(old_cnv);
+ cdCanvasActivate(ih->data->cddbuffer);
+ }
+
+ if (ret == IUP_DEFAULT)
+ return 0;
+
+ return 1;
+}
+
+/* Change the CD foreground color, for the selected color to draw a cell with
+ its FOREGROUND COLOR. This involves checking if there is a color attribute
+ that cell. If no, uses a color attribute for the line, else if no for the
+ column, else if no for the entire matrix. Finally, if not find any of
+ these, use the default color.
+ -> lin, col - cell coordinates, in IUP format - i.e., l,l represents the left
+ top cell of the matrix; lin and col values = 0 represents the
+ title lines and columns.
+ -> mark - indicate if a cell is marked. If yes, its color is attenuated.
+*/
+static unsigned long iMatrixDrawSetFgColor(Ihandle* ih, int lin, int col, int mark)
+{
+ unsigned char r = 0, g = 0, b = 0;
+ iupMatrixGetFgRGB(ih, lin, col, &r, &g, &b);
+
+ if (mark)
+ {
+ r = IMAT_ATENUATION(r);
+ g = IMAT_ATENUATION(g);
+ b = IMAT_ATENUATION(b);
+ }
+
+ return cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(r, g, b));
+}
+
+/* Change the CD foreground color, for the selected color to draw a cell with
+ its BACKGROUND COLOR. This involves checking if there is a color attribute
+ that cell. If no, uses a color attribute for the line, else if no for the
+ column, else if no for the entire matrix. Finally, if not find any of
+ these, use the default color.
+ -> lin, col - cell coordinates, in IUP format - i.e., l,l represents the left
+ top cell of the matrix; lin and col values = 0 represents the
+ title lines and columns.
+ -> mark - indicate if a cell is marked. If yes, its color is attenuated.
+*/
+static unsigned long iMatrixDrawSetBgColor(Ihandle* ih, int lin, int col, int mark, int active)
+{
+ unsigned char r = 255, g = 255, b = 255;
+
+ iupMatrixGetBgRGB(ih, lin, col, &r, &g, &b);
+
+ if (mark)
+ {
+ r = IMAT_ATENUATION(r);
+ g = IMAT_ATENUATION(g);
+ b = IMAT_ATENUATION(b);
+ }
+
+ if (!active)
+ {
+ r = cdIupLIGTHER(r);
+ g = cdIupLIGTHER(g);
+ b = cdIupLIGTHER(b);
+ }
+
+ return cdCanvasForeground(ih->data->cddbuffer, cdEncodeColor(r, g, b));
+}
+
+static void iMatrixDrawFrameHorizLineCell(Ihandle* ih, int lin, int col, int x1, int x2, int y, long framecolor, char* str)
+{
+ if (ih->data->checkframecolor && (ih->data->callback_mode || ih->data->cells[lin][col].flags & IUPMAT_FRAMEHCOLOR))
+ {
+ unsigned char r,g,b;
+ sprintf(str, "FRAMEHORIZCOLOR%d:%d", lin, col);
+ if (iupStrToRGB(iupAttribGet(ih, str), &r, &g, &b))
+ framecolor = cdEncodeColor(r, g, b);
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+ IUPMAT_LINE(ih, x1, y, x2, y); /* bottom horizontal line */
+}
+
+static void iMatrixDrawFrameVertLineCell(Ihandle* ih, int lin, int col, int x, int y1, int y2, long framecolor, char* str)
+{
+ if (ih->data->checkframecolor && (ih->data->callback_mode || ih->data->cells[lin][col].flags & IUPMAT_FRAMEVCOLOR))
+ {
+ unsigned char r,g,b;
+ sprintf(str, "FRAMEVERTCOLOR%d:%d", lin, col);
+ if (iupStrToRGB(iupAttribGet(ih, str), &r, &g, &b))
+ framecolor = cdEncodeColor(r, g, b);
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+ IUPMAT_LINE(ih, x, y1, x, y2); /* right vertical line */
+}
+
+static void iMatrixDrawFrameRectTitle(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor, char* str)
+{
+ /* avoid drawing over the frame of the next cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ iMatrixDrawFrameVertLineCell(ih, lin, col, x2, y1, y2, framecolor, str); /* right vertical line */
+ if (col==0)
+ {
+ IUPMAT_LINE(ih, x1, y1, x1, y2); /* left vertical line, reuse Foreground */
+ x1++;
+ }
+ else if (col==1 && ih->data->columns.sizes[0] == 0)
+ {
+ /* If does not have line titles then draw the left line of the cell frame */
+ IUPMAT_LINE(ih, x1, y1, x1, y2-1);
+ x1++;
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); /* Titles have a white line near the frame */
+ IUPMAT_LINE(ih, x1, y1+1, x1, y2-1);
+
+ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2, y2, framecolor, str); /* bottom horizontal line */
+ if (lin==0)
+ {
+ IUPMAT_LINE(ih, x1, y1, x2, y1); /* top horizontal line, reuse Foreground */
+ y1++;
+ }
+ else if (lin==1 && ih->data->lines.sizes[0] == 0)
+ {
+ /* If does not have column titles then draw the top line of the cell frame */
+ IUPMAT_LINE(ih, x1, y1, x2-1, y1);
+ y1++;
+ }
+
+ cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); /* Titles have a white line near the frame */
+ IUPMAT_LINE(ih, x1, y1, x2-1, y1);
+}
+
+static void iMatrixDrawFrameRectCell(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor, char* str)
+{
+ if (col==1 && ih->data->columns.sizes[0] == 0)
+ {
+ /* If does not have line titles then draw the left line of the cell frame */
+ iMatrixDrawFrameVertLineCell(ih, lin, col, x1, y1, y2-1-1, framecolor, str);
+ }
+
+ if (lin==1 && ih->data->lines.sizes[0] == 0)
+ {
+ /* If does not have column titles then draw the top line of the cell frame */
+ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2-1-1, y1, framecolor, str);
+ }
+
+ /* bottom line */
+ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2-1, y2-1, framecolor, str);
+
+ /* rigth line */
+ iMatrixDrawFrameVertLineCell(ih, lin, col, x2-1, y1, y2-1, framecolor, str);
+}
+
+static int iMatrixDrawSortSign(Ihandle* ih, int x2, int y1, int y2, int col, int active, char* str)
+{
+ int yc;
+ char* sort;
+
+ sprintf(str, "SORTSIGN%d", col);
+ sort = iupAttribGet(ih, str);
+ if (!sort || iupStrEqualNoCase(sort, "NO"))
+ return 0;
+
+ /* Remove the space between text and cell frame */
+ x2 -= IMAT_PADDING_W/2 + IMAT_FRAME_W/2;
+
+ /* Set the color used to draw the text */
+ if (active)
+ cdCanvasForeground(ih->data->cddbuffer, IMAT_CD_INACTIVE_FGCOLOR);
+ else
+ iMatrixDrawSetFgColor(ih, 0, col, 0);
+
+ yc = (int)( (y1 + y2 ) / 2.0 - .5);
+
+ cdCanvasBegin(ih->data->cddbuffer, CD_FILL);
+
+ if (iupStrEqualNoCase(sort, "DOWN"))
+ {
+ IUPMAT_VERTEX(ih, x2 - 5, yc + 2);
+ IUPMAT_VERTEX(ih, x2 - 1, yc - 2);
+ IUPMAT_VERTEX(ih, x2 - 9, yc - 2);
+ }
+ else
+ {
+ IUPMAT_VERTEX(ih, x2 - 1, yc + 2);
+ IUPMAT_VERTEX(ih, x2 - 9, yc + 2);
+ IUPMAT_VERTEX(ih, x2 - 5, yc - 2);
+ }
+
+ cdCanvasEnd(ih->data->cddbuffer);
+ return 1;
+}
+
+static void iMatrixDrawComboFeedback(Ihandle* ih, int x2, int y1, int y2, int active, long framecolor)
+{
+ int xh2, yh2, x1;
+
+ /* feedback area */
+ x2 -= IMAT_PADDING_W/2 + IMAT_FRAME_W/2;
+ x1 = x2 - IMAT_COMBOBOX_W;
+ y1 += IMAT_PADDING_H/2 + IMAT_FRAME_H/2;
+ y2 -= IMAT_PADDING_H/2 + IMAT_FRAME_H/2;
+
+ /* feedback background */
+ iMatrixDrawSetBgColor(ih, 0, 0, 0, active);
+ IUPMAT_BOX(ih, x1, x2, y1, y2);
+
+ /* feedback frame */
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+ IUPMAT_RECT(ih, x1, x2, y1, y2);
+
+ /* feedback arrow */
+ xh2 = x2 - IMAT_COMBOBOX_W / 2;
+ yh2 = y2 - (y2 - y1) / 2;
+
+ cdCanvasBegin(ih->data->cddbuffer, CD_FILL);
+ IUPMAT_VERTEX(ih, xh2, yh2 + 3);
+ IUPMAT_VERTEX(ih, xh2 + 4, yh2 - 1);
+ IUPMAT_VERTEX(ih, xh2 - 4, yh2 - 1);
+ cdCanvasEnd(ih->data->cddbuffer);
+}
+
+static void iMatrixDrawBackground(Ihandle* ih, int x1, int x2, int y1, int y2, int marked, int active, int lin, int col)
+{
+ /* avoid drawing over the frame of the next cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ iMatrixDrawSetBgColor(ih, lin, col, marked, active);
+ IUPMAT_BOX(ih, x1, x2, y1, y2);
+}
+
+/* Put the cell contents in the screen, using the specified color and alignment.
+ -> y1, y2 : vertical limits of the cell
+ -> x1, x2 : horizontal limits of the complete cell
+ -> alignment : alignment type (horizontal) assigned to the text. The options are:
+ [IMAT_T_CENTER,IMAT_T_LEFT,IMAT_T_RIGHT]
+ -> marked : mark state
+ -> lin, col - cell coordinates */
+static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, int alignment, int marked, int active, int lin, int col, IFniiiiiiC draw_cb)
+{
+ char *text;
+
+ /* avoid drawing over the frame of the next cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ /* avoid drawing over the frame of the cell */
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+
+ if (lin==0 || col==0)
+ {
+ /* avoid drawing over the frame of the cell */
+ x1 += IMAT_FRAME_W/2;
+ y1 += IMAT_FRAME_H/2;
+
+ if (col==0) x1 += IMAT_FRAME_W/2;
+ if (lin==0) y1 += IMAT_FRAME_H/2;
+ }
+ else if ((col==1 && ih->data->columns.sizes[0] == 0) || (lin==1 && ih->data->lines.sizes[0] == 0))
+ {
+ /* avoid drawing over the frame of the cell */
+ x1 += IMAT_FRAME_W/2;
+ y1 += IMAT_FRAME_H/2;
+ }
+
+ if (draw_cb && !iMatrixDrawCallDrawCB(ih, lin, col, x1, x2, y1, y2, draw_cb))
+ return;
+
+ text = iupMatrixCellGetValue(ih, lin, col);
+
+ /* Put the text */
+ if (text && *text)
+ {
+ int num_line, line_height, total_height;
+ int charheight, ypos;
+
+ num_line = iupStrLineCount(text);
+ iupdrvFontGetCharSize(ih, NULL, &charheight);
+
+ line_height = charheight;
+ total_height = (line_height + IMAT_PADDING_H/2) * num_line - IMAT_PADDING_H/2 - IMAT_FRAME_H/2;
+
+ if (lin==0)
+ {
+ int text_w;
+ iupdrvFontGetMultiLineStringSize(ih, text, &text_w, NULL);
+ if (text_w > x2 - x1 + 1 - IMAT_PADDING_W - IMAT_FRAME_W)
+ alignment = IMAT_T_LEFT;
+ }
+
+ /* Set the color used to draw the text */
+ if (!active)
+ cdCanvasForeground(ih->data->cddbuffer, IMAT_CD_INACTIVE_FGCOLOR);
+ else
+ iMatrixDrawSetFgColor(ih, lin, col, marked);
+
+ /* Set the clip area to the cell region informed, the text maybe greatter than the cell */
+ IUPMAT_CLIPAREA(ih, x1, x2, y1, y2);
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
+
+ cdCanvasNativeFont(ih->data->cddbuffer, iupMatrixGetFont(ih, lin, col));
+
+ /* Create an space between text and cell frame */
+ x1 += IMAT_PADDING_W/2; x2 -= IMAT_PADDING_W/2;
+ y1 += IMAT_PADDING_H/2; y2 -= IMAT_PADDING_H/2;
+
+ if (alignment == IMAT_T_CENTER)
+ cdCanvasTextAlignment(ih->data->cddbuffer, CD_CENTER);
+ else if(alignment == IMAT_T_LEFT)
+ cdCanvasTextAlignment(ih->data->cddbuffer, CD_WEST);
+ else
+ cdCanvasTextAlignment(ih->data->cddbuffer, CD_EAST);
+
+ if (num_line == 1)
+ {
+ ypos = (int)((y1 + y2) / 2.0 - 0.5);
+
+ /* Put the text */
+ if (alignment == IMAT_T_CENTER)
+ IUPMAT_TEXT(ih, (x1 + x2) / 2, ypos, text);
+ else if(alignment == IMAT_T_LEFT)
+ IUPMAT_TEXT(ih, x1, ypos, text);
+ else
+ IUPMAT_TEXT(ih, x2, ypos, text);
+ }
+ else
+ {
+ int i;
+ char *p, *q, *newtext;
+
+ newtext = iupStrDup(text);
+ p = newtext;
+
+ /* Get the position of the first text to be put in the screen */
+ ypos = (int)( (y1 + y2) / 2.0 - 0.5) - total_height/2 + line_height/2;
+
+ for(i = 0; i < num_line; i++)
+ {
+ q = strchr(p, '\n');
+ if (q) *q = 0; /* Cut the string to contain only one line */
+
+ /* Draw the text */
+ if(alignment == IMAT_T_CENTER)
+ IUPMAT_TEXT(ih, (x1 + x2) / 2, ypos, p);
+ else if(alignment == IMAT_T_LEFT)
+ IUPMAT_TEXT(ih, x1, ypos, p);
+ else
+ IUPMAT_TEXT(ih, x2, ypos, p);
+
+ /* Advance the string */
+ if (q) p = q + 1;
+
+ /* Advance a line */
+ ypos += line_height + IMAT_PADDING_H/2;
+ }
+
+ free(newtext);
+ }
+
+ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+ }
+}
+
+static void iMatrixDrawTitleCorner(Ihandle* ih)
+{
+ char str[100];
+ long framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ int active = iupdrvIsActive(ih);
+ IFniiiiiiC draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ iMatrixDrawBackground(ih, 0, ih->data->columns.sizes[0], 0, ih->data->lines.sizes[0], 0, active, 0, 0);
+
+ iMatrixDrawFrameRectTitle(ih, 0, 0, 0, ih->data->columns.sizes[0], 0, ih->data->lines.sizes[0], framecolor, str);
+
+ iMatrixDrawCellValue(ih, 0, ih->data->columns.sizes[0], 0, ih->data->lines.sizes[0], IMAT_T_CENTER, 0, active, 0, 0, draw_cb);
+}
+
+static void iMatrixDrawMatrix(Ihandle* ih)
+{
+ iupMatrixPrepareDrawData(ih);
+
+ /* fill the background because there will be empty cells */
+ if ((ih->data->lines.num == 1) || (ih->data->columns.num == 1))
+ {
+ cdCanvasBackground(ih->data->cddbuffer, cdIupConvertColor(ih->data->bgcolor_parent));
+ cdCanvasClear(ih->data->cddbuffer);
+ }
+
+ /* Draw the corner between line and column titles, if necessary */
+ if (ih->data->lines.sizes[0] && ih->data->columns.sizes[0])
+ iMatrixDrawTitleCorner(ih);
+
+ /* If there are columns, then draw their titles */
+ iupMatrixDrawColumnTitle(ih, ih->data->columns.first, ih->data->columns.last);
+
+ /* If there are lines, then draw their titles */
+ iupMatrixDrawLineTitle(ih, ih->data->lines.first, ih->data->lines.last);
+
+ /* If there are cells in the matrix, then draw them */
+ if ((ih->data->lines.num > 1) && (ih->data->columns.num > 1))
+ iupMatrixDrawCells(ih, ih->data->lines.first, ih->data->columns.first,
+ ih->data->lines.last, ih->data->columns.last);
+}
+
+static void iMatrixDrawFocus(Ihandle* ih)
+{
+ int x1, y1, x2, y2, dx, dy;
+
+ if (iupAttribGetBoolean(ih, "HIDEFOCUS"))
+ return;
+
+ if (!iupMatrixAuxIsCellVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ return;
+
+ iupMatrixAuxGetVisibleCellDim(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, &x1, &y1, &dx, &dy);
+
+ x2 = x1 + dx - 1;
+ y2 = y1 + dy - 1;
+
+ if (ih->data->columns.focus_cell == 1 && ih->data->columns.sizes[0] == 0)
+ x1++;
+ if (ih->data->lines.focus_cell == 1 && ih->data->lines.sizes[0] == 0)
+ y1++;
+
+ cdIupDrawFocusRect(ih, ih->data->cdcanvas, x1, iupMatrixInvertYAxis(ih, y1), x2, iupMatrixInvertYAxis(ih, y2));
+}
+
+
+/**************************************************************************/
+/* Exported functions */
+/**************************************************************************/
+
+
+/* Draw the line titles, visible, between lin and lastlin, include it.
+ Line titles marked will be draw with the appropriate feedback.
+ -> lin1 - First line to have its title drawn
+ -> lin2 - Last line to have its title drawn */
+void iupMatrixDrawLineTitle(Ihandle* ih, int lin1, int lin2)
+{
+ int x1, y1, x2, y2;
+ int lin, alignment, active;
+ char str[100];
+ long framecolor;
+ IFniiiiiiC draw_cb;
+
+ if (!ih->data->columns.sizes[0])
+ return;
+
+ if (lin1 > ih->data->lines.last ||
+ lin2 < ih->data->lines.first)
+ return;
+
+ if (lin1 < ih->data->lines.first)
+ lin1 = ih->data->lines.first;
+ if (lin2 > ih->data->lines.last)
+ lin2 = ih->data->lines.last;
+
+ /* Start the position of the line title */
+ x1 = 0;
+ x2 = ih->data->columns.sizes[0];
+
+ y1 = ih->data->lines.sizes[0];
+ for(lin = ih->data->lines.first; lin < lin1; lin++)
+ y1 += ih->data->lines.sizes[lin];
+
+ framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ active = iupdrvIsActive(ih);
+ draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ alignment = iMatrixDrawGetColAlignment(ih, 0, str);
+
+ /* Draw the titles */
+ for(lin = lin1; lin <= lin2; lin++)
+ {
+ /* If it is a hidden line (size = 0), don't draw the title */
+ if(ih->data->lines.sizes[lin] == 0)
+ continue;
+
+ y2 = y1 + ih->data->lines.sizes[lin];
+
+ /* If it doesn't have title, the loop just calculate the final position */
+ if (ih->data->columns.sizes[0])
+ {
+ int marked = iupMatrixLineIsMarked(ih, lin);
+
+ iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, lin, 0);
+
+ iMatrixDrawFrameRectTitle(ih, lin, 0, x1, x2, y1, y2, framecolor, str);
+
+ iMatrixDrawCellValue(ih, x1, x2, y1, y2, alignment, marked, active, lin, 0, draw_cb);
+ }
+
+ y1 = y2;
+ }
+}
+
+/* Draw the column titles, visible, between col and lastcol, include it.
+ Column titles marked will be draw with the appropriate feedback.
+ -> col1 - First column to have its title drawn
+ -> col2 - Last column to have its title drawn */
+void iupMatrixDrawColumnTitle(Ihandle* ih, int col1, int col2)
+{
+ int x1, y1, x2, y2;
+ int col, active;
+ char str[100];
+ long framecolor;
+ IFniiiiiiC draw_cb;
+
+ if (!ih->data->lines.sizes[0])
+ return;
+
+ if (col1 > ih->data->columns.last ||
+ col2 < ih->data->columns.first)
+ return;
+
+ if (col1 < ih->data->columns.first)
+ col1 = ih->data->columns.first;
+ if (col2 > ih->data->columns.last)
+ col2 = ih->data->columns.last;
+
+ /* Start the position of the first column title */
+ y1 = 0;
+ y2 = ih->data->lines.sizes[0];
+
+ x1 = ih->data->columns.sizes[0];
+ for(col = ih->data->columns.first; col < col1; col++)
+ x1 += ih->data->columns.sizes[col];
+
+ framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ active = iupdrvIsActive(ih);
+ draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ /* Draw the titles */
+ for(col = col1; col <= col2; col++)
+ {
+ /* If it is an hide column (size = 0), no draw the title */
+ if(ih->data->columns.sizes[col] == 0)
+ continue;
+
+ x2 = x1 + ih->data->columns.sizes[col];
+
+ /* If it doesn't have title, the loop just calculate the final position */
+ if (ih->data->lines.sizes[0])
+ {
+ int sort = 0;
+ int marked = iupMatrixColumnIsMarked(ih, col);
+
+ iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, 0, col);
+
+ iMatrixDrawFrameRectTitle(ih, 0, col, x1, x2, y1, y2, framecolor, str);
+
+ if (iMatrixDrawSortSign(ih, x2, y1, y2, col, active, str))
+ sort = IMAT_COMBOBOX_W; /* same space is used by the sort sign */
+
+ iMatrixDrawCellValue(ih, x1, x2-sort, y1, y2, IMAT_T_CENTER, marked, active, 0, col, draw_cb);
+ }
+
+ x1 = x2;
+ }
+}
+
+/* Redraw a block of cells of the matrix. Handle marked cells, change
+ automatically the background color of them.
+ - lin1, col1 : cell coordinates that mark the left top corner of the area to be redrawn
+ - lin2, col2 : cell coordinates that mark the right bottom corner of the area to be redrawn */
+void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+{
+ int x1, y1, x2, y2, old_x2, old_y1, old_y2;
+ int alignment, lin, col, active;
+ long framecolor, emptyarea_color = -1;
+ char str[100];
+ IFnii mark_cb;
+ IFnii dropcheck_cb;
+ IFniiiiiiC draw_cb;
+
+ x1 = 0;
+ x2 = ih->data->w-1;
+ y1 = 0;
+ y2 = ih->data->h-1;
+
+ old_x2 = x2;
+ old_y1 = y1;
+ old_y2 = y2;
+
+ if (col1 > ih->data->columns.last ||
+ col2 < ih->data->columns.first ||
+ lin1 > ih->data->lines.last ||
+ lin2 < ih->data->lines.first)
+ return;
+
+ if (col1 < ih->data->columns.first)
+ col1 = ih->data->columns.first;
+ if (col2 > ih->data->columns.last)
+ col2 = ih->data->columns.last;
+ if (lin1 < ih->data->lines.first)
+ lin1 = ih->data->lines.first;
+ if (lin2 > ih->data->lines.last)
+ lin2 = ih->data->lines.last;
+
+ /* Find the initial position of the first column */
+ x1 += ih->data->columns.sizes[0];
+ for(col = ih->data->columns.first; col < col1; col++)
+ x1 += ih->data->columns.sizes[col];
+
+ /* Find the final position of the last column */
+ x2 = x1;
+ for( ; col <= col2; col++)
+ x2 += ih->data->columns.sizes[col];
+
+ /* Find the initial position of the first line */
+ y1 += ih->data->lines.sizes[0];
+ for(lin = ih->data->lines.first; lin < lin1; lin++)
+ y1 += ih->data->lines.sizes[lin];
+
+ /* Find the final position of the last line */
+ y2 = y1;
+ for( ; lin <= lin2; lin++)
+ y2 += ih->data->lines.sizes[lin];
+
+ if ((col2 == ih->data->columns.num-1) && (old_x2 > x2))
+ {
+ emptyarea_color = cdIupConvertColor(ih->data->bgcolor_parent);
+ cdCanvasForeground(ih->data->cddbuffer, emptyarea_color);
+
+ /* If it was drawn until the last column and remains space in the right of it,
+ then delete this area with the the background color. */
+ IUPMAT_BOX(ih, x2, old_x2, old_y1, old_y2);
+ }
+
+ if ((lin2 == ih->data->lines.num-1) && (old_y2 > y2))
+ {
+ if (emptyarea_color == -1)
+ emptyarea_color = cdIupConvertColor(ih->data->bgcolor_parent);
+ cdCanvasForeground(ih->data->cddbuffer, emptyarea_color);
+
+ /* If it was drawn until the last line visible and remains space below it,
+ then delete this area with the the background color. */
+ IUPMAT_BOX(ih, 0, old_x2, y2, old_y2);
+ }
+
+ /***** Draw the cell values and frame */
+ old_y1 = y1;
+ framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+ active = iupdrvIsActive(ih);
+
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ dropcheck_cb = (IFnii)IupGetCallback(ih, "DROPCHECK_CB");
+ draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB");
+
+ for(col = col1; col <= col2; col++) /* For all the columns in the region */
+ {
+ if (ih->data->columns.sizes[col] == 0)
+ continue;
+
+ alignment = iMatrixDrawGetColAlignment(ih, col, str);
+
+ x2 = x1 + ih->data->columns.sizes[col];
+
+ for(lin = lin1; lin <= lin2; lin++) /* For all lines in the region */
+ {
+ int drop = 0;
+ int marked = 0;
+
+ if (ih->data->lines.sizes[lin] == 0)
+ continue;
+
+ y2 = y1 + ih->data->lines.sizes[lin];
+
+ /* If the cell is marked, then draw it with attenuation color */
+ marked = iupMatrixMarkCellGet(ih, lin, col, mark_cb, str);
+
+ iMatrixDrawBackground(ih, x1, x2, y1, y2, marked, active, lin, col);
+
+ iMatrixDrawFrameRectCell(ih, lin, col, x1, x2, y1, y2, framecolor, str);
+
+ if (dropcheck_cb && dropcheck_cb(ih, lin, col) == IUP_DEFAULT)
+ {
+ drop = IMAT_COMBOBOX_W;
+ iMatrixDrawComboFeedback(ih, x2, y1, y2, active, framecolor);
+ }
+
+ /* draw the cell contents */
+ iMatrixDrawCellValue(ih, x1, x2-drop, y1, y2, alignment, marked, active, lin, col, draw_cb);
+
+ y1 = y2;
+ }
+
+ x1 = x2;
+ y1 = old_y1; /* must reset also y */
+ }
+}
+
+void iupMatrixDraw(Ihandle* ih, int update)
+{
+ if (!ih->data->first_redraw)
+ return;
+
+ if (ih->data->need_calcsize)
+ iupMatrixAuxCalcSizes(ih);
+
+ iMatrixDrawMatrix(ih);
+
+ if (update)
+ iupMatrixDrawUpdate(ih);
+}
+
+void iupMatrixDrawUpdate(Ihandle* ih)
+{
+ cdCanvasFlush(ih->data->cddbuffer);
+
+ if (ih->data->has_focus)
+ iMatrixDrawFocus(ih);
+}
+
+int iupMatrixDrawSetRedrawAttrib(Ihandle* ih, const char* value)
+{
+ int type;
+
+ if (value == NULL)
+ type = 0;
+ else if(value[0] == 'L' || value[0] == 'l')
+ type = IMAT_PROCESS_LIN;
+ else if(value[0] == 'C' || value[0] == 'c')
+ type = IMAT_PROCESS_COL;
+ else
+ type = 0;
+
+ if (type)
+ {
+ int min = 0, max = 0;
+ value++;
+
+ if(iupStrToIntInt(value, &min, &max, ':') != 2)
+ max = min;
+
+ if (min > max)
+ return 0;
+
+ iupMatrixPrepareDrawData(ih);
+
+ if (ih->data->need_calcsize)
+ iupMatrixAuxCalcSizes(ih);
+
+ if (ih->data->lines.sizes[0] && ih->data->columns.sizes[0])
+ iMatrixDrawTitleCorner(ih);
+
+ if (type == IMAT_PROCESS_LIN)
+ {
+ iupMatrixDrawLineTitle(ih, min, max);
+ iupMatrixDrawCells(ih, min, ih->data->columns.first, max, ih->data->columns.last);
+ }
+ else
+ {
+ iupMatrixDrawColumnTitle(ih, min, max);
+ iupMatrixDrawCells(ih, ih->data->lines.first, min, ih->data->lines.last, max);
+ }
+ }
+ else
+ {
+ iupMatrixAuxCalcSizes(ih);
+ iMatrixDrawMatrix(ih);
+ }
+
+ iupMatrixDrawUpdate(ih);
+ return 0;
+}
diff --git a/iup/srccontrols/matrix/iupmat_draw.h b/iup/srccontrols/matrix/iupmat_draw.h
new file mode 100755
index 0000000..03337e7
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_draw.h
@@ -0,0 +1,31 @@
+/** \file
+ * \brief iupmatrix control
+ * draw functions.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_DRAW_H
+#define __IUPMAT_DRAW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2);
+void iupMatrixDrawColumnTitle(Ihandle* ih, int col1, int col2);
+void iupMatrixDrawLineTitle(Ihandle* ih, int lin1, int lin2);
+
+/* Render the visible cells and update display */
+void iupMatrixDraw(Ihandle* ih, int update);
+
+/* Update the display only */
+void iupMatrixDrawUpdate(Ihandle* ih);
+
+int iupMatrixDrawSetRedrawAttrib(Ihandle* ih, const char* value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_edit.c b/iup/srccontrols/matrix/iupmat_edit.c
new file mode 100755
index 0000000..a7e0a74
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_edit.c
@@ -0,0 +1,450 @@
+/** \file
+* \brief iupmatrix edit
+* Functions used to edit a node name in place.
+*
+* See Copyright Notice in "iup.h"
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupcontrols.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+#include "iup_childtree.h"
+
+#include "iupmat_def.h"
+#include "iupmat_scroll.h"
+#include "iupmat_aux.h"
+#include "iupmat_edit.h"
+#include "iupmat_key.h"
+#include "iupmat_getset.h"
+#include "iupmat_draw.h"
+
+
+static int iMatrixEditCallDropdownCb(Ihandle* ih, int lin, int col)
+{
+ IFnnii cb = (IFnnii)IupGetCallback(ih, "DROP_CB");
+ if(cb)
+ {
+ int ret;
+ char* value = iupMatrixCellGetValue(ih, lin, col);
+ if (!value) value = "";
+
+ iupAttribSetStr(ih->data->droph, "PREVIOUSVALUE", value);
+ IupSetAttribute(ih->data->droph, "VALUE", "1");
+
+ ret = cb(ih, ih->data->droph, lin, col);
+
+ /* check if the user set an invalid value */
+ if (IupGetInt(ih->data->droph, "VALUE") == 0)
+ IupSetAttribute(ih->data->droph, "VALUE", "1");
+
+ if(ret == IUP_DEFAULT)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int iMatrixEditDropDownAction_CB(Ihandle* ih, char* t, int i, int v)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniinsii cb = (IFniinsii)IupGetCallback(ih_matrix, "DROPSELECT_CB");
+ if(cb)
+ {
+ int ret = cb(ih_matrix, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, ih, t, i, v);
+
+ /* If the user returns IUP_CONTINUE in a dropselect_cb
+ the value is accepted and the matrix leaves edition mode. */
+ if (ret == IUP_CONTINUE)
+ {
+ iupMatrixEditHide(ih_matrix);
+ iupMatrixDrawUpdate(ih);
+ }
+ }
+
+ return IUP_DEFAULT;
+}
+
+static void iMatrixEditChooseElement(Ihandle* ih, int lin, int col)
+{
+ int drop = iMatrixEditCallDropdownCb(ih, lin, col);
+ if(drop)
+ ih->data->datah = ih->data->droph;
+ else
+ {
+ char* value;
+
+ ih->data->datah = ih->data->texth;
+
+ /* dropdown values are set by the user in DROP_CB.
+ text value is set here from cell contents. */
+ value = iupMatrixCellGetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (!value) value = "";
+ IupSetAttribute(ih->data->texth, "VALUE", value);
+ }
+}
+
+static int iMatrixEditCallEditionCb(Ihandle* ih, int mode, int update)
+{
+ int ret = iupMatrixAuxCallEditionCbLinCol(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, mode, update);
+
+ if (update && ret == IUP_DEFAULT && mode == 0) /* leaving edition mode */
+ iupMatrixCellUpdateValue(ih);
+
+ return ret;
+}
+
+static int iMatrixEditCancel(Ihandle* ih, int focus, int update, int ignore)
+{
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ {
+ int ret;
+
+ /* Avoid calling EDITION_CB twice. Usually because a killfocus. */
+ if (iupAttribGet(ih, "_IUPMAT_CALL_EDITION"))
+ return IUP_DEFAULT;
+
+ iupAttribSetStr(ih, "_IUPMAT_CALL_EDITION", "1");
+ ret = iMatrixEditCallEditionCb(ih, 0, update);
+ iupAttribSetStr(ih, "_IUPMAT_CALL_EDITION", NULL);
+
+ if (ret == IUP_IGNORE && ignore)
+ return IUP_IGNORE;
+
+ IupSetAttribute(ih->data->datah, "VISIBLE", "NO");
+ IupSetAttribute(ih->data->datah, "ACTIVE", "NO");
+
+ if (focus)
+ {
+ IupSetFocus(ih);
+ ih->data->has_focus = 1; /* set this so even if getfocus_cb is not called the focus is drawn */
+ }
+#ifdef SunOS
+ /* Usually when the edit control is hidden the matrix is automatically repainted by the system, except in SunOS. */
+ iupMatrixDrawUpdate(ih);
+#endif
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iMatrixEditKillFocus_CB(Ihandle* ih)
+{
+ Ihandle* ih_matrix = ih->parent;
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
+ {
+ if (iupAttribGet(ih_matrix, "_IUPMAT_DOUBLE_CLICK"))
+ return IUP_DEFAULT;
+ }
+
+ iupMatrixEditForceHidden(ih_matrix);
+ return IUP_DEFAULT;
+}
+
+int iupMatrixEditHide(Ihandle* ih)
+{
+ return iMatrixEditCancel(ih, 1, 1, 1); /* set focus + update + use ignore */
+}
+
+void iupMatrixEditForceHidden(Ihandle* ih)
+{
+ iMatrixEditCancel(ih, 0, 1, 0); /* no focus + update + no ignore */
+}
+
+int iupMatrixEditIsVisible(Ihandle* ih)
+{
+ if (!IupGetInt(ih, "ACTIVE"))
+ return 0;
+
+ if (!IupGetInt(ih->data->datah, "VISIBLE"))
+ return 0;
+
+ return 1;
+}
+
+int iupMatrixEditShow(Ihandle* ih)
+{
+ char* mask;
+ int w, h, x, y;
+
+ /* work around for Windows when using Multiline */
+ if (iupAttribGet(ih, "_IUPMAT_IGNORE_SHOW"))
+ {
+ iupAttribSetStr(ih, "_IUPMAT_IGNORE_SHOW", NULL);
+ return 0;
+ }
+
+ /* not active */
+ if(!IupGetInt(ih, "ACTIVE"))
+ return 0;
+
+ /* already visible */
+ if(IupGetInt(ih->data->datah, "VISIBLE"))
+ return 0;
+
+ /* notify application */
+ if (iMatrixEditCallEditionCb(ih, 1, 0) == IUP_IGNORE)
+ return 0;
+
+ /* select edit control */
+ iMatrixEditChooseElement(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+
+ /* position the cell to make it visible */
+ /* If the focus is not visible, a scroll is done for that the focus to be visible */
+ if (!iupMatrixAuxIsCellFullVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ iupMatrixScrollToVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+
+ /* set attributes */
+ iupMatrixPrepareDrawData(ih);
+ IupStoreAttribute(ih->data->datah, "BGCOLOR", iupMatrixGetBgColor(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ IupStoreAttribute(ih->data->datah, "FGCOLOR", iupMatrixGetFgColor(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ IupSetAttribute(ih->data->datah, "FONT", iupMatrixGetFont(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+
+ mask = IupMatGetAttribute(ih,"MASK", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (mask)
+ {
+ IupSetAttribute(ih->data->datah, "MASKCASEI", IupMatGetAttribute(ih,"MASKCASEI", ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ IupSetAttribute(ih->data->datah, "MASK", mask);
+ }
+ else
+ {
+ mask = IupMatGetAttribute(ih,"MASKINT", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (mask)
+ IupSetAttribute(ih->data->datah, "MASKINT", mask);
+ else
+ {
+ mask = IupMatGetAttribute(ih,"MASKFLOAT", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ if (mask)
+ IupSetAttribute(ih->data->datah, "MASKFLOAT", mask);
+ }
+ }
+
+ /* calc size */
+ iupMatrixAuxGetVisibleCellDim(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, &x, &y, &w, &h);
+
+ ih->data->datah->x = x;
+ ih->data->datah->y = y;
+ if (IupGetGlobal("GTKVERSION"))
+ {
+ /* In GTK, IupCanvas is not the actual container of the IupText/IupList */
+ ih->data->datah->x += ih->x;
+ ih->data->datah->y += ih->y;
+ }
+
+ ih->data->datah->currentwidth = w;
+ ih->data->datah->currentheight = h;
+ iupClassObjectLayoutUpdate(ih->data->datah);
+
+ /* activate and show */
+ IupSetAttribute(ih->data->datah, "ACTIVE", "YES");
+ IupSetAttribute(ih->data->datah, "VISIBLE", "YES");
+ IupSetFocus(ih->data->datah);
+
+ return 1;
+}
+
+static int iMatrixEditTextAction_CB(Ihandle* ih, int c, char* after)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniiiis cb = (IFniiiis) IupGetCallback(ih_matrix, "ACTION_CB");
+ if (cb && c!=0) /* only for valid characters */
+ {
+ int oldc = c;
+ c = cb(ih_matrix, c, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, 1, after);
+ if (c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if(c == IUP_DEFAULT)
+ c = oldc;
+ return c;
+ }
+
+ return IUP_DEFAULT;
+}
+
+static int iMatrixEditTextKeyAny_CB(Ihandle* ih, int c)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniiiis cb = (IFniiiis) IupGetCallback(ih_matrix, "ACTION_CB");
+ if (cb && c==0) /* only for other characters */
+ {
+ int oldc = c;
+ c = cb(ih_matrix, c, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, 1, IupGetAttribute(ih, "VALUE"));
+ if(c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if(c == IUP_DEFAULT)
+ c = oldc;
+ }
+
+ switch (c)
+ {
+ case K_cUP:
+ case K_cDOWN:
+ case K_cLEFT:
+ case K_cRIGHT:
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ break;
+ case K_UP:
+ if (IupGetInt(ih, "CARET") == 1)
+ {
+ /* if at the first line of the text */
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ break;
+ case K_DOWN:
+ {
+ char* value = IupGetAttribute(ih, "VALUE");
+ if (value)
+ {
+ /* if at the last line of the text */
+ if (iupStrLineCount(value) == IupGetInt(ih, "CARET"))
+ {
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ }
+ }
+ break;
+ case K_LEFT:
+ if (IupGetInt(ih, "CARETPOS") == 0)
+ {
+ /* if at the first character */
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ break;
+ case K_RIGHT:
+ {
+ char* value = IupGetAttribute(ih, "VALUE");
+ if (value)
+ {
+ /* if at the last character */
+ if ((int)strlen(value) == IupGetInt(ih, "CARETPOS"))
+ {
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ iupMatrixProcessKeyPress(ih_matrix, c);
+ return IUP_IGNORE;
+ }
+ }
+ }
+ }
+ break;
+ case K_ESC:
+ iMatrixEditCancel(ih_matrix, 1, 0, 0); /* set focus + NO update + NO ignore */
+ return IUP_IGNORE;
+ case K_CR:
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Win32") && IupGetInt(ih, "MULTILINE"))
+ {
+ /* work around for Windows when using Multiline */
+ iupAttribSetStr(ih_matrix, "_IUPMAT_IGNORE_SHOW", "1");
+ }
+
+ if (iupMatrixAuxCallLeaveCellCb(ih_matrix) != IUP_IGNORE)
+ {
+ iupMatrixScrollKeyCr(ih_matrix);
+ iupMatrixAuxCallEnterCellCb(ih_matrix);
+ }
+ iupMatrixDrawUpdate(ih_matrix);
+ return IUP_IGNORE;
+ }
+ break;
+ }
+
+ return IUP_CONTINUE;
+}
+
+static int iMatrixEditDropDownKeyAny_CB(Ihandle* ih, int c)
+{
+ Ihandle* ih_matrix = ih->parent;
+ IFniiiis cb = (IFniiiis)IupGetCallback(ih_matrix, "ACTION_CB");
+ if (cb)
+ {
+ int oldc = c;
+ c = cb(ih_matrix, c, ih_matrix->data->lines.focus_cell, ih_matrix->data->columns.focus_cell, 1, "");
+ if (c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if(c == IUP_DEFAULT)
+ c = oldc;
+ }
+
+ switch (c)
+ {
+ case K_CR:
+ if (iupMatrixEditHide(ih_matrix) == IUP_DEFAULT)
+ {
+ if (iupMatrixAuxCallLeaveCellCb(ih_matrix) != IUP_IGNORE)
+ {
+ iupMatrixScrollKeyCr(ih_matrix);
+ iupMatrixAuxCallEnterCellCb(ih_matrix);
+ }
+ iupMatrixDrawUpdate(ih_matrix);
+ return IUP_IGNORE;
+ }
+ break;
+ case K_ESC:
+ iMatrixEditCancel(ih_matrix, 1, 0, 0); /* set focus + NO update + NO ignore */
+ return IUP_IGNORE;
+ }
+
+ return IUP_CONTINUE;
+}
+
+char* iupMatrixEditGetValue(Ihandle* ih)
+{
+ if (ih->data->datah == ih->data->droph)
+ return IupGetAttribute(ih->data->droph, IupGetAttribute(ih->data->droph, "VALUE"));
+ else
+ return IupGetAttribute(ih->data->texth, "VALUE");
+}
+
+void iupMatrixEditCreate(Ihandle* ih)
+{
+ /******** EDIT *************/
+ ih->data->texth = IupText(NULL);
+ iupChildTreeAppend(ih, ih->data->texth);
+
+ IupSetCallback(ih->data->texth, "ACTION", (Icallback)iMatrixEditTextAction_CB);
+ IupSetCallback(ih->data->texth, "K_ANY", (Icallback)iMatrixEditTextKeyAny_CB);
+ IupSetCallback(ih->data->texth, "KILLFOCUS_CB", (Icallback)iMatrixEditKillFocus_CB);
+ IupSetAttribute(ih->data->texth, "VALUE", "");
+ IupSetAttribute(ih->data->texth, "VISIBLE", "NO");
+ IupSetAttribute(ih->data->texth, "ACTIVE", "NO");
+
+
+ /******** DROPDOWN *************/
+ ih->data->droph = IupList(NULL);
+ iupChildTreeAppend(ih, ih->data->droph);
+
+ IupSetCallback(ih->data->droph, "ACTION", (Icallback)iMatrixEditDropDownAction_CB);
+ IupSetCallback(ih->data->droph, "KILLFOCUS_CB", (Icallback)iMatrixEditKillFocus_CB);
+ IupSetCallback(ih->data->droph, "K_ANY", (Icallback)iMatrixEditDropDownKeyAny_CB);
+ IupSetAttribute(ih->data->droph, "DROPDOWN", "YES");
+ IupSetAttribute(ih->data->droph, "MULTIPLE", "NO");
+ IupSetAttribute(ih->data->droph, "VISIBLE", "NO");
+ IupSetAttribute(ih->data->droph, "ACTIVE", "NO");
+}
diff --git a/iup/srccontrols/matrix/iupmat_edit.h b/iup/srccontrols/matrix/iupmat_edit.h
new file mode 100755
index 0000000..9a7815f
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_edit.h
@@ -0,0 +1,26 @@
+/** \file
+ * \brief iupmatrix.
+ * Functions used to edit a cell in place.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_EDIT_H
+#define __IUPMAT_EDIT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixEditIsVisible (Ihandle *ih);
+int iupMatrixEditShow (Ihandle* ih);
+int iupMatrixEditHide (Ihandle* ih);
+void iupMatrixEditForceHidden(Ihandle* ih);
+char* iupMatrixEditGetValue (Ihandle* ih);
+void iupMatrixEditCreate (Ihandle* ih);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_focus.c b/iup/srccontrols/matrix/iupmat_focus.c
new file mode 100755
index 0000000..3c000f8
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_focus.c
@@ -0,0 +1,58 @@
+/** \file
+ * \brief iupmatrix focus control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_aux.h"
+#include "iupmat_focus.h"
+#include "iupmat_draw.h"
+
+
+void iupMatrixFocusSet(Ihandle* ih, int lin, int col)
+{
+ ih->data->lines.focus_cell = lin;
+ ih->data->columns.focus_cell = col;
+}
+
+int iupMatrixFocus_CB(Ihandle* ih, int focus)
+{
+ int rc = IUP_DEFAULT;
+
+ if (!iupMatrixIsValid(ih, 1))
+ return IUP_DEFAULT;
+
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
+ {
+ if (focus && iupAttribGet(ih, "_IUPMAT_DOUBLE_CLICK"))
+ {
+ iupAttribSetStr(ih, "_IUPMAT_DOUBLE_CLICK", NULL);
+ return IUP_DEFAULT;
+ }
+ }
+
+ ih->data->has_focus = focus;
+ iupMatrixDrawUpdate(ih);
+
+ if (focus)
+ iupMatrixAuxCallEnterCellCb(ih);
+ else
+ iupMatrixAuxCallLeaveCellCb(ih);
+
+ return rc;
+}
+
+
diff --git a/iup/srccontrols/matrix/iupmat_focus.h b/iup/srccontrols/matrix/iupmat_focus.h
new file mode 100755
index 0000000..75f5894
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_focus.h
@@ -0,0 +1,21 @@
+/** \file
+ * \brief iupmatrix focus control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_FOCUS_H
+#define __IUPMAT_FOCUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixFocus_CB(Ihandle* ih, int focus);
+void iupMatrixFocusSet(Ihandle* ih, int lin, int col);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_getset.c b/iup/srccontrols/matrix/iupmat_getset.c
new file mode 100755
index 0000000..34947b6
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_getset.c
@@ -0,0 +1,358 @@
+/** \file
+ * \brief iupmatrix setget control
+ * attributes set and get
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_drvfont.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_childtree.h"
+
+#include "iupmat_def.h"
+#include "iupmat_getset.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+#include "iupmat_aux.h"
+
+
+int iupMatrixCheckCellPos(Ihandle* ih, int lin, int col)
+{
+ /* Check if the cell exists */
+ if ((lin < 0) || (col < 0) || (lin > ih->data->lines.num-1) || (col > ih->data->columns.num-1))
+ return 0;
+
+ return 1;
+}
+
+void iupMatrixCellSetValue(Ihandle* ih, int lin, int col, const char* value)
+{
+ if (ih->data->callback_mode)
+ return;
+
+ if (ih->data->cells[lin][col].value)
+ free(ih->data->cells[lin][col].value);
+
+ ih->data->cells[lin][col].value = iupStrDup(value);
+
+ if (lin==0 || col==0)
+ ih->data->need_calcsize = 1;
+}
+
+char* iupMatrixCellGetValue (Ihandle* ih, int lin, int col)
+{
+ if (!ih->handle)
+ {
+ char str[100];
+ sprintf(str, "%d:%d", lin, col);
+ return iupAttribGet(ih, str);
+ }
+ else
+ {
+ if (ih->data->callback_mode)
+ {
+ sIFnii value_cb = (sIFnii)IupGetCallback(ih, "VALUE_CB");
+ return value_cb(ih, lin, col);
+ }
+ else
+ return ih->data->cells[lin][col].value;
+ }
+}
+
+void iupMatrixCellSetFlag(Ihandle* ih, int lin, int col, unsigned char attr, int set)
+{
+ if (!ih->handle)
+ return;
+
+ if (lin==-1)
+ {
+ if ((col < 0) || (col > ih->data->columns.num-1))
+ return;
+
+ if (set)
+ ih->data->columns.flags[col] |= attr;
+ else
+ ih->data->columns.flags[col] &= ~attr;
+ }
+ else if (col == -1)
+ {
+ if ((lin < 0) || (lin > ih->data->lines.num-1))
+ return;
+
+ if (set)
+ ih->data->lines.flags[lin] |= attr;
+ else
+ ih->data->lines.flags[lin] &= ~attr;
+ }
+ else
+ {
+ if (!ih->data->callback_mode)
+ {
+ if ((lin < 0) || (col < 0) || (lin > ih->data->lines.num-1) || (col > ih->data->columns.num-1))
+ return;
+
+ if (set)
+ ih->data->cells[lin][col].flags |= attr;
+ else
+ ih->data->cells[lin][col].flags &= ~attr;
+ }
+ }
+}
+
+void iupMatrixCellUpdateValue(Ihandle* ih)
+{
+ IFniis value_edit_cb;
+ char *value = iupMatrixEditGetValue(ih);
+
+ iupMatrixCellSetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, value);
+
+ value_edit_cb = (IFniis)IupGetCallback(ih, "VALUE_EDIT_CB");
+ if (value_edit_cb)
+ value_edit_cb(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, value);
+
+ iupMatrixPrepareDrawData(ih);
+ iupMatrixDrawCells(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+}
+
+void iupMatrixPrepareDrawData(Ihandle* ih)
+{
+ /* FGCOLOR, BGCOLOR and FONT */
+ iupAttribStoreStr(ih, "_IUPMAT_BGCOLOR_PARENT", iupControlBaseGetParentBgColor(ih));
+ iupAttribStoreStr(ih, "_IUPMAT_BGCOLOR", IupGetAttribute(ih, "BGCOLOR"));
+ iupAttribStoreStr(ih, "_IUPMAT_FGCOLOR", IupGetAttribute(ih, "FGCOLOR"));
+ iupAttribStoreStr(ih, "_IUPMAT_FONT", IupGetAttribute(ih, "FONT"));
+
+ ih->data->bgcolor_parent = iupAttribGet(ih, "_IUPMAT_BGCOLOR_PARENT");
+ ih->data->bgcolor = iupAttribGet(ih, "_IUPMAT_BGCOLOR");
+ ih->data->fgcolor = iupAttribGet(ih, "_IUPMAT_FGCOLOR");
+ ih->data->font = iupAttribGet(ih, "_IUPMAT_FONT");
+
+ ih->data->font_cb = (sIFnii)IupGetCallback(ih, "FONT_CB");
+ ih->data->fgcolor_cb = (IFniiIII)IupGetCallback(ih, "FGCOLOR_CB");
+ ih->data->bgcolor_cb = (IFniiIII)IupGetCallback(ih, "BGCOLOR_CB");
+}
+
+static char* iMatrixGetCellAttrib(Ihandle* ih, unsigned char attr, int lin, int col, int native_parent)
+{
+ char* value = NULL;
+ char attrib_id[100];
+ const char* attrib = NULL;
+ char* attrib_global = NULL;
+
+ if (attr == IUPMAT_FONT)
+ {
+ attrib = "FONT";
+ attrib_global = ih->data->font;
+ }
+ else if (attr == IUPMAT_BGCOLOR)
+ {
+ attrib = "BGCOLOR";
+ attrib_global = ih->data->bgcolor;
+ }
+ else if (attr == IUPMAT_FGCOLOR)
+ {
+ attrib = "FGCOLOR";
+ attrib_global = ih->data->fgcolor;
+ }
+
+ /* 1 - check for this cell */
+ if (ih->data->callback_mode || ih->data->cells[lin][col].flags & attr)
+ {
+ sprintf(attrib_id, "%s%d:%d", attrib, lin, col);
+ value = iupAttribGet(ih, attrib_id);
+ }
+ if (!value)
+ {
+ /* 2 - check for this line, if not title col */
+ if (col != 0)
+ {
+ if (ih->data->lines.flags[lin] & attr)
+ {
+ sprintf(attrib_id, "%s%d:*", attrib, lin);
+ value = iupAttribGet(ih, attrib_id);
+ }
+ }
+
+ if (!value)
+ {
+ /* 3 - check for this column, if not title line */
+ if (lin != 0)
+ {
+ if (ih->data->columns.flags[col] & attr)
+ {
+ sprintf(attrib_id,"%s*:%d", attrib, col);
+ value = iupAttribGet(ih, attrib_id);
+ }
+ }
+
+ if (!value)
+ {
+ /* 4 - check for the matrix or native parent */
+ if (native_parent)
+ value = ih->data->bgcolor_parent;
+ else
+ value = attrib_global;
+ }
+ }
+ }
+
+ return value;
+}
+
+static int iMatrixCallColorCB(Ihandle* ih, IFniiIII cb, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ int ir, ig, ib, ret;
+ ret = cb(ih, lin, col, &ir, &ig, &ib);
+ *r = iupBYTECROP(ir);
+ *g = iupBYTECROP(ig);
+ *b = iupBYTECROP(ib);
+ return ret;
+}
+
+char* iupMatrixGetFgColor(Ihandle* ih, int lin, int col)
+{
+ unsigned char r = 0, g = 0, b = 0;
+ /* called from Edit only */
+ if (!ih->data->fgcolor_cb || (iMatrixCallColorCB(ih, ih->data->fgcolor_cb, lin, col, &r, &g, &b) == IUP_IGNORE))
+ {
+ char* fgcolor = iMatrixGetCellAttrib(ih, IUPMAT_FGCOLOR, lin, col, 0);
+ if (!fgcolor)
+ {
+ if (lin ==0 || col == 0)
+ fgcolor = IupGetGlobal("DLGFGCOLOR");
+ else
+ fgcolor = IupGetGlobal("TXTFGCOLOR");
+ }
+ return fgcolor;
+ }
+ else
+ {
+ char* buffer = iupStrGetMemory(30);
+ sprintf(buffer, "%d %d %d", r, g, b);
+ return buffer;
+ }
+}
+
+void iupMatrixGetFgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ /* called from Draw only */
+ if (!ih->data->fgcolor_cb || (iMatrixCallColorCB(ih, ih->data->fgcolor_cb, lin, col, r, g, b) == IUP_IGNORE))
+ {
+ char* fgcolor = iMatrixGetCellAttrib(ih, IUPMAT_FGCOLOR, lin, col, 0);
+ if (!fgcolor)
+ {
+ if (lin ==0 || col == 0)
+ fgcolor = IupGetGlobal("DLGFGCOLOR");
+ else
+ fgcolor = IupGetGlobal("TXTFGCOLOR");
+ }
+ iupStrToRGB(fgcolor, r, g, b);
+ }
+}
+
+char* iupMatrixGetBgColor(Ihandle* ih, int lin, int col)
+{
+ unsigned char r = 0, g = 0, b = 0;
+ /* called from Edit only */
+ if (!ih->data->bgcolor_cb || (iMatrixCallColorCB(ih, ih->data->bgcolor_cb, lin, col, &r, &g, &b) == IUP_IGNORE))
+ {
+ int native_parent = 0;
+ if (lin == 0 || col == 0)
+ native_parent = 1;
+ return iMatrixGetCellAttrib(ih, IUPMAT_BGCOLOR, lin, col, native_parent);
+ }
+ else
+ {
+ char* buffer = iupStrGetMemory(30);
+ sprintf(buffer, "%d %d %d", r, g, b);
+ return buffer;
+ }
+}
+
+#define IMAT_DARKER(_x) (((_x)*9)/10)
+
+void iupMatrixGetBgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ /* called from Draw only */
+ if (!ih->data->bgcolor_cb || (iMatrixCallColorCB(ih, ih->data->bgcolor_cb, lin, col, r, g, b) == IUP_IGNORE))
+ {
+ int native_parent = 0;
+ if (lin == 0 || col == 0)
+ native_parent = 1;
+ iupStrToRGB(iMatrixGetCellAttrib(ih, IUPMAT_BGCOLOR, lin, col, native_parent), r, g, b);
+ if (native_parent)
+ {
+ int ir = IMAT_DARKER(*r), ig=IMAT_DARKER(*g), ib=IMAT_DARKER(*b); /* use a darker version of the background by 10% */
+ *r = iupBYTECROP(ir);
+ *g = iupBYTECROP(ig);
+ *b = iupBYTECROP(ib);
+ }
+ }
+}
+
+char* iupMatrixGetFont(Ihandle* ih, int lin, int col)
+{
+ char* font = NULL;
+ /* called from Draw and Edit only */
+ if (ih->data->font_cb)
+ font = ih->data->font_cb(ih, lin, col);
+ if (!font)
+ font = iMatrixGetCellAttrib(ih, IUPMAT_FONT, lin, col, 0);
+ return font;
+}
+
+char *iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels)
+{
+ char* str;
+ int size;
+ ImatLinColData *lincol_data;
+
+ if(m == IMAT_PROCESS_LIN)
+ lincol_data = &(ih->data->lines);
+ else
+ lincol_data = &(ih->data->columns);
+
+ if (index < 0 || index > lincol_data->num-1)
+ return NULL;
+
+ if (m == IMAT_PROCESS_LIN)
+ size = iupMatrixAuxGetLineHeight(ih, index);
+ else
+ size = iupMatrixAuxGetColumnWidth(ih, index);
+
+ str = iupStrGetMemory(100);
+
+ if (size)
+ {
+ /* remove the decoration added in iupMatrixAuxGet */
+ if (m == IMAT_PROCESS_COL)
+ size -= IMAT_PADDING_W + IMAT_FRAME_W;
+ else
+ size -= IMAT_PADDING_H + IMAT_FRAME_H;
+
+ if (!pixels)
+ {
+ int charwidth, charheight;
+ iupdrvFontGetCharSize(ih, &charwidth, &charheight);
+ if (m == IMAT_PROCESS_COL)
+ size = iupRASTER2WIDTH(size, charwidth);
+ else
+ size = iupRASTER2HEIGHT(size, charheight);
+ }
+ }
+
+ sprintf(str, "%d", size);
+ return str;
+}
diff --git a/iup/srccontrols/matrix/iupmat_getset.h b/iup/srccontrols/matrix/iupmat_getset.h
new file mode 100755
index 0000000..9ae3d07
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_getset.h
@@ -0,0 +1,37 @@
+/** \file
+ * \brief iupmatrix control
+ * attributes set and get.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_GETSET_H
+#define __IUPMAT_GETSET_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void iupMatrixCellSetValue(Ihandle* ih, int lin, int col, const char* value);
+char* iupMatrixCellGetValue(Ihandle* ih, int lin, int col);
+
+void iupMatrixCellSetFlag(Ihandle* ih, int lin, int col, unsigned char attr, int set);
+
+void iupMatrixPrepareDrawData(Ihandle* ih);
+char* iupMatrixGetFgColor(Ihandle* ih, int lin, int col);
+char* iupMatrixGetBgColor(Ihandle* ih, int lin, int col);
+char* iupMatrixGetFont (Ihandle* ih, int lin, int col);
+void iupMatrixGetBgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b);
+void iupMatrixGetFgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b);
+
+void iupMatrixCellUpdateValue(Ihandle* ih);
+
+char* iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels);
+
+int iupMatrixCheckCellPos(Ihandle* ih, int lin, int col);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_key.c b/iup/srccontrols/matrix/iupmat_key.c
new file mode 100755
index 0000000..ae9ed55
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_key.c
@@ -0,0 +1,229 @@
+/** \file
+ * \brief iupmatrix control
+ * keyboard control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to control keys in the matrix and in the text edition */
+/**************************************************************************/
+
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_scroll.h"
+#include "iupmat_focus.h"
+#include "iupmat_aux.h"
+#include "iupmat_getset.h"
+#include "iupmat_key.h"
+#include "iupmat_mark.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+
+
+int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+{
+ int ret = IUP_IGNORE; /* default for processed keys */
+
+ /* If the focus is not visible, a scroll is done for that the focus to be visible */
+ if (!iupMatrixAuxIsCellFullVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ iupMatrixScrollToVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+
+ switch (c)
+ {
+ case K_cHOME:
+ case K_sHOME:
+ case K_HOME:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyHome(ih);
+ ih->data->homekeycount++;
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_cEND:
+ case K_sEND:
+ case K_END:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyEnd(ih);
+ ih->data->endkeycount++;
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_sTAB:
+ case K_TAB:
+ return IUP_CONTINUE; /* do not redraw */
+
+ case K_cLEFT:
+ case K_sLEFT:
+ case K_LEFT:
+ if (iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyLeft(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_cRIGHT:
+ case K_sRIGHT:
+ case K_RIGHT:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyRight(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_cUP:
+ case K_sUP:
+ case K_UP:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyUp(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break ;
+
+ case K_cDOWN:
+ case K_sDOWN:
+ case K_DOWN:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyDown(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_sPGUP:
+ case K_PGUP:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyPgUp(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_sPGDN:
+ case K_PGDN:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+ iupMatrixScrollKeyPgDown(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+
+ case K_F2:
+ case K_SP:
+ case K_CR:
+ case K_sCR:
+ if (iupMatrixEditShow(ih))
+ return IUP_IGNORE; /* do not redraw */
+ break;
+
+ case K_sDEL:
+ case K_DEL:
+ {
+ int lin, col;
+ char str[100];
+ IFnii mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+
+ iupMatrixPrepareDrawData(ih);
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (iupMatrixMarkCellGet(ih, lin, col, mark_cb, str))
+ {
+ if (iupMatrixAuxCallEditionCbLinCol(ih, lin, col, 1, 1) != IUP_IGNORE)
+ {
+ IFniis value_edit_cb;
+
+ iupMatrixCellSetValue(ih, lin, col, NULL);
+
+ value_edit_cb = (IFniis)IupGetCallback(ih, "VALUE_EDIT_CB");
+ if (value_edit_cb)
+ value_edit_cb(ih, lin, col, NULL);
+
+ iupMatrixDrawCells(ih, lin, col, lin, col);
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ /* if a valid character is pressed enter edition mode */
+ if (iup_isprint(c))
+ {
+ if (iupMatrixEditShow(ih))
+ {
+ if (ih->data->datah == ih->data->texth)
+ {
+ char value[2] = {0,0};
+ value[0] = (char)c;
+ IupStoreAttribute(ih->data->datah, "VALUE", value);
+ IupSetAttribute(ih->data->datah, "CARET", "2");
+ }
+ return IUP_IGNORE; /* do not redraw */
+ }
+ }
+ ret = IUP_DEFAULT; /* unprocessed keys */
+ break;
+ }
+
+ iupMatrixDrawUpdate(ih);
+ return ret;
+}
+
+void iupMatrixKeyResetHomeEndCount(Ihandle* ih)
+{
+ ih->data->homekeycount = 0;
+ ih->data->endkeycount = 0;
+}
+
+int iupMatrixKeyPress_CB(Ihandle* ih, int c, int press)
+{
+ int oldc = c;
+ IFniiiis cb;
+
+ if (!iupMatrixIsValid(ih, 1))
+ return IUP_DEFAULT;
+
+ if (!press)
+ return IUP_DEFAULT;
+
+ cb = (IFniiiis)IupGetCallback(ih, "ACTION_CB");
+ if (cb)
+ {
+ if (iup_isprint(c))
+ {
+ char value[2]={0,0};
+ value[0] = (char)c;
+ c = cb(ih, c, ih->data->lines.focus_cell, ih->data->columns.focus_cell, 0, value);
+ }
+ else
+ {
+ c = cb(ih, c, ih->data->lines.focus_cell, ih->data->columns.focus_cell, 0,
+ iupMatrixCellGetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell));
+ }
+
+ if (c == IUP_IGNORE || c == IUP_CLOSE || c == IUP_CONTINUE)
+ return c;
+ else if (c == IUP_DEFAULT)
+ c = oldc;
+ }
+
+ if (c != K_HOME && c != K_sHOME)
+ ih->data->homekeycount = 0;
+ if (c != K_END && c != K_sEND)
+ ih->data->endkeycount = 0;
+
+ return iupMatrixProcessKeyPress(ih, c);
+}
diff --git a/iup/srccontrols/matrix/iupmat_key.h b/iup/srccontrols/matrix/iupmat_key.h
new file mode 100755
index 0000000..1062dd0
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_key.h
@@ -0,0 +1,23 @@
+/** \file
+ * \brief iupmatrix. keyboard control.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_KEY_H
+#define __IUPMAT_KEY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixKeyPress_CB(Ihandle* ih, int c, int press);
+int iupMatrixProcessKeyPress(Ihandle* ih, int c);
+
+void iupMatrixKeyResetHomeEndCount(Ihandle* ih);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_mark.c b/iup/srccontrols/matrix/iupmat_mark.c
new file mode 100755
index 0000000..99aad32
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mark.c
@@ -0,0 +1,720 @@
+/** \file
+ * \brief iupmatrix control
+ * cell selection
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to cell selection (mark) */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_mark.h"
+#include "iupmat_getset.h"
+#include "iupmat_draw.h"
+
+
+static void iMatrixMarkLinSet(Ihandle* ih, int lin, int mark)
+{
+ /* called when MARKMODE=LIN */
+ if (mark==-1)
+ mark = !(ih->data->lines.flags[lin] & IUPMAT_MARK);
+
+ if (mark)
+ ih->data->lines.flags[lin] |= IUPMAT_MARK;
+ else
+ ih->data->lines.flags[lin] &= ~IUPMAT_MARK;
+}
+
+static void iMatrixMarkColSet(Ihandle* ih, int col, int mark)
+{
+ /* called when MARKMODE=COL */
+ if (mark==-1)
+ mark = !(ih->data->columns.flags[col] & IUPMAT_MARK);
+
+ if (mark)
+ ih->data->columns.flags[col] |= IUPMAT_MARK;
+ else
+ ih->data->columns.flags[col] &= ~IUPMAT_MARK;
+}
+
+static void iMatrixMarkCellSet(Ihandle* ih, int lin, int col, int mark, IFniii markedit_cb, IFnii mark_cb, char* str)
+{
+ /* called only when MARKMODE=CELL */
+ if (mark == -1)
+ mark = !iupMatrixMarkCellGet(ih, lin, col, mark_cb, str);
+
+ if (ih->data->callback_mode)
+ {
+ if (markedit_cb)
+ markedit_cb(ih, lin, col, mark);
+ else
+ {
+ sprintf(str, "MARK%d:%d", lin, col);
+ if (mark)
+ iupAttribSetStr(ih, str, "1");
+ else
+ iupAttribSetStr(ih, str, NULL);
+ }
+ }
+ else
+ {
+ if (mark)
+ ih->data->cells[lin][col].flags |= IUPMAT_MARK;
+ else
+ ih->data->cells[lin][col].flags &= ~IUPMAT_MARK;
+ }
+}
+
+int iupMatrixMarkCellGet(Ihandle* ih, int lin, int col, IFnii mark_cb, char* str)
+{
+ /* called independent from MARKMODE */
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ if (ih->data->callback_mode)
+ {
+ if (mark_cb)
+ return mark_cb(ih, lin, col);
+ else
+ {
+ int mark = 0;
+ char* value;
+ sprintf(str, "MARK%d:%d", lin, col);
+ value = iupAttribGet(ih, str);
+ iupStrToInt(value, &mark);
+ return mark;
+ }
+ }
+ else
+ return ih->data->cells[lin][col].flags & IUPMAT_MARK;
+ }
+ else
+ {
+ if (ih->data->lines.flags[lin] & IUPMAT_MARK || ih->data->columns.flags[col] & IUPMAT_MARK)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static void iMatrixMarkItem(Ihandle* ih, int lin1, int col1, int mark, IFniii markedit_cb, IFnii mark_cb, char* str)
+{
+ int lin, col;
+
+ if (ih->data->mark_full1 == IMAT_PROCESS_LIN)
+ {
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for (col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkCellSet(ih, lin1, col, mark, markedit_cb, mark_cb, str);
+ }
+ else
+ {
+ iMatrixMarkLinSet(ih, lin1, mark);
+ iupMatrixDrawLineTitle(ih, lin1, lin1);
+ }
+
+ iupMatrixDrawCells(ih, lin1, 1, lin1, ih->data->columns.num-1);
+ }
+ else if (ih->data->mark_full1 == IMAT_PROCESS_COL)
+ {
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkCellSet(ih, lin, col1, mark, markedit_cb, mark_cb, str);
+ }
+ else
+ {
+ iMatrixMarkColSet(ih, col1, mark);
+ iupMatrixDrawColumnTitle(ih, col1, col1);
+ }
+
+ iupMatrixDrawCells(ih, 1, col1, ih->data->lines.num-1, col1);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ iMatrixMarkCellSet(ih, lin1, col1, mark, markedit_cb, mark_cb, str);
+ iupMatrixDrawCells(ih, lin1, col1, lin1, col1);
+ }
+}
+
+static void iMatrixMarkBlock(Ihandle* ih, int lin1, int col1, int lin2, int col2, int mark, IFniii markedit_cb, IFnii mark_cb, char* str)
+{
+ int lin, col;
+
+ if (lin1 > lin2) {int t = lin1; lin1 = lin2; lin2 = t;}
+ if (col1 > col2) {int t = col1; col1 = col2; col2 = t;}
+
+ if (ih->data->mark_full1 == IMAT_PROCESS_LIN)
+ {
+ for(lin=lin1; lin<=lin2; lin++)
+ iMatrixMarkItem(ih, lin, 0, mark, markedit_cb, mark_cb, str);
+ }
+ else if(ih->data->mark_full1 == IMAT_PROCESS_COL)
+ {
+ for(col=col1; col<=col2; col++)
+ iMatrixMarkItem(ih, 0, col, mark, markedit_cb, mark_cb, str);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(lin=lin1; lin<=lin2; lin++)
+ {
+ for(col=col1; col<=col2; col++)
+ iMatrixMarkItem(ih, lin, col, mark, markedit_cb, mark_cb, str);
+ }
+ }
+}
+
+void iupMatrixMarkMouseBlock(Ihandle* ih, int lin2, int col2)
+{
+ /* called only when "shift" is pressed and MARKMULTIPLE=YES */
+ IFniii markedit_cb = NULL;
+ IFnii mark_cb = NULL;
+ char str[100];
+
+ iupMatrixPrepareDrawData(ih);
+
+ ih->data->mark_full2 = 0;
+
+ if (lin2 == 0 && col2 == 0)
+ return;
+ /* If it was pointing for a column title... */
+ else if (lin2 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_COL)
+ ih->data->mark_full2 = IMAT_PROCESS_COL;
+ }
+ /* If it was pointing for a line title... */
+ else if (col2 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_LIN)
+ ih->data->mark_full2 = IMAT_PROCESS_LIN;
+ }
+
+ /* if new block is not the same, does nothing */
+ if (ih->data->mark_full1 != ih->data->mark_full2)
+ return;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL && ih->data->callback_mode)
+ {
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ }
+
+ /* Unmark previous block */
+ if (ih->data->mark_lin1 != -1 && ih->data->mark_lin2 != -1 &&
+ ih->data->mark_col1 != -1 && ih->data->mark_col2 != -1)
+ iMatrixMarkBlock(ih, ih->data->mark_lin1, ih->data->mark_col1, ih->data->mark_lin2, ih->data->mark_col2, 0, markedit_cb, mark_cb, str);
+
+ ih->data->mark_lin2 = lin2;
+ ih->data->mark_col2 = col2;
+
+ /* Unmark new block */
+ iMatrixMarkBlock(ih, ih->data->mark_lin1, ih->data->mark_col1, ih->data->mark_lin2, ih->data->mark_col2, 1, markedit_cb, mark_cb, str);
+}
+
+void iupMatrixMarkMouseReset(Ihandle* ih)
+{
+ ih->data->mark_lin1 = -1;
+ ih->data->mark_col1 = -1;
+ ih->data->mark_lin2 = -1;
+ ih->data->mark_col2 = -1;
+
+ ih->data->mark_full1 = 0;
+ ih->data->mark_full2 = 0;
+}
+
+void iupMatrixMarkMouseItem(Ihandle* ih, int ctrl, int lin1, int col1)
+{
+ int mark = 1, mark_full_all, lin, col;
+ IFniii markedit_cb = NULL;
+ IFnii mark_cb = NULL;
+ char str[100];
+
+ iupMatrixMarkMouseReset(ih);
+ iupMatrixPrepareDrawData(ih);
+
+ if (!ih->data->mark_multiple || ih->data->mark_continuous || !ctrl)
+ {
+ iupMatrixMarkClearAll(ih, 1);
+ iupMatrixDraw(ih, 0);
+ }
+ else
+ mark = -1; /* toggle mark state */
+
+ ih->data->mark_full1 = 0;
+ mark_full_all = 0;
+
+ if (lin1 == 0 && col1 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode == IMAT_MARK_COL ||
+ ih->data->mark_mode == IMAT_MARK_LIN)
+ mark_full_all = 1;
+ }
+ /* If it was pointing for a column title... */
+ else if (lin1 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_COL)
+ ih->data->mark_full1 = IMAT_PROCESS_COL;
+ }
+ /* If it was pointing for a line title... */
+ else if (col1 == 0)
+ {
+ if ((ih->data->mark_mode == IMAT_MARK_CELL && ih->data->mark_multiple) ||
+ ih->data->mark_mode & IMAT_MARK_LIN)
+ ih->data->mark_full1 = IMAT_PROCESS_LIN;
+ }
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL && ih->data->callback_mode)
+ {
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ }
+
+ if (mark_full_all)
+ {
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ char str[100];
+ for (col = 1; col < ih->data->columns.num; col++)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, mark_cb, str);
+ }
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_LIN)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkLinSet(ih, lin, mark);
+
+ iupMatrixDrawLineTitle(ih, 1, ih->data->lines.num-1);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_COL)
+ {
+ for (col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkColSet(ih, col, mark);
+
+ iupMatrixDrawColumnTitle(ih, 1, ih->data->columns.num-1);
+ }
+
+ iupMatrixDrawCells(ih, 1, 1, ih->data->lines.num-1, ih->data->columns.num-1);
+ }
+ else
+ iMatrixMarkItem(ih, lin1, col1, mark, markedit_cb, mark_cb, str);
+
+ ih->data->mark_lin1 = lin1;
+ ih->data->mark_col1 = col1;
+}
+
+static void iMatrixMarkAllLinCol(ImatLinColData *p, int mark)
+{
+ int i;
+ for(i = 1; i < p->num; i++)
+ {
+ if (mark)
+ p->flags[i] |= IUPMAT_MARK;
+ else
+ p->flags[i] &= ~IUPMAT_MARK;
+ }
+}
+
+void iupMatrixMarkClearAll(Ihandle* ih, int check)
+{
+ /* "!check" is used to clear all marks independent from MARKMODE */
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL || !check)
+ {
+ int lin, col;
+ IFniii markedit_cb = NULL;
+ char str[100];
+
+ if (check)
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkCellSet(ih, lin, col, 0, markedit_cb, NULL, str);
+ }
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_LIN || !check)
+ iMatrixMarkAllLinCol(&(ih->data->lines), 0);
+
+ if (ih->data->mark_mode & IMAT_MARK_COL || !check)
+ iMatrixMarkAllLinCol(&(ih->data->columns), 0);
+}
+
+int iupMatrixColumnIsMarked(Ihandle* ih, int col)
+{
+ if (col == 0 || /* Line titles are never marked... */
+ !(ih->data->mark_mode & IMAT_MARK_COL))
+ return 0;
+
+ return ih->data->columns.flags[col] & IUPMAT_MARK;
+}
+
+int iupMatrixLineIsMarked(Ihandle* ih, int lin)
+{
+ if (lin == 0 || /* Column titles are never marked... */
+ !(ih->data->mark_mode & IMAT_MARK_LIN))
+ return 0;
+
+ return ih->data->lines.flags[lin] & IUPMAT_MARK;
+}
+
+int iupMatrixSetMarkedAttrib(Ihandle* ih, const char* value)
+{
+ int lin, col, mark;
+ char str[100];
+ IFniii markedit_cb;
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return 0;
+
+ if (!value)
+ iupMatrixMarkClearAll(ih, 1);
+ else if (*value == 'C' || *value == 'c') /* columns */
+ {
+ if (ih->data->mark_mode == IMAT_MARK_LIN)
+ return 0;
+
+ value++; /* skip C mark */
+ if ((int)strlen(value) != ih->data->columns.num-1)
+ return 0;
+
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (*value++ == '1')
+ mark = 1;
+ else
+ mark = 0;
+
+ /* mark all the cells for that column */
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, NULL, str);
+ }
+ else
+ iMatrixMarkColSet(ih, col, mark);
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_LIN)
+ iMatrixMarkAllLinCol(&(ih->data->lines), 0);
+ }
+ else if (*value == 'L' || *value == 'l') /* lines */
+ {
+ if (ih->data->mark_mode == IMAT_MARK_COL)
+ return 0;
+
+ value++; /* skip L mark */
+ if ((int)strlen(value) != ih->data->lines.num-1)
+ return 0;
+
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ if (*value++ == '1')
+ mark = 1;
+ else
+ mark = 0;
+
+ /* Mark all the cells for that line */
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, NULL, str);
+ }
+ else
+ iMatrixMarkLinSet(ih, lin, mark);
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_COL)
+ iMatrixMarkAllLinCol(&(ih->data->columns), 0);
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_CELL) /* cells */
+ {
+ if ((int)strlen(value) != (ih->data->lines.num-1)*(ih->data->columns.num-1))
+ return 0;
+
+ markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (*value++ == '1')
+ mark = 1;
+ else
+ mark = 0;
+
+ iMatrixMarkCellSet(ih, lin, col, mark, markedit_cb, NULL, str);
+ }
+ }
+ }
+
+ if (ih->handle)
+ iupMatrixDraw(ih, 1);
+
+ return 0;
+}
+
+char* iupMatrixGetMarkedAttrib(Ihandle* ih)
+{
+ int lin, col, size;
+ IFnii mark_cb;
+ char str[100];
+ char* p, *value = NULL;
+ int exist_mark = 0; /* Show if there is someone marked */
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return NULL;
+
+ mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ size = (ih->data->lines.num-1) * (ih->data->columns.num-1) + 1;
+ value = iupStrGetMemory(size);
+ p = value;
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (iupMatrixMarkCellGet(ih, lin, col, mark_cb, str))
+ {
+ exist_mark = 1;
+ *p++ = '1';
+ }
+ else
+ *p++ = '0';
+ }
+ }
+ *p = 0;
+ }
+ else
+ {
+ int marked_lines = 0, marked_cols = 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_LINCOL) /* must find which format to return */
+ {
+ /* look for a marked column */
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (ih->data->columns.flags[col] & IUPMAT_MARK)
+ {
+ marked_cols = 1; /* at least one column is marked */
+ break;
+ }
+ }
+
+ if (!marked_cols)
+ marked_lines = 1;
+ }
+ else if (ih->data->mark_mode == IMAT_MARK_LIN)
+ marked_lines = 1;
+ else if (ih->data->mark_mode == IMAT_MARK_COL)
+ marked_cols = 1;
+
+ if (marked_lines)
+ {
+ size = 1 + (ih->data->lines.num-1) + 1;
+ value = iupStrGetMemory(size);
+ p = value;
+
+ *p++ = 'L';
+
+ for(lin = 1; lin < ih->data->lines.num; lin++)
+ {
+ if (ih->data->lines.flags[lin] & IUPMAT_MARK)
+ {
+ exist_mark = 1;
+ *p++ = '1';
+ }
+ else
+ *p++ = '0';
+ }
+ *p = 0;
+ }
+ else if (marked_cols)
+ {
+ size = 1 + (ih->data->columns.num-1) + 1;
+ value = iupStrGetMemory(size);
+ p = value;
+
+ *p++ = 'C';
+
+ for(col = 1; col < ih->data->columns.num; col++)
+ {
+ if (ih->data->columns.flags[col] & IUPMAT_MARK)
+ {
+ exist_mark = 1;
+ *p++ = '1';
+ }
+ else
+ *p++ = '0';
+ }
+ *p = 0;
+ }
+ }
+
+ return exist_mark? value: NULL;
+}
+
+int iupMatrixSetMarkAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0, col = 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return 0;
+
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ int mark;
+
+ if (lin == 0 || col == 0) /* title can NOT have a mark */
+ return 0;
+
+ mark = iupStrBoolean(value);
+
+ if (ih->data->callback_mode)
+ {
+ IFniii markedit_cb = (IFniii)IupGetCallback(ih, "MARKEDIT_CB");
+ if (markedit_cb)
+ markedit_cb(ih, lin, col, mark);
+ else if (mark)
+ return 1; /* store the attribute */
+ }
+ else
+ {
+ if (mark)
+ ih->data->cells[lin][col].flags |= IUPMAT_MARK;
+ else
+ ih->data->cells[lin][col].flags &= ~IUPMAT_MARK;
+ }
+
+ if (ih->handle)
+ {
+ /* This assumes that the matrix has been draw completely previously */
+ iupMatrixPrepareDrawData(ih);
+ iupMatrixDrawCells(ih, lin, col, lin, col);
+ }
+ }
+ else
+ {
+ int mark = iupStrBoolean(value);
+
+ if (ih->data->mark_mode & IMAT_MARK_LIN && lin!=0)
+ {
+ if (mark)
+ ih->data->lines.flags[lin] |= IUPMAT_MARK;
+ else
+ ih->data->lines.flags[lin] &= ~IUPMAT_MARK;
+ }
+
+ if (ih->data->mark_mode & IMAT_MARK_COL && col!=0)
+ {
+ if (mark)
+ ih->data->columns.flags[col] |= IUPMAT_MARK;
+ else
+ ih->data->columns.flags[col] &= ~IUPMAT_MARK;
+ }
+
+ if (ih->handle)
+ {
+ /* This assumes that the matrix has been draw completely previously */
+ iupMatrixPrepareDrawData(ih);
+ iupMatrixDrawCells(ih, lin, col, lin, col);
+ }
+ }
+ }
+
+ return 0;
+}
+
+char* iupMatrixGetMarkAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin = 0, col = 0;
+
+ if (ih->data->mark_mode == IMAT_MARK_NO)
+ return "0";
+
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return NULL;
+
+ if (ih->data->mark_mode == IMAT_MARK_CELL)
+ {
+ if (lin == 0 || col == 0) /* title can NOT have a mark */
+ return NULL;
+
+ if (ih->data->callback_mode)
+ {
+ IFnii mark_cb = (IFnii)IupGetCallback(ih, "MARK_CB");
+ if (mark_cb)
+ {
+ if (mark_cb(ih, lin, col))
+ return "1";
+ else
+ return "0";
+ }
+ else
+ return NULL; /* let check the hash table */
+ }
+ else
+ {
+ if (ih->data->cells[lin][col].flags & IUPMAT_MARK)
+ return "1";
+ else
+ return "0";
+ }
+ }
+ else
+ {
+ if (ih->data->mark_mode & IMAT_MARK_LIN && lin!=0 && ih->data->lines.flags[lin] & IUPMAT_MARK)
+ return "1";
+
+ if (ih->data->mark_mode & IMAT_MARK_COL && col!=0 && ih->data->columns.flags[col] & IUPMAT_MARK)
+ return "1";
+
+ return "0";
+ }
+ }
+
+ return NULL;
+}
diff --git a/iup/srccontrols/matrix/iupmat_mark.h b/iup/srccontrols/matrix/iupmat_mark.h
new file mode 100755
index 0000000..819916e
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mark.h
@@ -0,0 +1,42 @@
+/** \file
+ * \brief iupmatrix. cell selection.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_MARK_H
+#define __IUPMAT_MARK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Used to mark (or not mark) cells */
+#define IMAT_MARK_NO 0
+#define IMAT_MARK_LIN 1
+#define IMAT_MARK_COL 2
+#define IMAT_MARK_LINCOL 3
+#define IMAT_MARK_CELL 4
+
+int iupMatrixSetMarkedAttrib(Ihandle* ih, const char* value);
+char* iupMatrixGetMarkedAttrib(Ihandle* ih);
+char* iupMatrixGetMarkAttrib(Ihandle* ih, const char* name_id);
+int iupMatrixSetMarkAttrib(Ihandle* ih, const char* name_id, const char* value);
+
+void iupMatrixMarkClearAll(Ihandle* ih, int check);
+
+int iupMatrixMarkCellGet(Ihandle* ih, int lin, int col, IFnii mark_cb, char* str);
+
+int iupMatrixColumnIsMarked(Ihandle* ih, int col);
+int iupMatrixLineIsMarked (Ihandle* ih, int lin);
+
+void iupMatrixMarkMouseBlock(Ihandle* ih, int lin2, int col2);
+void iupMatrixMarkMouseItem(Ihandle* ih, int ctrl, int lin1, int col1);
+void iupMatrixMarkMouseReset(Ihandle* ih);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_mem.c b/iup/srccontrols/matrix/iupmat_mem.c
new file mode 100755
index 0000000..eebea7a
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mem.c
@@ -0,0 +1,319 @@
+/** \file
+ * \brief iupmatrix control memory allocation
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to allocate memory */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_mem.h"
+
+
+static void iMatrixGetInitialValues(Ihandle* ih)
+{
+ int lin, col;
+ char* value;
+ char attr[100];
+
+ for (lin=0; lin<ih->data->lines.num; lin++)
+ {
+ for (col=0; col<ih->data->columns.num; col++)
+ {
+ sprintf(attr, "%d:%d", lin, col);
+ value = iupAttribGet(ih, attr);
+ if (value)
+ {
+ /* get the initial value and remove it from the hash table */
+
+ if (*value)
+ ih->data->cells[lin][col].value = iupStrDup(value);
+
+ iupAttribSetStr(ih, attr, NULL);
+ }
+ }
+ }
+}
+
+void iupMatrixMemAlloc(Ihandle* ih)
+{
+ ih->data->lines.num_alloc = ih->data->lines.num;
+ if (ih->data->lines.num_alloc == 1)
+ ih->data->lines.num_alloc = 5;
+
+ ih->data->columns.num_alloc = ih->data->columns.num;
+ if (ih->data->columns.num_alloc == 1)
+ ih->data->columns.num_alloc = 5;
+
+ if (!ih->data->callback_mode)
+ {
+ int lin;
+
+ ih->data->cells = (ImatCell**)calloc(ih->data->lines.num_alloc, sizeof(ImatCell*));
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++)
+ ih->data->cells[lin] = (ImatCell*)calloc(ih->data->columns.num_alloc, sizeof(ImatCell));
+
+ iMatrixGetInitialValues(ih);
+ }
+
+ ih->data->lines.flags = (unsigned char*)calloc(ih->data->lines.num_alloc, sizeof(unsigned char));
+ ih->data->columns.flags = (unsigned char*)calloc(ih->data->columns.num_alloc, sizeof(unsigned char));
+ ih->data->lines.sizes = (int*)calloc(ih->data->lines.num_alloc, sizeof(int));
+ ih->data->columns.sizes = (int*)calloc(ih->data->columns.num_alloc, sizeof(int));
+}
+
+void iupMatrixMemRelease(Ihandle* ih)
+{
+ if (ih->data->cells)
+ {
+ int lin, col;
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++)
+ {
+ for (col = 0; col < ih->data->columns.num_alloc; col++)
+ {
+ ImatCell* cell = &(ih->data->cells[lin][col]);
+ if (cell->value)
+ {
+ free(cell->value);
+ cell->value = NULL;
+ }
+ }
+ free(ih->data->cells[lin]);
+ ih->data->cells[lin] = NULL;
+ }
+ free(ih->data->cells);
+ ih->data->cells = NULL;
+ }
+
+ if (ih->data->columns.flags)
+ {
+ free(ih->data->columns.flags);
+ ih->data->columns.flags = NULL;
+ }
+
+ if (ih->data->lines.flags)
+ {
+ free(ih->data->lines.flags);
+ ih->data->lines.flags = NULL;
+ }
+
+ if (ih->data->columns.sizes)
+ {
+ free(ih->data->columns.sizes);
+ ih->data->columns.sizes = NULL;
+ }
+
+ if (ih->data->lines.sizes)
+ {
+ free(ih->data->lines.sizes);
+ ih->data->lines.sizes = NULL;
+ }
+}
+
+void iupMatrixMemReAllocLines(Ihandle* ih, int old_num, int num, int base)
+{
+ int lin, col, end, diff_num, shift_num;
+
+ /* base is the first line where the change started */
+
+ /* If it doesn't have enough lines allocated, then allocate more space */
+ if (num > ih->data->lines.num_alloc) /* this also implicates that num>old_num */
+ {
+ int old_alloc = ih->data->lines.num_alloc;
+ ih->data->lines.num_alloc = num;
+
+ if (!ih->data->callback_mode)
+ {
+ ih->data->cells = (ImatCell**)realloc(ih->data->cells, ih->data->lines.num_alloc*sizeof(ImatCell*));
+
+ /* new space are allocated at the end, later we need to move the old data and clear the available space */
+ for(lin = old_alloc; lin < num; lin++)
+ ih->data->cells[lin] = (ImatCell*)calloc(ih->data->columns.num_alloc, sizeof(ImatCell));
+ }
+
+ ih->data->lines.sizes = (int*)realloc(ih->data->lines.sizes, ih->data->lines.num_alloc*sizeof(int));
+ ih->data->lines.flags = (unsigned char*)realloc(ih->data->lines.flags, ih->data->lines.num_alloc*sizeof(unsigned char));
+ }
+
+ if (old_num==num)
+ return;
+
+ if (num>old_num) /* ADD */
+ {
+ diff_num = num-old_num; /* size of the openned space */
+ shift_num = old_num-base; /* size of the data to be moved (base maximum is old_num) */
+ end = base+diff_num;
+
+ /* shift the old data, opening space for new data, from base to end */
+ /* do it in reverse order to avoid overlapping */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = shift_num-1; lin >= 0; lin--) /* all columns, shift_num lines */
+ memmove(ih->data->cells[lin+end], ih->data->cells[lin+base], ih->data->columns.num_alloc*sizeof(ImatCell));
+ memmove(ih->data->lines.sizes+end, ih->data->lines.sizes+base, shift_num*sizeof(int));
+ memmove(ih->data->lines.flags+end, ih->data->lines.flags+base, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the new space starting at base */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < diff_num; lin++) /* all columns, diff_num lines */
+ memset(ih->data->cells[lin+base], 0, ih->data->columns.num_alloc*sizeof(ImatCell));
+ memset(ih->data->lines.sizes+base, 0, diff_num*sizeof(int));
+ memset(ih->data->lines.flags+base, 0, diff_num*sizeof(unsigned char));
+ }
+ else /* DEL */
+ {
+ diff_num = old_num-num; /* size of the openned space */
+ shift_num = num-base; /* size of the data to be moved */
+ end = base+diff_num;
+
+ /* release memory from the opened space */
+ if (!ih->data->callback_mode)
+ {
+ for(lin = base; lin < end; lin++) /* all columns, base-end lines */
+ {
+ for (col = 0; col < ih->data->columns.num_alloc; col++)
+ {
+ ImatCell* cell = &(ih->data->cells[lin][col]);
+ if (cell->value)
+ {
+ free(cell->value);
+ cell->value = NULL;
+ }
+ cell->flags = 0;
+ }
+ }
+ }
+
+ /* move the old data to opened space from end to base */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < shift_num; lin++) /* all columns, shift_num lines */
+ memmove(ih->data->cells[lin+base], ih->data->cells[lin+end], ih->data->columns.num_alloc*sizeof(ImatCell));
+ memmove(ih->data->lines.sizes+base, ih->data->lines.sizes+end, shift_num*sizeof(int));
+ memmove(ih->data->lines.flags+base, ih->data->lines.flags+end, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the remaining space starting at num */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < diff_num; lin++) /* all columns, diff_num lines */
+ memset(ih->data->cells[lin+num], 0, ih->data->columns.num_alloc*sizeof(ImatCell));
+ memset(ih->data->lines.sizes+num, 0, diff_num*sizeof(int));
+ memset(ih->data->lines.flags+num, 0, diff_num*sizeof(unsigned char));
+ }
+}
+
+void iupMatrixMemReAllocColumns(Ihandle* ih, int old_num, int num, int base)
+{
+ int lin, col, end, diff_num, shift_num;
+
+ /* base is the first column where the change started */
+
+ /* If it doesn't have enough columns allocated, then allocate more space */
+ if (num > ih->data->columns.num_alloc) /* this also implicates that also num>old_num */
+ {
+ ih->data->columns.num_alloc = num;
+
+ /* new space are allocated at the end, later we need to move the old data and clear the available space */
+
+ if (!ih->data->callback_mode)
+ {
+ for(lin = 0; lin < ih->data->lines.num_alloc; lin++)
+ ih->data->cells[lin] = (ImatCell*)realloc(ih->data->cells[lin], ih->data->columns.num_alloc*sizeof(ImatCell));
+ }
+
+ ih->data->columns.sizes = (int*)realloc(ih->data->columns.sizes, ih->data->columns.num_alloc*sizeof(int));
+ ih->data->columns.flags = (unsigned char*)realloc(ih->data->columns.flags, ih->data->columns.num_alloc*sizeof(unsigned char));
+ }
+
+ if (old_num==num)
+ return;
+
+ if (num>old_num) /* ADD */
+ {
+ /* even if (old_num-base)>(num-old_num) memmove will correctly copy the memory */
+ /* then clear the openned space starting at base */
+
+ diff_num = num-old_num; /* size of the openned space */
+ shift_num = old_num-base; /* size of the data to be moved (base maximum is old_num) */
+ end = base+diff_num;
+
+ /* shift the old data, opening space for new data, from base to end */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, shift_num columns */
+ memmove(ih->data->cells[lin]+end, ih->data->cells[lin]+base, shift_num*sizeof(ImatCell));
+ memmove(ih->data->columns.sizes+end, ih->data->columns.sizes+base, shift_num*sizeof(int));
+ memmove(ih->data->columns.flags+end, ih->data->columns.flags+base, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the openned space starting at base */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, diff_num columns */
+ memset(ih->data->cells[lin]+base, 0, diff_num*sizeof(ImatCell));
+ memset(ih->data->columns.sizes+base, 0, diff_num*sizeof(int));
+ memset(ih->data->columns.flags+base, 0, diff_num*sizeof(unsigned char));
+ }
+ else /* DEL */
+ {
+ diff_num = old_num-num; /* size of the openned space */
+ shift_num = num-base; /* size of the data to be moved */
+ end = base+diff_num;
+
+ /* release memory from the opened space */
+ if (!ih->data->callback_mode)
+ {
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, base-end columns */
+ {
+ for(col = base; col < end; col++)
+ {
+ ImatCell* cell = &(ih->data->cells[lin][col]);
+ if (cell->value)
+ {
+ free(cell->value);
+ cell->value = NULL;
+ }
+ cell->flags = 0;
+ }
+ }
+ }
+
+ /* move the old data to opened space from end to base */
+ /* even if (num-base)>(old_num-num) memmove will correctly copy the memory */
+ if (shift_num)
+ {
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, shift_num columns */
+ memmove(ih->data->cells[lin]+base, ih->data->cells[lin]+end, shift_num*sizeof(ImatCell));
+ memmove(ih->data->columns.sizes+base, ih->data->columns.sizes+end, shift_num*sizeof(int));
+ memmove(ih->data->columns.flags+base, ih->data->columns.flags+end, shift_num*sizeof(unsigned char));
+ }
+
+ /* then clear the remaining space starting at num */
+ if (!ih->data->callback_mode)
+ for (lin = 0; lin < ih->data->lines.num_alloc; lin++) /* all lines, diff_num columns */
+ memset(ih->data->cells[lin]+num, 0, diff_num*sizeof(ImatCell));
+ memset(ih->data->columns.sizes+num, 0, diff_num*sizeof(int));
+ memset(ih->data->columns.flags+num, 0, diff_num*sizeof(unsigned char));
+ }
+}
diff --git a/iup/srccontrols/matrix/iupmat_mem.h b/iup/srccontrols/matrix/iupmat_mem.h
new file mode 100755
index 0000000..05a047b
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mem.h
@@ -0,0 +1,24 @@
+/** \file
+ * \brief iupmatrix control
+ * memory allocation.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_MEM_H
+#define __IUPMAT_MEM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void iupMatrixMemAlloc(Ihandle* ih);
+void iupMatrixMemRelease(Ihandle* ih);
+void iupMatrixMemReAllocLines (Ihandle* ih, int old_num, int num, int base);
+void iupMatrixMemReAllocColumns(Ihandle* ih, int old_num, int num, int base);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_mouse.c b/iup/srccontrols/matrix/iupmat_mouse.c
new file mode 100755
index 0000000..33b5fe7
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mouse.c
@@ -0,0 +1,212 @@
+/** \file
+ * \brief iupmatrix control
+ * mouse events
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to handle mouse events */
+/**************************************************************************/
+
+#include <stdlib.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_colres.h"
+#include "iupmat_aux.h"
+#include "iupmat_focus.h"
+#include "iupmat_mouse.h"
+#include "iupmat_key.h"
+#include "iupmat_mark.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+#include "iupmat_scroll.h"
+
+
+#define IMAT_DRAG_SCROLL_DELTA 5
+
+static void iMatrixMouseCallMoveCb(Ihandle* ih, int lin, int col)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "MOUSEMOVE_CB");
+ if (cb)
+ cb(ih, lin, col);
+}
+
+static int iMatrixMouseCallClickCb(Ihandle* ih, int press, int lin, int col, char* r)
+{
+ IFniis cb;
+
+ if (press)
+ cb = (IFniis)IupGetCallback(ih, "CLICK_CB");
+ else
+ cb = (IFniis)IupGetCallback(ih, "RELEASE_CB");
+
+ if (cb)
+ return cb(ih, lin, col, r);
+
+ return IUP_DEFAULT;
+}
+
+static void iMatrixMouseLeftPress(Ihandle* ih, int lin, int col, int shift, int ctrl, int dclick)
+{
+ if (dclick)
+ {
+ iupMatrixMarkMouseReset(ih);
+
+ if (lin==0 || col==0)
+ return;
+
+ /* if a double click NOT in the current cell */
+ if (lin != ih->data->lines.focus_cell || col != ih->data->columns.focus_cell)
+ {
+ /* leave the previous cell if the matrix previously had the focus */
+ if (ih->data->has_focus && iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ return;
+
+ iupMatrixFocusSet(ih, lin, col);
+
+ iupMatrixAuxCallEnterCellCb(ih);
+ }
+
+ if (iupMatrixEditShow(ih))
+ {
+ if(ih->data->datah == ih->data->droph)
+ IupSetAttribute(ih->data->datah, "SHOWDROPDOWN", "YES");
+
+ if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
+ if(atoi(IupGetGlobal("MOTIFNUMBER")) < 2203) /* since OpenMotif version 2.2.3 this is not necessary */
+ iupAttribSetStr(ih, "_IUPMAT_DOUBLE_CLICK", "1");
+ }
+ }
+ else /* single click */
+ {
+ if (shift && ih->data->mark_multiple && ih->data->mark_mode != IMAT_MARK_NO)
+ {
+ iupMatrixMarkMouseBlock(ih, lin, col);
+ }
+ else
+ {
+ ih->data->leftpressed = 1;
+
+ if (lin>0 && col>0)
+ {
+ if (iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ return;
+
+ iupMatrixFocusSet(ih, lin, col);
+
+ /* process mark before EnterCell */
+ if (ih->data->mark_mode != IMAT_MARK_NO)
+ iupMatrixMarkMouseItem(ih, ctrl, lin, col);
+
+ iupMatrixAuxCallEnterCellCb(ih);
+ }
+ else
+ {
+ /* only process marks if at titles */
+ if (ih->data->mark_mode != IMAT_MARK_NO)
+ iupMatrixMarkMouseItem(ih, ctrl, lin, col);
+ }
+ }
+ }
+}
+
+int iupMatrixMouseButton_CB(Ihandle* ih, int b, int press, int x, int y, char* r)
+{
+ int lin=-1, col=-1;
+
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+
+ /* reset press state */
+ ih->data->leftpressed = 0;
+
+ if (press)
+ {
+ /* The edit Focus callback is not called when the user clicks in the parent canvas.
+ so we have to compensate that. */
+ iupMatrixEditForceHidden(ih);
+ ih->data->has_focus = 1;
+ }
+
+ iupMatrixAuxGetLinColFromXY(ih, x, y, &lin, &col);
+
+ if (b == IUP_BUTTON1)
+ {
+ if (press)
+ {
+ iupMatrixKeyResetHomeEndCount(ih);
+
+ if (iupMatrixColResStart(ih, x, y))
+ return IUP_DEFAULT; /* Resize of the width a of a column was started */
+
+ if (lin!=-1 && col!=-1)
+ iMatrixMouseLeftPress(ih, lin, col, isshift(r), iscontrol(r), isdouble(r));
+ }
+ else
+ {
+ if (iupMatrixColResIsResizing(ih)) /* If it was made a column resize, finish it */
+ iupMatrixColResFinish(ih, x);
+ }
+ }
+ else
+ iupMatrixMarkMouseReset(ih);
+
+ if (lin!=-1 && col!=-1)
+ {
+ if (iMatrixMouseCallClickCb(ih, press, lin, col, r) == IUP_IGNORE)
+ return IUP_DEFAULT;
+ }
+
+ iupMatrixDrawUpdate(ih);
+ return IUP_DEFAULT;
+}
+
+int iupMatrixMouseMove_CB(Ihandle* ih, int x, int y)
+{
+ int lin, col;
+
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+
+ if (ih->data->leftpressed && ih->data->mark_multiple && ih->data->mark_mode != IMAT_MARK_NO)
+ {
+ if ((x < ih->data->columns.sizes[0] || x < IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.first > 1))
+ iupMatrixScrollLeft(ih);
+ else if ((x > ih->data->w - IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.last < ih->data->columns.num-1))
+ iupMatrixScrollRight(ih);
+
+ if ((y < ih->data->lines.sizes[0] || y < IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.first > 1))
+ iupMatrixScrollUp(ih);
+ else if ((y > ih->data->h - IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.last < ih->data->lines.num-1))
+ iupMatrixScrollDown(ih);
+
+ if (iupMatrixAuxGetLinColFromXY(ih, x, y, &lin, &col))
+ {
+ iupMatrixMarkMouseBlock(ih, lin, col);
+ iupMatrixDrawUpdate(ih);
+
+ iMatrixMouseCallMoveCb(ih, lin, col);
+ }
+ return IUP_DEFAULT;
+ }
+ else if(iupMatrixColResIsResizing(ih)) /* Make a resize in a column size */
+ iupMatrixColResMove(ih, x);
+ else /* Change cursor when it is passed on a join involving column titles */
+ iupMatrixColResCheckChangeCursor(ih, x, y);
+
+ if (iupMatrixAuxGetLinColFromXY(ih, x, y, &lin, &col))
+ iMatrixMouseCallMoveCb(ih, lin, col);
+
+ return IUP_DEFAULT;
+}
diff --git a/iup/srccontrols/matrix/iupmat_mouse.h b/iup/srccontrols/matrix/iupmat_mouse.h
new file mode 100755
index 0000000..17a09ec
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_mouse.h
@@ -0,0 +1,22 @@
+/** \file
+ * \brief iMatrixrix control
+ * mouse events.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_MOUSE_H
+#define __IUPMAT_MOUSE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixMouseButton_CB (Ihandle* ih, int b, int press, int x, int y, char* r);
+int iupMatrixMouseMove_CB (Ihandle* ih, int x, int y);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_numlc.c b/iup/srccontrols/matrix/iupmat_numlc.c
new file mode 100755
index 0000000..e48720a
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_numlc.c
@@ -0,0 +1,495 @@
+/** \file
+ * \brief iupmatrix control
+ * change number of columns or lines
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+/**************************************************************************/
+/* Functions to change the number of lines and columns of the matrix, */
+/* after it has been created. */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_edit.h"
+#include "iupmat_mem.h"
+#include "iupmat_numlc.h"
+#include "iupmat_draw.h"
+
+
+static void iMatrixUpdateLineAttributes(Ihandle* ih, int base, int count, int add)
+{
+#define IMAT_NUM_ATTRIB_LINE 6
+#define IMAT_ATTRIB_LINE_ONLY 3
+ char* attrib_format[IMAT_NUM_ATTRIB_LINE] = {
+ "BGCOLOR%d:*",
+ "FGCOLOR%d:*",
+ "FONT%d:*",
+ "BGCOLOR%d:%d",
+ "FGCOLOR%d:%d",
+ "FONT%d:%d"};
+ char* attrib = iupStrGetMemory(100);
+ int a, lin, col;
+ char* value;
+
+ if (add) /* ADD */
+ {
+ /* copy the attributes of the moved cells, from base+count to num */
+ /* do it in reverse order to avoid overlapping */
+ /* then clear the new space starting from base to base+count */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_LINE; a++)
+ {
+ for(lin = ih->data->lines.num-1; lin >= base+count; lin--)
+ {
+ /* Update the line attributes */
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin-count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update the cell attribute */
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin-count, col);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(lin = base; lin < base+count; lin++)
+ {
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+ else /* DEL */
+ {
+ /* copy the attributes of the moved cells from base+count to base */
+ /* then clear the remaining space starting at num */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_LINE; a++)
+ {
+ for(lin = base; lin < ih->data->lines.num; lin++)
+ {
+ /* Update the line attributes */
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin+count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update each cell attribute */
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin+count, col);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(lin = ih->data->lines.num; lin < ih->data->lines.num+count; lin++)
+ {
+ if (a < IMAT_ATTRIB_LINE_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], lin);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(col = 0; col < ih->data->columns.num; col++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+}
+
+static void iMatrixUpdateColumnAttributes(Ihandle* ih, int base, int count, int add)
+{
+#define IMAT_NUM_ATTRIB_COL 7
+#define IMAT_ATTRIB_COL_ONLY 4
+ char* attrib_format[IMAT_NUM_ATTRIB_COL] = {
+ "ALIGNMENT%d",
+ "BGCOLOR*:%d",
+ "FGCOLOR*:%d",
+ "FONT*:%d",
+ "BGCOLOR%d:%d",
+ "FGCOLOR%d:%d",
+ "FONT%d:%d"};
+ char* attrib = iupStrGetMemory(100);
+ int a, col, lin;
+ char* value;
+
+ if (add) /* ADD */
+ {
+ /* update the attributes of the moved cells, from base+count to num */
+ /* do it in reverse order to avoid overlapping */
+ /* then clear the new space starting from base to base+count */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_COL; a++)
+ {
+ for(col = ih->data->columns.num-1; col >= base+count; col--)
+ {
+ /* Update the column attributes */
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col-count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib,attrib_format[a],col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update the cell attributes */
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col-count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(col = base; col < base+count; col++)
+ {
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+ else /* DEL */
+ {
+ /* copy the attributes of the moved cells from base+count to base */
+ /* then clear the remaining space starting at num */
+
+ for(a = 0; a < IMAT_NUM_ATTRIB_COL; a++)
+ {
+ for(col = base; col < ih->data->columns.num; col++)
+ {
+ /* Update the column attributes */
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col+count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ /* Update the cell attributes */
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col+count);
+ value = iupAttribGet(ih, attrib);
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribStoreStr(ih, attrib, value);
+ }
+ }
+
+ for(col = ih->data->columns.num; col < ih->data->columns.num+count; col++)
+ {
+ if (a < IMAT_ATTRIB_COL_ONLY)
+ {
+ sprintf(attrib, attrib_format[a], col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ else for(lin = 0; lin < ih->data->lines.num; lin++)
+ {
+ sprintf(attrib, attrib_format[a], lin, col);
+ iupAttribSetStr(ih, attrib, NULL);
+ }
+ }
+ }
+ }
+}
+
+static int iMatrixGetStartEnd(const char* value, int *base, int *count, int max, int del)
+{
+ int ret;
+
+ if (!value)
+ return 0;
+
+ *base = 0;
+ *count = 1;
+
+ ret = sscanf(value, "%d-%d", base, count);
+ if (ret <= 0 || ret > 2)
+ return 0;
+ if (ret == 1)
+ *count = 1;
+
+ if (*count <= 0)
+ return 0;
+
+ if (del)
+ {
+ if (*base <= 0) /* the first valid element is always 1 */
+ *base = 1;
+
+ /* when del, base can be at the last element */
+ if (*base > max-1)
+ *base = max-1;
+
+ /* when del, count must be inside the existant range */
+ if (*base + *count > max)
+ *count = max - *base;
+ }
+ else
+ {
+ (*base)++; /* add after the given index, so increment to position the base */
+
+ if (*base <= 0) /* the first valid element is always 1 */
+ *base = 1;
+
+ /* when add, base can be just after the last element but not more */
+ if (*base > max)
+ *base = max;
+
+ /* when add, count can be any positive value */
+ }
+
+ return 1;
+}
+
+
+/**************************************************************************/
+/* Exported functions */
+/**************************************************************************/
+
+int iupMatrixSetAddLinAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, lines_num = ih->data->lines.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, lines_num, 0))
+ return 0;
+
+ /* if the focus cell is after the inserted area */
+ if (ih->data->lines.focus_cell >= base)
+ {
+ /* leave of the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* move it to the same cell */
+ ih->data->lines.focus_cell += count;
+ }
+
+ iupMatrixMemReAllocLines(ih, lines_num, lines_num+count, base);
+
+ ih->data->lines.num += count;
+ ih->data->need_calcsize = 1;
+
+ if (base < lines_num) /* If before the last line. */
+ iMatrixUpdateLineAttributes(ih, base, count, 1);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetDelLinAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, lines_num = ih->data->lines.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, lines_num, 1))
+ return 0;
+
+ /* if the focus cell is after the removed area */
+ if (ih->data->lines.focus_cell >= base)
+ {
+ /* leave of the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* if the focus cell is inside the removed area */
+ if (ih->data->lines.focus_cell <= base+count-1)
+ ih->data->lines.focus_cell = base; /* move it to the first existant cell */
+ else
+ ih->data->lines.focus_cell -= count; /* move it to the same cell */
+ }
+
+ iupMatrixMemReAllocLines(ih, lines_num, lines_num-count, base);
+
+ ih->data->lines.num -= count;
+ ih->data->need_calcsize = 1;
+
+ if (ih->data->lines.focus_cell >= ih->data->lines.num)
+ ih->data->lines.focus_cell = ih->data->lines.num-1;
+ if (ih->data->lines.focus_cell <= 0)
+ ih->data->lines.focus_cell = 1;
+
+ if (base < lines_num) /* If before the last line. (always true when deleting) */
+ iMatrixUpdateLineAttributes(ih, base, count, 0);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetAddColAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, columns_num = ih->data->columns.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, columns_num, 0))
+ return 0;
+
+ /* if the focus cell is after the inserted area */
+ if (ih->data->columns.focus_cell >= base)
+ {
+ /* leave the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* move it to the same cell */
+ ih->data->columns.focus_cell += count;
+ }
+
+ iupMatrixMemReAllocColumns(ih, columns_num, columns_num+count, base);
+
+ ih->data->columns.num += count;
+ ih->data->need_calcsize = 1;
+
+ if (base < columns_num) /* If before the last column. */
+ iMatrixUpdateColumnAttributes(ih, base, count, 1);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetDelColAttrib(Ihandle* ih, const char* value)
+{
+ int base, count, columns_num = ih->data->columns.num;
+
+ if (!ih->handle) /* do not store the action before map */
+ return 0;
+
+ if (!iMatrixGetStartEnd(value, &base, &count, columns_num, 1))
+ return 0;
+
+ /* if the focus cell is after the removed area */
+ if (ih->data->columns.focus_cell >= base)
+ {
+ /* leave the edition mode */
+ iupMatrixEditForceHidden(ih);
+
+ /* if the focus cell is inside the removed area */
+ if (ih->data->columns.focus_cell <= base+count-1)
+ ih->data->columns.focus_cell = base; /* move it to the first existant cell */
+ else
+ ih->data->columns.focus_cell -= count; /* move it to the same cell */
+ }
+
+ iupMatrixMemReAllocColumns(ih, columns_num, columns_num-count, base);
+
+ ih->data->columns.num -= count;
+ ih->data->need_calcsize = 1;
+
+ if (ih->data->columns.focus_cell >= ih->data->columns.num)
+ ih->data->columns.focus_cell = ih->data->columns.num-1;
+ if (ih->data->columns.focus_cell <= 0)
+ ih->data->columns.focus_cell = 1;
+
+ if (base < columns_num) /* If before the last column. (always true when deleting) */
+ iMatrixUpdateColumnAttributes(ih, base, count, 0);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+int iupMatrixSetNumLinAttrib(Ihandle* ih, const char* value)
+{
+ int num = 0;
+ if (iupStrToInt(value, &num))
+ {
+ if (num < 0) num = 0;
+
+ num++; /* add room for title line */
+
+ /* can be set before map */
+ if (ih->handle)
+ {
+ int base; /* base is after the end */
+ if (num >= ih->data->lines.num) /* add or alloc */
+ base = ih->data->lines.num;
+ else
+ base = num;
+ iupMatrixMemReAllocLines(ih, ih->data->lines.num, num, base);
+ }
+
+ ih->data->lines.num = num;
+ ih->data->need_calcsize = 1;
+
+ if (ih->handle)
+ iupMatrixDraw(ih, 1);
+ }
+
+ return 0;
+}
+
+int iupMatrixSetNumColAttrib(Ihandle* ih, const char* value)
+{
+ int num = 0;
+ if (iupStrToInt(value, &num))
+ {
+ if (num < 0) num = 0;
+
+ num++; /* add room for title column */
+
+ /* can be set before map */
+ if (ih->handle)
+ {
+ int base; /* base is after the end */
+ if (num >= ih->data->columns.num) /* add or alloc */
+ base = ih->data->columns.num;
+ else
+ base = num;
+ iupMatrixMemReAllocColumns(ih, ih->data->columns.num, num, base);
+ }
+
+ ih->data->columns.num = num;
+ ih->data->need_calcsize = 1;
+
+ if (ih->handle)
+ iupMatrixDraw(ih, 1);
+ }
+
+ return 0;
+}
diff --git a/iup/srccontrols/matrix/iupmat_numlc.h b/iup/srccontrols/matrix/iupmat_numlc.h
new file mode 100755
index 0000000..df5e16f
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_numlc.h
@@ -0,0 +1,27 @@
+/** \file
+ * \brief iupmatrix. change number of collumns or lines.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_NUMLC_H
+#define __IUPMAT_NUMLC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixSetAddLinAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetDelLinAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetAddColAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetDelColAttrib(Ihandle* ih, const char* value);
+
+int iupMatrixSetNumLinAttrib(Ihandle* ih, const char* value);
+int iupMatrixSetNumColAttrib(Ihandle* ih, const char* value);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmat_scroll.c b/iup/srccontrols/matrix/iupmat_scroll.c
new file mode 100755
index 0000000..24bbef2
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_scroll.c
@@ -0,0 +1,495 @@
+/** \file
+ * \brief iupmatrix control
+ * scrolling
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include <cd.h>
+
+#include "iup_object.h"
+#include "iup_stdcontrols.h"
+
+#include "iupmat_def.h"
+#include "iupmat_scroll.h"
+#include "iupmat_focus.h"
+#include "iupmat_aux.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+
+
+/* Macros used by "dir" parameter of the iMatrixScrollLine and iMatrixScrollColumn functions */
+#define IMAT_SCROLL_LEFT 0
+#define IMAT_SCROLL_RIGHT 1
+#define IMAT_SCROLL_UP 2
+#define IMAT_SCROLL_DOWN 3
+
+
+/**************************************************************************/
+/* Private functions */
+/**************************************************************************/
+
+
+static int iMatrixScrollIsFullVisibleLast(ImatLinColData *p)
+{
+ int i, sum = 0;
+
+ for(i = p->first; i <= p->last; i++)
+ sum += p->sizes[i];
+
+ if (sum > p->visible_size)
+ return 0;
+ else
+ return 1;
+}
+
+/* Scroll columns/lines in the left/top side of the matriz until the last column/line is FULLY visible.
+ -> m : Define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL] */
+static void iMatrixScrollToVisible(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (index < p->first)
+ {
+ p->first = index;
+ return;
+ }
+ else if (index > p->last)
+ {
+ /* Increment the first column/line until the index is visible */
+ while(index > p->last && p->last != (p->num - 1))
+ {
+ p->first++;
+ iupMatrixAuxUpdateLast(p);
+ }
+ }
+
+ if (index == p->last)
+ {
+ /* must increment util the last is fully visible */
+ while(index == p->last && p->last != (p->num - 1) && !iMatrixScrollIsFullVisibleLast(p))
+ {
+ p->first++;
+ iupMatrixAuxUpdateLast(p);
+ }
+ }
+}
+
+/* Callback to report to the user which visualization area of
+ the matrix changed. */
+static void iMatrixScrollCallScrollTopCb(Ihandle* ih)
+{
+ IFnii cb = (IFnii)IupGetCallback(ih, "SCROLLTOP_CB");
+ if (cb)
+ cb(ih, ih->data->lines.first, ih->data->columns.first);
+}
+
+static int iMatrixScrollGetNextNonEmpty(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ while(index < p->num && p->sizes[index] == 0)
+ index++;
+
+ if (index > p->num-1)
+ {
+ if (p->num == 1)
+ return 1;
+ else
+ return p->num-1;
+ }
+ else
+ return index;
+}
+
+static int iMatrixScrollGetPrevNonEmpty(Ihandle* ih, int m, int index)
+{
+ ImatLinColData* p;
+
+ if (m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ while(index > 0 && p->sizes[index] == 0)
+ index--;
+
+ if (index < 1)
+ return 1;
+ else
+ return index;
+}
+
+static void iMatrixScrollSetFocusScrollToVisible(Ihandle* ih, int m, int index)
+{
+ if (m == IMAT_PROCESS_COL)
+ iupMatrixFocusSet(ih, ih->data->lines.focus_cell, index);
+ else
+ iupMatrixFocusSet(ih, index, ih->data->columns.focus_cell);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+}
+
+/**************************************************************************/
+/* Exported functions */
+/**************************************************************************/
+
+
+/* Move using the cells of matrix.
+ Receive as a parameter a pointer to a function that will make the work,
+ in fact. This is done to avoid a test to each of the manipulation cursor
+ functions, verifying if it is necessary to call or not the scroll
+ callback. This is only done here.
+ -> func - pointer to the function that will make the movement
+ -> mode - parameter passed to func, specify if the movement request is of
+ the scrollbar or the keyboard
+ -> pos - parameter passed to func, that will be the handle position function
+ of the scrollbar, returning the scrollbar thumb position...
+ if func is other function, this parameter will be ignored
+ -> m - parameter passed to func, specify which is the mode of operation:
+ lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollMoveCursor(iupMatrixScrollMoveF func, Ihandle* ih, int mode, float pos, int m)
+{
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
+
+ iupMatrixEditForceHidden(ih);
+
+ func(ih, mode, pos, m);
+
+ if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
+ {
+ if (ih->data->columns.first != old_columns_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+
+ if (ih->data->lines.first != old_lines_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iMatrixScrollCallScrollTopCb(ih);
+
+ iupMatrixDraw(ih, 0);
+ }
+}
+
+void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col)
+{
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
+
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, col);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, lin);
+
+ if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
+ {
+ if (ih->data->columns.first != old_columns_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+
+ if (ih->data->lines.first != old_lines_first)
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iMatrixScrollCallScrollTopCb(ih);
+
+ iupMatrixDraw(ih, 1);
+ }
+}
+
+/* This function is called when the "home" key is pressed.
+ In the first time, go to the beginning of the line.
+ In the second time, go to the beginning of the page.
+ In the third time, go to the beginning of the matrix.
+ -> mode and pos : DO NOT USED.
+*/
+void iupMatrixScrollHome(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ if(ih->data->homekeycount == 0) /* go to the beginning of the line */
+ {
+ ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+ iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.first);
+ }
+ else if(ih->data->homekeycount == 1) /* go to the beginning of the visible page */
+ {
+ iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+ else if(ih->data->homekeycount == 2) /* go to the beginning of the matrix 1:1 */
+ {
+ ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+ ih->data->lines.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_LIN, 1);
+
+ iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+}
+
+/* This function is called when the "end" key is pressed.
+ In the first time, go to the end of the line.
+ In the second time, go to the end of the page.
+ In the third time, go to the end of the matrix.
+ -> mode and pos : DO NOT USED.
+*/
+void iupMatrixScrollEnd(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ if(ih->data->endkeycount == 0) /* go to the end of the line */
+ {
+ int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+ iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, last_col);
+ }
+ else if(ih->data->endkeycount == 1) /* go to the end of the visible page */
+ {
+ iupMatrixFocusSet(ih, ih->data->lines.last, ih->data->columns.last);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+ else if(ih->data->endkeycount == 2) /* go to the end of the matrix */
+ {
+ int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+ int last_lin = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_LIN, ih->data->lines.num-1);
+
+ iupMatrixFocusSet(ih, last_lin, last_col);
+
+ /* set for both because current focus maybe hidden */
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+ iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
+ }
+}
+
+/* This function is called to move a cell to the left or up.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollLeftUp(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell-1);
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first-1);
+ }
+}
+
+/* This function is called to move a cell to the right or down.
+ -> mode : indicate if the command from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollRightDown(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetNextNonEmpty(ih, m, p->focus_cell+1);
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetNextNonEmpty(ih, m, p->first+1);
+ }
+}
+
+/* This function is called to move a page to the left or up.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgLeft) or columns (PgUp) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPgLeftUp(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell - (p->last - p->first));
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first - (p->last - p->first));
+ }
+}
+
+/* This function is called to move a page to the right or down.
+ -> mode : indicate if the command was from the keyboard or the scrollbar. If scrollbar,
+ do not change the focus.
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgDown) or columns (PgRight) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPgRightDown(Ihandle* ih, int mode, float pos, int m)
+{
+ ImatLinColData* p;
+ (void)pos;
+
+ if(m == IMAT_PROCESS_LIN)
+ p = &(ih->data->lines);
+ else
+ p = &(ih->data->columns);
+
+ if (mode == IMAT_SCROLLKEY)
+ {
+ int next = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, p->focus_cell + (p->last - p->first));
+ iMatrixScrollSetFocusScrollToVisible(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first + (p->last - p->first));
+ }
+}
+
+void iupMatrixScrollCr(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+{
+ int oldlin = ih->data->lines.focus_cell;
+ int oldcol = ih->data->columns.focus_cell;
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+
+ /* called only for mode==IMAT_SCROLLKEY */
+
+ /* try the normal processing of next cell down */
+ iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN);
+
+ if(ih->data->lines.focus_cell == oldlin && ih->data->columns.focus_cell == oldcol)
+ {
+ /* If focus was not changed, it was because it is in the last line of the column.
+ Go to the next column of the same line. */
+ iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL);
+ }
+}
+
+/* This function is called when a drag is performed in the scrollbar.
+ -> x : scrollbar thumb position, value between 0 and 1
+ -> mode : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+*/
+void iupMatrixScrollPos(Ihandle* ih, int mode, float pos, int m)
+{
+ int scroll_pos, index, vp;
+ float d;
+ ImatLinColData* p;
+ (void)mode;
+
+ if (m == IMAT_PROCESS_LIN)
+ {
+ p = &(ih->data->lines);
+ d = IupGetFloat(ih, "DY");
+ }
+ else
+ {
+ p = &(ih->data->columns);
+ d = IupGetFloat(ih, "DX");
+ }
+
+ if (p->num == 1)
+ {
+ p->first = 1;
+ return;
+ }
+
+ scroll_pos = (int)(pos * p->total_size + 0.5);
+
+ vp = 0;
+ for(index = 1; index < p->num; index++)
+ {
+ vp += p->sizes[index];
+ if (vp > scroll_pos)
+ break;
+ }
+
+ if (index == p->num)
+ {
+ if (p->num == 1)
+ index = 1;
+ else
+ index = p->num-1;
+ }
+
+ p->first = index;
+}
+
+int iupMatrixScroll_CB(Ihandle* ih, int action, float x, float y)
+{
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+
+ switch(action)
+ {
+ case IUP_SBUP : iupMatrixScrollUp(ih); break;
+ case IUP_SBDN : iupMatrixScrollDown(ih); break;
+ case IUP_SBPGUP : iupMatrixScrollPgUp(ih); break;
+ case IUP_SBPGDN : iupMatrixScrollPgDown(ih); break;
+ case IUP_SBRIGHT : iupMatrixScrollRight(ih); break;
+ case IUP_SBLEFT : iupMatrixScrollLeft(ih); break;
+ case IUP_SBPGRIGHT : iupMatrixScrollPgRight(ih); break;
+ case IUP_SBPGLEFT : iupMatrixScrollPgLeft(ih); break;
+ case IUP_SBPOSV : iupMatrixScrollPosVer(ih,y); break;
+ case IUP_SBPOSH : iupMatrixScrollPosHor(ih,x); break;
+ case IUP_SBDRAGV : iupMatrixScrollPosVer(ih,y); break;
+ case IUP_SBDRAGH : iupMatrixScrollPosHor(ih,x); break;
+ }
+
+ iupMatrixDrawUpdate(ih);
+
+ return IUP_DEFAULT;
+}
diff --git a/iup/srccontrols/matrix/iupmat_scroll.h b/iup/srccontrols/matrix/iupmat_scroll.h
new file mode 100755
index 0000000..582442b
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmat_scroll.h
@@ -0,0 +1,69 @@
+/** \file
+ * \brief iupmatrix control
+ * scrolling.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUPMAT_SCROLL_H
+#define __IUPMAT_SCROLL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int iupMatrixScroll_CB(Ihandle* ih, int action, float x, float y);
+
+void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col);
+
+typedef void (*iupMatrixScrollMoveF)(Ihandle* ih, int mode, float pos, int m);
+void iupMatrixScrollMoveCursor(iupMatrixScrollMoveF func, Ihandle* ih, int mode, float pos, int m);
+
+/* Used only by the macros bellow */
+void iupMatrixScrollHome (Ihandle* ih, int, float, int);
+void iupMatrixScrollEnd (Ihandle* ih, int, float, int);
+void iupMatrixScrollLeftUp (Ihandle* ih, int, float, int);
+void iupMatrixScrollRightDown (Ihandle* ih, int, float, int);
+void iupMatrixScrollPgLeftUp (Ihandle* ih, int, float, int);
+void iupMatrixScrollPgRightDown(Ihandle* ih, int, float, int);
+void iupMatrixScrollPos (Ihandle* ih, int, float, int);
+void iupMatrixScrollCr (Ihandle* ih, int, float, int);
+
+/* Mode used to "walk" inside the matrix.
+ It shows if the movement request was from the scrollbar or from a key.
+ Possible values for the "mode" parameter of the iupMatrixScrollMoveCursor function.
+ */
+#define IMAT_SCROLLBAR 0
+#define IMAT_SCROLLKEY 1
+
+/* Macros to help during the call of iupMatrixScrollMoveCursor function */
+
+/* used in the keyboard processing module */
+#define iupMatrixScrollKeyHome(ih) iupMatrixScrollMoveCursor(iupMatrixScrollHome , ih, IMAT_SCROLLKEY, 0, 0)
+#define iupMatrixScrollKeyEnd(ih) iupMatrixScrollMoveCursor(iupMatrixScrollEnd , ih, IMAT_SCROLLKEY, 0, 0)
+#define iupMatrixScrollKeyPgUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyPgDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollKeyUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollKeyLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollKeyCr(ih) iupMatrixScrollMoveCursor(iupMatrixScrollCr , ih, IMAT_SCROLLKEY, 0, 0)
+
+/* Used by the scrollbar callback only */
+#define iupMatrixScrollUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollPgUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollPgLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollPgDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+#define iupMatrixScrollPgRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+#define iupMatrixScrollPosVer(ih, y) iupMatrixScrollMoveCursor(iupMatrixScrollPos , ih, IMAT_SCROLLBAR, y, IMAT_PROCESS_LIN)
+#define iupMatrixScrollPosHor(ih, x) iupMatrixScrollMoveCursor(iupMatrixScrollPos , ih, IMAT_SCROLLBAR, x, IMAT_PROCESS_COL)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/iup/srccontrols/matrix/iupmatrix.c b/iup/srccontrols/matrix/iupmatrix.c
new file mode 100755
index 0000000..20d618d
--- /dev/null
+++ b/iup/srccontrols/matrix/iupmatrix.c
@@ -0,0 +1,980 @@
+/** \file
+ * \brief IupMatrix control core
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupcontrols.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvfont.h"
+#include "iup_stdcontrols.h"
+#include "iup_controls.h"
+#include "iup_register.h"
+
+#include "iupmat_def.h"
+#include "iupmat_getset.h"
+#include "iupmat_scroll.h"
+#include "iupmat_aux.h"
+#include "iupmat_mem.h"
+#include "iupmat_mouse.h"
+#include "iupmat_focus.h"
+#include "iupmat_key.h"
+#include "iupmat_numlc.h"
+#include "iupmat_colres.h"
+#include "iupmat_mark.h"
+#include "iupmat_edit.h"
+#include "iupmat_draw.h"
+
+
+int iupMatrixIsValid(Ihandle* ih, int check_cells)
+{
+ if (!ih->data->cddbuffer)
+ return 0;
+ if (check_cells && ((ih->data->columns.num == 0) || (ih->data->lines.num == 0)))
+ return 0;
+ return 1;
+}
+
+static int iMatrixSetOriginAttrib(Ihandle* ih, const char* value)
+{
+ int lin = -1, col = -1;
+
+ /* Get the parameters. The '*' indicates that want to keep the table in
+ the same line or column */
+ if (iupStrToIntInt(value, &lin, &col, ':') != 2)
+ {
+ if (lin != -1)
+ col = ih->data->columns.first;
+ else if (col != -1)
+ lin = ih->data->lines.first;
+ else
+ return 0;
+ }
+
+ /* Check if the cell exists */
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ /* Can not be a title */
+ if((lin < 1) || (col < 1))
+ return 0;
+
+ ih->data->columns.first = col;
+ ih->data->lines.first = lin;
+
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+ iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
+
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+static int iMatrixSetShowAttrib(Ihandle* ih, const char* value)
+{
+ int lin = -1, col = -1;
+
+ /* Get the parameters. The '*' indicates that want to keep the table in
+ the same line or column */
+ if (iupStrToIntInt(value, &lin, &col, ':') != 2)
+ {
+ if (lin != -1)
+ col = ih->data->columns.first;
+ else if (col != -1)
+ lin = ih->data->lines.first;
+ else
+ return 0;
+ }
+
+ /* Check if the cell exists */
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ /* Can not be a title */
+ if((lin < 1) || (col < 1))
+ return 0;
+
+ if (!iupMatrixAuxIsCellFullVisible(ih, lin, col))
+ iupMatrixScrollToVisible(ih, lin, col);
+
+ return 0;
+}
+
+static char* iMatrixGetOriginAttrib(Ihandle* ih)
+{
+ char* val = iupStrGetMemory(100);
+ sprintf(val, "%d:%d", ih->data->lines.first, ih->data->columns.first);
+ return val;
+}
+
+static int iMatrixSetFocusCellAttrib(Ihandle* ih, const char* value)
+{
+ int lin = 0, col = 0;
+ if (iupStrToIntInt(value, &lin, &col, ':') == 2)
+ {
+ if (!iupMatrixCheckCellPos(ih, lin, col))
+ return 0;
+
+ if (lin <= 0 || col <= 0) /* title can NOT have the focus */
+ return 0;
+ if (lin >= ih->data->lines.num || col >= ih->data->columns.num)
+ return 0;
+
+ iupMatrixFocusSet(ih, lin, col);
+
+ if (ih->data->cddbuffer)
+ iupMatrixDrawUpdate(ih);
+ }
+
+ return 0;
+}
+
+static char* iMatrixGetFocusCellAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(100);
+ sprintf(str, "%d:%d", ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ return str;
+}
+
+static int iMatrixSetUseTitleSizeAttrib(Ihandle* ih, const char* value)
+{
+ /* can be set only before map */
+ if (ih->handle)
+ return 0;
+
+ if (iupStrBoolean(value))
+ ih->data->use_title_size = 1;
+ else
+ ih->data->use_title_size = 0;
+
+ return 0;
+}
+
+static char* iMatrixGetUseTitleSizeAttrib(Ihandle* ih)
+{
+ if (ih->data->use_title_size)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iMatrixSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ IupStoreAttribute(ih->data->datah, "VALUE", value);
+ else
+ iupMatrixCellSetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell, value);
+ return 0;
+}
+
+static char* iMatrixGetValueAttrib(Ihandle* ih)
+{
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ return iupMatrixEditGetValue(ih);
+ else
+ return iupMatrixCellGetValue(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+}
+
+static int iMatrixSetCaretAttrib(Ihandle* ih, const char* value)
+{
+ IupStoreAttribute(ih->data->texth, "CARET", value);
+ return 1;
+}
+
+static char* iMatrixGetCaretAttrib(Ihandle* ih)
+{
+ return IupGetAttribute(ih->data->texth, "CARET");
+}
+
+static int iMatrixSetSelectionAttrib(Ihandle* ih, const char* value)
+{
+ IupStoreAttribute(ih->data->texth, "SELECTION", value);
+ return 1;
+}
+
+static char* iMatrixGetSelectionAttrib(Ihandle* ih)
+{
+ return IupGetAttribute(ih->data->texth, "SELECTION");
+}
+
+static int iMatrixSetMultilineAttrib(Ihandle* ih, const char* value)
+{
+ IupStoreAttribute(ih->data->texth, "MULTILINE", value);
+ if (iupStrBoolean(value))
+ IupSetAttribute(ih->data->texth, "SCROLLBAR", "NO");
+ return 1;
+}
+
+static char* iMatrixGetMultilineAttrib(Ihandle* ih)
+{
+ return IupGetAttribute(ih->data->texth, "MULTILINE");
+}
+
+static char* iMatrixGetNumLinAttrib(Ihandle* ih)
+{
+ char* num = iupStrGetMemory(100);
+ sprintf(num, "%d", ih->data->lines.num-1);
+ return num;
+}
+
+static char* iMatrixGetNumColAttrib(Ihandle* ih)
+{
+ char* num = iupStrGetMemory(100);
+ sprintf(num, "%d", ih->data->columns.num-1);
+ return num;
+}
+
+static int iMatrixSetMarkModeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "CELL"))
+ ih->data->mark_mode = IMAT_MARK_CELL;
+ else if (iupStrEqualNoCase(value, "LIN"))
+ ih->data->mark_mode = IMAT_MARK_LIN;
+ else if (iupStrEqualNoCase(value, "COL"))
+ ih->data->mark_mode = IMAT_MARK_COL;
+ else if(iupStrEqualNoCase(value, "LINCOL"))
+ ih->data->mark_mode = IMAT_MARK_LINCOL;
+ else
+ ih->data->mark_mode = IMAT_MARK_NO;
+
+ if (ih->handle)
+ {
+ iupMatrixMarkClearAll(ih, 0);
+ iupMatrixDraw(ih, 1);
+ }
+ return 0;
+}
+
+static char* iMatrixGetMarkModeAttrib(Ihandle* ih)
+{
+ char* mark2str[] = {"NO", "LIN", "COL", "LINCOL", "CELL"};
+ return mark2str[ih->data->mark_mode];
+}
+
+static int iMatrixSetMarkAreaAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "NOT_CONTINUOUS"))
+ ih->data->mark_continuous = 0;
+ else
+ ih->data->mark_continuous = 1;
+
+ if (ih->handle)
+ {
+ iupMatrixMarkClearAll(ih, 0);
+ iupMatrixDraw(ih, 1);
+ }
+ return 0;
+}
+
+static char* iMatrixGetMarkAreaAttrib(Ihandle* ih)
+{
+ if (ih->data->mark_continuous)
+ return "CONTINUOUS";
+ else
+ return "NOT_CONTINUOUS";
+}
+
+static int iMatrixSetMarkMultipleAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ ih->data->mark_multiple = 1;
+ else
+ ih->data->mark_multiple = 0;
+
+ if (ih->handle)
+ {
+ iupMatrixMarkClearAll(ih, 0);
+ iupMatrixDraw(ih, 1);
+ }
+ return 0;
+}
+
+static char* iMatrixGetMarkMultipleAttrib(Ihandle* ih)
+{
+ if (ih->data->mark_multiple)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iMatrixSetEditModeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ iupMatrixEditShow(ih);
+ else
+ {
+ iupMatrixEditHide(ih);
+ iupMatrixDrawUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetEditModeAttrib(Ihandle* ih)
+{
+ if (iupMatrixEditIsVisible(ih))
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iMatrixSetActiveAttrib(Ihandle* ih, const char* value)
+{
+ iupBaseSetActiveAttrib(ih, value);
+ iupMatrixDraw(ih, 1);
+ return 0;
+}
+
+static int iMatrixSetWidthAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int col = 0;
+ if (iupStrToInt(name_id, &col))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetWidthAttrib(Ihandle* ih, const char* name_id)
+{
+ int col;
+ if (iupStrToInt(name_id, &col))
+ return iupMatrixGetSize(ih, col, IMAT_PROCESS_COL, 0);
+ return NULL;
+}
+
+static int iMatrixSetHeightAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0;
+ if (iupStrToInt(name_id, &lin))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetHeightAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin;
+ if (iupStrToInt(name_id, &lin))
+ return iupMatrixGetSize(ih, lin, IMAT_PROCESS_LIN, 0);
+ return NULL;
+}
+
+static int iMatrixSetRasterWidthAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int col = 0;
+ if (iupStrToInt(name_id, &col))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetRasterWidthAttrib(Ihandle* ih, const char* name_id)
+{
+ int col;
+ if (iupStrToInt(name_id, &col))
+ return iupMatrixGetSize(ih, col, IMAT_PROCESS_COL, 1);
+ return NULL;
+}
+
+static int iMatrixSetRasterHeightAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0;
+ if (iupStrToInt(name_id, &lin))
+ {
+ (void)value;
+ ih->data->need_calcsize = 1;
+ IupUpdate(ih);
+ }
+ return 1;
+}
+
+static char* iMatrixGetRasterHeightAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin;
+ if (iupStrToInt(name_id, &lin))
+ return iupMatrixGetSize(ih, lin, IMAT_PROCESS_LIN, 1);
+ return NULL;
+}
+
+static char* iMatrixGetAlignmentAttrib(Ihandle* ih, const char* name_id)
+{
+ char* align;
+ char str[50];
+ sprintf(str, "ALIGNMENT%s", name_id);
+ align = iupAttribGet(ih, str);
+ if (!align)
+ {
+ int col;
+ if (iupStrToInt(name_id, &col))
+ {
+ if (col == 0)
+ return "ALEFT";
+ else
+ return "ACENTER";
+ }
+ }
+
+ return NULL;
+}
+
+static int iMatrixSetIdValueAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int lin = 0, col = 0;
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (iupMatrixCheckCellPos(ih, lin, col))
+ iupMatrixCellSetValue(ih, lin, col, value);
+ }
+ return 0;
+}
+
+static char* iMatrixGetIdValueAttrib(Ihandle* ih, const char* name_id)
+{
+ int lin, col;
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ {
+ if (iupMatrixCheckCellPos(ih, lin, col))
+ return iupMatrixCellGetValue(ih, lin, col);
+ }
+ return NULL;
+}
+
+static int iMatrixSetFlagsAttrib(Ihandle* ih, const char* name_id, const char* value, unsigned char attr)
+{
+ if (name_id[0]==0)
+ return 1;
+ if (name_id[0]=='*' && name_id[1]==':')
+ {
+ int col;
+ name_id += 2; /* skip '*' and ':' */
+ if (iupStrToInt(name_id, &col))
+ iupMatrixCellSetFlag(ih, -1, col, attr, value!=NULL);
+ }
+ else if (name_id[strlen(name_id)-1]=='*')
+ {
+ int lin;
+ if (iupStrToInt(name_id, &lin))
+ iupMatrixCellSetFlag(ih, lin, -1, attr, value!=NULL);
+ }
+ else
+ {
+ int lin, col;
+ if (iupStrToIntInt(name_id, &lin, &col, ':') == 2)
+ iupMatrixCellSetFlag(ih, lin, col, attr, value!=NULL);
+ }
+ return 1;
+}
+
+static int iMatrixSetBgColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_BGCOLOR);
+}
+
+static int iMatrixSetFgColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FGCOLOR);
+}
+
+static int iMatrixSetFontAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FONT);
+}
+
+static int iMatrixSetFrameHorizColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ ih->data->checkframecolor = value!=NULL;
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FRAMEHCOLOR);
+}
+
+static int iMatrixSetFrameVertColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ ih->data->checkframecolor = value!=NULL;
+ return iMatrixSetFlagsAttrib(ih, name_id, value, IUPMAT_FRAMEVCOLOR);
+}
+
+static char* iMatrixGetFontAttrib(Ihandle* ih, const char* name_id)
+{
+ if (name_id[0]==0)
+ return iupGetFontAttrib(ih);
+ return NULL;
+}
+
+static char* iMatrixGetBgColorAttrib(Ihandle* ih, const char* name_id)
+{
+ if (name_id[0]==0)
+ {
+ /* check the hash table */
+ char *color = iupAttribGet(ih, "BGCOLOR");
+
+ /* If not defined return the default for normal cells */
+ if (!color)
+ color = IupGetGlobal("TXTBGCOLOR");
+
+ return color;
+ }
+ return NULL;
+}
+
+static char* iMatrixGetNumColVisibleAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(50);
+ sprintf(buffer, "%d", ih->data->columns.last - ih->data->columns.first);
+ return buffer;
+}
+
+static char* iMatrixGetNumLinVisibleAttrib(Ihandle* ih)
+{
+ char* buffer = iupStrGetMemory(50);
+ sprintf(buffer, "%d", ih->data->lines.last - ih->data->lines.first);
+ return buffer;
+}
+
+static char* iMatrixGetMaskDataAttrib(Ihandle* ih)
+{
+ /* Used only by the OLD iupmask API */
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+ return IupGetAttribute(ih->data->datah,"OLD_MASK_DATA");
+ else
+ return NULL;
+}
+
+
+/*****************************************************************************/
+/* Callbacks registered to the Canvas */
+/*****************************************************************************/
+
+
+static int iMatrixResize_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(ih->data->cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+ }
+
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ /* update size */
+ cdCanvasActivate(ih->data->cddbuffer);
+ cdCanvasGetSize(ih->data->cddbuffer, &ih->data->w, &ih->data->h, NULL, NULL);
+
+ iupMatrixEditForceHidden(ih);
+
+ ih->data->need_calcsize = 1;
+ iupMatrixDraw(ih, 0);
+
+ return IUP_DEFAULT;
+}
+
+static int iMatrixRedraw_CB(Ihandle* ih)
+{
+ if (!ih->data->cddbuffer)
+ return IUP_DEFAULT;
+
+ if (!ih->data->first_redraw)
+ {
+ ih->data->first_redraw = 1;
+ iupMatrixDraw(ih, 0);
+ }
+
+ iupMatrixDrawUpdate(ih);
+
+ return IUP_DEFAULT;
+}
+
+
+/***************************************************************************/
+
+
+static int iMatrixCreateMethod(Ihandle* ih, void **params)
+{
+ if (params && params[0])
+ {
+ char* action_cb = (char*)params[0];
+ iupAttribStoreStr(ih, "ACTION_CB", action_cb);
+ }
+
+ /* free the data allocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* change the IupCanvas default values */
+ iupAttribSetStr(ih, "SCROLLBAR", "YES");
+ iupAttribSetStr(ih, "BORDER", "NO");
+ iupAttribSetStr(ih, "CURSOR", "IupMatrixCrossCursor");
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "ACTION", (Icallback)iMatrixRedraw_CB);
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iMatrixResize_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iupMatrixMouseButton_CB);
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iupMatrixMouseMove_CB);
+ IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iupMatrixKeyPress_CB);
+ IupSetCallback(ih, "FOCUS_CB", (Icallback)iupMatrixFocus_CB);
+ IupSetCallback(ih, "SCROLL_CB", (Icallback)iupMatrixScroll_CB);
+
+ /* Create the edit fields */
+ iupMatrixEditCreate(ih);
+
+ /* defaults */
+ ih->data->datah = ih->data->texth;
+ ih->data->mark_continuous = 1;
+ ih->data->columns.num = 1;
+ ih->data->lines.num = 1;
+ ih->data->need_calcsize = 1;
+ ih->data->lines.first = 1;
+ ih->data->columns.first = 1;
+ ih->data->lines.focus_cell = 1;
+ ih->data->columns.focus_cell = 1;
+ ih->data->mark_lin1 = -1;
+ ih->data->mark_col1 = -1;
+ ih->data->mark_lin2 = -1;
+ ih->data->mark_col2 = -1;
+ ih->data->use_title_size = 0;
+
+ return IUP_NOERROR;
+}
+
+static int iMatrixMapMethod(Ihandle* ih)
+{
+ ih->data->cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ ih->data->cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->cdcanvas);
+
+ if (IupGetCallback(ih, "VALUE_CB"))
+ {
+ ih->data->callback_mode = 1;
+
+ if (!IupGetCallback(ih, "VALUE_EDIT_CB"))
+ iupAttribSetStr(ih, "READONLY", "YES");
+ }
+
+ iupMatrixMemAlloc(ih);
+
+ return IUP_NOERROR;
+}
+
+static void iMatrixUnMapMethod(Ihandle* ih)
+{
+ if(ih->data->cddbuffer)
+ {
+ cdKillCanvas(ih->data->cddbuffer);
+ ih->data->cddbuffer = NULL;
+ }
+
+ if(ih->data->cdcanvas)
+ {
+ cdKillCanvas(ih->data->cdcanvas);
+ ih->data->cdcanvas = NULL;
+ }
+
+ iupMatrixMemRelease(ih);
+}
+
+static int iMatrixGetNaturalWidth(Ihandle* ih)
+{
+ int width = 0, num, col;
+
+ num = iupAttribGetInt(ih, "NUMCOL_VISIBLE")+1; /* include the title column */
+
+ if (iupAttribGetInt(ih, "NUMCOL_VISIBLE_LAST"))
+ {
+ int start = ih->data->columns.num - (num-1); /* title is computed apart */
+ if (start<1) start=1;
+ width += iupMatrixAuxGetColumnWidth(ih, 0); /* compute title */
+ for(col = start; col < ih->data->columns.num; col++)
+ width += iupMatrixAuxGetColumnWidth(ih, col);
+ }
+ else
+ {
+ if (num > ih->data->columns.num)
+ num = ih->data->columns.num;
+ for(col = 0; col < num; col++)
+ width += iupMatrixAuxGetColumnWidth(ih, col);
+ }
+
+ return width;
+}
+
+static int iMatrixGetNaturalHeight(Ihandle* ih)
+{
+ int height = 0, num, lin;
+
+ num = iupAttribGetInt(ih, "NUMLIN_VISIBLE")+1; /* include the title line */
+
+ if (iupAttribGetInt(ih, "NUMLIN_VISIBLE_LAST"))
+ {
+ int start = ih->data->lines.num - (num-1); /* title is computed apart */
+ if (start<1) start=1;
+ height += iupMatrixAuxGetLineHeight(ih, 0); /* compute title */
+ for(lin = start; lin < ih->data->lines.num; lin++)
+ height += iupMatrixAuxGetLineHeight(ih, lin);
+ }
+ else
+ {
+ if (num > ih->data->lines.num)
+ num = ih->data->lines.num;
+ for(lin = 0; lin < num; lin++)
+ height += iupMatrixAuxGetLineHeight(ih, lin);
+ }
+
+ return height;
+}
+
+static void iMatrixComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+{
+ int natural_w = 0, natural_h = 0;
+ (void)expand; /* unset if not a container */
+
+ if (!ih->handle)
+ ih->data->canvas.sb = iupBaseGetScrollbar(ih);
+
+ /* add scrollbar */
+ if (ih->data->canvas.sb)
+ {
+ int sb_size = iupdrvGetScrollbarSize();
+ if (ih->data->canvas.sb & IUP_SB_HORIZ)
+ natural_w += sb_size;
+ if (ih->data->canvas.sb & IUP_SB_VERT)
+ natural_h += sb_size;
+ }
+
+ *w = natural_w + iMatrixGetNaturalWidth(ih);
+ *h = natural_h + iMatrixGetNaturalHeight(ih);
+}
+
+static void iMatrixCreateCursor(void)
+{
+ Ihandle *imgcursor;
+ unsigned char matrx_img_cur_excel[15*15] =
+ {
+ 0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 1,1,1,1,1,2,2,2,2,1,1,1,1,1,0,
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
+ 1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,
+ 0,1,1,1,1,2,2,2,2,1,1,1,1,1,1,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,2,2,2,2,1,1,0,0,0,0,
+ 0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ };
+
+ imgcursor = IupImage(15, 15, matrx_img_cur_excel);
+ IupSetAttribute(imgcursor, "0", "BGCOLOR");
+ IupSetAttribute(imgcursor, "1", "0 0 0");
+ IupSetAttribute(imgcursor, "2", "255 255 255");
+ IupSetAttribute(imgcursor, "HOTSPOT", "7:7"); /* Centered Hotspot */
+ IupSetHandle("IupMatrixCrossCursor", imgcursor);
+ IupSetHandle("matrx_img_cur_excel", imgcursor); /* for backward compatibility */
+}
+
+Iclass* iupMatrixGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "matrix";
+ ic->format = "A"; /* one optional callback name */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+ ic->has_attrib_id = 1; /* has attributes with IDs that must be parsed */
+
+ /* Class functions */
+ ic->Create = iMatrixCreateMethod;
+ ic->Map = iMatrixMapMethod;
+ ic->UnMap = iMatrixUnMapMethod;
+ ic->ComputeNaturalSize = iMatrixComputeNaturalSizeMethod;
+
+ /* Do not need to set base attributes because they are inherited from IupCanvas */
+
+ /* IupMatrix Callbacks */
+ /* --- Interaction --- */
+ iupClassRegisterCallback(ic, "ACTION_CB", "iiiis");
+ iupClassRegisterCallback(ic, "CLICK_CB", "iis");
+ iupClassRegisterCallback(ic, "RELEASE_CB", "iis");
+ iupClassRegisterCallback(ic, "MOUSEMOVE_CB", "ii");
+ iupClassRegisterCallback(ic, "ENTERITEM_CB", "ii");
+ iupClassRegisterCallback(ic, "LEAVEITEM_CB", "ii");
+ iupClassRegisterCallback(ic, "SCROLLTOP_CB", "ii");
+ /* --- Drawing --- */
+ iupClassRegisterCallback(ic, "BGCOLOR_CB", "iiIII");
+ iupClassRegisterCallback(ic, "FGCOLOR_CB", "iiIII");
+ iupClassRegisterCallback(ic, "FONT_CB", "ii=s");
+ iupClassRegisterCallback(ic, "DRAW_CB", "iiiiii");
+ iupClassRegisterCallback(ic, "DROPCHECK_CB", "ii");
+ /* --- Editing --- */
+ iupClassRegisterCallback(ic, "DROP_CB", "nii");
+ iupClassRegisterCallback(ic, "DROPSELECT_CB", "iinsii");
+ iupClassRegisterCallback(ic, "EDITION_CB", "iii");
+ /* --- Callback Mode --- */
+ iupClassRegisterCallback(ic, "VALUE_CB", "ii=s");
+ iupClassRegisterCallback(ic, "VALUE_EDIT_CB", "iis");
+ iupClassRegisterCallback(ic, "MARK_CB", "ii");
+ iupClassRegisterCallback(ic, "MARKEDIT_CB", "iii");
+
+ /* IupMatrix Attributes - CELL */
+ iupClassRegisterAttributeId(ic, "IDVALUE", iMatrixGetIdValueAttrib, iMatrixSetIdValueAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FOCUS_CELL", iMatrixGetFocusCellAttrib, iMatrixSetFocusCellAttrib, IUPAF_SAMEASSYSTEM, "1:1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* can be NOT mapped */
+ iupClassRegisterAttribute(ic, "VALUE", iMatrixGetValueAttrib, iMatrixSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "FGCOLOR", NULL, iMatrixSetFgColorAttrib, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttributeId(ic, "FONT", iMatrixGetFontAttrib, iMatrixSetFontAttrib, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttributeId(ic, "FRAMEHORIZCOLOR", NULL, iMatrixSetFrameHorizColorAttrib, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttributeId(ic, "FRAMEVERTCOLOR", NULL, iMatrixSetFrameVertColorAttrib, IUPAF_NOT_MAPPED);
+
+ /* IupMatrix Attributes - COLUMN */
+ iupClassRegisterAttributeId(ic, "ALIGNMENT", iMatrixGetAlignmentAttrib, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "SORTSIGN", NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - SIZE */
+ iupClassRegisterAttribute(ic, "NUMLIN", iMatrixGetNumLinAttrib, iupMatrixSetNumLinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMCOL", iMatrixGetNumColAttrib, iupMatrixSetNumColAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMLIN_VISIBLE", iMatrixGetNumLinVisibleAttrib, NULL, IUPAF_SAMEASSYSTEM, "3", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMCOL_VISIBLE", iMatrixGetNumColVisibleAttrib, NULL, IUPAF_SAMEASSYSTEM, "4", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMLIN_VISIBLE_LAST", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NUMCOL_VISIBLE_LAST", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "WIDTHDEF", NULL, NULL, IUPAF_SAMEASSYSTEM, "80", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "HEIGHTDEF", NULL, NULL, IUPAF_SAMEASSYSTEM, "8", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "WIDTH", iMatrixGetWidthAttrib, iMatrixSetWidthAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "HEIGHT", iMatrixGetHeightAttrib, iMatrixSetHeightAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "RASTERWIDTH", iMatrixGetRasterWidthAttrib, iMatrixSetRasterWidthAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "RASTERHEIGHT", iMatrixGetRasterHeightAttrib, iMatrixSetRasterHeightAttrib, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - MARK */
+ iupClassRegisterAttribute(ic, "MARKED", iupMatrixGetMarkedAttrib, iupMatrixSetMarkedAttrib, NULL, NULL, IUPAF_NO_INHERIT); /* noticed that MARKED must be mapped */
+ iupClassRegisterAttributeId(ic, "MARK", iupMatrixGetMarkAttrib, iupMatrixSetMarkAttrib, IUPAF_NO_INHERIT); /* noticed that for MARK the matrix must be mapped */
+ iupClassRegisterAttribute(ic, "MARK_MODE", iMatrixGetMarkModeAttrib, iMatrixSetMarkModeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARKMODE", iMatrixGetMarkModeAttrib, iMatrixSetMarkModeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AREA", iMatrixGetMarkAreaAttrib, iMatrixSetMarkAreaAttrib, IUPAF_SAMEASSYSTEM, "CONTINUOUS", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARKAREA", iMatrixGetMarkAreaAttrib, iMatrixSetMarkAreaAttrib, IUPAF_SAMEASSYSTEM, "CONTINUOUS", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MULTIPLE", iMatrixGetMarkMultipleAttrib, iMatrixSetMarkMultipleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARKMULTIPLE", iMatrixGetMarkMultipleAttrib, iMatrixSetMarkMultipleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - ACTION (only mapped) */
+ iupClassRegisterAttribute(ic, "ADDLIN", NULL, iupMatrixSetAddLinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DELLIN", NULL, iupMatrixSetDelLinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ADDCOL", NULL, iupMatrixSetAddColAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DELCOL", NULL, iupMatrixSetDelColAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ORIGIN", iMatrixGetOriginAttrib, iMatrixSetOriginAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOW", NULL, iMatrixSetShowAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "EDIT_MODE", iMatrixGetEditModeAttrib, iMatrixSetEditModeAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "REDRAW", NULL, iupMatrixDrawSetRedrawAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - EDITION */
+ iupClassRegisterAttribute(ic, "CARET", iMatrixGetCaretAttrib, iMatrixSetCaretAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SELECTION", iMatrixGetSelectionAttrib, iMatrixSetSelectionAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MULTILINE", iMatrixGetMultilineAttrib, iMatrixSetMultilineAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "MASK", NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupMatrix Attributes - GENERAL */
+ iupClassRegisterAttribute(ic, "USETITLESIZE", iMatrixGetUseTitleSizeAttrib, iMatrixSetUseTitleSizeAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "FRAMECOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "100 100 100", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "READONLY", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "RESIZEMATRIX", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "HIDEFOCUS", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* Overwrite IupCanvas Attributes */
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iMatrixSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttributeId(ic, "BGCOLOR", iMatrixGetBgColorAttrib, iMatrixSetBgColorAttrib, IUPAF_NOT_MAPPED);
+
+ /* IupMatrix Attributes - MASK */
+ iupClassRegisterAttribute(ic, "OLD_MASK_DATA", iMatrixGetMaskDataAttrib, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ if (!IupGetHandle("IupMatrixCrossCursor"))
+ iMatrixCreateCursor();
+
+ return ic;
+}
+
+
+/*****************************************************************************************************/
+
+
+Ihandle* IupMatrix(const char* action)
+{
+ void *params[2];
+ params[0] = (void*)action;
+ params[1] = NULL;
+ return IupCreatev("matrix", params);
+}
+
+void IupMatSetAttribute(Ihandle* ih, const char* a, int l, int c, char* v)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ IupSetAttribute(ih, attr, v);
+}
+
+void IupMatStoreAttribute(Ihandle* ih, const char* a, int l, int c, char* v)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ IupStoreAttribute(ih, attr, v);
+}
+
+char* IupMatGetAttribute(Ihandle* ih, const char* a, int l, int c)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ return IupGetAttribute(ih, attr);
+}
+
+int IupMatGetInt(Ihandle* ih, const char* a, int l, int c)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ return IupGetInt(ih, attr);
+}
+
+float IupMatGetFloat(Ihandle* ih, const char* a, int l, int c)
+{
+ char* attr = iupStrGetMemory(100);
+ sprintf(attr, "%s%d:%d", a, l, c);
+ return IupGetFloat(ih, attr);
+}
+
+void IupMatSetfAttribute(Ihandle* ih, const char* a, int l, int c, char* f, ...)
+{
+ static char v[SHRT_MAX];
+ char* attr = iupStrGetMemory(100);
+ va_list arglist;
+ sprintf(attr, "%s%d:%d", a, l, c);
+ va_start(arglist, f);
+ vsprintf(v, f, arglist);
+ va_end(arglist);
+ IupStoreAttribute(ih, attr, v);
+}