diff --git a/history.c b/history.c index 514ae9a..b5d0ac4 100644 --- a/history.c +++ b/history.c @@ -2,6 +2,19 @@ #include "fm.h" #ifdef USE_HISTORY +/* Merge entries from their history into ours */ +static int +mergeHistory(Hist *ours, Hist *theirs) +{ + HistItem *item; + + for (item = theirs->list->first; item; item = item->next) + if (!getHashHist(ours, item->ptr)) + pushHist(ours, (char *)item->ptr); + + return 0; +} + Buffer * historyBuffer(Hist *hist) { @@ -31,16 +44,23 @@ historyBuffer(Hist *hist) return loadHTMLString(src); } -void +int loadHistory(Hist *hist) { FILE *f; Str line; + struct stat st; if (hist == NULL) - return; + return 1; if ((f = fopen(rcFile(HISTORY_FILE), "rt")) == NULL) - return; + return 1; + + if (fstat(fileno(f), &st) == -1) { + fclose(f); + return 1; + } + hist->mtime = (long long)st.st_mtim.tv_sec; while (!feof(f)) { line = Strfgets(f); @@ -52,42 +72,61 @@ loadHistory(Hist *hist) pushHist(hist, url_quote(line->ptr)); } fclose(f); + return 0; } void saveHistory(Hist *hist, size_t size) { FILE *f; + Hist *fhist; HistItem *item; + char *histf; char *tmpf; int rename_ret; + struct stat st; if (hist == NULL || hist->list == NULL) return; - tmpf = tmpfname(TMPF_HIST, NULL)->ptr; - if ((f = fopen(tmpf, "w")) == NULL) { - /* FIXME: gettextize? */ - disp_err_message("Can't open history", FALSE); - return; + + histf = rcFile(HISTORY_FILE); + if (stat(histf, &st) == -1) + goto fail; + if (hist->mtime != (long long)st.st_mtim.tv_sec) { + fhist = newHist(); + if (loadHistory(fhist) || mergeHistory(fhist, hist)) + disp_err_message("Can't merge history", FALSE); + else + hist = fhist; } + + tmpf = tmpfname(TMPF_HIST, NULL)->ptr; + if ((f = fopen(tmpf, "w")) == NULL) + goto fail; for (item = hist->list->first; item && hist->list->nitem > size; item = item->next) size++; for (; item; item = item->next) fprintf(f, "%s\n", (char *)item->ptr); - if (fclose(f) == EOF) { - /* FIXME: gettextize? */ - disp_err_message("Can't save history", FALSE); - return; - } + if (fclose(f) == EOF) + goto fail; rename_ret = rename(tmpf, rcFile(HISTORY_FILE)); - if (rename_ret != 0) { - disp_err_message("Can't save history", FALSE); - return; - } + if (rename_ret != 0) + goto fail; + + return; + +fail: + disp_err_message("Can't open history", FALSE); + return; } #endif /* USE_HISTORY */ +/* + * The following functions are used for internal stuff, we need them regardless + * if history is used or not. + */ + Hist * newHist(void) { diff --git a/history.h b/history.h index a6468ec..3f229f5 100644 --- a/history.h +++ b/history.h @@ -16,6 +16,7 @@ typedef struct { HistList *list; HistItem *current; Hash_sv *hash; + long long mtime; } Hist; extern Hist *newHist(void); @@ -28,4 +29,12 @@ extern char *lastHist(Hist *hist); extern char *nextHist(Hist *hist); extern char *prevHist(Hist *hist); +#ifdef USE_HISTORY +extern int loadHistory(Hist *hist); +extern void saveHistory(Hist *hist, size_t size); +extern void ldHist(void); +#else /* not USE_HISTORY */ +#define ldHist nulcmd +#endif /* not USE_HISTORY */ + #endif /* HISTORY_H */ diff --git a/proto.h b/proto.h index 3be7d22..0d1fa96 100644 --- a/proto.h +++ b/proto.h @@ -391,11 +391,6 @@ extern char *inputLineHistSearch(char *prompt, char *def_str, int flag, extern Str unescape_spaces(Str s); #ifdef USE_HISTORY extern Buffer *historyBuffer(Hist *hist); -extern void loadHistory(Hist *hist); -extern void saveHistory(Hist *hist, size_t size); -extern void ldHist(void); -#else /* not USE_HISTORY */ -#define ldHist nulcmd #endif /* not USE_HISTORY */ extern double log_like(int x); extern struct table *newTable(void);