1 | /* $XConsortium: toc.c,v 2.55 91/07/23 16:25:56 converse Exp $ |
---|
2 | * |
---|
3 | * |
---|
4 | * COPYRIGHT 1987 |
---|
5 | * DIGITAL EQUIPMENT CORPORATION |
---|
6 | * MAYNARD, MASSACHUSETTS |
---|
7 | * ALL RIGHTS RESERVED. |
---|
8 | * |
---|
9 | * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND |
---|
10 | * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. |
---|
11 | * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR |
---|
12 | * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. |
---|
13 | * |
---|
14 | * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT |
---|
15 | * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN |
---|
16 | * ADDITION TO THAT SET FORTH ABOVE. |
---|
17 | * |
---|
18 | * Permission to use, copy, modify, and distribute this software and its |
---|
19 | * documentation for any purpose and without fee is hereby granted, provided |
---|
20 | * that the above copyright notice appear in all copies and that both that |
---|
21 | * copyright notice and this permission notice appear in supporting |
---|
22 | * documentation, and that the name of Digital Equipment Corporation not be |
---|
23 | * used in advertising or publicity pertaining to distribution of the software |
---|
24 | * without specific, written prior permission. |
---|
25 | */ |
---|
26 | |
---|
27 | /* toc.c -- handle things in the toc widget. */ |
---|
28 | |
---|
29 | #include "xmh.h" |
---|
30 | #include "tocintrnl.h" |
---|
31 | #include "toc.h" |
---|
32 | #include "tocutil.h" |
---|
33 | #include <sys/stat.h> |
---|
34 | |
---|
35 | static int IsDir(name) |
---|
36 | char *name; |
---|
37 | { |
---|
38 | char str[500]; |
---|
39 | struct stat buf; |
---|
40 | if (*name == '.') |
---|
41 | return FALSE; |
---|
42 | (void) sprintf(str, "%s/%s", app_resources.mail_path, name); |
---|
43 | if (stat(str, &buf) /* failed */) return False; |
---|
44 | return (buf.st_mode & S_IFMT) == S_IFDIR; |
---|
45 | } |
---|
46 | |
---|
47 | |
---|
48 | static void MakeSureFolderExists(namelistptr, numfoldersptr, name) |
---|
49 | char ***namelistptr; |
---|
50 | int *numfoldersptr; |
---|
51 | char *name; |
---|
52 | { |
---|
53 | int i; |
---|
54 | char str[200]; |
---|
55 | for (i=0 ; i<*numfoldersptr ; i++) |
---|
56 | if (strcmp((*namelistptr)[i], name) == 0) return; |
---|
57 | (void) sprintf(str, "%s/%s", app_resources.mail_path, name); |
---|
58 | (void) mkdir(str, 0700); |
---|
59 | *numfoldersptr = ScanDir(app_resources.mail_path, namelistptr, IsDir); |
---|
60 | for (i=0 ; i<*numfoldersptr ; i++) |
---|
61 | if (strcmp((*namelistptr)[i], name) == 0) return; |
---|
62 | Punt("Can't create new mail folder!"); |
---|
63 | } |
---|
64 | |
---|
65 | |
---|
66 | static void MakeSureSubfolderExists(namelistptr, numfoldersptr, name) |
---|
67 | char *** namelistptr; |
---|
68 | int * numfoldersptr; |
---|
69 | char * name; |
---|
70 | { |
---|
71 | char folder[300]; |
---|
72 | char subfolder_path[300]; |
---|
73 | char *subfolder; |
---|
74 | struct stat buf; |
---|
75 | |
---|
76 | /* Make sure that the parent folder exists */ |
---|
77 | |
---|
78 | subfolder = index( strcpy(folder, name), '/'); |
---|
79 | *subfolder = '\0'; |
---|
80 | subfolder++; |
---|
81 | MakeSureFolderExists(namelistptr, numfoldersptr, folder); |
---|
82 | |
---|
83 | /* The parent folder exists. Make sure the subfolder exists. */ |
---|
84 | |
---|
85 | (void) sprintf(subfolder_path, "%s/%s", app_resources.mail_path, name); |
---|
86 | if (stat(subfolder_path, &buf) /* failed */) { |
---|
87 | (void) mkdir(subfolder_path, 0700); |
---|
88 | if (stat(subfolder_path, &buf) /* failed */) |
---|
89 | Punt("Can't create new xmh subfolder!"); |
---|
90 | } |
---|
91 | |
---|
92 | if ((buf.st_mode & S_IFMT) != S_IFDIR) |
---|
93 | Punt("Can't create new xmh subfolder!"); |
---|
94 | } |
---|
95 | |
---|
96 | int TocFolderExists(toc) |
---|
97 | Toc toc; |
---|
98 | { |
---|
99 | struct stat buf; |
---|
100 | if (! toc->path) { |
---|
101 | char str[500]; |
---|
102 | (void) sprintf(str, "%s/%s", app_resources.mail_path, toc->foldername); |
---|
103 | toc->path = XtNewString(str); |
---|
104 | } |
---|
105 | return ((stat(toc->path, &buf) == 0) && |
---|
106 | ((buf.st_mode & S_IFMT) == S_IFDIR)); |
---|
107 | } |
---|
108 | |
---|
109 | static void LoadCheckFiles() |
---|
110 | { |
---|
111 | FILE *fid; |
---|
112 | char str[1024]; |
---|
113 | |
---|
114 | (void) sprintf(str, "%s/.xmhcheck", homeDir); |
---|
115 | fid = myfopen(str, "r"); |
---|
116 | if (fid) { |
---|
117 | int i; |
---|
118 | char *ptr, *ptr2; |
---|
119 | |
---|
120 | while (ptr = ReadLine(fid)) { |
---|
121 | while (*ptr == ' ' || *ptr == '\t') ptr++; |
---|
122 | ptr2 = ptr; |
---|
123 | while (*ptr2 && *ptr2 != ' ' && *ptr2 != '\t') ptr2++; |
---|
124 | if (*ptr2 == 0) continue; |
---|
125 | *ptr2++ = 0; |
---|
126 | while (*ptr2 == ' ' || *ptr2 == '\t') ptr2++; |
---|
127 | if (*ptr2 == 0) continue; |
---|
128 | for (i=0 ; i<numFolders ; i++) { |
---|
129 | if (strcmp(ptr, folderList[i]->foldername) == 0) { |
---|
130 | folderList[i]->incfile = XtNewString(ptr2); |
---|
131 | break; |
---|
132 | } |
---|
133 | } |
---|
134 | } |
---|
135 | myfclose(fid); |
---|
136 | } else if ( app_resources.initial_inc_file && |
---|
137 | *app_resources.initial_inc_file) |
---|
138 | InitialFolder->incfile = app_resources.initial_inc_file; |
---|
139 | } |
---|
140 | |
---|
141 | |
---|
142 | /* PUBLIC ROUTINES */ |
---|
143 | |
---|
144 | |
---|
145 | /* Read in the list of folders. */ |
---|
146 | |
---|
147 | void TocInit() |
---|
148 | { |
---|
149 | Toc toc; |
---|
150 | char **namelist; |
---|
151 | int i; |
---|
152 | extern alphasort(); |
---|
153 | numFolders = ScanDir(app_resources.mail_path, &namelist, IsDir); |
---|
154 | if (numFolders < 0) { |
---|
155 | (void) mkdir(app_resources.mail_path, 0700); |
---|
156 | numFolders = ScanDir(app_resources.mail_path, &namelist, IsDir); |
---|
157 | if (numFolders < 0) |
---|
158 | Punt("Can't create or read mail directory!"); |
---|
159 | } |
---|
160 | if (IsSubfolder(app_resources.initial_folder_name)) |
---|
161 | MakeSureSubfolderExists(&namelist, &numFolders, |
---|
162 | app_resources.initial_folder_name); |
---|
163 | else |
---|
164 | MakeSureFolderExists(&namelist, &numFolders, |
---|
165 | app_resources.initial_folder_name); |
---|
166 | |
---|
167 | if (IsSubfolder(app_resources.drafts_folder_name)) |
---|
168 | MakeSureSubfolderExists(&namelist, &numFolders, |
---|
169 | app_resources.drafts_folder_name); |
---|
170 | else |
---|
171 | MakeSureFolderExists(&namelist, &numFolders, |
---|
172 | app_resources.drafts_folder_name); |
---|
173 | folderList = (Toc *) XtMalloc((Cardinal)numFolders * sizeof(Toc)); |
---|
174 | for (i=0 ; i<numFolders ; i++) { |
---|
175 | toc = folderList[i] = TUMalloc(); |
---|
176 | toc->foldername = XtNewString(namelist[i]); |
---|
177 | free((char *)namelist[i]); |
---|
178 | } |
---|
179 | if (! (InitialFolder = TocGetNamed(app_resources.initial_folder_name))) |
---|
180 | InitialFolder = TocCreate(app_resources.initial_folder_name); |
---|
181 | |
---|
182 | if (! (DraftsFolder = TocGetNamed(app_resources.drafts_folder_name))) |
---|
183 | DraftsFolder = TocCreate(app_resources.drafts_folder_name); |
---|
184 | free((char *)namelist); |
---|
185 | LoadCheckFiles(); |
---|
186 | } |
---|
187 | |
---|
188 | |
---|
189 | |
---|
190 | /* Create a toc and add a folder to the folderList. */ |
---|
191 | |
---|
192 | Toc TocCreate(foldername) |
---|
193 | char *foldername; |
---|
194 | { |
---|
195 | Toc toc = TUMalloc(); |
---|
196 | |
---|
197 | toc->foldername = XtNewString(foldername); |
---|
198 | folderList = (Toc *) XtRealloc((char *) folderList, |
---|
199 | (unsigned) ++numFolders * sizeof(Toc)); |
---|
200 | folderList[numFolders - 1] = toc; |
---|
201 | return toc; |
---|
202 | } |
---|
203 | |
---|
204 | |
---|
205 | /* Create a new folder with the given name. */ |
---|
206 | |
---|
207 | Toc TocCreateFolder(foldername) |
---|
208 | char *foldername; |
---|
209 | { |
---|
210 | Toc toc; |
---|
211 | char str[500]; |
---|
212 | if (TocGetNamed(foldername)) return NULL; |
---|
213 | (void) sprintf(str, "%s/%s", app_resources.mail_path, foldername); |
---|
214 | if (mkdir(str, 0700) < 0) return NULL; |
---|
215 | toc = TocCreate(foldername); |
---|
216 | return toc; |
---|
217 | } |
---|
218 | |
---|
219 | int TocHasMail(toc) |
---|
220 | Toc toc; |
---|
221 | { |
---|
222 | return toc->mailpending; |
---|
223 | } |
---|
224 | |
---|
225 | static int CheckForNewMail(toc) |
---|
226 | Toc toc; |
---|
227 | { |
---|
228 | if (toc->incfile) |
---|
229 | return (GetFileLength(toc->incfile) > 0); |
---|
230 | else if (toc == InitialFolder) { |
---|
231 | char **argv; |
---|
232 | char *result; |
---|
233 | int hasmail; |
---|
234 | |
---|
235 | argv = MakeArgv(4); |
---|
236 | argv[0] = "msgchk"; |
---|
237 | argv[1] = "-nonotify"; |
---|
238 | argv[2] = "nomail"; |
---|
239 | argv[3] = "-nodate"; |
---|
240 | result = DoCommandToString(argv); |
---|
241 | hasmail = (*result != '\0'); |
---|
242 | XtFree(result); |
---|
243 | XtFree((char*)argv); |
---|
244 | return hasmail; |
---|
245 | } |
---|
246 | return False; |
---|
247 | } |
---|
248 | |
---|
249 | /*ARGSUSED*/ |
---|
250 | void TocCheckForNewMail(update) |
---|
251 | Boolean update; /* if True, actually make the check */ |
---|
252 | { |
---|
253 | Toc toc; |
---|
254 | Scrn scrn; |
---|
255 | int i, j, hasmail; |
---|
256 | Boolean mail_waiting = False; |
---|
257 | |
---|
258 | if (update) { |
---|
259 | for (i=0 ; i<numFolders ; i++) { |
---|
260 | toc = folderList[i]; |
---|
261 | if (TocCanIncorporate(toc)) { |
---|
262 | toc->mailpending = hasmail = CheckForNewMail(toc); |
---|
263 | if (hasmail) mail_waiting = True; |
---|
264 | for (j=0 ; j<numScrns ; j++) { |
---|
265 | scrn = scrnList[j]; |
---|
266 | if (scrn->kind == STtocAndView) |
---|
267 | /* give visual indication of new mail waiting */ |
---|
268 | BBoxMailFlag(scrn->folderbuttons, TocName(toc), |
---|
269 | hasmail); |
---|
270 | } |
---|
271 | } |
---|
272 | } |
---|
273 | } else { |
---|
274 | for (i=0; i < numFolders; i++) { |
---|
275 | toc = folderList[i]; |
---|
276 | if (toc->mailpending) { |
---|
277 | mail_waiting = True; |
---|
278 | break; |
---|
279 | } |
---|
280 | } |
---|
281 | } |
---|
282 | |
---|
283 | if (app_resources.mail_waiting_flag) { |
---|
284 | Arg args[1]; |
---|
285 | static Boolean icon_state = -1; |
---|
286 | |
---|
287 | if (icon_state != mail_waiting) { |
---|
288 | icon_state = mail_waiting; |
---|
289 | for (i=0; i < numScrns; i++) { |
---|
290 | scrn = scrnList[i]; |
---|
291 | if (scrn->kind == STtocAndView) { |
---|
292 | XtSetArg(args[0], XtNiconPixmap, |
---|
293 | (mail_waiting ? app_resources.new_mail_icon |
---|
294 | : app_resources.no_mail_icon)); |
---|
295 | XtSetValues(scrn->parent, args, (Cardinal)1); |
---|
296 | } |
---|
297 | } |
---|
298 | } |
---|
299 | } |
---|
300 | } |
---|
301 | |
---|
302 | /* Intended to support mutual exclusion on deleting folders, so that you |
---|
303 | * cannot have two confirm popups at the same time on the same folder. |
---|
304 | * |
---|
305 | * You can have confirm popups on different folders simultaneously. |
---|
306 | * However, I did not protect the user from popping up a delete confirm |
---|
307 | * popup on folder A, then popping up a delete confirm popup on folder |
---|
308 | * A/subA, then deleting A, then deleting A/subA -- which of course is |
---|
309 | * already gone, and will cause xmh to Punt. |
---|
310 | * |
---|
311 | * TocClearDeletePending is a callback from the No confirmation button |
---|
312 | * of the confirm popup. |
---|
313 | */ |
---|
314 | |
---|
315 | Boolean TocTestAndSetDeletePending(toc) |
---|
316 | Toc toc; |
---|
317 | { |
---|
318 | Boolean flag; |
---|
319 | |
---|
320 | flag = toc->delete_pending; |
---|
321 | toc->delete_pending = True; |
---|
322 | return flag; |
---|
323 | } |
---|
324 | |
---|
325 | void TocClearDeletePending(toc) |
---|
326 | Toc toc; |
---|
327 | { |
---|
328 | toc->delete_pending = False; |
---|
329 | } |
---|
330 | |
---|
331 | |
---|
332 | /* Recursively delete an entire directory. Nasty. */ |
---|
333 | |
---|
334 | static void NukeDirectory(path) |
---|
335 | char *path; |
---|
336 | { |
---|
337 | struct stat buf; |
---|
338 | |
---|
339 | #ifdef S_IFLNK |
---|
340 | /* POSIX.1 does not discuss symbolic links. */ |
---|
341 | if (lstat(path, &buf) /* failed */) |
---|
342 | return; |
---|
343 | if ((buf.st_mode & S_IFMT) == S_IFLNK) { |
---|
344 | (void) unlink(path); |
---|
345 | return; |
---|
346 | } |
---|
347 | #endif |
---|
348 | if (stat(path, &buf) /* failed */) |
---|
349 | return; |
---|
350 | if (buf.st_mode & S_IWRITE) { |
---|
351 | char **argv = MakeArgv(3); |
---|
352 | argv[0] = "/bin/rm"; |
---|
353 | argv[1] = "-rf"; |
---|
354 | argv[2] = path; |
---|
355 | (void) DoCommand(argv, (char*)NULL, (char*)NULL); |
---|
356 | XtFree((char*)argv); |
---|
357 | } |
---|
358 | } |
---|
359 | |
---|
360 | |
---|
361 | /* Destroy the given folder. */ |
---|
362 | |
---|
363 | void TocDeleteFolder(toc) |
---|
364 | Toc toc; |
---|
365 | { |
---|
366 | Toc toc2; |
---|
367 | int i, j, w; |
---|
368 | if (toc == NULL) return; |
---|
369 | TUGetFullFolderInfo(toc); |
---|
370 | |
---|
371 | w = -1; |
---|
372 | for (i=0 ; i<numFolders ; i++) { |
---|
373 | toc2 = folderList[i]; |
---|
374 | if (toc2 == toc) |
---|
375 | w = i; |
---|
376 | else if (toc2->validity == valid) |
---|
377 | for (j=0 ; j<toc2->nummsgs ; j++) |
---|
378 | if (toc2->msgs[j]->desttoc == toc) |
---|
379 | MsgSetFate(toc2->msgs[j], Fignore, (Toc) NULL); |
---|
380 | } |
---|
381 | if (w < 0) Punt("Couldn't find it in TocDeleteFolder!"); |
---|
382 | NukeDirectory(toc->path); |
---|
383 | if (toc->validity == valid) { |
---|
384 | for (i=0 ; i<toc->nummsgs ; i++) { |
---|
385 | MsgSetScrnForce(toc->msgs[i], (Scrn) NULL); |
---|
386 | MsgFree(toc->msgs[i]); |
---|
387 | } |
---|
388 | XtFree((char *) toc->msgs); |
---|
389 | } |
---|
390 | XtFree((char *)toc); |
---|
391 | numFolders--; |
---|
392 | for (i=w ; i<numFolders ; i++) folderList[i] = folderList[i+1]; |
---|
393 | } |
---|
394 | |
---|
395 | |
---|
396 | /* |
---|
397 | * Display the given toc in the given scrn. If scrn is NULL, then remove the |
---|
398 | * toc from all scrns displaying it. |
---|
399 | */ |
---|
400 | |
---|
401 | void TocSetScrn(toc, scrn) |
---|
402 | Toc toc; |
---|
403 | Scrn scrn; |
---|
404 | { |
---|
405 | int i; |
---|
406 | if (toc == NULL && scrn == NULL) return; |
---|
407 | if (scrn == NULL) { |
---|
408 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
409 | TocSetScrn((Toc) NULL, toc->scrn[i]); |
---|
410 | return; |
---|
411 | } |
---|
412 | if (scrn->toc == toc) return; |
---|
413 | if (scrn->toc != NULL) { |
---|
414 | for (i=0 ; i<scrn->toc->num_scrns ; i++) |
---|
415 | if (scrn->toc->scrn[i] == scrn) break; |
---|
416 | if (i >= scrn->toc->num_scrns) |
---|
417 | Punt("Couldn't find scrn in TocSetScrn!"); |
---|
418 | scrn->toc->scrn[i] = scrn->toc->scrn[--scrn->toc->num_scrns]; |
---|
419 | } |
---|
420 | scrn->toc = toc; |
---|
421 | if (toc == NULL) { |
---|
422 | TUResetTocLabel(scrn); |
---|
423 | TURedisplayToc(scrn); |
---|
424 | StoreWindowName(scrn, progName); |
---|
425 | } else { |
---|
426 | toc->num_scrns++; |
---|
427 | toc->scrn = (Scrn *) XtRealloc((char *) toc->scrn, |
---|
428 | (unsigned)toc->num_scrns*sizeof(Scrn)); |
---|
429 | toc->scrn[toc->num_scrns - 1] = scrn; |
---|
430 | TUEnsureScanIsValidAndOpen(toc); |
---|
431 | TUResetTocLabel(scrn); |
---|
432 | if (app_resources.prefix_wm_and_icon_name) { |
---|
433 | char wm_name[64]; |
---|
434 | int length = strlen(progName); |
---|
435 | (void) strncpy(wm_name, progName, length); |
---|
436 | (void) strncpy(wm_name + length , ": ", 2); |
---|
437 | (void) strcpy(wm_name + length + 2, toc->foldername); |
---|
438 | StoreWindowName(scrn, wm_name); |
---|
439 | } |
---|
440 | else |
---|
441 | StoreWindowName(scrn, toc->foldername); |
---|
442 | TURedisplayToc(scrn); |
---|
443 | SetCurrentFolderName(scrn, toc->foldername); |
---|
444 | } |
---|
445 | EnableProperButtons(scrn); |
---|
446 | } |
---|
447 | |
---|
448 | |
---|
449 | |
---|
450 | /* Remove the given message from the toc. Doesn't actually touch the file. |
---|
451 | Also note that it does not free the storage for the msg. */ |
---|
452 | |
---|
453 | void TocRemoveMsg(toc, msg) |
---|
454 | Toc toc; |
---|
455 | Msg msg; |
---|
456 | { |
---|
457 | Msg newcurmsg; |
---|
458 | MsgList mlist; |
---|
459 | int i; |
---|
460 | if (toc->validity == unknown) |
---|
461 | TUGetFullFolderInfo(toc); |
---|
462 | if (toc->validity != valid) |
---|
463 | return; |
---|
464 | newcurmsg = TocMsgAfter(toc, msg); |
---|
465 | if (newcurmsg) newcurmsg->changed = TRUE; |
---|
466 | newcurmsg = toc->curmsg; |
---|
467 | if (msg == toc->curmsg) { |
---|
468 | newcurmsg = TocMsgAfter(toc, msg); |
---|
469 | if (newcurmsg == NULL) newcurmsg = TocMsgBefore(toc, msg); |
---|
470 | toc->curmsg = NULL; |
---|
471 | } |
---|
472 | toc->length -= msg->length; |
---|
473 | if (msg->visible) toc->lastPos -= msg->length; |
---|
474 | for(i = TUGetMsgPosition(toc, msg), toc->nummsgs--; i<toc->nummsgs ; i++) { |
---|
475 | toc->msgs[i] = toc->msgs[i+1]; |
---|
476 | if (msg->visible) toc->msgs[i]->position -= msg->length; |
---|
477 | } |
---|
478 | for (i=0 ; i<toc->numsequences ; i++) { |
---|
479 | mlist = toc->seqlist[i]->mlist; |
---|
480 | if (mlist) DeleteMsgFromMsgList(mlist, msg); |
---|
481 | } |
---|
482 | |
---|
483 | if (msg->visible && toc->num_scrns > 0 && !toc->needsrepaint) |
---|
484 | TSourceInvalid(toc, msg->position, -msg->length); |
---|
485 | TocSetCurMsg(toc, newcurmsg); |
---|
486 | TUSaveTocFile(toc); |
---|
487 | } |
---|
488 | |
---|
489 | |
---|
490 | |
---|
491 | void TocRecheckValidity(toc) |
---|
492 | Toc toc; |
---|
493 | { |
---|
494 | int i; |
---|
495 | if (toc && toc->validity == valid && TUScanFileOutOfDate(toc)) { |
---|
496 | if (app_resources.block_events_on_busy) ShowBusyCursor(); |
---|
497 | |
---|
498 | TUScanFileForToc(toc); |
---|
499 | if (toc->source) |
---|
500 | TULoadTocFile(toc); |
---|
501 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
502 | TURedisplayToc(toc->scrn[i]); |
---|
503 | |
---|
504 | if (app_resources.block_events_on_busy) UnshowBusyCursor(); |
---|
505 | } |
---|
506 | } |
---|
507 | |
---|
508 | |
---|
509 | /* Set the current message. */ |
---|
510 | |
---|
511 | void TocSetCurMsg(toc, msg) |
---|
512 | Toc toc; |
---|
513 | Msg msg; |
---|
514 | { |
---|
515 | Msg msg2; |
---|
516 | int i; |
---|
517 | if (toc->validity != valid) return; |
---|
518 | if (msg != toc->curmsg) { |
---|
519 | msg2 = toc->curmsg; |
---|
520 | toc->curmsg = msg; |
---|
521 | if (msg2) |
---|
522 | MsgSetFate(msg2, msg2->fate, msg2->desttoc); |
---|
523 | } |
---|
524 | if (msg) { |
---|
525 | MsgSetFate(msg, msg->fate, msg->desttoc); |
---|
526 | if (toc->num_scrns) { |
---|
527 | if (toc->stopupdate) |
---|
528 | toc->needsrepaint = TRUE; |
---|
529 | else { |
---|
530 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
531 | XawTextSetInsertionPoint(toc->scrn[i]->tocwidget, |
---|
532 | msg->position); |
---|
533 | } |
---|
534 | } |
---|
535 | } |
---|
536 | } |
---|
537 | |
---|
538 | |
---|
539 | /* Return the current message. */ |
---|
540 | |
---|
541 | Msg TocGetCurMsg(toc) |
---|
542 | Toc toc; |
---|
543 | { |
---|
544 | return toc->curmsg; |
---|
545 | } |
---|
546 | |
---|
547 | |
---|
548 | |
---|
549 | |
---|
550 | /* Return the message after the given one. (If none, return NULL.) */ |
---|
551 | |
---|
552 | Msg TocMsgAfter(toc, msg) |
---|
553 | Toc toc; |
---|
554 | Msg msg; |
---|
555 | { |
---|
556 | int i; |
---|
557 | i = TUGetMsgPosition(toc, msg); |
---|
558 | do { |
---|
559 | i++; |
---|
560 | if (i >= toc->nummsgs) |
---|
561 | return NULL; |
---|
562 | } while (!(toc->msgs[i]->visible)); |
---|
563 | return toc->msgs[i]; |
---|
564 | } |
---|
565 | |
---|
566 | |
---|
567 | |
---|
568 | /* Return the message before the given one. (If none, return NULL.) */ |
---|
569 | |
---|
570 | Msg TocMsgBefore(toc, msg) |
---|
571 | Toc toc; |
---|
572 | Msg msg; |
---|
573 | { |
---|
574 | int i; |
---|
575 | i = TUGetMsgPosition(toc, msg); |
---|
576 | do { |
---|
577 | i--; |
---|
578 | if (i < 0) |
---|
579 | return NULL; |
---|
580 | } while (!(toc->msgs[i]->visible)); |
---|
581 | return toc->msgs[i]; |
---|
582 | } |
---|
583 | |
---|
584 | |
---|
585 | |
---|
586 | /* The caller KNOWS the toc's information is out of date; rescan it. */ |
---|
587 | |
---|
588 | void TocForceRescan(toc) |
---|
589 | Toc toc; |
---|
590 | { |
---|
591 | register int i; |
---|
592 | if (toc->num_scrns) { |
---|
593 | toc->viewedseq = toc->seqlist[0]; |
---|
594 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
595 | TUResetTocLabel(toc->scrn[i]); |
---|
596 | TUScanFileForToc(toc); |
---|
597 | TULoadTocFile(toc); |
---|
598 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
599 | TURedisplayToc(toc->scrn[i]); |
---|
600 | } else { |
---|
601 | TUGetFullFolderInfo(toc); |
---|
602 | (void) unlink(toc->scanfile); |
---|
603 | toc->validity = invalid; |
---|
604 | } |
---|
605 | } |
---|
606 | |
---|
607 | |
---|
608 | |
---|
609 | /* The caller has just changed a sequence list. Reread them from mh. */ |
---|
610 | |
---|
611 | void TocReloadSeqLists(toc) |
---|
612 | Toc toc; |
---|
613 | { |
---|
614 | int i; |
---|
615 | TocSetCacheValid(toc); |
---|
616 | TULoadSeqLists(toc); |
---|
617 | TURefigureWhatsVisible(toc); |
---|
618 | for (i=0 ; i<toc->num_scrns ; i++) { |
---|
619 | TUResetTocLabel(toc->scrn[i]); |
---|
620 | EnableProperButtons(toc->scrn[i]); |
---|
621 | } |
---|
622 | } |
---|
623 | |
---|
624 | |
---|
625 | /*ARGSUSED*/ |
---|
626 | void XmhReloadSeqLists(w, event, params, num_params) |
---|
627 | Widget w; |
---|
628 | XEvent *event; |
---|
629 | String *params; |
---|
630 | Cardinal *num_params; |
---|
631 | { |
---|
632 | Scrn scrn = ScrnFromWidget(w); |
---|
633 | TocReloadSeqLists(scrn->toc); |
---|
634 | TUCheckSequenceMenu(scrn->toc); |
---|
635 | } |
---|
636 | |
---|
637 | |
---|
638 | |
---|
639 | /* Return TRUE if the toc has an interesting sequence. */ |
---|
640 | |
---|
641 | int TocHasSequences(toc) |
---|
642 | Toc toc; |
---|
643 | { |
---|
644 | return toc && toc->numsequences > 1; |
---|
645 | } |
---|
646 | |
---|
647 | |
---|
648 | /* Change which sequence is being viewed. */ |
---|
649 | |
---|
650 | void TocChangeViewedSeq(toc, seq) |
---|
651 | Toc toc; |
---|
652 | Sequence seq; |
---|
653 | { |
---|
654 | if (seq == NULL) seq = toc->viewedseq; |
---|
655 | toc->viewedseq = seq; |
---|
656 | toc->force_reset = True; /* %%% force Text source to be reset */ |
---|
657 | TURefigureWhatsVisible(toc); |
---|
658 | } |
---|
659 | |
---|
660 | |
---|
661 | /* Return the sequence with the given name in the given toc. */ |
---|
662 | |
---|
663 | Sequence TocGetSeqNamed(toc, name) |
---|
664 | Toc toc; |
---|
665 | char *name; |
---|
666 | { |
---|
667 | register int i; |
---|
668 | if (name == NULL) |
---|
669 | return (Sequence) NULL; |
---|
670 | |
---|
671 | for (i=0 ; i<toc->numsequences ; i++) |
---|
672 | if (strcmp(toc->seqlist[i]->name, name) == 0) |
---|
673 | return toc->seqlist[i]; |
---|
674 | return (Sequence) NULL; |
---|
675 | } |
---|
676 | |
---|
677 | |
---|
678 | /* Return the sequence currently being viewed in the toc. */ |
---|
679 | |
---|
680 | Sequence TocViewedSequence(toc) |
---|
681 | Toc toc; |
---|
682 | { |
---|
683 | return toc->viewedseq; |
---|
684 | } |
---|
685 | |
---|
686 | |
---|
687 | /* Set the selected sequence in the toc */ |
---|
688 | |
---|
689 | void TocSetSelectedSequence(toc, sequence) |
---|
690 | Toc toc; |
---|
691 | Sequence sequence; |
---|
692 | { |
---|
693 | if (toc) |
---|
694 | toc->selectseq = sequence; |
---|
695 | } |
---|
696 | |
---|
697 | |
---|
698 | /* Return the sequence currently selected */ |
---|
699 | |
---|
700 | Sequence TocSelectedSequence(toc) |
---|
701 | Toc toc; |
---|
702 | { |
---|
703 | if (toc) return (toc->selectseq); |
---|
704 | else return (Sequence) NULL; |
---|
705 | } |
---|
706 | |
---|
707 | |
---|
708 | /* Return the list of messages currently selected. */ |
---|
709 | |
---|
710 | #define SrcScan XawTextSourceScan |
---|
711 | |
---|
712 | MsgList TocCurMsgList(toc) |
---|
713 | Toc toc; |
---|
714 | { |
---|
715 | MsgList result; |
---|
716 | XawTextPosition pos1, pos2; |
---|
717 | extern Msg MsgFromPosition(); |
---|
718 | if (toc->num_scrns == 0) return NULL; |
---|
719 | result = MakeNullMsgList(); |
---|
720 | XawTextGetSelectionPos( toc->scrn[0]->tocwidget, &pos1, &pos2); /* %%% */ |
---|
721 | if (pos1 < pos2) { |
---|
722 | pos1 = SrcScan(toc->source, pos1, XawstEOL, XawsdLeft, 1, FALSE); |
---|
723 | pos2 = SrcScan(toc->source, pos2, XawstPositions, XawsdLeft, 1, TRUE); |
---|
724 | pos2 = SrcScan(toc->source, pos2, XawstEOL, XawsdRight, 1, FALSE); |
---|
725 | while (pos1 < pos2) { |
---|
726 | AppendMsgList(result, MsgFromPosition(toc, pos1, XawsdRight)); |
---|
727 | pos1 = SrcScan(toc->source, pos1, XawstEOL, XawsdRight, 1, TRUE); |
---|
728 | } |
---|
729 | } |
---|
730 | return result; |
---|
731 | } |
---|
732 | |
---|
733 | |
---|
734 | |
---|
735 | /* Unset the current selection. */ |
---|
736 | |
---|
737 | void TocUnsetSelection(toc) |
---|
738 | Toc toc; |
---|
739 | { |
---|
740 | if (toc->source) |
---|
741 | XawTextUnsetSelection(toc->scrn[0]->tocwidget); |
---|
742 | } |
---|
743 | |
---|
744 | |
---|
745 | |
---|
746 | /* Create a brand new, blank message. */ |
---|
747 | |
---|
748 | Msg TocMakeNewMsg(toc) |
---|
749 | Toc toc; |
---|
750 | { |
---|
751 | Msg msg; |
---|
752 | static int looping = False; |
---|
753 | TUEnsureScanIsValidAndOpen(toc); |
---|
754 | msg = TUAppendToc(toc, "#### empty\n"); |
---|
755 | if (FileExists(MsgFileName(msg))) { |
---|
756 | if (looping++) Punt( "Cannot correct scan file" ); |
---|
757 | DEBUG2("**** FOLDER %s WAS INVALID; msg %d already existed!\n", |
---|
758 | toc->foldername, msg->msgid); |
---|
759 | TocForceRescan(toc); |
---|
760 | return TocMakeNewMsg(toc); /* Try again. Using recursion here is ugly, |
---|
761 | but what the hack ... */ |
---|
762 | } |
---|
763 | CopyFileAndCheck("/dev/null", MsgFileName(msg)); |
---|
764 | looping = False; |
---|
765 | return msg; |
---|
766 | } |
---|
767 | |
---|
768 | |
---|
769 | /* Set things to not update cache or display until further notice. */ |
---|
770 | |
---|
771 | void TocStopUpdate(toc) |
---|
772 | Toc toc; |
---|
773 | { |
---|
774 | int i; |
---|
775 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
776 | XawTextDisableRedisplay(toc->scrn[i]->tocwidget); |
---|
777 | toc->stopupdate++; |
---|
778 | } |
---|
779 | |
---|
780 | |
---|
781 | /* Start updating again, and do whatever updating has been queued. */ |
---|
782 | |
---|
783 | void TocStartUpdate(toc) |
---|
784 | Toc toc; |
---|
785 | { |
---|
786 | int i; |
---|
787 | if (toc->stopupdate && --(toc->stopupdate) == 0) { |
---|
788 | for (i=0 ; i<toc->num_scrns ; i++) { |
---|
789 | if (toc->needsrepaint) |
---|
790 | TURedisplayToc(toc->scrn[i]); |
---|
791 | if (toc->needslabelupdate) |
---|
792 | TUResetTocLabel(toc->scrn[i]); |
---|
793 | } |
---|
794 | if (toc->needscachesave) |
---|
795 | TUSaveTocFile(toc); |
---|
796 | } |
---|
797 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
798 | XawTextEnableRedisplay(toc->scrn[i]->tocwidget); |
---|
799 | } |
---|
800 | |
---|
801 | |
---|
802 | |
---|
803 | /* Something has happened that could later convince us that our cache is out |
---|
804 | of date. Make this not happen; our cache really *is* up-to-date. */ |
---|
805 | |
---|
806 | void TocSetCacheValid(toc) |
---|
807 | Toc toc; |
---|
808 | { |
---|
809 | TUSaveTocFile(toc); |
---|
810 | } |
---|
811 | |
---|
812 | |
---|
813 | /* Return the full folder pathname of the given toc, prefixed w/'+' */ |
---|
814 | |
---|
815 | char *TocMakeFolderName(toc) |
---|
816 | Toc toc; |
---|
817 | { |
---|
818 | char* name = XtMalloc((Cardinal) (strlen(toc->path) + 2) ); |
---|
819 | (void)sprintf( name, "+%s", toc->path ); |
---|
820 | return name; |
---|
821 | } |
---|
822 | |
---|
823 | char *TocName(toc) |
---|
824 | Toc toc; |
---|
825 | { |
---|
826 | return toc->foldername; |
---|
827 | } |
---|
828 | |
---|
829 | |
---|
830 | |
---|
831 | /* Given a foldername, return the corresponding toc. */ |
---|
832 | |
---|
833 | Toc TocGetNamed(name) |
---|
834 | char *name; |
---|
835 | { |
---|
836 | int i; |
---|
837 | for (i=0; i<numFolders ; i++) |
---|
838 | if (strcmp(folderList[i]->foldername, name) == 0) return folderList[i]; |
---|
839 | return NULL; |
---|
840 | } |
---|
841 | |
---|
842 | |
---|
843 | |
---|
844 | /* Throw out all changes to this toc, and close all views of msgs in it. |
---|
845 | Requires confirmation by the user. */ |
---|
846 | |
---|
847 | /*ARGSUSED*/ |
---|
848 | static void TocCataclysmOkay(widget, client_data, call_data) |
---|
849 | Widget widget; /* unused */ |
---|
850 | XtPointer client_data; |
---|
851 | XtPointer call_data; /* unused */ |
---|
852 | { |
---|
853 | Toc toc = (Toc) client_data; |
---|
854 | register int i; |
---|
855 | |
---|
856 | for (i=0; i < toc->nummsgs; i++) |
---|
857 | MsgSetFate(toc->msgs[i], Fignore, (Toc)NULL); |
---|
858 | |
---|
859 | /* Doesn't make sense to have this MsgSetScrn for loop here. dmc. %%% */ |
---|
860 | for (i=0; i < toc->nummsgs; i++) |
---|
861 | MsgSetScrn(toc->msgs[i], (Scrn) NULL, (XtCallbackList) NULL, |
---|
862 | (XtCallbackList) NULL); |
---|
863 | } |
---|
864 | |
---|
865 | int TocConfirmCataclysm(toc, confirms, cancels) |
---|
866 | Toc toc; |
---|
867 | XtCallbackList confirms; |
---|
868 | XtCallbackList cancels; |
---|
869 | { |
---|
870 | register int i; |
---|
871 | int found = False; |
---|
872 | static XtCallbackRec yes_callbacks[] = { |
---|
873 | {TocCataclysmOkay, (XtPointer) NULL}, |
---|
874 | {(XtCallbackProc) NULL, (XtPointer) NULL}, |
---|
875 | {(XtCallbackProc) NULL, (XtPointer) NULL} |
---|
876 | }; |
---|
877 | |
---|
878 | if (! toc) |
---|
879 | return 0; |
---|
880 | |
---|
881 | for (i=0 ; i<toc->nummsgs && !found ; i++) |
---|
882 | if (toc->msgs[i]->fate != Fignore) found = True; |
---|
883 | |
---|
884 | if (found) { |
---|
885 | char str[300]; |
---|
886 | Widget tocwidget; |
---|
887 | int i; |
---|
888 | |
---|
889 | (void)sprintf(str,"Are you sure you want to remove all changes to %s?", |
---|
890 | toc->foldername); |
---|
891 | yes_callbacks[0].closure = (XtPointer) toc; |
---|
892 | yes_callbacks[1].callback = confirms[0].callback; |
---|
893 | yes_callbacks[1].closure = confirms[0].closure; |
---|
894 | |
---|
895 | tocwidget = NULL; |
---|
896 | for (i=0; i < toc->num_scrns; i++) |
---|
897 | if (toc->scrn[i]->mapped) { |
---|
898 | tocwidget = toc->scrn[i]->tocwidget; |
---|
899 | break; |
---|
900 | } |
---|
901 | |
---|
902 | PopupConfirm(tocwidget, str, yes_callbacks, cancels); |
---|
903 | return NEEDS_CONFIRMATION; |
---|
904 | } |
---|
905 | else { |
---|
906 | /* Doesn't make sense to have this MsgSetFate for loop here. dmc. %%% */ |
---|
907 | for (i=0 ; i<toc->nummsgs ; i++) |
---|
908 | MsgSetFate(toc->msgs[i], Fignore, (Toc)NULL); |
---|
909 | |
---|
910 | for (i=0 ; i<toc->nummsgs ; i++) |
---|
911 | if (MsgSetScrn(toc->msgs[i], (Scrn) NULL, confirms, cancels)) |
---|
912 | return NEEDS_CONFIRMATION; |
---|
913 | return 0; |
---|
914 | } |
---|
915 | } |
---|
916 | |
---|
917 | |
---|
918 | /* Commit all the changes in this toc; all messages will meet their 'fate'. */ |
---|
919 | |
---|
920 | /*ARGSUSED*/ |
---|
921 | void TocCommitChanges(widget, client_data, call_data) |
---|
922 | Widget widget; /* unused */ |
---|
923 | XtPointer client_data; |
---|
924 | XtPointer call_data; /* unused */ |
---|
925 | { |
---|
926 | Toc toc = (Toc) client_data; |
---|
927 | Msg msg; |
---|
928 | int i, cur; |
---|
929 | char str[100], **argv; |
---|
930 | FateType curfate, fate; |
---|
931 | Toc desttoc; |
---|
932 | Toc curdesttoc; |
---|
933 | XtCallbackRec confirms[2]; |
---|
934 | |
---|
935 | confirms[0].callback = TocCommitChanges; |
---|
936 | confirms[0].closure = (XtPointer) toc; |
---|
937 | confirms[1].callback = (XtCallbackProc) NULL; |
---|
938 | confirms[1].closure = (XtPointer) NULL; |
---|
939 | |
---|
940 | if (toc == NULL) return; |
---|
941 | for (i=0 ; i<toc->nummsgs ; i++) { |
---|
942 | msg = toc->msgs[i]; |
---|
943 | fate = MsgGetFate(msg, (Toc *)NULL); |
---|
944 | if (fate != Fignore && fate != Fcopy) |
---|
945 | if (MsgSetScrn(msg, (Scrn) NULL, confirms, (XtCallbackList) NULL) |
---|
946 | == NEEDS_CONFIRMATION) |
---|
947 | return; |
---|
948 | } |
---|
949 | XFlush(XtDisplay(toc->scrn[0]->parent)); |
---|
950 | for (i=0 ; i<numFolders ; i++) |
---|
951 | TocStopUpdate(folderList[i]); |
---|
952 | toc->haschanged = TRUE; |
---|
953 | if (app_resources.block_events_on_busy) ShowBusyCursor(); |
---|
954 | |
---|
955 | do { |
---|
956 | curfate = Fignore; |
---|
957 | i = 0; |
---|
958 | while (i < toc->nummsgs) { |
---|
959 | msg = toc->msgs[i]; |
---|
960 | fate = MsgGetFate(msg, &desttoc); |
---|
961 | if (curfate == Fignore && fate != Fignore) { |
---|
962 | curfate = fate; |
---|
963 | argv = MakeArgv(2); |
---|
964 | switch (curfate) { |
---|
965 | case Fdelete: |
---|
966 | argv[0] = XtNewString("rmm"); |
---|
967 | argv[1] = TocMakeFolderName(toc); |
---|
968 | cur = 2; |
---|
969 | curdesttoc = NULL; |
---|
970 | break; |
---|
971 | case Fmove: |
---|
972 | case Fcopy: |
---|
973 | argv[0] = XtNewString("refile"); |
---|
974 | cur = 1; |
---|
975 | curdesttoc = desttoc; |
---|
976 | break; |
---|
977 | } |
---|
978 | } |
---|
979 | if (curfate != Fignore && |
---|
980 | curfate == fate && desttoc == curdesttoc) { |
---|
981 | argv = ResizeArgv(argv, cur + 1); |
---|
982 | (void) sprintf(str, "%d", MsgGetId(msg)); |
---|
983 | argv[cur++] = XtNewString(str); |
---|
984 | MsgSetFate(msg, Fignore, (Toc)NULL); |
---|
985 | if (curdesttoc) { |
---|
986 | (void) TUAppendToc(curdesttoc, MsgGetScanLine(msg)); |
---|
987 | curdesttoc->haschanged = TRUE; |
---|
988 | } |
---|
989 | if (curfate != Fcopy) { |
---|
990 | TocRemoveMsg(toc, msg); |
---|
991 | MsgFree(msg); |
---|
992 | i--; |
---|
993 | } |
---|
994 | if (cur > 40) |
---|
995 | break; /* Do only 40 at a time, just to be safe. */ |
---|
996 | } |
---|
997 | i++; |
---|
998 | } |
---|
999 | if (curfate != Fignore) { |
---|
1000 | switch (curfate) { |
---|
1001 | case Fmove: |
---|
1002 | case Fcopy: |
---|
1003 | argv = ResizeArgv(argv, cur + 4); |
---|
1004 | argv[cur++] = XtNewString(curfate == Fmove ? "-nolink" |
---|
1005 | : "-link"); |
---|
1006 | argv[cur++] = XtNewString("-src"); |
---|
1007 | argv[cur++] = TocMakeFolderName(toc); |
---|
1008 | argv[cur++] = TocMakeFolderName(curdesttoc); |
---|
1009 | break; |
---|
1010 | } |
---|
1011 | if (app_resources.debug) { |
---|
1012 | for (i = 0; i < cur; i++) |
---|
1013 | (void) fprintf(stderr, "%s ", argv[i]); |
---|
1014 | (void) fprintf(stderr, "\n"); |
---|
1015 | (void) fflush(stderr); |
---|
1016 | } |
---|
1017 | DoCommand(argv, (char *) NULL, (char *) NULL); |
---|
1018 | for (i = 0; argv[i]; i++) |
---|
1019 | XtFree((char *) argv[i]); |
---|
1020 | XtFree((char *) argv); |
---|
1021 | } |
---|
1022 | } while (curfate != Fignore); |
---|
1023 | for (i=0 ; i<numFolders ; i++) { |
---|
1024 | if (folderList[i]->haschanged) { |
---|
1025 | TocReloadSeqLists(folderList[i]); |
---|
1026 | folderList[i]->haschanged = FALSE; |
---|
1027 | } |
---|
1028 | TocStartUpdate(folderList[i]); |
---|
1029 | } |
---|
1030 | |
---|
1031 | if (app_resources.block_events_on_busy) UnshowBusyCursor(); |
---|
1032 | } |
---|
1033 | |
---|
1034 | |
---|
1035 | |
---|
1036 | /* Return whether the given toc can incorporate mail. */ |
---|
1037 | |
---|
1038 | int TocCanIncorporate(toc) |
---|
1039 | Toc toc; |
---|
1040 | { |
---|
1041 | return (toc && (toc == InitialFolder || toc->incfile)); |
---|
1042 | } |
---|
1043 | |
---|
1044 | |
---|
1045 | /* Incorporate new messages into the given toc. */ |
---|
1046 | |
---|
1047 | int TocIncorporate(toc) |
---|
1048 | Toc toc; |
---|
1049 | { |
---|
1050 | char **argv; |
---|
1051 | char str[100], *file, *ptr; |
---|
1052 | Msg msg, firstmessage = NULL; |
---|
1053 | FILEPTR fid; |
---|
1054 | |
---|
1055 | argv = MakeArgv(toc->incfile ? 7 : 4); |
---|
1056 | argv[0] = "inc"; |
---|
1057 | argv[1] = TocMakeFolderName(toc); |
---|
1058 | argv[2] = "-width"; |
---|
1059 | (void) sprintf(str, "%d", app_resources.toc_width); |
---|
1060 | argv[3] = str; |
---|
1061 | if (toc->incfile) { |
---|
1062 | argv[4] = "-file"; |
---|
1063 | argv[5] = toc->incfile; |
---|
1064 | argv[6] = "-truncate"; |
---|
1065 | } |
---|
1066 | if (app_resources.block_events_on_busy) ShowBusyCursor(); |
---|
1067 | |
---|
1068 | file = DoCommandToFile(argv); |
---|
1069 | XtFree(argv[1]); |
---|
1070 | XtFree((char *)argv); |
---|
1071 | TUGetFullFolderInfo(toc); |
---|
1072 | if (toc->validity == valid) { |
---|
1073 | fid = FOpenAndCheck(file, "r"); |
---|
1074 | TocStopUpdate(toc); |
---|
1075 | while (ptr = ReadLineWithCR(fid)) { |
---|
1076 | if (atoi(ptr) > 0) { |
---|
1077 | msg = TUAppendToc(toc, ptr); |
---|
1078 | if (firstmessage == NULL) firstmessage = msg; |
---|
1079 | } |
---|
1080 | } |
---|
1081 | if (firstmessage && firstmessage->visible) { |
---|
1082 | TocSetCurMsg(toc, firstmessage); |
---|
1083 | } |
---|
1084 | TocStartUpdate(toc); |
---|
1085 | (void) myfclose(fid); |
---|
1086 | } |
---|
1087 | DeleteFileAndCheck(file); |
---|
1088 | |
---|
1089 | if (app_resources.block_events_on_busy) UnshowBusyCursor(); |
---|
1090 | |
---|
1091 | toc->mailpending = False; |
---|
1092 | return (firstmessage != NULL); |
---|
1093 | } |
---|
1094 | |
---|
1095 | |
---|
1096 | /* The given message has changed. Rescan it and change the scanfile. */ |
---|
1097 | |
---|
1098 | void TocMsgChanged(toc, msg) |
---|
1099 | Toc toc; |
---|
1100 | Msg msg; |
---|
1101 | { |
---|
1102 | char **argv, str[100], str2[10], *ptr; |
---|
1103 | int length, delta, i; |
---|
1104 | FateType fate; |
---|
1105 | Toc desttoc; |
---|
1106 | if (toc->validity != valid) return; |
---|
1107 | fate = MsgGetFate(msg, &desttoc); |
---|
1108 | MsgSetFate(msg, Fignore, (Toc) NULL); |
---|
1109 | argv = MakeArgv(6); |
---|
1110 | argv[0] = "scan"; |
---|
1111 | argv[1] = TocMakeFolderName(toc); |
---|
1112 | (void) sprintf(str, "%d", msg->msgid); |
---|
1113 | argv[2] = str; |
---|
1114 | argv[3] = "-width"; |
---|
1115 | (void) sprintf(str2, "%d", app_resources.toc_width); |
---|
1116 | argv[4] = str2; |
---|
1117 | argv[5] = "-noheader"; |
---|
1118 | ptr = DoCommandToString(argv); |
---|
1119 | XtFree(argv[1]); |
---|
1120 | XtFree((char *) argv); |
---|
1121 | if (strcmp(ptr, msg->buf) != 0) { |
---|
1122 | length = strlen(ptr); |
---|
1123 | delta = length - msg->length; |
---|
1124 | XtFree(msg->buf); |
---|
1125 | msg->buf = ptr; |
---|
1126 | msg->length = length; |
---|
1127 | toc->length += delta; |
---|
1128 | if (msg->visible) { |
---|
1129 | if (delta != 0) { |
---|
1130 | for (i=TUGetMsgPosition(toc, msg)+1; i<toc->nummsgs ; i++) |
---|
1131 | toc->msgs[i]->position += delta; |
---|
1132 | toc->lastPos += delta; |
---|
1133 | } |
---|
1134 | for (i=0 ; i<toc->num_scrns ; i++) |
---|
1135 | TURedisplayToc(toc->scrn[i]); |
---|
1136 | } |
---|
1137 | MsgSetFate(msg, fate, desttoc); |
---|
1138 | TUSaveTocFile(toc); |
---|
1139 | } else XtFree(ptr); |
---|
1140 | } |
---|
1141 | |
---|
1142 | |
---|
1143 | |
---|
1144 | Msg TocMsgFromId(toc, msgid) |
---|
1145 | Toc toc; |
---|
1146 | int msgid; |
---|
1147 | { |
---|
1148 | int h, l, m; |
---|
1149 | l = 0; |
---|
1150 | h = toc->nummsgs - 1; |
---|
1151 | if (h < 0) { |
---|
1152 | if (app_resources.debug) { |
---|
1153 | char str[100]; |
---|
1154 | (void)sprintf(str, "Toc is empty! folder=%s\n", toc->foldername); |
---|
1155 | DEBUG( str ) |
---|
1156 | } |
---|
1157 | return NULL; |
---|
1158 | } |
---|
1159 | while (l < h - 1) { |
---|
1160 | m = (l + h) / 2; |
---|
1161 | if (toc->msgs[m]->msgid > msgid) |
---|
1162 | h = m; |
---|
1163 | else |
---|
1164 | l = m; |
---|
1165 | } |
---|
1166 | if (toc->msgs[l]->msgid == msgid) return toc->msgs[l]; |
---|
1167 | if (toc->msgs[h]->msgid == msgid) return toc->msgs[h]; |
---|
1168 | if (app_resources.debug) { |
---|
1169 | char str[100]; |
---|
1170 | (void) sprintf(str, |
---|
1171 | "TocMsgFromId search failed! hi=%d, lo=%d, msgid=%d\n", |
---|
1172 | h, l, msgid); |
---|
1173 | DEBUG( str ) |
---|
1174 | } |
---|
1175 | return NULL; |
---|
1176 | } |
---|
1177 | |
---|
1178 | /* Sequence names are put on a stack which is specific to the folder. |
---|
1179 | * Sequence names are very volatile, so we make our own copies of the strings. |
---|
1180 | */ |
---|
1181 | |
---|
1182 | /*ARGSUSED*/ |
---|
1183 | void XmhPushSequence(w, event, params, count) |
---|
1184 | Widget w; |
---|
1185 | XEvent *event; |
---|
1186 | String *params; |
---|
1187 | Cardinal *count; |
---|
1188 | { |
---|
1189 | Scrn scrn = ScrnFromWidget(w); |
---|
1190 | Toc toc; |
---|
1191 | int i; |
---|
1192 | |
---|
1193 | if (! (toc = scrn->toc)) return; |
---|
1194 | |
---|
1195 | if (*count == 0) { |
---|
1196 | if (toc->selectseq) |
---|
1197 | Push(&toc->sequence_stack, XtNewString(toc->selectseq->name)); |
---|
1198 | } |
---|
1199 | else |
---|
1200 | for (i=0; i < *count; i++) |
---|
1201 | Push(&toc->sequence_stack, XtNewString(params[i])); |
---|
1202 | } |
---|
1203 | |
---|
1204 | |
---|
1205 | /*ARGSUSED*/ |
---|
1206 | void XmhPopSequence(w, event, params, count) |
---|
1207 | Widget w; /* any widget on the screen of interest */ |
---|
1208 | XEvent *event; |
---|
1209 | String *params; |
---|
1210 | Cardinal *count; |
---|
1211 | { |
---|
1212 | Scrn scrn = ScrnFromWidget(w); |
---|
1213 | char *seqname; |
---|
1214 | Widget sequenceMenu, selected, original; |
---|
1215 | Button button; |
---|
1216 | Sequence sequence; |
---|
1217 | |
---|
1218 | if ((seqname = Pop(&scrn->toc->sequence_stack)) != NULL) { |
---|
1219 | |
---|
1220 | button = BBoxFindButtonNamed(scrn->mainbuttons, |
---|
1221 | MenuBoxButtons[XMH_SEQUENCE].button_name); |
---|
1222 | sequenceMenu = BBoxMenuOfButton(button); |
---|
1223 | |
---|
1224 | if (selected = XawSimpleMenuGetActiveEntry(sequenceMenu)) |
---|
1225 | ToggleMenuItem(selected, False); |
---|
1226 | |
---|
1227 | if (original = XtNameToWidget(sequenceMenu, seqname)) { |
---|
1228 | ToggleMenuItem(original, True); |
---|
1229 | sequence = TocGetSeqNamed(scrn->toc, seqname); |
---|
1230 | TocSetSelectedSequence(scrn->toc, sequence); |
---|
1231 | } |
---|
1232 | XtFree(seqname); |
---|
1233 | } |
---|
1234 | } |
---|