iup-stack/iup/srccontrols/matrixex/iupmatex_find.c

363 lines
12 KiB
C
Raw Normal View History

2023-02-20 16:44:45 +00:00
/** \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);
}