Back to index

tetex-bin  3.0
Defines | Functions | Variables
search-internal.c File Reference
#include "xdvi-config.h"
#include "xdvi.h"
#include <locale.h>
#include <ctype.h>
#include "dvi-init.h"
#include "dvi-draw.h"
#include "search-internal.h"
#include "search-dialog.h"
#include "message-window.h"
#include "statusline.h"
#include "events.h"
#include "encodings.h"
#include "pagesel.h"
#include "util.h"
#include "x_util.h"
#include "string-utils.h"
#include "mag.h"
#include "pagehist.h"

Go to the source code of this file.

Defines

#define SWITCH_TO_UTF8   1
#define DEBUG_SEARCH   0
#define GET_BBOX(bbox, shrink, x, y, w, h)

Functions

void search_signal_page_changed (void)
static void reset_info (struct word_info *w_info)
static void generate_highlight_expose (const struct word_info *info)
static void draw_bboxes (const struct word_info *info)
Boolean search_have_match (int pageno)
int search_inside_bbox_match (int x, int y)
void search_draw_inverted_regions (void)
static void shift_info_down (struct search_info *searchinfo, struct word_info *info, struct page_mapping *page_mapping)
static void shift_info_up (struct word_info *info, struct page_mapping *page_mapping)
static void append_to_info (struct word_info *info, const char *str)
static void append_info (struct word_info *info1, const struct word_info *info2)
static void prepend_info (const struct word_info *info1, struct word_info *info2)
static Boolean is_utf8_ideograph (const unsigned char *p)
static void dump_buffer (const struct word_info *info, size_t offset, FILE *fp, outputFormatT fmt)
static void scan_page (FILE *fp, int pageno, struct word_info *w_info)
static Boolean do_scan_page (struct word_info *w_info, struct search_settings *settings, struct page_mapping *page_mapping, int buffer_offset, int pageno, searchDirectionT direction)
static void try_match (const struct word_info *info, const struct search_settings *settings, struct search_info *searchinfo)
static void erase_match_highlighting (struct word_info *info, Boolean flag)
static void highlight_match (struct search_settings *settings, const struct word_info *w_info, const struct page_mapping *page_mapping)
char * get_text_selection (int *len, int ulx, int uly, int lrx, int lry)
Boolean search_extract_text (outputFormatT fmt, struct select_pages_info *pinfo)
void search_erase_highlighting (Boolean reset)
static void message_search_ended (XtPointer arg)
void search_restart (XtPointer arg)
static void normalize_newline (char *str)
static Boolean reinit_searchterm (struct search_settings *settings, const char *encoding)
void search_reset_info (void)
static void warn_no_regex (void)
static Boolean scan_two_pages (struct search_settings *settings, struct word_info *info, struct page_mapping *page_mapping, int curr_page)
void search_dvi (XtPointer arg)

Variables

const int BBOX_LOWER_MARGIN = 2
const int BBOX_UPPER_MARGIN = 1
static struct word_infom_info = NULL
static int m_match_page = -1
static Boolean m_changed_page = False
static Boolean m_highlight_region_changed = True

Define Documentation

#define DEBUG_SEARCH   0

Definition at line 105 of file search-internal.c.

#define GET_BBOX (   bbox,
  shrink,
  x,
  y,
  w,
  h 
)
Value:
x = (bbox.ulx + shrink / 2) / shrink - BBOX_UPPER_MARGIN;      \
       y = (bbox.uly + shrink / 2) / shrink - BBOX_UPPER_MARGIN;      \
       w = (bbox.lrx - bbox.ulx + shrink - 1) / shrink                \
           + BBOX_UPPER_MARGIN + BBOX_LOWER_MARGIN + 1;        \
       h = (bbox.lry - bbox.uly + shrink - 1) / shrink                \
           + BBOX_UPPER_MARGIN + BBOX_LOWER_MARGIN + 2;

Definition at line 123 of file search-internal.c.

#define SWITCH_TO_UTF8   1

Definition at line 70 of file search-internal.c.


Function Documentation

static void append_info ( struct word_info info1,
const struct word_info info2 
) [static]

Definition at line 445 of file search-internal.c.

{
    if (info2->txt_buf_size > 0) {
       info1->txt_buf = xrealloc(info1->txt_buf, sizeof *(info1->txt_buf)
                              * (info1->txt_buf_size + info2->txt_buf_size));
       memcpy(info1->txt_buf + info1->curr_buf_idx, info2->txt_buf, info2->txt_buf_size);
       info1->txt_buf_size += info2->txt_buf_size;
       info1->curr_buf_idx += info2->curr_buf_idx;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void append_to_info ( struct word_info info,
const char *  str 
) [static]

Definition at line 428 of file search-internal.c.

{
    size_t len = strlen(str);
    size_t new_size = info->txt_buf_size;
    while (len >= new_size) { /* space for trailing 0 */
       new_size++;
    }
    if (new_size > info->txt_buf_size) {
       info->txt_buf_size = new_size;
       info->txt_buf = xrealloc(info->txt_buf, sizeof *(info->txt_buf) * info->txt_buf_size);
    }
    memcpy(info->txt_buf + info->curr_buf_idx, str, len + 1); /* also copy trailing 0 */
    info->curr_buf_idx += len;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Boolean do_scan_page ( struct word_info w_info,
struct search_settings settings,
struct page_mapping page_mapping,
int  buffer_offset,
int  pageno,
searchDirectionT  direction 
) [static]

Definition at line 583 of file search-internal.c.

{
    struct word_info page_info = { NULL, 0, 0, NULL, 0, 0, NULL, NULL, 0, False, True, False };
    page_info.settings = settings;
    ASSERT(buffer_offset >= 0, "buffer_offset must have been initialized");
    page_info.buffer_offset = buffer_offset;
    TRACE_FIND((stderr, "scanning page: %d; from_pos: %d", pageno, settings->searchinfo->from_pos));

    if (read_events(EV_NOWAIT) & EV_GE_FIND_CANCEL) {
       TRACE_FIND((stderr, "interrupted!!"));
       return False;
    }
    
    scan_page(globals.dvi_file.bak_fp, pageno, &page_info);

    /*     TRACE_FIND((stderr, "scanned buffer of length %d on page %d; contents: |%s|", */
    /*               page_info.curr_buf_idx, pageno, page_info.txt_buf)); */
    
    /* terminate page */
    append_to_info(&page_info, "\n");
    if (direction == SEARCH_DOWN) {
       /* append to existing info */
       append_info(w_info, &page_info);
       page_mapping->offset = w_info->curr_buf_idx;
    }
    else {
       prepend_info(&page_info, w_info);
       /*     TRACE_FIND((stderr, "buffer after prepending: |%s|", w_info->txt_buf)); */
       page_mapping->offset = page_info.curr_buf_idx;
    }
    page_mapping->pageno = pageno;
    
    return True;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void draw_bboxes ( const struct word_info info) [static]

Definition at line 200 of file search-internal.c.

{
    size_t i;
    static GC bboxGC = 0;
    static Boolean highlight_inverted_bak;

    if (bboxGC != 0 && highlight_inverted_bak != resource.match_highlight_inverted) {
       XFreeGC(DISP, bboxGC);
       bboxGC = 0;
    }
    highlight_inverted_bak = resource.match_highlight_inverted;
    
    if (resource.match_highlight_inverted) {
       if (MAGNIFIER_ACTIVE && !INSIDE_MANE_WIN)
           return;
       
       TRACE_FIND((stderr, "-- EXPOSED region: x %d, y %d, w %d, h %d",
                  globals.win_expose.min_x, globals.win_expose.min_y, globals.win_expose.max_x - globals.win_expose.min_x, globals.win_expose.max_y - globals.win_expose.min_y));
       
       if (bboxGC == 0) {
           XGCValues values;
           unsigned long valuemask;
           
           values.function = GXinvert; /* was: GXxor; see bug #850788 */
           if (values.function == GXinvert) {
              valuemask = GCFunction;
           }
           else {
              values.foreground = WhitePixelOfScreen(SCRN) ^ BlackPixelOfScreen(SCRN);
/*            fprintf(stderr, "foreground: 0x%lx, white pixel: 0x%lx, black pixel: 0x%lx\n", */
/*                   values.foreground, WhitePixelOfScreen(SCRN), BlackPixelOfScreen(SCRN)); */
              valuemask = GCFunction | GCForeground;
           }
           bboxGC = XCreateGC(DISP, XtWindow(globals.widgets.top_level), valuemask, &values);
       }
    }
    else if (bboxGC == 0) {
       XGCValues values;
       values.function = GXcopy;
       values.line_width = 2;
       values.cap_style = CapRound;
       values.foreground = resource.hl_Pixel;
       values.background = resource.back_Pixel;
       bboxGC = XCreateGC(DISP, XtWindow(globals.widgets.top_level),
                        GCFunction | GCLineWidth | GCCapStyle | GCForeground | GCBackground, &values);
    }

    TRACE_FIND((stderr, "bboxes_idx: %lu", (unsigned long)info->bboxes_idx));
    for (i = 0; info->bboxes != NULL && i <= info->bboxes_idx && info->bboxes[i].ulx < INT_MAX; i++) {
       int x, y, w, h;

       if (info->bboxes[i].ulx > 10000 || info->bboxes[i].uly > 10000) {
           TRACE_FIND((stderr, "skipping box: x %d, y %d",
                     info->bboxes[i].ulx, info->bboxes[i].uly));
           continue;
       }
       
       GET_BBOX(info->bboxes[i], currwin.shrinkfactor, x, y, w, h);
       TRACE_FIND((stderr, "DRAWING box: x %d, y %d, w %d, h %d; shrink: %d",
                  x, y, w, h, currwin.shrinkfactor));
       if (resource.match_highlight_inverted) {
           if (clip_region(&x, &y, &w, &h)) {
              TRACE_FIND((stderr, "CLIPPED box: x %d, y %d, w %d, h %d",
                         x, y, w, h));
              TEST_DELAY("Redrawing BBOX ............... ");
              XFillRectangle(DISP, mane.win, bboxGC, x, y, w, h);
              TEST_DELAY("Inverting BBOX ............... ");
           }
       }
       /*     XDrawRectangle(DISP, mane.win, globals.gc.high, x, y, w + 0, h + 0); */
       /*     clearexpose(&mane, x, y, w + 3, h + 3); */
       /*     XDrawRectangle(DISP, mane.win, globals.gc.high, x, y, w + 2, h + 2); */
       /*         XDrawRectangle(DISP, mane.win, globals.gc.high, x + 1, y + 1, w, h); */
       else {
           static XPoint points[5] = { {0,0}, {0,0}, {0,0}, {0,0}, {0,0} };
           
           h++;
           
           points[0].x = x;
           points[0].y = y;
           
           points[1].x = w;
           
           points[2].y = h;
           
           points[3].x = -w;
           
           points[4].y = -h;
           
           XDrawLines(DISP, mane.win, bboxGC, points, 5, CoordModePrevious);
       }

       if (!MAGNIFIER_ACTIVE) {
           /* note: inverted y_max y_min, since we want to display the full box here */
           scroll_page_if_needed(x + w, x, y + h, y);
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dump_buffer ( const struct word_info info,
size_t  offset,
FILE fp,
outputFormatT  fmt 
) [static]

Definition at line 518 of file search-internal.c.

{
    size_t i = offset, len, tot_len;

    if (info->txt_buf == NULL)
       return;
    
    tot_len = strlen(info->txt_buf);
    while (i < tot_len) {
       if (fmt == FMT_UTF8) { /* just dump as-is */
           fputc(info->txt_buf[i++], fp);
       }
       else { /* convert to iso-latin1, rendering unknown characters as `?' */
           uint32_t ucs4;
           const char *ret;

           /* first apply normalization heurisitcs also used by search */
           len = utf8_to_ucs4(info->txt_buf + i, &ucs4, strlen(info->txt_buf + i));
           if ((ret = search_normalize_chars(ucs4)) != NULL)
              fputs(ret, fp);
           else if (ucs4 <= 0xff) /* in iso-latin1 range */
              fputc((unsigned char)ucs4, fp);
           else
              fprintf(fp, "\\%.4lX", (unsigned long)ucs4);
           i += len;
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void erase_match_highlighting ( struct word_info info,
Boolean  flag 
) [static]

Definition at line 817 of file search-internal.c.

{
    size_t i;

    if (info == NULL || (MAGNIFIER_ACTIVE && !INSIDE_MANE_WIN))
       return;

    for (i = 0; info->bboxes != NULL && i <= info->bboxes_idx && info->bboxes[i].ulx < INT_MAX; i++) {
       int x, y, w, h;
       GET_BBOX(info->bboxes[i], currwin.shrinkfactor, x, y, w, h);
       if (resource.match_highlight_inverted) {
           if (flag || m_highlight_region_changed) {
              clearexpose(&mane, x, y, w, h);
           }
           else if (clip_region(&x, &y, &w, &h)) {
              TRACE_FIND((stderr, "ERASING box: x %d, y %d, w %d, h %d",
                         x, y, w, h));
              TEST_DELAY("Showing BBOX ............... ");
              XClearArea(DISP, mane.win, x, y, w, h, False);
              TEST_DELAY("Clearing BBOX ............... ");
           }
       }
       else if (flag) {
           /* erase only the existing marks, not the entire bounding box, to avoid flashing of
              the text inside the bounding box. 1 pixel added to w, h just to make sure in case of
              rounding errors. */
           h++;
           clearexpose(&mane, x - 1, y - 1, 2, h + 2);
           clearexpose(&mane, x - 1, y - 1, w + 2, 2);
           clearexpose(&mane, x + w - 1, y - 1, 2, h + 2);
           clearexpose(&mane, x - 1, y + h - 1, w + 2, 2);
       }
    }
    if (flag) {
       reset_info(info);
       info = NULL;
    }
    else
       m_highlight_region_changed = False;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void generate_highlight_expose ( const struct word_info info) [static]

Definition at line 174 of file search-internal.c.

{
    int x1 = INT_MAX, y1 = INT_MAX, x2 = 0, y2 = 0;
    size_t i;
    for (i = 0; info->bboxes != NULL && i <= info->bboxes_idx && info->bboxes[i].ulx < INT_MAX; i++) {
       if (info->bboxes[i].ulx < x1)
           x1 = info->bboxes[i].ulx;
       if (info->bboxes[i].uly < y1)
           y1 = info->bboxes[i].uly;
       if (info->bboxes[i].lrx > x2)
           x2 = info->bboxes[i].lrx;
       if (info->bboxes[i].lry > y2)
           y2 = info->bboxes[i].lry;
    }
#if 0
    fprintf(stderr, "region for exposure: %d,%d to %d,%d\n",
           x1, y1, x2, y2);
#endif /* 0 */
    x1 -= MAX(BBOX_UPPER_MARGIN, BBOX_LOWER_MARGIN) - 2;
    y1 -= MAX(BBOX_UPPER_MARGIN, BBOX_LOWER_MARGIN) - 2;
    x2 += MAX(BBOX_UPPER_MARGIN, BBOX_LOWER_MARGIN) + 2;
    y2 += MAX(BBOX_UPPER_MARGIN, BBOX_LOWER_MARGIN) + 2;
    clearexpose(&mane, x1, y1, x2 - x1, y2 - y1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* get_text_selection ( int len,
int  ulx,
int  uly,
int  lrx,
int  lry 
)

Definition at line 1010 of file search-internal.c.

{
    struct word_info txt_info = { NULL, 0, 0, NULL, 0, 0, NULL, NULL, 0, False, False, True };
    struct bbox text_bbox;
    
    text_bbox.ulx = ulx;
    text_bbox.uly = uly;
    text_bbox.lrx = lrx;
    text_bbox.lry = lry;

    txt_info.bboxes = &text_bbox;

    /* initialize buffer with empty string */
    txt_info.txt_buf_size = 1;
    txt_info.txt_buf = xmalloc(txt_info.txt_buf_size);
    txt_info.txt_buf[0] = '\0';

    /* this enlarges the buffer as needed */
    scan_page(globals.dvi_file.bak_fp, current_page, &txt_info);
    
    *len = txt_info.txt_buf_size;
    return txt_info.txt_buf;
    
#if 0
    /*     fprintf(stderr, "========== SELECTION (len %d):\n", txt_info.curr_buf_idx); */
    /*     dump_buffer(&txt_info, 0, stderr, FMT_ISO_8859_1); */
    /*     fprintf(stderr, "==========\n"); */

    buf = xmalloc(4 * txt_info.curr_buf_idx + 1); /* just in case we get many non-printables */
    while (i < txt_info.curr_buf_idx) {
       uint32_t ucs4;
       const char *ret;
       
       /* first apply normalization heurisitcs also used by search */
       size_t len = utf8_to_ucs4(txt_info.txt_buf + i, &ucs4, strlen(txt_info.txt_buf + i));
       if ((ret = search_normalize_chars(ucs4)) != NULL) {
           size_t len_ret = strlen(ret);
           memcpy(buf + offset, ret, len_ret);
           offset += len_ret;
       }      
       else if (ucs4 <= 0xff) { /* in iso-latin1 range */
           buf[offset++] = (unsigned char)ucs4;
       }
       else {
           sprintf(buf + offset, "\\%.4lX", ucs4);
           offset += 4;
       }
       i += len;
    }
    buf[offset] = '\0';
    free(txt_info.txt_buf);
    return buf;
#endif /* 0 */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void highlight_match ( struct search_settings settings,
const struct word_info w_info,
const struct page_mapping page_mapping 
) [static]

Definition at line 859 of file search-internal.c.

{
    const int context = 10;
    int match_page, i, j = 0;
    static struct word_info curr_info = { NULL, 0, 0, NULL, 0, 0, NULL, NULL, 0, True, False, False };
    struct search_info *searchinfo = settings->searchinfo;
    Boolean match_wrapped = False;
    
    curr_info.settings = settings;
    curr_info.page_mapping = page_mapping;

    TRACE_FIND((stderr, "MATCH from pos %d to %d:",
              searchinfo->from_pos, searchinfo->to_pos));
    
    if (globals.debug & DBG_FIND) {
       fprintf(stderr, "current page_mapping:\n");
       for (i = 0; i < 2; i++) {
           fprintf(stderr, "%d: %d\n", page_mapping[i].pageno, page_mapping[i].offset);
       }
    }

    TRACE_FIND((stderr, "to_pos: %d, %d", searchinfo->to_pos, page_mapping[0].offset));
    if (searchinfo->from_pos < page_mapping[0].offset) {
       match_page = page_mapping[0].pageno;
       if (searchinfo->to_pos > page_mapping[0].offset) {
           match_wrapped = True;
       }
    }
    else {
       ASSERT(searchinfo->from_pos < page_mapping[1].offset, "to_pos should be smaller than page_mapping[1].offset!");
       match_page = page_mapping[1].pageno;
       if (searchinfo->to_pos > page_mapping[1].offset) {
           match_wrapped = True;
       }
    }
    if (match_wrapped)
       statusline_print(STATUS_MEDIUM, "Match from page %d to %d", match_page + 1,  match_page + 2);
    else
       statusline_print(STATUS_MEDIUM, "Match on page %d", match_page + 1);
    
    if (globals.debug & DBG_FIND) {
       fprintf(stderr, "*** match_page: %d, adding: %d\n", match_page, searchinfo->page_offset);
    
       for (j = searchinfo->from_pos - context; j < searchinfo->from_pos; j++) {
           if (j >= 0)
              fputc(w_info->txt_buf[j], stderr);
           else
              fputc(' ', stderr);
       }
       fputs("\n        >>", stderr);
       for (j = searchinfo->from_pos; j < searchinfo->to_pos; j++) {
           fputc(w_info->txt_buf[j], stderr);
       }
       fputs("<<\n          ", stderr);
       for (j = searchinfo->from_pos; j < searchinfo->to_pos; j++) {
           fputc(' ', stderr);
       }
       for (j = searchinfo->to_pos; j < (int)w_info->curr_buf_idx; j++) {
           fputc(w_info->txt_buf[j], stderr);
           if (w_info->txt_buf[j] == '\n')
              break;
       }
       fputc('\n', stderr);
    }
    
    if (match_page != current_page) {
       goto_page(match_page, resource.keep_flag ? NULL : home, False);
       page_history_insert(match_page);
/*     globals.ev.flags |= EV_NEWPAGE; */
    }
    /* don't raise the window - this can obscure the search popup */
    /*     XMapRaised(DISP, XtWindow(globals.widgets.top_level)); */

    /* this erases contents of m_info, so be careful - contents of curr_info
       will be indirectly erased by this ... */
    erase_match_highlighting(m_info, True);
    
    /* now rescan the page to get bounding box info for the match */
    scan_page(globals.dvi_file.bak_fp, match_page, &curr_info);
    m_info = &curr_info;
    
    m_match_page = match_page;
    
    do_autoscroll = True; /* enable scrolling to match */
    /* create an expose event so that the region gets highlighted */
    if (m_info != NULL) {
       generate_highlight_expose(m_info);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Boolean is_utf8_ideograph ( const unsigned char *  p) [static]

Definition at line 505 of file search-internal.c.

{
    int len;
    uint32_t ucs4;
    
    if ((len = utf8_to_ucs4((const char *)p, &ucs4, strlen((const char*)p))) <= 0)
       return False;
    
    return is_ideograph(ucs4);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void message_search_ended ( XtPointer  arg) [static]

Definition at line 1105 of file search-internal.c.

{
    struct search_settings *settings = (struct search_settings *)arg;

    settings->searchinfo->from_pos = settings->searchinfo->to_pos = -1;
    TRACE_FIND((stderr, "search ended; current_page: %d", current_page));
    settings->from_page = current_page;
    search_signal_page_changed();
    settings->message_window = 0;
    /*     statusline_append(STATUS_SHORT, " stopped."); */
    statusline_print(STATUS_SHORT, "Search stopped.");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void normalize_newline ( char *  str) [static]

Definition at line 1167 of file search-internal.c.

{
    size_t i, j;
    for (i = 0, j = 0; str[i] != '\0'; i++, j++) {
       if (str[i] == '\\' && str[i + 1] == 'n') {
           if (i > 0 && str[i - 1] == '\\') {
              str[j] = 'n';
              i++;
           }
           else {
              str[j] = '\n';
              i++;
           }
       }
       else {
           str[j] = str[i];
       }
    }
    str[j] = str[i]; /* copy terminating '\0' */
}

Here is the caller graph for this function:

static void prepend_info ( const struct word_info info1,
struct word_info info2 
) [static]

Definition at line 458 of file search-internal.c.

{
    if (info1->txt_buf_size > 0) {
       info2->txt_buf = xrealloc(info2->txt_buf, sizeof *(info2->txt_buf)
                              * (info2->txt_buf_size + info1->txt_buf_size + 1));
       memmove(info2->txt_buf + info1->curr_buf_idx, info2->txt_buf, info2->curr_buf_idx);
       info2->txt_buf[info1->curr_buf_idx + info2->curr_buf_idx] = '\0';
       memcpy(info2->txt_buf, info1->txt_buf, info1->curr_buf_idx);
       /*     TRACE_FIND((stderr, "prepend_info: info2->txt_buf is: |%s|", info2->txt_buf)); */
       info2->txt_buf_size += info1->txt_buf_size;
       info2->curr_buf_idx += info1->curr_buf_idx;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Boolean reinit_searchterm ( struct search_settings settings,
const char *  encoding 
) [static]

Definition at line 1190 of file search-internal.c.

{
    struct search_info *searchinfo = settings->searchinfo;

    free(settings->utf8_term);
    settings->utf8_term = NULL;

    if (memicmp(encoding, "iso-8859-1", strlen("iso-8859-1")) == 0
       || memicmp(encoding, "iso8859-1", strlen("iso8859-1")) == 0) {
       int conv_len = (strlen(settings->term) + 1) * 2;
       int ret_len;
       char *ptr = xmalloc(conv_len);
       if ((ret_len = str_iso_8859_1_to_utf8(settings->term, ptr, conv_len)) < 0) {
           XBell(DISP, 0);
           popup_message(XtNameToWidget(globals.widgets.top_level, "*find_popup"),
                       MSG_ERR,
                       NULL,
                       "Shouldn't happen: search term `%s' is too long (> %d)", settings->term, conv_len);
           searchinfo->locked = False;
           free(ptr);
           settings->utf8_term = xstrdup("");
           return False;
       }
       settings->utf8_term = ptr;
    }
    else if (memicmp(encoding, "utf-8", strlen("utf-8")) == 0
            || memicmp(encoding, "utf8", strlen("utf8")) == 0) {
       settings->utf8_term = xstrdup(settings->term);
    }
    else {
       if ((settings->utf8_term = iconv_convert_string(encoding, "utf-8", settings->term)) == NULL) {
           return False;
       }
    }

    TRACE_FIND((stderr, "UTF-8 search term: |%s|", settings->utf8_term));
    normalize_newline(settings->utf8_term);
    TRACE_FIND((stderr, "UTF-8 search term after normalizing newline: |%s|", settings->utf8_term));

#if 0
    /* lowercasing for regexps is dealt with by REG_ICASE */
    if (!settings->case_sensitive && !settings->use_regexp) {
        if (!utf8_lowercase(settings->utf8_term))
            return False;
        TRACE_FIND((stderr, "Lowercased UTF-8 search term: |%s|", settings->utf8_term));
    }
#else /* always lowercase, since REG_ICASE is broken with UTF-8(?) */
    if (!settings->case_sensitive && !utf8_lowercase(settings->utf8_term))
       return False;
    TRACE_FIND((stderr, "Lowercased UTF-8 search term: |%s|", settings->utf8_term));
#endif /* 1 */
    
    /* remove spaces/newlines before/after an ideographic char */
    {
       unsigned char *p = (unsigned char *)settings->utf8_term;
       unsigned char *q;
       int l, len = strlen((char *)p);
       uint32_t ucs4;
       Boolean had_ideograph;
       
       had_ideograph = False;
       while (len > 0) {
           if (*p == ' ' || *p == '\n') {
              q = p + 1;
              while (*q == ' ' || *q == '\n')
                  q++;
              len -= q - p;
              if (had_ideograph || is_utf8_ideograph(q))
                  memmove(p, q, len + 1); /* remove spaces/newlines */
              else
                  p = q;                  /* preserve spaces/newlines */
           }
           else {
              if ((l = utf8_to_ucs4((char *)p, &ucs4, len)) <= 0)
                  break;
              len -= l;
              had_ideograph = is_ideograph(ucs4);
              p += l;
           }
       }

       settings->utf8_term = xrealloc(settings->utf8_term, strlen(settings->utf8_term) + 1);
    }
    
    return True;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void reset_info ( struct word_info w_info) [static]

Definition at line 154 of file search-internal.c.

{
    if (w_info == NULL)
       return;

    free(w_info->txt_buf);
    w_info->txt_buf = NULL;
    w_info->txt_buf_size = 0;
    w_info->curr_buf_idx = 0;

    free(w_info->bboxes);
    w_info->bboxes = NULL;
    w_info->bboxes_size = 0;
    w_info->bboxes_idx = 0;

    m_highlight_region_changed = True;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void scan_page ( FILE fp,
int  pageno,
struct word_info w_info 
) [static]

Definition at line 548 of file search-internal.c.

{
    off_t pos_save;
    static ubyte my_scan_buffer[DVI_BUFFER_LEN];
    struct drawinf currinf_save;
    struct scan_info info;
    ubyte maxchar_save;

    reinit_text_scan(); /* to reset scanning heuristics (linebreaks etc.) */
    info.data = (void *)w_info;
    info.geom_special = NULL; /* no procedure here */
    
    /* Save file position */
    pos_save = save_file_status(globals.dvi_file.bak_fp, &currinf_save, &maxchar_save);
    
    lseek(fileno(fp), pageinfo_get_offset(pageno), SEEK_SET);
    memset((char *)&currinf.data, 0, sizeof currinf.data);
    currinf.tn_table_len = TNTABLELEN;
    currinf.tn_table = tn_table;
    currinf.tn_head = tn_head;

    /* point currinf to our own buffer: */
    G_dvi_buf_ptr = my_scan_buffer;
    
    currinf.pos = currinf.end = G_dvi_buf_ptr;
    currinf.virtual = NULL;
    
    geom_scan(text_do_char, fp, &info, pageno);

    /* Restore file status.  */
    restore_file_status(globals.dvi_file.bak_fp, currinf_save, maxchar_save, pos_save);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Boolean scan_two_pages ( struct search_settings settings,
struct word_info info,
struct page_mapping page_mapping,
int  curr_page 
) [static]

Definition at line 1353 of file search-internal.c.

{
    Boolean cancelled = False;
    struct search_info *searchinfo = settings->searchinfo;
    
    if (curr_page != page_mapping[0].pageno
       && curr_page != page_mapping[1].pageno) { /* none of 2 pages scanned yet */
       reset_info(info);
       if (settings->direction == SEARCH_DOWN) {
           if (!do_scan_page(info, settings, &(page_mapping[0]),
                           0, curr_page, settings->direction)
              || (curr_page + 1 < total_pages &&
                  !do_scan_page(info, settings, &(page_mapping[1]),
                              page_mapping[0].offset, curr_page + 1, settings->direction)))
              cancelled = True;
       }
       else {
           if (!do_scan_page(info, settings, &(page_mapping[1]),
                           0, curr_page, settings->direction)
              || (curr_page > 0 &&
                  !do_scan_page(info, settings, &(page_mapping[0]),
                              page_mapping[1].offset, curr_page - 1, settings->direction)))
              cancelled = True;
           else if (page_mapping[0].offset != -1) {
              page_mapping[1].offset += page_mapping[0].offset;
              if (searchinfo->from_pos != INT_MAX)
                  searchinfo->from_pos += page_mapping[0].offset;
           }
       }
    }
    else if (curr_page != page_mapping[0].pageno) { /* current page scanned as page_mapping[1] */
       if (settings->direction == SEARCH_DOWN && curr_page + 1 < total_pages) {
           shift_info_down(searchinfo, info, page_mapping);
           if (!do_scan_page(info, settings, &(page_mapping[1]),
                           page_mapping[0].offset, curr_page + 1, settings->direction))
              cancelled = True;
       }
       else if (curr_page - 1 != page_mapping[0].pageno && curr_page > 0) {
           if (!do_scan_page(info, settings, &(page_mapping[0]),
                           0, curr_page - 1, settings->direction))
              cancelled = True;
           else {
              page_mapping[1].offset += page_mapping[0].offset;
              if (searchinfo->from_pos != INT_MAX)
                  searchinfo->from_pos += page_mapping[0].offset;
           }
       }
    }
    else if (curr_page != page_mapping[1].pageno) { /* current page scanned as page_mapping[0] */
       if (settings->direction == SEARCH_UP && curr_page > 0) {
           shift_info_up(info, page_mapping);
           if (!do_scan_page(info, settings, &(page_mapping[0]),
                           0, curr_page - 1, settings->direction))
              cancelled = True;
           else {
              page_mapping[1].offset += page_mapping[0].offset;
              if (searchinfo->from_pos != INT_MAX) {
                  searchinfo->from_pos += page_mapping[0].offset;
                  searchinfo->to_pos += page_mapping[0].offset;
              }
              TRACE_FIND((stderr, "new offsets: from=%d, to=%d", searchinfo->from_pos, searchinfo->to_pos));
           }
       }
       else if (curr_page + 1 != page_mapping[1].pageno && curr_page + 1 < total_pages) {
           if (!do_scan_page(info, settings, &(page_mapping[1]),
                           page_mapping[0].offset, curr_page + 1, settings->direction))
              cancelled = True;
       }
    }
    
    return !cancelled;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 347 of file search-internal.c.

{
    if (m_info != NULL) {
       draw_bboxes(m_info);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void search_dvi ( XtPointer  arg)

Definition at line 1430 of file search-internal.c.

{
    struct search_settings *settings = (struct search_settings *)arg;
    struct search_info *searchinfo = settings->searchinfo;
    
#if HAVE_REGEX_H
    static regex_t regex;
#endif /* HAVE_REGEX_H */
    
    /* a mapping of page numbers to index positions in w_info->txt_buf,
       for the 2 pages that we scanned */
    static struct page_mapping page_mapping[2] = { { -1, -1 }, { -1, -1 } };
    
    static struct word_info w_info = { NULL, 0, 0, NULL, 0, 0, NULL, NULL, 0, False, False, False };

    static time_t dvi_time_bak = 0;
    static char *searchterm_bak = NULL;

    static const char *text_encoding = NULL;

    static Boolean case_sensitive_bak = False;
    static Boolean ignore_hyphens_bak = False;
    static Boolean ignore_linebreaks_bak = False;
    static searchDirectionT direction_bak = SEARCH_UNINITIALIZED;
    /* from_pos_bak is needed to mark the start of the match when switching from
       search down to search backwards, where we want to jump to the previous match,
       so we need the start of the current match again (and down search sets
       searchinfo->from_pos = searchinfo->to_pos) */
    static int from_pos_bak = -1;
    int curr_page = settings->from_page;

    Boolean reinit = False;
    Boolean recompile_regexp = False;
    Boolean adjust_hyphen_offset = False;
    
    /* prevent multiple invocations while still busy searching */
    if (searchinfo->locked) {
       TRACE_FIND((stderr, "LOCKED"));
       return;
    }
    searchinfo->locked = True;

    if (dvi_time_bak == 0) { /* first invocation */
       case_sensitive_bak = settings->case_sensitive;
       ignore_hyphens_bak = settings->ignore_hyphens;
       ignore_linebreaks_bak = settings->ignore_linebreaks;
       dvi_time_bak = globals.dvi_file.time;
    }
    if (globals.dvi_file.time > dvi_time_bak) {
       dvi_time_bak = globals.dvi_file.time;
       reinit = True;
    }

    m_match_page = -1;
    
    if (raise_message_windows()) { /* any popups user still needs to deal with? */
       TRACE_GUI((stderr, "Still open message windows to deal with, returning ..."));
       searchinfo->locked = False;
       return;
    }

    ASSERT(settings->term != NULL, "settings->term mustn't be NULL!");
    if (strlen(settings->term) == 0) {
       positioned_popup_message(XtNameToWidget(globals.widgets.top_level, "*find_popup"),
                             MSG_ERR,
                             settings->x_pos, settings->y_pos,
                             NULL, "Empty search term");
       searchinfo->locked = False;
       return;
    }
    
    TRACE_FIND((stderr, "dvi_search: Searching for |%s| from page %d", settings->term, settings->from_page));
    TRACE_FIND((stderr, "  settings: down = %d, re = %d, case = %d",
              settings->direction, settings->use_regexp, settings->case_sensitive));

    if (m_changed_page) {
       m_changed_page = False;
       reinit = True;
    }
    
    /* initialize text_encoding */
    if (text_encoding == NULL) {
       text_encoding = get_text_encoding();
    }
    
    /* first call to this routine, or search term changed:
       Re-initialize the utf-8 representation and the regexp */
    if (settings->utf8_term == NULL
       || searchterm_bak == NULL
       || strcmp(settings->term, searchterm_bak) != 0) {

       if (!reinit_searchterm(settings, text_encoding)) {
           searchinfo->locked = False;
           return;
       }

       free(searchterm_bak);
       searchterm_bak = xstrdup(settings->term);
       recompile_regexp = True;
    }

    if (strlen(settings->utf8_term) == 0) {
       positioned_popup_message(XtNameToWidget(globals.widgets.top_level, "*find_popup"),
                             MSG_WARN,
                             settings->x_pos, settings->y_pos,
                             NULL, "Search term is empty after UTF-8 conversion!");
       searchinfo->locked = False;
       return;
    }

    if (direction_bak != settings->direction && direction_bak != SEARCH_UNINITIALIZED
       && searchinfo->from_pos != INT_MAX && searchinfo->from_pos != -1) {
       TRACE_FIND((stderr, "changed direction! from_pos: %d", searchinfo->from_pos));
       if (settings->direction == SEARCH_DOWN) {
           searchinfo->from_pos = searchinfo->to_pos;
           TRACE_FIND((stderr, "DOWN; new from_pos: %d", searchinfo->from_pos));
       }
       else if (settings->direction == SEARCH_UP) {
           if (from_pos_bak != -1) {
              searchinfo->from_pos = from_pos_bak;
           }
           else {
              searchinfo->from_pos = 0;
           }
           TRACE_FIND((stderr, "UP; new from_pos: %d", searchinfo->from_pos));
       }
    }
    direction_bak = settings->direction;

    /* If one of the settings for case, hyphens ore linebreaks has
     * changed, we need to rescan the page to undo lowercasing,
     * hyphenation or linebreak removal in w_info, but preserve
     * searchinfo->from_pos since user will want to find next match.
     */
    if (case_sensitive_bak != settings->case_sensitive
       || ignore_hyphens_bak != settings->ignore_hyphens
       || ignore_linebreaks_bak != settings->ignore_linebreaks) {

       if (ignore_hyphens_bak != settings->ignore_hyphens)
           adjust_hyphen_offset = True;
       case_sensitive_bak = settings->case_sensitive;
       ignore_hyphens_bak = settings->ignore_hyphens;
       ignore_linebreaks_bak = settings->ignore_linebreaks;
       
       reset_info(&w_info);

       /* adjust from_pos if it's on second page (we'll rescan it as first page) */
       if (searchinfo->from_pos >= page_mapping[0].offset)
           searchinfo->from_pos -= page_mapping[0].offset;

       TRACE_FIND((stderr, "from_pos: %d", searchinfo->from_pos));
       page_mapping[0].offset = page_mapping[1].offset = page_mapping[0].pageno = page_mapping[1].pageno = -1;
       /* also need to recompile regexp, and undo lowercasing of search term */
       if (!reinit_searchterm(settings, text_encoding))
           return;
       recompile_regexp = True;
    }
    
    if (reinit) { /* file changed, or on different page: re-initialize scan info */
       TRACE_FIND((stderr, "re-initializing scan info!"));
       page_mapping[0].offset = page_mapping[1].offset = page_mapping[0].pageno = page_mapping[1].pageno = -1;

       /* re-initialize info */
       reset_info(&w_info);
       if (settings->direction == SEARCH_DOWN)
           searchinfo->from_pos = searchinfo->to_pos = 0;
       else
           settings->searchinfo->from_pos = settings->searchinfo->to_pos = INT_MAX;
    }

    TRACE_FIND((stderr, "from_pos initialized with: %d", settings->searchinfo->from_pos));
    
    if (settings->use_regexp && recompile_regexp) {
#if HAVE_REGEX_H
       if (!do_recompile_regexp(settings, &regex))
           return;
#else
       warn_no_regex();
#endif /* HAVE_REGEX_H */
    }

    for (;;) {       /* scan pages, try to match */
       statusline_print(STATUS_MEDIUM, "Searching on page %d", curr_page);
       TRACE_FIND((stderr, "curr_page: %d, pageno 0: %d, pageno1: %d",
                  curr_page, page_mapping[0].pageno, page_mapping[1].pageno));

       settings->hyphen_delta = 0;
       /* scan_two_pages will return False if user cancelled */
       if (!scan_two_pages(settings, &w_info, page_mapping, curr_page)
           || (read_events(EV_NOWAIT) & EV_GE_FIND_CANCEL)) {
           statusline_append(STATUS_SHORT,
                           "- cancelled.",
                           "- cancelled.");
           settings->searchinfo->locked = False;
           return;
       
       }

       TRACE_FIND((stderr, "page mapping:\n%d: %d\n%d: %d",
                  page_mapping[0].pageno, page_mapping[0].offset,
                  page_mapping[1].pageno, page_mapping[1].offset));
       
/*     dump_buffer(&w_info, 0, stderr, FMT_ISO_8859_1); */

       /* If ignore_hyphens has changed (in which case adjust_hyphen_offset
          is true), the buffer will contain settings->hyphen_delta fewer
          or more characters than in the previous pass due to the removal
          or addition of hyphens; adjust from_pos and to_pos accordingly:
       */
       if (adjust_hyphen_offset) {
           TRACE_FIND((stderr, "adjusting offset by %d", settings->hyphen_delta));
           if (settings->ignore_hyphens) { /* fewer characters */
              settings->searchinfo->from_pos -= settings->hyphen_delta;
              settings->searchinfo->to_pos -= settings->hyphen_delta;
           }
           else { /* more characters */
              settings->searchinfo->from_pos += settings->hyphen_delta;
              settings->searchinfo->to_pos += settings->hyphen_delta;
           }
           TRACE_FIND((stderr, "NEW from_pos: %d; to_pos: %d",
                     settings->searchinfo->from_pos, settings->searchinfo->to_pos));
       }

       
       /* match the searchstring */
#if HAVE_REGEX_H
       if (settings->use_regexp) {
           if (!try_regexp_match(&regex, &w_info, settings, searchinfo)) /* regexp error */
              return;
           
       }
       else {
#endif
           try_match(&w_info, settings, searchinfo);
#if HAVE_REGEX_H
       }
#endif

       /* again, check if user cancelled */
       if (read_events(EV_NOWAIT) & EV_GE_FIND_CANCEL) { /* user cancelled */
           statusline_append(STATUS_SHORT,
                           "- cancelled.",
                           "- cancelled.");
           settings->searchinfo->locked = False;
           return;
       
       }
       
       if (searchinfo->have_match) { /* match, highlight it */
           highlight_match(settings, &w_info, page_mapping);
           settings->searchinfo->locked = False;
           if (settings->direction == SEARCH_DOWN) {
              from_pos_bak = searchinfo->from_pos;
              searchinfo->from_pos = searchinfo->to_pos;
           }
           break;
       }
       else if ((settings->direction == SEARCH_DOWN && curr_page + 1 < total_pages)
               || (settings->direction == SEARCH_UP && curr_page > 0)) {
           if (settings->direction == SEARCH_DOWN)
              curr_page++;
           else
              curr_page--;
           TRACE_FIND((stderr, "continuing on page %d", curr_page));
           erase_match_highlighting(m_info, True);
           /* no match, and we have more pages; continue scanning */
           continue;
       }
       else { /* reached end of file */
           Widget find_popup;

           if ((find_popup = XtNameToWidget(globals.widgets.top_level, "*find_popup")) == 0) {
              XDVI_WARNING((stderr, "Couldn't find \"find_popup\" widget!"));
              find_popup = globals.widgets.top_level;
           }
           
           statusline_append(STATUS_MEDIUM,
                           "... searched to end of file.",
                           "... searched to end of file.");
           erase_match_highlighting(m_info, True);
           settings->searchinfo->locked = False;
           
           settings->message_window =
              positioned_choice_dialog(find_popup,
                                    MSG_QUESTION,
                                    settings->x_pos, settings->y_pos,
                                    NULL,
#ifndef MOTIF
                                    "do-search-restart",
#endif
                                    NULL, NULL, /* no pre_callbacks */
                                    "Yes", search_restart, (XtPointer)settings,
                                    "Cancel", message_search_ended, (XtPointer)settings,
                                    "Searched %s of file without finding the pattern.\n"
                                    "Start again from the %s of the file?",
                                    settings->direction == SEARCH_DOWN
                                    ? "forward to end" : "backward to beginning",
                                    settings->direction == SEARCH_DOWN
                                    ? "beginning" : "end");
           TRACE_GUI((stderr, "message_window: %p\n", (void *)settings->message_window));
           /* notreached */
           break;
       }
    } /* for(;;) */
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1099 of file search-internal.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1066 of file search-internal.c.

{
    int i;
    FILE *fp;
    struct file_info *finfo = pinfo->finfo;
    
    if ((fp = XFOPEN(finfo->txt_out.fname, "wb")) == NULL) {
       popup_message(globals.widgets.top_level,
                    MSG_ERR,
                    NULL, "Could not open %s for writing: %s.",
                    finfo->txt_out.fname,
                    strerror(errno));
       return False;
    }

    for (i = 0; i < total_pages; i++) {
       if (pinfo->callback == NULL || pinfo->callback(pinfo, i)) {
           struct word_info txt_info = { NULL, 0, 0, NULL, 0, 0, NULL, NULL, 0, False, False, False };
           scan_page(globals.dvi_file.bak_fp, i, &txt_info);

           dump_buffer(&txt_info, 0, fp, fmt);

           free(txt_info.txt_buf);
           
           fputs("\n\n", fp); /* two newlines for page breaks */
       }
    }
    
    fclose(fp);
    return True;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 301 of file search-internal.c.

{
/*     fprintf(stderr, "pageno: %d --- m_info: %p\n", pageno, m_info); */
/*     fprintf(stderr, "m_match_page: %d\n", m_match_page); */
    return m_info != NULL && m_match_page == pageno;
}

Here is the caller graph for this function:

Definition at line 314 of file search-internal.c.

{
    size_t i;

    ASSERT(m_info != NULL, "inside_match musn't be called with m_info == NULL!");
    TRACE_FIND((stderr, "m_info->bboxes: %p; idx: %lu", (void *)m_info->bboxes, (unsigned long)m_info->bboxes_idx));
    for (i = 0; m_info->bboxes != NULL && i <= m_info->bboxes_idx && m_info->bboxes[i].ulx < INT_MAX; i++) {
       TRACE_FIND((stderr, "inside_bbox_match: %d, %d", x, y));
       TRACE_FIND((stderr, "x: %d, y: %d, x2: %d, y2: %d",
                  (int)(m_info->bboxes[i].ulx / (double)currwin.shrinkfactor + 0.5),
                  (int)(m_info->bboxes[i].uly / (double)currwin.shrinkfactor + 0.5),
                  (int)(m_info->bboxes[i].lrx / (double)currwin.shrinkfactor + 0.5),
                  (int)(m_info->bboxes[i].lry / (double)currwin.shrinkfactor + 0.5)));

       if (x >= (int)(m_info->bboxes[i].ulx / (double)currwin.shrinkfactor + 0.5)
           && x <= (int)(m_info->bboxes[i].lrx / (double)currwin.shrinkfactor + 0.5)
           && y >= (int)(m_info->bboxes[i].uly / (double)currwin.shrinkfactor + 0.5)
           && y <= (int)(m_info->bboxes[i].lry / (double)currwin.shrinkfactor + 0.5)) {
           TRACE_FIND((stderr, "%d == %d",
                     x - 1, (int)(m_info->bboxes[i].ulx / (double)currwin.shrinkfactor + 0.5)));
           TRACE_FIND((stderr, "%d == %d",
                     y - 1, (int)(m_info->bboxes[i].uly / (double)currwin.shrinkfactor + 0.5)));
           if (x - 1 == (int)(m_info->bboxes[i].ulx / (double)currwin.shrinkfactor + 0.5)
              && y - 1 == (int)(m_info->bboxes[i].uly / (double)currwin.shrinkfactor + 0.5))
              return 2;
           else
              return 1;
       }
    }
    return 0;
}

Definition at line 1278 of file search-internal.c.

{
    TRACE_FIND((stderr, "resetting info!"));
    reset_info(m_info);
    m_info = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void search_restart ( XtPointer  arg)

Definition at line 1120 of file search-internal.c.

{
    struct search_settings *settings = (struct search_settings *)arg;
    Widget popup, textfield;
    char *searchterm = NULL;
    
    TRACE_FIND((stderr, "restart search!"));

    /* Update the search term (user might have changed it before
       hitting `Return' to restart the search).  We need to start
       from the toplevel widget since this method may be called
       from a different window (e.g. confirmation popup).
    */
    if (get_widget_by_name(&popup, globals.widgets.top_level, Xdvi_SEARCH_POPUP_NAME, True)
       && get_widget_by_name(&textfield, popup, Xdvi_SEARCHBOX_INPUT_NAME, True)) {
       XtVaGetValues(textfield,
#ifdef MOTIF
                    XmNvalue,
#else
                    XtNstring,
#endif
                    &searchterm, NULL);
       if (searchterm == NULL) {
           XDVI_WARNING((stderr, "Got NULL searchterm in search_restart()!"));
           return;
       }
       settings->term = searchterm;
    }

    if (settings->direction == SEARCH_DOWN) {
       settings->from_page = 0;
    }
    else {
       settings->from_page = total_pages - 1;
    }
    if (settings->direction == SEARCH_DOWN)
       settings->searchinfo->from_pos = settings->searchinfo->to_pos = -1;
    else
       settings->searchinfo->from_pos = settings->searchinfo->to_pos = INT_MAX;
    
    settings->message_window = 0;
    search_signal_page_changed();
    search_dvi((XtPointer)settings);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 147 of file search-internal.c.

Here is the caller graph for this function:

static void shift_info_down ( struct search_info searchinfo,
struct word_info info,
struct page_mapping page_mapping 
) [static]

Definition at line 360 of file search-internal.c.

{
    size_t initial_offset = 0;
    if (page_mapping[0].offset != -1) { /* remember value */
       initial_offset = page_mapping[0].offset;
    }
    
    if (globals.debug & DBG_FIND) {
       int i;
       fprintf(stderr, "current page_mapping:\n");
       for (i = 0; i < 2; i++) {
           fprintf(stderr, "%d: %d\n", page_mapping[i].pageno, page_mapping[i].offset);
       }
    }
    
    TRACE_FIND((stderr, "initial offset: %lu", (unsigned long)initial_offset));

    page_mapping[0].offset = page_mapping[1].offset - initial_offset;
    page_mapping[0].pageno = page_mapping[1].pageno;
    ASSERT(page_mapping[0].offset >= 0, "new index mustn't be negative!\n");
    page_mapping[1].offset = page_mapping[1].pageno = -1;
    
    TRACE_FIND((stderr, "new val at 0: %d; curr_idx: %lu, len: %lu",
              page_mapping[0].offset,
              (unsigned long)(info->curr_buf_idx - initial_offset),
              (unsigned long)(strlen(info->txt_buf + initial_offset))));

    /* move the text buffer down, and update its current index accordingly */
    ASSERT(info->curr_buf_idx >= initial_offset, "info->curr_buf_idx mustn't become negative!");
    memmove(info->txt_buf, info->txt_buf + initial_offset, info->curr_buf_idx - initial_offset + 1);
    info->curr_buf_idx -= initial_offset;
    TRACE_FIND((stderr, "new index: %lu", (unsigned long)info->curr_buf_idx));

    searchinfo->from_pos -= initial_offset;
    searchinfo->to_pos -= initial_offset;
    if (searchinfo->from_pos < 0)
       searchinfo->from_pos = 0;
    if (searchinfo->to_pos < 0)
       searchinfo->to_pos = 0;
    TRACE_FIND((stderr, "new offsets: from=%d, to=%d", searchinfo->from_pos, searchinfo->to_pos));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void shift_info_up ( struct word_info info,
struct page_mapping page_mapping 
) [static]

Definition at line 407 of file search-internal.c.

{
    if (globals.debug & DBG_FIND) {
       int i;
       fprintf(stderr, "current page_mapping:\n");
       for (i = 0; i < 2; i++) {
           fprintf(stderr, "%d: %d\n", page_mapping[i].pageno, page_mapping[i].offset);
       }
    }
    
    ASSERT(page_mapping[0].offset > 0, "info->curr_buf_idx mustn't become negative!");
    info->curr_buf_idx = page_mapping[0].offset;
    TRACE_FIND((stderr, "new index: %lu", (unsigned long)info->curr_buf_idx));

    page_mapping[1].offset = page_mapping[0].offset;
    page_mapping[1].pageno = page_mapping[0].pageno;
    page_mapping[0].offset = page_mapping[0].pageno = -1;
    
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void try_match ( const struct word_info info,
const struct search_settings settings,
struct search_info searchinfo 
) [static]

Definition at line 639 of file search-internal.c.

{
    char *res = NULL;
    size_t from_pos = 0;
    
    ASSERT(info->curr_buf_idx == strlen(info->txt_buf), "");
    TRACE_FIND((stderr, "buffer index: %lu, len: %lu; from: %lu",
              (unsigned long)info->curr_buf_idx,
              (unsigned long)strlen(info->txt_buf),
              (unsigned long)searchinfo->from_pos));
    if (searchinfo->from_pos != -1)
       from_pos = searchinfo->from_pos;
    
    if (settings->direction == SEARCH_DOWN) {
       TRACE_FIND((stderr, "trying to match |%s| from %lu; total: %lu",
                  settings->utf8_term,
                  (unsigned long)from_pos,
                  (unsigned long)strlen(info->txt_buf)));

       res = strstr(info->txt_buf + from_pos, settings->utf8_term);
    }
    else {
       size_t curr_pos = 0;
       char *res_bak = NULL;

       TRACE_FIND((stderr, "UP; trying to match |%s| from %lu, %lu",
                  settings->utf8_term,
                  (unsigned long)curr_pos, (unsigned long)from_pos));
       TRACE_FIND((stderr, "buf: |%s|", info->txt_buf + curr_pos));
       while (curr_pos <= from_pos) {
           res_bak = res;
           res = strstr(info->txt_buf + curr_pos, settings->utf8_term);
           if (res != NULL) {
              curr_pos = res - info->txt_buf + strlen(settings->utf8_term);
           }
           else {
              break;
           }
       }
       res = res_bak;
    }
    if (res != NULL) {
       searchinfo->have_match = True;
       searchinfo->from_pos = res - info->txt_buf;
       searchinfo->to_pos = searchinfo->from_pos + strlen(settings->utf8_term);
    }
    else {
       searchinfo->have_match = False;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void warn_no_regex ( void  ) [static]

Definition at line 1337 of file search-internal.c.

{
    XBell(DISP, 0);
    popup_message(XtNameToWidget(globals.widgets.top_level, "*find_popup"),
                MSG_WARN,
                NULL,
                "POSIX regular expression support (regex.h) is not available on this platform; "
                "using ordinary string matching instead.");
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 110 of file search-internal.c.

Definition at line 111 of file search-internal.c.

Definition at line 142 of file search-internal.c.

Definition at line 144 of file search-internal.c.

struct word_info* m_info = NULL [static]

Definition at line 132 of file search-internal.c.

int m_match_page = -1 [static]

Definition at line 133 of file search-internal.c.