tocutil.c revision c9e2be55
1c9e2be55Smrg/*
2c9e2be55Smrg * $XConsortium: tocutil.c,v 2.60 95/01/09 16:52:53 swick Exp $
3c9e2be55Smrg * $XFree86: xc/programs/xmh/tocutil.c,v 3.3 2001/10/28 03:34:40 tsi Exp $
4c9e2be55Smrg *
5c9e2be55Smrg *
6c9e2be55Smrg *			COPYRIGHT 1987, 1989
7c9e2be55Smrg *		   DIGITAL EQUIPMENT CORPORATION
8c9e2be55Smrg *		       MAYNARD, MASSACHUSETTS
9c9e2be55Smrg *			ALL RIGHTS RESERVED.
10c9e2be55Smrg *
11c9e2be55Smrg * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
12c9e2be55Smrg * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
13c9e2be55Smrg * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
14c9e2be55Smrg * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
15c9e2be55Smrg *
16c9e2be55Smrg * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT
17c9e2be55Smrg * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN
18c9e2be55Smrg * ADDITION TO THAT SET FORTH ABOVE.
19c9e2be55Smrg *
20c9e2be55Smrg * Permission to use, copy, modify, and distribute this software and its
21c9e2be55Smrg * documentation for any purpose and without fee is hereby granted, provided
22c9e2be55Smrg * that the above copyright notice appear in all copies and that both that
23c9e2be55Smrg * copyright notice and this permission notice appear in supporting
24c9e2be55Smrg * documentation, and that the name of Digital Equipment Corporation not be
25c9e2be55Smrg * used in advertising or publicity pertaining to distribution of the software
26c9e2be55Smrg * without specific, written prior permission.
27c9e2be55Smrg */
28c9e2be55Smrg
29c9e2be55Smrg/* tocutil.c -- internal routines for toc stuff. */
30c9e2be55Smrg
31c9e2be55Smrg#include "xmh.h"
32c9e2be55Smrg#include "toc.h"
33c9e2be55Smrg#include "tocutil.h"
34c9e2be55Smrg#include "tocintrnl.h"
35c9e2be55Smrg
36c9e2be55Smrg#ifdef X_NOT_POSIX
37c9e2be55Smrgextern long lseek();
38c9e2be55Smrg#endif
39c9e2be55Smrg
40c9e2be55SmrgToc TUMalloc(void)
41c9e2be55Smrg{
42c9e2be55Smrg    Toc toc;
43c9e2be55Smrg    toc = XtNew(TocRec);
44c9e2be55Smrg    bzero((char *)toc, (int) sizeof(TocRec));
45c9e2be55Smrg    toc->msgs = (Msg *) NULL;
46c9e2be55Smrg    toc->seqlist = (Sequence *) NULL;
47c9e2be55Smrg    toc->validity = unknown;
48c9e2be55Smrg    return toc;
49c9e2be55Smrg}
50c9e2be55Smrg
51c9e2be55Smrg
52c9e2be55Smrg/* Returns TRUE if the scan file for the given toc is out of date. */
53c9e2be55Smrg
54c9e2be55Smrgint TUScanFileOutOfDate(Toc toc)
55c9e2be55Smrg{
56c9e2be55Smrg    return LastModifyDate(toc->path) > toc->lastreaddate;
57c9e2be55Smrg}
58c9e2be55Smrg
59c9e2be55Smrg
60c9e2be55Smrg/* Make sure the sequence menu entries correspond exactly to the sequences
61c9e2be55Smrg * for this toc.
62c9e2be55Smrg */
63c9e2be55Smrg
64c9e2be55Smrgvoid TUCheckSequenceMenu(Toc toc)
65c9e2be55Smrg{
66c9e2be55Smrg    Scrn	scrn;
67c9e2be55Smrg    register int i, n;
68c9e2be55Smrg    Arg		query_args[2];
69c9e2be55Smrg    char 	*name;
70c9e2be55Smrg    Cardinal	j;
71c9e2be55Smrg    int		numChildren;
72c9e2be55Smrg    Widget	menu, item;
73c9e2be55Smrg    Button	button;
74c9e2be55Smrg    WidgetList	children;
75c9e2be55Smrg
76c9e2be55Smrg    static XtCallbackRec callbacks[] = {
77c9e2be55Smrg	{ DoSelectSequence,		(XtPointer) NULL},
78c9e2be55Smrg	{ (XtCallbackProc) NULL,	(XtPointer) NULL},
79c9e2be55Smrg    };
80c9e2be55Smrg    static Arg  args[] = {
81c9e2be55Smrg	{ XtNcallback,			(XtArgVal) callbacks},
82c9e2be55Smrg	{ XtNleftMargin, 		(XtArgVal) 18},
83c9e2be55Smrg    };
84c9e2be55Smrg
85c9e2be55Smrg    for (j=0; j < toc->num_scrns; j++) {
86c9e2be55Smrg	scrn = toc->scrn[j];
87c9e2be55Smrg
88c9e2be55Smrg	/* Find the sequence menu and the number of entries in it. */
89c9e2be55Smrg
90c9e2be55Smrg	name = MenuBoxButtons[XMH_SEQUENCE].button_name;
91c9e2be55Smrg	button = BBoxFindButtonNamed(scrn->mainbuttons, name);
92c9e2be55Smrg	menu = BBoxMenuOfButton(button);
93c9e2be55Smrg	XtSetArg(query_args[0], XtNnumChildren, &numChildren);
94c9e2be55Smrg	XtSetArg(query_args[1], XtNchildren, &children);
95c9e2be55Smrg	XtGetValues(menu, query_args, (Cardinal) 2);
96c9e2be55Smrg	n = MenuBoxButtons[XMH_SEQUENCE].num_entries;
97c9e2be55Smrg	if (strcmp(XtName(children[0]), "menuLabel") == 0)
98c9e2be55Smrg	    n++;
99c9e2be55Smrg
100c9e2be55Smrg	/* Erase the current check mark. */
101c9e2be55Smrg
102c9e2be55Smrg	for (i=(n-1); i < numChildren; i++)
103c9e2be55Smrg	    ToggleMenuItem(children[i], False);
104c9e2be55Smrg
105c9e2be55Smrg	/* Delete any entries which should be deleted. */
106c9e2be55Smrg
107c9e2be55Smrg	for (i=n; i < numChildren; i++)
108c9e2be55Smrg	    if (! TocGetSeqNamed(toc, XtName(children[i])))
109c9e2be55Smrg		XtDestroyWidget(children[i]);
110c9e2be55Smrg
111c9e2be55Smrg	/* Create any entries which should be created. */
112c9e2be55Smrg
113c9e2be55Smrg	callbacks[0].closure = (XtPointer) scrn;
114c9e2be55Smrg	for (i=1; i < toc->numsequences; i++)
115c9e2be55Smrg	    if (! XtNameToWidget(menu, toc->seqlist[i]->name))
116c9e2be55Smrg		XtCreateManagedWidget(toc->seqlist[i]->name, smeBSBObjectClass,
117c9e2be55Smrg				      menu, args, XtNumber(args));
118c9e2be55Smrg
119c9e2be55Smrg	/* Set the check mark. */
120c9e2be55Smrg
121c9e2be55Smrg	name = toc->viewedseq->name;
122c9e2be55Smrg	if ((item = XtNameToWidget(menu, name)) != NULL)
123c9e2be55Smrg	    ToggleMenuItem(item, True);
124c9e2be55Smrg    }
125c9e2be55Smrg    TocSetSelectedSequence(toc, toc->viewedseq);
126c9e2be55Smrg}
127c9e2be55Smrg
128c9e2be55Smrg
129c9e2be55Smrgvoid TUScanFileForToc(Toc toc)
130c9e2be55Smrg{
131c9e2be55Smrg    Scrn scrn;
132c9e2be55Smrg    char  **argv, str[100];
133c9e2be55Smrg    if (toc) {
134c9e2be55Smrg	TUGetFullFolderInfo(toc);
135c9e2be55Smrg	if (toc->num_scrns) scrn = toc->scrn[0];
136c9e2be55Smrg	else scrn = scrnList[0];
137c9e2be55Smrg
138c9e2be55Smrg	(void) sprintf(str, "Rescanning %s", toc->foldername);
139c9e2be55Smrg	ChangeLabel(scrn->toclabel, str);
140c9e2be55Smrg
141c9e2be55Smrg	argv = MakeArgv(5);
142c9e2be55Smrg	argv[0] = "scan";
143c9e2be55Smrg	argv[1] = TocMakeFolderName(toc);
144c9e2be55Smrg	argv[2] = "-width";
145c9e2be55Smrg	(void) sprintf(str, "%d", app_resources.toc_width);
146c9e2be55Smrg	argv[3] = str;
147c9e2be55Smrg	argv[4] = "-noheader";
148c9e2be55Smrg	DoCommand(argv, (char *) NULL, toc->scanfile);
149c9e2be55Smrg	XtFree(argv[1]);
150c9e2be55Smrg	XtFree((char *) argv);
151c9e2be55Smrg
152c9e2be55Smrg	toc->needslabelupdate = True;
153c9e2be55Smrg	toc->validity = valid;
154c9e2be55Smrg	toc->curmsg = NULL;	/* Get cur msg somehow! %%% */
155c9e2be55Smrg    }
156c9e2be55Smrg}
157c9e2be55Smrg
158c9e2be55Smrg
159c9e2be55Smrg
160c9e2be55Smrgint TUGetMsgPosition(Toc toc, Msg msg)
161c9e2be55Smrg{
162c9e2be55Smrg    int msgid, h = 0, l, m;
163c9e2be55Smrg    char str[100];
164c9e2be55Smrg    static Boolean ordered = True;
165c9e2be55Smrg    msgid = msg->msgid;
166c9e2be55Smrg    if (ordered) {
167c9e2be55Smrg	l = 0;
168c9e2be55Smrg	h = toc->nummsgs - 1;
169c9e2be55Smrg	while (l < h - 1) {
170c9e2be55Smrg	    m = (l + h) / 2;
171c9e2be55Smrg	    if (toc->msgs[m]->msgid > msgid)
172c9e2be55Smrg		h = m;
173c9e2be55Smrg	    else
174c9e2be55Smrg		l = m;
175c9e2be55Smrg	}
176c9e2be55Smrg	if (toc->msgs[l] == msg) return l;
177c9e2be55Smrg	if (toc->msgs[h] == msg) return h;
178c9e2be55Smrg    }
179c9e2be55Smrg    ordered = False;
180c9e2be55Smrg    for (l = 0; l < toc->nummsgs; l++) {
181c9e2be55Smrg	if (msgid == toc->msgs[l]->msgid) return l;
182c9e2be55Smrg    }
183c9e2be55Smrg    (void) sprintf(str,
184c9e2be55Smrg		   "TUGetMsgPosition search failed! hi=%d, lo=%d, msgid=%d",
185c9e2be55Smrg		   h, l, msgid);
186c9e2be55Smrg    Punt(str);
187c9e2be55Smrg    return 0; /* Keep lint happy. */
188c9e2be55Smrg}
189c9e2be55Smrg
190c9e2be55Smrg
191c9e2be55Smrgvoid TUResetTocLabel(Scrn scrn)
192c9e2be55Smrg{
193c9e2be55Smrg    char str[500];
194c9e2be55Smrg    Toc toc;
195c9e2be55Smrg    if (scrn) {
196c9e2be55Smrg	toc = scrn->toc;
197c9e2be55Smrg	if (toc == NULL)
198c9e2be55Smrg	    (void) strcpy(str, " ");
199c9e2be55Smrg	else {
200c9e2be55Smrg	    if (toc->stopupdate) {
201c9e2be55Smrg		toc->needslabelupdate = TRUE;
202c9e2be55Smrg		return;
203c9e2be55Smrg	    }
204c9e2be55Smrg	    (void) sprintf(str, "%s:%s", toc->foldername,
205c9e2be55Smrg			   toc->viewedseq->name);
206c9e2be55Smrg	    toc->needslabelupdate = FALSE;
207c9e2be55Smrg	}
208c9e2be55Smrg	ChangeLabel((Widget) scrn->toclabel, str);
209c9e2be55Smrg    }
210c9e2be55Smrg}
211c9e2be55Smrg
212c9e2be55Smrg
213c9e2be55Smrg/* A major toc change has occured; redisplay it.  (This also should work even
214c9e2be55Smrg   if we now have a new source to display stuff from.) */
215c9e2be55Smrg
216c9e2be55Smrgvoid TURedisplayToc(Scrn scrn)
217c9e2be55Smrg{
218c9e2be55Smrg    Toc toc;
219c9e2be55Smrg    Widget source;
220c9e2be55Smrg    if (scrn != NULL && scrn->tocwidget != NULL) {
221c9e2be55Smrg	toc = scrn->toc;
222c9e2be55Smrg 	if (toc) {
223c9e2be55Smrg	    if (toc->stopupdate) {
224c9e2be55Smrg		toc->needsrepaint = TRUE;
225c9e2be55Smrg		return;
226c9e2be55Smrg	    }
227c9e2be55Smrg	    XawTextDisableRedisplay(scrn->tocwidget);
228c9e2be55Smrg	    source = XawTextGetSource(scrn->tocwidget);
229c9e2be55Smrg	    if (toc->force_reset || source != toc->source) {
230c9e2be55Smrg		XawTextSetSource(scrn->tocwidget, toc->source,
231c9e2be55Smrg				 (XawTextPosition) 0);
232c9e2be55Smrg		toc->force_reset = False; /* %%% temporary */
233c9e2be55Smrg	    }
234c9e2be55Smrg	    TocSetCurMsg(toc, TocGetCurMsg(toc));
235c9e2be55Smrg	    XawTextEnableRedisplay(scrn->tocwidget);
236c9e2be55Smrg	    TUCheckSequenceMenu(toc);
237c9e2be55Smrg	    toc->needsrepaint = FALSE;
238c9e2be55Smrg	} else {
239c9e2be55Smrg	    XawTextSetSource(scrn->tocwidget, PNullSource, (XawTextPosition) 0);
240c9e2be55Smrg	}
241c9e2be55Smrg    }
242c9e2be55Smrg}
243c9e2be55Smrg
244c9e2be55Smrg
245c9e2be55Smrgvoid TULoadSeqLists(Toc toc)
246c9e2be55Smrg{
247c9e2be55Smrg    Sequence seq;
248c9e2be55Smrg    FILEPTR fid;
249c9e2be55Smrg    char    str[500], *ptr, *ptr2, viewed[500], selected[500];
250c9e2be55Smrg    int     i;
251c9e2be55Smrg    if (toc->viewedseq) (void) strcpy(viewed, toc->viewedseq->name);
252c9e2be55Smrg    else *viewed = 0;
253c9e2be55Smrg    if (toc->selectseq) (void) strcpy(selected, toc->selectseq->name);
254c9e2be55Smrg    else *selected = 0;
255c9e2be55Smrg    for (i = 0; i < toc->numsequences; i++) {
256c9e2be55Smrg	seq = toc->seqlist[i];
257c9e2be55Smrg	XtFree((char *) seq->name);
258c9e2be55Smrg	if (seq->mlist) FreeMsgList(seq->mlist);
259c9e2be55Smrg	XtFree((char *)seq);
260c9e2be55Smrg    }
261c9e2be55Smrg    toc->numsequences = 1;
262c9e2be55Smrg    toc->seqlist = (Sequence *) XtRealloc((char *) toc->seqlist,
263c9e2be55Smrg					  (Cardinal) sizeof(Sequence));
264c9e2be55Smrg    seq = toc->seqlist[0] = XtNew(SequenceRec);
265c9e2be55Smrg    seq->name = XtNewString("all");
266c9e2be55Smrg    seq->mlist = NULL;
267c9e2be55Smrg    toc->viewedseq = seq;
268c9e2be55Smrg    toc->selectseq = seq;
269c9e2be55Smrg    (void) sprintf(str, "%s/.mh_sequences", toc->path);
270c9e2be55Smrg    fid = myfopen(str, "r");
271c9e2be55Smrg    if (fid) {
272c9e2be55Smrg	while ((ptr = ReadLine(fid))) {
273c9e2be55Smrg	    ptr2 = strchr(ptr, ':');
274c9e2be55Smrg	    if (ptr2) {
275c9e2be55Smrg		*ptr2 = 0;
276c9e2be55Smrg		if (strcmp(ptr, "all") != 0 &&
277c9e2be55Smrg		    strcmp(ptr, "cur") != 0 &&
278c9e2be55Smrg		    strcmp(ptr, "unseen") != 0) {
279c9e2be55Smrg		    toc->numsequences++;
280c9e2be55Smrg		    toc->seqlist = (Sequence *)
281c9e2be55Smrg			XtRealloc((char *) toc->seqlist, (Cardinal)
282c9e2be55Smrg				  toc->numsequences * sizeof(Sequence));
283c9e2be55Smrg		    seq = toc->seqlist[toc->numsequences - 1] =
284c9e2be55Smrg			XtNew(SequenceRec);
285c9e2be55Smrg		    seq->name = XtNewString(ptr);
286c9e2be55Smrg		    seq->mlist = StringToMsgList(toc, ptr2 + 1);
287c9e2be55Smrg		    if (strcmp(seq->name, viewed) == 0) {
288c9e2be55Smrg			toc->viewedseq = seq;
289c9e2be55Smrg			*viewed = 0;
290c9e2be55Smrg		    }
291c9e2be55Smrg		    if (strcmp(seq->name, selected) == 0) {
292c9e2be55Smrg			toc->selectseq = seq;
293c9e2be55Smrg			*selected = 0;
294c9e2be55Smrg		    }
295c9e2be55Smrg		}
296c9e2be55Smrg	    }
297c9e2be55Smrg	}
298c9e2be55Smrg	(void) myfclose(fid);
299c9e2be55Smrg    }
300c9e2be55Smrg}
301c9e2be55Smrg
302c9e2be55Smrg
303c9e2be55Smrg
304c9e2be55Smrg/* Refigure what messages are visible. */
305c9e2be55Smrg
306c9e2be55Smrgvoid TURefigureWhatsVisible(Toc toc)
307c9e2be55Smrg{
308c9e2be55Smrg    MsgList mlist;
309c9e2be55Smrg    Msg msg, oldcurmsg;
310c9e2be55Smrg    int i;
311c9e2be55Smrg    int	w, changed, newval, msgid;
312c9e2be55Smrg    Sequence seq = toc->viewedseq;
313c9e2be55Smrg    mlist = seq->mlist;
314c9e2be55Smrg    oldcurmsg = toc->curmsg;
315c9e2be55Smrg    TocSetCurMsg(toc, (Msg)NULL);
316c9e2be55Smrg    w = 0;
317c9e2be55Smrg    changed = FALSE;
318c9e2be55Smrg
319c9e2be55Smrg    for (i = 0; i < toc->nummsgs; i++) {
320c9e2be55Smrg	msg = toc->msgs[i];
321c9e2be55Smrg	msgid = msg->msgid;
322c9e2be55Smrg	while (mlist && mlist->msglist[w] && mlist->msglist[w]->msgid < msgid)
323c9e2be55Smrg	    w++;
324c9e2be55Smrg	newval = (!mlist
325c9e2be55Smrg		  || (mlist->msglist[w] && mlist->msglist[w]->msgid == msgid));
326c9e2be55Smrg	if (newval != msg->visible) {
327c9e2be55Smrg	    changed = TRUE;
328c9e2be55Smrg	    msg->visible = newval;
329c9e2be55Smrg	}
330c9e2be55Smrg    }
331c9e2be55Smrg    if (changed) {
332c9e2be55Smrg	TURefigureTocPositions(toc);
333c9e2be55Smrg	if (oldcurmsg) {
334c9e2be55Smrg	    if (!oldcurmsg->visible) {
335c9e2be55Smrg		toc->curmsg = TocMsgAfter(toc, oldcurmsg);
336c9e2be55Smrg		if (toc->curmsg == NULL)
337c9e2be55Smrg		    toc->curmsg = TocMsgBefore(toc, oldcurmsg);
338c9e2be55Smrg	    } else toc->curmsg = oldcurmsg;
339c9e2be55Smrg	}
340c9e2be55Smrg	for (i=0 ; i<toc->num_scrns ; i++)
341c9e2be55Smrg	    TURedisplayToc(toc->scrn[i]);
342c9e2be55Smrg    } else TocSetCurMsg(toc, oldcurmsg);
343c9e2be55Smrg    for (i=0 ; i<toc->num_scrns ; i++)
344c9e2be55Smrg	TUResetTocLabel(toc->scrn[i]);
345c9e2be55Smrg}
346c9e2be55Smrg
347c9e2be55Smrg
348c9e2be55Smrg/* (Re)load the toc from the scanfile.  If reloading, this makes efforts to
349c9e2be55Smrg   keep the fates of msgs, and to keep msgs that are being edited.  Note that
350c9e2be55Smrg   this routine must know of all places that msg ptrs are stored; it expects
351c9e2be55Smrg   them to be kept only in tocs, in scrns, and in msg sequences. */
352c9e2be55Smrg
353c9e2be55Smrg#define SeemsIdentical(msg1, msg2) ((msg1)->msgid == (msg2)->msgid &&	      \
354c9e2be55Smrg				    ((msg1)->temporary || (msg2)->temporary ||\
355c9e2be55Smrg				     strcmp((msg1)->buf, (msg2)->buf) == 0))
356c9e2be55Smrg
357c9e2be55Smrgvoid TULoadTocFile(Toc toc)
358c9e2be55Smrg{
359c9e2be55Smrg    int maxmsgs, l, orignummsgs, i, j, origcurmsgid;
360c9e2be55Smrg    FILEPTR fid;
361c9e2be55Smrg    XawTextPosition position;
362c9e2be55Smrg    char *ptr;
363c9e2be55Smrg    Msg msg, curmsg;
364c9e2be55Smrg    Msg *origmsgs;
365c9e2be55Smrg    int bufsiz = app_resources.toc_width + 1;
366c9e2be55Smrg    static char *buf;
367c9e2be55Smrg
368c9e2be55Smrg    if (!buf)
369c9e2be55Smrg	buf = XtMalloc((Cardinal) bufsiz);
370c9e2be55Smrg    TocStopUpdate(toc);
371c9e2be55Smrg    toc->lastreaddate = LastModifyDate(toc->scanfile);
372c9e2be55Smrg    if (toc->curmsg) {
373c9e2be55Smrg	origcurmsgid = toc->curmsg->msgid;
374c9e2be55Smrg	TocSetCurMsg(toc, (Msg)NULL);
375c9e2be55Smrg    } else origcurmsgid = 0;  /* The "default" current msg; 0 means none */
376c9e2be55Smrg    fid = FOpenAndCheck(toc->scanfile, "r");
377c9e2be55Smrg    maxmsgs = orignummsgs = toc->nummsgs;
378c9e2be55Smrg    if (maxmsgs == 0) maxmsgs = 100;
379c9e2be55Smrg    toc->nummsgs = 0;
380c9e2be55Smrg    origmsgs = toc->msgs;
381c9e2be55Smrg    toc->msgs = (Msg *) XtMalloc((Cardinal) maxmsgs * sizeof(Msg));
382c9e2be55Smrg    position = 0;
383c9e2be55Smrg    i = 0;
384c9e2be55Smrg    curmsg = NULL;
385c9e2be55Smrg    while ((ptr = fgets(buf, bufsiz, fid))) {
386c9e2be55Smrg	toc->msgs[toc->nummsgs++] = msg = XtNew(MsgRec);
387c9e2be55Smrg	bzero((char *) msg, sizeof(MsgRec));
388c9e2be55Smrg	msg->toc = toc;
389c9e2be55Smrg	msg->position = position;
390c9e2be55Smrg	msg->length = l = strlen(ptr);
391c9e2be55Smrg	position += l;
392c9e2be55Smrg	if (l == app_resources.toc_width && buf[bufsiz-2] != '\n') {
393c9e2be55Smrg	    buf[bufsiz-2] = '\n';
394c9e2be55Smrg	    msg->buf = strcpy(XtMalloc((Cardinal) ++l), ptr);
395c9e2be55Smrg	    msg->msgid = atoi(ptr);
396c9e2be55Smrg	    do
397c9e2be55Smrg		ptr = fgets(buf, bufsiz, fid);
398c9e2be55Smrg	    while (ptr && (int) strlen(ptr) == app_resources.toc_width
399c9e2be55Smrg		   && buf[bufsiz-2] != '\n');
400c9e2be55Smrg	} else {
401c9e2be55Smrg	    msg->buf = strcpy(XtMalloc((Cardinal) ++l), ptr);
402c9e2be55Smrg	    msg->msgid = atoi(ptr);
403c9e2be55Smrg	}
404c9e2be55Smrg	if (msg->msgid == origcurmsgid)
405c9e2be55Smrg	    curmsg = msg;
406c9e2be55Smrg	msg->buf[MARKPOS] = ' ';
407c9e2be55Smrg	msg->changed = FALSE;
408c9e2be55Smrg	msg->fate = Fignore;
409c9e2be55Smrg	msg->desttoc = NULL;
410c9e2be55Smrg	msg->visible = TRUE;
411c9e2be55Smrg	if (toc->nummsgs >= maxmsgs) {
412c9e2be55Smrg	    maxmsgs += 100;
413c9e2be55Smrg	    toc->msgs = (Msg *) XtRealloc((char *) toc->msgs,
414c9e2be55Smrg					  (Cardinal) maxmsgs * sizeof(Msg));
415c9e2be55Smrg	}
416c9e2be55Smrg	while (i < orignummsgs && origmsgs[i]->msgid < msg->msgid) i++;
417c9e2be55Smrg	if (i < orignummsgs) {
418c9e2be55Smrg	    origmsgs[i]->buf[MARKPOS] = ' ';
419c9e2be55Smrg	    if (SeemsIdentical(origmsgs[i], msg))
420c9e2be55Smrg		MsgSetFate(msg, origmsgs[i]->fate, origmsgs[i]->desttoc);
421c9e2be55Smrg	}
422c9e2be55Smrg    }
423c9e2be55Smrg    toc->length = toc->origlength = toc->lastPos = position;
424c9e2be55Smrg    toc->msgs = (Msg *) XtRealloc((char *) toc->msgs,
425c9e2be55Smrg				  (Cardinal) toc->nummsgs * sizeof(Msg));
426c9e2be55Smrg    (void) myfclose(fid);
427c9e2be55Smrg    if ( (toc->source == NULL) && ( toc->num_scrns > 0 ) ) {
428c9e2be55Smrg        Arg args[1];
429c9e2be55Smrg
430c9e2be55Smrg	XtSetArg(args[0], XtNtoc, toc);
431c9e2be55Smrg	toc->source = XtCreateWidget("tocSource", tocSourceWidgetClass,
432c9e2be55Smrg				     toc->scrn[0]->tocwidget,
433c9e2be55Smrg				     args, (Cardinal) 1);
434c9e2be55Smrg    }
435c9e2be55Smrg    for (i=0 ; i<numScrns ; i++) {
436c9e2be55Smrg	msg = scrnList[i]->msg;
437c9e2be55Smrg	if (msg && msg->toc == toc) {
438c9e2be55Smrg	    for (j=0 ; j<toc->nummsgs ; j++) {
439c9e2be55Smrg		if (SeemsIdentical(toc->msgs[j], msg)) {
440c9e2be55Smrg		    msg->position = toc->msgs[j]->position;
441c9e2be55Smrg		    msg->visible = TRUE;
442c9e2be55Smrg		    ptr = toc->msgs[j]->buf;
443c9e2be55Smrg		    l = toc->msgs[j]->length;
444c9e2be55Smrg		    *(toc->msgs[j]) = *msg;
445c9e2be55Smrg		    toc->msgs[j]->buf = ptr;
446c9e2be55Smrg		    toc->msgs[j]->length = l;
447c9e2be55Smrg		    scrnList[i]->msg = toc->msgs[j];
448c9e2be55Smrg		    break;
449c9e2be55Smrg		}
450c9e2be55Smrg	    }
451c9e2be55Smrg	    if (j >= toc->nummsgs) {
452c9e2be55Smrg		msg->temporary = FALSE;	/* Don't try to auto-delete msg. */
453c9e2be55Smrg		MsgSetScrnForce(msg, (Scrn) NULL);
454c9e2be55Smrg	    }
455c9e2be55Smrg	}
456c9e2be55Smrg    }
457c9e2be55Smrg    for (i=0 ; i<orignummsgs ; i++)
458c9e2be55Smrg	MsgFree(origmsgs[i]);
459c9e2be55Smrg    XtFree((char *)origmsgs);
460c9e2be55Smrg    TocSetCurMsg(toc, curmsg);
461c9e2be55Smrg    TULoadSeqLists(toc);
462c9e2be55Smrg    TocStartUpdate(toc);
463c9e2be55Smrg}
464c9e2be55Smrg
465c9e2be55Smrg
466c9e2be55Smrgvoid TUSaveTocFile(Toc toc)
467c9e2be55Smrg{
468c9e2be55Smrg    Msg msg;
469c9e2be55Smrg    int fid;
470c9e2be55Smrg    int i;
471c9e2be55Smrg    XawTextPosition position;
472c9e2be55Smrg    char c;
473c9e2be55Smrg    if (toc->stopupdate) {
474c9e2be55Smrg	toc->needscachesave = TRUE;
475c9e2be55Smrg	return;
476c9e2be55Smrg    }
477c9e2be55Smrg    fid = -1;
478c9e2be55Smrg    position = 0;
479c9e2be55Smrg    for (i = 0; i < toc->nummsgs; i++) {
480c9e2be55Smrg	msg = toc->msgs[i];
481c9e2be55Smrg	if (fid < 0 && msg->changed) {
482c9e2be55Smrg	    fid = myopen(toc->scanfile, O_RDWR, 0666);
483c9e2be55Smrg	    (void) lseek(fid, (long)position, 0);
484c9e2be55Smrg	}
485c9e2be55Smrg	if (fid >= 0) {
486c9e2be55Smrg	    c = msg->buf[MARKPOS];
487c9e2be55Smrg	    msg->buf[MARKPOS] = ' ';
488c9e2be55Smrg	    (void) write(fid, msg->buf, msg->length);
489c9e2be55Smrg	    msg->buf[MARKPOS] = c;
490c9e2be55Smrg	}
491c9e2be55Smrg	position += msg->length;
492c9e2be55Smrg    }
493c9e2be55Smrg    if (fid < 0 && toc->length != toc->origlength)
494c9e2be55Smrg	fid = myopen(toc->scanfile, O_RDWR, 0666);
495c9e2be55Smrg    if (fid >= 0) {
496c9e2be55Smrg#if defined(SYSV) && (defined(i386) || defined(MOTOROLA))
497c9e2be55Smrg	(void) ftruncate_emu(fid, toc->length, toc->scanfile);
498c9e2be55Smrg#else
499c9e2be55Smrg	(void) ftruncate(fid, toc->length);
500c9e2be55Smrg	myclose(fid);
501c9e2be55Smrg#endif
502c9e2be55Smrg	toc->origlength = toc->length;
503c9e2be55Smrg    }
504c9e2be55Smrg    toc->needscachesave = FALSE;
505c9e2be55Smrg    toc->lastreaddate = LastModifyDate(toc->scanfile);
506c9e2be55Smrg}
507c9e2be55Smrg
508c9e2be55Smrg
509c9e2be55Smrgstatic Boolean UpdateScanFile(
510c9e2be55Smrg  XtPointer client_data)	/* Toc */
511c9e2be55Smrg{
512c9e2be55Smrg    Toc toc = (Toc)client_data;
513c9e2be55Smrg    int i;
514c9e2be55Smrg
515c9e2be55Smrg    if (app_resources.block_events_on_busy) ShowBusyCursor();
516c9e2be55Smrg
517c9e2be55Smrg    TUScanFileForToc(toc);
518c9e2be55Smrg    TULoadTocFile(toc);
519c9e2be55Smrg
520c9e2be55Smrg    for (i=0 ; i<toc->num_scrns ; i++)
521c9e2be55Smrg	TURedisplayToc(toc->scrn[i]);
522c9e2be55Smrg
523c9e2be55Smrg    if (app_resources.block_events_on_busy) UnshowBusyCursor();
524c9e2be55Smrg
525c9e2be55Smrg    return True;
526c9e2be55Smrg}
527c9e2be55Smrg
528c9e2be55Smrg
529c9e2be55Smrgvoid TUEnsureScanIsValidAndOpen(Toc toc, Boolean delay)
530c9e2be55Smrg{
531c9e2be55Smrg    if (toc) {
532c9e2be55Smrg	TUGetFullFolderInfo(toc);
533c9e2be55Smrg	if (TUScanFileOutOfDate(toc)) {
534c9e2be55Smrg	    if (!delay)
535c9e2be55Smrg		UpdateScanFile((XtPointer)toc);
536c9e2be55Smrg	    else {
537c9e2be55Smrg		/* this is a hack to get the screen mapped before
538c9e2be55Smrg		 * spawning the subprocess (and blocking).
539c9e2be55Smrg		 * Need to make sure the scanfile exists at this point.
540c9e2be55Smrg		 */
541c9e2be55Smrg		int fid = myopen(toc->scanfile, O_RDWR|O_CREAT, 0666);
542c9e2be55Smrg		myclose(fid);
543c9e2be55Smrg		XtAppAddWorkProc(XtWidgetToApplicationContext(toplevel),
544c9e2be55Smrg				 UpdateScanFile,
545c9e2be55Smrg				 (XtPointer)toc);
546c9e2be55Smrg	    }
547c9e2be55Smrg	}
548c9e2be55Smrg	if (toc->source == NULL)
549c9e2be55Smrg	    TULoadTocFile(toc);
550c9e2be55Smrg    }
551c9e2be55Smrg}
552c9e2be55Smrg
553c9e2be55Smrg
554c9e2be55Smrg
555c9e2be55Smrg/* Refigure all the positions, based on which lines are visible. */
556c9e2be55Smrg
557c9e2be55Smrgvoid TURefigureTocPositions(Toc toc)
558c9e2be55Smrg{
559c9e2be55Smrg    int i;
560c9e2be55Smrg    Msg msg;
561c9e2be55Smrg    XawTextPosition position, length;
562c9e2be55Smrg    position = length = 0;
563c9e2be55Smrg    for (i=0; i<toc->nummsgs ; i++) {
564c9e2be55Smrg	msg = toc->msgs[i];
565c9e2be55Smrg	msg->position = position;
566c9e2be55Smrg	if (msg->visible) position += msg->length;
567c9e2be55Smrg	length += msg->length;
568c9e2be55Smrg    }
569c9e2be55Smrg    toc->lastPos = position;
570c9e2be55Smrg    toc->length = length;
571c9e2be55Smrg}
572c9e2be55Smrg
573c9e2be55Smrg
574c9e2be55Smrg
575c9e2be55Smrg/* Make sure we've loaded ALL the folder info for this toc, including its
576c9e2be55Smrg   path and sequence lists. */
577c9e2be55Smrg
578c9e2be55Smrgvoid TUGetFullFolderInfo(Toc toc)
579c9e2be55Smrg{
580c9e2be55Smrg    char str[500];
581c9e2be55Smrg    if (! toc->scanfile) {
582c9e2be55Smrg	if (! toc->path) {
583c9e2be55Smrg	    /* usually preset by TocFolderExists */
584c9e2be55Smrg	    (void) sprintf(str, "%s/%s", app_resources.mail_path,
585c9e2be55Smrg			   toc->foldername);
586c9e2be55Smrg	    toc->path = XtNewString(str);
587c9e2be55Smrg	}
588c9e2be55Smrg	(void) sprintf(str, "%s/.xmhcache", toc->path);
589c9e2be55Smrg	toc->scanfile = XtNewString(str);
590c9e2be55Smrg	toc->lastreaddate = LastModifyDate(toc->scanfile);
591c9e2be55Smrg	if (TUScanFileOutOfDate(toc))
592c9e2be55Smrg	    toc->validity = invalid;
593c9e2be55Smrg	else {
594c9e2be55Smrg	    toc->validity = valid;
595c9e2be55Smrg	    TULoadTocFile(toc);
596c9e2be55Smrg	}
597c9e2be55Smrg    }
598c9e2be55Smrg}
599c9e2be55Smrg
600c9e2be55Smrg/* Append a message to the end of the toc.  It has the given scan line.  This
601c9e2be55Smrg   routine will figure out the message number, and change the scan line
602c9e2be55Smrg   accordingly. */
603c9e2be55Smrg
604c9e2be55SmrgMsg TUAppendToc(Toc toc, char *ptr)
605c9e2be55Smrg{
606c9e2be55Smrg    Msg msg;
607c9e2be55Smrg    int msgid;
608c9e2be55Smrg
609c9e2be55Smrg    TUGetFullFolderInfo(toc);
610c9e2be55Smrg    if (toc->validity != valid)
611c9e2be55Smrg	return NULL;
612c9e2be55Smrg
613c9e2be55Smrg    if (toc->nummsgs > 0)
614c9e2be55Smrg	msgid = toc->msgs[toc->nummsgs - 1]->msgid + 1;
615c9e2be55Smrg    else
616c9e2be55Smrg	msgid = 1;
617c9e2be55Smrg    (toc->nummsgs)++;
618c9e2be55Smrg    toc->msgs = (Msg *) XtRealloc((char *) toc->msgs,
619c9e2be55Smrg				  (Cardinal) toc->nummsgs * sizeof(Msg));
620c9e2be55Smrg    toc->msgs[toc->nummsgs - 1] = msg = XtNew(MsgRec);
621c9e2be55Smrg    bzero((char *) msg, (int) sizeof(MsgRec));
622c9e2be55Smrg    msg->toc = toc;
623c9e2be55Smrg    msg->buf = XtNewString(ptr);
624c9e2be55Smrg    if (msgid >= 10000)
625c9e2be55Smrg	msgid %= 10000;
626c9e2be55Smrg    (void)sprintf(msg->buf, "%4d", msgid);
627c9e2be55Smrg    msg->buf[MARKPOS] = ' ';
628c9e2be55Smrg    msg->msgid = msgid;
629c9e2be55Smrg    msg->position = toc->lastPos;
630c9e2be55Smrg    msg->length = strlen(ptr);
631c9e2be55Smrg    msg->changed = TRUE;
632c9e2be55Smrg    msg->fate = Fignore;
633c9e2be55Smrg    msg->desttoc = NULL;
634c9e2be55Smrg    if (toc->viewedseq == toc->seqlist[0]) {
635c9e2be55Smrg	msg->visible = TRUE;
636c9e2be55Smrg	toc->lastPos += msg->length;
637c9e2be55Smrg    }
638c9e2be55Smrg    else
639c9e2be55Smrg	msg->visible = FALSE;
640c9e2be55Smrg    toc->length += msg->length;
641c9e2be55Smrg    if ( (msg->visible) && (toc->source != NULL) )
642c9e2be55Smrg	TSourceInvalid(toc, msg->position, msg->length);
643c9e2be55Smrg    TUSaveTocFile(toc);
644c9e2be55Smrg    return msg;
645c9e2be55Smrg}
646