|
|
1.1 ! root 1: #ifndef lint ! 2: static char rcs_id[] = "$Header: tocutil.c,v 1.14 87/09/11 08:19:27 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: /* tocutil.c -- internal routines for toc stuff. */ ! 30: ! 31: #include "xmh.h" ! 32: #include "toc.h" ! 33: #include "tocutil.h" ! 34: #include "tocintrnl.h" ! 35: #include <sys/file.h> ! 36: ! 37: Toc TUMalloc() ! 38: { ! 39: Toc toc; ! 40: toc = (Toc) XtMalloc(sizeof(TocRec)); ! 41: bzero((char *)toc, (int) sizeof(TocRec)); ! 42: toc->msgs = (Msg *) XtMalloc(1); ! 43: toc->seqlist = (Sequence *) XtMalloc(1); ! 44: toc->validity = unknown; ! 45: return toc; ! 46: } ! 47: ! 48: ! 49: /* Returns TRUE if the scan file for the given toc is out of date. */ ! 50: ! 51: int TUScanFileOutOfDate(toc) ! 52: Toc toc; ! 53: { ! 54: return LastModifyDate(toc->path) > toc->lastreaddate; ! 55: } ! 56: ! 57: ! 58: /* Make sure the shown sequence buttons correspond exactly to the sequences ! 59: for this toc. If not, then rebuild the buttonbox. */ ! 60: ! 61: static void CheckSeqButtons(toc) ! 62: Toc toc; ! 63: { ! 64: Scrn scrn = toc->scrn; ! 65: int i, numinbox; ! 66: int rebuild; ! 67: extern void PrepareDoubleClickSequence(); ! 68: if (scrn == NULL) return; ! 69: rebuild = FALSE; ! 70: numinbox = BBoxNumButtons(scrn->seqbuttons); ! 71: if (numinbox != toc->numsequences) ! 72: rebuild = TRUE; ! 73: else { ! 74: for (i=0 ; i<toc->numsequences && !rebuild; i++) ! 75: rebuild = ! 76: strcmp(toc->seqlist[i]->name, ! 77: BBoxNameOfButton(BBoxButtonNumber(scrn->seqbuttons, ! 78: i))); ! 79: } ! 80: if (rebuild) { ! 81: BBoxStopUpdate(scrn->seqbuttons); ! 82: for (i = 1; i < numinbox ; i++) ! 83: BBoxDeleteButton(BBoxButtonNumber(scrn->seqbuttons, 1)); ! 84: for (i = (numinbox ? 1 : 0); i < toc->numsequences; i++) ! 85: BBoxAddButton(scrn->seqbuttons, toc->seqlist[i]->name, ! 86: PrepareDoubleClickSequence, 999, TRUE); ! 87: BBoxStartUpdate(scrn->seqbuttons); ! 88: } ! 89: if (scrn->seqbuttons) ! 90: BBoxSetRadio(scrn->seqbuttons, ! 91: BBoxFindButtonNamed(scrn->seqbuttons, ! 92: toc->viewedseq->name)); ! 93: } ! 94: ! 95: ! 96: ! 97: void TUScanFileForToc(toc) ! 98: Toc toc; ! 99: { ! 100: static Arg arglist[] = { ! 101: {XtNlabel, NULL}, ! 102: {XtNx, (XtArgVal) 30}, ! 103: {XtNy, (XtArgVal) 30} ! 104: }; ! 105: ! 106: Window parent, label; ! 107: Scrn scrn; ! 108: char **argv, str[100], str2[10]; ! 109: if (toc) { ! 110: TUGetFullFolderInfo(toc); ! 111: scrn = toc->scrn; ! 112: if (!scrn) scrn = scrnList[0]; ! 113: parent = scrn->tocwindow; ! 114: if (!parent) parent = scrn->window; ! 115: (void) sprintf(str, "Rescanning %s", toc->foldername); ! 116: arglist[0].value = (XtArgVal) str; ! 117: label = XtLabelCreate(DISPLAY parent, arglist, XtNumber(arglist)); ! 118: QXMapWindow(theDisplay, label); ! 119: (void) XtSendExpose(DISPLAY label); ! 120: QXFlush(theDisplay); ! 121: ! 122: argv = MakeArgv(4); ! 123: argv[0] = "scan"; ! 124: (void) sprintf(str, "+%s", toc->foldername); ! 125: argv[1] = str; ! 126: argv[2] = "-width"; ! 127: (void) sprintf(str2, "%d", defTocWidth); ! 128: argv[3] = str2; ! 129: DoCommand(argv, (char *) NULL, toc->scanfile); ! 130: XtFree((char *) argv); ! 131: ! 132: (void) XtSendDestroyNotify(DISPLAY label); ! 133: QXDestroyWindow(theDisplay, label); ! 134: toc->validity = valid; ! 135: toc->curmsg = NULL; /* Get cur msg somehow! %%% */ ! 136: } ! 137: } ! 138: ! 139: ! 140: ! 141: int TUGetMsgPosition(toc, msg) ! 142: Toc toc; ! 143: Msg msg; ! 144: { ! 145: int msgid, h, l, m; ! 146: char str[100]; ! 147: msgid = msg->msgid; ! 148: l = 0; ! 149: h = toc->nummsgs - 1; ! 150: while (l < h - 1) { ! 151: m = (l + h) / 2; ! 152: if (toc->msgs[m]->msgid > msgid) ! 153: h = m; ! 154: else ! 155: l = m; ! 156: } ! 157: if (toc->msgs[l] == msg) return l; ! 158: if (toc->msgs[h] == msg) return h; ! 159: (void) sprintf(str, "TUGetMsgPosition search failed! hi=%d, lo=%d, msgid=%d", ! 160: h, l, msgid); ! 161: Punt(str); ! 162: return 0; /* Keep lint happy. */ ! 163: } ! 164: ! 165: ! 166: void TUResetTocLabel(scrn) ! 167: Scrn scrn; ! 168: { ! 169: char str[500]; ! 170: Toc toc; ! 171: if (scrn) { ! 172: toc = scrn->toc; ! 173: if (toc == NULL) ! 174: (void) strcpy(str, " "); ! 175: else { ! 176: if (toc->stopupdate) { ! 177: toc->needslabelupdate = TRUE; ! 178: return; ! 179: } ! 180: (void) sprintf(str, "%s:%s", toc->foldername, ! 181: toc->viewedseq->name); ! 182: toc->needslabelupdate = FALSE; ! 183: } ! 184: ChangeLabel(scrn->toclabel, str); ! 185: } ! 186: } ! 187: ! 188: ! 189: /* A major toc change has occured; redisplay it. (This also should work even ! 190: if we now have a new source to display stuff from.) */ ! 191: ! 192: void TURedisplayToc(scrn) ! 193: Scrn scrn; ! 194: { ! 195: Toc toc; ! 196: int lines, width, height; ! 197: XtTextPosition position; ! 198: if (scrn != NULL && scrn->tocwindow != NULL) { ! 199: toc = scrn->toc; ! 200: if (toc) { ! 201: if (toc->stopupdate) { ! 202: toc->needsrepaint = TRUE; ! 203: return; ! 204: } ! 205: GetWindowSize(scrn->tocwindow, &width, &height); ! 206: lines = scrn->tocsink->maxLines(scrn->tocsink, height); ! 207: position = toc->source->getLastPos(toc->source); ! 208: position = toc->source->scan(toc->source, position, XtstEOL, ! 209: XtsdLeft, lines, FALSE); ! 210: XtTextNewSource(DISPLAY scrn->tocwindow, toc->source, position); ! 211: TocSetCurMsg(toc, TocGetCurMsg(toc)); ! 212: CheckSeqButtons(toc); ! 213: toc->needsrepaint = FALSE; ! 214: } else { ! 215: XtTextNewSource(DISPLAY scrn->tocwindow, NullSource, (XtTextPosition) 0); ! 216: } ! 217: } ! 218: } ! 219: ! 220: ! 221: ! 222: void TULoadSeqLists(toc) ! 223: Toc toc; ! 224: { ! 225: Sequence seq; ! 226: FILEPTR fid; ! 227: char str[500], *ptr, *ptr2, viewed[500]; ! 228: int i; ! 229: if (toc->viewedseq) (void) strcpy(viewed, toc->viewedseq->name); ! 230: else *viewed = 0; ! 231: for (i = 0; i < toc->numsequences; i++) { ! 232: seq = toc->seqlist[i]; ! 233: XtFree((char *) seq->name); ! 234: if (seq->mlist) FreeMsgList(seq->mlist); ! 235: XtFree((char *)seq); ! 236: } ! 237: toc->numsequences = 1; ! 238: toc->seqlist = (Sequence *) XtRealloc((char *) toc->seqlist, ! 239: sizeof(Sequence)); ! 240: seq = toc->seqlist[0] = (Sequence) XtMalloc(sizeof(SequenceRec)); ! 241: bzero((char *) seq, sizeof(SequenceRec)); ! 242: seq->name = MallocACopy("all"); ! 243: seq->mlist = NULL; ! 244: toc->viewedseq = seq; ! 245: (void) sprintf(str, "%s/.mh_sequences", toc->path); ! 246: fid = myfopen(str, "r"); ! 247: if (fid) { ! 248: while (ptr = ReadLine(fid)) { ! 249: ptr2 = index(ptr, ':'); ! 250: if (ptr2) { ! 251: *ptr2 = 0; ! 252: if (strcmp(ptr, "all") != 0 && ! 253: strcmp(ptr, "cur") != 0 && ! 254: strcmp(ptr, "unseen") != 0) { ! 255: toc->numsequences++; ! 256: toc->seqlist = (Sequence *) ! 257: XtRealloc((char *) toc->seqlist, ! 258: (unsigned) toc->numsequences * sizeof(Sequence)); ! 259: seq = toc->seqlist[toc->numsequences - 1] = ! 260: (Sequence) XtMalloc(sizeof(SequenceRec)); ! 261: bzero((char *) seq, sizeof(SequenceRec)); ! 262: seq->name = MallocACopy(ptr); ! 263: seq->mlist = StringToMsgList(toc, ptr2 + 1); ! 264: if (strcmp(seq->name, viewed) == 0) { ! 265: toc->viewedseq = seq; ! 266: *viewed = 0; ! 267: } ! 268: } ! 269: } ! 270: } ! 271: (void) myfclose(fid); ! 272: } ! 273: } ! 274: ! 275: ! 276: ! 277: /* Refigure what messages are visible. Also makes sure we're displaying the ! 278: correct set of seq buttons. */ ! 279: ! 280: void TURefigureWhatsVisible(toc) ! 281: Toc toc; ! 282: { ! 283: MsgList mlist; ! 284: Msg msg, oldcurmsg; ! 285: int i, w, changed, newval, msgid; ! 286: Sequence seq = toc->viewedseq; ! 287: mlist = seq->mlist; ! 288: oldcurmsg = toc->curmsg; ! 289: TocSetCurMsg(toc, (Msg)NULL); ! 290: w = 0; ! 291: changed = FALSE; ! 292: CheckSeqButtons(toc); ! 293: for (i = 0; i < toc->nummsgs; i++) { ! 294: msg = toc->msgs[i]; ! 295: msgid = msg->msgid; ! 296: while (mlist && mlist->msglist[w] && mlist->msglist[w]->msgid < msgid) ! 297: w++; ! 298: newval = (!mlist || mlist->msglist[w]->msgid == msgid); ! 299: if (newval != msg->visible) { ! 300: changed = TRUE; ! 301: msg->visible = newval; ! 302: } ! 303: } ! 304: if (changed) { ! 305: TURefigureTocPositions(toc); ! 306: if (oldcurmsg) { ! 307: if (!oldcurmsg->visible) { ! 308: toc->curmsg = TocMsgAfter(toc, oldcurmsg); ! 309: if (toc->curmsg == NULL) ! 310: toc->curmsg = TocMsgBefore(toc, oldcurmsg); ! 311: } else toc->curmsg = oldcurmsg; ! 312: } ! 313: TURedisplayToc(toc->scrn); ! 314: } else TocSetCurMsg(toc, oldcurmsg); ! 315: TUResetTocLabel(toc->scrn); ! 316: } ! 317: ! 318: ! 319: /* (Re)load the toc from the scanfile. If reloading, this makes efforts to ! 320: keep the fates of msgs, and to keep msgs that are being edited. Note that ! 321: this routine must know of all places that msg ptrs are stored; it expects ! 322: them to be kept only in tocs, in scrns, and in msg sequences. */ ! 323: ! 324: #define SeemsIdentical(msg1, msg2) ((msg1)->msgid == (msg2)->msgid && \ ! 325: ((msg1)->temporary || (msg2)->temporary ||\ ! 326: strcmp((msg1)->buf, (msg2)->buf) == 0)) ! 327: ! 328: void TULoadTocFile(toc) ! 329: Toc toc; ! 330: { ! 331: int maxmsgs, l, orignummsgs, i, j, origcurmsgid; ! 332: FILEPTR fid; ! 333: XtTextPosition position; ! 334: char *ptr; ! 335: Msg msg, curmsg; ! 336: Msg *origmsgs; ! 337: ! 338: TocStopUpdate(toc); ! 339: toc->lastreaddate = CurrentDate(); ! 340: if (toc->curmsg) { ! 341: origcurmsgid = toc->curmsg->msgid; ! 342: TocSetCurMsg(toc, (Msg)NULL); ! 343: } else origcurmsgid = 0; ! 344: fid = FOpenAndCheck(toc->scanfile, "r"); ! 345: maxmsgs = 10; ! 346: orignummsgs = toc->nummsgs; ! 347: toc->nummsgs = 0; ! 348: origmsgs = toc->msgs; ! 349: toc->msgs = (Msg *) XtMalloc((unsigned) maxmsgs * sizeof(Msg)); ! 350: position = 0; ! 351: i = 0; ! 352: curmsg = NULL; ! 353: while (ptr = ReadLineWithCR(fid)) { ! 354: toc->msgs[toc->nummsgs++] = msg = (Msg) XtMalloc(sizeof(MsgRec)); ! 355: bzero((char *) msg, sizeof(MsgRec)); ! 356: l = strlen(ptr); ! 357: msg->toc = toc; ! 358: msg->position = position; ! 359: msg->length = l; ! 360: msg->buf = MallocACopy(ptr); ! 361: msg->msgid = atoi(ptr); ! 362: if (msg->msgid == origcurmsgid) ! 363: curmsg = msg; ! 364: msg->buf[MARKPOS] = ' '; ! 365: position += l; ! 366: msg->changed = FALSE; ! 367: msg->fate = Fignore; ! 368: msg->desttoc = NULL; ! 369: msg->visible = TRUE; ! 370: if (toc->nummsgs >= maxmsgs) { ! 371: maxmsgs += 100; ! 372: toc->msgs = (Msg *) XtRealloc((char *) toc->msgs, ! 373: (unsigned) maxmsgs * sizeof(Msg)); ! 374: } ! 375: while (i < orignummsgs && origmsgs[i]->msgid < msg->msgid) i++; ! 376: if (i < orignummsgs) { ! 377: origmsgs[i]->buf[MARKPOS] = ' '; ! 378: if (SeemsIdentical(origmsgs[i], msg)) ! 379: MsgSetFate(msg, origmsgs[i]->fate, origmsgs[i]->desttoc); ! 380: } ! 381: } ! 382: toc->length = toc->origlength = toc->lastPos = position; ! 383: toc->msgs = (Msg *) XtRealloc((char *) toc->msgs, ! 384: (unsigned) toc->nummsgs * sizeof(Msg)); ! 385: (void) myfclose(fid); ! 386: if (toc->source == NULL) ! 387: toc->source = TSourceCreate(toc); ! 388: for (i=0 ; i<numScrns ; i++) { ! 389: msg = scrnList[i]->msg; ! 390: if (msg && msg->toc == toc) { ! 391: for (j=0 ; j<toc->nummsgs ; j++) { ! 392: if (SeemsIdentical(toc->msgs[j], msg)) { ! 393: msg->position = toc->msgs[j]->position; ! 394: msg->visible = TRUE; ! 395: ptr = toc->msgs[j]->buf; ! 396: *(toc->msgs[j]) = *msg; ! 397: toc->msgs[j]->buf = ptr; ! 398: scrnList[i]->msg = toc->msgs[j]; ! 399: break; ! 400: } ! 401: } ! 402: if (j >= toc->nummsgs) { ! 403: msg->temporary = FALSE; /* Don't try to auto-delete msg. */ ! 404: MsgSetScrnForce(msg, (Scrn) NULL); ! 405: } ! 406: } ! 407: } ! 408: for (i=0 ; i<orignummsgs ; i++) ! 409: MsgFree(origmsgs[i]); ! 410: XtFree((char *)origmsgs); ! 411: TocSetCurMsg(toc, curmsg); ! 412: TULoadSeqLists(toc); ! 413: TocStartUpdate(toc); ! 414: } ! 415: ! 416: ! 417: void TUSaveTocFile(toc) ! 418: Toc toc; ! 419: { ! 420: extern long lseek(); ! 421: Msg msg; ! 422: int fid; ! 423: int i; ! 424: XtTextPosition position; ! 425: char c; ! 426: if (toc->stopupdate) { ! 427: toc->needscachesave = TRUE; ! 428: return; ! 429: } ! 430: fid = -1; ! 431: position = 0; ! 432: for (i = 0; i < toc->nummsgs; i++) { ! 433: msg = toc->msgs[i]; ! 434: if (fid < 0 && msg->changed) { ! 435: fid = myopen(toc->scanfile, O_RDWR, 0666); ! 436: (void) lseek(fid, (long)position, 0); ! 437: } ! 438: if (fid >= 0) { ! 439: c = msg->buf[MARKPOS]; ! 440: msg->buf[MARKPOS] = ' '; ! 441: (void) write(fid, msg->buf, msg->length); ! 442: msg->buf[MARKPOS] = c; ! 443: } ! 444: position += msg->length; ! 445: } ! 446: if (fid < 0 && toc->length != toc->origlength) ! 447: fid = myopen(toc->scanfile, O_RDWR, 0666); ! 448: if (fid >= 0) { ! 449: (void) ftruncate(fid, toc->length); ! 450: toc->origlength = toc->length; ! 451: (void) myclose(fid); ! 452: } else ! 453: (void) utime(toc->scanfile, (time_t *)NULL); ! 454: toc->needscachesave = FALSE; ! 455: toc->lastreaddate = CurrentDate(); ! 456: } ! 457: ! 458: ! 459: void TUEnsureScanIsValidAndOpen(toc) ! 460: Toc toc; ! 461: { ! 462: if (toc) { ! 463: TUGetFullFolderInfo(toc); ! 464: if (TUScanFileOutOfDate(toc)) { ! 465: if (toc->source) { ! 466: XtFree((char *) toc->source); ! 467: toc->source = NULL; ! 468: } ! 469: TUScanFileForToc(toc); ! 470: } ! 471: if (toc->source == NULL) ! 472: TULoadTocFile(toc); ! 473: toc->validity = valid; ! 474: } ! 475: } ! 476: ! 477: ! 478: ! 479: /* Refigure all the positions, based on which lines are visible. */ ! 480: ! 481: void TURefigureTocPositions(toc) ! 482: Toc toc; ! 483: { ! 484: int i; ! 485: Msg msg; ! 486: XtTextPosition position, length; ! 487: position = length = 0; ! 488: for (i=0; i<toc->nummsgs ; i++) { ! 489: msg = toc->msgs[i]; ! 490: msg->position = position; ! 491: if (msg->visible) position += msg->length; ! 492: length += msg->length; ! 493: } ! 494: toc->lastPos = position; ! 495: toc->length = length; ! 496: } ! 497: ! 498: ! 499: ! 500: /* Make sure we've loaded ALL the folder info for this toc, including its ! 501: path and sequence lists. */ ! 502: ! 503: void TUGetFullFolderInfo(toc) ! 504: Toc toc; ! 505: { ! 506: char str[500]; ! 507: if (toc->path == NULL) { ! 508: (void) sprintf(str, "%s/%s", mailDir, toc->foldername); ! 509: toc->path = MallocACopy(str); ! 510: (void) sprintf(str, "%s/.xmhcache", toc->path); ! 511: toc->scanfile = MallocACopy(str); ! 512: toc->lastreaddate = LastModifyDate(toc->scanfile); ! 513: if (TUScanFileOutOfDate(toc)) ! 514: toc->validity = invalid; ! 515: else { ! 516: toc->validity = valid; ! 517: TULoadTocFile(toc); ! 518: } ! 519: } ! 520: } ! 521: ! 522: /* Append a message to the end of the toc. It has the given scan line. This ! 523: routine will figure out the message number, and change the scan line ! 524: accordingly. */ ! 525: ! 526: Msg TUAppendToc(toc, ptr) ! 527: Toc toc; ! 528: char *ptr; ! 529: { ! 530: char str[10]; ! 531: Msg msg; ! 532: int msgid, i; ! 533: TUGetFullFolderInfo(toc); ! 534: if (toc->validity != valid) ! 535: return NULL; ! 536: ! 537: if (toc->nummsgs > 0) ! 538: msgid = toc->msgs[toc->nummsgs - 1]->msgid + 1; ! 539: else ! 540: msgid = 1; ! 541: (toc->nummsgs)++; ! 542: toc->msgs = (Msg *) XtRealloc((char *) toc->msgs, ! 543: (unsigned) toc->nummsgs * sizeof(Msg)); ! 544: toc->msgs[toc->nummsgs - 1] = msg = (Msg) XtMalloc(sizeof(MsgRec)); ! 545: bzero((char *) msg, (int) sizeof(MsgRec)); ! 546: msg->toc = toc; ! 547: msg->buf = MallocACopy(ptr); ! 548: (void)sprintf(str, "%4d", msgid); ! 549: for (i=0; i<4 ; i++) msg->buf[i] = str[i]; ! 550: msg->buf[MARKPOS] = ' '; ! 551: msg->msgid = msgid; ! 552: msg->position = toc->lastPos; ! 553: msg->length = strlen(ptr); ! 554: msg->changed = TRUE; ! 555: msg->fate = Fignore; ! 556: msg->desttoc = NULL; ! 557: if (toc->viewedseq == toc->seqlist[0]) { ! 558: msg->visible = TRUE; ! 559: toc->lastPos += msg->length; ! 560: } ! 561: else ! 562: msg->visible = FALSE; ! 563: toc->length += msg->length; ! 564: TURedisplayToc(toc->scrn); ! 565: TUSaveTocFile(toc); ! 566: return msg; ! 567: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.