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