/** \file * \brief Cells Control. * * See Copyright Notice in "iup.h" */ #include #include #include #include "iup.h" #include "iupcbs.h" #include "iupkey.h" #include #include #include #include #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" #define ICELLS_OUT -999 struct _IcontrolData { iupCanvas canvas; /* from IupCanvas (must reserve it) */ cdCanvas* cd_canvas; /* 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 */ IupSetInt(ih, "POSX", posx); IupSetInt(ih, "POSY", 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); IupSetInt(ih, "POSY", 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); IupSetInt(ih, "POSX", 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 iCellsAdjustScroll(Ihandle* ih, int canvas_w, int canvas_h) { int virtual_height, virtual_width; /* Getting the virtual size */ iCellsGetVirtualSize(ih, &virtual_width, &virtual_height); IupSetInt(ih, "XMAX", virtual_width); IupSetInt(ih, "YMAX", virtual_height); /* Setting the object scrollbar position */ IupSetInt(ih, "DX", canvas_w); IupSetInt(ih, "DY", canvas_h); } /* 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 oldxmin, oldxmax, oldymin, oldymax, oldclip; int w = ih->data->w; int h = ih->data->h; IFniiiiiiC draw_cb; cdCanvas* old_cnv = cdActiveCanvas(); /* Getting clipping area for post restore */ oldclip = cdCanvasClip(ih->data->cd_canvas, CD_QUERY); cdCanvasGetClipArea(ih->data->cd_canvas, &oldxmin, &oldxmax, &oldymin, &oldymax); if (ih->data->clipped) /* Clipping the cell area */ { int cxmin, cxmax, cymin, cymax; cdCanvasClip(ih->data->cd_canvas, 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->cd_canvas, cxmin, cxmax, cymin, cymax); } draw_cb = (IFniiiiiiC)IupGetCallback(ih, "DRAW_CB"); if (draw_cb) { if (old_cnv != ih->data->cd_canvas) /* backward compatibility code */ cdActivate(ih->data->cd_canvas); draw_cb(ih, i, j, xmin, xmax, ymin, ymax, ih->data->cd_canvas); if (old_cnv && old_cnv != ih->data->cd_canvas) { cdActivate(old_cnv); cdCanvasActivate(ih->data->cd_canvas); } } cdCanvasClip(ih->data->cd_canvas, oldclip); cdCanvasClipArea(ih->data->cd_canvas, 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->cd_canvas, CD_BLACK); cdCanvasRect(ih->data->cd_canvas, 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->cd_canvas, ih->data->bgcolor); cdCanvasClear(ih->data->cd_canvas); /* 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->cd_canvas == 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->cd_canvas); } static int iCellsRedraw_CB(Ihandle* ih) { if (!ih->data->cd_canvas) return IUP_DEFAULT; /* update display */ cdCanvasFlush(ih->data->cd_canvas); 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 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++) { if (!(xmin > w)) { int hspan = iCellsGetHspan(ih, i, j); int 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; /* 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) { int fline = iCellsGetFirstLine(ih); int fcol = iCellsGetFirstCol(ih); ret = cb(ih, fline, fcol); } if (ret == IUP_DEFAULT) iCellsRepaint(ih); return IUP_DEFAULT; } static int iCellsResize_CB(Ihandle* ih, int w, int h) { /* recalculate scrollbars limits */ iCellsAdjustScroll(ih, w, h); /* This could have changed the scrollbar visibility, so the canvas client size can change, so updated it twice. */ IupGetIntInt(ih, "DRAWSIZE", &w, &h); IupSetInt(ih, "DX", w); IupSetInt(ih, "DY", h); /* update canvas size */ cdCanvasActivate(ih->data->cd_canvas); cdCanvasGetSize(ih->data->cd_canvas, &ih->data->w, &ih->data->h, NULL, NULL); /* 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 int iCellsMotion_CB(Ihandle* ih, int x, int y, char* r) { int i, j; IFniiiis cb; y = cdIupInvertYAxis(y, ih->data->h); /* 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. */ 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 char* iCellsGetImageCanvasAttrib(Ihandle* ih) { return (char*)ih->data->cd_canvas; } static char* iCellsGetCanvasAttrib(Ihandle* ih) { cdCanvas* cd_canvas_front = (cdCanvas*)IupGetAttribute(ih, "_CD_CANVAS"); /* front buffer canvas */ return (char*)cd_canvas_front; } static char* iCellsGetFirstLineAttrib(Ihandle* ih) { return iupStrReturnInt(iCellsGetFirstLine(ih)); } static char* iCellsGetFirstColAttrib(Ihandle* ih) { return iupStrReturnInt(iCellsGetFirstCol(ih)); } static char* iCellsGetLimitsAttrib(Ihandle* ih, int i, int j) { int xmin, xmax, ymin, ymax; iCellsGetLimits(ih, i, j, &xmin, &xmax, &ymin, &ymax); return iupStrReturnStrf("%d:%d:%d:%d", xmin, xmax, ymin, ymax); } static int iCellsSetBufferizeAttrib(Ihandle* ih, const char* value) { if (iupStrBoolean(value)) ih->data->bufferize = 1; else { ih->data->bufferize = 0; iCellsAdjustScroll(ih, ih->data->w, ih->data->h); iCellsRepaint(ih); } return 0; } static char* iCellsGetBufferizeAttrib(Ihandle* ih) { return iupStrReturnBoolean (ih->data->bufferize); } static int iCellsSetRepaintAttrib(Ihandle* ih, const char* value) { (void)value; /* not used */ ih->data->bufferize = 0; iCellsAdjustScroll(ih, ih->data->w, ih->data->h); 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) { return iupStrReturnInt(ih->data->non_scrollable_cols); } 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) { return iupStrReturnInt(ih->data->non_scrollable_lins); } static int iCellsSetBoxedAttrib(Ihandle* ih, const char* value) { ih->data->boxed = iupStrBoolean(value); iCellsRepaint(ih); return 0; } static char* iCellsGetBoxedAttrib(Ihandle* ih) { return iupStrReturnBoolean(ih->data->boxed); } static int iCellsSetClippedAttrib(Ihandle* ih, const char* value) { ih->data->clipped = iupStrBoolean(value); iCellsRepaint(ih); return 0; } static char* iCellsGetClippedAttrib(Ihandle* ih) { return iupStrReturnBoolean(ih->data->clipped); } 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->cd_canvas = cdCreateCanvas(CD_IUPDBUFFER, ih); if (!ih->data->cd_canvas) return IUP_ERROR; return IUP_NOERROR; } static void iCellsUnMapMethod(Ihandle* ih) { if (ih->data->cd_canvas) { cdKillCanvas(ih->data->cd_canvas); ih->data->cd_canvas = NULL; } } static int iCellsCreateMethod(Ihandle* ih, void **params) { (void)params; /* free the data allocated by IupCanvas */ free(ih->data); ih->data = iupALLOCCTRLDATA(); /* change the IupCanvas default values */ iupAttribSet(ih, "SCROLLBAR", "YES"); iupAttribSet(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* iupCellsNewClass(void) { Iclass* ic = iupClassNew(iupRegisterFindClass("canvas")); ic->name = "cells"; ic->format = NULL; /* no parameters */ ic->nativetype = IUP_TYPECANVAS; ic->childtype = IUP_CHILDNONE; ic->is_interactive = 1; ic->has_attrib_id = 2; /* has attributes with two IDs that must be parsed */ /* Class functions */ ic->New = iupCellsNewClass; 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", "iiiiiiC"); 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); iupClassRegisterAttributeId2(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"); }