Annotation of researchv9/X11/src/X.V11R1/clients/xmh/msg.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char rcs_id[] = "$Header: msg.c,v 1.18 87/08/20 11:14:28 swick 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: /* msgs.c -- handle operations on messages. */
        !            30: 
        !            31: #include "xmh.h"
        !            32: #include "tocintrnl.h"
        !            33: #include <sys/file.h>
        !            34: 
        !            35: #ifdef NOGRABFOCUS
        !            36: /* Overload this Xlib routine, as the toolkit widgets use it directly. */
        !            37: 
        !            38: XSetInputFocus(d, w, r, t)
        !            39:      Display d;
        !            40:      Window w;
        !            41:      int r;
        !            42:      Time t;
        !            43: {
        !            44: }
        !            45: #endif
        !            46: 
        !            47: 
        !            48: /* Return the user-viewable name of the given message. */
        !            49: 
        !            50: static char *NameOfMsg(msg)
        !            51: Msg msg;
        !            52: {
        !            53:     static char result[100];
        !            54:     (void) sprintf(result, "%s:%d", msg->toc->foldername, msg->msgid);
        !            55:     return result;
        !            56: }
        !            57: 
        !            58: 
        !            59: /* Update the message titlebar in the given scrn. */
        !            60: 
        !            61: static void ResetMsgLabel(scrn)
        !            62: Scrn scrn;
        !            63: {
        !            64:     Msg msg;
        !            65:     char str[200];
        !            66:     if (scrn) {
        !            67:        msg = scrn->msg;
        !            68:        if (msg == NULL) (void) strcpy(str, Version());
        !            69:        else {
        !            70:            (void) strcpy(str, NameOfMsg(msg));
        !            71:            switch (msg->fate) {
        !            72:              case Fdelete:
        !            73:                (void) strcat(str, " -> *Delete*");
        !            74:                break;
        !            75:              case Fcopy:
        !            76:              case Fmove:
        !            77:                (void) strcat(str, " -> ");
        !            78:                (void) strcat(str, msg->desttoc->foldername);
        !            79:                if (msg->fate == Fcopy)
        !            80:                    (void) strcat(str, " (Copy)");
        !            81:                break;
        !            82:            }
        !            83:            if (msg->temporary) (void)strcat(str, " [Temporary]");
        !            84:        }
        !            85:        ChangeLabel(scrn->viewlabel, str);
        !            86:     }
        !            87: }
        !            88: 
        !            89: 
        !            90: /* A major msg change has occured; redisplay it.  (This also should
        !            91: work even if we now have a new source to display stuff from.)  This
        !            92: routine arranges to hide boring headers, and also will set the text
        !            93: insertion point to the proper place if this is a composition and we're
        !            94: viewing it for the first time. */
        !            95: 
        !            96: static void RedisplayMsg(scrn)
        !            97: Scrn scrn;
        !            98: {
        !            99:     Msg msg;
        !           100:     XtTextPosition startPos, lastPos, nextPos;
        !           101:     int length; char str[100];
        !           102:     XtTextBlock text;
        !           103:     if (scrn) {
        !           104:        msg = scrn->msg;
        !           105:        if (msg) {
        !           106:            startPos = 0;
        !           107:            if (defHideBoringHeaders && scrn->kind != STcomp) {
        !           108:                lastPos = msg->source->getLastPos(msg->source);
        !           109:                while (startPos < lastPos) {
        !           110:                    nextPos = startPos;
        !           111:                    length = 0;
        !           112:                    while (length < 8 && nextPos < lastPos) {
        !           113:                        nextPos = (*msg->source->read)(msg->source, nextPos,
        !           114:                                                       &text, 8 - length);
        !           115:                        (void) strncpy(str + length, text.ptr, text.length);
        !           116:                        length += text.length;
        !           117:                    }
        !           118:                    if (length == 8) {
        !           119:                        if (strncmp(str, "From:", 5) == 0 ||
        !           120:                            strncmp(str, "To:", 3) == 0 ||
        !           121:                            strncmp(str, "Date:", 5) == 0 ||
        !           122:                            strncmp(str, "Subject:", 8) == 0) break;
        !           123:                    }
        !           124:                    startPos = (*msg->source->scan)
        !           125:                        (msg->source, startPos, XtstEOL, XtsdRight, 1,TRUE);
        !           126:                }
        !           127:            }
        !           128:            if (startPos >= lastPos) startPos = 0;
        !           129:            XtTextNewSource(DISPLAY scrn->viewwindow, msg->source, startPos);
        !           130:            if (msg->startPos > 0) {
        !           131: #ifdef X10
        !           132:            /* Do an incredibly disgusting hack to make things display right.
        !           133:               The X10 toolkit stinks. */
        !           134:                MapScrn(scrn);
        !           135:                EmptyEventQueue();
        !           136: #endif X10
        !           137:                XtTextSetInsertionPoint(DISPLAY scrn->viewwindow,
        !           138:                                        msg->startPos);
        !           139:                msg->startPos = 0; /* Start in magic place only once. */
        !           140:            }
        !           141:        } else {
        !           142:            XtTextNewSource(DISPLAY scrn->viewwindow,
        !           143:                            NullSource, (XtTextPosition) 0);
        !           144:        }
        !           145:     }
        !           146: }
        !           147: 
        !           148: 
        !           149: 
        !           150: static char tempDraftFile[100] = "";
        !           151: 
        !           152: /* Temporarily move the draftfile somewhere else, so we can exec an mh
        !           153:    command that affects it. */
        !           154: 
        !           155: static void TempMoveDraft()
        !           156: {
        !           157:     char *ptr;
        !           158:     if (FileExists(draftFile)) {
        !           159:        do {
        !           160:            ptr = MakeNewTempFileName();
        !           161:            (void) strcpy(tempDraftFile, draftFile);
        !           162:            (void) strcpy(rindex(tempDraftFile, '/'), rindex(ptr, '/'));
        !           163:        } while (FileExists(tempDraftFile));
        !           164:        RenameAndCheck(draftFile, tempDraftFile);
        !           165:     }
        !           166: }
        !           167: 
        !           168: 
        !           169: 
        !           170: /* Restore the draftfile from its temporary hiding place. */
        !           171: 
        !           172: static void RestoreDraft()
        !           173: {
        !           174:     if (*tempDraftFile) {
        !           175:        RenameAndCheck(tempDraftFile, draftFile);
        !           176:        *tempDraftFile = 0;
        !           177:     }
        !           178: }
        !           179: 
        !           180: 
        !           181: 
        !           182: /* Public routines */
        !           183: 
        !           184: 
        !           185: /* Given a message, return the corresponding filename. */
        !           186: 
        !           187: char *MsgFileName(msg)
        !           188: Msg msg;
        !           189: {
        !           190:     static char result[500];
        !           191:     (void) sprintf(result, "%s/%d", msg->toc->path, msg->msgid);
        !           192:     return result;
        !           193: }
        !           194: 
        !           195: 
        !           196: 
        !           197: /* Save any changes to a message.  Also calls the toc routine to update the
        !           198:    scanline for this msg. */
        !           199: 
        !           200: void MsgSaveChanges(msg)
        !           201: Msg msg;
        !           202: {
        !           203:     if (msg->source) {
        !           204:        XtEDiskSaveFile(msg->source);
        !           205:        EnableProperButtons(msg->scrn);
        !           206:        if (!msg->temporary)
        !           207:            TocMsgChanged(msg->toc, msg);
        !           208:     }
        !           209: }
        !           210: 
        !           211: /*ARGSUSED*/
        !           212: static Boolean IfMapWindow(dpy, event, scrn)
        !           213: Display *dpy;
        !           214: XEvent *event;
        !           215: Scrn scrn;
        !           216: {
        !           217:     return (event->type == MapNotify && event->xany.window == scrn->window);
        !           218: }
        !           219: 
        !           220: /* Associate the given message with the given scrn.  If a message is
        !           221:    changed, and we are removing it from any scrn, then ask for confirmation
        !           222:    first.  If the message is a temporary one and it is removed from any scrn,
        !           223:    it is deleted. */
        !           224: 
        !           225: static int SetScrn(msg, scrn, force)
        !           226: Msg msg;
        !           227: Scrn scrn;
        !           228: Boolean force; /* If TRUE, don't ask for confirm; just do it */
        !           229: {
        !           230:     char str[100];
        !           231:     if (msg == NULL && scrn == NULL) return 0;
        !           232:     if (scrn && scrn->msg != msg)
        !           233:        if (SetScrn(scrn->msg, (Scrn) NULL, force))
        !           234:            return DELETEABORTED;
        !           235:     if (msg == NULL)
        !           236:        return 0;
        !           237:     if (msg->scrn == scrn) return 0;
        !           238:     if (msg->scrn) {
        !           239:        if (msg->source && scrn == NULL) {
        !           240:            if (XtEDiskChanged(msg->source) && !force) {
        !           241:                (void)sprintf(str,
        !           242:                              "Are you sure you want to remove changes to %s?",
        !           243:                              NameOfMsg(msg));
        !           244:                if (!Confirm(msg->scrn, str)) return DELETEABORTED;
        !           245:            }
        !           246:            XtDestroyEDiskSource(msg->source);
        !           247:            msg->source = NULL;
        !           248:        }
        !           249:        msg->scrn->msg = NULL;
        !           250:        ResetMsgLabel(msg->scrn);
        !           251:        RedisplayMsg(msg->scrn);
        !           252:        EnableProperButtons(msg->scrn);
        !           253:        if (msg->scrn->kind != STtocAndView)
        !           254:            QXStoreName(theDisplay, msg->scrn->window, progName);
        !           255:        msg->scrn = NULL;
        !           256:        if (scrn == NULL) {
        !           257:            if (msg->temporary) {
        !           258:                (void) unlink(MsgFileName(msg));
        !           259:                TocRemoveMsg(msg->toc, msg);
        !           260:                MsgFree(msg);
        !           261:            }           
        !           262:            return 0;
        !           263:        }
        !           264:     }
        !           265:     if (msg->source == NULL)
        !           266:        msg->source = XtCreateEDiskSource(MsgFileName(msg), XttextRead);
        !           267:     if (scrn->kind == STcomp) {
        !           268:        XtEDiskChangeEditMode(msg->source, XttextEdit);
        !           269:        if (defGrabFocus) {
        !           270:            XEvent event;
        !           271:            QXMapWindow(theDisplay, scrn->window);
        !           272:            XPeekIfEvent(theDisplay, &event, IfMapWindow, (char *)scrn);
        !           273:            QXSetInputFocus(theDisplay, scrn->viewwindow,
        !           274:                            RevertToParent, CurrentTime);
        !           275:        }
        !           276:     }
        !           277: 
        !           278:     msg->scrn = scrn;
        !           279:     scrn->msg = msg;
        !           280:     ResetMsgLabel(msg->scrn);
        !           281:     RedisplayMsg(msg->scrn);
        !           282:     EnableProperButtons(msg->scrn);
        !           283:     if (msg->scrn->kind != STtocAndView)
        !           284:        QXStoreName(theDisplay, msg->scrn->window, NameOfMsg(msg));
        !           285:     return 0;
        !           286: }
        !           287: 
        !           288: 
        !           289: /* Associate the given msg and scrn, asking for confirmation if necessary. */
        !           290: 
        !           291: int MsgSetScrn(msg, scrn)
        !           292: Msg msg;
        !           293: Scrn scrn;
        !           294: {
        !           295:     return SetScrn(msg, scrn, FALSE);
        !           296: }
        !           297: 
        !           298: 
        !           299: /* Same as above, but with the extra information that the message is actually
        !           300:    a composition.  (Nothing currently takes advantage of that extra fact.) */
        !           301: 
        !           302: int MsgSetScrnForComp(msg, scrn)
        !           303: Msg msg;
        !           304: Scrn scrn;
        !           305: {
        !           306:     return SetScrn(msg, scrn, FALSE);
        !           307: }
        !           308: 
        !           309: 
        !           310: 
        !           311: /* Associate the given msg and scrn, even if it means losing some unsaved
        !           312:    changes. */
        !           313: 
        !           314: void MsgSetScrnForce(msg, scrn)
        !           315: Msg msg;
        !           316: Scrn scrn;
        !           317: {
        !           318:     (void) SetScrn(msg, scrn, TRUE);
        !           319: }
        !           320: 
        !           321: 
        !           322: 
        !           323: /* Return what screen (if any) is displaying the given msg. */
        !           324: 
        !           325: Scrn MsgGetScrn(msg)
        !           326: Msg msg;
        !           327: {
        !           328:     return msg->scrn;
        !           329: }
        !           330: 
        !           331: 
        !           332: 
        !           333: /* Set the fate of the given message. */
        !           334: 
        !           335: void MsgSetFate(msg, fate, desttoc)
        !           336:   Msg msg;
        !           337:   FateType fate;
        !           338:   Toc desttoc;
        !           339: {
        !           340:     Toc toc = msg->toc;
        !           341:     XtTextBlock text;
        !           342:     msg->fate = fate;
        !           343:     msg->desttoc = desttoc;
        !           344:     if (fate == Fignore && msg == msg->toc->curmsg)
        !           345:        text.ptr = "+";
        !           346:     else {
        !           347:        switch (fate) {
        !           348:            case Fignore:       text.ptr = " "; break;
        !           349:            case Fcopy:         text.ptr = "C"; break;
        !           350:            case Fmove:         text.ptr = "^"; break;
        !           351:            case Fdelete:       text.ptr = "D"; break;
        !           352:        }
        !           353:     }
        !           354:     text.length = 1;
        !           355:     text.firstPos = msg->position + MARKPOS;
        !           356:     if (toc->stopupdate)
        !           357:        toc->needsrepaint = TRUE;
        !           358:     if (toc->scrn && msg->visible && !toc->needsrepaint &&
        !           359:            *text.ptr != msg->buf[MARKPOS])
        !           360:        (void) XtTextReplace(DISPLAY toc->scrn->tocwindow,
        !           361:                             msg->position + MARKPOS,
        !           362:                             msg->position + MARKPOS + 1, &text);
        !           363:     else
        !           364:        msg->buf[MARKPOS] = *text.ptr;
        !           365:     if (msg->scrn)
        !           366:        ResetMsgLabel(msg->scrn);
        !           367: }
        !           368: 
        !           369: 
        !           370: 
        !           371: /* Get the fate of this message. */
        !           372: 
        !           373: FateType MsgGetFate(msg, toc)
        !           374: Msg msg;
        !           375: Toc *toc;                      /* RETURN */
        !           376: {
        !           377:     if (toc) *toc = msg->desttoc;
        !           378:     return msg->fate;
        !           379: }
        !           380: 
        !           381: 
        !           382: /* Make this a temporary message. */
        !           383: 
        !           384: void MsgSetTemporary(msg)
        !           385: Msg msg;
        !           386: {
        !           387:     msg->temporary = TRUE;
        !           388:     ResetMsgLabel(msg->scrn);
        !           389: }
        !           390: 
        !           391: 
        !           392: /* Make this a permanent message. */
        !           393: 
        !           394: void MsgSetPermanent(msg)
        !           395: Msg msg;
        !           396: {
        !           397:     msg->temporary = FALSE;
        !           398:     ResetMsgLabel(msg->scrn);
        !           399: }
        !           400: 
        !           401: 
        !           402: 
        !           403: /* Return the id# of this message. */
        !           404: 
        !           405: int MsgGetId(msg)
        !           406: Msg msg;
        !           407: {
        !           408:     return msg->msgid;
        !           409: }
        !           410: 
        !           411: 
        !           412: /* Return the scanline for this message. */
        !           413: 
        !           414: char *MsgGetScanLine(msg)
        !           415: Msg msg;
        !           416: {
        !           417:     return msg->buf;
        !           418: }
        !           419: 
        !           420: 
        !           421: 
        !           422: /* Return the toc this message is in. */
        !           423: 
        !           424: Toc MsgGetToc(msg)
        !           425: Msg msg;
        !           426: {
        !           427:     return msg->toc;
        !           428: }
        !           429: 
        !           430: 
        !           431: /* Set the reapable flag for this msg. */
        !           432: 
        !           433: void MsgSetReapable(msg)
        !           434: Msg msg;
        !           435: {
        !           436:     msg->reapable = TRUE;
        !           437:     EnableProperButtons(msg->scrn);
        !           438: }
        !           439: 
        !           440: 
        !           441: 
        !           442: /* Clear the reapable flag for this msg. */
        !           443: 
        !           444: void MsgClearReapable(msg)
        !           445: Msg msg;
        !           446: {
        !           447:     msg->reapable = FALSE;
        !           448:     EnableProperButtons(msg->scrn);
        !           449: }
        !           450: 
        !           451: 
        !           452: /* Get the reapable value for this msg.  Returns TRUE iff the reapable flag
        !           453:    is set AND no changes have been made. */
        !           454: 
        !           455: int MsgGetReapable(msg)
        !           456: Msg msg;
        !           457: {
        !           458:     return msg == NULL || (msg->reapable &&
        !           459:                           (msg->source == NULL ||
        !           460:                            !XtEDiskChanged(msg->source)));
        !           461: }
        !           462: 
        !           463: 
        !           464: /* Make it possible to edit the given msg. */
        !           465: void MsgSetEditable(msg)
        !           466: Msg msg;
        !           467: {
        !           468:     if (msg && msg->source) {
        !           469:        XtEDiskChangeEditMode(msg->source, XttextEdit);
        !           470:        if (defGrabFocus && msg->scrn)
        !           471:            QXSetInputFocus(theDisplay, msg->scrn->viewwindow,
        !           472:                            RevertToParent, CurrentTime);
        !           473:        EnableProperButtons(msg->scrn);
        !           474:     }
        !           475: }
        !           476: 
        !           477: 
        !           478: 
        !           479: /* Turn off editing for the given msg. */
        !           480: 
        !           481: void MsgClearEditable(msg)
        !           482: Msg msg;
        !           483: {
        !           484:     if (msg && msg->source) {
        !           485:        XtEDiskChangeEditMode(msg->source, XttextRead);
        !           486:        EnableProperButtons(msg->scrn);
        !           487:     }
        !           488: }
        !           489: 
        !           490: 
        !           491: 
        !           492: /* Get whether the msg is editable. */
        !           493: 
        !           494: int MsgGetEditable(msg)
        !           495: Msg msg;
        !           496: {
        !           497:     return msg && msg->source &&
        !           498:        (*msg->source->editType)(msg->source) == XttextEdit;
        !           499: }
        !           500: 
        !           501: 
        !           502: /* Get whether the msg has changed since last saved. */
        !           503: 
        !           504: int MsgChanged(msg)
        !           505: Msg msg;
        !           506: {
        !           507:     return msg && msg->source && XtEDiskChanged(msg->source);
        !           508: }
        !           509: 
        !           510: 
        !           511: 
        !           512: /* Call the given function when the msg changes. */
        !           513: 
        !           514: void MsgSetCallOnChange(msg, func, param)
        !           515: Msg msg;
        !           516: void (*func)();
        !           517: caddr_t param;
        !           518: {
        !           519:     XtEDiskSetCallbackWhenChanged(msg->source, func, param);
        !           520: }
        !           521: 
        !           522: 
        !           523: 
        !           524: /* Call no function when the msg changes. */
        !           525: 
        !           526: void MsgClearCallOnChange(msg)
        !           527: Msg msg;
        !           528: {
        !           529:     XtEDiskSetCallbackWhenChanged(msg->source, NULL, (caddr_t) NULL);
        !           530: }
        !           531: 
        !           532: 
        !           533: /* Send (i.e., mail) the given message as is.  First break it up into lines,
        !           534:    and copy it to a new file in the process.  The new file is one of 10
        !           535:    possible draft files; we rotate amoung the 10 so that the user can have up
        !           536:    to 10 messages being sent at once.  (Using a file in /tmp is a bad idea
        !           537:    because these files never actually get deleted, but renamed with some
        !           538:    prefix.  Also, these should stay in an area private to the user for
        !           539:    security.) */
        !           540: 
        !           541: void MsgSend(msg)
        !           542: Msg msg;
        !           543: {
        !           544:     FILEPTR from;
        !           545:     FILEPTR to;
        !           546:     int     p, c, l, inheader, sendwidth, sendbreakwidth;
        !           547:     char   *ptr, *ptr2, **argv, str[100];
        !           548:     static sendcount = -1;
        !           549:     MsgSaveChanges(msg);
        !           550:     from = FOpenAndCheck(MsgFileName(msg), "r");
        !           551:     sendcount = (sendcount + 1) % 10;
        !           552:     (void) sprintf(str, "%s%d", xmhDraftFile, sendcount);
        !           553:     to = FOpenAndCheck(str, "w");
        !           554:     sendwidth = defSendLineWidth;
        !           555:     sendbreakwidth = defBreakSendLineWidth;
        !           556:     inheader = TRUE;
        !           557:     while (ptr = ReadLine(from)) {
        !           558:        if (inheader) {
        !           559:            if (strncmpIgnoringCase(ptr, "sendwidth:", 10) == 0) {
        !           560:                if (atoi(ptr+10) > 0) sendwidth = atoi(ptr+10);
        !           561:                continue;
        !           562:            }
        !           563:            if (strncmpIgnoringCase(ptr, "sendbreakwidth:", 15) == 0) {
        !           564:                if (atoi(ptr+15) > 0) sendbreakwidth = atoi(ptr+15);
        !           565:                continue;
        !           566:            }
        !           567:            for (l = 0, ptr2 = ptr ; *ptr2 && !l ; ptr2++)
        !           568:                l = (*ptr2 != ' ' && *ptr2 != '\t' && *ptr != '-');
        !           569:            if (l) {
        !           570:                (void) fprintf(to, "%s\n", ptr);
        !           571:                continue;
        !           572:            }
        !           573:            inheader = FALSE;
        !           574:            if (sendbreakwidth < sendwidth) sendbreakwidth = sendwidth;
        !           575:        }
        !           576:        do {
        !           577:            for (p = c = l = 0, ptr2 = ptr;
        !           578:                 *ptr2 && c < sendbreakwidth;
        !           579:                 p++, ptr2++) {
        !           580:                 if (*ptr2 == ' ' && c < sendwidth)
        !           581:                     l = p;
        !           582:                 if (*ptr2 == '\t') {
        !           583:                     if (c < sendwidth) l = p;
        !           584:                     c += 8 - (c % 8);
        !           585:                 }
        !           586:                 else
        !           587:                 c++;
        !           588:             }
        !           589:            if (c < sendbreakwidth) {
        !           590:                (void) fprintf(to, "%s\n", ptr);
        !           591:                *ptr = 0;
        !           592:            }
        !           593:            else
        !           594:                if (l) {
        !           595:                    ptr[l] = 0;
        !           596:                    (void) fprintf(to, "%s\n", ptr);
        !           597:                    ptr += l + 1;
        !           598:                }
        !           599:                else {
        !           600:                    for (c = 0; c < sendwidth; ) {
        !           601:                        if (*ptr == '\t') c += 8 - (c % 8);
        !           602:                        else c++;
        !           603:                        (void) fputc(*ptr++, to);
        !           604:                    }
        !           605:                    (void) fputc('\n', to);
        !           606:                }
        !           607:        } while (*ptr);
        !           608:     }
        !           609:     (void) myfclose(from);
        !           610:     (void) myfclose(to);
        !           611:     argv = MakeArgv(3);
        !           612:     argv[0] = "send";
        !           613:     argv[1] = "-push";
        !           614:     argv[2] = str;
        !           615:     DoCommand(argv, (char *) NULL, (char *) NULL);
        !           616:     XtFree((char *) argv);
        !           617: }
        !           618: 
        !           619: 
        !           620: /* Make the msg into the form for a generic composition.  Set msg->startPos
        !           621:    so that the text insertion point will be placed at the end of the first
        !           622:    line (which is usually the "To:" field). */
        !           623: 
        !           624: void MsgLoadComposition(msg)
        !           625: Msg msg;
        !           626: {
        !           627:     static char *blankcomp = NULL; /* Array containing comp template */
        !           628:     static int compsize = 0;
        !           629:     static XtTextPosition startPos;
        !           630:     char *file, **argv;
        !           631:     int fid;
        !           632:     if (blankcomp == NULL) {
        !           633:        file = MakeNewTempFileName();
        !           634:        argv = MakeArgv(4);
        !           635:        argv[0] = "comp";
        !           636:        argv[1] = "-file";
        !           637:        argv[2] = file;
        !           638:        argv[3] = "-nowhatnowproc";
        !           639:        DoCommand(argv, (char *) NULL, "/dev/null");
        !           640:        XtFree((char *) argv);
        !           641:        compsize = GetFileLength(file);
        !           642:        blankcomp = XtMalloc((unsigned) compsize);
        !           643:        fid = myopen(file, O_RDONLY, 0666);
        !           644:        if (compsize != read(fid, blankcomp, compsize))
        !           645:            Punt("Error reading in MsgLoadComposition!");
        !           646:        (void) myclose(fid);
        !           647:        DeleteFileAndCheck(file);
        !           648:        startPos = index(blankcomp, '\n') - blankcomp;
        !           649:     }
        !           650:     fid = myopen(MsgFileName(msg), O_WRONLY | O_TRUNC | O_CREAT, 0666);
        !           651:     if (compsize != write(fid, blankcomp, compsize))
        !           652:        Punt("Error writing in MsgLoadComposition!");
        !           653:     (void) myclose(fid);
        !           654:     TocSetCacheValid(msg->toc);
        !           655:     msg->startPos = startPos;
        !           656: }
        !           657: 
        !           658: 
        !           659: 
        !           660: /* Load a msg with a template of a reply to frommsg.  Set msg->startPos so
        !           661:    that the text insertion point will be placed at the beginning of the
        !           662:    message body. */
        !           663: 
        !           664: void MsgLoadReply(msg, frommsg)
        !           665: Msg msg, frommsg;
        !           666: {
        !           667:     char **argv;
        !           668:     char str1[100], str2[10];
        !           669:     TempMoveDraft();
        !           670:     argv = MakeArgv(4);
        !           671:     argv[0] = "repl";
        !           672:     (void) sprintf(str1, "+%s", frommsg->toc->foldername);
        !           673:     argv[1] = str1;
        !           674:     (void) sprintf(str2, "%d", frommsg->msgid);
        !           675:     argv[2] = str2;
        !           676:     argv[3] = "-nowhatnowproc";
        !           677:     DoCommand(argv, (char *) NULL, "/dev/null");
        !           678:     RenameAndCheck(draftFile, MsgFileName(msg));
        !           679:     RestoreDraft();
        !           680:     TocSetCacheValid(frommsg->toc); /* If -anno is set, this keeps us from
        !           681:                                       rescanning folder. */
        !           682:     TocSetCacheValid(msg->toc);
        !           683:     msg->startPos = GetFileLength(MsgFileName(msg));
        !           684: }
        !           685: 
        !           686: 
        !           687: 
        !           688: /* Load a msg with a template of forwarding a list of messages.  Set 
        !           689:    msg->startPos so that the text insertion point will be placed at the end
        !           690:    of the first line (which is usually a "To:" field). */
        !           691: 
        !           692: void MsgLoadForward(msg, mlist)
        !           693:   Msg msg;
        !           694:   MsgList mlist;
        !           695: {
        !           696:     char  **argv, str[100];
        !           697:     int     i;
        !           698:     TempMoveDraft();
        !           699:     argv = MakeArgv(3 + mlist->nummsgs);
        !           700:     argv[0] = "forw";
        !           701:     (void) sprintf(str, "+%s", mlist->msglist[0]->toc->foldername);
        !           702:     argv[1] = MallocACopy(str);
        !           703:     for (i = 0; i < mlist->nummsgs; i++) {
        !           704:         (void) sprintf(str, "%d", mlist->msglist[i]->msgid);
        !           705:         argv[2 + i] = MallocACopy(str);
        !           706:     }
        !           707:     argv[2 + i] = "-nowhatnowproc";
        !           708:     DoCommand(argv, (char *) NULL, "/dev/null");
        !           709:     for (i = 1; i < 2 + mlist->nummsgs; i++)
        !           710:         XtFree((char *) argv[i]);
        !           711:     XtFree((char *) argv);
        !           712:     RenameAndCheck(draftFile, MsgFileName(msg));
        !           713:     RestoreDraft();
        !           714:     TocSetCacheValid(msg->toc);
        !           715:     msg->source = XtCreateEDiskSource(MsgFileName(msg), XttextEdit);
        !           716:     msg->startPos = (*msg->source->scan)(msg->source, 0, XtstEOL, XtsdRight,
        !           717:                                         1, FALSE);
        !           718: }
        !           719: 
        !           720: 
        !           721: /* Load msg with a copy of frommsg. */
        !           722: 
        !           723: void MsgLoadCopy(msg, frommsg)
        !           724: Msg msg, frommsg;
        !           725: {
        !           726:     char str[500];
        !           727:     (void)strcpy(str, MsgFileName(msg));
        !           728:     CopyFileAndCheck(MsgFileName(frommsg), str);
        !           729:     TocSetCacheValid(msg->toc);
        !           730: }
        !           731: 
        !           732: 
        !           733: 
        !           734: /* Checkpoint the given message. */
        !           735: 
        !           736: void MsgCheckPoint(msg)
        !           737: Msg msg;
        !           738: {
        !           739:     if (msg && msg->source) {
        !           740:        XtEDiskMakeCheckpoint(msg->source);
        !           741:        TocSetCacheValid(msg->toc);
        !           742:     }
        !           743: }
        !           744: 
        !           745: 
        !           746: /* Free the storage being used by the given msg. */
        !           747: 
        !           748: void MsgFree(msg)
        !           749: Msg msg;
        !           750: {
        !           751:     XtFree(msg->buf);
        !           752:     XtFree((char *)msg);
        !           753: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.