diff options
Diffstat (limited to 'src/history.c')
-rw-r--r-- | src/history.c | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/src/history.c b/src/history.c deleted file mode 100644 index a63658c..0000000 --- a/src/history.c +++ /dev/null @@ -1,320 +0,0 @@ -/* Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts <sabetts@vcn.bc.ca> - * - * This file is part of ratpoison. - * - * ratpoison is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * ratpoison is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -#include <ctype.h> -#include <errno.h> -#include <string.h> -#include <limits.h> - -#include "ratpoison.h" - -#ifdef HAVE_HISTORY -#include "readline/history.h" -#endif - -static char * -get_history_filename (void) -{ - char *homedir = getenv ("HOME"); - char *filename; - - if (homedir) - { - filename = xmalloc (strlen (homedir) + strlen ("/" HISTORY_FILE) + 1); - sprintf (filename, "%s/" HISTORY_FILE, homedir); - } - else - { - filename = xstrdup (HISTORY_FILE); - } - - return filename; -} - -static const char * -extract_shell_part (const char *p) -{ - if (strncmp(p, "exec", 4) && - strncmp(p, "verbexec", 8)) - return NULL; - while( *p && !isspace(*p) ) - p++; - while( *p && isspace(*p) ) - p++; - if (*p) - return p; - return NULL; -} - -struct history_item { - struct list_head node; - char *line; -}; - -static struct history { - struct list_head head, *current; - size_t count; -} histories[hist_COUNT]; - -#ifndef HAVE_GETLINE -ssize_t -getline(char **lineptr, size_t *n, FILE *f) -{ - size_t ofs; - - if (!*lineptr) { - *lineptr = xmalloc (4096); - *n = 4096; - } - ofs = 0; - do { - (*lineptr)[ofs] = '\0'; - if (!fgets (*lineptr, (*n) - ofs, f)) { - /* do not tread unterminated last lines as errors, - * (it's still a malformed text file and noone should - * have created it) */ - return ofs?(ssize_t)ofs:-1; - } - ofs += strlen ((*lineptr) + ofs); - if (ofs >= *n) - /* should never happen... */ - return -1; - if (ofs > 0 && (*lineptr)[ofs-1] == '\n') - return ofs; - if (ofs + 1 == *n) { - if (*n >= INT_MAX - 4096) - return -1; - *n += 4096; - *lineptr = xrealloc(*lineptr, *n); - } - } while(1); -} -#endif - -static void -history_add_upto (int history_id, const char *item, size_t max) -{ - struct history *h = histories + history_id; - struct history_item *i; - - if (item == NULL || *item == '\0' || isspace(*item)) - return; - - list_last (i, &histories[history_id].head, node); - if (i && !strcmp (i->line, item)) - return; - - if (history_id == hist_COMMAND) { - const char *p = extract_shell_part (item); - if (p) - history_add_upto (hist_SHELLCMD, p, max); - } - - if (defaults.history_compaction && max != INT_MAX) { - struct list_head *l; - - for (l = h->head.prev ; l != &h->head ; l = l->prev) { - if (!strcmp (list_entry(l, struct history_item, node)->line, item)) { - list_del (l); - list_add_tail (l, &h->head); - return; - } - } - } - - while (h->count >= max) { - list_first (i, &h->head, node); - if (!i) { - h->count = 0; - break; - } - list_del (&i->node); - free (i->line); - free (i); - h->count--; - } - - if( max == 0 ) - return; - - i = xmalloc (sizeof (*i)); - i->line = xstrdup (item); - - list_add_tail (&i->node, &h->head); - h->count++; -} - -void -history_add (int history_id, const char *item) -{ - history_add_upto (history_id, item, defaults.history_size); -} - -void -history_load (void) -{ - char *filename = get_history_filename (); - FILE *f; - char *line = NULL; - size_t s = 0; - ssize_t linelen; - int id; - - for (id = hist_NONE ; id < hist_COUNT ; id++ ) { - INIT_LIST_HEAD (&histories[id].head); - histories[id].current = &histories[id].head; - histories[id].count = 0; - } - - if (!filename) - return; - f = fopen (filename, "r"); - if (!f) { - PRINT_DEBUG (("ratpoison: could not read %s - %s\n", filename, strerror (errno))); - free (filename); - return; - } - - while ((linelen = getline (&line, &s, f)) >= 0) { - while (linelen > 0 && (line[linelen-1] == '\n' || line[linelen-1] == '\r')) { - line[--linelen] = '\0'; - } - if (linelen == 0) - continue; - /* defaults.history_size might be only set later */ - history_add_upto (hist_COMMAND, line, INT_MAX); - } - if (ferror (f)) { - PRINT_DEBUG (("ratpoison: error reading %s - %s\n", filename, strerror (errno))); - fclose(f); - free (filename); - return; - } - if (!fclose(f)) - PRINT_DEBUG (("ratpoison: error reading %s - %s\n", filename, strerror (errno))); - free (filename); -} - -void -history_save (void) -{ - char *filename = get_history_filename (); - FILE *f; - struct history_item *item; - - if (!defaults.history_size) - return; - - if (!filename) - return; - f = fopen (filename, "w"); - if (!f) { - PRINT_DEBUG (("ratpoison: could not write %s - %s\n", filename, strerror (errno))); - free (filename); - return; - } - - list_for_each_entry(item, &histories[hist_COMMAND].head, node) { - fputs(item->line, f); - putc('\n', f); - } - - if (ferror (f)) { - PRINT_DEBUG (("ratpoison: error writing %s - %s\n", filename, strerror (errno))); - fclose(f); - free (filename); - return; - } - if (!fclose(f)) - PRINT_DEBUG (("ratpoison: error writing %s - %s\n", filename, strerror (errno))); - free (filename); -} - -void -history_reset (void) -{ - int id; - - for (id = hist_NONE ; id < hist_COUNT ; id++ ) - histories[id].current = &histories[id].head; -} - -void -history_resize (int size) -{ - struct history_item *i; - struct history *h; - int id; - - for (id = hist_NONE ; id < hist_COUNT ; id++ ) { - h = histories + id; - while (h->count >= (size_t)size) { - list_first (i, &h->head, node); - list_del (&i->node); - free (i->line); - free (i); - h->count--; - } - } -} - -const char * -history_previous (int history_id) -{ - if (history_id == hist_NONE) - return NULL; - /* return NULL, if list empty or already at first */ - if (histories[history_id].current == histories[history_id].head.next) - return NULL; - histories[history_id].current = histories[history_id].current->prev; - return list_entry(histories[history_id].current, struct history_item, node)->line; -} - -const char * -history_next (int history_id) -{ - if (history_id == hist_NONE) - return NULL; - /* return NULL, if list empty or already behind last */ - if (histories[history_id].current == &histories[history_id].head) - return NULL; - histories[history_id].current = histories[history_id].current->next; - if (histories[history_id].current == &histories[history_id].head) - return NULL; - return list_entry(histories[history_id].current, struct history_item, node)->line; -} - -int history_expand_line (int history_id UNUSED, char *string, char **output) -{ -#ifdef HAVE_HISTORY - struct history_item *item; - - if (strchr (string, '!')) { - clear_history (); - using_history (); - list_for_each_entry(item, &histories[history_id].head, node) { - add_history (item->line); - } - return history_expand (string, output); - } -#endif - *output = xstrdup(string); - return 0; -} |