Apply this patch like so (in links-x.y directory)

    patch -p1 < unhistory.diff

then,

    cd intl; ./synclang

There is a config file variable, "keep_unhistory".  Read the source or
email me to find out how to use it.

Peter Wang (tjaden@psynet.net)


diff -urN mikulas1/default.c mikulas2/default.c
--- mikulas1/default.c	Mon Nov 13 09:06:05 2000
+++ mikulas2/default.c	Mon Nov 13 09:51:50 2000
@@ -898,6 +898,7 @@
 	1, NULL, prog_rd, prog_wr, 0, 0, &tn3270_prog, "tn3270", NULL,
 	1, NULL, bind_rd, NULL, 0, 0, NULL, "bind", NULL,
 	1, NULL, unbind_rd, NULL, 0, 0, NULL, "unbind", NULL,
+	1, NULL, num_rd, NULL, 0, 1, &keep_unhistory, "keep_unhistory", NULL,
 	0, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL,
 };
 
diff -urN mikulas1/intl/english.lng mikulas2/intl/english.lng
--- mikulas1/intl/english.lng	Mon Nov 13 08:58:12 2000
+++ mikulas2/intl/english.lng	Mon Nov 13 09:51:29 2000
@@ -78,6 +78,7 @@
 T_GOTO_URL, "Go to URL",
 T_GO_BACK, "Go back",
 T_HISTORY, "History",
+T_UNHISTORY, "Unhistory",
 T_RELOAD, "Reload",
 T_SAVE_AS, "Save as",
 T_SAVE_URL_AS, "Save URL as",
@@ -299,6 +300,7 @@
 T_HK_GOTO_URL, "G",
 T_HK_GO_BACK, "B",
 T_HK_HISTORY, "H",
+T_HK_UNHISTORY, "T",
 T_HK_RELOAD, "R",
 T_HK_SAVE_AS, "V",
 T_HK_SAVE_URL_AS, "U",
diff -urN mikulas1/kbdbind.c mikulas2/kbdbind.c
--- mikulas1/kbdbind.c	Mon Nov 13 09:20:35 2000
+++ mikulas2/kbdbind.c	Mon Nov 13 09:51:29 2000
@@ -179,6 +179,7 @@
 		"search-back",
 		"toggle-display-images",
 		"toggle-html-plain",
+		"unback",
 		"up",
 		"view-image",
 		"zoom-frame",
@@ -281,6 +282,8 @@
 	{ ACT_ENTER, KBD_RIGHT, 0 },
 	{ ACT_ENTER, KBD_ENTER, 0 },
 	{ ACT_BACK, KBD_LEFT, 0 },
+	{ ACT_UNBACK, 'u', 0 },
+    	{ ACT_UNBACK, 'U', 0 },
 	{ ACT_DOWNLOAD, 'd', 0 },
 	{ ACT_DOWNLOAD, 'D', 0 },
 	{ ACT_SEARCH, '/', 0 },
diff -urN mikulas1/links.h mikulas2/links.h
--- mikulas1/links.h	Mon Nov 13 09:20:24 2000
+++ mikulas2/links.h	Mon Nov 13 09:51:29 2000
@@ -1395,6 +1395,7 @@
 #define WTD_IMGMAP	2
 #define WTD_RELOAD	3
 #define WTD_BACK	4
+#define WTD_UNBACK	5
 
 #define cur_loc(x) ((struct location *)((x)->history.next))
 
@@ -1421,6 +1422,8 @@
 	struct window *ask;
 };
 
+extern int keep_unhistory;
+
 extern struct list_head downloads;
 
 struct file_to_load {
@@ -1438,6 +1441,7 @@
 	struct session *next;
 	struct session *prev;
 	struct list_head history;
+	struct list_head unhistory;
 	struct terminal *term;
 	struct window *win;
 	int id;
@@ -1493,6 +1497,7 @@
 void abort_loading(struct session *);
 void goto_imgmap(struct session *, unsigned char *, unsigned char *, unsigned char *);
 void go_back(struct session *);
+void go_unback(struct session *);
 void reload(struct session*, int);
 struct frame *ses_find_frame(struct session *, unsigned char *);
 struct frame *ses_change_frame_url(struct session *, unsigned char *, unsigned char *);
@@ -2129,6 +2134,7 @@
 	ACT_SEARCH_BACK,
 	ACT_TOGGLE_DISPLAY_IMAGES,
 	ACT_TOGGLE_HTML_PLAIN,
+	ACT_UNBACK,
 	ACT_UP,
 	ACT_VIEW_IMAGE,
 	ACT_ZOOM_FRAME
diff -urN mikulas1/menu.c mikulas2/menu.c
--- mikulas1/menu.c	Mon Nov 13 08:58:12 2000
+++ mikulas2/menu.c	Mon Nov 13 09:51:29 2000
@@ -259,9 +259,8 @@
 	while (steps > 1) {
 		struct location *loc = ses->history.next;
 		if ((void *) loc == &ses->history) return;
-		loc = loc->next;
-		if ((void *) loc == &ses->history) return;
-		destroy_location(loc);
+		del_from_list(loc);
+		add_to_list(ses->unhistory, loc);
 
 		--steps;
 	}
@@ -270,6 +269,22 @@
 		go_back(ses);
 }
 
+void go_unbackwards(struct terminal *term, void *psteps, struct session *ses)
+{
+	int steps = (int) psteps;
+
+	abort_loading(ses);
+
+	while (steps--) {
+	    	struct location *loc = ses->unhistory.next;
+		if ((void *) loc == &ses->unhistory) return;
+		del_from_list(loc);
+		add_to_list(ses->history, loc);
+	}
+
+	go_unback(ses);
+}
+
 struct menu_item no_hist_menu[] = {
 	TEXT(T_NO_HISTORY), "", M_BAR, NULL, NULL, 0, 0,
 	NULL, NULL, 0, NULL, NULL, 0, 0
@@ -291,6 +306,20 @@
 	else do_menu(term, mi, ses);
 }
 
+void unhistory_menu(struct terminal *term, void *ddd, struct session *ses)
+{
+	struct location *l;
+	struct menu_item *mi = NULL;
+	int n = 0;
+	foreach(l, ses->unhistory) {
+		if (!mi && !(mi = new_menu(3))) return;
+		add_to_menu(&mi, stracpy(l->vs.url), "", "", MENU_FUNC go_unbackwards, (void *) n, 0);
+		n++;
+	}
+	if (!n) do_menu(term, no_hist_menu, ses);
+	else do_menu(term, mi, ses);
+}
+
 struct menu_item no_downloads_menu[] = {
 	TEXT(T_NO_DOWNLOADS), "", M_BAR, NULL, NULL, 0, 0,
 	NULL, NULL, 0, NULL, NULL, 0, 0
@@ -970,6 +999,7 @@
 	TEXT(T_GOTO_URL), "g", TEXT(T_HK_GOTO_URL), MENU_FUNC menu_goto_url, (void *)0, 0, 0,
 	TEXT(T_GO_BACK), "<-", TEXT(T_HK_GO_BACK), MENU_FUNC menu_go_back, (void *)0, 0, 0,
 	TEXT(T_HISTORY), ">", TEXT(T_HK_HISTORY), MENU_FUNC history_menu, (void *)0, 1, 0,
+	TEXT(T_UNHISTORY), ">", TEXT(T_HK_UNHISTORY), MENU_FUNC unhistory_menu, (void *)0, 1, 0,
 	TEXT(T_RELOAD), "Ctrl-R", TEXT(T_HK_RELOAD), MENU_FUNC menu_reload, (void *)0, 0, 0,
 };
 
diff -urN mikulas1/session.c mikulas2/session.c
--- mikulas1/session.c	Mon Nov 13 08:58:12 2000
+++ mikulas2/session.c	Mon Nov 13 09:51:29 2000
@@ -1,5 +1,7 @@
 #include "links.h"
 
+int keep_unhistory = 0;
+
 struct list_head downloads = {&downloads, &downloads};
 
 int are_there_downloads()
@@ -276,7 +278,8 @@
 	loc = ses->history.next;
 	if (ses->search_word) mem_free(ses->search_word), ses->search_word = NULL;
 	if ((void *)loc == &ses->history) return;
-	destroy_location(loc);
+    	del_from_list(loc);
+	add_to_list(ses->unhistory, loc);	
 	loc = ses->history.next;
 	if ((void *)loc == &ses->history) return;
 	if (!strcmp(loc->vs.url, ses->loading_url)) return;
@@ -284,6 +287,17 @@
 	ses_forward(ses);
 }
 
+void ses_unback(struct session *ses)
+{
+	struct location *loc;
+	free_files(ses); 
+	loc = ses->unhistory.next;
+	if (ses->search_word) mem_free(ses->search_word), ses->search_word = NULL;
+	if ((void *)loc == &ses->unhistory) return;
+	del_from_list(loc);
+	add_to_list(ses->history, loc);
+}
+
 void end_load(struct status *, struct session *);
 void doc_end_load(struct status *, struct session *);
 void file_end_load(struct status *, struct file_to_load *);
@@ -921,7 +935,7 @@
 			return 2;
 		}
 		if (gp) mem_free(gp);
-		if (w == WTD_BACK) {
+		if (w == WTD_BACK || w == WTD_UNBACK) {
 			ses_goto(ses, u, NULL, PRI_MAIN, NC_CACHE, WTD_RELOAD, NULL, end_load, 1);
 			return 2;
 		}
@@ -941,6 +955,7 @@
 	}
 	if (ses->wtd == WTD_IMGMAP) ses_imgmap(ses);
 	if (ses->wtd == WTD_BACK) ses_back(ses);
+	if (ses->wtd == WTD_UNBACK) ses_unback(ses);
 	if (ses->wtd == WTD_RELOAD) ses_back(ses), ses_forward(ses);
 	if ((*stat)->state >= 0) change_connection(&ses->loading, *stat = &cur_loc(ses)->stat, PRI_MAIN);
 	else cur_loc(ses)->stat.state = ses->loading.state;
@@ -1164,6 +1179,7 @@
 	if ((ses = mem_alloc(sizeof(struct session)))) {
 		memset(ses, 0, sizeof(struct session));
 		init_list(ses->history);
+	    	init_list(ses->unhistory);
 		init_list(ses->scrn_frames);
 		init_list(ses->more_files);
 		ses->term = term;
@@ -1316,18 +1332,8 @@
 	if (ses->screen) detach_formatted(ses->screen), mem_free(ses->screen);
 	foreach(fdc, ses->scrn_frames) detach_formatted(fdc);
 	free_list(ses->scrn_frames);
-	while ((void *)(l = ses->history.next) != &ses->history) {
-		struct frame *frm;
-		while ((void *)(frm = l->frames.next) != &l->frames) {
-			destroy_vs(&frm->vs);
-			mem_free(frm->name);
-			del_from_list(frm);
-			mem_free(frm);
-		}
-		destroy_vs(&l->vs);
-		del_from_list(l);
-		mem_free(l);
-	}
+	foreach(l, ses->history) destroy_location(l);
+	foreach(l, ses->unhistory) destroy_location(l);
 	if (ses->loading_url) mem_free(ses->loading_url);
 	if (ses->display_timer != -1) kill_timer(ses->display_timer);
 	if (ses->goto_position) mem_free(ses->goto_position);
@@ -1412,6 +1418,18 @@
 	ses_goto(ses, url, NULL, PRI_MAIN, NC_ALWAYS_CACHE, WTD_BACK, NULL, end_load, 0);
 }
 
+void go_unback(struct session *ses)
+{
+	unsigned char *url;
+	ses->reloadlevel = NC_CACHE;
+	if (ses->unhistory.next == &ses->unhistory)
+		return;
+	abort_loading(ses);
+	if (!(url = stracpy(((struct location *)ses->unhistory.next)->vs.url)))
+		return;
+	ses_goto(ses, url, NULL, PRI_MAIN, NC_ALWAYS_CACHE, WTD_UNBACK, NULL, end_load, 1);
+}
+
 void goto_url_w(struct session *ses, unsigned char *url, unsigned char *target, int wtd)
 {
 	unsigned char *u;
@@ -1440,6 +1458,11 @@
 	abort_loading(ses);
 	ses_goto(ses, u, target, PRI_MAIN, NC_CACHE, wtd, pos, end_load, 0);
 	/*abort_loading(ses);*/
+
+    	if (!keep_unhistory) {
+		struct location *l;
+		foreach(l, ses->unhistory) destroy_location(l);
+	}
 }
 
 void goto_url_f(struct session *ses, unsigned char *url, unsigned char *target)
diff -urN mikulas1/view.c mikulas2/view.c
--- mikulas1/view.c	Mon Nov 13 09:24:27 2000
+++ mikulas2/view.c	Mon Nov 13 09:51:29 2000
@@ -1398,6 +1398,11 @@
 	go_back(ses);
 }
 
+void unback(struct session *ses, struct f_data_c *f, int a)
+{
+	go_unback(ses);
+}
+
 void selected_item(struct terminal *term, void *pitem, struct session *ses)
 {
 	int item = (int)pitem;
@@ -1966,6 +1971,9 @@
 				goto x;
 			case ACT_BACK:
 				back(ses, NULL, 0);
+				goto x;
+			case ACT_UNBACK:
+				unback(ses, NULL, 0);
 				goto x;
 			case ACT_RELOAD:
 				reload(ses, -1);
