#include <HTUtils.h>
#include <HTAlert.h>
#include <LYUtils.h>
#include <LYStrings.h>
#include <LYSearch.h>
#include <LYGlobalDefs.h>
#include <GridText.h>
#include <LYLeaks.h>
static BOOL link_has_target(int cur,
char *target)
{
LinkInfo *a = &links[cur];
OptionType *option;
char *stars = NULL;
const char *cp;
int count;
/*
* Search the hightext strings, if present, taking the case_sensitive
* setting into account.
*/
for (count = 0;; ++count) {
const char *text = LYGetHiliteStr(cur, count);
if (text == NULL)
break;
if (LYno_attr_strstr(text, target))
return TRUE;
}
/*
* Search the relevant form fields, taking the case_sensitive setting into
* account. - FM
*/
if ((a->l_form != NULL && a->l_form->value != NULL) &&
a->l_form->type != F_HIDDEN_TYPE) {
if (a->l_form->type == F_PASSWORD_TYPE) {
/*
* Check the actual, hidden password, and then the displayed
* string. - FM
*/
if (LYno_attr_strstr(a->l_form->value, target)) {
return TRUE;
}
StrAllocCopy(stars, a->l_form->value);
memset(stars, '*', strlen(stars));
if (LYno_attr_strstr(stars, target)) {
FREE(stars);
return TRUE;
}
FREE(stars);
} else if (a->l_form->type == F_OPTION_LIST_TYPE) {
/*
* Search the option strings that are displayed when the popup is
* invoked. - FM
*/
option = a->l_form->select_list;
while (option != NULL) {
if (LYno_attr_strstr(option->name, target)) {
return TRUE;
}
option = option->next;
}
} else if (a->l_form->type == F_RADIO_TYPE) {
/*
* Search for checked or unchecked parens. - FM
*/
if (a->l_form->num_value) {
cp = checked_radio;
} else {
cp = unchecked_radio;
}
if (LYno_attr_strstr(cp, target)) {
return TRUE;
}
} else if (a->l_form->type == F_CHECKBOX_TYPE) {
/*
* Search for checked or unchecked square brackets. - FM
*/
if (a->l_form->num_value) {
cp = checked_box;
} else {
cp = unchecked_box;
}
if (LYno_attr_strstr(cp, target)) {
return TRUE;
}
} else {
/*
* Check the values intended for display. May have been found
* already via the hightext search, but make sure here that the
* entire value is searched. - FM
*/
if (LYno_attr_strstr(a->l_form->value, target)) {
return TRUE;
}
}
}
return FALSE;
}
/*
* Search for the target string inside of the links that are currently
* displayed on the screen beginning with the one after the currently selected
* one. If found set cur to the new value and return TRUE. If not found do
* not reset cur and return FALSE.
*/
static int check_next_target_in_links(int *cur,
char *target)
{
int i;
if (nlinks != 0) {
for (i = *cur + 1; i < nlinks; ++i) {
if (link_has_target(i, target)) {
*cur = i;
return TRUE;
}
}
}
return FALSE;
}
static int check_prev_target_in_links(int *cur,
char *target)
{
int i;
if (nlinks != 0) {
for (i = *cur - 1; i >= 0; --i) {
if (link_has_target(i, target)) {
*cur = i;
return TRUE;
}
}
}
return FALSE;
}
/*
* Textsearch checks the prev_target variable to see if it is empty. If it is
* then it requests a new search string. It then searches the current file for
* the next instance of the search string and finds the line number that the
* string is on
*
* This is the primary USER search engine and is case sensitive or case
* insensitive depending on the 'case_sensitive' global variable
*/
BOOL textsearch(DocInfo *cur_doc, char *prev_target,
int target_size,
int direction)
{
int offset;
int oldcur = cur_doc->link;
static char prev_target_buffer[512]; /* Search string buffer */
static BOOL first = TRUE;
char *cp;
int ch = 0;
RecallType recall;
int QueryTotal;
int QueryNum;
BOOLEAN FirstRecall = TRUE;
/*
* Initialize the search string buffer. - FM
*/
if (first) {
*prev_target_buffer = '\0';
first = FALSE;
}
QueryTotal = (search_queries ? HTList_count(search_queries) : 0);
recall = ((QueryTotal >= 1) ? RECALL_URL : NORECALL);
QueryNum = QueryTotal;
if (direction != 0)
/*
* LYK_NEXT or LYK_PREV was pressed, so copy the buffer into
* prev_target.
*/
LYstrncpy(prev_target, prev_target_buffer, target_size);
if (strlen(prev_target) == 0) {
/*
* This is a new WHEREIS search ('/'), or LYK_NEXT was pressed but
* there was no previous search, so we need to get a search string from
* the user. - FM
*/
_statusline(ENTER_WHEREIS_QUERY);
if ((ch = LYgetstr(prev_target, VISIBLE, target_size, recall)) < 0) {
/*
* User cancelled the search via ^G. Restore prev_target and
* return. - FM
*/
LYstrncpy(prev_target, prev_target_buffer, target_size);
HTInfoMsg(CANCELLED);
return (FALSE);
}
}
check_recall:
if (strlen(prev_target) == 0 &&
!(recall && (ch == UPARROW || ch == DNARROW))) {
/*
* No entry. Simply return, retaining the current buffer. Because
* prev_target is now reset, highlighting of the previous search string
* will no longer occur, but it can be used again via LYK_NEXT or
* LYK_PREV.
*/
HTInfoMsg(CANCELLED);
return (FALSE);
}
if (recall && ch == UPARROW) {
if (FirstRecall) {
/*
* Use the current string or last query in the list. - FM
*/
FirstRecall = FALSE;
if (*prev_target_buffer) {
for (QueryNum = (QueryTotal - 1); QueryNum > 0; QueryNum--) {
if ((cp = (char *) HTList_objectAt(search_queries,
QueryNum)) != NULL &&
!strcmp(prev_target_buffer, cp)) {
break;
}
}
} else {
QueryNum = 0;
}
} else {
/*
* Go back to the previous query in the list. - FM
*/
QueryNum++;
}
if (QueryNum >= QueryTotal)
/*
* Roll around to the last query in the list. - FM
*/
QueryNum = 0;
if ((cp = (char *) HTList_objectAt(search_queries,
QueryNum)) != NULL) {
LYstrncpy(prev_target, cp, target_size);
if (*prev_target_buffer &&
!strcmp(prev_target_buffer, prev_target)) {
_statusline(EDIT_CURRENT_QUERY);
} else if ((*prev_target_buffer && QueryTotal == 2) ||
(!(*prev_target_buffer) && QueryTotal == 1)) {
_statusline(EDIT_THE_PREV_QUERY);
} else {
_statusline(EDIT_A_PREV_QUERY);
}
if ((ch = LYgetstr(prev_target, VISIBLE, target_size, recall)) < 0) {
/*
* User canceled the search via ^G. Restore prev_target and
* return. - FM
*/
LYstrncpy(prev_target, prev_target_buffer, target_size);
HTInfoMsg(CANCELLED);
return (FALSE);
}
goto check_recall;
}
} else if (recall && ch == DNARROW) {
if (FirstRecall) {
/*
* Use the current string or first query in the list. - FM
*/
FirstRecall = FALSE;
if (*prev_target_buffer) {
for (QueryNum = 0; QueryNum < (QueryTotal - 1); QueryNum++) {
if ((cp = (char *) HTList_objectAt(search_queries,
QueryNum)) != NULL &&
!strcmp(prev_target_buffer, cp)) {
break;
}
}
} else {
QueryNum = QueryTotal - 1;
}
} else {
/*
* Advance to the next query in the list. - FM
*/
QueryNum--;
}
if (QueryNum < 0)
/*
* Roll around to the first query in the list. - FM
*/
QueryNum = QueryTotal - 1;
if ((cp = (char *) HTList_objectAt(search_queries,
QueryNum)) != NULL) {
LYstrncpy(prev_target, cp, target_size);
if (*prev_target_buffer &&
!strcmp(prev_target_buffer, prev_target)) {
_statusline(EDIT_CURRENT_QUERY);
} else if ((*prev_target_buffer && QueryTotal == 2) ||
(!(*prev_target_buffer) && QueryTotal == 1)) {
_statusline(EDIT_THE_PREV_QUERY);
} else {
_statusline(EDIT_A_PREV_QUERY);
}
if ((ch = LYgetstr(prev_target, VISIBLE, target_size, recall)) < 0) {
/*
* User cancelled the search via ^G. Restore prev_target and
* return. - FM
*/
LYstrncpy(prev_target, prev_target_buffer, target_size);
HTInfoMsg(CANCELLED);
return (FALSE);
}
goto check_recall;
}
}
/*
* Replace the search string buffer with the new target. - FM
*/
LYstrncpy(prev_target_buffer, prev_target, sizeof(prev_target_buffer) - 1);
HTAddSearchQuery(prev_target_buffer);
if (direction < 0) {
offset = 0;
if (check_prev_target_in_links(&cur_doc->link, prev_target)) {
/*
* Found in link, changed cur, we're done.
*/
LYhighlight(OFF, oldcur, prev_target);
return (TRUE);
}
} else {
/*
* Search the links on the currently displayed page for the string,
* starting after the current link. - FM
*/
if (check_next_target_in_links(&cur_doc->link, prev_target)) {
/*
* Found in link, changed cur, we're done.
*/
LYhighlight(OFF, oldcur, prev_target);
return (TRUE);
}
/*
* We'll search the text starting from the link we are on, or the next
* page.
*/
if (nlinks == 0)
offset = (display_lines - 1);
else
offset = links[cur_doc->link].ly - 1;
}
/*
* Resume search, this time for all text. Set www_search_result if string
* found, and position the hit near top of screen.
*/
www_user_search((cur_doc->line + offset), cur_doc, prev_target, direction);
if (cur_doc->link != oldcur) {
LYhighlight(OFF, oldcur, prev_target);
return (TRUE);
}
return (BOOL) (www_search_result > 0);
}