#pragma title ("LSICINI.C - UPDATE INI FUNCTIONS")
/*******************************************************************************
*                                                                              *
* Module Name     : LSICINI.C                                                  *
*                                                                              *
* Description     : ASCII .INI file routines (i.e. IBMLAN.INI)                 *
*                                                                              *
* Copyright       : OCO source materials                                       *
*                   (C) Copyright IBM Corp. 1990                               *
*                                                                              *
* External Module : LANINST.EXE                                                *
*                                                                              *
* Status (Level)  : Version(0), Level(0.0)                                     *
*                                                                              *
* Function        : Routines to Query, Update or add, and delete entries       *
*                   in text based INI files.                                   *
*                                                                              *
* Restrictions    : These routines will not work with .INI files that          *
*                   are in binary form, such as OS2.INI.                       *
* Dependencies    : The structure of the .INI file is the same as IBMLAN.INI.  *
* Other Effects   : None.                                                      *
* Invocation      : Routines are called during INI file creations or Updates   *
*                                                                              *
* External                                                                     *
* References      : Lower level string and file functions in LSICLOWL.C        *
*                                                                              *
* Parameters      :                                                            *
*    Input        : parm1      - Description of the parameter                  *
*                   parm2      - Description of the parameter                  *
*                                                                              *
*    Output       : parmx      - Description of the parameter                  *
*                                                                              *
* Exit            :                                                            *
*    Normal       : Describe what this module does when it exits under normal  *
*                   conditions.                                                *
*                                                                              *
*    Error        : Describe what this module does when it exits under an error*
*                   condition.                                                 *
*                                                                              *
* Sub-routines    :                                                            *
*                                                                              *
*    Function Name: Function name                                              *
*                                                                              *
*    Function     : Description of what it does                                *
*    Other Effects: Other effects this function may have                       *
*    External                                                                  *
*    References   : Other functions referenced by this module                  *
*    Parameters   :                                                            *
*       Input     : parm1      - Description of the parameter                  *
*                   parm2      - Description of the parameter                  *
*       Output    : parmx      - Description of the parameter                  *
*    Exit         :                                                            *
*       Normal    : Describe what this module does when it exits under normal  *
*                   conditions.                                                *
*       Error     : Describe what this module does when it exits under an error*
*                   condition.                                                 *
*                                                                              *
* Change Activity :                                                            *
*                                                                              *
* DCR/PTR        Rel. Date     Init Description                                *
*
*******************************************************************************/
#define INCL_DOSERRORS
#define INCL_BASE

#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <os2me.h>
//#include "mdmi.h"
//#include "mdmextrn.h"
//#include "mmpmini.h"                   /* DosError Flags                   */
#include "vsdini.h"


/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: IniQuery                                                º */
/* º                                                                      º */
/* º      Query entries in the .INI file                                  º */
/* º                                                                      º */
/* º    Input parameters:                                                 º */
/* º      pszFileBuff      Pointer where the search is to start from      º */
/* º      pszSection       Section (field between []) containing entry    º */
/* º      pszEntry         Entry (field left of '=') to query             º */
/* º      pszRetValue      Storage buffer where the value is copied.      º */
/* º                                                                      º */
/* º    Output parameters:                                                º */
/* º      pszLineFound     Beginning of line (if located) in the buffer   º */
/* º                                                                      º */
/* º    Returns:           Return code.                                   º */
/* º                         INI_OK          Successful                   º */
/* º                         INI_NO_SECTION  Section not found            º */
/* º                         INI_NO_ENTRY    Entry not found              º */
/* º                         INI_MEM_ALLOC   Error on buffer allocation   º */
/* º                                                                      º */
/* º   Psuedo code:                                                       º */
/* º                                                                      º */
/* º     Build the section field (put [] around it)                       º */
/* º     Search for the section                                           º */
/* º     if found                                                         º */
/* º       get the next line                                              º */
/* º       loop until entry is found, next section, or INI end            º */
/* º        if the line starts the next section stop loop                 º */
/* º        else                                                          º */
/* º         format the line                                              º */
/* º         if what's left of = matches entry                            º */
/* º           find len of value and alloc memory for it                  º */
/* º           copy value to buffer                                       º */
/* º         else                                                         º */
/* º           get next line                                              º */
/* º                                                                      º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG IniQuery(                  /* Returns a return code.                 */

   PSZ    pszFileBuffer,          /* File buffer (from ReadFileToBuffer)    */
   PSZ    pszSection,             /* Section (field between [] )            */
   PSZ    pszEntry,               /* Entry (field to the left of '=')       */
   PSZ    *pszLineFound,          /* Beginning of located line in file buff */
   PSZ    pszValue   )            /* Returned value for the entry.          */
                                  /* ...This space is reserved by IniQuery  */

{
 ULONG  uRetCode;                          /* Return code.                 */
 PSZ    pszPos;                             /* Position ptr in the buffer   */
 CHAR   szEntryField[128];                  /* Entry with equal at end      */
 CHAR   szIniLine[256];                     /* Buffer for a line of the file*/
 BOOL   fIsSection;                         /* Indicates line starts section*/
 PSZ    pszTemp;                            /* Position ptr in temp line    */
 ULONG  cbValueLen;                         /* Length of the entry's value  */
 CHAR   pszSectionLow[256];                 /* Section field in lower case  */
 CHAR   pszEntryLow[256];                   /* Entry field in lower case    */

 uRetCode = INI_NO_SECTION;                /* Init to nothing found        */
 *pszLineFound = NULL;

 strcpy(szEntryField,"");                   /* Build the entry field        */
 strcpy(pszSectionLow,pszSection);
 strlwr(pszSectionLow);                     /* convert to lower case        */
 strcpy(pszEntryLow,pszEntry);
 strlwr(pszEntryLow);                       /* convert to lower case        */
 BuildEntry (pszEntryLow,szEntryField);

                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Find the section           ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
 pszPos = FindSection (pszFileBuffer, pszSectionLow);

                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Find the entry             ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
 if (pszPos != NULL)                        /* If section was found above   */
   {
    uRetCode = INI_NO_ENTRY;               /* Section found, entry not yet */
    for ( pszPos = NextLine(pszPos),        /* Next line after found section*/
            fIsSection = FALSE;             /* Flag now means next section  */
          uRetCode == INI_NO_ENTRY  &&     /* While not found and          */
            fIsSection == FALSE      &&     /* ...haven't hit next section  */
            pszPos != NULL;                 /* ...and not end of file       */
          pszPos = NextLine(pszPos)         /* Check next line              */
        )
      {
       CopyLine (pszPos, szIniLine);
       if (szIniLine[0] != ';')
         {
          if (SectionStart(szIniLine))      /* If line starts next section  */
             fIsSection = TRUE;
          else
            {
             FormatEntryLine (szIniLine);

             if (strnicmp (szIniLine,
                           szEntryField,
                           strlen(szEntryField)) == 0)
               {
                pszTemp = (PSZ) ((ULONG)szIniLine + (ULONG)strlen(szEntryField));
                cbValueLen = strlen (pszTemp);

//              *pszValue = (PSZ) ((ULONG)szIniLine + (ULONG)strlen(szEntryField));
                strcpy (pszValue, pszTemp);
                *pszLineFound = pszPos;     /* Ret ptr to located line */
                uRetCode = INI_OK;
               }                            /* if entry found               */
            }                               /* else not another section     */
         }                                  /* if not a comment             */
      }                                     /* For loop checking for entry  */
   }                                        /* if section found             */
 return (uRetCode);
}                                           /* IniQuery                     */


/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: IniUpdate                                               º */
/* º                                                                      º */
/* º      Changes entries in the .INI file                                º */
/* º                                                                      º */
/* º    Input parameters:                                                 º */
/* º      pszFileBuff      Pointer where the search is to start from      º */
/* º      pszSection       Section (field between []) containing entry    º */
/* º      pszEntry         Entry (field left of '=') to update            º */
/* º      pszValue         New value of the entry                         º */
/* º                                                                      º */
/* º    Output parameters:                                                º */
/* º      None                                                            º */
/* º                                                                      º */
/* º    Returns:           Return code.                                   º */
/* º                         INI_OK          Successful                   º */
/* º                                                                      º */
/* º   Psuedo code:                                                       º */
/* º                                                                      º */
/* º      If section not found add it                                     º */
/* º      Locate section                                                  º */
/* º      If entry not found in section add it                            º */
/* º      Locate entry                                                    º */
/* º      Insert new entry, overlay all past '=' up to next line          º */
/* º                                                                      º */
/* º                                                                      º */
/* º                                                                      º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG  IniUpdate(                 /* Returns a return code.                 */

   PSZ    pszFileBuffer,          /* File buffer (from ReadFileToBuffer)    */
   PSZ    pszSection,             /* Section (field between [] )            */
   PSZ    pszEntry,               /* Entry (field to the left of '=')       */
   PSZ    pszValue       )        /* New value for the entry.               */


{
 ULONG  uQueryRC;                          /* IniQuery return code         */
 PSZ    pszLineFound;                       /* Ptr to line start where      */
                                            /* ...query was found           */
 PSZ    pszQueryValue;                      /* Value from query (not used)  */
 PSZ    pszPos;                             /* Position ptr in buffer       */
 PSZ    pszLastEntry;                       /* Last entry in section        */
 BOOL   fNextSection;                       /* Next section located         */
 CHAR   szField[128];                       /* Formed section or entry field*/
 CHAR   szIniLine[256];                     /* Buffer for a line of the file*/
 CHAR   szQueryValue[256];                  /* Value from query (not used)  */


                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Query for existing         ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/


  uQueryRC = IniQuery(pszFileBuffer, pszSection, pszEntry,
                         &pszLineFound, (PSZ)szQueryValue);
                                            /* See if section & entry exist */
                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ No section                 ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
  if (uQueryRC == INI_NO_SECTION)           /* If the section is not there  */
    {
     strcpy(szField,"");                    /* Build the section field      */
     BuildSection (pszSection, szField);
     AppendLine (pszFileBuffer, szField);   /* Put new section at end       */
     uQueryRC = INI_NO_ENTRY;               /* It now needs an entry        */
     if (!(strcmp(pszEntry,"")))            /* No Entry to Add              */
        return (INI_OK);
    }

                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ No entry under the section ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
  if (uQueryRC == INI_NO_ENTRY)            /* If no entry under the section*/
    {
     pszLastEntry =
     pszPos = FindSection (pszFileBuffer, pszSection);
                                            /* Find specified section.      */
                                            /* It'll be there since it was  */
                                            /* ...added above if it wasn't  */
                                            /* ...already there             */

                                            /* Find last valid line (not    */
                                            /* ...just CRLF) in the section */
     for (pszPos = NextLine(pszPos),        /* Start at next valid          */
            fNextSection = FALSE;           /* Haven't hit next section     */
          fNextSection == FALSE   &&        /* While not at next section and*/
            pszPos != NULL;                 /* ...not at the end of buffer  */
          pszPos = NextLine(pszPos)         /* Next line                    */
         )
       {
           CopyLine (pszPos, szIniLine);    /* Copy a line to a temp buffer */
           if (SectionStart(szIniLine))     /* If line starts next section  */
              fNextSection = TRUE;          /* ...stop the search           */
           else                             /* Else save as the last valid  */
              pszLastEntry = pszPos;        /* ...line in the section       */
       }

     strcpy (szField,"  ");                 /* Build the entry= (but    P2C */
     BuildEntry (pszEntry, szField);        /* ...not the value just yet)   */
                                            /* Build the entry field        */
     pszPos = strstr(pszLastEntry, CRLF);   /* Find 1st CRLF after start of */
                                            /* ...last entry                */
     if (pszPos == NULL)                    /* If there is none (last entry */
       {                                    /* ...is last of file & has no  */
                                            /* ...CRLF at end)              */
        AppendLine (pszFileBuffer, szField); /* ..then append entry at end  */
       }
     else
       {
        pszPos += strlen(CRLF);
        strcat (szField, CRLF);
        InsertString(szField,
                     pszPos,
                     pszPos);
       }

     uQueryRC = IniQuery(pszFileBuffer, pszSection, pszEntry,
                          &pszLineFound, (PSZ)szQueryValue);
                                            /* Now locate the line          */
    }

  pszPos = strchr (pszLineFound, EQUAL) + 1;
  pszPos = pszPos + strspn(pszPos, BLANK_TAB);

  InsertString (pszValue,
                pszPos,
                strpbrk(pszPos, EOFLINE) );

 return (uQueryRC);
}                                           /* IniUpdate                    */


/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: IniDelete                                               º */
/* º                                                                      º */
/* º      Deletes entries in the .INI file                                º */
/* º                                                                      º */
/* º    Input parameters:                                                 º */
/* º      pszFileBuff      Pointer where the search is to start from      º */
/* º      pszSection       Section (field between []) containing entry    º */
/* º      pszEntry         Entry (field left of '=') to delete            º */
/* º                        or NULL to delete an entire section           º */
/* º                                                                      º */
/* º    Output parameters:                                                º */
/* º      None                                                            º */
/* º                                                                      º */
/* º    Returns:           Return code.                                   º */
/* º                         INI_OK          Successful                   º */
/* º                         INI_NO_SECTION  Section not found            º */
/* º                         INI_NO_ENTRY    Entry not found              º */
/* º                                                                      º */
/* º   Psuedo code:                                                       º */
/* º     Locate section                                                   º */
/* º     If found                                                         º */
/* º       If entry is specified                                          º */
/* º         locate entry                                                 º */
/* º         if found                                                     º */
/* º           delete up to next line                                     º */
/* º         else rc = entry not found                                    º */
/* º       else (delete whole section)                                    º */
/* º         delete everything up to the next section                     º */
/* º                                                                      º */
/* º                                                                      º */
/* º     else rc = not found                                              º */
/* º                                                                      º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG  IniDelete(                 /* Returns a return code.                 */

   PSZ    pszFileBuffer,          /* File buffer (from ReadFileToBuffer)    */
   PSZ    pszSection,             /* Section (field between [] )            */
   PSZ    pszEntry       )        /* Entry (field to the left of '=')       */
                                  /* ...or NULL to delete an entire section */


{
 ULONG  uRetCode=INI_OK;                   /* Return code.                 */
 PSZ    pszNukeStart;                       /* Ptr to where delete begins   */
 PSZ    pszNukeUpTo;                        /* Delete from found location   */
                                            /* ...up to this character      */
 PSZ    pszQueryValue;                      /* Value from query (not used)  */
 PSZ    pszPos;                             /* Temp position pointer        */
 CHAR   szIniLine[256];                     /* Buffer for a line of the file*/
 CHAR   pszSectionLow[256];                 /* Section field in lower case  */
 CHAR   szQueryValue[256];                  /* Value from query (not used)  */

 if (pszEntry == NULL)
   {                                        /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Delete entire section      ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
    strcpy(pszSectionLow,pszSection);
    strlwr(pszSectionLow);                  /* convert to lower case        */
    pszNukeStart = FindSection(pszFileBuffer, pszSectionLow);
                                            /* Locate section to delete     */
    if (pszNukeStart != NULL)               /* If found nuke up to next     */
      {                                     /* ---Find the next section---  */
       for (pszPos= NextLine(pszNukeStart), /* Start search at next line    */
              pszNukeUpTo = NULL;           /* Haven't hit next section     */
            pszNukeUpTo == NULL &&          /* While not at next section and*/
              pszPos != NULL;               /* ...not at the end of buffer  */
            pszPos = NextLine(pszPos)       /* Next line                    */
           )
         {
             CopyLine (pszPos, szIniLine);  /* Copy a line to a temp buffer */
             if (SectionStart(szIniLine))   /* If line starts next section  */
                pszNukeUpTo = pszPos;       /* ...stop the search           */
         }
       if (pszNukeUpTo == NULL)
          pszNukeUpTo = strchr (pszNukeStart, EOFFILE);
                                            /* If no other section (end of  */
                                            /* ...buffer) nuke up to EOF    */
       ScootString (pszNukeUpTo, (LONG)pszNukeStart - (LONG)pszNukeUpTo);
                                            /* Scoot string 'left' to delete*/
      }
    else                                    /* Else can't find section to   */
       uRetCode = INI_NO_SECTION;          /* ...delete                    */
   }                                        /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
 else                                       /*³ Delete only 1 entry        ³*/
   {                                        /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
    uRetCode = IniQuery(pszFileBuffer, pszSection, pszEntry,
                         &pszNukeStart, (PSZ)szQueryValue);
                                            /* Find the entry in the section*/
    if (uRetCode == INI_OK)
      {
       pszNukeUpTo = strstr (pszNukeStart, CRLF);
       if (pszNukeUpTo == NULL)
          pszNukeUpTo = strchr (pszNukeStart, EOFFILE);
       else
          pszNukeUpTo += strlen(CRLF);
       ScootString (pszNukeUpTo, (ULONG)pszNukeStart - (ULONG)pszNukeUpTo);
      }

   }
 return (uRetCode);
}                                           /* IniDelete                    */


/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: BuildSection                                            º */
/* º                                                                      º */
/* º      Builds the section field in a supplied buffer                   º */
/* º      The field is concatenated on to accommodate leading blanks      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
VOID BuildSection(
     PSZ    pszSection,                /* Section (without brackets)        */
     PSZ    pszSectionField )          /* Area to store result              */

{
 CHAR   szSectionLow[128];                /* Section with brackets around */

 strcpy (szSectionLow,pszSection);
 strlwr (szSectionLow);                     /* convert to lower case        */
 strcat (pszSectionField, "[");             /* Build the section field      */
 strcat (pszSectionField, szSectionLow);    /*                              */
 strcat (pszSectionField, "]");             /*                              */
 return;
}                                           /* BuildSection                 */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: BuildEntry                                              º */
/* º                                                                      º */
/* º      Builds the entry field in a supplied buffer                     º */
/* º      The field is concatenated on to accommodate leading blanks      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
VOID BuildEntry(
     PSZ    pszEntry,                       /* Entry (without '=' after it)      */
     PSZ    pszEntryField )                 /* Area to store result              */
{
 strcat (pszEntryField, pszEntry);          /* Build the entry field        */
 strcat (pszEntryField, "=");
 return;
}                                           /* BuildEntry                   */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: FindSection                                             º */
/* º                                                                      º */
/* º      Returns a pointer to the line where a specifed section starts   º */
/* º      or NULL if the section is not found.                            º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
PSZ  FindSection(
     PSZ    pszFileBuffer,             /* Ptr to start of buffer            */
     PSZ    pszSection )               /* Section to locate                 */
{
 PSZ    pszSectionLine;                     /* Returned pointer             */
 PSZ    pszPos;                             /* Temporary position pointer   */
 CHAR   szSectionField[128];                /* Section with brackets around */
 CHAR   szIniLine[256];                     /* Buffer for a line of the file*/

 strcpy (szSectionField,"");
 BuildSection (pszSection, szSectionField); /* Build the section field      */


// if (pszLastSectionFound != NULL)
//    {
//    CopyLine (pszLastSectionFound, szIniLine); /* Copy a line to a temp buffer */
//    strlwr(szIniLine);                   /* convert to lower case        */
//    if (szIniLine[0] != ';'  &&          /* If not a comment line        */
//        strstr (szIniLine,               /* ...and the [section] is found*/
//                szSectionField) != NULL) /* ...in the line then          */
//       {
//       pszSectionLine = pszLastSectionFound;          /* ...found. Stop the search    */
//       return(pszSectionLine);                    /* Ptr to start of line or NULL */
//       }
//    }

 for (pszPos = pszFileBuffer,               /* Search from specified start  */
        pszSectionLine = NULL;              /* Nothing found yet            */
      pszSectionLine == NULL   &&           /* While not found and          */
        pszPos != NULL;                     /* ...not at the end of buffer  */
      pszPos = NextLine(pszPos)             /* Next line                    */
     )
   {
       CopyLine (pszPos, szIniLine);        /* Copy a line to a temp buffer */
       strlwr(szIniLine);                   /* convert to lower case        */
       if (szIniLine[0] != ';'  &&          /* If not a comment line        */
           strstr (szIniLine,               /* ...and the [section] is found*/
                   szSectionField) != NULL) /* ...in the line then          */
          {
          pszSectionLine = pszPos;          /* ...found. Stop the search    */
//          pszLastSectionFound = pszPos;
          }
   }

 return(pszSectionLine);                    /* Ptr to start of line or NULL */
                                            /* ...if not found by loop      */
}                                           /* FindSection                  */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: SectionStart                                            º */
/* º                                                                      º */
/* º      Returns a boolean indicating if a given line starts a section   º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
BOOL SectionStart(
     PSZ    pszIniLine )               /* Line of the INI file to check     */
{
 BOOL   fIsSectionStart;                    /* Returned boolean             */

 if (pszIniLine[0] != ';'            &&     /* If not a comment line        */
     strchr (pszIniLine,'[') != NULL &&     /* ...and both a '[' and ']'    */
     strchr (pszIniLine,']') != NULL    )   /* ...exist in the line         */
    fIsSectionStart = TRUE;                 /* ...it is a section delimiter */
 else
    fIsSectionStart = FALSE;

 return(fIsSectionStart);
}                                           /* SectionStart                 */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: FormatEntryLine                                         º */
/* º                                                                      º */
/* º      Formats an entry line of an ascii INI file by removing          º */
/* º      selected white space.  Statements will be put in the            º */
/* º      following format                                                º */
/* º        entry=value                                                   º */
/* º      White space before and after entry, and white space just        º */
/* º      after '=' will be removed. White space at the end of value      º */
/* º      is also removed.  If for some reason the value has white        º */
/* º      space imbedded within it will not be removed.                   º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
VOID FormatEntryLine(
     PSZ    pszFormatted  )            /* Line to format                    */
{
 PSZ   pszNextWhite;                   /* Next white space in line          */
 PSZ   pszEqualChar;                   /* First '=' assignment in line      */

 StripFrontWhite (pszFormatted);            /* If blanks or tabs at front   */
                                            /* ...strip them off            */



 pszEqualChar = strchr(pszFormatted, EQUAL);/* Get ptr to 1st '='           */
 if (pszEqualChar != NULL)                  /* If an '=' is found           */
   {
                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Strip blanks before =      ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
    pszNextWhite = strpbrk(pszFormatted,    /* Get ptr to first white space */
                           BLANK_TAB);
    if (pszNextWhite != NULL &&             /* If there is white space and  */
        pszNextWhite <  pszEqualChar)       /* ...it's before the = strip it*/
      {
       StripFrontWhite (pszNextWhite);
      }
                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Strip blanks just after =  ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
    pszEqualChar = strchr(pszFormatted, EQUAL);
                                            /* Relocate the 1st '='         */
    StripFrontWhite (pszEqualChar + 1);
   }                                        /* If '=' found                 */
                                            /* Else no '='.  Don't format   */
 return;
}                                           /* FormatEntryLine              */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: IniParseEntryLine                                       º */
/* º                                                                      º */
/* º      Parse the entry line starting at offset iIndex,                 º */
/* º      untile a token is delimited by blank, comma, or EOL.            º */
/* º                                                                      º */
/* º      Convert the token to the requested datatype,                    º */
/* º      specified by uTokenType, and place the value in pTokenVaule     º */
/* º      then update index.                                              º */
/* º                                                                      º */
/* º                                                                      º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG IniParseEntryLine(
     PSZ      pFormatted,                   /* Line to format               */
     PULONG   pulIndex,
     ULONG    ulTokenBufLen,
     PVOID    pTokenValue,
     ULONG    ulTokenType)


{
 ULONG  i = 0;                              /* counter                        */
 PSZ    pszNumString;                       /* Current token                  */
 PSZ    pszTokenStart;                      /* start of Token                 */
 PSZ    pszTokenEnd;                        /* end of Token                   */
 PVOID  pTokenValEnd;                       /* Token Line                     */
 CHAR   delimiter[3];                       /* valid delimiters               */
 CHAR   seperator[1];                       /* next seperator                 */
 CHAR   quote[2];                           /* delimiters for Quote           */
 ULONG  ulToken;
 ULONG  uByteCount;                         /* length of Token String       */
 ULONG  ulRetCode;
 BOOL   FirstTime = TRUE;
 BOOL   NullToken = FALSE;                  /* ALK */
 CHAR    temp[1];                           /* ALK */
 CHAR    temp2[1];                          /* ALK */

    delimiter[0] = COMMA;
//  delimiter[1] = BLANK;
    delimiter[1] = QUOTE;
    delimiter[2] = '\0';
    quote[0]     = QUOTE;
    quote[1]     = '\0';

    pszTokenStart = pFormatted;             /* Start of next token           */
    pszTokenEnd   = pFormatted;             /* End of next token             */

    do                                /*                               */
      {
      pszTokenStart = pszTokenEnd;             /* Start of next token           */
      do
        {
         NullToken = FALSE;                 /* ALK  may not be the selected token*/
         if (!FirstTime)
           {
            strncpy(temp,pszTokenStart,1);      /* ALK */
            pszTokenStart++;
            strncpy(temp2,pszTokenStart,1);     /* ALK */
            if ((strncmp(temp,temp2,1)==0) && (temp[0] == COMMA))    /* ALK */
              {
                NullToken = TRUE;            /* ALK need to increment token ct*/
                i++;
              }

           }
         else
           {
            FirstTime = FALSE;
            strncpy(temp,pszTokenStart,1);      /* ALK */
            if (temp[0] == COMMA)                  /* ALK */
              {
                NullToken = TRUE;            /* ALK need to increment token ct*/
                i++;
              }
           }
         pszTokenEnd = strpbrk(pszTokenStart,delimiter);
         if (pszTokenEnd != END_OF_STRING)
           {
            strncpy(seperator,pszTokenEnd,1);
            if (seperator[0] == QUOTE)
              {
               pszTokenStart++;
               pszTokenEnd = strpbrk(pszTokenStart,quote);
              }
           }
        }
      while((pszTokenStart==pszTokenEnd)&&(pszTokenEnd != NULL)
             && (i < *pulIndex));
         if (!NullToken)
           {
            i++;
           }
      }
    while ((i<*pulIndex) && (pszTokenEnd != NULL) );
    if ( i == *pulIndex)
      {
       (*pulIndex)++;
       switch (ulTokenType)
         {
      case T_STRING:

        if ((temp[0] == temp2[0]) && (temp[0] == COMMA))    /* ALK  if comma comma*/
          {
            strncpy(pTokenValue,"",1);           /* ALK */
          }
        else
          {
            if (pszTokenEnd == END_OF_STRING)
              {
               uByteCount = strlen(pszTokenStart);
              }
            else
              {
               uByteCount = pszTokenEnd-pszTokenStart;
              }
            if (uByteCount < ulTokenBufLen)
              {
               strncpy(pTokenValue,   /* convert token to req data   */
                       pszTokenStart,
                       uByteCount);
               pTokenValEnd=(PVOID)((ULONG)pTokenValue + uByteCount);
               strncpy(pTokenValEnd,  /* convert token to req data   */
                       "",
                       1);
              }
            else
              {
               ulRetCode = INI_BUFLEN_TOO_SMALL;
              }
            } /* ALK if not comma comma */
            break;

       case T_NUMERIC:
        if ((temp[0] == temp2[0]) && (temp[0] == COMMA))    /* ALK  if comma comma*/
          {
            *(PULONG)pTokenValue= 0L;                       /* ALK */
          }
        else
          {
            DosAllocMem ( (PVOID *) pszNumString, (ULONG) (256),
                     PAG_COMMIT | PAG_READ | PAG_WRITE);
            *pszNumString = '\0';
            if (pszTokenEnd == END_OF_STRING)
              {
               uByteCount = strlen(pszTokenStart);
              }
            else
              {
               uByteCount = pszTokenEnd-pszTokenStart;
              }
            if (uByteCount < 256)
              {
               strncat(pszNumString,              /* convert token to req data   */
                       pszTokenStart,
                       uByteCount);
               ulToken = atol(pszNumString);      /* convert token to req data   */
               *(PULONG)pTokenValue= ulToken;
               DosFreeMem (pszNumString);
              }
            else
              {
               ulRetCode = INI_BUFLEN_TOO_SMALL;
              }
           } /* ALK if not comma comma */
            break;
        }                                      /* End Switch                  */
      ulRetCode = INI_OK;
    }
  else
    {
     ulRetCode = INI_INDEX_TOO_LARGE;
    }
 return (ulRetCode);
}                                               /* IniParseEntryLine       */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: AppendLine                                              º */
/* º                                                                      º */
/* º      Adds a given string as a the last line of a buffer.             º */
/* º      If a CRLF isn't at the end of the previous last it              º */
/* º      is added.                                                       º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
VOID AppendLine(
     PSZ    pszBuffer,                 /*                                   */
     PSZ    pszNewLine )               /*                                   */
{
 PSZ pszEndOfFile;                     /* Ptr to EOF char in the buffer     */
 PSZ pszPos;                           /* A positioning ptr in the buffer   */
 PSZ pszAfterLastCRLF;                 /* Char after last CRLF in buffer    */


 pszEndOfFile = strchr (pszBuffer, EOFFILE);
                                            /* Find the end of the buffer   */
                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Find last CRLF in buffer   ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
 for (pszPos = pszBuffer;                   /* Start from beginning         */
      pszPos != NULL;                       /* Until no more CRLF found     */
      pszPos = strstr (pszPos,CRLF)         /* Find next CRLF               */
     )
   {
    pszPos += strlen(CRLF);                 /* Advance to 1st char beyond   */
    pszAfterLastCRLF = pszPos;              /* ...this CRLF                 */
   }

 if (pszAfterLastCRLF != pszEndOfFile)      /* If a CRLF is not the last    */
   {                                        /* ...thing in the file         */
    InsertString (CRLF,                     /* Add one                      */
                  pszEndOfFile,             /* ...before the EOF            */
                  pszEndOfFile);            /* ...saving the EOF            */
    pszEndOfFile += strlen(CRLF);           /* Adjust for added CRLF        */
   }

 InsertString (pszNewLine,                  /* Now add the new string       */
               pszEndOfFile,
               pszEndOfFile);
 pszEndOfFile += strlen(pszNewLine);
 InsertString (CRLF,                        /* and place a CRLF at the end  */
               pszEndOfFile,
               pszEndOfFile);
 return;
}                                           /* AppendLine                   */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: IniAppendToken                                          º */
/* º                                                                      º */
/* º      Append a token to the end of a token string                     º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
BOOL   IniAppendToken(
          PSZ      pszValueString,               /* Line to format               */
          ULONG    uValueBufLen,
          PVOID    pTokenValue,
          ULONG    uTokenType)


{
 PSZ    pszConvert;                         /* Line to format               */
 ULONG  uTokenValueSize;
 ULONG  uValueStringSize;
 BOOL   RetCode;
 ULONG  temp;

   uValueStringSize = strlen(pszValueString);
   if (uValueStringSize != 0)               /* not new(or null) string */
     {
      pszValueString = strcat(pszValueString,",");/* separate token by comma*/
     }
   switch (uTokenType)
      {
       case T_STRING:
          uTokenValueSize = strlen(pTokenValue);  /* find size of token     */
          if ((uValueStringSize + uTokenValueSize) <= uValueBufLen)
            {
             pszValueString = strcat(pszValueString,pTokenValue);
             RetCode=APPEND_OK;
            }
          else
            {
             RetCode=BUFFER_TOO_SMALL;
            }
          break;
       case T_NUMERIC:
          DosAllocMem ( (PVOID *) pszConvert, (ULONG) (256),
                       PAG_COMMIT | PAG_READ | PAG_WRITE);
          *pszConvert = '\0';
          temp = *(PULONG)pTokenValue;
          pszConvert=(PSZ)ltoa(temp,pszConvert,10);

          uTokenValueSize = strlen(pszConvert);
          if ((uValueStringSize + uTokenValueSize) <= uValueBufLen)
            {
             pszValueString = strcat(pszValueString,pszConvert);
             RetCode=APPEND_OK;
            }
          else
            {
             RetCode=BUFFER_TOO_SMALL;
            }
          DosFreeMem ( (PVOID *) pszConvert);
          break;
      }

 return (RetCode);
}                                               /* ConvertEntryLine          */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: IniKeyWordQuery                                         º */
/* º                                                                      º */
/* º      Query Keywords in the .INI file                                 º */
/* º                                                                      º */
/* º    Input parameters:                                                 º */
/* º      pszFileBuff      Pointer where the search is to start from      º */
/* º      pszSection       Section (field between []) containing entry    º */
/* º                                                                      º */
/* º    Output parameters:                                                º */
/* º      pszKeysFound     Beginning of line which contains               º */
/* º      pszRetValue      Storage buffer where the value is copied.      º */
/* º                          This memory is allocated by this routine.   º */
/* º                                                                      º */
/* º    Returns:           Return code.                                   º */
/* º                         INI_OK          Successful                   º */
/* º                         INI_NO_SECTION  Section not found            º */
/* º                         INI_NO_ENTRY    Entry not found              º */
/* º                         INI_MEM_ALLOC   Error on buffer allocation   º */
/* º                                                                      º */
/* º   Psuedo code:                                                       º */
/* º                                                                      º */
/* º     Build the section field (put [] around it)                       º */
/* º     Search for the section                                           º */
/* º     if found                                                         º */
/* º       get the next line                                              º */
/* º       loop until next section, or INI end                            º */
/* º        if the line starts the next section stop loop                 º */
/* º        else                                                          º */
/* º         format the line                                              º */
/* º         if what's left of = matches entry                            º */
/* º           find len of value and alloc memory for it                  º */
/* º           copy value to buffer                                       º */
/* º         else                                                         º */
/* º           get next line                                              º */
/* º                                                                      º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG  IniKeywordQuery(           /* Returns a return code.                 */

   PSZ           pszFileBuffer,   /* File buffer (from ReadFileToBuffer)    */
   PSZ           pszSection,      /* Section Name                           */
   PSZ           pszKeywordList,  /* Buffer for keywords                    */
   ULONG         uKeyBufLen)      /* Length of keyword  buffer              */

{
 ULONG  uRetCode;                          /* Return code.                 */
 PSZ    pszPos;                             /* Position ptr in the buffer   */
 CHAR   szIniLine[256];                     /* Buffer for a line of the file*/
 PSZ    pszIniLineEnd;                      /* pointer to end of keyword    */
 BOOL   fIsSection;                         /* Indicates line starts section*/
 CHAR   pszSectionLow[256];                 /* Section field in lower case  */
 ULONG  uByteCount;                         /* length of keyword            */


 uRetCode = INI_NO_SECTION;                /* Init to section not found    */


                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Find the section           ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
 strcpy(pszSectionLow,pszSection);
 strlwr(pszSectionLow);                     /* convert to lower case        */
 pszPos = FindSection (pszFileBuffer, pszSectionLow);

                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Find the entry             ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
 if (pszPos != NULL)                        /* If section was found above   */
   {
    for ( pszPos = NextLine(pszPos),        /* Next line after found section*/
            fIsSection = FALSE;             /* Flag now means next section  */
            fIsSection == FALSE      &&     /* ...haven't hit next section  */
            pszPos != NULL;                 /* ...and not end of file       */
          pszPos = NextLine(pszPos)         /* Check next line              */
        )
      {
       CopyLine (pszPos, szIniLine);
       if (szIniLine[0] != ';')             /* if line not a comment        */
         {
          if (SectionStart(szIniLine))      /* If line starts next section  */
             fIsSection = TRUE;
          else
            {
             FormatEntryLine (szIniLine);   /* get rid of blanks            */
                                            /* find end of keyword          */
             pszIniLineEnd = strchr(szIniLine,EQUAL);

                                            /* find length of keyword       */
             uByteCount = (ULONG)pszIniLineEnd - (ULONG)&szIniLine;

                                            /* if buffer large enough       */
                                            /* copy keyword to keyword list */
             if ((strlen(pszKeywordList) + uByteCount) < uKeyBufLen)
               {
                strncat((char *) pszKeywordList,
                       (const char *) &szIniLine,
                       (ULONG) uByteCount);

                                            /* seperate by a blank          */
                strcat(pszKeywordList,
                                " ");
                uRetCode = INI_OK;
               }
             else
               {
                uRetCode = INI_BUFLEN_TOO_SMALL;
               };
            };
         };

      };
   };
 return (uRetCode);
}                                               /* ConvertEntryLine          */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: NextLine                                                º */
/* º                                                                      º */
/* º    Finds the next line after a specified spot in a file buffer.      º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
PSZ NextLine(                          /* * * * * * * * * * * * * * * * * * */
                                       /* Returns pointer to the next line  */
                                       /* ...or NULL if end of file         */
             PSZ    pszPos)            /* Get next line after this position */
{

   pszPos = (PSZ)strpbrk(pszPos,EOFLINE);
                                       /* Find first CR, LF, or EOF (strpbrk*/
                                       /* ...finds 1st of str2 in str1)     */
   while (*pszPos == CR ||             /* Skip over carriage returns and    */
          *pszPos == LF    )           /* ...line feeds                     */
      pszPos++;

   return((*pszPos == EOFFILE)?NULL:pszPos);
                                       /* If at end of file return 0        */
                                       /* ...else return pointer            */

}   /* NextLine() */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: CopyLine                                                º */
/* º                                                                      º */
/* º    Copies a line of a file to a buffer                               º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
VOID CopyLine(
              PSZ pszPos,              /* Starting position to copy from    */
              PSZ pszBuffer)           /* Buffer to copy the line to        */
{
   ULONG   uCharsToCopy;              /* Number of characters to copy      */

   uCharsToCopy = strcspn(pszPos,EOFLINE);
   strncpy (pszBuffer,
            pszPos,
            uCharsToCopy);
   *(pszBuffer+uCharsToCopy) = '\0';

}                                           /* CopyLine                     */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: StripFrontWhite                                         º */
/* º                                                                      º */
/* º      Strips the white space off the front of a string.               º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
VOID StripFrontWhite(
     PSZ    pszStrip )            /* String to strip                        */
{
 LONG  cbStartJunk;                         /* White space at the beginning */
                                            /* ... of the line              */
 cbStartJunk = strspn (pszStrip, BLANK_TAB);
                                            /* Get # of blanks and tabs at  */
                                            /* ...the front of the string   */
 if (cbStartJunk)                           /* If there are some there      */
    ScootString(pszStrip+cbStartJunk,       /* ...strip them off by 'shift' */
                -cbStartJunk);              /* ...to the left               */
 return;
}                                           /* StripFrontWhite              */

/****************************************************************************/
/* Steve Dobbelstein's routines                                             */
/****************************************************************************/
/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: ScootString                                             º */
/* º                                                                      º */
/* º    Shifts or scoots the remainder of a string to the right or        º */
/* º    left.  Given a pointer into the string, the rest of the string    º */
/* º    will scoot a given number (positive or negative) of bytes.        º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */

CHAR * ScootString(CHAR *pchString, LONG sNumBytes)
   {
   CHAR * pchSource;
   CHAR * pchTarget;
   ULONG  cbLength;
   signed int chDirection;

   if(pchString != NULL)
      {
      if(sNumBytes != 0)
         {
         cbLength = StringLength(pchString);
         if(sNumBytes > 0)
            {
            chDirection = -1;
            pchSource = pchString + cbLength;
            }
         else
            {
            chDirection = 1;
            pchSource = pchString;
            }
         pchTarget = pchSource + sNumBytes;
         cbLength++;

         while(cbLength)
            {
            *pchTarget = *pchSource;
            pchSource += chDirection;
            pchTarget += chDirection;
            cbLength--;
            }

         }
      return(pchString + sNumBytes);
      }
   else
      {
      return(pchString);
      }
   }                                            /*                          */

ULONG  StringLength(CHAR *pchLine)
   {
   ULONG  cchStringLength;

   for(cchStringLength = 0;                     /*                          */
       pchLine[cchStringLength] != '\0';
       cchStringLength++);

   return(cchStringLength);
   }                                            /*                          */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: InsertString                                            º */
/* º                                                                      º */
/* º    Inserts a new string into a buffer at a particular location.      º */
/* º    Appends what's after a second specified location.                 º */
/* º    Can be used to either insert or overlay portions of the buffer.   º */
/* º                                                                      º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
LONG  InsertString(
                                       /* Returns the adjusted size in bytes*/
       PSZ    pszInsert,               /* String to insert                  */
       PSZ    pszInsertAt,             /* Position to insert it at          */
       PSZ    pszSaveAfter)            /* Everything beyond this location   */
                                       /* ...is appended after insert string*/
                                       /* ...If == pszInsertAt then insert  */
                                       /* ...Otherwise pszInsert replaces   */
                                       /* ...from pszInsertAt - pszSaveAfter*/
                                       /* ...Must be beyond pszInsertAt     */
{
   LONG  cbInsertLen;
   LONG  cbDelChars;

   cbInsertLen = strlen(pszInsert);
   cbDelChars  = pszSaveAfter - pszInsertAt;

   if (cbInsertLen != cbDelChars)
      ScootString (pszSaveAfter, (cbInsertLen-cbDelChars));

  CopyNBytes (pszInsertAt, pszInsert, cbInsertLen);
  return(cbInsertLen - cbDelChars);    /* Return the size of the adjustment */
                                       /* ...This is the # of chars inserted*/
                                       /* ...minus the  # of chars deleted  */

}

/*****************************************************************************/

CHAR * CopyNBytes(CHAR *pchTarget, CHAR *pchSource, ULONG cbNumBytes)
   {
   ULONG  ichIndex;

   for(ichIndex = 0; ichIndex < cbNumBytes; ichIndex++)
      {
      pchTarget[ichIndex] = pchSource[ichIndex];
      }

   return(pchTarget);
   }

/*****************************************************************************/

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: ReadFileToBuffer                                        º */
/* º                                                                      º */
/* º      Reads a given file into a memory buffer allocated by this       º */
/* º      routine.  An ASCIIZ '\0' is appended to the end so the buffer   º */
/* º      can be treated as one long string.  The buffer is 4K larger     º */
/* º      than the file to allow expansion.  Files > (64K-4K) can't       º */
/* º      be used by this routine.                                        º */
/* º      The routine also appends an EOF character (x1A) at the          º */
/* º      end if one isn't there already.  This additional character      º */
/* º      is not reflected in the returned usFileSize, allowing a         º */
/* º      caller to figure if it was added (by comparing usFileSize       º */
/* º      to strlen(pszBuffer) ) and strip if desired.                    º */
/* º                                                                      º */
/* º                                                                      º */
/* º    Input parameters:                                                 º */
/* º      pszFileName      Full drive, path, and name of file             º */
/* º      fsOpenMode       Mode in which to open the file                 º */
/* º                                                                      º */
/* º    Output parameters:                                                º */
/* º      pszBuffer        Buffer allocated by this proc                  º */
/* º      ulFileSize       Size in bytes of the file                      º */
/* º      hfHandle         File handle, needed to write file              º */
/* º                                                                      º */
/* º    Returns:           Function return code.  RF_xxx in LIB_DEFS.H    º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG ReadFileToBuffer(
                                       /* Returns a return code             */
       PSZ    pszFileName,             /* Full drive, path, and name of file*/
       ULONG  fsOpenMode,              /* Mode in which to open the file    */
                                       /* Values returned.......            */
       PSZ    *pszBuffer,              /* Buffer allocated by this proc     */
       PULONG  pulFileSize,             /* Size in bytes of the file         */
       PHFILE  phfHandle          )     /* File handle, needed to write file */
{
 ULONG      ulAction;                  /* Action taken by DosOpen for input */
 ULONG      cbBytesRead;               /* Number of bytes read into buffer  */
 ULONG      ulRetCode;                 /* Return code from DosCalls         */
 ULONG      ulRC;                      /* Return code from DosCalls         */
 FILESTATUS fstsFile;                  /* structure of file information     */
 PSZ        FoundLF;                   /* found last line feed              */
 PSZ        FoundCR;                   /* found last carriage return        */
 ULONG      fsOpenFlag;                /* ALK */
 ULONG      ulAllocSize;

 DosError(DISABLE_ERRORPOPUP);              /* disable hard error popups    */
                                            /* Open the file                */

 fsOpenFlag =  (ULONG)OPEN_ACTION_CREATE_IF_NEW |    /* ALK */
               (ULONG)OPEN_ACTION_OPEN_IF_EXISTS;    /* ALK */

 ulRetCode =
      DosOpen (pszFileName,                            /* File Name         */
               phfHandle,                              /* Handle            */
               &ulAction,                              /* Action taken      */
               0L,                                     /* Size if created   */
               0L,                                     /* File Attribute    */
               fsOpenFlag,                             /* Action to take if */
                                                       /*   it exists or not*/
               fsOpenMode,                             /* Mode in which to  */
                                                       /* ...open file      */
               0L);                                    /* Reserved          */
 DosError(ENABLE_ERRORPOPUP);               /* enable hard error popups     */

 if (!ulRetCode)
    {
     ulRC =
     DosQueryFileInfo(*phfHandle,                /* Get the size of the file     */
                  FIL_STANDARD,
                  (PBYTE)&fstsFile,
                  (ULONG)(sizeof(FILESTATUS)));

     if (fstsFile.cbFile > SEG_SIZE)        /* File size > 64K ?            */
         ulRetCode = ERROR_BUFFER_OVERFLOW;
     else
         *pulFileSize = fstsFile.cbFile;

     if (ulRetCode == NO_ERROR)
        {
        if (*pulFileSize < 4096L)
           ulAllocSize = 16384L;
        else
           ulAllocSize = *pulFileSize + 8192L;

        if ((DosAllocMem ( (PVOID *) pszBuffer, ulAllocSize,
                       PAG_COMMIT | PAG_READ | PAG_WRITE)))
           {
           ulRC = MCIERR_OUT_OF_MEMORY;
           }

        if(!ulRC)
           {
            ulRC=DosRead((HFILE)*phfHandle,              /* Read in the file             */
                    (PVOID)*pszBuffer,
                    (ULONG)*pulFileSize,
                    (PULONG)&cbBytesRead);

 //         if (cbBytesRead)                /* If something actually read   */
 //           {
               (*pszBuffer)[cbBytesRead] = '\0';
                                            /* null terminate string        */
               if ((CHAR *)strchr(*pszBuffer, EOFFILE) == NULL)
                 {                          /* If no EOF (x1A) at end add it*/
                  (*pszBuffer)[cbBytesRead] = EOFFILE;
                  (*pszBuffer)[cbBytesRead+1] = '\0';
                  cbBytesRead = cbBytesRead+1;
                 }
               FoundLF= strrchr(*pszBuffer,LF);         /* find last lf P5A */
               FoundCR= strrchr(*pszBuffer,CR);         /* find last cr P5A */
               if (((!(FoundCR)) && (!(FoundLF))) ||
                   ((!(FoundCR)) && ((*(FoundLF+1)) == EOFFILE)) ||
                   ((!(FoundLF)) && ((*(FoundCR+1)) == EOFFILE)))     //P7A
                 {                         /* if no CRLF on last line add it*/
                  (*pszBuffer)[cbBytesRead-1] = CR;     /* add carr ret P5A */
                  (*pszBuffer)[cbBytesRead] = LF;       /* add linefeed P5A */
                  (*pszBuffer)[cbBytesRead+1] = EOFFILE;/* add eof      P5A */
                  (*pszBuffer)[cbBytesRead+2] = '\0';   /* add null termP5A */
                 }
           }
        else
           ulRetCode = ERROR_NOT_ENOUGH_MEMORY;   /* not enough memory      */
        }
    }                                       /* End if !DosOpen()            */
 else                                       /* Else DosOpen Failed          */
  {
   if (ulRetCode == ERROR_OPEN_FAILED)
    ulRetCode = ERROR_FILE_NOT_FOUND;

  }

 return(ulRetCode);

}   /* ReadFileToBuffer() */

/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function:  WriteBufferToFile                                      º */
/* º                                                                      º */
/* º      Writes a memory buffer to a file.  The memory buffer            º */
/* º      contains the complete contents of the file.                     º */
/* º                                                                      º */
/* º    Input parameters:                                                 º */
/* º      hfHandle         Handle of the file                             º */
/* º      pszBuffer        Buffer (ASCIIZ string) to write                º */
/* º                                                                      º */
/* º    Output parameters:                                                º */
/* º      None                                                            º */
/* º                                                                      º */
/* º    Returns:           0 or DOS API return code                       º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG WriteBufferToFile(
                                       /* Returns a return code             */
       HFILE  hfHandle,                /* File handle                       */
       PSZ    pszBuffer)               /* Buffer to write                   */
{
 ULONG      uRetCode;                   /* Return code from DosCalls        */
 ULONG      cchFileSize;                /* Size of the new file             */
 ULONG      ulNewPtr;                   /* File pointer                     */
 ULONG      cbBytesWritten;             /* Number of bytes written from buff*/
 ULONG      fsOpenFlag;                 /* ALK */
  PSZ     pszEnv;
  CHAR    pszINIFile[260];
  PSZ     p;
 ULONG      ulAction;                  /* Action taken by DosOpen for input */


 DosError(DISABLE_ERRORPOPUP);              /* disable hard error popups    */
 cchFileSize = (ULONG)strlen(pszBuffer);  /* Number of bytes to write     */
// fsOpenFlag =  (ULONG)OPEN_ACTION_CREATE_IF_NEW |    /* ALK */
//               (ULONG)OPEN_ACTION_OPEN_IF_EXISTS;    /* ALK */
//
//  if (!DosScanEnv("MMBASE", &pszEnv))
//     {
//     strcpy(pszINIFile, pszEnv);
//     if (p = strchr(pszINIFile, ';'))
//        *p = 0;
//     strcat(pszINIFile, "\\VBLASTER.INI");
//     }
//  else
//     {
//     strcpy(pszINIFile, "c:\\VBLASTER.INI");
//     }
// uRetCode =
//      DosOpen (pszINIFile,                             /* File Name         */
//               &hfHandle,                              /* Handle            */
//               &ulAction,                              /* Action taken      */
//               0L,                                     /* Size if created   */
//               0L,                                     /* File Attribute    */
//               fsOpenFlag,                             /* Action to take if */
//                                                       /*   it exists or not*/
//               (ULONG)OPEN_ACCESS_READWRITE|OPEN_SHARE_DENYREADWRITE,
//                                                       /* ...open file      */
//               0L);                                    /* Reserved          */

                                            /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Set file ptr for next write³*/
 if (! (uRetCode =                          /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
        DosChgFilePtr (hfHandle,            /* File Handle                  */
                       0L,                  /* Number of bytes to move ptr  */
                       FILE_BEGIN,          /* Move starts from beginning   */
                       &ulNewPtr) ))        /* New pointer location         */
   {                                        /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Write the buffer           ³*/
    if (! (uRetCode =                      /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
           DosWrite (hfHandle,              /* File Handle                  */
                     pszBuffer,             /* Pointer to buffer            */
                     cchFileSize,           /* Number of bytes to write     */
                     &cbBytesWritten)))     /* # of bytes actually written  */
      {                                     /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Change file size           ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
                                            /* Not needed for expanding,    */
       if (! (uRetCode =                   /* ...but required for shrink   */
              DosNewSize (hfHandle,         /* File Handle                  */
                  (ULONG) cchFileSize)))    /* New size in bytes            */
         {                                  /*ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿*/
                                            /*³ Close the file             ³*/
                                            /*ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ*/
          if(! (uRetCode = DosClose (hfHandle))) /* Close the file       */
           {
//!!!        usINIUpdated=0;
           }
        }                                   /* End if DosNewSize    OK      */
      }                                     /* End if Write         OK      */
   }                                        /* End if DosChgFilePtr OK      */
 DosError(ENABLE_ERRORPOPUP);               /* enable hard error popups     */

 return(uRetCode);                         /* Return last DOS API ret code */
}                                           /* WriteBufferToFile()          */



/* ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· */
/* º    Function: IniFileClose                                            º */
/* º                                                                      º */
/* º      Close a file and free the memory buffer                         º */
/* º      contains the complete contents of the file.                     º */
/* º                                                                      º */
/* º    Input parameters:                                                 º */
/* º      hfHandle         Handle of the file                             º */
/* º      pszBuffer        Buffer (ASCIIZ string) to close                º */
/* º                                                                      º */
/* º    Output parameters:                                                º */
/* º      None                                                            º */
/* º                                                                      º */
/* º    Returns:           0 or DOS API return code                       º */
/* º                                                                      º */
/* ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ½ */
ULONG IniFileClose(HFILE  hfHandle)     /* File handle                      */
{
 ULONG      uRetCode;                   /* Return code from DosCalls        */

          uRetCode = DosClose (hfHandle);  /* Close the file       */
          hfHandle = 0;

 return(uRetCode);                         /* Return last DOS API ret code */
}                                           /* WriteBufferToFile()          */
