home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xmh / tocutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-30  |  16.1 KB  |  632 lines

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