Back to index

tetex-bin  3.0
Classes | Defines | Enumerations | Functions
hypertex.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  htex_prescan_data

Defines

#define HTEXTEX_H_
#define LINK_COLOR_FALLBACK   "BLUE2"
#define VISITED_LINK_COLOR_FALLBACK   "Purple4"

Enumerations

enum  htexPrescanTypeT { HTEX_ANCHOR_NUM, HTEX_ANCHOR_STRING }
enum  htexObjectT { HTEX_TEXT, HTEX_IMG }

Functions

const char * is_local_file (const char *filename)
void launch_program (const char *filename)
void launch_xdvi (const char *filename, const char *anchor_name)
Boolean htex_handleref (int x, int y, Boolean newwindow)
void htex_reinit (void)
void htex_resize_page (void)
void htex_draw_anchormarkers (void)
void htex_record_position (int, int, int, int)
void htex_initpage (Boolean dvi_file_changed, Boolean size_changed, int pageno)
Boolean htex_prescan_special (const char *str, int str_len, struct htex_prescan_data *data)
int htex_prescan_get_depth (void)
size_t htex_prescan_get_mismatched_anchor_num (size_t depth)
void htex_prescan_save (void)
void htex_prescan_reset_firstpass (void)
void htex_prescan_restore (int pageno)
void htex_prescan_initpage (void)
void htex_prescan_carry_over (int old_page, int new_page)
void htex_set_anchorsize (int x, int y, int w, int h)
void htex_set_objecttype (htexObjectT type)
void htex_reset_page (int pageno)
void htex_displayanchor (int, int)
void htex_set_anchormarker (int y)
void htex_back (void)
void htex_forward (void)
Boolean htex_scan_anchor (const char *special, size_t len)

Class Documentation

struct htex_prescan_data

Definition at line 43 of file hypertex.h.

Class Members
int anchor_num
int pageno
htexPrescanTypeT scan_type

Define Documentation

#define HTEXTEX_H_

Definition at line 24 of file hypertex.h.

#define LINK_COLOR_FALLBACK   "BLUE2"

Definition at line 27 of file hypertex.h.

#define VISITED_LINK_COLOR_FALLBACK   "Purple4"

Definition at line 28 of file hypertex.h.


Enumeration Type Documentation

Enumerator:
HTEX_TEXT 
HTEX_IMG 

Definition at line 49 of file hypertex.h.

Enumerator:
HTEX_ANCHOR_NUM 
HTEX_ANCHOR_STRING 

Definition at line 41 of file hypertex.h.


Function Documentation

Definition at line 1367 of file hypertex.c.

{
    struct history_info *info;

    if (htex_history == NULL) {
       XBell(DISP, 0);
       statusline_print(STATUS_SHORT, "Hyperref history is empty");
       return;
    }
    info = htex_history->item;

    if (htex_history->prev == NULL) {
       XBell(DISP, 0);
       statusline_print(STATUS_SHORT, "At begin of history");
       htex_update_toolbar_navigation();
       return;
    }

    if (strcmp(info->filename, globals.dvi_name) != 0) { /* new filename different */
       Boolean tried_dvi_ext = False;
       char *new_dvi_name = NULL;
       
       if ((new_dvi_name = open_dvi_file_wrapper(info->filename, False, False,
                                            &tried_dvi_ext, False))
           == NULL) {
           
           statusline_print(STATUS_MEDIUM, "Re-opening file \"%s\" failed!\n", info->filename);
           return;
       }
       else {
           set_dvi_name(new_dvi_name);
           globals.ev.flags |= EV_NEWDOC;
           globals.ev.flags |= EV_PAGEHIST_INSERT;
/*         statusline_print(STATUS_MEDIUM, "Back to file: \"%s\"", globals.dvi_name); */
       }
    }
    else {
       page_history_insert(info->page);
    }
    goto_page(info->page, resource.keep_flag ? NULL : home, False);

    MYTRACE((stderr, "curr page now: %d", current_page));
    htex_history = htex_history->prev;

    info = htex_history->item;

#if 0
    MYTRACE((stderr, "------ before skipping: %d, %s", info->page, info->anchor));
    show_history();
    while (info->page == current_page && htex_history->prev != NULL) {
       /* skip identical locations */
       MYTRACE((stderr, "+++++++ skipping identical page %d, %s", current_page, info->anchor));
       htex_history = htex_history->prev;
       info = htex_history->item;
    }
    MYTRACE((stderr, "------ after skipping: %d, %s", info->page, info->anchor));
#endif

    htex_update_toolbar_navigation();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1674 of file hypertex.c.

{
    static int id_bak = -1;
    static int pageno_bak = -1;
    int id_curr;
    char *anchor_text;

    anchor_text = get_anchor_at_index(x, y, &id_curr);

    if (anchor_text != NULL) { /* found an anchor */
       if (!(globals.cursor.flags & CURSOR_LINK) && !dragging_text_selection()) {
           globals.cursor.flags |= CURSOR_LINK;
           globals.ev.flags |= EV_CURSOR;
       }
       /* to prevent flicker, print only when it differs from previous one,
          i.e. when it either has a different ID or is on a different page: */
       if ((resource.expert_mode & XPRT_SHOW_STATUSLINE) != 0
           && (id_curr != id_bak || current_page != pageno_bak)) {
           statusline_print(STATUS_FOREVER, "%s", anchor_text);
           id_bak = id_curr;
           pageno_bak = current_page;
       }
    }
    else { /* not over anchor text, reset cursor and statusline */
       if (globals.cursor.flags & CURSOR_LINK) {
           globals.cursor.flags &= ~CURSOR_LINK;
           globals.ev.flags |= EV_CURSOR;
       }

       if (id_bak != -1 && (resource.expert_mode & XPRT_SHOW_STATUSLINE) != 0) {
           statusline_clear();
           id_bak = -1;
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1740 of file hypertex.c.

{
    int i;
    int rule_height = (globals.page.h / 1000.0);
    XRectangle rect = { -1, -1, 0, 0 };
    
    if (rule_height == 0)
       rule_height = 1;

    if (current_page == g_anchormarker.page
       && strcmp(globals.dvi_name, g_anchormarker.filename) == 0
       &&  g_anchormarker.y_pos > 0) {
       htex_draw_anchormarker(g_anchormarker.y_pos);
    }
    
    if (resource.link_style == 0 || resource.link_style == 2)
       return;
    
    for (i = 0; i < htex_page_info.curr_cnt; i++) {
       struct anchor_info anchor = htex_page_info.anchors[i];

       if (anchor.a_href != NULL) {
           int offset;
           Boolean visited = False;

#if 0
           XDrawRectangle(DISP, mane.win, globals.gc.high,
                        anchor.ulx, anchor.uly,
                        anchor.lrx - anchor.ulx, anchor.lry - anchor.uly);
                        
#endif
           
           if (is_visited(&visited_links, current_page, i)) {/*  || wrapped_anchor_is_visited(i)) { */
              visited = True;
           }
           offset = ANCHOR_XTRA_V_BBOX / (double)currwin.shrinkfactor + 0.5;

           TRACE_HTEX((stderr, "UNDERLINE: %d, %s is %s", i, anchor.a_href,
                     visited ? "******* visited ****** " : "not visited"));
           anchor.ulx -= currwin.base_x;
           anchor.lrx -= currwin.base_x;
           anchor.lry -= currwin.base_y;
           anchor.uly -= currwin.base_y;
           
           /* BUG ALERT: Don't use put_rule here, since this will cause a segfault
            * with the new color code when switching density (#616920)!
            */
           MYTRACE((stderr, "UNDERLINE: checking if %d is visited: %d!", i, visited));

/*         if (clip_region_to_rect(&rect)) { */
           if (anchor.object_type == HTEX_IMG) {
              rect.x = anchor.ulx - 1;
              rect.y = anchor.uly - 1;
              rect.width = anchor.lrx - anchor.ulx + 2;
              rect.height = anchor.lry - anchor.uly + 2;
              if (clip_region_to_rect(&rect)) {
                  XDrawRectangle(DISP, mane.win,
                               visited ? globals.gc.visited_linkcolor : globals.gc.linkcolor,
                               rect.x, rect.y,
                               rect.width, rect.height);
              }
           }
           else {
              rect.x = anchor.ulx - 1;
              rect.y = anchor.lry + offset;
              rect.width = anchor.lrx - anchor.ulx + 2;
              rect.height = rule_height;
              if (clip_region_to_rect(&rect)) {
                  XFillRectangle(DISP, mane.win,
                               visited ? globals.gc.visited_linkcolor : globals.gc.linkcolor,
                               rect.x, rect.y,
                               rect.width, rect.height);
              }
           }
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1430 of file hypertex.c.

{
    struct history_info *info;
    char *link;
    
    if (htex_history == NULL) {
       XBell(DISP, 0);
       statusline_print(STATUS_SHORT, "Hyperref history is empty");
       return;
    }
    if (htex_history->next == NULL) {
       XBell(DISP, 0);
       statusline_print(STATUS_SHORT, "At end of history");
       return;
    }
    
    htex_history = htex_history->next;
    info = htex_history->item;
    link = info->anchor;
    /* go there */
    if (*link == '#') { /* it's a relative link */
       MYTRACE((stderr, "XXXXXXXX %s:%d: setting anchor to |%s|+1", __FILE__, __LINE__, info->anchor));
       free(g_anchor_pos);
       g_anchor_pos = xstrdup(info->anchor + 1);
       g_anchor_len = strlen(g_anchor_pos);
       globals.ev.flags |= EV_ANCHOR;
    }
    else { /* it's an absolute link */
       char *new_linkname = NULL;
       char *new_dvi_name = NULL;
       Boolean tried_dvi_ext = False;
       
       if ((new_linkname = check_relative_name(link)) != NULL)
           link = new_linkname;

       if ((new_dvi_name = open_dvi_file_wrapper(link, False, False,
                                            &tried_dvi_ext, False)) == NULL) {
           statusline_print(STATUS_MEDIUM, "Re-opening file \"%s\" failed!\n", info->filename);
           free(new_linkname);
           return;
       }
       else {
           set_dvi_name(new_dvi_name);
           
           globals.ev.flags |= EV_NEWDOC;
           goto_page(0, resource.keep_flag ? NULL : home, False);
           globals.ev.flags |= EV_PAGEHIST_INSERT;

           if (g_anchor_pos != NULL)
              globals.ev.flags |= EV_ANCHOR;

/*         statusline_print(STATUS_MEDIUM, "Loaded file: \"%s\"", globals.dvi_name); */
           free(new_linkname);
       }
    }

    htex_update_toolbar_navigation();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Boolean htex_handleref ( int  x,
int  y,
Boolean  newwindow 
)

Definition at line 1604 of file hypertex.c.

{
    char *link;
    int link_num;

/*      fprintf(stderr, "---------- htex_handleref!\n"); */
    if (!(globals.cursor.flags & CURSOR_LINK))
       /* When no link cursor is shown, clicking shouldn't jump to link */
       return False;
    
    if ((link = get_anchor_at_index(x, y, &link_num)) != NULL) {
       set_visited(&visited_links, current_page, link_num);

       if (*link == '#') { /* it's a relative link */
           if (newwindow) {
              launch_xdvi(globals.dvi_name, link + 1);
              redraw_anchors(link_num);
              return True;
           }
           else {
              history_save_anchor(link, current_page, globals.dvi_name);
              free(g_anchor_pos);
              g_anchor_pos = xstrdup(link + 1);
              g_anchor_len = strlen(g_anchor_pos);
              globals.ev.flags |= EV_ANCHOR;
              redraw_anchors(link_num);
              return True;
           }
       }
       else { /* it's an absolute link */
           char *new_dvi_name = NULL;
           int pageno_bak = current_page;
           char *new_linkname = NULL;
           char *orig_link = link;
           Boolean tried_dvi_ext = False;
           
           MYTRACE((stderr, "OLD FILE: |%s|", globals.dvi_name));

           if ((new_linkname = check_relative_name(link)) != NULL)
              link = new_linkname;
           
           if ((new_dvi_name = open_dvi_file_wrapper(link, False, newwindow,
                                                &tried_dvi_ext, False)) != NULL) {
              /* only save link in history if opening succeeds */
              history_save_anchor(orig_link, pageno_bak, globals.dvi_name);
              set_dvi_name(new_dvi_name);
              if (!newwindow) {
                  globals.ev.flags |= EV_NEWDOC;
                  goto_page(0, resource.keep_flag ? NULL : home, False);
                  globals.ev.flags |= EV_PAGEHIST_INSERT;
                  
                  MYTRACE((stderr, "NEW FILE: |%s|", globals.dvi_name));
                  if (g_anchor_pos != NULL)
                     globals.ev.flags |= EV_ANCHOR;
/*                statusline_print(STATUS_MEDIUM, "Loaded file: \"%s\"", dvi_name); */
              }
              else {
                  redraw_anchors(link_num);
              }
           }
           free(new_linkname);
           redraw_anchors(link_num);
           return True;
       }
    }
    return False;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void htex_initpage ( Boolean  dvi_file_changed,
Boolean  size_changed,
int  pageno 
)

Definition at line 1056 of file hypertex.c.

{
    reset_page_info(&htex_page_info, pageno, size_changed | new_dvi_file);
    init_visited_links(&visited_links, total_pages, new_dvi_file);

#if 0
    show_visited(&visited_links, pageno);
#endif
    
    if (pageno > 0
       && (int)m_prescan_info.pagelist_len > pageno /* pagelist_len will be 0 for file with no hyperlinks */
       && m_prescan_info.pagelist[pageno - 1] != NULL) {
       add_anchor(&htex_page_info, A_HREF,
                 m_prescan_info.pagelist[pageno - 1],
                 strlen(m_prescan_info.pagelist[pageno - 1]),
                 pageno, NULL);
       htex_page_info.curr_cnt++;
       MYTRACE((stderr, "++++++++++ mismatched anchor text (at %d): |%s|",
              htex_page_info.curr_cnt - 1, m_prescan_info.pagelist[pageno - 1]));
       /*     x_pos_bak = y_pos_bak = INT_MAX; */
       x_pos_bak = y_pos_bak = INT_MAX;
       set_anchor_size(&htex_page_info, htex_page_info.curr_cnt - 1, 0, 0, 1, 1);
       htex_page_info.have_wrapped = htex_page_info.curr_cnt - 1;
       if (bg_current != NULL) { /* only if it has been initialized by redraw_page in events.c */
           push_colorspecial();
       }
/*     else { */
/*         fprintf(stderr, "----------------------- NOT pushing color, waiting ...\n"); */
/*     } */
       push_stack(&stack, A_HREF, htex_page_info.curr_cnt - 1);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void htex_prescan_carry_over ( int  old_page,
int  new_page 
)

Definition at line 423 of file hypertex.c.

{
    ASSERT(old_page >= 0, "old_page out of range");
    ASSERT(old_page < (int)m_prescan_info.pagelist_len, "old_page out of range");

    /* resize if needed */
    if (new_page >= (int)m_prescan_info.pagelist_len) {
       size_t old_len = m_prescan_info.pagelist_len;
       size_t i;
       m_prescan_info.pagelist_len = new_page + 1;
       m_prescan_info.pagelist = XREALLOC(m_prescan_info.pagelist,
                                      m_prescan_info.pagelist_len * sizeof *m_prescan_info.pagelist);
       /* initialize with NULL values */
       for (i = old_len; i < m_prescan_info.pagelist_len; i++) {
           m_prescan_info.pagelist[i] = NULL;
       }
    }
    free(m_prescan_info.pagelist[new_page]);
    /* don't share pointers here */
    m_prescan_info.pagelist[new_page] = xstrdup(m_prescan_info.pagelist[old_page]);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 416 of file hypertex.c.

{
    return m_prescan_info.anchor_depth;
}

Here is the caller graph for this function:

Definition at line 446 of file hypertex.c.

{
    ASSERT((int)depth <= m_prescan_info.anchor_depth, "depth too large");
    ASSERT(depth <= m_prescan_info.anchor_list_size, "depth too large for lookup list");
    
    return m_prescan_info.anchor_list[m_prescan_info.anchor_depth - 1];
}

Here is the caller graph for this function:

Definition at line 287 of file hypertex.c.

{
    m_prescan_info.anchor_num = 0;
}

Here is the caller graph for this function:

Definition at line 250 of file hypertex.c.

{
    MYTRACE((stderr, "resetting anchor_depth to 0!!!!!!!!!!!!"));
    m_prescan_info.anchor_depth = 0;
    m_prescan_info.anchor_num = 0;
    m_prescan_info.anchor_list_size = 0;
    FREE(m_prescan_info.anchor_list);
    m_prescan_info.anchor_list = NULL;
}

Here is the caller graph for this function:

Definition at line 218 of file hypertex.c.

{
    m_prescan_info.anchor_depth = m_save_prescan_info.anchor_depth;
    m_prescan_info.anchor_num = m_save_prescan_info.anchor_num;
    /* copy back anchor list */
    if (m_save_prescan_info.anchor_depth > 0) {
       int i;
       /* old list might have been free()d in htex_prescan_reset_firstpass */
       while (m_save_prescan_info.anchor_depth >= (int)m_prescan_info.anchor_list_size) {
           m_prescan_info.anchor_list_size += HTEX_ALLOC_STEP;
           m_prescan_info.anchor_list = XREALLOC(m_prescan_info.anchor_list,
                                            m_prescan_info.anchor_list_size
                                            * sizeof *(m_prescan_info.anchor_list));
       }
       for (i = 0; i < m_save_prescan_info.anchor_depth; i++) {
           m_prescan_info.anchor_list[i] = m_save_prescan_info.anchor_list[i];
       }
    }
    /* reset anchor string info for this page */
    if ((int)m_prescan_info.pagelist_len > pageno) {
       ASSERT(m_prescan_info.pagelist != NULL, "m_prescan_info.pagelist not properly allocated");
       FREE(m_prescan_info.pagelist[pageno]);
       m_prescan_info.pagelist[pageno] = NULL;
    }
}

Here is the caller graph for this function:

Definition at line 194 of file hypertex.c.

{
    m_save_prescan_info.anchor_depth = m_prescan_info.anchor_depth;
    m_save_prescan_info.anchor_num = m_prescan_info.anchor_num;
    /* copy over anchor list */
    while (m_save_prescan_info.anchor_depth >= (int)m_save_prescan_info.anchor_list_size) {
       int i;
       m_save_prescan_info.anchor_list_size += HTEX_ALLOC_STEP;
       m_save_prescan_info.anchor_list = XREALLOC(m_save_prescan_info.anchor_list,
                                             m_save_prescan_info.anchor_list_size
                                             * sizeof *(m_save_prescan_info.anchor_list));
       for (i = 0; i < m_save_prescan_info.anchor_depth; i++) {
           m_save_prescan_info.anchor_list[i] = m_prescan_info.anchor_list[i];
       }
    }
    /* the page list of anchor strings can only have had its current position modified;
       we'll simply delete that position in htex_prescan_restore().
    */
}

Here is the caller graph for this function:

Boolean htex_prescan_special ( const char *  str,
int  str_len,
struct htex_prescan_data data 
)

Definition at line 294 of file hypertex.c.

{
    UNUSED(cp_len);
    ASSERT(data != NULL, "data argument to htex_prescan_special() mustn't be NULL");
    if (data->pageno + 1 < (int)m_prescan_info.pagelist_len) { /* already scanned this page */
       MYTRACE((stderr, "already scanned page %d", data->pageno+1));
       return False;
    }

    /* resize pagelist */
    while (data->pageno >= (int)m_prescan_info.pagelist_len) {
       size_t old_len = m_prescan_info.pagelist_len;
       size_t i;
       MYTRACE((stderr, "============ resizing pagelist to %d", data->pageno + 1));
       m_prescan_info.pagelist_len = data->pageno + 1;
       m_prescan_info.pagelist = XREALLOC(m_prescan_info.pagelist,
                                      m_prescan_info.pagelist_len * sizeof *m_prescan_info.pagelist);
       /* initialize with NULL values */
       for (i = old_len; i < m_prescan_info.pagelist_len; i++) {
           MYTRACE((stderr, "============ initializing pagelist %d", i));
           m_prescan_info.pagelist[i] = NULL;
       }
    }
    
    if (data->scan_type == HTEX_ANCHOR_STRING) {
       if ((int)m_prescan_info.anchor_num == data->anchor_num) {
           char *anchor;
           const char *beg, *end;
           const char *cp1 = cp;
           const char *ptr = NULL;
           const char *pptr = NULL;
           
           if (memicmp(cp1, "<a href", strlen("<a href")) == 0) {
              cp1 += strlen("<a href");
              parse_html_special(cp1, strlen(cp1), &beg, &end);
              anchor = xmalloc(end - beg + 1);
              memcpy(anchor, beg, end - beg);
              anchor[end - beg] = '\0';
              /* save the anchor string in m_prescan_info.pagelist[<current_page>] */
              m_prescan_info.pagelist[data->pageno] = anchor;
           }
           else if (memcmp(cp1, "/A", 2) == 0) {
              if ((ptr = strstr(cp1 + 2, "/GoToR")) != NULL /* external file */
                  && (ptr = strchr(ptr, '(')) != NULL
                  && (pptr = strchr(ptr + 1, '(')) != NULL) {
                  anchor = xmalloc(pptr - ptr);
                  memcpy(anchor, ptr + 1, pptr - ptr - 1);
                  anchor[pptr - ptr - 1] = '\0';
                  /* save the anchor string in m_prescan_info.pagelist[<current_page>] */
                  m_prescan_info.pagelist[data->pageno] = anchor;
              }
              else if ((ptr = strstr(cp1 + 2, "/URI")) != NULL /* external file */
                  && (ptr = strchr(ptr, '(')) != NULL
                  && (pptr = strchr(ptr + 1, '(')) != NULL) {
                  anchor = xmalloc(pptr - ptr);
                  memcpy(anchor, ptr + 1, pptr - ptr - 1);
                  anchor[pptr - ptr - 1] = '\0';
                  /* save the anchor string in m_prescan_info.pagelist[<current_page>] */
                  m_prescan_info.pagelist[data->pageno] = anchor;
              }
           }
           else if (memcmp(cp, "/L", 2) == 0) {
              if ((ptr = strstr(cp1 + 2, "/Dest")) != NULL /* internal link */
                  && (ptr = strchr(ptr, '(')) != NULL
                  && (pptr = strchr(ptr + 1, '(')) != NULL) {
                  anchor = xmalloc(pptr - ptr);
                  memcpy(anchor, ptr + 1, pptr - ptr - 1);
                  anchor[pptr - ptr - 1] = '\0';
                  /* save the anchor string in m_prescan_info.pagelist[<current_page>] */
                  m_prescan_info.pagelist[data->pageno] = anchor;
              }
           }
       }
    }
    if (memicmp(cp, "<a ", 3) == 0) {
       while (m_prescan_info.anchor_depth >= (int)m_prescan_info.anchor_list_size) {
           m_prescan_info.anchor_list_size += HTEX_ALLOC_STEP;
           m_prescan_info.anchor_list = XREALLOC(m_prescan_info.anchor_list,
                                            m_prescan_info.anchor_list_size
                                            * sizeof *(m_prescan_info.anchor_list));
       }
       ASSERT(m_prescan_info.anchor_depth >= 0, "List should contain previous anchor info");
       m_prescan_info.anchor_list[m_prescan_info.anchor_depth] = m_prescan_info.anchor_num;
       m_prescan_info.anchor_depth++;
       m_prescan_info.anchor_num++;
    }
    else if (memicmp(cp, "</a", 3) == 0) {
       if (m_prescan_info.anchor_depth < 1) {
           /* this can happen when stuff had been prescanned before */
           return False;
       }
       m_prescan_info.anchor_depth--;
       m_prescan_info.anchor_num++;
    }
    else if (memcmp(cp, "H.S end", strlen("H.S end")) == 0) { /* start of anchor */
       while (m_prescan_info.anchor_depth >= (int)m_prescan_info.anchor_list_size) {
           m_prescan_info.anchor_list_size += HTEX_ALLOC_STEP;
           m_prescan_info.anchor_list = XREALLOC(m_prescan_info.anchor_list,
                                            m_prescan_info.anchor_list_size
                                            * sizeof *(m_prescan_info.anchor_list));
       }
       ASSERT(m_prescan_info.anchor_depth >= 0, "List should contain previous anchor info");
       m_prescan_info.anchor_list[m_prescan_info.anchor_depth] = m_prescan_info.anchor_num;
       m_prescan_info.anchor_depth++;
       m_prescan_info.anchor_num++;

    }
    else if (memcmp(cp, "H.R end", strlen("H.R end")) == 0 /* end of rect */
            || memcmp(cp, "H.A end", strlen("H.A end")) == 0 /* end of anchor */
            || memcmp(cp, "H.L end", strlen("H.L end")) == 0 /* end of link */
            ) {
       if (m_prescan_info.anchor_depth < 1) {
           /* this can happen when stuff had been prescanned before */
           return False;
       }
       m_prescan_info.anchor_depth--;
       m_prescan_info.anchor_num++;
    }
    return False;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void htex_record_position ( int  ,
int  ,
int  ,
int   
)

Definition at line 1232 of file hypertex.c.

{
    int lrx, lry;
    int y_delta, x_delta;

    if (!INSIDE_MANE_WIN) /* this would give wrong values */
       return;

    lrx = ulx + w;
    lry = uly + h;

    y_delta = lry - uly;
    x_delta = lrx - ulx;

    /* heuristics for creating new bounding box at what might be linebreaks */
    if (lrx < x_pos_bak /* ordinary linebreak */
       || lry + y_delta < y_pos_bak) { /* column break (from bottom of 1st to top 2nd column) */
       htexAnchorT type;
       int idx, prev, curr;
       /* get anchor index of topmost stack item, to find the matching open tag */
       if ((type = peek_stack(&stack, &idx)) == A_NONE) {
/*         fprintf(stderr, "!!!!!!!!!!!! couldn't find opening tag for this wrapped link!"); */
           return;
       }
       ASSERT(idx >= 0, "Index out of range");
/*     fprintf(stderr, "wrapped link: index %d, type %d\n", idx, type); */
       /* get correct idx */
       if (m_href_type == HYPERTEX_LINK) {
           while (htex_page_info.anchors[idx].a_href == NULL && idx > 0) {
              idx--;
           }
           if (htex_page_info.anchors[idx].a_href == NULL && idx == 0) {
              XDVI_ERROR((stderr, "Couldn't find wrapped anchor for idx %d, page %d!", idx, current_page));
              return;
           }
           add_anchor(&htex_page_info, A_HREF,
                     htex_page_info.anchors[idx].a_href,
                     strlen(htex_page_info.anchors[idx].a_href),
                     0, NULL);
       }
       else {
           add_anchor(&htex_page_info, A_HREF, "__WRAPPED__", strlen("__WRAPPED__"), 0, NULL);
       }
       htex_page_info.curr_cnt++;
       /* add wrapping info */
       if (htex_page_info.have_wrapped >= 0) {
           /* this is the only case where some other material might have come between
              this and the previous anchor */
           prev = htex_page_info.have_wrapped;
           htex_page_info.have_wrapped = -1;
       }
       else {
           prev = htex_page_info.curr_cnt - 2;
       }
       curr = htex_page_info.curr_cnt - 1;
       ASSERT(prev >= 0, "Index out of range");

/*     fprintf(stderr, "setting prev to %d, curr to %d\n", prev, curr); */
       htex_page_info.anchors[prev].next_wrapped = curr;
       htex_page_info.anchors[curr].prev_wrapped = prev;
       /* initialize it to cover current character */
       set_anchor_size(&htex_page_info, htex_page_info.curr_cnt - 1, ulx, uly, lrx, lry);
    }
    else {
       int prev_idx = htex_page_info.curr_cnt - 1;

       if (prev_idx >= 0) {
           enlarge_anchor_size(&htex_page_info, prev_idx, ulx, uly, lrx, lry);
       }
       else {
           MYTRACE((stderr, "!!!!!!!!!!!! Bug? prev_idx < 0"));
       }
    }
    x_pos_bak = lrx;
    y_pos_bak = uly;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1727 of file hypertex.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void htex_reset_page ( int  pageno)

Definition at line 1120 of file hypertex.c.

Here is the call graph for this function:

Definition at line 1715 of file hypertex.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Boolean htex_scan_anchor ( const char *  special,
size_t  len 
)

Definition at line 1127 of file hypertex.c.

{
    char *ptr;
    
    if (memicmp(cp, "</a>", 4) == 0) { /* end tag */
       /*     struct anchor_info *anchor; */
       int num;
       htexAnchorT type = pop_stack(&stack, &num);
       if (type == A_MISMATCH)
           return False;

       /* ASSERT(htex_page_info.curr_cnt - 1 >= 0, "Index out of range"); */
       /* anchor = &(htex_page_info.anchors[htex_page_info.curr_cnt - 1]); */

       /* reset color if needed */
       if (resource.link_style > 1 && resource.link_color != NULL && htex_is_href(type))
           pop_colorspecial();
    }
    else if (memicmp(cp, "<a ", 3) == 0) {
       m_href_type = HYPERTEX_LINK;
       cp += 3; /* skip over `<a ' part */
       len -= 3;
       TRACE_HTEX((stderr, "scan_anchor: |%s|", cp));
       if (memicmp(cp, "name", 4) == 0) {
           add_anchor(&htex_page_info, A_NAME, cp + 4, len - 4, 0, NULL);
           htex_page_info.curr_cnt++;
           push_stack(&stack, A_NAME, htex_page_info.curr_cnt);
       }
       else if (memicmp(cp, "href", 4) == 0) {
           add_anchor(&htex_page_info, A_HREF, cp + 4, len - 4, 0, NULL);
           htex_page_info.curr_cnt++;
           push_stack(&stack, A_HREF, htex_page_info.curr_cnt);

           /* MYTRACE((stderr, "NON-WRAPPED ANCHOR at %d,%d!", PXL_H, PXL_V)); */
           push_colorspecial();
           x_pos_bak = PXL_H;
           y_pos_bak = PXL_V;
/*         set_anchor_size(&htex_page_info, htex_page_info.curr_cnt - 1, PXL_H, PXL_V, PXL_H + 10, PXL_V + 10); */
       }
       else {
           XDVI_WARNING((stderr, "Skipping unimplemented htex special `%s'", cp));
           push_stack(&stack, A_OTHER, htex_page_info.curr_cnt);
       }
    }
    else if (memcmp(cp, "H.S end", strlen("H.S end")) == 0) {
       /* start of anchor, link or rect. We just assume that the link
          target will have length 0, so when we see text between H.S
          and H.R, assume that it's the link text.
       */
       m_href_type = HDVIPS_LINK;
       /* add dummy */
       add_anchor(&htex_page_info, A_HDVIPS_HREF, "__DUMMY__", strlen("__DUMMY__"), 0, NULL);
       htex_page_info.curr_cnt++;
       push_stack(&stack, A_HREF, htex_page_info.curr_cnt - 1);
       push_colorspecial();
       x_pos_bak = PXL_H;
       y_pos_bak = PXL_V;
       return True;
    }
    else if (memcmp(cp, "H.R end", strlen("H.R end")) == 0 /* end of rect */
            || memcmp(cp, "H.A end", strlen("H.A end")) == 0 /* end of anchor */
            || memcmp(cp, "H.L end", strlen("H.L end")) == 0 /* end of link */
            ) {
       int num;
       htexAnchorT type = pop_stack(&stack, &num);
       if (type == A_MISMATCH)
           return False;
       if (resource.link_style > 1 && resource.link_color != NULL)
           pop_colorspecial();
       return False;
    }
    /* add anchor texts for hdvips links */
    else if (memcmp(cp, "/A", 2) == 0) { /* possibly an hdvips external link */
/*     fprintf(stderr, "+++++ EXT: |%s|\n", cp); */
       if ((ptr = strstr(cp + 2, "/GoToR")) != NULL /* external file */
           && (ptr = strchr(ptr, '(')) != NULL) {
           hdvips_add_anchor(&htex_page_info, A_HREF_FILE, ptr + 1);
       }
       else if ((ptr = strstr(cp + 2, "/URI")) != NULL /* URL */
               && (ptr = strchr(ptr, '(')) != NULL) {
           hdvips_add_anchor(&htex_page_info, A_HREF_URL, ptr + 1);
       }
       return False;
    }
    else if (memcmp(cp, "/L", 2) == 0) { /* possibly an hdvips internal link */
       if ((ptr = strstr(cp + 2, "/Dest")) != NULL
           && (ptr = strchr(ptr, '(')) != NULL) {
           hdvips_add_anchor(&htex_page_info, A_HDVIPS_INTERNAL, ptr + 1);
       }
       return False;
    }
    else if (memcmp(cp, "/V", 2) == 0) { /* possibly an hdvips anchor */
       if ((ptr = strstr(cp + 2, "/Dest")) != NULL
           && (ptr = strchr(ptr, '(')) != NULL) {
           hdvips_add_anchor(&htex_page_info, A_HDVIPS_NAME, ptr + 1);
       }
       return False;
    }
    else { /* not a start tag */
       MYTRACE((stderr, "Xdvi warning: skipping malformed hyperref special `%s'", cp));
    }
    return get_href_depth(&stack);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2082 of file hypertex.c.

{
    Position drawing_x;

    /* erase old marker if it's on the same page as the new marker, after
       cancelling the old timeout so that it won't affect the new marker */
    if (m_href_timeout_id)
       XtRemoveTimeOut(m_href_timeout_id);
    htex_erase_anchormarker(NULL, NULL);
    XFlush(DISP);
    
    XtVaGetValues(globals.widgets.draw_widget, XtNx, &drawing_x, NULL);
    g_anchormarker.page = current_page;
    free(g_anchormarker.filename);
    g_anchormarker.filename = xstrdup(globals.dvi_name);
    g_anchormarker.y_pos = y;
    g_anchormarker.x_pos = DEFAULT_MARKER_X_OFFSET + -drawing_x;
    m_href_timeout_id = XtAppAddTimeOut(app, STATUS_SHORT * 1000, htex_erase_anchormarker, (XtPointer)NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void htex_set_anchorsize ( int  x,
int  y,
int  w,
int  h 
)

Definition at line 974 of file hypertex.c.

{
    set_anchor_size(&htex_page_info, htex_page_info.curr_cnt - 1,
                  ulx, uly, lrx, lry);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 968 of file hypertex.c.

Here is the caller graph for this function:

const char* is_local_file ( const char *  filename)

Definition at line 816 of file hypertex.c.

{
    int i;
    if (strchr(filename, ':') != NULL) {
       if (memicmp(filename, "file:", strlen("file:")) == 0) {
           TRACE_HTEX((stderr, "%s uses file scheme", filename));
           filename += strlen("file:");
           /*
             skip over `//localhost' part, and skip first `/' iff the
             absolute path starts with `//' (as required by RFC2396,
             but in the past most browsers/applications didn't support
             this).
            */
           if (memicmp(filename, "//localhost", strlen("//localhost")) == 0) {
              filename += strlen("//localhost");
           }
           if (memicmp(filename, "//", 2) == 0) {
              filename += 1;
           }
           return filename;
       }
       
       /* check remote schemes */
       for (i = 0; remote_URL_schemes[i] != NULL; i++) {
           if (memicmp(filename, remote_URL_schemes[i], strlen(remote_URL_schemes[i])) == 0) {
              TRACE_HTEX((stderr, "%s is a remote scheme", filename));
              return NULL;
           }
       }
    }
    /* in all other cases, treat it as an ordinary filename */
    TRACE_HTEX((stderr, "%s is an ordinary filename", filename));
    return filename;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void launch_program ( const char *  filename)

Definition at line 1922 of file hypertex.c.

{
    const char *format_string = NULL;
    char *content_type = NULL;
    char *viewer = NULL;
    char *argv[4];
    struct stat statbuf;
    const char *local_filename_sans_prefix;
    char *path, *syscmd, *tmp;
#if COPY_TMP_FILE
    int tmp_fd;
#endif
    const char *ptr;
    char *fullpath = NULL;
    char canonical_path[MAXPATHLEN + 1];
    Boolean needs_terminal;
    
    TRACE_HTEX((stderr, "launch_program called with |%s|", filename));

    /* is it a local file? */
    local_filename_sans_prefix = is_local_file(filename);
    if (local_filename_sans_prefix == NULL) { /* not local */
       launch_browser(filename);
       return;
    }

    /* expand the filename if it contains a relative path */
    path = find_file(local_filename_sans_prefix, &statbuf, kpse_program_text_format);
    if (path != NULL) {
       /* fully canonicalize path before passing it to helper applications */
       fullpath = REALPATH(path, canonical_path);
       if (fullpath == NULL) {
           XDVI_WARNING((stderr, "Couldn't canonicalize %s to full path - returning unexpanded.",
                       path));
           fullpath = path;
       }
       else
           FREE(path);
    }
    else {
       XDVI_WARNING((stderr, "Couldn't find file %s; passing to application unchanged.",
                    local_filename_sans_prefix));
       /* if it doesn't exist, maybe the user has encoded some magic in the
          filename; in that case, pass it to the application unchanged. */
       fullpath = (char *)local_filename_sans_prefix;
    }

    TRACE_HTEX((stderr, "fullpath: |%s|", fullpath));
    content_type = figure_mime_type(fullpath);
    ASSERT(content_type != NULL, "figure_mime_type() should have returned a valid type (eventually a fallback)");
    
    /* make it safe to pass the argument to system() or `sh -c',
       by escaping all `dangerous' characters: */
    tmp = shell_escape_string(fullpath);
    fullpath = tmp;
    
    if ((viewer = figure_viewer(content_type, &format_string, &needs_terminal, fullpath)) == NULL) {
       /* warn user if no application has been found. Help text needs to be constructed at
          run-time, since we want the correct content-type in it. */
#if 0
       char *errmsg = NULL;
#else
       char *errmsg = xstrdup("Please assign an application to the MIME type `");
       errmsg = xstrcat(errmsg, content_type);
       errmsg = xstrcat(errmsg, "' in your ~/.mailcap file. "
                            "E.g. if you want to view the file with netscape, add the following line to your ~/.mailcap:\n");
       errmsg = xstrcat(errmsg, content_type);
       errmsg = xstrcat(errmsg, "; netscape -raise  -remote 'openURL(%%s,new-window)'\n\n");
#endif
       popup_message(globals.widgets.top_level,
                    MSG_WARN,
                    errmsg,
                    "Could not determine an application for the file %s, MIME type `%s'.",
                    fullpath, content_type);
       /* FIXME: something's wrong with the memory allocation scheme here -
          can't free errmsg, it's already free'd inside popup_message() ?? */
       /* free(errmsg); */
       free(fullpath);
       return;
    }
    
#if COPY_TMP_FILE
    /* copy the file to a temporary location before passing it to the
       viewer.  This is e.g. how Acroread does it. This should fix the
       problem with xdvizilla without -no-rm for DVI files (see comment
       in figure_viewer(), mime.c).
       SU 2003/10/02: currently I can't reproduce the xdvizilla problem
       any more - it seems that for xdvi files, argv[0] will be invoked
       anyway? Also, copying the files to tmp may break figure locations
       and relative links for DVI files. Suspended this for the time being.
    */
    tmp = NULL;
    if ((tmp_fd = xdvi_temp_fd(&tmp)) == -1) {
       XDVI_ERROR((stderr, "couldn't create temporary file; not calling helper application."));
       return;
    }
    TRACE_HTEX((stderr, "copying to temporary location: |%s->%s|", fullpath, tmp));
    if (!copy_file(fullpath, tmp)) {
       XDVI_ERROR((stderr, "couldn't copy %s to temporary file %s; not invoking helper application.",
                  fullpath, tmp));
       return;
    }
    free(fullpath);
    fullpath = tmp;
#endif
    
    if (strlen(format_string) > 0) {
       ptr = find_format_str(viewer, format_string);
    }
    else { /* countrary to RFC 1343, we don't pass stuff via pipes (too bothersome) */
       ptr = strchr(viewer, '\0');
    }

    if (needs_terminal) {
       size_t offset = strlen("xterm -e ");
       syscmd = xmalloc(offset + strlen(viewer) + strlen(fullpath) + 1);
       strcpy(syscmd, "xterm -e ");
       memcpy(syscmd + offset, viewer, ptr - viewer);
       strcpy(syscmd + offset + (ptr - viewer), fullpath);
       strcpy(syscmd + offset + (ptr - viewer) + strlen(fullpath), ptr + strlen(format_string));
       
    }
    else {
       syscmd = xmalloc(strlen(viewer) + strlen(fullpath) + 1);
       memcpy(syscmd, viewer, ptr - viewer);
       strcpy(syscmd + (ptr - viewer), fullpath);
       strcpy(syscmd + (ptr - viewer) + strlen(fullpath), ptr + strlen(format_string));
    }

    /*
      mailcap(4) says that the mailcap command shall be passed to system(),
      so we musn't use fork_process() directly here. Instead, we pass the command
      to `/bin/sh -c', but via fork_process so that
      
      - xdvi doesn't hang if the process doesn't return;
      - we can still catch the return value if `sh -c' exits with an error
        (e.g. if the viewer command is not found).

      Note however that this doesn't mimick most of POSIX's system() semantics.
    */
    TRACE_HTEX((stderr, "execv(\"/bin/sh -c %s\")", syscmd));
    argv[0] = "/bin/sh";
    argv[1] = "-c";
    argv[2] = syscmd;
    argv[3] = NULL;
#if COPY_TMP_FILE
    fork_process("/bin/sh", False, globals.dvi_file.dirname, remove_temp_file, fullpath, argv);
#else
    fork_process("/bin/sh", False, globals.dvi_file.dirname, NULL, NULL, argv);
#endif

    FREE(viewer);
#if COPY_TMP_FILE
#else
    FREE(fullpath);
#endif
    FREE(syscmd);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void launch_xdvi ( const char *  filename,
const char *  anchor_name 
)

Definition at line 1819 of file hypertex.c.

{
#define ARG_LEN 32
    int i = 0;
    char *argv[ARG_LEN];
    char *shrink_arg = NULL;

    ASSERT(filename != NULL, "filename argument to launch_xdvi() mustn't be NULL");

    argv[i++] = program_invocation_name;
    /* FIXME: there's something broken with this and invoking xdvi.bin.
       To reproduce the problem, invoke from the shell:
       xdvi.bin -geometry 829x1172 /usr/share/texmf/doc/programs/kpathsea.dvi
       this will run at 300dpi, i.e. ignore an .Xdefaults setting as opposed to:
       xdvi.bin /usr/share/texmf/doc/programs/kpathsea.dvi

       Also, how about the other command-line switches that might have
       been passed to the parent instance? How about things that have been changed
       at run-time, like shrink factor - should they be converted to command-line
       options?
    */

    argv[i++] = "-name";
    argv[i++] = "xdvi";

    /* start the new instance with the same debug flags as the current instance */
    if (globals.debug != 0) {
       char debug_flag[128];
       SNPRINTF(debug_flag, 128, "%lu", globals.debug);
       argv[i++] = "-debug";
       argv[i++] = debug_flag;
    }
    
    if (anchor_name != NULL) {
       argv[i++] = "-anchorposition";
       argv[i++] = (char *)anchor_name;
    }

    argv[i++] = "-s";
    shrink_arg = XMALLOC(shrink_arg, LENGTH_OF_INT + 1);
    sprintf(shrink_arg, "%d", currwin.shrinkfactor);
    argv[i++] = shrink_arg;

    argv[i++] = (char *)filename; /* FIXME */
    
    argv[i++] = NULL;
    ASSERT(i <= ARG_LEN, "Too few elements in argv[]");
    
    if (globals.debug & DBG_HTEX) {
       fprintf(stderr, "Invoking:\n");
       for (i = 0; argv[i]; i++) {
           fprintf(stderr, "%s\n", argv[i]);
       }
    }

    /*
      FIXME: using fork_process here hangs the new xdvi process when it tries
      printing to stderr, so we use plain fork/exec (see comments in util.c)
    */
#if 0
    fork_process(argv[0], False, NULL, NULL, NULL, argv);
#else
    {
       int pid;
       switch (pid = fork()) {
       case -1:
           perror("fork");
       case 0:
           execvp(argv[0], argv);
           MYTRACE((stderr, "%s: Execution of %s failed.", globals.program_name, argv[0]));
           _exit(EXIT_FAILURE);
       default:
           FREE(shrink_arg);
       }
    }
#endif
#undef ARG_LEN
}

Here is the call graph for this function:

Here is the caller graph for this function: