|
|
1.1 ! root 1: #ifndef lint ! 2: static char rcs_id[] = "$Header: toc.c,v 1.17 87/08/06 13:23:54 toddb Exp $"; ! 3: #endif lint ! 4: /* ! 5: * COPYRIGHT 1987 ! 6: * DIGITAL EQUIPMENT CORPORATION ! 7: * MAYNARD, MASSACHUSETTS ! 8: * ALL RIGHTS RESERVED. ! 9: * ! 10: * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND ! 11: * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ! 12: * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ! 13: * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ! 14: * ! 15: * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, ! 16: * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT ! 17: * SET FORTH ABOVE. ! 18: * ! 19: * ! 20: * Permission to use, copy, modify, and distribute this software and its ! 21: * documentation for any purpose and without fee is hereby granted, provided ! 22: * that the above copyright notice appear in all copies and that both that ! 23: * copyright notice and this permission notice appear in supporting documentation, ! 24: * and that the name of Digital Equipment Corporation not be used in advertising ! 25: * or publicity pertaining to distribution of the software without specific, ! 26: * written prior permission. ! 27: */ ! 28: ! 29: /* toc.c -- handle things in the toc window. */ ! 30: ! 31: #include "xmh.h" ! 32: #include "tocintrnl.h" ! 33: #include "toc.h" ! 34: #include "tocutil.h" ! 35: #include <sys/stat.h> ! 36: #include <sys/dir.h> ! 37: ! 38: /* PUBLIC ROUTINES */ ! 39: ! 40: ! 41: static int IsDir(ent) ! 42: struct direct *ent; ! 43: { ! 44: char str[500]; ! 45: struct stat buf; ! 46: if (ent->d_name[0] == '.') ! 47: return FALSE; ! 48: (void) sprintf(str, "%s/%s", mailDir, ent->d_name); ! 49: (void) stat(str, &buf); ! 50: return (buf.st_mode & S_IFMT) == S_IFDIR; ! 51: } ! 52: ! 53: ! 54: ! 55: static void MakeSureFolderExists(namelistptr, numfoldersptr, name) ! 56: struct direct ***namelistptr; ! 57: int *numfoldersptr; ! 58: char *name; ! 59: { ! 60: int i; ! 61: extern alphasort(); ! 62: char str[200]; ! 63: for (i=0 ; i<*numfoldersptr ; i++) ! 64: if (strcmp((*namelistptr)[i]->d_name, name) == 0) return; ! 65: (void) sprintf(str, "%s/%s", mailDir, name); ! 66: (void) mkdir(str, 0700); ! 67: *numfoldersptr = scandir(mailDir, namelistptr, IsDir, alphasort); ! 68: for (i=0 ; i<*numfoldersptr ; i++) ! 69: if (strcmp((*namelistptr)[i]->d_name, name) == 0) return; ! 70: Punt("Can't create new mail folder!"); ! 71: } ! 72: ! 73: ! 74: static void LoadCheckFiles() ! 75: { ! 76: FILE *fid; ! 77: char str[1024], *ptr, *ptr2; ! 78: int i; ! 79: (void) sprintf(str, "%s/.xmhcheck", homeDir); ! 80: fid = myfopen(str, "r"); ! 81: if (fid) { ! 82: while (ptr = ReadLine(fid)) { ! 83: while (*ptr == ' ' || *ptr == '\t') ptr++; ! 84: ptr2 = ptr; ! 85: while (*ptr2 && *ptr2 != ' ' && *ptr2 != '\t') ptr2++; ! 86: if (*ptr2 == 0) continue; ! 87: *ptr2++ = 0; ! 88: while (*ptr2 == ' ' || *ptr2 == '\t') ptr2++; ! 89: if (*ptr2 == 0) continue; ! 90: for (i=0 ; i<numFolders ; i++) { ! 91: if (strcmp(ptr, folderList[i]->foldername) == 0) { ! 92: folderList[i]->incfile = MallocACopy(ptr2); ! 93: break; ! 94: } ! 95: } ! 96: } ! 97: myfclose(fid); ! 98: } else if (initialIncFile) { ! 99: if (*initialIncFile != '\0') ! 100: InitialFolder->incfile = initialIncFile; ! 101: } else { ! 102: ptr = getenv("MAIL"); ! 103: if (ptr == NULL) ptr = getenv("mail"); ! 104: if (ptr == NULL) { ! 105: ptr = getenv("USER"); ! 106: if (ptr) { ! 107: (void) sprintf(str, "/usr/spool/mail/%s", ptr); ! 108: ptr = str; ! 109: } ! 110: } ! 111: if (ptr) ! 112: InitialFolder->incfile = MallocACopy(ptr); ! 113: } ! 114: } ! 115: ! 116: ! 117: ! 118: ! 119: /* Read in the list of folders. */ ! 120: ! 121: void TocInit() ! 122: { ! 123: Toc toc; ! 124: struct direct **namelist; ! 125: int i; ! 126: extern alphasort(); ! 127: numFolders = scandir(mailDir, &namelist, IsDir, alphasort); ! 128: if (numFolders < 0) { ! 129: (void) mkdir(mailDir, 0700); ! 130: numFolders = scandir(mailDir, &namelist, IsDir, alphasort); ! 131: if (numFolders < 0) ! 132: Punt("Can't create or read mail directory!"); ! 133: } ! 134: MakeSureFolderExists(&namelist, &numFolders, initialFolderName); ! 135: MakeSureFolderExists(&namelist, &numFolders, draftsFolderName); ! 136: folderList = (Toc *) XtMalloc((unsigned) numFolders * sizeof(Toc)); ! 137: for (i=0 ; i<numFolders ; i++) { ! 138: toc = folderList[i] = TUMalloc(); ! 139: toc->foldername = MallocACopy(namelist[i]->d_name); ! 140: XtFree((char *)namelist[i]); ! 141: } ! 142: InitialFolder = TocGetNamed(initialFolderName); ! 143: DraftsFolder = TocGetNamed(draftsFolderName); ! 144: XtFree((char *)namelist); ! 145: if (defNewMailCheck) LoadCheckFiles(); ! 146: } ! 147: ! 148: ! 149: /* Create a new folder with the given name. */ ! 150: ! 151: Toc TocCreateFolder(foldername) ! 152: char *foldername; ! 153: { ! 154: Toc toc; ! 155: int i, j; ! 156: char str[500]; ! 157: if (TocGetNamed(foldername)) return NULL; ! 158: (void) sprintf(str, "%s/%s", mailDir, foldername); ! 159: if (mkdir(str, 0700) < 0) return NULL; ! 160: toc = TUMalloc(); ! 161: toc->foldername = MallocACopy(foldername); ! 162: for (i=0 ; i<numFolders ; i++) ! 163: if (strcmp(foldername, folderList[i]->foldername) < 0) break; ! 164: folderList = (Toc *) XtRealloc((char *) folderList, ! 165: (unsigned) ++numFolders * sizeof(Toc)); ! 166: for (j=numFolders - 1 ; j > i ; j--) ! 167: folderList[j] = folderList[j-1]; ! 168: folderList[i] = toc; ! 169: return toc; ! 170: } ! 171: ! 172: ! 173: ! 174: /* Check to see if what folders have new mail, and highlight their ! 175: folderbuttons appropriately. */ ! 176: ! 177: void TocCheckForNewMail() ! 178: { ! 179: #ifdef X11 ! 180: Toc toc; ! 181: Scrn scrn; ! 182: int i, j, hasmail; ! 183: if (!defNewMailCheck) return; ! 184: for (i=0 ; i<numFolders ; i++) { ! 185: toc = folderList[i]; ! 186: if (toc->incfile) { ! 187: hasmail = (GetFileLength(toc->incfile) > 0); ! 188: if (hasmail != toc->mailpending) { ! 189: toc->mailpending = hasmail; ! 190: for (j=0 ; j<numScrns ; j++) { ! 191: scrn = scrnList[j]; ! 192: if (scrn->kind == STtocAndView) { ! 193: if (toc == InitialFolder) { ! 194: scrn->hints.icon_pixmap = ! 195: hasmail ? NewMailPixmap : NoMailPixmap; ! 196: XSetWMHints(theDisplay, scrn->window, ! 197: &(scrn->hints)); ! 198: } else { ! 199: BBoxChangeBorderWidth( /* %%% HACK */ ! 200: BBoxButtonNumber(scrnList[j]->folderbuttons, i), ! 201: (unsigned)(hasmail ? 2 : 1)); ! 202: } ! 203: } ! 204: } ! 205: } ! 206: } ! 207: } ! 208: #endif X11 ! 209: } ! 210: ! 211: ! 212: /* Recursively delete an entire directory. Nasty. */ ! 213: ! 214: static void NukeDirectory(path) ! 215: char *path; ! 216: { ! 217: char str[500]; ! 218: (void) sprintf(str, "rm -rf %s", path); ! 219: (void) system(str); ! 220: } ! 221: ! 222: ! 223: ! 224: /* Destroy the given folder. */ ! 225: ! 226: void TocDeleteFolder(toc) ! 227: Toc toc; ! 228: { ! 229: Toc toc2; ! 230: int i, j, w; ! 231: TUGetFullFolderInfo(toc); ! 232: if (TocConfirmCataclysm(toc)) return; ! 233: TocSetScrn(toc, (Scrn) NULL); ! 234: w = -1; ! 235: for (i=0 ; i<numFolders ; i++) { ! 236: toc2 = folderList[i]; ! 237: if (toc2 == toc) ! 238: w = i; ! 239: else if (toc2->validity == valid) ! 240: for (j=0 ; j<toc2->nummsgs ; j++) ! 241: if (toc2->msgs[j]->desttoc == toc) ! 242: MsgSetFate(toc2->msgs[j], Fignore, (Toc) NULL); ! 243: } ! 244: if (w < 0) Punt("Couldn't find it in TocDeleteFolder!"); ! 245: NukeDirectory(toc->path); ! 246: if (toc->validity == valid) { ! 247: for (i=0 ; i<toc->nummsgs ; i++) { ! 248: MsgSetScrnForce(toc->msgs[i], (Scrn) NULL); ! 249: MsgFree(toc->msgs[i]); ! 250: } ! 251: XtFree((char *) toc->msgs); ! 252: } ! 253: XtFree((char *)toc); ! 254: numFolders--; ! 255: for (i=w ; i<numFolders ; i++) folderList[i] = folderList[i+1]; ! 256: } ! 257: ! 258: ! 259: ! 260: /* Display the given toc in the given scrn. */ ! 261: ! 262: void TocSetScrn(toc, scrn) ! 263: Toc toc; ! 264: Scrn scrn; ! 265: { ! 266: if (toc == NULL && scrn == NULL) return; ! 267: if (scrn && scrn->toc != NULL) ! 268: TocSetScrn(scrn->toc, (Scrn) NULL); ! 269: if (toc == NULL) return; ! 270: if (toc->scrn == scrn) return; ! 271: if (toc->scrn) { ! 272: toc->scrn->toc = NULL; ! 273: TUResetTocLabel(toc->scrn); ! 274: TURedisplayToc(toc->scrn); ! 275: QXStoreName(theDisplay, toc->scrn->window, progName); ! 276: EnableProperButtons(toc->scrn); ! 277: toc->scrn = NULL; ! 278: if (scrn == NULL) return; ! 279: } ! 280: ! 281: scrn->toc = toc; ! 282: toc->scrn = scrn; ! 283: ! 284: TUEnsureScanIsValidAndOpen(toc); ! 285: TUResetTocLabel(scrn); ! 286: QXStoreName(theDisplay, toc->scrn->window, toc->foldername); ! 287: TURedisplayToc(toc->scrn); ! 288: ! 289: BBoxSetRadio(scrn->folderbuttons, ! 290: BBoxFindButtonNamed(scrn->folderbuttons, toc->foldername)); ! 291: ! 292: EnableProperButtons(scrn); ! 293: ! 294: return; ! 295: } ! 296: ! 297: ! 298: ! 299: /* Remove the given message from the toc. Doesn't actually touch the file. ! 300: Also note that it does not free the storage for the msg. */ ! 301: ! 302: void TocRemoveMsg(toc, msg) ! 303: Toc toc; ! 304: Msg msg; ! 305: { ! 306: Msg newcurmsg; ! 307: MsgList mlist; ! 308: int i; ! 309: if (toc->validity == unknown) ! 310: TUGetFullFolderInfo(toc); ! 311: if (toc->validity != valid) ! 312: return; ! 313: newcurmsg = TocMsgAfter(toc, msg); ! 314: if (newcurmsg) newcurmsg->changed = TRUE; ! 315: newcurmsg = toc->curmsg; ! 316: if (msg == toc->curmsg) { ! 317: newcurmsg = TocMsgAfter(toc, msg); ! 318: if (newcurmsg == NULL) newcurmsg = TocMsgBefore(toc, msg); ! 319: toc->curmsg = NULL; ! 320: } ! 321: toc->length -= msg->length; ! 322: if (msg->visible) toc->lastPos -= msg->length; ! 323: for(i = TUGetMsgPosition(toc, msg), toc->nummsgs--; i<toc->nummsgs ; i++) { ! 324: toc->msgs[i] = toc->msgs[i+1]; ! 325: if (msg->visible) toc->msgs[i]->position -= msg->length; ! 326: } ! 327: for (i=0 ; i<toc->numsequences ; i++) { ! 328: mlist = toc->seqlist[i]->mlist; ! 329: if (mlist) DeleteMsgFromMsgList(mlist, msg); ! 330: } ! 331: ! 332: if (msg->visible) TURedisplayToc(toc->scrn); ! 333: TocSetCurMsg(toc, newcurmsg); ! 334: TUSaveTocFile(toc); ! 335: } ! 336: ! 337: ! 338: ! 339: void TocRecheckValidity(toc) ! 340: Toc toc; ! 341: { ! 342: if (toc && toc->validity == valid && TUScanFileOutOfDate(toc)) { ! 343: TUScanFileForToc(toc); ! 344: if (toc->source) ! 345: TULoadTocFile(toc); ! 346: TURedisplayToc(toc->scrn); ! 347: } ! 348: } ! 349: ! 350: ! 351: /* Set the current message. */ ! 352: ! 353: void TocSetCurMsg(toc, msg) ! 354: Toc toc; ! 355: Msg msg; ! 356: { ! 357: Msg msg2; ! 358: if (toc->validity != valid) return; ! 359: if (msg != toc->curmsg) { ! 360: msg2 = toc->curmsg; ! 361: toc->curmsg = msg; ! 362: if (msg2) ! 363: MsgSetFate(msg2, msg2->fate, msg2->desttoc); ! 364: } ! 365: if (msg) { ! 366: MsgSetFate(msg, msg->fate, msg->desttoc); ! 367: if (toc->scrn) { ! 368: if (toc->stopupdate) ! 369: toc->needsrepaint = TRUE; ! 370: else ! 371: XtTextSetInsertionPoint(DISPLAY toc->scrn->tocwindow, ! 372: msg->position); ! 373: } ! 374: } ! 375: } ! 376: ! 377: ! 378: /* Return the current message. */ ! 379: ! 380: Msg TocGetCurMsg(toc) ! 381: Toc toc; ! 382: { ! 383: return toc->curmsg; ! 384: } ! 385: ! 386: ! 387: ! 388: ! 389: /* Return the message after the given one. (If none, return NULL.) */ ! 390: ! 391: Msg TocMsgAfter(toc, msg) ! 392: Toc toc; ! 393: Msg msg; ! 394: { ! 395: int i; ! 396: i = TUGetMsgPosition(toc, msg); ! 397: do { ! 398: i++; ! 399: if (i >= toc->nummsgs) ! 400: return NULL; ! 401: } while (!(toc->msgs[i]->visible)); ! 402: return toc->msgs[i]; ! 403: } ! 404: ! 405: ! 406: ! 407: /* Return the message before the given one. (If none, return NULL.) */ ! 408: ! 409: Msg TocMsgBefore(toc, msg) ! 410: Toc toc; ! 411: Msg msg; ! 412: { ! 413: int i; ! 414: i = TUGetMsgPosition(toc, msg); ! 415: do { ! 416: i--; ! 417: if (i < 0) ! 418: return NULL; ! 419: } while (!(toc->msgs[i]->visible)); ! 420: return toc->msgs[i]; ! 421: } ! 422: ! 423: ! 424: ! 425: /* The caller KNOWS the toc's information is out of date; rescan it. */ ! 426: ! 427: void TocForceRescan(toc) ! 428: Toc toc; ! 429: { ! 430: if (toc->scrn) { ! 431: toc->viewedseq = toc->seqlist[0]; ! 432: TUResetTocLabel(toc->scrn); ! 433: TUScanFileForToc(toc); ! 434: TULoadTocFile(toc); ! 435: TURedisplayToc(toc->scrn); ! 436: } else { ! 437: TUGetFullFolderInfo(toc); ! 438: (void) unlink(toc->scanfile); ! 439: toc->validity = invalid; ! 440: } ! 441: } ! 442: ! 443: ! 444: ! 445: /* The caller has just changed a sequence list. Reread them from mh. */ ! 446: ! 447: void TocReloadSeqLists(toc) ! 448: Toc toc; ! 449: { ! 450: TocSetCacheValid(toc); ! 451: TULoadSeqLists(toc); ! 452: TURefigureWhatsVisible(toc); ! 453: TUResetTocLabel(toc->scrn); ! 454: EnableProperButtons(toc->scrn); ! 455: } ! 456: ! 457: ! 458: /* Return TRUE if the toc has an interesting sequence. */ ! 459: ! 460: int TocHasSequences(toc) ! 461: Toc toc; ! 462: { ! 463: return toc && toc->numsequences > 1; ! 464: } ! 465: ! 466: ! 467: /* Change which sequence is being viewed. */ ! 468: ! 469: void TocChangeViewedSeq(toc, seq) ! 470: Toc toc; ! 471: Sequence seq; ! 472: { ! 473: if (seq == NULL) seq = toc->viewedseq; ! 474: toc->viewedseq = seq; ! 475: TURefigureWhatsVisible(toc); ! 476: if (toc->scrn && toc->scrn->seqbuttons) ! 477: BBoxSetRadio(toc->scrn->seqbuttons, ! 478: BBoxFindButtonNamed(toc->scrn->seqbuttons, seq->name)); ! 479: TUResetTocLabel(toc->scrn); ! 480: } ! 481: ! 482: ! 483: /* Return the sequence with the given name in the given toc. */ ! 484: ! 485: Sequence TocGetSeqNamed(toc, name) ! 486: Toc toc; ! 487: char *name; ! 488: { ! 489: int i; ! 490: for (i=0 ; i<toc->numsequences ; i++) ! 491: if (strcmp(toc->seqlist[i]->name, name) == 0) ! 492: return toc->seqlist[i]; ! 493: return (Sequence) NULL; ! 494: } ! 495: ! 496: ! 497: /* Return the sequence currently being viewed in the toc. */ ! 498: ! 499: Sequence TocViewedSequence(toc) ! 500: Toc toc; ! 501: { ! 502: return toc->viewedseq; ! 503: } ! 504: ! 505: ! 506: /* Return the list of messages currently selected. */ ! 507: ! 508: MsgList TocCurMsgList(toc) ! 509: Toc toc; ! 510: { ! 511: MsgList result; ! 512: XtTextPosition pos1, pos2; ! 513: extern Msg MsgFromPosition(); ! 514: if (toc->scrn == NULL) return NULL; ! 515: result = MakeNullMsgList(); ! 516: XtTextGetSelectionPos(DISPLAY toc->scrn->tocwindow, &pos1, &pos2); ! 517: if (pos1 < pos2) { ! 518: pos1 = toc->source->scan(toc->source, pos1, XtstEOL, XtsdLeft, ! 519: 1, FALSE); ! 520: pos2 = toc->source->scan(toc->source, pos2, XtstPositions, XtsdLeft, ! 521: 1, TRUE); ! 522: pos2 = toc->source->scan(toc->source, pos2, XtstEOL, XtsdRight, ! 523: 1, FALSE); ! 524: while (pos1 < pos2) { ! 525: AppendMsgList(result, MsgFromPosition(toc, pos1, XtsdRight)); ! 526: pos1 = toc->source->scan(toc->source, pos1, XtstEOL, XtsdRight, ! 527: 1, TRUE); ! 528: } ! 529: } ! 530: return result; ! 531: } ! 532: ! 533: ! 534: ! 535: /* Unset the current selection. */ ! 536: ! 537: void TocUnsetSelection(toc) ! 538: Toc toc; ! 539: { ! 540: if (toc->scrn) ! 541: XtTextUnsetSelection(DISPLAY toc->scrn->tocwindow); ! 542: } ! 543: ! 544: ! 545: ! 546: /* Create a brand new, blank message. */ ! 547: ! 548: Msg TocMakeNewMsg(toc) ! 549: Toc toc; ! 550: { ! 551: Msg msg; ! 552: TUEnsureScanIsValidAndOpen(toc); ! 553: msg = TUAppendToc(toc, "#### empty\n"); ! 554: if (FileExists(MsgFileName(msg))) { ! 555: if (debug) (void) fprintf(stderr, "**** FOLDER %s WAS INVALID!!!\n", ! 556: toc->foldername); ! 557: TocForceRescan(toc); ! 558: return TocMakeNewMsg(toc); /* Try again. Using recursion here is ugly, ! 559: but what the hack ... */ ! 560: } ! 561: CopyFileAndCheck("/dev/null", MsgFileName(msg)); ! 562: return msg; ! 563: } ! 564: ! 565: ! 566: /* Set things to not update cache or display until further notice. */ ! 567: ! 568: void TocStopUpdate(toc) ! 569: Toc toc; ! 570: { ! 571: toc->stopupdate++; ! 572: } ! 573: ! 574: ! 575: /* Start updating again, and do whatever updating has been queued. */ ! 576: ! 577: void TocStartUpdate(toc) ! 578: Toc toc; ! 579: { ! 580: if (toc->stopupdate && --(toc->stopupdate) == 0) { ! 581: if (toc->needsrepaint) ! 582: TURedisplayToc(toc->scrn); ! 583: if (toc->needslabelupdate) ! 584: TUResetTocLabel(toc->scrn); ! 585: if (toc->needscachesave) ! 586: TUSaveTocFile(toc); ! 587: } ! 588: } ! 589: ! 590: ! 591: ! 592: /* Something has happened that could later convince us that our cache is out ! 593: of date. Make this not happen; our cache really *is* up-to-date. */ ! 594: ! 595: void TocSetCacheValid(toc) ! 596: Toc toc; ! 597: { ! 598: TUSaveTocFile(toc); ! 599: } ! 600: ! 601: ! 602: /* Return the foldername of the given toc. */ ! 603: ! 604: char *TocGetFolderName(toc) ! 605: Toc toc; ! 606: { ! 607: return toc->foldername; ! 608: } ! 609: ! 610: ! 611: ! 612: /* Given a foldername, return the corresponding toc. */ ! 613: ! 614: Toc TocGetNamed(name) ! 615: char *name; ! 616: { ! 617: int i; ! 618: for (i=0; i<numFolders ; i++) ! 619: if (strcmp(folderList[i]->foldername, name) == 0) return folderList[i]; ! 620: return NULL; ! 621: } ! 622: ! 623: ! 624: ! 625: /* Throw out all changes to this toc, and close all views of msgs in it. ! 626: Requires confirmation by the user. */ ! 627: ! 628: int TocConfirmCataclysm(toc) ! 629: Toc toc; ! 630: { ! 631: int i; ! 632: int found = FALSE; ! 633: char str[500]; ! 634: for (i=0 ; i<toc->nummsgs && !found ; i++) ! 635: if (toc->msgs[i]->fate != Fignore) found = TRUE; ! 636: if (found) { ! 637: (void)sprintf(str,"Are you sure you want to remove all changes to %s?", ! 638: toc->foldername); ! 639: if (!Confirm(toc->scrn, str)) ! 640: return DELETEABORTED; ! 641: } ! 642: for (i=0 ; i<toc->nummsgs ; i++) ! 643: MsgSetFate(toc->msgs[i], Fignore, (Toc)NULL); ! 644: for (i=0 ; i<toc->nummsgs ; i++) ! 645: if (MsgSetScrn(toc->msgs[i], (Scrn) NULL)) return DELETEABORTED; ! 646: return 0; ! 647: } ! 648: ! 649: ! 650: ! 651: /* Commit all the changes in this toc; all messages will meet their 'fate'. */ ! 652: ! 653: void TocCommitChanges(toc) ! 654: Toc toc; ! 655: { ! 656: Msg msg; ! 657: int i, cur; ! 658: char str[100], **argv; ! 659: FateType curfate, fate; ! 660: Toc desttoc; ! 661: Toc curdesttoc; ! 662: ! 663: if (toc == NULL) return; ! 664: for (i=0 ; i<toc->nummsgs ; i++) { ! 665: msg = toc->msgs[i]; ! 666: fate = MsgGetFate(msg, (Toc *)NULL); ! 667: if (fate != Fignore && fate != Fcopy) ! 668: if (MsgSetScrn(msg, (Scrn) NULL)) ! 669: return; ! 670: } ! 671: QXFlush(theDisplay); ! 672: for (i=0 ; i<numFolders ; i++) ! 673: TocStopUpdate(folderList[i]); ! 674: do { ! 675: curfate = Fignore; ! 676: i = 0; ! 677: while (i < toc->nummsgs) { ! 678: msg = toc->msgs[i]; ! 679: fate = MsgGetFate(msg, &desttoc); ! 680: if (curfate == Fignore && fate != Fignore) { ! 681: curfate = fate; ! 682: argv = MakeArgv(2); ! 683: switch (curfate) { ! 684: case Fdelete: ! 685: argv[0] = MallocACopy("rmm"); ! 686: (void) sprintf(str, "+%s", toc->foldername); ! 687: argv[1] = MallocACopy(str); ! 688: cur = 2; ! 689: curdesttoc = NULL; ! 690: break; ! 691: case Fmove: ! 692: case Fcopy: ! 693: argv[0] = MallocACopy("refile"); ! 694: cur = 1; ! 695: curdesttoc = desttoc; ! 696: break; ! 697: } ! 698: } ! 699: if (curfate != Fignore && ! 700: curfate == fate && desttoc == curdesttoc) { ! 701: argv = ResizeArgv(argv, cur + 1); ! 702: (void) sprintf(str, "%d", MsgGetId(msg)); ! 703: argv[cur++] = MallocACopy(str); ! 704: MsgSetFate(msg, Fignore, (Toc)NULL); ! 705: if (curdesttoc) ! 706: (void) TUAppendToc(curdesttoc, MsgGetScanLine(msg)); ! 707: if (curfate != Fcopy) { ! 708: TocRemoveMsg(toc, msg); ! 709: MsgFree(msg); ! 710: i--; ! 711: } ! 712: if (cur > 40) ! 713: break; /* Do only 40 at a time, just to be safe. */ ! 714: } ! 715: i++; ! 716: } ! 717: if (curfate != Fignore) { ! 718: switch (curfate) { ! 719: case Fmove: ! 720: case Fcopy: ! 721: argv = ResizeArgv(argv, cur + 4); ! 722: argv[cur++] = MallocACopy(curfate == Fmove ? "-nolink" ! 723: : "-link"); ! 724: argv[cur++] = MallocACopy("-src"); ! 725: (void) sprintf(str, "+%s", toc->foldername); ! 726: argv[cur++] = MallocACopy(str); ! 727: (void) sprintf(str, "+%s", curdesttoc->foldername); ! 728: argv[cur++] = MallocACopy(str); ! 729: break; ! 730: } ! 731: if (debug) { ! 732: for (i = 0; i < cur; i++) ! 733: (void) fprintf(stderr, "%s ", argv[i]); ! 734: (void) fprintf(stderr, "\n"); ! 735: } ! 736: DoCommand(argv, (char *) NULL, "/dev/null"); ! 737: for (i = 0; argv[i]; i++) ! 738: XtFree((char *) argv[i]); ! 739: XtFree((char *) argv); ! 740: } ! 741: } while (curfate != Fignore); ! 742: for (i=0 ; i<numFolders ; i++) { ! 743: if (folderList[i]->needsrepaint) TocReloadSeqLists(folderList[i]); ! 744: TocStartUpdate(folderList[i]); ! 745: } ! 746: } ! 747: ! 748: ! 749: ! 750: /* Return whether the given toc can incorporate mail. */ ! 751: ! 752: int TocCanIncorporate(toc) ! 753: Toc toc; ! 754: { ! 755: return (toc && (toc == InitialFolder || toc->incfile)); ! 756: } ! 757: ! 758: ! 759: /* Incorporate new messages into the given toc. */ ! 760: ! 761: void TocIncorporate(toc) ! 762: Toc toc; ! 763: { ! 764: char **argv; ! 765: char str[100], str2[10], *file, *ptr; ! 766: Msg msg, firstmessage; ! 767: FILEPTR fid; ! 768: argv = MakeArgv(toc->incfile ? 7 : 5); ! 769: argv[0] = "inc"; ! 770: (void) sprintf(str, "+%s", toc->foldername); ! 771: argv[1] = str; ! 772: argv[2] = "-width"; ! 773: (void) sprintf(str2, "%d", defTocWidth); ! 774: argv[3] = str2; ! 775: if (toc->incfile) { ! 776: argv[4] = "-file"; ! 777: argv[5] = toc->incfile; ! 778: argv[6] = "-truncate"; ! 779: } else argv[4] = "-truncate"; ! 780: file = DoCommandToFile(argv); ! 781: XtFree((char *)argv); ! 782: TUGetFullFolderInfo(toc); ! 783: if (toc->validity == valid) { ! 784: fid = FOpenAndCheck(file, "r"); ! 785: firstmessage = NULL; ! 786: TocStopUpdate(toc); ! 787: while (ptr = ReadLineWithCR(fid)) { ! 788: if (atoi(ptr) > 0) { ! 789: msg = TUAppendToc(toc, ptr); ! 790: if (firstmessage == NULL) firstmessage = msg; ! 791: } ! 792: } ! 793: if (firstmessage && firstmessage->visible) { ! 794: TocSetCurMsg(toc, firstmessage); ! 795: } ! 796: TocStartUpdate(toc); ! 797: (void) myfclose(fid); ! 798: } ! 799: DeleteFileAndCheck(file); ! 800: } ! 801: ! 802: ! 803: ! 804: /* The given message has changed. Rescan it and change the scanfile. */ ! 805: ! 806: void TocMsgChanged(toc, msg) ! 807: Toc toc; ! 808: Msg msg; ! 809: { ! 810: char **argv, str[100], str2[10], str3[10], *ptr; ! 811: int length, delta, i; ! 812: FateType fate; ! 813: Toc desttoc; ! 814: if (toc->validity != valid) return; ! 815: fate = MsgGetFate(msg, &desttoc); ! 816: MsgSetFate(msg, Fignore, (Toc) NULL); ! 817: argv = MakeArgv(5); ! 818: argv[0] = "scan"; ! 819: (void) sprintf(str, "+%s", toc->foldername); ! 820: argv[1] = str; ! 821: (void) sprintf(str2, "%d", msg->msgid); ! 822: argv[2] = str2; ! 823: argv[3] = "-width"; ! 824: (void) sprintf(str3, "%d", defTocWidth); ! 825: argv[4] = str3; ! 826: ptr = DoCommandToString(argv); ! 827: XtFree((char *) argv); ! 828: if (strcmp(ptr, msg->buf) != 0) { ! 829: length = strlen(ptr); ! 830: delta = length - msg->length; ! 831: XtFree(msg->buf); ! 832: msg->buf = ptr; ! 833: msg->length = length; ! 834: toc->length += delta; ! 835: if (msg->visible) { ! 836: if (delta != 0) { ! 837: for (i=TUGetMsgPosition(toc, msg)+1; i<toc->nummsgs ; i++) ! 838: toc->msgs[i]->position += delta; ! 839: toc->lastPos += delta; ! 840: TURedisplayToc(toc->scrn); ! 841: } else { ! 842: if (toc->scrn) ! 843: XtTextInvalidate(DISPLAY toc->scrn->tocwindow, ! 844: msg->position, ! 845: msg->position + msg->length); ! 846: } ! 847: } ! 848: MsgSetFate(msg, fate, desttoc); ! 849: TUSaveTocFile(toc); ! 850: } else XtFree(ptr); ! 851: } ! 852: ! 853: ! 854: ! 855: Msg TocMsgFromId(toc, msgid) ! 856: Toc toc; ! 857: int msgid; ! 858: { ! 859: int h, l, m; ! 860: char str[100]; ! 861: l = 0; ! 862: h = toc->nummsgs - 1; ! 863: while (l < h - 1) { ! 864: m = (l + h) / 2; ! 865: if (toc->msgs[m]->msgid > msgid) ! 866: h = m; ! 867: else ! 868: l = m; ! 869: } ! 870: if (toc->msgs[l]->msgid == msgid) return toc->msgs[l]; ! 871: if (toc->msgs[h]->msgid == msgid) return toc->msgs[h]; ! 872: (void) sprintf(str, "TocMsgFromId search failed! hi=%d, lo=%d, msgid=%d", ! 873: h, l, msgid); ! 874: Punt(str); ! 875: return 0; /* Keep lint happy. */ ! 876: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.