1 /*								    HTHist.c
2 **	NAVIGATION MANAGER
3 **
4 **	(c) COPYRIGHT MIT 1995.
5 **	Please first read the full copyright statement in the file COPYRIGH.
6 **	@(#) $Id$
7 **
8 **	The history manager for the Library. This module is not called any
9 **	where in the Library so if the application does not call it, it is
10 **	not linked in at all.
11 */
12 
13 /* Library include files */
14 #include "wwwsys.h"
15 #include "HTUtils.h"
16 #include "HTAnchor.h"
17 #include "HTHist.h"					 /* Implemented here */
18 
19 struct _HTHistory {
20     HTList *	alist;					  /* List of anchors */
21     int		pos;	       /* Current position in list. 1 is home anchor */
22 };
23 
24 /* ------------------------------------------------------------------------- */
25 
26 /*	Create a new History List
27 **	-------------------------
28 **      Creates a new history list and returns a handle to it. There can be
29 **	multiple history lists - for example one for each open window in
30 **	an application.
31 **	Returns HTHistory object if OK, else NULL
32 */
HTHistory_new(void)33 PUBLIC HTHistory *HTHistory_new (void)
34 {
35     HTHistory *element;
36     if ((element = (HTHistory  *) HT_CALLOC(1, (sizeof(HTHistory)))) == NULL)
37         HT_OUTOFMEM("HTHistory_new");
38     element->alist = HTList_new();
39     return element;
40 }
41 
42 /*	Delete a History list
43 **	---------------------
44 **      Deletes the history list.
45 **	Returns YES if OK, else NO
46 */
HTHistory_delete(HTHistory * hist)47 PUBLIC BOOL HTHistory_delete (HTHistory * hist)
48 {
49     if (hist) {
50 	HTList_delete(hist->alist);
51 	HT_FREE(hist);
52 	return YES;
53     }
54     return NO;
55 }
56 
57 /*	Record an entry in a list
58 **	-------------------------
59 **      Registers the object in the linear list. The first entry is the
60 **	home page. No check is done for duplicates.
61 **	Returns YES if ok, else NO
62 */
HTHistory_record(HTHistory * hist,HTAnchor * cur)63 PUBLIC BOOL HTHistory_record (HTHistory * hist, HTAnchor * cur)
64 {
65     return (hist && cur && HTList_addObject(hist->alist, cur) && hist->pos++);
66 }
67 
68 /*	Replace list with new element
69 **	-----------------------------
70 **      Inserts the new element at the current position and removes all any
71 **	old list from current position. For example if c is cur pos
72 **		before: a b c d e
73 **		after : a b f
74 **	Returns YES if ok, else NO
75 */
HTHistory_replace(HTHistory * hist,HTAnchor * cur)76 PUBLIC BOOL HTHistory_replace (HTHistory * hist, HTAnchor * cur)
77 {
78     if (hist && cur) {
79 	HTHistory_removeFrom(hist, hist->pos);
80 	HTHistory_record(hist, cur);
81     }
82     return NO;
83 }
84 
85 /*	Delete last entry in a list
86 **	---------------------------
87 **      Deletes the last object from the list
88 **	Returns YES if OK, else NO
89 */
HTHistory_removeLast(HTHistory * hist)90 PUBLIC BOOL HTHistory_removeLast (HTHistory * hist)
91 {
92     return (hist && HTList_removeLastObject(hist->alist) && hist->pos--);
93 }
94 
95 /*	Remove the History list from position
96 **	------------------------------------
97 **      Deletes the history list FROM the entry at position 'cur' (excluded).
98 **	Home page has position 1.
99 **	Returns YES if OK, else NO
100 */
HTHistory_removeFrom(HTHistory * hist,int pos)101 PUBLIC BOOL HTHistory_removeFrom  (HTHistory * hist, int pos)
102 {
103     if (hist && pos>=0) {
104 	int cnt = HTList_count(hist->alist) - pos;
105 	while (cnt-->0 && HTList_removeLastObject(hist->alist));
106 	if (hist->pos > pos)
107 	    hist->pos = pos;
108 	return YES;
109     }
110     return NO;
111 }
112 
113 /*	Number of elements stored
114 **     	-------------------------
115 **	Returns the size of the history list or -1 if none.
116 */
HTHistory_count(HTHistory * hist)117 PUBLIC int HTHistory_count (HTHistory * hist)
118 {
119     return (hist ? HTList_count(hist->alist) : -1);
120 }
121 
122 /*	Current Location
123 **     	----------------
124 **	Returns the current position or -1
125 */
HTHistory_position(HTHistory * hist)126 PUBLIC int HTHistory_position (HTHistory * hist)
127 {
128     return (hist ? hist->pos : -1);
129 }
130 
131 /* ------------------------------------------------------------------------- */
132 /* 				    NAVIGATION				     */
133 /* ------------------------------------------------------------------------- */
134 
135 /*	Find and re-register visited anchor
136 **     	-----------------------------------
137 **	Finds already registered anchor at given position and registers it
138 **	again EXCEPT if last entry. This allows for `circular' history lists
139 **	with duplicate entries. Position 1 is the home anchor.
140 */
HTHistory_recall(HTHistory * hist,int pos)141 PUBLIC HTAnchor * HTHistory_recall (HTHistory * hist, int pos)
142 {
143     HTAnchor *cur = NULL;
144     if (hist && pos > 0) {
145 	int len = HTList_count(hist->alist);
146 	if ((cur = (HTAnchor *) HTList_objectAt(hist->alist, len-pos))) {
147 	    if (cur != HTList_lastObject (hist->alist)) {
148 		HTHistory_record(hist, cur);
149 	    } else
150 		hist->pos = pos;
151 	}
152     }
153     return cur;
154 }
155 
156 /*	Find Entry at position
157 **	----------------------
158 **	Entry with the given index in the list (1 is the home page). Like
159 **	HTHistory_recall but without re-registration. Current position is
160 **	updated.
161 */
HTHistory_find(HTHistory * hist,int pos)162 PUBLIC HTAnchor * HTHistory_find (HTHistory * hist, int pos)
163 {
164     HTAnchor *cur = NULL;
165     if (hist && pos > 0) {
166 	if ((cur = (HTAnchor *)
167 	     (HTList_objectAt(hist->alist, HTList_count(hist->alist)-pos))))
168 	    hist->pos = pos;
169     }
170     return cur;
171 }
172 
173 /*	List Entry at position
174 **	----------------------
175 **	Entry with the given index in the list (1 is the home page). Like
176 **	HTHistory_find but current position is NOT updated.
177 */
HTHistory_list(HTHistory * hist,int pos)178 PUBLIC HTAnchor * HTHistory_list (HTHistory * hist, int pos)
179 {
180     return (hist ? (HTAnchor *)
181 	    (HTList_objectAt(hist->alist, HTList_count(hist->alist)-pos)) :
182 	    NULL);
183 }
184 
185 /*	Can we back in history
186 **	----------------------
187 **	Returns YES if the current anchor is not the first entry (home page)
188 */
HTHistory_canBacktrack(HTHistory * hist)189 PUBLIC BOOL HTHistory_canBacktrack (HTHistory * hist)
190 {
191     return ((hist && hist->pos > 1) ? YES : NO);
192 }
193 
194 /*
195 **	Backtrack with deletion
196 **	-----------------------
197 **	Returns the previous object and erases the last object. This does not
198 **	allow for 'forward' as we are always at the end of the list. If no
199 **	previous object exists, NULL is returned so that the application knows
200 **	that no previous object was found. See also HTHistory_back().
201 */
HTHistory_backtrack(HTHistory * hist)202 PUBLIC HTAnchor * HTHistory_backtrack (HTHistory * hist)
203 {
204     if (HTHistory_canBacktrack(hist)) {
205 	HTHistory_removeLast(hist);
206 	return (HTAnchor *) HTList_lastObject(hist->alist);
207     }
208     return NULL;
209 }
210 
211 /*
212 **	Backtrack without deletion
213 **	--------------------------
214 **	Returns the previos object but does not erase the last object. This
215 **	does not allow for 'forward'. If no previous object exists,  NULL is
216 **	returned so that the application knows that no previous object was
217 **	found. See also HTHistory_backtrack()
218 */
HTHistory_back(HTHistory * hist)219 PUBLIC HTAnchor * HTHistory_back (HTHistory * hist)
220 {
221     if (HTHistory_canBacktrack(hist)) {
222 	int pos = HTList_count(hist->alist) - (--hist->pos);
223 	return ((HTAnchor *) HTList_objectAt(hist->alist, pos));
224     }
225     return NULL;
226 }
227 
228 /*	Can we go forward
229 **	-----------------
230 **	Returns YES if the current anchor is not the last entry
231 */
HTHistory_canForward(HTHistory * hist)232 PUBLIC BOOL HTHistory_canForward (HTHistory * hist)
233 {
234     return ((hist && hist->pos < HTList_count(hist->alist)) ? YES : NO);
235 }
236 
237 /*
238 **	Forward
239 **	-------
240 **	Return the next object in the list or NULL if none
241 */
HTHistory_forward(HTHistory * hist)242 PUBLIC HTAnchor * HTHistory_forward (HTHistory * hist)
243 {
244     if (HTHistory_canForward(hist)) {
245 	int pos = HTList_count(hist->alist) - (++hist->pos);
246 	return ((HTAnchor *) HTList_objectAt(hist->alist, pos));
247     }
248     return NULL;
249 }
250