diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/xdvik/filehist.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/xdvik/filehist.c')
-rw-r--r-- | Build/source/texk/xdvik/filehist.c | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/filehist.c b/Build/source/texk/xdvik/filehist.c new file mode 100644 index 00000000000..43664025e1e --- /dev/null +++ b/Build/source/texk/xdvik/filehist.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2004 Stefan Ulrich + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/* + List of recently visited files, initialized from X resource + fileHistory and displayed in `File -> Open Recent' menu. +*/ + +#include <ctype.h> + +#include "xdvi-config.h" +#include "xdvi.h" +#include "util.h" +#include "my-snprintf.h" +#include "string-utils.h" +#include "dvi-init.h" +#include "events.h" +#include "message-window.h" +#include "xm_menu.h" +#include "xaw_menu.h" +#include "filehist.h" + +/**************************************************************************** + * + * File-scope globals + * + ****************************************************************************/ + +/* list of files */ +static struct dl_list *m_file_history = NULL; + +/* current size of the list */ +static int m_file_history_length = 0; + +/* /\* current position in the list *\/ */ +/* static int m_file_history_currpos = 0; */ + +/* item in above list */ +struct file_history { + char *filename; + int pageno; +}; + +#define DEBUG 1 + +/**************************************************************************** + * + * Private functions + * + ****************************************************************************/ + +static void +file_history_show(struct dl_list *list) +{ + if (globals.debug & DBG_FILES) { + int n; + fprintf(stderr, "======= File history:\n"); + for (n = 0; list != NULL; list = list->next, n++) { + struct file_history *item = (struct file_history *)(list->item); + if (item == NULL) { + fprintf(stderr, "item %d is NULL!\n", n); + continue; + } + fprintf(stderr, "item %d: %d:%s\n", n, item->pageno, item->filename); + } + } +} + + +/**************************************************************************** + * + * Exported functions + * + ****************************************************************************/ + +void +file_history_init(void) +{ + char **fileinfo; + size_t i; + struct dl_list *head = NULL; + + m_file_history_length = 0; + + if (resource.file_history == NULL) + return; + + fileinfo = get_separated_list(resource.file_history, "\n", False); + + for (i = 0; fileinfo[i] != NULL && i < (size_t)resource.file_history_size; i++) { + struct file_history *item = xmalloc(sizeof *item); + char *ptr; + int pageno = strtol(fileinfo[i], &ptr, 10); + TRACE_FILES((stderr, "FILEINFO: %s", fileinfo[i])); + if (ptr == fileinfo[i]) { + XDVI_WARNING((stderr, "Missing page number in resource line `%s'!\n", + fileinfo[i])); + pageno = 0; + } + else { + while (isspace((int)*ptr)) + ptr++; + } + + item->pageno = pageno; + item->filename = xstrdup(ptr); + + TRACE_FILES((stderr, "FILE: %d:%s", item->pageno, item->filename)); + + m_file_history = dl_list_insert(m_file_history, item); + if (head == NULL) /* remember head position */ + head = m_file_history; + + TRACE_FILES((stderr, "NEW ELEM: %p", (void *)m_file_history)); + + m_file_history_length++; + + free(fileinfo[i]); + } + free(fileinfo); + + m_file_history = head; + file_history_show(m_file_history); +} + +static Boolean +equals_filename(const void *it, const void *fname) +{ + const struct file_history *item = (const struct file_history *)it; + const char *filename = (const char *)fname; + + return strcmp(item->filename, filename) == 0; +} + + +/* put new elem for filename `filename' and page number `page' at the front + of the list. Return True if the addition caused the history to grow, else + False (in case the item was only moved to the front). +*/ +Boolean +file_history_push(const char *filename) +{ + int i; + struct file_history *item = NULL; + void *removed_data = NULL; + struct file_history *removed_item = NULL; + int len_bak = m_file_history_length; + int count = 0; + + TRACE_FILES((stderr, "Pushing: |%s|", filename)); + + /* if list already contains an item with same filename, remove it */ + m_file_history = dl_list_remove(m_file_history, filename, &count, &removed_data, equals_filename); + if (count == 0) + m_file_history_length++; + + removed_item = (struct file_history *)removed_data; + + file_history_show(m_file_history); + + TRACE_FILES((stderr, "current length: %d, max: %d", m_file_history_length, resource.file_history_size)); + + /* truncate list if it has reached its max length */ + if (m_file_history_length > resource.file_history_size) { + struct dl_list *listpos = m_file_history; + struct dl_list *last_pos = listpos; + for (i = 0; listpos != NULL && i < m_file_history_length; i++) { + last_pos = listpos; + listpos = listpos->next; + } + + item = last_pos->item; /* reuse item */ + TRACE_FILES((stderr, "Re-using item: |%s| -> |%s|", item->filename, filename)); + item->filename = xrealloc(item->filename, strlen(filename) + 1); + strcpy(item->filename, filename); + + (void)dl_list_remove_item(&last_pos); + m_file_history_length--; + } + else if (removed_item != NULL) { + TRACE_FILES((stderr, "Re-using item: |%s|\n", removed_item->filename)); + item = removed_item; /* reuse item */ + } + else { + item = xmalloc(sizeof *item); + TRACE_FILES((stderr, "NEW item: |%s|\n", filename)); + item->filename = xstrdup(filename); + item->pageno = 0; + } + + /* add new element at front of list */ + m_file_history = dl_list_push_front(m_file_history, item); + + file_history_show(m_file_history); + + TRACE_FILES((stderr, "returning: %d < %d", len_bak, m_file_history_length)); + return len_bak < m_file_history_length; +} + +size_t file_history_size(void) +{ + return m_file_history_length; +} + +void file_history_set_page(int pageno) +{ + struct dl_list *head; + + TRACE_FILES((stderr, "SETTING HEAD to %d", pageno)); + file_history_show(m_file_history); + head = dl_list_head(m_file_history); + if (head != NULL) { + struct file_history *item = (struct file_history *)head->item; + TRACE_FILES((stderr, "Setting page of |%s| to %d", item->filename, pageno)); + item->pageno = pageno; + } +} + +void file_history_set_page_at(int idx, int pageno) +{ + int i; + struct dl_list *listpos = dl_list_head(m_file_history); + struct file_history *item; + + for (i = 0; listpos != NULL && i < idx; i++) { + listpos = listpos->next; + } + if (listpos == NULL) { + TRACE_FILES((stderr, "Asked for file at position %d, but only %d elements in list", + idx, i - 1)); + return; + } + item = (struct file_history *)listpos->item; + TRACE_FILES((stderr, "set_page_at index %d: Setting page of |%s| to %d", idx, item->filename, pageno)); + item->pageno = pageno; +} + +int file_history_get_page(void) +{ + struct dl_list *head = dl_list_head(m_file_history); + if (head != NULL) { + struct file_history *item = (struct file_history *)head->item; + TRACE_FILES((stderr, "Getting page of |%s|: %d", item->filename, item->pageno)); + return item->pageno; + } + return 0; +} + +/* + * Invoke `callback' for each elem of file history, passing + * the current index, filename, page number, and data passed to + * this function. + */ +void +file_history_enumerate(filehistCallbackT callback, void *data) +{ + int i; + struct dl_list *listpos = dl_list_head(m_file_history); + + for (i = 0; listpos != NULL; i++) { + struct file_history *item = (struct file_history *)listpos->item; + callback(i, item->filename, item->pageno, data); + listpos = listpos->next; + } +} + +char * +file_history_get_elem(int idx, int *ret_page) +{ + int i; + struct dl_list *listpos = dl_list_head(m_file_history); + struct file_history *item; + + for (i = 0; listpos != NULL && i < idx; i++) { + listpos = listpos->next; + } + if (listpos == NULL) { + XDVI_WARNING((stderr, "Asked for file at position %d, but only %d elements in list", + idx, i - 1)); + return NULL; + } + item = (struct file_history *)listpos->item; + *ret_page = item->pageno; + file_history_show(m_file_history); + return item->filename; +} + +char * +file_history_get_list(void) +{ + char buf[LENGTH_OF_INT]; + char *ret = xstrdup(""); + struct dl_list *listpos; + + for (listpos = dl_list_head(m_file_history); + listpos != NULL; + listpos = listpos->next) { + + struct file_history *item = (struct file_history *)listpos->item; + SNPRINTF(buf, LENGTH_OF_INT, "%d ", item->pageno); + ret = xstrcat(ret, buf); + ret = xstrcat(ret, item->filename); + ret = xstrcat(ret, "\n"); + } + + ret[strlen(ret) - 1] = '\0'; /* chop off excess \n at end */ + return ret; +} + +void +file_history_open(const char *fname) +{ + Boolean tried_dvi_ext = True; + char *new_dvi_name = NULL; + + int dummy_cnt = 0; + void *dummy_data = NULL; + + file_history_set_page(current_page); + if ((new_dvi_name = open_dvi_file_wrapper(fname, + True, /* pretend file is from commandline, otherwise xdvi will + try to fork for non-existing files, leading to confusing + popup error messages */ + False, &tried_dvi_ext, + True /* don't exit on error */)) == NULL) { + /* remove this item from the file history */ + m_file_history = dl_list_remove(m_file_history, fname, &dummy_cnt, &dummy_data, equals_filename); + m_file_history_length--; + file_history_show(m_file_history); + + filehist_menu_refresh(); + return; + } + else { + dviErrFlagT errflag; + if (load_dvi_file(True, &errflag)) { + /* page_history_insert(pageno); */ + set_dvi_name(new_dvi_name); + + globals.ev.flags |= EV_NEWDOC; + globals.ev.flags |= EV_FILEHIST_GOTO_PAGE; + globals.ev.flags |= EV_PAGEHIST_INSERT; + } + else { /* re-open old file */ + popup_message(globals.widgets.top_level, + MSG_ERR, + NULL, + "Could not open `%s': %s.\n" + /* "Removing this file from the history." */, + globals.dvi_name, get_dvi_error(errflag)); + /* remove this item from the file history */ + m_file_history = dl_list_remove(m_file_history, globals.dvi_name, + &dummy_cnt, &dummy_data, + equals_filename); + m_file_history_length--; + filehist_menu_refresh(); + + if (!internal_open_dvi(globals.dvi_name, &errflag, True)) { +/* || !internal_init_dvi(&errflag, True)) { */ + popup_message(globals.widgets.top_level, + MSG_ERR, + NULL, + "Couldn't reopen `%s': %s.\n" + /* "Removing this file from the history." */, + globals.dvi_name, get_dvi_error(errflag)); + /* remove this item from the file history */ + m_file_history = dl_list_remove(m_file_history, globals.dvi_name, &dummy_cnt, &dummy_data, equals_filename); + m_file_history_length--; + filehist_menu_refresh(); + } + else { + globals.ev.flags |= EV_NEWPAGE; + } + } + } +} |