/************************************************************/
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
/************************************************************/

/* trans4.c -- routines brought from trans2.c due to compiler stack overflow */

#define NOWINMESSAGES
#define NOVIRTUALKEYCODES
#define NOWINSTYLES
#define NOCLIPBOARD
#define NOGDICAPMASKS
#define NOSYSMETRICS
#define NOMENUS
#define NOKEYSTATE
#define NOGDI
#define NORASTEROPS
#define NOSYSCOMMANDS
#define NOSHOWWINDOW
#define NOCOLOR
#define NOATOM
#define NOBITMAP
#define NOICON
#define NOBRUSH
#define NOCREATESTRUCT
#define NOMB
#define NOFONT
#define NOMSG
#define NOOPENFILE
#define NOPEN
#define NOPOINT
#define NOREGION
#define NOSCROLL
#define NOSOUND
#define NOWH
#define NOWINOFFSETS
#define NOWNDCLASS
#define NOCOMM
#include <windows.h>

#include "mw.h"
#include "doslib.h"
#include "propdefs.h"
#define NOUAC
#include "cmddefs.h"
#include "docdefs.h"
#include "filedefs.h"
#include "fkpdefs.h"
#include "editdefs.h"
#include "printdef.h"
#define NOKCCODES
#include "ch.h"
#define NOSTRUNDO
#define NOSTRERRORS
#include "str.h"
#include "debug.h"
#include "fontdefs.h"


CHAR    *PchGetPn();
CHAR    *PchFromFc();
typePN  PnAllocT2();
struct  PGTB **HpgtbGet();


extern int             vfnWriting;
extern struct BPS      *mpibpbps;
extern typeTS          tsMruBps;
extern int             vibpWriting;
extern CHAR            (**vhrgbSave)[];
extern struct DOD      (**hpdocdod)[];
extern int             docCur;
extern int             docMac;
extern int             docScrap;
extern int             docUndo;
extern struct FCB      (**hpfnfcb)[];
extern int             fnMac;
extern int             wwMac;
extern int             vfBuffersDirty;
extern int             vfDiskFull;
extern int             vfDiskError;
extern typeCP          vcpFetch;
extern CHAR            *vpchFetch;
extern int             vccpFetch;
extern typeFC          fcMacPapIns;
extern typeFC          fcMacChpIns;
extern typeCP          vcpLimParaCache;
extern struct FKPD     vfkpdCharIns;
extern struct FKPD     vfkpdParaIns;
extern struct PAP      vpapPrevIns;
extern struct PAP      vpapAbs;
extern struct PAP      *vppapNormal;
extern struct CHP      vchpNormal;
extern struct CHP      vchpInsert;
extern struct CHP      vchpFetch;
extern unsigned        cwHeapFree;
extern struct FPRM     fprmCache;

extern int              ferror;
extern CHAR             szExtBackup[];
extern CHAR             (**hszTemp)[];

#ifdef INTL /* International version */

extern int  vWordFmtMode; /* used during saves. If false, no conversion is
			      done. True is convert to Word format,CVTFROMWORD
			      is translate chars from Word character set at
			      save */
#endif  /* International version */


/***        WriteUnformatted - Write unformatted document to file
 *
 *
 *
 */


WriteUnformatted(fn, doc)
int fn;
int doc;
{
 extern typeCP vcpLimParaCache;
 extern typeCP cpMinCur, cpMacCur;
 typeCP cpMinCurT = cpMinCur;
 typeCP cpMacCurT = cpMacCur;
 typeCP cpNow;
 typeCP cpLimPara;
 typeCP cpMac = (**hpdocdod) [doc].cpMac;

 /* Expand range of interest to whole document (for CachePara) */

 cpMinCur = cp0;
 cpMacCur = cpMac;

 /* Loop on paras */

 cpNow = cp0;
 for ( cpNow = cp0; cpNow < cpMac; cpNow = cpLimPara )
    {
LRestart:    
    CachePara( doc, cpNow );
    cpLimPara = vcpLimParaCache;
    if (vpapAbs.fGraphics)
        continue;

    /* Now write out the para, a run at a time */

                
    while ((cpNow < cpLimPara && cpNow < cpMacCur) 
		   && !(vfDiskFull || vfDiskError))
        {
		extern typeCP CpMin();
        extern int vccpFetch;
        int ccpAccept;
		CHAR bufT[cbSector + 1];
		CHAR *pch;

        FetchCp( doc, cpNow, 0, fcmChars + fcmNoExpand );
		Assert (vccpFetch <= cbSector);
#ifdef WINVER >= 0x300        
        if (vccpFetch == 0)
            {
            /* In this case we've had an error with a "hole" in the
               the piece table due to hitting a mem-alloc error -- we 
               won't ever advance cpNow!  To get around this we bump 
               cpNow to the cpMin of the next piece and continue by 
               doing a CachePara on the next piece  3/14/90..pault */

            struct PCTB *ppctb = *(**hpdocdod)[doc].hpctb;
            int ipcd = IpcdFromCp(ppctb, cpNow);
            struct PCD *ppcd = &ppctb->rgpcd[ipcd + 1]; /* NEXT piece */

            cpNow = ppcd->cpMin;
            goto LRestart;
            }
#endif
        ccpAccept = (int) CpMin( (typeCP)vccpFetch, (cpLimPara - cpNow));

#ifdef INTL /* International version */
		if (vWordFmtMode != TRUE)  /* no character set conversion */
#endif  /* International version */

			WriteRgch( fn, vpchFetch, ccpAccept );

#ifdef INTL /* International version */
        else   /* convert to OEM set */
			{
			 /* convert ANSI chars to OEM for Word format file */
			/* load chars into bufT and translate to OEM
			 chars, and write out */
			pch = (CHAR *) bltbyte(vpchFetch, bufT, 
			  (int)ccpAccept);
			*pch = '\0';
			AnsiToOem((LPSTR)bufT, (LPSTR)bufT);
			WriteRgch(fn, bufT, (int)ccpAccept);
		   }
#endif  /* International version */

        cpNow += ccpAccept;
        }
        if ((vfDiskFull || vfDiskError))
                break;

    }

 /* Restore cpMinCur, cpMacCur */

 cpMinCur = cpMinCurT;
 cpMacCur = cpMacCurT;
}




/***        PurgeTemps - Delete all temporary files not referenced in any doc
 *
 */

PurgeTemps()
{ /* Delete all temporary files not referenced in any doc */
int fn;
struct FCB *pfcb, *mpfnfcb;
struct DOD *pdod;
struct PCD *ppcd;
int doc;

Assert(fnScratch == 0);
FreezeHp();
mpfnfcb = &(**hpfnfcb)[0];

#ifdef DFILE
    CommSz("PurgeTemps:\n\r");
#endif

/* Prime the doc/piece table loop */
/* Find the first valid doc (there is guaranteed to be one) */
/* Set up doc, pdod, ppcd */
for (doc = 0, pdod = &(**hpdocdod)[0]; pdod->hpctb == 0; doc++, pdod++)
        continue;
ppcd = &(**pdod->hpctb).rgpcd[0];

/* Now go through the deletable files, looking for references */
for (fn = fnScratch + 1, pfcb = &mpfnfcb[fnScratch + 1];
    fn < fnMac; fn++, pfcb++)
        { /* For each file (don't bother with scratch file) */
        /* Fn must be valid, deletable, and not previously referenced */
        /* if (pfcb->rfn != rfnFree && pfcb->fDelete && !pfcb->fReferenced &&
            fn != fnPrint) */
        if (pfcb->rfn != rfnFree && pfcb->fDelete && !pfcb->fReferenced)
                { /* For each deletable fn */
                int fnT;

                for (;;)
                        { /* Until we determine there is or isn't a ref */
                        if (doc >= docMac)
                                goto OutOfDocs;
                        while ((fnT = ppcd->fn) == fnNil)
                                { /* End of pctb */
#ifdef CASHMERE
                                struct SETB **hsetb = pdod->hsetb;
                                if (hsetb != 0)
                                        { /* Check section table. Doesn't need to be quite
                                                as smart as piece table checker; smaller. */
                                        int csed = (**hsetb).csed;
                                        struct SED *psed = &(**hsetb).rgsed[0];
                                        while (csed--)
                                                {
                                                fnT = psed->fn;
                                                if (fnT == fn) /* Referenced. */
                                                        goto NextFn;
                                                if (fnT > fn) /* Future fn referenced */
                                                        mpfnfcb[fnT].fReferenced = true;
                                                psed++;
                                                }
                                        }
#endif
                                while (++doc < docMac && (++pdod)->hpctb == 0)
                                        continue;
                                if (doc >= docMac)
                                    {
OutOfDocs:                            /* No references to this fn, delete it */
                                    MeltHp();
#ifdef DFILE
        {
        char rgch[200];
        wsprintf(rgch,"    fn %d, %s \n\r", fn,(LPSTR)(**pfcb->hszFile));
        CommSz(rgch);
        }
#endif        
                                    FDeleteFn(fn);    /* HEAP MOVEMENT */
                                    FreezeHp();

                                    /* NOTE: Once we get here, there is no   */
                                    /* further use of pdod or ppcd; we zip   */
                                    /* through the remaining fn's and just   */
                                    /* test fcb fields.  Therefore, pdod     */
                                    /* and ppcd are not updated although     */
                                    /* there was (maybe) heap movement above */

                                    mpfnfcb = &(**hpfnfcb)[0];
                                    pfcb = &mpfnfcb[fn];

                                    goto NextFn;
                                    }
                                ppcd = &(**pdod->hpctb).rgpcd[0];
                                }
                        if (fnT == fn) /* A reference to this fn */
                                goto NextFn;
                        if (fnT > fn) /* Ref to a future fn */
                                mpfnfcb[fnT].fReferenced = true;
                        ++ppcd;
                        }
                }
        else
                pfcb->fReferenced = false;
NextFn: ;
        }
MeltHp();
}


#if WINVER >= 0x300
/* We only use one document at a time, thus in general we won't have
   doc's referencing pieces from multiple fns (unless they've been 
   pasted and reference docscrap or something).  

   In any case we want to free up these files esp. for network user 
   convenience.  The dilemma in particular is when someone's opened
   a file on the net and then does a File.New, File.SaveAs, or File.Open
   and is using another file -- we don't release the previous one so
   another user will get a sharing error even though it seems that file
   should be free!

   Modeled after PurgeTemps() above  ..pault 10/23/89 */

void FreeUnreferencedFns()
    {
    int fn;
    struct FCB *pfcb, *mpfnfcb;
    struct DOD *pdod;
    struct PCD *ppcd;
    int doc;

    Assert(fnScratch == 0);
    FreezeHp();
    mpfnfcb = &(**hpfnfcb)[0];
    
    /* Prime the doc/piece table loop */
    /* Find the first valid doc (there is guaranteed to be one) */
    /* Set up doc, pdod, ppcd */
    for (doc = 0, pdod = &(**hpdocdod)[0]; pdod->hpctb == 0; doc++, pdod++)
        continue;
    ppcd = &(**pdod->hpctb).rgpcd[0];
#ifdef DFILE
    CommSz("FreeUnreferencedFns: \n\r");
#endif

    for (fn = fnScratch + 1, pfcb = &mpfnfcb[fnScratch + 1]; fn < fnMac; fn++, pfcb++)
        { /* For each file (don't bother with scratch file) */
        
#ifdef DFILE
        {
        char rgch[200];
        wsprintf(rgch,"    fn %d, %s \trfnFree %d fRefd %d fDelete %d  ",
                fn,(LPSTR)(**pfcb->hszFile),pfcb->rfn==rfnFree,pfcb->fReferenced,pfcb->fDelete);
        CommSz(rgch);
        }
#endif        
        /* For each unreferenced fn, we ask: is this file the current
           document being edited?  If so then we definitely don't want
           to free up the file.  However PREVIOUS documents that were
           being edited can now "be free".  Temp files are not freed
           here because we want them to be remembered so they are deleted
           at the end of the Write session 2/1/90 ..pault */
        
        if ((WCompSz(*(**hpdocdod)[ docCur ].hszFile,**pfcb->hszFile)==0)
            || pfcb->fDelete)
            goto LRefd;
        else if (pfcb->rfn != rfnFree && !pfcb->fReferenced)
            {
            int fnT;

            for (;;)
                { /* Until we determine there is or isn't a ref */
                if (doc >= docMac)
                    {
                    goto OutOfDocs;
                    }
                while ((fnT = ppcd->fn) == fnNil)
                    { /* End of pctb */
                    while (++doc < docMac && (++pdod)->hpctb == 0)
                        continue;
                    if (doc >= docMac)
                        {
OutOfDocs:              /* No references to this fn, delete it */

                        MeltHp();
#ifdef DFILE
                        CommSz(" FREEING!");
#endif                        
                        FreeFn(fn);    /* HEAP MOVEMENT */
                        FreezeHp();

                        /* NOTE: Once we get here, there is no   */
                        /* further use of pdod or ppcd; we zip   */
                        /* through the remaining fn's and just   */
                        /* test fcb fields.  Therefore, pdod     */
                        /* and ppcd are not updated although     */
                        /* there was (maybe) heap movement above */

                        mpfnfcb = &(**hpfnfcb)[0];
                        pfcb = &mpfnfcb[fn];

                        goto NextFn;
                        }
                    ppcd = &(**pdod->hpctb).rgpcd[0];
                    }
                if (fnT == fn) /* A reference to this fn */
                    {
                    goto NextFn;
                    }
                if (fnT > fn) /* Ref to a future fn */
                    {
                    mpfnfcb[fnT].fReferenced = true;
                    }
                ++ppcd;
                }
            }
        else
            {
LRefd:
            pfcb->fReferenced = false;
            }
NextFn: ;
#ifdef DFILE
        CommSz("\n\r");
#endif        
        }
    MeltHp();
    }
#endif /* WIN30 */
