363 lines
12 KiB
C
363 lines
12 KiB
C
|
/** \file
|
||
|
* \brief IupMatrix Expansion Library.
|
||
|
*
|
||
|
* See Copyright Notice in "iup.h"
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <limits.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "iup.h"
|
||
|
#include "iupcbs.h"
|
||
|
|
||
|
#include "iup_array.h"
|
||
|
#include "iup_object.h"
|
||
|
#include "iup_attrib.h"
|
||
|
#include "iup_str.h"
|
||
|
#include "iup_matrixex.h"
|
||
|
|
||
|
|
||
|
static void iMatrixExFindDialogUpdateResult(ImatExData* matex_data, Ihandle* ih_button)
|
||
|
{
|
||
|
char* last_found = IupGetAttribute(matex_data->ih, "_IUP_LAST_FOUND");
|
||
|
if (!last_found)
|
||
|
IupSetStrAttribute(IupGetDialogChild(ih_button, "RESULT"), "TITLE", "_@IUP_NOT_FOUND");
|
||
|
else
|
||
|
{
|
||
|
char *lin_title, *col_title;
|
||
|
int lin, col;
|
||
|
iupStrToIntInt(last_found, &lin, &col, ':');
|
||
|
lin_title = IupGetAttributeId2(matex_data->ih, "", lin, 0);
|
||
|
col_title = IupGetAttributeId2(matex_data->ih, "", 0, col);
|
||
|
if (lin_title && col_title)
|
||
|
IupSetfAttribute(IupGetDialogChild(ih_button, "RESULT"), "TITLE", "%s %s (%s, %s)", IupGetLanguageString("IUP_FOUND_AT"), last_found, lin_title, col_title);
|
||
|
else if (lin_title)
|
||
|
IupSetfAttribute(IupGetDialogChild(ih_button, "RESULT"), "TITLE", "%s %s (%s, %d)", IupGetLanguageString("IUP_FOUND_AT"), last_found, lin_title, col);
|
||
|
else if (col_title)
|
||
|
IupSetfAttribute(IupGetDialogChild(ih_button, "RESULT"), "TITLE", "%s %s (%d, %s)", IupGetLanguageString("IUP_FOUND_AT"), last_found, lin, col_title);
|
||
|
else
|
||
|
IupSetfAttribute(IupGetDialogChild(ih_button, "RESULT"), "TITLE", "%s %s", IupGetLanguageString("IUP_FOUND_AT"), last_found);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int iMatrixExFindDialogFindNext_CB(Ihandle* ih_button)
|
||
|
{
|
||
|
Ihandle* text = IupGetDialogChild(ih_button, "FINDTEXT");
|
||
|
char* find = IupGetAttribute(text, "VALUE");
|
||
|
if (find && find[0]!=0)
|
||
|
{
|
||
|
ImatExData* matex_data = (ImatExData*)IupGetAttribute(ih_button, "MATRIX_EX_DATA");
|
||
|
int matchcase = IupGetInt(IupGetDialogChild(ih_button, "MATCHCASE"), "VALUE");
|
||
|
int matchwholecell = IupGetInt(IupGetDialogChild(ih_button, "MATCHWHOLECELL"), "VALUE");
|
||
|
int searchbyrow = IupGetInt(IupGetDialogChild(ih_button, "SEARCHBYROW"), "VALUE");
|
||
|
|
||
|
iupAttribSet(matex_data->ih, "FINDMATCHCASE", matchcase? "Yes": "No");
|
||
|
iupAttribSet(matex_data->ih, "FINDMATCHWHOLECELL", matchwholecell? "Yes": "No");
|
||
|
iupAttribSet(matex_data->ih, "FINDDIRECTION", searchbyrow? "RIGHTBOTTOM": "BOTTOMRIGHT"); /* Forward */
|
||
|
|
||
|
IupSetAttribute(IupGetDialogChild(ih_button, "RESULT"), "TITLE", "");
|
||
|
|
||
|
IupSetStrAttribute(matex_data->ih, "FIND", find);
|
||
|
|
||
|
iMatrixExFindDialogUpdateResult(matex_data, ih_button);
|
||
|
}
|
||
|
return IUP_DEFAULT;
|
||
|
}
|
||
|
|
||
|
static int iMatrixExFindDialogFindPrevious_CB(Ihandle* ih_button)
|
||
|
{
|
||
|
Ihandle* text = IupGetDialogChild(ih_button, "FINDTEXT");
|
||
|
char* find = IupGetAttribute(text, "VALUE");
|
||
|
if (find && find[0]!=0)
|
||
|
{
|
||
|
ImatExData* matex_data = (ImatExData*)IupGetAttribute(ih_button, "MATRIX_EX_DATA");
|
||
|
int matchcase = IupGetInt(IupGetDialogChild(ih_button, "MATCHCASE"), "VALUE");
|
||
|
int matchwholecell = IupGetInt(IupGetDialogChild(ih_button, "MATCHWHOLECELL"), "VALUE");
|
||
|
int searchbyrow = IupGetInt(IupGetDialogChild(ih_button, "SEARCHBYROW"), "VALUE");
|
||
|
|
||
|
iupAttribSet(matex_data->ih, "FINDMATCHCASE", matchcase? "Yes": "No");
|
||
|
iupAttribSet(matex_data->ih, "FINDMATCHWHOLECELL", matchwholecell? "Yes": "No");
|
||
|
iupAttribSet(matex_data->ih, "FINDDIRECTION", searchbyrow? "LEFTTOP": "TOPLEFT"); /* Backward */
|
||
|
|
||
|
IupSetAttribute(IupGetDialogChild(ih_button, "RESULT"), "TITLE", "");
|
||
|
|
||
|
IupSetStrAttribute(matex_data->ih, "FIND", find);
|
||
|
|
||
|
iMatrixExFindDialogUpdateResult(matex_data, ih_button);
|
||
|
}
|
||
|
return IUP_DEFAULT;
|
||
|
}
|
||
|
|
||
|
static int iMatrixExFindDialogClose_CB(Ihandle* ih_button)
|
||
|
{
|
||
|
IupHide(IupGetDialog(ih_button));
|
||
|
return IUP_DEFAULT;
|
||
|
}
|
||
|
|
||
|
static void iMatrixExFindCreateDialog(ImatExData* matex_data)
|
||
|
{
|
||
|
Ihandle *text_box, *options_box, *find_next, *find_prev, *result_box,
|
||
|
*dlg, *close, *dlg_box, *button_box, *parent;
|
||
|
|
||
|
text_box = IupSetAttributes(IupHbox(
|
||
|
IupLabel("_@IUP_FIND_WHAT"),
|
||
|
IupSetAttributes(IupText(NULL), "EXPAND=HORIZONTAL, NAME=FINDTEXT"),
|
||
|
NULL), "ALIGNMENT=ACENTER");
|
||
|
IupSetAttribute(text_box,"MARGIN","0x0");
|
||
|
|
||
|
options_box = IupHbox(
|
||
|
IupVbox(
|
||
|
IupSetAttributes(IupToggle("_@IUP_MATCH_CASE", NULL), "NAME=MATCHCASE"),
|
||
|
IupSetAttributes(IupToggle("_@IUP_MATCH_WHOLE_CELL", NULL), "NAME=MATCHWHOLECELL"),
|
||
|
NULL),
|
||
|
IupSetAttributes(IupFrame(IupRadio(IupHbox(
|
||
|
IupSetAttributes(IupToggle("_@IUP_BY_ROW", NULL), "NAME=SEARCHBYROW"),
|
||
|
IupSetAttributes(IupToggle("_@IUP_BY_COL", NULL), "NAME=SEARCHBYCOL"),
|
||
|
NULL))), "TITLE=_@IUP_SEARCH, MARGIN=5x5"),
|
||
|
NULL);
|
||
|
IupSetAttribute(options_box,"MARGIN","0x5");
|
||
|
|
||
|
find_prev = IupButton("_@IUP_FIND_PREVIOUS", NULL);
|
||
|
IupSetStrAttribute(find_prev, "PADDING", IupGetGlobal("DEFAULTBUTTONPADDING"));
|
||
|
IupSetCallback(find_prev, "ACTION", (Icallback)iMatrixExFindDialogFindPrevious_CB);
|
||
|
|
||
|
find_next = IupButton("_@IUP_FIND_NEXT", NULL);
|
||
|
IupSetStrAttribute(find_next, "PADDING", IupGetGlobal("DEFAULTBUTTONPADDING"));
|
||
|
IupSetCallback(find_next, "ACTION", (Icallback)iMatrixExFindDialogFindNext_CB);
|
||
|
|
||
|
close = IupButton("_@IUP_CLOSE", NULL);
|
||
|
IupSetStrAttribute(close, "PADDING", IupGetGlobal("DEFAULTBUTTONPADDING"));
|
||
|
IupSetCallback(close, "ACTION", (Icallback)iMatrixExFindDialogClose_CB);
|
||
|
|
||
|
button_box = IupHbox(
|
||
|
IupFill(),
|
||
|
find_prev,
|
||
|
find_next,
|
||
|
close,
|
||
|
NULL);
|
||
|
IupSetAttribute(button_box,"MARGIN","0x0");
|
||
|
IupSetAttribute(button_box, "NORMALIZESIZE", "HORIZONTAL");
|
||
|
|
||
|
result_box = IupHbox(
|
||
|
IupSetAttributes(IupLabel(""), "EXPAND=HORIZONTAL, NAME=RESULT"),
|
||
|
NULL);
|
||
|
IupSetAttribute(result_box,"MARGIN","0x0");
|
||
|
|
||
|
dlg_box = IupVbox(
|
||
|
text_box,
|
||
|
options_box,
|
||
|
button_box,
|
||
|
result_box,
|
||
|
NULL);
|
||
|
IupSetAttribute(dlg_box,"MARGIN","10x10");
|
||
|
IupSetAttribute(dlg_box,"GAP","5");
|
||
|
|
||
|
dlg = IupDialog(dlg_box);
|
||
|
|
||
|
parent = IupGetDialog(matex_data->ih);
|
||
|
|
||
|
IupSetStrAttribute(dlg,"TITLE","_@IUP_FIND");
|
||
|
IupSetAttribute(dlg,"MINBOX","NO");
|
||
|
IupSetAttribute(dlg,"MAXBOX","NO");
|
||
|
IupSetAttribute(dlg, "TOOLBOX","YES");
|
||
|
IupSetAttributeHandle(dlg,"DEFAULTENTER", find_next);
|
||
|
IupSetAttributeHandle(dlg,"DEFAULTESC", close);
|
||
|
IupSetAttributeHandle(dlg,"PARENTDIALOG", parent);
|
||
|
|
||
|
IupSetAttribute(dlg, "MATRIX_EX_DATA", (char*)matex_data); /* do not use "_IUP_MATEX_DATA" to enable inheritance */
|
||
|
|
||
|
if (IupGetAttribute(parent, "ICON"))
|
||
|
IupSetStrAttribute(dlg,"ICON", IupGetAttribute(parent, "ICON"));
|
||
|
else
|
||
|
IupSetStrAttribute(dlg,"ICON", IupGetGlobal("ICON"));
|
||
|
|
||
|
matex_data->find_dlg = dlg;
|
||
|
}
|
||
|
|
||
|
static void iMatrixExFindInitDialog(ImatExData* matex_data)
|
||
|
{
|
||
|
char* direction;
|
||
|
|
||
|
if (!(matex_data->find_dlg))
|
||
|
iMatrixExFindCreateDialog(matex_data);
|
||
|
|
||
|
IupSetStrAttribute(IupGetDialogChild(matex_data->find_dlg, "MATCHCASE"), "VALUE", iupAttribGetStr(matex_data->ih, "FINDMATCHCASE"));
|
||
|
IupSetStrAttribute(IupGetDialogChild(matex_data->find_dlg, "MATCHWHOLECELL"), "VALUE", iupAttribGetStr(matex_data->ih, "FINDMATCHWHOLECELL"));
|
||
|
IupSetAttribute(IupGetDialogChild(matex_data->find_dlg, "RESULT"), "TITLE", "");
|
||
|
|
||
|
direction = iupAttribGetStr(matex_data->ih, "FINDDIRECTION");
|
||
|
if (iupStrEqualNoCase(direction, "LEFTTOP") || iupStrEqualNoCase(direction, "RIGHTBOTTOM"))
|
||
|
IupSetAttribute(IupGetDialogChild(matex_data->find_dlg, "SEARCHBYROW"), "VALUE", "Yes");
|
||
|
else
|
||
|
IupSetAttribute(IupGetDialogChild(matex_data->find_dlg, "SEARCHBYCOL"), "VALUE", "Yes");
|
||
|
}
|
||
|
|
||
|
void iupMatrixExFindShowDialog(ImatExData* matex_data)
|
||
|
{
|
||
|
iMatrixExFindInitDialog(matex_data);
|
||
|
|
||
|
/* Only position the dialog at the first time,
|
||
|
then let the user choose the dialog position on screen */
|
||
|
if (!(matex_data->find_dlg->handle))
|
||
|
{
|
||
|
int x, y;
|
||
|
iupMatrixExGetDialogPosition(matex_data, &x, &y);
|
||
|
IupShowXY(matex_data->find_dlg, x, y);
|
||
|
}
|
||
|
else
|
||
|
IupShow(matex_data->find_dlg);
|
||
|
}
|
||
|
|
||
|
static int iMatrixMatch(Ihandle *ih, const char* findvalue, int lin, int col, int matchcase, int matchwholecell, int utf8)
|
||
|
{
|
||
|
char* value = iupMatrixExGetCellValue(ih, lin, col, 1); /* get displayed value */
|
||
|
if (!value || value[0] == 0)
|
||
|
return 0;
|
||
|
|
||
|
if (matchwholecell)
|
||
|
return iupStrCompareEqual(value, findvalue, matchcase, utf8, 0);
|
||
|
else
|
||
|
return iupStrCompareFind(value, findvalue, matchcase, utf8); /* search only for the first occurrence */
|
||
|
}
|
||
|
|
||
|
static int iMatrixExSetFind(Ihandle *ih, const char* value, int inc, int flip, int matchcase, int matchwholecell, int *lin, int *col, int search_cur_cell)
|
||
|
{
|
||
|
int utf8 = IupGetInt(NULL, "UTF8MODE");
|
||
|
int num_lin = IupGetInt(ih, "NUMLIN");
|
||
|
int num_col = IupGetInt(ih, "NUMCOL");
|
||
|
int count = (num_lin+1)*(num_col+1);
|
||
|
int pos, start_pos;
|
||
|
char* find_value;
|
||
|
|
||
|
find_value = iupStrDup(value);
|
||
|
|
||
|
if (search_cur_cell) /* search the current cell */
|
||
|
{
|
||
|
/* the FOCUSCELL is always visible and not a title */
|
||
|
if (iMatrixMatch(ih, find_value, *lin, *col, matchcase, matchwholecell, utf8))
|
||
|
{
|
||
|
free(find_value);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (flip)
|
||
|
pos = (*col)*(num_lin+1) + *lin;
|
||
|
else
|
||
|
pos = (*lin)*(num_col+1) + *col;
|
||
|
|
||
|
start_pos = pos;
|
||
|
do
|
||
|
{
|
||
|
pos += inc;
|
||
|
|
||
|
if (pos < 0) pos = count-1; /* if less than first cell, go to last */
|
||
|
if (pos > count-1) pos = 0; /* if more than last cell, go to first */
|
||
|
|
||
|
if (flip)
|
||
|
{
|
||
|
*lin = pos % (num_lin+1);
|
||
|
*col = pos / (num_lin+1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*lin = pos / (num_col+1);
|
||
|
*col = pos % (num_col+1);
|
||
|
}
|
||
|
|
||
|
if (*lin == 0 || *col == 0) /* don't search on titles */
|
||
|
continue;
|
||
|
|
||
|
if (pos == start_pos)
|
||
|
{
|
||
|
if (!search_cur_cell)
|
||
|
{
|
||
|
if (iMatrixMatch(ih, find_value, *lin, *col, matchcase, matchwholecell, utf8))
|
||
|
{
|
||
|
free(find_value);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
free(find_value);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!iupMatrixExIsLineVisible(ih, *lin) || !iupMatrixExIsColumnVisible(ih, *col))
|
||
|
continue;
|
||
|
|
||
|
} while (!iMatrixMatch(ih, find_value, *lin, *col, matchcase, matchwholecell, utf8));
|
||
|
|
||
|
free(find_value);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int iMatrixExSetFindAttrib(Ihandle *ih, const char* value)
|
||
|
{
|
||
|
int lin=1, col=1, search_cur_cell = 0;
|
||
|
int inc, flip, matchcase, matchwholecell;
|
||
|
char* direction;
|
||
|
|
||
|
if (!value || value[0]==0)
|
||
|
return 0;
|
||
|
|
||
|
IupGetIntInt(ih, "FOCUSCELL", &lin, &col);
|
||
|
|
||
|
direction = iupAttribGetStr(ih, "FINDDIRECTION");
|
||
|
if (iupStrEqualNoCase(direction, "LEFTTOP"))
|
||
|
{
|
||
|
flip = 0;
|
||
|
inc = -1;
|
||
|
}
|
||
|
else if (iupStrEqualNoCase(direction, "TOPLEFT"))
|
||
|
{
|
||
|
flip = 1;
|
||
|
inc = -1;
|
||
|
}
|
||
|
else if (iupStrEqualNoCase(direction, "BOTTOMRIGHT"))
|
||
|
{
|
||
|
flip = 1;
|
||
|
inc = +1;
|
||
|
}
|
||
|
else /* RIGHTBOTTOM */
|
||
|
{
|
||
|
flip = 0;
|
||
|
inc = +1;
|
||
|
}
|
||
|
matchcase = iupAttribGetInt(ih, "FINDMATCHCASE");
|
||
|
matchwholecell = iupAttribGetInt(ih, "FINDMATCHWHOLECELL");
|
||
|
|
||
|
{
|
||
|
int last_lin=0, last_col=0;
|
||
|
IupGetIntInt(ih, "_IUP_LAST_FOUND", &last_lin, &last_col);
|
||
|
if (last_lin!=lin || last_col!=col)
|
||
|
search_cur_cell = 1; /* search in the current cell */
|
||
|
}
|
||
|
|
||
|
if (iMatrixExSetFind(ih, value, inc, flip, matchcase, matchwholecell, &lin, &col, search_cur_cell))
|
||
|
{
|
||
|
IupSetfAttribute(ih,"FOCUSCELL", "%d:%d", lin, col);
|
||
|
IupSetfAttribute(ih,"SHOW", "%d:%d", lin, col);
|
||
|
IupSetAttribute(ih,"MARKED",NULL);
|
||
|
IupSetAttributeId2(ih,"MARK",lin,col,"1");
|
||
|
IupSetfAttribute(ih,"REDRAW","L%d", lin);
|
||
|
IupSetfAttribute(ih,"_IUP_LAST_FOUND", "%d:%d", lin, col);
|
||
|
IupSetFocus(ih);
|
||
|
}
|
||
|
else
|
||
|
IupSetAttribute(ih,"_IUP_LAST_FOUND", NULL);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void iupMatrixExRegisterFind(Iclass* ic)
|
||
|
{
|
||
|
iupClassRegisterAttribute(ic, "FIND", NULL, iMatrixExSetFindAttrib, NULL, NULL, IUPAF_NO_INHERIT);
|
||
|
|
||
|
iupClassRegisterAttribute(ic, "FINDDIRECTION", NULL, NULL, IUPAF_SAMEASSYSTEM, "RIGHTBOTTOM", IUPAF_NO_INHERIT);
|
||
|
iupClassRegisterAttribute(ic, "FINDMATCHCASE", NULL, NULL, IUPAF_SAMEASSYSTEM, "Yes", IUPAF_NO_INHERIT);
|
||
|
iupClassRegisterAttribute(ic, "FINDMATCHWHOLECELL", NULL, NULL, IUPAF_SAMEASSYSTEM, "Yes", IUPAF_NO_INHERIT);
|
||
|
}
|