File:  [OS/2 SDKs] / pmsdk / samples / newcard / cffile.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:28:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: pmsdk-1988, HEAD
Microsoft OS/2 SDK PM 08-08-1988

#define NOCOMM
#define NOVIRTUALKEYCODES
#define NOWINMESSAGES
#include "cardfile.h"

/*********************************************************************/
/*  Windows/PM Cardfile Shared Code                                  */
/*                                                                   */
/*  (c) Copyright Microsoft Corp. 1987,1988 - All Rights Reserved    */
/*********************************************************************/

/*********************************************************************/
/*    The following shared code was developed from the original      */
/* Cardfile application.  This code can be compiled to run under     */
/* either the Windows or the PM manager environment.  All            */
/* functionality associated with bitmaps or printing has been        */
/* deleted.  Some comments refering to these functions may still be  */
/* present in the code and should be disregarded. jw.                */
/*********************************************************************/


/*********************************************************************/
/*    This file contains the routines for writing and reading        */
/* information to the disk.  All of the procedures in this file      */
/* consist entirely of shared code.                                  */
/*********************************************************************/



/*********************************************************************/
/*                                                                   */
/* cardfile data files are layed out with the following format:      */
/* three magic bytes "MGC"                                           */
/* a word count of cards in the file                                 */
/* array of cardheaders, each one containing:                        */
/*                                                                   */
/*  char          reserved[6];        bytes available for future use */
/*  unsigned long lfData;             file offset of data            */
/*  unsigned char flags;              flags                          */
/*  char          line[LINELENGTH+1]; 40 character lines plus null   */
/*                                                                   */
/*  These are stored sorted in alphabetical order on the             */
/*  header (line).                                                   */
/*                                                                   */
/*  Following the headers are the cards' data.  lfData in a card's   */
/*  header points to somewhere in this area.  Each card's data is    */
/*  layed out like this:                                             */
/*                                                                   */
/*  unsigned bmSize;            size in bytes of the bitmap          */
/*      Ooops, this won't work so well when we get 64K bitmaps       */
/*  (Must be 0 for this time round!)                                 */
/*                                                                   */
/*  If bmSize is > 0 then the card has a bitmap, and then next       */
/*  bytes contain:                                                   */
/*                                                                   */
/*  int cxBitmap;           cx in pixels of bitmap                   */
/*  int cyBitmap;           cy in pixels of bitmap                   */
/*  int cxEighths;          (x coord of bitmap * 8) / cxFont         */
/*  int cyEighths;          (y coord of bitmap * 8) / cyFont         */
/*  BYTE  bmBits[bmSize]    bitmap bits                              */
/*                                                                   */
/*  The x and y coords are in the funny format so that the bitmap    */
/*  will appear in roughly the same place on the card on different   */
/*  displays.                                                        */
/*                                                                   */
/*  Following the bitmap information is the card's text              */
/*                                                                   */
/*  unsigned tSize;         size in bytes                            */
/*  char  Text[tSize];      text characters                          */
/*                                                                   */
/*                                                                   */
/*********************************************************************/


/*********************************************************************/
/* MergeCardFile -                                                   */
/*    Merges the file specified by pchName into the current file.    */
/*                                                                   */
/*    Same for PM and Windows                                        */
/*********************************************************************/

BOOL FAR MergeCardFile(pchName)
PSTR pchName;
    {
    int fh;
    unsigned i;
    char buf[PATHMAX];
    char MaGiC[4];
    OFSTRUCT mergereopen;
    LPSTR lpText;
    HANDLE hText;
    unsigned cMergeCards;
    unsigned tSize;
    unsigned lTemp;
    unsigned long lCurPos;
    int result = FALSE;

    /* if no extension, append the default one */
    AppendExtension(pchName, buf);

    /* open file */
    if ((fh = OpenFile((LPSTR)buf, (LPOFSTRUCT)&mergereopen, 
                       OF_PROMPT | OF_CANCEL)) < 0)
        return(FALSE);

    /* now read it in */
    /* check that the first three bytes signify a Cardfile */
    MaGiC[3] = 0;
    myread(fh, MaGiC, 3);
    if (Mylstrcmp(MaGiC, "MGC"))
        {
        CardfileOkError(IDS_ENOTVALIDFILE);
        goto MergeClean;
        }

    /* read the number of cards in the file */
    myread(fh, (PSTR)&cMergeCards, sizeof(int));

    /* allocate enough memory for the file */
    lTemp = (cCards+cMergeCards)*sizeof(CARDHEADER);
    if (!GlobalReAlloc(hCards, lTemp, GMEM_MOVEABLE))
        {
MergeInsMem:
        CardfileOkError(IDS_EINSMEMORY);
        goto MergeClean;
        }

    /* allocate a buffer for the text on the cards */
    hText = GlobalAlloc(GHND, (long)CARDTEXTSIZE);
    if (!hText)
        goto MergeInsMem;
    lpText = GlobalLock(hText);

    /* for each card in the merged file */
    for(i = 0; i < cMergeCards; ++i)
        {
        /* read its header */
        myread(fh, (PSTR)&CurCardHead, sizeof(CARDHEADER));
        /* save current position, and seek to the data */
        lCurPos = MyLseek(fh, 0L, 1);
        MyLseek(fh, CurCardHead.lfData, 0);

        CurCard.hBitmap = 0;

        /* if there's a bitmap, display an error */
        myread(fh, (PSTR)&CurCard.bmSize, sizeof(int));
        if (CurCard.bmSize)
            {
            CardfileOkError( IDS_NOBITMAP );
            goto MergeClean;
            }
         
        /* read text size */
        myread(fh, (PSTR)&tSize, sizeof(int));

        /* make sure text is no bigger than buffer */
        if (tSize >= CARDTEXTSIZE)
            tSize = CARDTEXTSIZE-1;

        /* read text */
        mylread(fh, (LPSTR)lpText, tSize);
        *(lpText+tSize) = 0;

        /* write out the card, so we'll be able to get it in the future */
        if (tSize = WriteCurCard(&CurCardHead, &CurCard, lpText))
            {
            iFirstCard = AddCurCard();
            }

        /* seek to next header */
        MyLseek(fh, lCurPos, 0);
        if (!tSize)
            goto MergeClean;
        }
    GlobalUnlock(hText);
    GlobalFree(hText);
    fFileDirty = TRUE;
    result = TRUE;
MergeClean:
    MyClose(fh);
    return(result);
    }

/*********************************************************************/
/* ReadCardFile -                                                    */
/*    Reads specified cardfile.                                      */
/*                                                                   */
/*    Same for PM and Windows                                        */
/*********************************************************************/

BOOL FAR ReadCardFile(pchName)
PSTR pchName;
    {
    int fh;
    LPCARDHEADER lpTCards;
    unsigned i;
    char buf[PATHMAX];
    char MaGiC[4];
    unsigned cNewCards;
    unsigned lTemp;
    int result = FALSE;
    OFSTRUCT tmpmain;

    /* if no extension, append the default */
    AppendExtension(pchName, buf);

    /* open file */
    if ((fh = OpenFile((LPSTR)buf, (LPOFSTRUCT)&tmpmain, 
                       OF_PROMPT | OF_CANCEL)) < 0)
        return(FALSE);

    /* now read it in, and verify that it's a cardfile */
    MaGiC[3] = 0;
    myread(fh, (PSTR)MaGiC, 3);
    if (Mylstrcmp(MaGiC, "MGC"))
        {
        CardfileOkError(IDS_ENOTVALIDFILE);
        goto ReadClean;
        }

    /* read the number of cards in the file */
    myread(fh, (PSTR)&cNewCards, sizeof(int));

    /* allocate the object to hold all the headers */
    lTemp = cNewCards * sizeof(CARDHEADER);
    if (!GlobalReAlloc(hCards, lTemp, GMEM_MOVEABLE))
        {
        CardfileOkError(IDS_EINSMEMORY);
        goto ReadClean;
        }
    /* save card count */
    cCards = cNewCards;
    lpTCards = (LPCARDHEADER) GlobalLock(hCards);

    /* for all cards */
    for(i = 0; i < cNewCards; ++i)
        {
        /* read the header, and save it */
        myread(fh, (PSTR)&CurCardHead, sizeof(CARDHEADER));
        *lpTCards++ = CurCardHead;
        }
    GlobalUnlock(hCards);
    fFileDirty = FALSE;

    mainreopen = tmpmain;     /* save new OFSTRUCT */
    Mylstrcpy((LPSTR)CurIFile, (LPSTR)mainreopen.szPathName);
    result = TRUE;
ReadClean:
    MyClose(fh);
    return(result);
    }

/*********************************************************************/
/* AppendExtension -                                                 */
/*    This routine checks for an extension, and if none exists,      */
/* appends the default (CRD).  A single '.' denotes an extension, so */
/* here is what this routine will do:                                */
/*    FOO     -> FOO.CRD                                             */
/*    FOO.    -> FOO.                                                */
/*    FOO.BAR -> FOO.BAR                                             */
/*                                                                   */
/*    Same for PM and Windows                                        */
/*********************************************************************/

void FAR AppendExtension(pchName, pchBuf)
PSTR pchName;
PSTR pchBuf;
    {
    char *pch1;
    char ch;

    /* save name */
    Mylstrcpy((LPSTR)pchBuf, (LPSTR)pchName);

    /* get to end */
    pch1 = pchBuf + Mylstrlen((LPSTR)pchBuf);

    /* scan backwards for beginning or end of filename */
    while ((ch = *pch1) != '.' && ch != '\\' && ch != ':' && pch1 > pchBuf)
        pch1 = FAR_TO_NEAR( AnsiPrev((LPSTR)pchBuf, (LPSTR)pch1) );

    /* if no '.', need to tack on extension */
    if (*pch1 != '.')
        Mylstrcat((LPSTR)pchBuf, (LPSTR)".CRD");

    /* what the heck, upper case it */
    AnsiUpper((LPSTR)pchBuf);
    }

/*********************************************************************/
/* WriteCardFile -                                                   */
/*    This routine writes out a cardfile                             */
/*                                                                   */
/*    Same for PM and Windows                                        */
/*********************************************************************/

BOOL FAR WriteCardFile(pchName)
PSTR pchName;
    {
    LPCARDHEADER lpTCards = NULL;       /* so cleaning works */
    char bakName[PATHMAX];
    unsigned i;
    int fhBak;
    int fhDollar;
    int fhOld;
    int fh;
    unsigned long lCurLoc;
    unsigned long lCardData;
    unsigned bmSize;
    HANDLE hText;
    LPSTR lpText;
    char buf[PATHMAX];
    unsigned tSize;
    int fSameFile;
    char *pchFileName;
    int result = FALSE;
    CARDHEADER CardHeader;
    LPCARDHEADER lpCards;
    OFSTRUCT bakofStruct;

    /* if no extension, append the default one */
    AppendExtension(pchName, buf);

    /* if saving to same file, need to save out to temporary one */
    if (fSameFile = !Mylstrcmp(buf, CurIFile))
        {
        /* get a tempfile name */
        if(!GetTempFileName(CurIFile[0] | TF_FORCEDRIVE, (LPSTR)"CRD", 0, 
                            (LPSTR)bakName))
            goto SaveTempProblem;
        }
    else
        /* otherwise, just save to specified file */
        Mylstrcpy((LPSTR)bakName, (LPSTR)buf);

    /* open the new file */
    fhBak = OpenFile((LPSTR)bakName, (LPOFSTRUCT)&bakofStruct, OF_CREATE);
    /* open files */
    if (CurIFile[0])
        pchFileName = CurIFile;
    else
        pchFileName = rgchCardData;
    /* open temporary file */
    if (fReadOnly)
        goto SaveTempProblem;

    fhDollar = OpenFile((LPSTR)pchFileName, (LPOFSTRUCT)&tmpreopen, 
                        OF_PROMPT | OF_REOPEN | 2);
    if (fhDollar == -1)
        {
SaveTempProblem:
        CardfileOkError(IDS_EDISKFULLFILE);
        return(FALSE);
        }
    if (fhBak < 0)
        {
        goto CantMakeFile;
        }
    /* if curifile is null, then won't use fhOld */
    if (CurIFile[0])
        fhOld = OpenFile((LPSTR)CurIFile, (LPOFSTRUCT)&mainreopen, 
                         OF_PROMPT | OF_REOPEN);

    if (MyLseek(fhBak, 0L, 0) == -1)
        {
        if (CurIFile[0])
            MyClose(fhOld);
CantMakeFile:
        MyClose(fhDollar);
        CardfileOkError(IDS_ECANTMAKEFILE);
        return(FALSE);
        }
    /* truncate file */
    mywrite(fhBak, (PSTR)"", 0);

    /* write out cardfile magic bytes */
    mywrite(fhBak, (PSTR)"MGC", 3);

    /* write the number of cards in the file */
    mywrite(fhBak, (PSTR)&cCards, sizeof(int));
    lCardData = MyLseek(fhBak, 0L, 1) + (cCards * sizeof(CARDHEADER));

    /* allocate buf for card text */
    hText = GlobalAlloc(GHND, (long)CARDTEXTSIZE);
    if (!hText) 
       {
       MyClose(fhBak);
       MyClose(fhOld);
       MyClose(fhDollar);
       Fdelete(bakName);
       CardfileOkError(IDS_EINSMEMORY);
       goto WriteFileClean;
       }

    lpText = (LPSTR)GlobalLock(hText);

    /* lock down the card headers */
    lpCards = lpTCards = (LPCARDHEADER) GlobalLock(hCards);

    /* for each card in file */
    for(i = 0; i < cCards; ++i)
        {
        /* see where the card's data is */
        if (lpTCards->flags & FTMPFILE)
            fh = fhDollar;
        else
            fh = fhOld;
        /* seek to data */
        MyLseek(fh, lpTCards->lfData, 0);
        /* get header */
        CardHeader = *lpTCards++;
        /* clear out tmpfile bit */
        CardHeader.flags &= (!FTMPFILE);
        CardHeader.lfData = lCardData;
        /* write header */
        if (mylwrite(fhBak, (LPSTR)&CardHeader, sizeof(CARDHEADER)) 
             < sizeof(CARDHEADER))
            goto WFDiskFull;
        lCurLoc = MyLseek(fhBak, 0L, 1);
        /* seek to data spot in new file */
        MyLseek(fhBak, lCardData, 0);
        myread(fh, (PSTR)&bmSize, sizeof(int));
        mywrite(fhBak, (PSTR)&bmSize, sizeof(int));

        /* save text */
        myread(fh, (PSTR)&tSize, sizeof(int));
        if (mywrite(fhBak, (PSTR)&tSize, sizeof(int)) < sizeof(int))
            goto WFDiskFull;
        mylread(fh, (LPSTR)lpText, tSize);
        if (mylwrite(fhBak, (LPSTR)lpText, tSize) < tSize)
            {
WFDiskFull:
            MyClose(fhBak);
            MyClose(fhOld);
            MyClose(fhDollar);
            Fdelete(bakName);
            CardfileOkError(IDS_EDISKFULLFILE);
            goto WriteFileClean;
            }

        lCardData = MyLseek(fhBak, 0L, 1);
        MyLseek(fhBak, lCurLoc, 0);
        }
    MyClose(fhBak);
    if (CurIFile[0])
        MyClose(fhOld);
    MyLseek(fhDollar, 0L, 0);
    mywrite(fhDollar, (PSTR)"", 0);
    MyClose(fhDollar);
    if (fSameFile)
        {
        Fdelete(buf);
        Frename(bakName, buf);
        fhOld = OpenFile((LPSTR)buf, (LPOFSTRUCT)&mainreopen, 2);
        }
    else
        {
        AnsiUpper((LPSTR)CurIFile);
        fhOld = OpenFile((LPSTR)bakName, (LPOFSTRUCT)&mainreopen, 2);
        }

    Mylstrcpy((LPSTR)CurIFile, (LPSTR)mainreopen.szPathName);

    MyLseek(fhOld, 5L, 0);
    lpTCards = lpCards;
    for(i = 0; i < cCards; ++i)
        {
        myread(fhOld, (PSTR)&CardHeader, sizeof(CARDHEADER));
        *lpTCards++ = CardHeader;
        }
    MyClose(fhOld);
    fFileDirty = FALSE;
    result = TRUE;
WriteFileClean:
    if (hText)
        {
        GlobalUnlock(hText);
        GlobalFree(hText);
        }
    if (lpTCards)
        GlobalUnlock(hCards);
    return(result);
    }

/*********************************************************************/
/* WriteCurCard -                                                    */
/*    Write out the data for the current card                        */
/*                                                                   */
/*    Same for PM and Windows                                        */
/*********************************************************************/

BOOL FAR WriteCurCard(pCardHead, pCard, lpText)
PCARDHEADER pCardHead;
PCARD pCard;
LPSTR lpText;
    {
    int fh;
    unsigned long lEnd;
    int zero = 0;
    unsigned tSize;
    char *pchFileName;
    unsigned cchWritten;

    /* get right string in case of error */
    if (CurIFile[0])
        pchFileName = CurIFile;
    else
        pchFileName = rgchCardData;

    /* open temp file, if necessary asking for it */
   
    fh = OpenFile((LPSTR)pchFileName, (LPOFSTRUCT)&tmpreopen, 
                  OF_CANCEL | OF_PROMPT | OF_REOPEN | 2);
    if (fh == -1)
        {
        CardfileOkError(IDS_EOPENTEMPSAVE);
        return(FALSE);
        }

    /* seek to end of temp file */
    lEnd = MyLseek(fh, 0L, 2);

    mywrite(fh, (PSTR)&zero, sizeof(int));

    /* save text */
    tSize = Mylstrlen((LPSTR)lpText);
    if (tSize >= CARDTEXTSIZE)
        tSize = CARDTEXTSIZE-1;
    if (mywrite(fh, (PSTR)&tSize, sizeof(int)) < sizeof(int))
        goto WCDiskFull;
    cchWritten = mylwrite(fh, (LPSTR)lpText, tSize);
    MyClose(fh);
    if (cchWritten < tSize)
        {
WCDiskFull:
        CardfileOkError(IDS_EDISKFULLSAVE);
        return(FALSE);
        }
    pCardHead->flags |= FTMPFILE;
    pCardHead->lfData = lEnd;
    return(TRUE);
    }

/*********************************************************************/
/* ReadCurData -                                                     */
/*    Read current card's data                                       */
/*                                                                   */
/*    Same for PM and Windows                                        */
/*********************************************************************/

BOOL FAR ReadCurCardData(pCardHead, pCard, lpText)
PCARDHEADER pCardHead;
PCARD pCard;
LPSTR lpText;
    {
    int fh;
    unsigned tSize;
    char *pchFileName;
    int result = TRUE;

    /* assume no bitmap */
    pCard->hBitmap = 0;

    /* if a new card, then can't get it out of any file */
    if (pCardHead->flags & FNEW)
        {
        /* no text */
        lpText = (LPSTR)"";
        return(result);
        }

    /* if data is in temp file, get the right file handle */
    if (pCardHead->flags & FTMPFILE)
        {
        if (CurIFile[0])
            pchFileName = CurIFile;
        else
            pchFileName = rgchCardData;
        fh = OpenFile((LPSTR)pchFileName, (LPOFSTRUCT)&tmpreopen, 
                      OF_PROMPT | OF_REOPEN | 2);
        }
    else
        fh = OpenFile((LPSTR)CurIFile, (LPOFSTRUCT)&mainreopen, 
                      OF_PROMPT | OF_REOPEN);

    /* seek to data */
    MyLseek(fh, pCardHead->lfData, 0);

    /* This must be 0 */
    myread(fh, (PSTR)&(pCard->bmSize), sizeof(int));

    /* read text */
    myread(fh, (PSTR)&tSize, sizeof(int));
    if (tSize >= CARDTEXTSIZE)
        tSize = CARDTEXTSIZE-1;
    mylread(fh, (LPSTR)lpText, tSize);
    *(lpText+tSize) = 0;
    MyClose(fh);
    return (result);
}

/*********************************************************************/
/* MakeTmpFile -                                                     */
/*    Create a temporary file, with a random name provided by system */
/*                                                                   */
/*    Same for PM and Windows                                        */
/*********************************************************************/

void FAR MakeTmpFile()
    {
    int  fh;

    if(GetTempFileName(CurIFile[0], (LPSTR)"CRD", 0, (LPSTR)TmpFile))
        {
        if ((fh = OpenFile((LPSTR)TmpFile, (LPOFSTRUCT)&tmpreopen, 
                           OF_CREATE)) < 0)
            goto CantMakeTmp;
        else
            MyClose(fh);
        }
    else
        {
        /* if can't make temp file, mark "read only", although I'm sure */
        /* this readonly stuff doesn't work well.  Should rarely happen. */
CantMakeTmp:
        CardfileOkError(IDS_ECANTMAKETEMP);
        fReadOnly = TRUE;
        }
    }


unix.superglobalmegacorp.com

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