#include <HTUtils.h>
#include <HTAlert.h>
#include <LYUtils.h>
#include <LYStrings.h>
#include <LYSearch.h>
#include <LYGlobalDefs.h>
#include <GridText.h>
#include <LYLeaks.h>
/*
* 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.
*/
PRIVATE int check_for_target_in_links ARGS2(
int *, cur,
char *, new_target)
{
int i = *cur + 1;
OptionType *option;
char *stars = NULL, *cp;
if (nlinks == 0)
return(FALSE);
for (; i < nlinks; i++) {
/*
* Search the hightext string, and hightext2 if present,
* taking the case_sensitive setting into account. - FM
*/
if (((links[i].hightext != NULL && case_sensitive == TRUE) &&
LYno_attr_char_strstr(links[i].hightext, new_target)) ||
((links[i].hightext != NULL && case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(links[i].hightext, new_target))) {
break;
}
if (((links[i].hightext2 != NULL && case_sensitive == TRUE) &&
LYno_attr_char_strstr(links[i].hightext2, new_target)) ||
((links[i].hightext2 != NULL && case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(links[i].hightext2, new_target))) {
break;
}
/*
* Search the relevant form fields, taking the
* case_sensitive setting into account. - FM
*/
if ((links[i].form != NULL && links[i].form->value != NULL) &&
links[i].form->type != F_HIDDEN_TYPE) {
if (links[i].form->type == F_PASSWORD_TYPE) {
/*
* Check the actual, hidden password, and then
* the displayed string. - FM
*/
if (((case_sensitive == TRUE) &&
LYno_attr_char_strstr(links[i].form->value,
new_target)) ||
((case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(links[i].form->value,
new_target))) {
break;
}
StrAllocCopy(stars, links[i].form->value);
for (cp = stars; *cp != '\0'; cp++)
*cp = '*';
if (((case_sensitive == TRUE) &&
LYno_attr_char_strstr(stars, new_target)) ||
((case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(stars, new_target))) {
FREE(stars);
break;
}
FREE(stars);
} else if (links[i].form->type == F_OPTION_LIST_TYPE) {
/*
* Search the option strings that are displayed
* when the popup is invoked. - FM
*/
option = links[i].form->select_list;
while (option != NULL) {
if (((option->name != NULL &&
case_sensitive == TRUE) &&
LYno_attr_char_strstr(option->name, new_target)) ||
((option->name != NULL &&
case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(option->name,
new_target))) {
break;
}
option = option->next;
}
if (option != NULL) {
break;
}
} else if (links[i].form->type == F_RADIO_TYPE) {
/*
* Search for checked or unchecked parens. - FM
*/
if (links[i].form->num_value) {
cp = checked_radio;
} else {
cp = unchecked_radio;
}
if (((case_sensitive == TRUE) &&
LYno_attr_char_strstr(cp, new_target)) ||
((case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(cp, new_target))) {
break;
}
} else if (links[i].form->type == F_CHECKBOX_TYPE) {
/*
* Search for checked or unchecked square brackets. - FM
*/
if (links[i].form->num_value) {
cp = checked_box;
} else {
cp = unchecked_box;
}
if (((case_sensitive == TRUE) &&
LYno_attr_char_strstr(cp, new_target)) ||
((case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(cp, new_target))) {
break;
}
} 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 (((case_sensitive == TRUE) &&
LYno_attr_char_strstr(links[i].form->value,
new_target)) ||
((case_sensitive == FALSE) &&
LYno_attr_char_case_strstr(links[i].form->value,
new_target))) {
break;
}
}
}
}
if (i == nlinks)
return(FALSE);
*cur = i;
return(TRUE);
}
/*
* 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
*
*/
PUBLIC BOOL textsearch ARGS3(
document *, cur_doc,
char *, prev_target,
BOOL, next)
{
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, 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 : NORECALL);
QueryNum = QueryTotal;
if (next)
/*
* LYK_NEXT was pressed, so copy the
* buffer into prev_target. - FM
*/
strcpy(prev_target, prev_target_buffer);
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,
sizeof(prev_target_buffer), recall)) < 0) {
/*
* User cancelled the search via ^G.
* Restore prev_target and return. - FM
*/
strcpy(prev_target, prev_target_buffer);
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. - FM
*/
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) {
strcpy(prev_target, cp);
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,
sizeof(prev_target_buffer), recall)) < 0) {
/*
* User canceled the search via ^G.
* Restore prev_target and return. - FM
*/
strcpy(prev_target, prev_target_buffer);
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) {
strcpy(prev_target, cp);
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,
sizeof(prev_target_buffer), recall)) < 0) {
/*
* User cancelled the search via ^G.
* Restore prev_target and return. - FM
*/
strcpy(prev_target, prev_target_buffer);
HTInfoMsg(CANCELLED);
return(FALSE);
}
goto check_recall;
}
}
/*
* Replace the search string buffer with the new target. - FM
*/
strcpy(prev_target_buffer, prev_target);
HTAddSearchQuery(prev_target_buffer);
/*
* Search the links on the currently displayed page for
* the string, starting after the current link. - FM
*/
if (check_for_target_in_links(&cur_doc->link, prev_target)) {
/*
* Found in link, changed cur, we're done.
*/
highlight(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);
if (cur_doc->link != oldcur) {
highlight(OFF, oldcur, prev_target);
return(TRUE);
}
return (BOOL) (www_search_result > 0);
}