//+++keyword+++ "@(#)%v %n, %f, %w"
// "@(#)1 DBTOOLS.S, 14-Dec-94,15:32:48, LDH"

macro_file DBTOOLS;                     // Db Tools with CommandSet API

#include METOOLS.SH
#include DBTOOLS.SH

// #define _DEBUG_

#ifdef _DEBUG_
  #include DBUG.SH
#endif


void DbToolsExit( int Result, int DbFlags, int OrgWin ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbToolsExit

  Function: Support routine for the DbTools routines.  Will check DbFlags for
            the no_delete and no_switch window flags and will delete the
            current if it is not OrgWin window and switch to OrgWin when the
            flags are not set.  Also clears some global strings attached to the
            deleted window by some of the DbTools routines.

  Syntax  : Result = DbTools( Result, DbFlags, OrgWin );

  Entry   : int Result    - The exit Result of the calling DbTool routine
            int DbFlags   - The DbFlags when the calling routine started
                            (Note: only the following flags are checked)

              _dbf_NoDelWin     - When not set, causes the current window to be
                                  deleted and OrgWin to be selected as the
                                  current window.

              _dbf_NoSwitchWin  - When not set, causes the current window to be
                                  changed to OrgWin

            int OrgWin    - The window_id number of the original window when the
                            calling macro was started

  Exit    : None.

  Globals : gstr "~Section_#" - Global set by LocateDbPage where # is WindowId
            gstr "~DbRec_#"   - Global set by DbGetRecord where # is WindowId
            gstr "~DbCmd_#"   - Global set by DbGetCmd where # is WindowId

  Macros  : None.

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  if ( ( Result != _ErrorNoFile ) && ( Window_Id != OrgWin ) ) {
    if ( ( DbFlags & _dbf_NoDelWin ) == 0 ) {
      Set_Global_Str( _db_PageGlob + Str( Window_Id ), "" );
      Set_Global_Str( _db_RecGlob + Str( Window_Id ), "" );
      Set_Global_Str( _db_CmdGlob + Str( Window_Id ), "" );
      if ( File_Changed ) {
        Save_File;
      }
      Delete_Window;
      DbFlags = 0;
    }
    if ( ( DbFlags & _dbf_NoSwitchWin ) == 0 ) {
      Switch_Win_Id( OrgWin );
    }
  }
}  // DbToolsExit

int DbGetPage( str FName[128], str DbPage[80], int &FirstRec, int &NumRec ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetPage

  Function: Locate a DbPage and return the line number of the firt record and
            the number of record in the page.

  Syntax  : Result = DbGetPage( FName, DbPage, FirstRec, NumRec );

  Entry   : str FName     - The db file to search for DbPage.
                            (Note: use "" to cause the current window to be
                            searched instead of trying to locate the file)

            str DbPage    - The DbPage to find

            int FirstRec  - A variable used to return the first record line
                            number

            int NumRec    - A variable used to return the number of records in
                            the found DbPage

  Exit    : int
              _NoError        - Success, page found.
                int FirstRec    - Line number the first record is located on.
                int NumRec      - Number of records in DB Page.

              _ErrorNoFile    - Failure, file FName not found.
              _ErrorNoDbPage  - Failure, DbPage not found.

  Globals : None.

  Macros  : int LocateDbPage

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int OrgWin = Window_Id;
  int Result = _ErrorNoDbPage;
  int TRefresh = Refresh;
  int Fnd;

  Refresh = False;
  if ( FName == "" ) {
    Tof;
    Fnd = Find_Text( "^\f" + DbPage + "$| ", 0, _RegExp );
  }
  else {
    Fnd = LocateDbPage( FName, DbPage, False );
  }
  if ( Fnd == True ) {
    Mark_Pos;
    Result = _NoError;
    FirstRec = C_Line;
    Eol;
    if ( Find_Text( "^(\f)|(" + Make_Literal_X( "****START****" ) + ")", 0,
        _RegExp ) == True ) {
      if ( Cur_Char != "\f" ) {
        FirstRec = C_Line;
        if ( Find_Text( "^\f", 0, _RegExp ) == False ) {
          Eof;
          if ( C_Col > 1 ) {
            Down;
          }
        }
      }
    }
    else {
      Eof;
      if ( C_Col > 1 ) {
        Down;
      }
    }
    ++FirstRec;
    NumRec = C_Line - FirstRec;
    Goto_Mark;
  }
  else if ( Error_Level != 0 ) {
    Delete_Window;
    Switch_Win_Id( OrgWin );
    Error_Level = 0;
    Result = _ErrorNoFile;
  }
  Refresh = TRefresh;
  return ( Result );

}  // DbGetPage

int DbGetRecord( str FName[128], str DbPage[80], str DbField, str &DbData[2048],
        int &RecNum, int &Flags, str Misc )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetRecord

  Function: Finds and returns a specified record from DbPage in the db file
            FName.

  Syntax  : Result = DbGetRecord( FName, DbPage, DbField, DbData, RecNum, Flags,
                    Misc );

  Entry   : str FName   - The db file to search
                          (Note: use "" to search the current file)

            str DbPage  - The db page header to search
            str DbField - The field name to search
            str DbData  - The field data to find based upon Flags
            int RecNum  - The record number to get (overrides field search)
            int Flags   - Search mode and other db flags. (ORed together).

                          Search mode flags: Defaults - 0
                            Search forward from start of DbPage
                            Find section that exactly matches Section
                            Search is not sensitive to case
                            Will return first record when record not found

              _sf_RegExp        - Search for the regular expression in DbData
              _sf_Contains      - Search for a match that contains DbData.
              _sf_CaseSensitive - Search will be CaseSensitive.
              _sf_Backwards     - Search Backwards from stored position (Only
                                  used when _sf_Position is set)

              _sf_Position      - Position to last found DbData before doing
                                  new search (Default is to search forward)

              _sf_FirstField    - Will search for DbData in first field
              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Defaults - 0
                            Window with Db file will be deleted upon exit.
                            Entry window will be current window upon exit.

              _dbf_NoSwitchWin  - Will return with the Db window being current.
                                  (Note only used when _dbf_NoDelWin is set).

              _dbf_NoDelWin     - Will cause the the window the Db is loaded in
                                  to not be deleted.

            str Misc    - Miscellaneous parameters
                            /LD=str  Delimit to use, default is ASCII 127

  Exit    : int
              _NoError          - Success, record found and variables updated
                str DbData        - The found record data
                int RecNum        - The record number of the found record
                int Flags         - The total number of records under DbPage

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, DbPage not found in FName
              _ErrorNoDbRecord  - Failure, no matching record found
                                    (Note: Variables are not updated when
                                    _sf_ErrorNoRec is set).

                str DbData        - The first record data
                int RecNum        - 1
                int Flags         - The total number of records under DbPage

  Globals : str ~DbRec_#  - Contains the data from DbField and DbData that was
                            last used to find a record. (# is the Window_Id of
                            the window that contains FName).

                            Note: Marker 2 of marker set 3 is also used to save
                            the position of the last found record in window #.
                            Used when _sf_Position flag is passed.

  Macros  : int  DbGetPage
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int DbFlags = Flags;
  int OrgWin = Window_Id;
  int TRefresh = Refresh;
  int FirstRec;
  int NumRec;
  int Result;

  Refresh = False;
  Result = DbGetPage( FName, DbPage, FirstRec, NumRec );
  if ( Result == _NoError ) {
    Flags = NumRec;
    Result = _ErrorNoDbRecord;
    if ( NumRec < 1 ) {
      Goto Exit;
    }

    char Delim = Parse_Str( "/LD=", Misc );
    if ( Delim == "\x0" ) {
      Delim = _db_Delimit;
    }

    int L = 0, C, R, O;
    int FndFlag = _RegExp | ( DbFlags & _sf_CaseSensitive );
    int LastRec = NumRec + FirstRec;

    if ( RecNum > 0 ) {
      if ( RecNum > NumRec ) {
        if ( DbFlags & _sf_ErrorNoRec ) {
          Goto Exit;
        }
        RecNum = 1;
      }
      Result = _NoError;
      Goto_Line( FirstRec + RecNum - 1 );
    }
    else {
      Goto_Line( FirstRec );
    }
    if ( DbFlags & _sf_Position ) {
      Result = _ErrorNoDbRecord;
      if ( RecNum < 1 ) {
        Get_Mark_Record( 2, 3, L, C, R, O );
        if ( L != 0 ) {
          Goto_Line( L );
          if ( ( DbField == "" ) && ( DbData == "" ) ) {
            DbData = Global_Str( _db_RecGlob + Str( Window_Id ) );
            DbField = Parse_Str( "/F=", DbData );
            DbData = Parse_Str( "/D=", DbData );
          }
        }
      }
      NumRec = 0;
      if ( DbFlags & _sf_Backwards ) {
        FndFlag |= _sf_Backwards;
        if ( C_Line > FirstRec ) {
          NumRec = C_Line - FirstRec;
        }
        Up;
        Eol;
      }
      else {
        Down;
        Goto_Col( 1 );
        if ( C_Line < LastRec ) {
          NumRec = LastRec - C_Line;
        }
      }
      if ( NumRec < 1 ) {
        Goto Exit;
      }
    }
    if ( Result != _NoError ) {

      str FndStr = Delim + DbField + "=";

      if ( DbFlags & _sf_FirstField ) {
        FndStr = "^" + FndStr;
      }
      if ( ( DbFlags & _sf_RegExp ) == 0 ) {
        DbData = Make_Literal_X( DbData );
      }
      if ( DbFlags & _sf_Contains ) {
        FndStr += "[^" + Delim + "]*" + DbData;
      }
      else {
        FndStr += DbData + Delim + "|$";
      }
      if ( Find_Text( FndStr, NumRec, FndFlag ) == True ) {
        Result = _NoError;
      }
    }
    if ( Result == _NoError ) {
      Set_Global_Str( _db_RecGlob + Str( Window_Id ), "/F=" + DbField +
          "/D=" + DbData );
      Set_Mark_Record( 2, 3, C_Line, C_Col, 1, 1 );
      DbData = Get_Line;
      RecNum = C_Line - FirstRec + 1;
    }
    else if ( ( DbFlags & _sf_ErrorNoRec ) == 0 ) {
      DbData = Get_Line;
      RecNum = C_Line - FirstRec + 1;
    }
  }

Exit:
  DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
  Refresh = TRefresh;
  return ( Result );

}  // DbGetRecord

int DbDelRecord( str FName[128], str DbPage[80], str DbField, str &DbData[2048],
        int &RecNum, int &Flags, str Misc )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbDelRecord

  Function: Finds and deletes a specified record from DbPage in the db file
            FName.  Returns the deleted record data.

  Syntax  : Result = DbDelRecord( FName, DbPage, DbField, DbData, RecNum, Flags,
                    Misc );

  Entry   : str FName   - The db file to search
                          (Note: use "" to search the current file)

            str DbPage  - The db page header to search
            str DbField - The field name to search
            str DbData  - The field data to find based upon Flags
            int RecNum  - The record number to delete (overrides field search)
            int Flags   - Search mode and other db flags. (ORed together).

                          Search mode flags: Defaults - 0
                            Search forward from start of DbPage
                            Find section that exactly matches Section
                            Search is not sensitive to case
                            Will return first record when record not found

              _sf_RegExp        - Search for the regular expression in DbData
              _sf_Contains      - Search for a match that contains DbData.
              _sf_CaseSensitive - Search will be CaseSensitive.
              _sf_Backwards     - Search Backwards from stored position (Only
                                  used when _sf_Position is set)

              _sf_Position      - Position to last found DbData before doing
                                  new search (Default is to search forward)

              _sf_FirstField    - Will search for DbData in first field
              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Defaults - 0
                            Db file FName will not be save after changes
                            Window with Db file will be deleted upon exit
                            Entry window will be current window upon exit

              _dbf_SaveFile     - Save the db file FName after changes made
              _dbf_NoSwitchWin  - Will return with the Db window being current
                                  (Note only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the Db is loaded in
                                  to not be deleted

            str Misc    - Miscellaneous parameters
                            /LD=str  Delimit to use, default is ASCII 127

  Exit    : int
              _NoError          - Success, record found and variables updated
                str DbData        - The found record data
                int RecNum        - The record number of the found record
                int Flags         - The total number of records under DbPage

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, DbPage not found in FName
              _ErrorNoDbRecord  - Failure, no matching record found
                                    (Note: Variables are not updated when
                                    _sf_ErrorNoRec is set).

                str DbData        - The first record data
                int RecNum        - 1
                int Flags         - The total number of records under DbPage

  Globals : None

  Macros  : int  DbGetRecord
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int DbFlags = Flags;
  int OrgWin = Window_Id;
  int TRefresh = Refresh;
  int Result;

  Refresh = False;
  Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
  Result = DbGetRecord( FName, DbPage, DbField, DbData, RecNum, Flags, Misc );
  if ( Result == _NoError ) {
    Del_Line;
    if ( DbFlags & _dbf_SaveFile ) {
      Save_File;
    }
  }
  DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
  Refresh = TRefresh;
  return ( Result );

}  // DbDelRecord

int DbPutRecord( str FName[128], str DbPage[80], str DbField, str &DbData[2048],
        int &RecNum, int &Flags, str Misc, str NewData[2048] )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbPutRecord

  Function: Insert a new record or replace a specified record in DbPage in the
            db file FName with the record in NewData.  Returns the found and/or
            replaced record data.

  Syntax  : Result = DbPutRecord( FName, DbPage, DbField, DbData, RecNum, Flags,
                    Misc, NewData );

  Entry   : str FName   - The db file to search
                          (Note: use "" to search the current file)

            str DbPage  - The db page header to search
            str DbField - The field name to search
            str DbData  - The field data to find based upon Flags
            int RecNum  - The record number to delete (overrides field search)

            int Flags     - Search modes, placement and other db flags.
                            (ORed together)

                          Search mode flags: Defaults - 0
                            Search forward from start of DbPage
                            Find section that exactly matches Section
                            Search is not sensitive to case
                            Will return first record when record not found

              _sf_RegExp        - Search for the regular expression in DbData
              _sf_Contains      - Search for a match that contains DbData.
              _sf_CaseSensitive - Search will be CaseSensitive.
              _sf_Backwards     - Search Backwards from stored position (Only
                                  used when _sf_Position is set)
              _sf_Position      - Position to last found DbData before doing
                                  new search (Default is to search forward)
              _sf_FirstField    - Will search for DbData in first field
              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Placement and other db flags:  Defaults - 0
                            Will allow duplicate records to be added
                            Insert NewData
                            After found record or as last record in DbPage
                            Db file FName will not be save after changes
                            Window with db file will be deleted upon exit
                            Entry window will be current window upon exit
                            DbPage will not be create if it does not exist

              _dbf_NoDups       - Will not insert new record when it is a
                                  duplicate.
              _dbf_ReplaceRec   - Replace the found record with NewData
              _dbf_InsertBefore - Insert NewData before found record or as
                                  the first record in DbPage
              _dbf_SaveFile     - Save the db file FName after changes made
              _dbf_NoSwitchWin  - Will return with the Db window being current
                                  (Note only used when _dbf_NoDelWin is set)
              _dbf_NoDelWin     - Will cause the the window the Db is loaded in
                                  to not be deleted
              _dbf_CreatePage   - Create DbPage if it does not exist

            str Misc    - Miscellaneous parameters
                            /LD=str  Delimit to use, default is ASCII 127

            str NewData - The new data record

  Exit    : int
              _NoError          - Success, record found and variables updated
                str DbData        - The found record data
                int RecNum        - The record number of the new record
                int Flags         - The total number of records under DbPage

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, DbPage not found in FName
              _ErrorNoDbRecord  - Failure, no matching record found
                                    (Note: Variables are not updated when
                                    _sf_ErrorNoRec is set).
                str DbData        - The first record data
                int RecNum        - 1
                int Flags         - The total number of records under DbPage

              _ErrorDupRecord   - Failure, record not added, would be duplicate
                str DbData        - The found record data
                int RecNum        - The record number of the found record
                int Flags         - The total number of records under DbPage

  Globals : None

  Macros  : int  DbGetRecord
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( NewData != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int TInsert_Mode = Insert_Mode;

    Refresh = False;
    Insert_Mode = True;
    Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
    if ( ( DbField != "" ) && ( DbFlags & _dbf_NoDups ) &&
        ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) ) {

      char Delim = Parse_Str( "/LD=", Misc );
      if ( Delim == "\x0" ) {
        Delim = _db_Delimit;
      }

      str TStr = Parse_Str( Delim + DbField + "=", NewData );

      int TFlags = Flags;
      int TRecNum = RecNum;

      Flags &= 0xFFFF ^ _sf_Contains;
      Result = DbGetRecord( FName, DbPage, DbField, TStr, RecNum, Flags, Misc );
      switch ( Result ) {

        case _NoError :
          Result = _ErrorDupRecord;
          DbData = TStr;

        case _ErrorNoFile :
          Goto Exit;
      }
      FName = "";
      Flags = TFlags;
      RecNum = TRecNum;
    }
    Result = DbGetRecord( FName, DbPage, DbField, DbData, RecNum, Flags, Misc );
    if ( ( Result == _ErrorNoDbPage ) && ( DbFlags & _dbf_CreatePage ) ) {
      Eof;
      if ( C_Col > 1 ) {
        Cr;
      }
      Text( "\f" + DbPage );
      Down;
      Result = _ErrorNoDbRecord;
    }
    switch ( Result ) {

      case _NoError :
        if ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) {
          if ( DbFlags & _dbf_InsertBefore ) {
            Up;
            --RecNum;
          }
          Eol;
          Cr;
          ++RecNum;
          ++Flags;
        }
        break;

      case _ErrorNoDbRecord :
        if ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) {
          Result = _NoError;
          if ( DbFlags & _dbf_InsertBefore ) {
            Up;
            RecNum = 1;
          }
          else {
            Up;
            Goto_Line( C_Line + Flags );
            RecNum = Flags + 1;
          }
          Eol;
          Cr;
          ++Flags;
        }
        break;
    }
    if ( Result == _NoError ) {
      Put_Line( NewData );
      if ( DbFlags & _dbf_SaveFile ) {
        Save_File;
      }
    }

Exit:
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Insert_Mode = TInsert_Mode;
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbPutRecord

int DbCheckDupFields( str DbPage, str DbLine[2048], str FieldData, ... ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbCheckDupFields

  Function: Searches DbPage in the current window for duplicate fields (one or
            more) that matches FieldData and return True when duplicates found.

  Syntax  : Result = DbCheckDupFields( DbPage, DbLine, FieldData, ... );

  Entry   : str DbPage      - The DbPage to search
            str DbLine      - The original Db record, will not match
            str FieldData   - The FieldData to search for duplicates
            str ...         - One or more optional field names to search
                              (Note: must be full field names i.e. NAME=)

  Exit    : int
              True    - Duplicate fields found
                        (Note: current line contains record with duplicate)

              False   - No duplicate fields found

  Globals : None

  Macros  : int DbGetPage

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Dup = False;
  int TRefresh  = Refresh;
  int FirstRec;
  int NumRec;

  Refresh = False;
  if ( DbGetPage( "", DbPage, FirstRec, NumRec ) == _NoError ) {

    int LastRec = FirstRec + NumRec;
    int Pc = 0;

    str FStr;

    while ( Get_Param_Type( ++Pc ) == 1 ) {
      FStr = Get_Param_Str( Pc ) + FieldData;
      FStr = Make_Literal_X( FStr ) + Copy( FStr, 1, 1 ) + "|$";
      Goto_Line( FirstRec );
      while ( Find_Text( FStr, NumRec, _RegExp ) ) {
        if ( DbLine != Get_Line( ) ) {
          Dup = True;
          break;
        }
        Goto_Col( 1 );
        Down;
        NumRec = LastRec - C_Line;
      }
      NumRec = LastRec - FirstRec;
    }
  }
  Refresh = TRefresh;
  return ( Dup );

}  // DbCheckDupFields

str DbGetKeyStr( int K1, int K2 ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetKeyStr

  Function: Return a command mapping key string suitable for use with the
            command set APIs.

  Syntax  : KStr = DbGetKeyStr( KeyVal1, KeyVal2 );

  Entry   : int K1    - The Key1 value of the desired key.
            int K2    - The Key2 value of the desired key.

  Exit    : str       - The CmdMap key string for the passed key.
                        Note: values of 0 for K1 and K2 will return "".

  Globals : None.

  Macros  : None.

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  str Result = "";

  if ( ( K1 != 0 ) || ( K2 != 0 ) ) {
    Result = "/KL=" + Make_Key_Name( Make_Word( K1, K2 ) );
    Result += "/K1=" + str( K1 ) + "/K2=" + str( K2 );
  }
  return ( Result );

}  // DbGetKeyStr

int DbCheckWCmd( str &DbRecord[1024] ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbCheckWCmd

  Function: Scans the command map db in the current window for a duplicate WCmd,
            creates a unique WCmd and return the updated DbRecord and WCmd.

  Syntax  : Result = DbCheckWCmd( DbRecord );

  Entry   : str DbRecord  - The Db Record that contains the checked for WCmd.

  Exit    : int     - A unique WCmd
              str DbRecord    - Updated DbRecord

  Globals : None

  Macros  : int DbCheckDupFields

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = True;
  int TRefresh = Refresh;

  str WCmdStr = _db_Delimit + _db_cmd_WCmd + "=";
  str WCmdVal = Parse_Str( WCmdSTr, DbRecord );

  Refresh = False;
  Mark_Pos;
  if ( WCmdVal != "" ) {
    Result = DbCheckDupFields( _db_cmd_CMPage, DbRecord, WCmdVal, WCmdStr );
  }
  if ( Result == True ) {

    int TWin = Window_Id;
    int SortWin;
    int FirstRec;
    int NumRec;
    int NumSort = 0;
    int UseWCmd = _db_cmd_UserWCmd;

    Create_Window;
    SortWin = Cur_Window;
    Switch_Win_Id( TWin );

    if ( DbGetPage( "", _db_cmd_CMPage, FirstRec, NumRec ) == _NoError ) {
      Goto_Line( FirstRec );
      while ( NumRec > 0 ) {
        Result = Parse_Int( _db_Delimit + _db_cmd_WCmd + "=", Get_Line( ) );
        Down;
        --NumRec;
        if ( Result >= _db_cmd_UserWCmd ) {
          Put_Line_To_Win( Str( Result ), NumSort + 1, SortWin, 0 );
          ++NumSort;
        }
      }
    }
    if ( NumSort ) {
      Switch_Window( SortWin );
      QSort_Lines( 1, NumSort, 1, 1, 5, 0 );
      Tof;
      while ( !At_Eof ) {
        Val( Result, Get_Line( ) );
        if ( Result > UseWcmd ) {
          break;
        }
        else {
          UseWCmd = Result + 1;
        }
        Down;
      }
      Delete_Window;
    }
    Switch_Win_Id( TWin );

    Var_Remove_Str( _db_Delimit + _db_cmd_WCmd + "=", DbRecord );
    DbRecord += _db_Delimit + _db_cmd_WCmd + "=" + Str( UseWcmd );
  }
  Result = Parse_Int( WCmdStr, DbRecord );
  Goto_Mark;
  Refresh = TRefresh;
  return ( Result );

}  // DbCheckWCmd

int DbCheckDupKeys( str DbRecord[1024] ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbCheckDupKeys

  Function: Check the command map db in the current window for duplicate key
            assignments.  Returns True if duplicates found and the current line
            will contain the record with the duplicate key.

  Syntax  : Result = DbCheckDupKeys( DbRecord );

  Entry   : str DbRecord  - The DbRecord which contain the key assignments to
                            check for duplicates.

  Exit    : int
              True    - Duplicate keys found
                        (Note: current line contains duplicate key assignments)

              False   - No duplicate keys found

  Globals : None

  Macros  : int DbCheckDupFields

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = False;
  int TRefresh = Refresh;

  str KStr = _db_Delimit + _db_cmd_Key + "=";
  str K2Str = _db_Delimit + _db_cmd_Key2 + "=";
  str KVal = Parse_Str( KStr, DbRecord );

  Refresh = False;
  if ( KVal != "" ) {
    Result = DbCheckDupFields( _db_cmd_CMPage, DbRecord, KVal, KStr, K2Str);
  }
  KVal = Parse_Str( K2Str, DbRecord );
  if ( ( Result == False ) && ( KVal != "" ) ) {
    Result = DbCheckDupFields( _db_cmd_CMPage, DbRecord, KVal, KStr, K2Str);
  }
  Refresh = TRefresh;
  return ( Result );

}  // DbCheckDupKeys

str DbCmdMap2Rec( struct TCmdMap CmdMap ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbCmdMap2Rec

  Function: Converts the data in a CmdMap structure to a DbRecord as stored in
            CmdSet DB files.

  Syntax  : DbRecord = DbCmdMap2Rec( CmdMap );

  Entry   : struct CmdMap   - The CmdMap structure that contains the data.

  Exit    : str       - The returned DbRecord.

  Globals : None
  Macros  : None

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  str Delim = _db_Delimit;
  str DbRecord[1024] = "";

  if ( CmdMap.Name != "" ) {
    DbRecord += Delim + _db_cmd_Name + "=" + CmdMap.Name;
  }
  if ( CmdMap.Cmd != "" ) {
    DbRecord += Delim + _db_cmd_Cmd + "=" + CmdMap.Cmd;
  }
  if ( CmdMap.Type != 0 ) {
    DbRecord += Delim + _db_cmd_Type + "=" + Str( CmdMap.Type );
  }
  if ( CmdMap.KeyStr != "" ) {
    DbRecord += Delim + _db_cmd_Key + "=" + CmdMap.KeyStr;
  }
  if ( CmdMap.Key2Str != "" ) {
    DbRecord += Delim + _db_cmd_Key2 + "=" + CmdMap.Key2Str;
  }
  if ( CmdMap.Icon != "" ) {
    DbRecord += Delim + _db_cmd_Icon + "=" + CmdMap.Icon;
  }
  if ( CmdMap.Icon2 != "" ) {
    DbRecord += Delim + _db_cmd_Icon2 + "=" + CmdMap.Icon2;
  }
  if ( CmdMap.TBText != "" ) {
    DbRecord += Delim + _db_cmd_TBText + "=" + CmdMap.TBText;
  }
  if ( CmdMap.HlpCtx != "" ) {
    DbRecord += Delim + _db_cmd_HlpCtx + "=" + CmdMap.HlpCtx;
  }
  if ( CmdMap.OffId != "" ) {
    DbRecord += Delim + _db_cmd_OffId + "=" + CmdMap.OffId;
  }
  if ( CmdMap.Checked != "" ) {
    DbRecord += Delim + _db_cmd_Checked + "=" + CmdMap.Checked;
  }
  if ( CmdMap.WCmdId != "" ) {
    DbRecord += Delim + _db_cmd_WCmdId + "=" + CmdMap.WCmdId;
  }
  if ( CmdMap.Flags != 0 ) {
    if ( CmdMap.Flags & _db_cf_XMin ) {
      DbRecord += Delim + _db_cmd_XMin + "=1";
    }
  }
  if ( CmdMap.WCmd != 0 ) {
    DbRecord += Delim + _db_cmd_WCmd + "=" + Str( CmdMap.WCmd );
  }
  return ( DbRecord );

}  // DbCmdMap2Rec

void DbRec2CmdMap( struct TCmdMap CmdMap, str DbRecord[1024] ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbRec2CmdMap

  Function: Fills a TCmdMap structure with the data from a CmdSet Db record.

  Syntax  : DbRec2CmdMap( CmdMap, DbRecord );

  Entry   : struct CmdMap   - The CmdMap structure to be filled
            str DbRecord    - The DbRecord data to use to fill CmdMap

  Exit    : None
              struct CmdMap   - The filled CmdMap structure.

  Globals : None
  Macros  : None

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  str Delim = _db_Delimit;

  CmdMap.Name = Parse_Str( Delim + _db_cmd_Name + "=", DbRecord );
  CmdMap.Cmd = Parse_Str( Delim + _db_cmd_Cmd + "=", DbRecord );
  CmdMap.Type = Parse_Int( Delim + _db_cmd_Type + "=", DbRecord );
  CmdMap.KeyStr = Parse_Str( Delim + _db_cmd_Key + "=", DbRecord );
  CmdMap.Key2Str = Parse_Str( Delim + _db_cmd_Key2 + "=", DbRecord );
  CmdMap.Icon = Parse_Str( Delim + _db_cmd_Icon + "=", DbRecord );
  CmdMap.Icon2 = Parse_Str( Delim + _db_cmd_Icon2 + "=", DbRecord );
  CmdMap.TBText = Parse_Str( Delim + _db_cmd_TBText + "=", DbRecord );
  CmdMap.HlpCtx = Parse_Str( Delim + _db_cmd_HlpCtx + "=", DbRecord );
  CmdMap.OffId = Parse_Str( Delim + _db_cmd_OffId + "=", DbRecord );
  CmdMap.Checked = Parse_Str( Delim + _db_cmd_Checked + "=", DbRecord );
  CmdMap.WCmdId = Parse_Str( Delim + _db_cmd_WCmdId + "=", DbRecord );
  CmdMap.WCmd = Parse_Int( Delim + _db_cmd_WCmd + "=", DbRecord );
  CmdMap.Flags = 0;
  if ( Parse_Int( Delim + _db_cmd_XMin + "=", DbRecord ) != 0 ) {
    CmdMap.Flags |= _db_cf_XMin;
  }
}  // DbRec2CmdMap

int DbGetCmdSection( str FName[128], str &Section, int &Flags ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetCmdSection

  Function: Search for and return a command section header from the db file
            FName that matches Section based upon the search Flags.

  Syntax  : Result = DbGetCmdSection( FName, Section, Flags );

  Entry   : str FName   - The db file to search
                          (Note: use "" to search the current file)

            str Section - The name of the section to find
                          (Note: use "" to search for any section)

            int Flags   - Search mode and other db flags. (ORed together)

                          Search mode flags: Defaults - 0
                            Search forward from start of db page
                            Find section that exactly matches Section
                            Search is not sensitive to case
                            Will return first record if record not found

              _sf_RegExp        - Search for the regular expression in Section
              _sf_Contains      - Search for a match that contains Section
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found Section before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Default - 0
                            Entry window will be current window upon exit.
                            Window with Db file will be deleted upon exit.

              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, Section found and variables updated
                str Section       - The full name of the found section
                int Flags         - The number of commands under Section

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, no matching section found
                                    (Note: Variables updated only when
                                    _sf_ErrorNoRec is not set)

                str Section       - The full name of the first section
                int Flags         - The number of commands under first Section

  Globals : None

  Macros  : int  DbGetRecord
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int DbFlags = Flags;
  int OrgWin = Window_Id;
  int TRefresh = Refresh;
  int Result;
  int RecNo = 0;

  str SecStr = Make_Literal_X( _db_cmd_Section );

  Refresh = False;
  Flags |= _sf_FirstField | _dbf_NoDelWin | _dbf_NoSwitchWin;
  Result = DbGetRecord( FName, _db_cmd_CMPage, SecStr, Section, RecNo, Flags,
      "" );

  if ( Result == _NoError ) {
    Section = Copy( Section, 5, Svl( Section ) - 4 );
    Mark_Pos;
    Down;
    Goto_Col( 1 );
    Flags -= RecNo;
    if ( Flags > 0 ) {

      int FirstRec = C_Line;

      SecStr = "^" + _db_Delimit + SecStr + "=";
      if ( Find_Text( SecStr, Flags, _RegExp ) == True ) {
        Flags = C_Line - FirstRec;
      }
    }
    Goto_Mark;
  }
  DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
  Refresh = TRefresh;
  return ( Result );

}  // DbGetCmdSection

int DbDelCmdSection( str FName[128], str &Section, int &Flags ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbDelCmdSection

  Function: Delete a command Section header and all commands define under it
            from the db file FName.  Returns the full section name and number
            of command records deleted upon success.

  Syntax  : Result = DbDelCmdSection( FName, Section, Flags );

  Entry   : str FName   - The db file to search
                          (Note: use "" to search the current file)

            str Section - The section header to delete
            int Flags   - Search mode and other db flags. (ORed together)

                          Search mode flags: Defaults - 0
                            Search forward from start of db page
                            Find section that exactly matches Section
                            Search is not sensitive to case
                            Will return first record if record not found

              _sf_RegExp        - Search for the regular expression in Section
              _sf_Contains      - Search for a match that contains Section
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found Section before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Default - 0
                            FName will not be save after changes
                            Entry window will be current window upon exit
                            Window with Db file will be deleted upon exit

              _dbf_SaveFile     - Save the db file FName before returning
              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, Section and all commands under it
                                  deleted

                str Section       - The full name of the deleted section
                int Flags         - The number of commands deleted

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, no matching section found

  Globals : None

  Macros  : int  DbGetCmdSection
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( Section != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;

    Refresh = False;
    Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
    Result = DbGetCmdSection( FName, Section, Flags );
    if ( Result == _NoError ) {
      Block_Begin;
      Goto_Line( C_Line + Flags );
      Delete_Block;
      if ( DbFlags & _dbf_SaveFile ) {
        Save_File;
      }
    }
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbDelCmdSection

int DbPutCmdSection( str FName[128], str &Section, int &Flags, str NewSection ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbPutCmdSection

  Function: Add or update a section header in the command list in the FName DB
            file.

  Syntax  : Result = DbPutCmdSection( FName, Section, Flags, NewSection );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str Section   - The section header to find
            int Flags     - Search modes, placement and other db flags
                            (ORed together)

                          Search mode flags: Defaults - 0
                            Search forward from start of db page
                            Find section that exactly matches Section
                            Search is not sensitive to case
                            Will return first record if record not found

              _sf_RegExp        - Search for the regular expression in Section
              _sf_Contains      - Search for a match that contains Section
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found Section before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Placement and other db flags:  Defaults - 0
                            Insert NewSection
                            After found section or as last section in DbPage
                            Will not save file FName after each update
                            Entry window will be current window upon exit
                            Window with Db file will be deleted upon exit
                            WCMDMAP.DB will not be created if not found

              _dbf_ReplaceRec   - Replace the found Section with NewSection
              _dbf_InsertBefore - Insert NewSection before found Section or as
                                  the first section in DbPage
              _dbf_SaveFile     - Save the db file FName after each update
              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note only used when _dbf_NoDelWin is set)
              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

            str NewSection  - The NewSection header name to add or update to

  Exit    : int
              _NoError          - Success, section added or updated
                str Section       - The found or replaced section
                int Flags         - The number of commands under section

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, NewSection was blank, already exists
                                  or no matching section found when updating

  Globals : None

  Macros  : int  DbGetCmdSection
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( NewSection != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int TInsert_Mode = Insert_Mode;
    int TFlags = Flags | _dbf_NoDelWin | _dbf_NoSwitchWin;

    str TStr = NewSection;

    Refresh = False;
    Insert_Mode = True;
    Flags = TFlags & ( 0xFFFF ^_sf_Contains );
    if ( DbGetCmdSection( FName, TStr, Flags ) == _NoError ) {
      Result = _ErrorDupRecord;
      Section = TStr;
      Goto Exit;                        //  Section already exists
    }
    FName = "";
    Flags = TFlags;
    if ( Section == "" ) {
      if ( DbFlags & _dbf_ReplaceRec ) {
        Goto Exit;
      }
      Flags &= 0xFFFF ^ _sf_Contains;
    }
    Result = DbGetCmdSection( FName, Section, Flags );
    switch ( Result ) {

      case _NoError :                   // Section found
        if ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) {
          if ( DbFlags & _dbf_InsertBefore ) {
            Up;
          }
          else {
            Goto_Line( C_Line + Flags );
          }
          Eol;
          Cr;
          Flags = 0;
        }
        break;

      case _ErrorNoDbRecord :           // No section found
        if ( DbFlags & _dbf_ReplaceRec ) {
          break;
        }
        if ( DbFlags & _dbf_InsertBefore ) {
          Up;
        }
        else {
          if ( Find_Text( "^\f", 0, _RegExp ) == True ) {  // Find end of FName
            Up;
          }
          else {
            Eof;
            if ( C_Col == 1 ) {
              Up;
            }
          }
        }
        Eol;
        Cr;
        Flags = 0;
        Result = _NoError;
        break;
    }
    if ( Result == _NoError ) {
      Put_Line( _db_Delimit + _db_cmd_Section + "=" + NewSection );
      if ( DbFlags & _dbf_SaveFile )  {
        Save_File;
      }
    }

Exit:
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Insert_Mode = TInsert_Mode;
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbPutCmdSection

int DbGetCmd( str FName[128], str &Section, str &CmdRecord[1024], int &Flags ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetCmd

  Function: Search for and return data about a command from the FName db file.
            Commands can be searched for in a number of ways depending upon
            Flags and the data in CmdRecord.

  Syntax  : Result = DbGetCmd( FName, Section, CmdRecord, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str Section   - Name of section header to find
                            (Note: use "" to skip the search for Section)

            str CmdRecord - The command data to find
                            (Note: Only one of WCmd, Key and Name fields are
                            used in searching.  The first of these field that
                            contains data is used as the search data.  The
                            order for scanning is WCmd, Key and Name)

            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from start of DbPage or Section
                              Find command that exactly matches WCmd or
                              Find command that has Key defined or
                              Find command that exactly matches Name
                              Name search is not sensitive to case

              _sf_RegExp        - Search for the regular expression in Name
              _sf_Contains      - Search for a match that contains Name
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found command before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                            Other Db flags: Default - 0
                              Window with Db file will be deleted upon exit.
                              Entry window will be current window upon exit.

              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, the command was found.
                str Section       - Name of section the command was found under
                str CmdRecord     - The found command data
                int Flag          - The WCmd of the found command

              _ErrorNoFile      - Failure, FName DB file was not found
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, no matching command found
                str Section       - The name of section when found otherwise ""
                int Flag          - The number of commands under section when
                                    found otherwise invalid

  Globals : str ~DbCmd_#  - Contains the data from CmdRecord that was last used
                            to find a section. (# is the  Window_Id of the
                            window that contains FName).

                            Note: Marker 3 of marker set 3 is also used to save
                            the position of the last found command in window #.
                            Used when _sf_Position flag is passed.

  Macros  : int  DbGetPage
            int  DbGetCmdSection
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int DbFlags = Flags;
  int OrgWin = Window_Id;
  int Result;
  int TRefresh = Refresh;
  int NumRec = _sf_Contains | _dbf_NoDelWin | _dbf_NoSwitchWin;
  int FirstRec;

  Refresh = False;
  if ( Section != "" ) {
    Result = DbGetCmdSection( FName, Section, NumRec );
    FirstRec = C_Line + 1;
    if ( Result != _NoError ) {
      Section = "";
    }
    else {
      Flags = NumRec;
    }
  }
  else {
    Result = DbGetPage( FName, _db_cmd_CMPage, FirstRec, NumRec );
  }
  if ( Result == _NoError ) {
    Result = _ErrorNoDbRecord;
    if ( NumRec < 1 ) {
      Goto Exit;
    }

    int L = 0, C, R, O;
    int LastRec = FirstRec + NumRec;
    int FndFlag = _RegExp;
    int WCmd;

    str Delim = _db_Delimit;
    str CmdGlobal = _db_CmdGlob + Str( Window_Id );
    str FndStr;
    str KeyStr;
    str Name;

    Goto_Line( FirstRec );
    if ( DbFlags & _sf_Position ) {
      Get_Mark_Record( 3, 3, L, C, R, O );
      if ( L != 0 ) {
        Goto_Line( L );
        if ( CmdRecord == "" ) {
          CmdRecord = Global_Str( CmdGlobal );
        }
      }
      NumRec = 0;
      if ( DbFlags & _sf_Backwards ) {
        FndFlag |= _sf_Backwards;
        if ( C_Line > FirstRec ) {
          NumRec = C_Line - FirstRec;
        }
        Up;
        Eol;
      }
      else {
        Down;
        Goto_Col( 1 );
        if ( C_Line < LastRec ) {
          NumRec = LastRec - C_Line;
        }
      }
      if ( NumRec < 1 ) {
        Goto Exit;
      }
    }
    Var_Parse_Int( Delim + _db_cmd_WCmd + "=", CmdRecord, WCmd );
    Var_Parse_Str( Delim + _db_cmd_Key + "=", CmdRecord, KeyStr );
    Var_Parse_Str( Delim + _db_cmd_Name + "=", CmdRecord, Name );
    if ( WCmd != 0 ) {
      FndStr = Delim + _db_cmd_WCmd + "=" + Str( WCmd ) + Delim + "|$";
    }
    else if ( KeyStr != "" ) {
      FndStr = Delim + "(" + _db_cmd_Key + ")|(" + _db_cmd_Key2 + ")=" +
          Make_Literal_X( KeyStr ) + Delim + "|$";
    }
    else {
      FndFlag |= ( DbFlags & _sf_CaseSensitive );
      FndStr = "^" + Delim + _db_cmd_Name + "=";
      if ( ( DbFlags & _sf_RegExp ) == 0 ) {
        Name = Make_Literal_X( Name );
      }
      if ( DbFlags & _sf_Contains ) {
        FndStr += "[^" + Delim + "]*" + Name;
      }
      else {
        FndStr += Name + Delim + "|$";
      }
    }
    if ( Find_Text( FndStr, NumRec, FndFlag ) == True ) {
      Result = _NoError;
      Set_Global_Str( CmdGlobal, CmdRecord );
      Set_Mark_Record( 3, 3, C_Line, C_Col, 1, 1 );
      CmdRecord = Get_Line( );
      Flags = Parse_Int( _db_Delimit + _db_cmd_WCmd + "=", CmdRecord );
      Mark_Pos;
      NumRec = C_Line - FirstRec;
      Up;
      Eol;
      Delim += _db_cmd_Section + "=";
      if ( Find_Text( "^" + Make_Literal_X( Delim ), NumRec,
          _RegExp | _Backward ) == True ) {
        Section = Parse_Str( Delim, Get_Line( ) );
      }
      Goto_Mark;
    }
  }

Exit:
  DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
  Refresh = TRefresh;
  return ( Result );

}  // DbGetCmd

int DbDelCmd( str FName[128], str &Section, str &CmdRecord[1024], int &Flags ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbDelCmd

  Function: Delete the command specified in Section/CmdRecord from the db file
            FName and return the deleted command data.

  Syntax  : int DbDelCmd( FName, Section, CmdRecord, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str Section   - Section name to find command under
            str CmdRecord - Command data searched for to be deleted
            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from start of DbPage or Section
                              Find command that exactly matches WCmd or
                              Find command that has Key defined or
                              Find command that exactly matches Name
                              Name search is not sensitive to case

              _sf_RegExp        - Search for the regular expression in Name
              _sf_Contains      - Search for a match that contains Name
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found command before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                            Other Db flags: Default - 0
                              Db file FName will not be save after changes
                              Window with Db file will be deleted upon exit
                              Entry window will be current window upon exit

              _dbf_SaveFile     - Save the db file FName after changes
              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, command deleted from FName
                str Section       - The Section the deleted command was under
                str CmdRecord     - The deleted command data
                int Flags         - The WCmd for the deleted command

              _ErrorNoFile      - Failure, FName file not found.
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, command not found or deleted

  Globals : None.

  Macros  : int  DbGetCmd
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( CmdRecord != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;

    Refresh = False;
    Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
    Result = DbGetCmd( FName, Section, CmdRecord, Flags );
    if ( Result == _NoError ) {
      Del_Line;
      if ( DbFlags & _dbf_SaveFile ) {
        Save_File;
      }
    }
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbDelCmd

int DbPutCmd( str FName[128], str &Section, str &CmdRecord[1024], int &Flags,
        str NewCmdRecord[1024] )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbPutCmd

  Function: Update the command specified in Section/CmdRecord or add the
            command in NewCmdRecord to the db file FName and return the
            replaced command data and WCmd for the new command.

  Syntax  : int DbPutCmd( FName, Section, CmdRecord, Flags, NewCmdRecord );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str Section   - Section name to find command under
                            (Note: use "" to skip seection search)

            str CmdRecord - Command data to find
            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from start of DbPage or Section
                              Find command that exactly matches WCmd or
                              Find command that has Key defined or
                              Find command that exactly matches Name
                              Name search is not sensitive to case

              _sf_RegExp        - Search for the regular expression in Name
              _sf_Contains      - Search for a match that contains Name
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found command before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Placement and other db flags:  Defaults - 0
                            Will allow duplicate commands to be added
                            Insert NewCmdRecord
                            After found CmdRecord or as last record in DbPage
                            Db file FName will not be save after changes
                            Window with db file will be deleted upon exit
                            Entry window will be current window upon exit
                            WCMDMAP.DB will not be created

              _dbf_NoDups       - Will not insert new record when it is a
                                  duplicate.

              _dbf_ReplaceRec   - Replace found CmdRecord with NewCmdRecord
              _dbf_InsertBefore - Insert NewCmdRecord before found CmdRecord or
                                  as the first command in DbPage

              _dbf_SaveFile     - Save the db file FName after changes
              _dbf_NoSwitchWin  - Will return with the Db window being current
                                  (Note only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the Db is loaded in
                                  to not be deleted

            str NewCmdRecord  -  The new command data

  Exit    : int
              _NoError          - Success, command added or updated in FName
                str Section       - Section the added/updated command was
                                    under

                str CmdRecord     - The old replaced or found command data
                int Flags         - The WCmd for the added or updated command

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, NewCmdRecord was empty or command
                                  not found when updating

              _ErrorDupRecord   - Failure, command not added, would be duplicate
                str Section       - Section the found command is under
                int CmdRecord     - The original found command record
                int Flags         - The WCmd of the found command

  Globals : None.

  Macros  : int  DbGetCmd
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( NewCmdRecord != "" )  {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int TInsert_Mode = Insert_Mode;
    int WCmd = Parse_Int( _db_Delimit + _db_cmd_WCmd + "=", NewCmdRecord );

    Refresh = False;
    Insert_Mode = True;
    Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
    if ( ( DbFlags & _dbf_NoDups ) && !( DbFlags & _dbf_ReplaceRec ) ) {

      str TStr[1024] = NewCmdRecord;

      int TFlags = Flags;

      Flags &= 0xFFFF ^ _sf_Contains;
      if ( DbGetCmd( FName, Section, TStr, Flags ) == _NoError ) {
        Result = _ErrorDupRecord;
        CmdRecord = TStr;
        Goto Exit;
      }
      FName = "";
      Flags = TFlags;
    }
    if ( CmdRecord == "" ) {
      if ( DbFlags & _dbf_ReplaceRec ) {
        Goto Exit;
      }
      Flags |= _sf_Contains;
    }
    Result = DbGetCmd( FName, Section, CmdRecord, Flags );
    switch ( Result ) {

      case _NoError :
        if ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) {
          if ( DbFlags & _dbf_InsertBefore ) {
            Up;
          }
          Eol;
          Cr;
        }
        break;

      case _ErrorNoDbRecord :
        if ( DbFlags & _dbf_ReplaceRec ) {
          break;
        }
        Result = _NoError;
        if ( Section != "" ) {
          Up;
          if ( ( DbFlags & _dbf_InsertBefore ) == 0 ) {
            Goto_Line( C_Line + Flags );
          }
        }
        else {
          if ( Find_Text( "^\f", 0, _RegExp ) == True ) {
            Up;
          }
          else {
            Eof;
            if ( C_Col == 1 ) {
              Up;
            }
          }
        }
        Eol;
        Cr;
        break;
    }
    if ( Result == _NoError ) {
      if ( Section == "" ) {
        Mark_Pos;
        Goto_Col( 1 );
        do {
          Up;
          if ( XPos( _db_Delimit + _db_cmd_Section + "=", Get_Line( ), 1 ) ) {
            Section = Parse_Str( _db_Delimit + _db_cmd_Section + "=",
                Get_Line( ) );
            break;
          }
        } while ( ( Cur_Char != "\f" ) && ( C_Col != 1 ) );
        Goto_Mark;
      }
      if ( Section != "" ) {
        Mark_Pos;
        Put_Line( NewCmdRecord );
        Flags = DbCheckWCmd( NewCmdRecord );
        Put_Line( NewCmdRecord );
        if ( DbCheckDupKeys( NewCmdRecord ) == True ) {
          Result = _ErrorDupKey;
          Pop_Mark;
        }
        else {
          Goto_Mark;
        }
        if ( DbFlags & _dbf_SaveFile ) {
          Save_File;
        }
      }
      else {
        Result = _ErrorNoDbRecord;
      }
    }

Exit:
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Insert_Mode = TInsert_Mode;
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbPutCmd

str DbExpandChar( str TStr[2048], str XChar[1] ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbExpanChar

  Function: Makes a regular expressing with XChar and '*' inserted before every
            character in TStr.

  Syntax  : RegExpStr = DbExpandChar( TStr, XChar );

  Entry   : str TStr  - The string to expand
            str XChar - The character to insert before all chars in TStr

  Exit    : str   - The expanded string

  Globals : None

  Macros  : None

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/


  int StrLen = Svl( TStr );
  int Cnt = 0;

  str NStr[2048] = "";

  while ( Cnt < StrLen ) {
    NStr += XChar + "*" + Copy( TStr, ++Cnt, 1 );
  }
  return ( NStr );

}

str DbMenu2Rec( str MenuText, int Level, int WCmd ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbMenu2Rec

  Function: Returns a menu record as stored in the command set db files, for
            MenuText, Level and WCmd.  Can be passed to the DbMenuXXX routines.

  Syntax  : MnuRec = DbMenu2Rec( MenuText, Level, WCmd );

  Entry   : str MenuText  - The menu entry text
            int Level     - The level of the menu entry (1-4)
            int WCmd      - The WCmd for the menu entry

  Exit    : str     - The menu record

  Globals : None

  Macros  : None

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  str MenuRec;
  str Sep = "0";

  if ( WCmd == _db_mnu_SepWCmd ) {
    MenuText = "";
    Sep = "1";
  }
  MenuRec = _db_Delimit + _db_mnu_Menu + "=" + _db_mnu_Text + MenuText +
      _db_mnu_Level + Str( Level ) + _db_mnu_Sep + Sep +
      _db_Delimit + _db_mnu_WCmd + "=" + Str( WCmd );

  return ( MenuRec );

}  // DbMenu2Rec

void DbRec2Menu( str &MenuText, int &Level, int &WCmd, str MenuRec ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbRec2Menu

  Function: Fills the passed variable with the data from a MenuRec db record.

  Syntax  : DbRec2Menu( MenuText, Level, WCmd, MenuRec );

  Entry   : str MenuText  - A variable to contain the returned menu text
            int Level     - A variable to contain the returned menu Level
            int WCmd      - A variable to contain the returned menu WCmd
            str MenuRec   - The menu record

  Exit    : None
              str MenuText  - The extracted menu entry text
              int Level     - The level of the menu entry (1-4)
              int WCmd      - The WCmd for the menu entry

  Globals : None

  Macros  : None

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  str TStr = Parse_Str( _db_Delimit + _db_mnu_Menu + "=", MenuRec );

  MenuText = Parse_Str( _db_mnu_Text, TStr );
  Level = Parse_Int( _db_mnu_Level, TStr );
  WCmd = Parse_Int( _db_Delimit + _db_mnu_WCmd + "=", MenuRec );

}  // DbRec2Menu

int DbGetMenu( str FName[128], str MenuPage[80], struct TMenus Menus,
        int &Level, int &WCmd, int &Flags )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetMenu

  Function: Find and return data about a specified menu entry.

  Syntax  : Result = DbGetMenu( FName, MenuPage, Menus, Level, WCmd, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search current file)

            str MenuPage  - The menu db page to search
                            (Note: "" defaults to MAIN.MNU)

            struct Menus  - A structure containing the hierarchy of menu entries
                            to search for. The search algorithm uses each entry
                            up to the Level entry to find a matching menu
                            entry.  Use "" to match anything at that level.

            int Level     - The Level of the menu entry to get, max of 4 levels
                            (Note: using 0 will search for any level menu entry
                            and uses Menus.Menu1 as the menu text to find)

            int WCmd      - The WCmd of the menu entry to get
                            (Note: overrides Menus/Level search when not 0)

            int Flags     - Search mode and other db flags. (ORed together).

                            Search mode flags: Defaults - 0
                              Search forward from start of MenuPage
                              Find menu that exactly matches text in Menus
                              Search is not sensitive to case
                              Will return no data if menu not found

              _sf_Contains      - Search for a match that contains text in Menus
              _sf_CaseSensitive - Search will be CaseSensitive.
              _sf_Backwards     - Search Backwards from stored position (Only
                                  used when _sf_Position is set)

              _sf_Position      - Position to last found menu entry before doing
                                  new search (Default is to search forward)

                            Other Db flags: Defaults - 0
                              Window with Db file will be deleted upon exit.
                              Entry window will be current window upon exit.

              _dbf_NoSwitchWin  - Will return with the Db window being current.
                                  (Note only used when _dbf_NoDelWin is set).

              _dbf_NoDelWin     - Will cause the the window the Db is loaded in
                                  to not be deleted.


  Exit    : int
              _NoError          - Success, menu found and variables updated
                struct Menus      - The text of each menu entry to Level
                int Level         - The Level of the found menu
                int WCmd          - The WCmd of the found menu
                int Flags         - The number of submenus

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, MenuPage not found in FName
              _ErrorNoDbRecord  - Failure, no matching menu found

  Globals : None

  Macros  : str  DbExpandChar
            int  DbGetRecord
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( ( Level >= 0 ) && ( Level < 5 ) ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int Cnt = 1;
    int TFlags = Flags | _dbf_NoDelWin | _dbf_NoSwitchWin;
    int RecNo = 0;
    int NumRec;

    str CurMenu[1024];
    str CurField;
    str LevelSep = _db_mnu_Level + "." + _db_mnu_Sep + ".";

    Refresh = False;
    if ( MenuPage == "" ) {
      MenuPage = _db_mnu_MainPage;
    }
    if ( WCmd != 0 ) {
      CurField = _db_mnu_WCmd;
      CurMenu = Str( WCmd );
      TFlags &= 0xFFFF ^ _sf_FirstField;
    }
    else {
      CurField = _db_mnu_Menu;
      TFlags |= _sf_RegExp | _sf_FirstField;
      while ( True ) {
        switch ( Cnt ) {

          case 1 :
            CurMenu = Menus.Menu1;
            break;

          case 2 :
            CurMenu = Menus.Menu2;
            break;

          case 3 :
            CurMenu = Menus.Menu3;
            break;

          case 4 :
            CurMenu = Menus.Menu4;
            break;
        }
        if ( CurMenu != "" ) {
          if ( XPos( "&", CurMenu, 1 ) == 0 ) {
            CurMenu = DbExpandChar( CurMenu, "&" );
          }
          if ( DbFlags & _sf_Contains ) {
            CurMenu += ".*";
          }
          else {
            CurMenu = _db_mnu_Text + CurMenu;
          }
          if ( Cnt >= Level ) {
            if ( Level != 0 ) {
              LevelSep = _db_mnu_Level + Str( Cnt ) + _db_mnu_Sep + ".";
            }
            CurMenu += LevelSep;
            break;
          }
          LevelSep = _db_mnu_Level + Str( Cnt ) + _db_mnu_Sep + ".";
          CurMenu += LevelSep;
          NumRec = TFlags;
          Result = DbGetRecord( FName, MenuPage, CurField, CurMenu, RecNo,
              NumRec, "" );
          if ( Result != _NoError ) {
            Goto Exit;
          }
          FName = "";
          TFlags |= _sf_Position;
        }
        else if ( Cnt >= Level ) {
          break;
        }
        ++Cnt;
      }
    }
    NumRec = TFlags;
    Result = DbGetRecord( FName, MenuPage, CurField, CurMenu, RecNo,
        NumRec, "" );
    if ( Result == _NoError ) {
      Level = Parse_Int( _db_mnu_Level, CurMenu );
      WCmd = Parse_Int( _db_Delimit + _db_mnu_WCmd + "=", CurMenu );
      Flags = 0;
      if ( WCmd == 0 ) {
        // Set Flags to number of menu entries under this menu.
        Mark_Pos;
        Down;
        Cnt = C_Line;
        Flags = NumRec - RecNo;
        if ( Find_Text( _db_mnu_Level + Str( Level ), NumRec - RecNo, 0 ) ) {
          Flags = C_Line - Cnt;
        }
        Goto_Mark;
      }
      Mark_Pos;
      Cnt = Level;
      Menus.Menu1 = "";
      Menus.Menu2 = "";
      Menus.Menu3 = "";
      Menus.Menu4 = "";
      while ( True ) {
        switch ( Cnt ) {

          case 1 :
            Menus.Menu1 = Parse_Str( _db_mnu_Text, CurMenu );
            break;

          case 2 :
            Menus.Menu2 = Parse_Str( _db_mnu_Text, CurMenu );
            break;

          case 3 :
            Menus.Menu3 = Parse_Str( _db_mnu_Text, CurMenu );
            break;

          case 4 :
            Menus.Menu4 = Parse_Str( _db_mnu_Text, CurMenu );
            break;
        }
        --Cnt;
        if ( Cnt == 0 ) {
          break;
        }
        NumRec = C_Line;
        if ( Find_Text( _db_mnu_Level + Str( Cnt ), RecNo, _Backward ) ) {
          CurMenu = Get_Line( );
          RecNo -= NumRec - C_Line;
        }
        else {
          break;
        }
      }
      Goto_Mark;
    }

Exit:
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbGetMenu

int DbDelMenu( str FName[128], str MenuPage[80], struct TMenus Menus,
        int &Level, int &WCmd, int &Flags )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbDelMenu

  Function: Find and delete a specified menu entry and all submenus under it.

  Syntax  : Result = DbDelMenu( FName, MenuPage, Menus, Level, WCmd, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search current file)

            str MenuPage  - The menu db page to search
                            (Note: "" defaults to MAIN.MNU)

            struct Menus  - A structure containing the hierarchy of menu entries
                            to search for. The search algorithm uses each entry
                            up to the Level entry to find a matching menu
                            entry.  Use "" to match anything at that level.

            int Level     - The Level of the menu entry to delete, (max of 4)
                            (Note: using 0 will search for any level menu entry
                            and uses Menus.Menu1 as the menu text to find)

            int WCmd      - The WCmd of the menu entry to delete
                            (Note: overrides Menus/Level search when not 0)

            int Flags     - Search mode and other db flags. (ORed together).

                            Search mode flags: Defaults - 0
                              Search forward from start of MenuPage
                              Find menu that exactly matches text in Menus
                              Search is not sensitive to case
                              Will return no data if menu not found

              _sf_Contains      - Search for a match that contains text in Menus
              _sf_CaseSensitive - Search will be CaseSensitive.
              _sf_Backwards     - Search Backwards from stored position (Only
                                  used when _sf_Position is set)

              _sf_Position      - Position to last found menu entry before doing
                                  new search (Default is to search forward)

                            Other Db flags: Defaults - 0
                              FName will not be save after changes
                              Window with Db file will be deleted upon exit.
                              Entry window will be current window upon exit.

              _dbf_SaveFile     - Save the db file FName before returning
              _dbf_NoSwitchWin  - Will return with the Db window being current.
                                  (Note only used when _dbf_NoDelWin is set).

              _dbf_NoDelWin     - Will cause the the window the Db is loaded in
                                  to not be deleted.

  Exit    : int
              _NoError          - Success, menu deleted and variables updated
                struct Menus      - The text of each menu entry to Level
                int Level         - The Level of the deleted menu
                int WCmd          - The WCmd of the deleted menu
                int Flags         - The number of submenus deleted

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, MenuPage not found in FName
              _ErrorNoDbRecord  - Failure, no matching menu found

  Globals : None

  Macros  : int  DbGetMenu
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int DbFlags = Flags;
  int OrgWin = Window_Id;
  int TRefresh = Refresh;
  int Result = _ErrorNoDbRecord;

  Refresh = False;
  Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
  Result = DbGetMenu( FName, MenuPage, Menus, Level, WCmd, Flags );
  if ( Result == _NoError ) {
    Block_Begin;
    Goto_Line( C_Line + Flags );
    Delete_Block;
    if ( DbFlags & _dbf_SaveFile ) {
      Save_File;
    }
  }
  DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
  Refresh = TRefresh;
  return ( Result );

}  // DbDelMenu

int DbPutMenu( str FName[128], str MenuPage[80], struct TMenus Menus,
        int &Level, int &WCmd, int &Flags, str &NewMenuRec )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbPutMenu

  Function: Insert or replace a specified menu entry in MenuPage in the db file
            FName.

  Syntax  : Result = DbAddMenu( FName, MenuPage, Menus, Level, WCmd, Flags,
                NewMenuRec );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search current file)

            str MenuPage  - The menu db page to search
                            (Note: "" defaults to MAIN.MNU)

            struct Menus  - A structure containing the hierarchy of menu entries
                            to search for. The search algorithm uses each entry
                            up to the Level entry to find a matching menu
                            entry.  Use "" to match anything at that level.

            int Level     - The Level of the menu entry to find, (max of 4)
                            (Note: using 0 will search for any level menu entry
                            and uses Menus.Menu1 as the menu text to find)

            int WCmd      - The WCmd of the menu entry to find
                            (Note: overrides Menus/Level search when not 0)

            int Flags     - Search mode and other db flags. (ORed together).

                            Search mode flags: Defaults - 0
                              Search forward from start of MenuPage
                              Find menu that exactly matches text in Menus
                              Search is not sensitive to case
                              Will return no data if menu not found

              _sf_Contains      - Search for a match that contains text in Menus
              _sf_CaseSensitive - Search will be CaseSensitive.
              _sf_Backwards     - Search Backwards from stored position (Only
                                  used when _sf_Position is set)

              _sf_Position      - Position to last found menu entry before doing
                                  new search (Default is to search forward)

                            Other Db flags: Defaults - 0
                              Will allow duplicate menus to be added
                              FName will not be save after changes
                              Window with Db file will be deleted upon exit
                              Entry window will be current window upon exit
                              MenuPage will not be create if it does not exist

              _dbf_SaveFile     - Save the db file FName before returning
              _dbf_NoSwitchWin  - Will return with the Db window being current.
                                  (Note only used when _dbf_NoDelWin is set).

              _dbf_NoDelWin     - Will cause the the window the Db is loaded in
                                  to not be deleted.

              _dbf_CreatePage   - Create MenuPage if it does not exist

            str NewMenuRec  - The menu record to insert or replace

  Exit    : int
              _NoError          - Success, menu deleted and variables updated
                struct Menus      - The text of each menu entry to Level
                int Level         - The Level of the deleted menu
                int WCmd          - The WCmd of the deleted menu
                int Flags         - The number of submenus deleted

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, MenuPage not found in FName
              _ErrorNoDbRecord  - Failure, no matching menu found

  Globals : None

  Macros  : void DbRec2Menu
            int  DbGetMenu
            str  DbMenu2Rec
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( NewMenuRec != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int TInsert_Mode = Insert_Mode;
    int NewWCmd;
    int NewLevel;

    str NewMenu;

    Refresh = False;
    Insert_Mode = True;
    DbRec2Menu( NewMenu, NewLevel, NewWCmd, NewMenuRec );
    if ( NewWCmd == _db_mnu_SepWCmd ) {
      NewMenu = "";
    }
    Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
    Result = DbGetMenu( FName, MenuPage, Menus, Level, WCmd, Flags );
    if ( ( Result == _ErrorNoDbPage ) && ( DbFlags & _dbf_CreatePage ) ) {
      Eof;
      if ( C_Col > 1 ) {
        Cr;
      }
      Text( "\f" + MenuPage );
      Down;
      Result = _ErrorNoDbRecord;
    }
    switch ( Result ) {

      case _NoError :
        Result = _ErrorNoDbRecord;
        if ( DbFlags & _dbf_ReplaceRec ) {
          if ( ( WCmd == 0 ) && ( NewWCmd != 0 ) ) {
            break;
          }
          if ( ( NewLevel == 0 ) || ( NewLevel == Level ) ) {
            Result = _NoError;
            NewMenuRec = DbMenu2Rec( NewMenu, Level, NewWCmd );
          }
        }
        else {
          if ( WCmd == 0 ) {
            if ( NewLevel == 0 ) {
              NewLevel = Level + 1;
            }
            if ( NewLevel != ( Level + 1 ) ) {
              break;
            }
            if ( DbFlags & _dbf_InsertBefore ) {
              Up;
            }
            else {
              Goto_Line( C_Line + Flags );
            }
            ++Flags;
          }
          else {
            if ( NewLevel == 0 ) {
              NewLevel = Level;
            }
            if ( Level != NewLevel ) {
              break;
            }
            if ( DbFlags & _dbf_InsertBefore ) {
              Up;
            }
            Flags = 0;
          }
          Eol;
          Cr;
          Result = _NoError;
          NewMenuRec = DbMenu2Rec( NewMenu, NewLevel, NewWCmd );
        }
        break;

      case _ErrorNoDbRecord :
        if ( ( DbFlags & _dbf_ReplaceRec ) || ( NewLevel > 1 ) ) {
          break;
        }
        if ( DbFlags & _dbf_InsertBefore ) {
          Up;
        }
        else {
          if ( Find_Text( "^\f", 0, _RegExp ) == True ) {
            Up;
          }
          else {
            Eof;
            if ( C_Col == 1 ) {
              Up;
            }
          }
        }
        Eol;
        Cr;
        Result = _NoError;
        NewMenuRec = DbMenu2Rec( NewMenu, 1, NewWCmd );
        Flags = 0;
        break;
    }
    if ( Result == _NoError ) {
      Put_Line( NewMenuRec );
      if ( DbFlags & _dbf_SaveFile )  {
        Save_File;
      }
    }
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Insert_Mode = TInsert_Mode;
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbPutMenu

str DbTBox2Rec( str TBoxName, int BoxShow, int BoxStyle, int UseIcon ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbTBox2Rec

  Function: Returns a toolbox record as stored in command set db files.

  Syntax  : TBoxRec = DbTBox2Rec( TBoxName, BoxShow, BoxStyle, UseIcon );

  Entry   : str TBoxName  - The name of a toolbox
            int BoxShow   - A flag used to specify if a toolbox is visable
                            (See TBTOOLS.SH for _db_tbs_xxx constants)

            int BoxStyle  - The position of a toolbox
                            (See TBTOOLS.SH for _db_tbp_xxx constants)

            int UseIcon   - The size of icon to used in toolboxes
                            (See TBTOOLS.SH for _db_tbi_xxx constants)

  Exit    : str     - The toolbox record

  Globals : None
  Macros  : None

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  str TBoxRec;

  TBoxRec = _db_Delimit + _db_tbx_BoxId + "=" + TBoxName +
      _db_Delimit + _db_tbx_BoxShow + "=" + Str( BoxShow ) +
      _db_Delimit + _db_tbx_BoxStyle + "=" + Str( BoxStyle ) +
      _db_Delimit + _db_tbx_UseIcon + "=" + Str( UseIcon );

  return ( TBoxRec );

}  // DbTBox2Rec

void DbRec2TBox( str &TBoxName, int &BoxShow, int &BoxStyle, int &UseIcon,
        str TBoxRec )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbRec2TBox

  Function: Fills the passed variable with data from a ToolBox db record.

  Syntax  : DbRec2TBox( TBoxName, BoxShow, BoxStyle, UseIcon, TBoxRec );

  Entry   : str TBoxName  - The returned toolbox name
            int BoxShow   - The returned toolbox show flag
            int BoxStyle  - The returned toolbox style flag
            int UseIcon   - The returned toolbox icon flag
            str TBoxRec   - The toolbox record

  Exit    : None
  Globals : None
  Macros  : None

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  TBoxName = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", TBoxRec );
  BoxShow = Parse_Int( _db_Delimit + _db_tbx_BoxShow + "=", TBoxRec );
  BoxStyle = Parse_Int( _db_Delimit + _db_tbx_BoxStyle + "=", TBoxRec );
  UseIcon = Parse_Int( _db_Delimit + _db_tbx_UseIcon + "=", TBoxRec );

}  // DbRec2TBox

int DbGetToolBox( str FName[128], str &TBoxName, int &Flags ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetToolBox

  Function: Find and return a toolbox record from the BOXLIST.DB page in the db
            file FName which matches TBoxName using search Flags.

  Syntax  : Result = DbGetToolBox( FName, TBoxName, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str TBoxName  - The name of the toolbox to find
                            (Note: use "" to search for any toolbox)

            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from start of db page
                              Find section that exactly matches TBoxName
                              Search is not sensitive to case
                              Will return first record if record not found

              _sf_RegExp        - Search for the regular expression in TBoxName
              _sf_Contains      - Search for a match that contains TBoxName
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found Section before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Default - 0
                            Entry window will be current window upon exit.
                            Window with Db file will be deleted upon exit.

              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note: only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, Section found and variables updated
                str TBoxName      - The found toolbox record
                int Flags         - The number of buttons in toolbox

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, no matching section found
                                    (Note: Variables updated only when
                                    _sf_ErrorNoRec is not set)

                str TBoxName      - The first toolbox
                int Flags         - The number of buttons in toolbox

  Globals : None

  Macros  : int  DbGetRecord
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int DbFlags = Flags;
  int OrgWin = Window_Id;
  int TRefresh = Refresh;
  int Result;
  int RecNo = 0;

  Refresh = False;
  Flags |= _sf_FirstField | _dbf_NoDelWin | _dbf_NoSwitchWin;
  Result = DbGetRecord( FName, _db_tbx_TBPage, _db_tbx_BoxId, TBoxName, RecNo,
      Flags, "" );
  if ( Result == _NoError ) {

    str FndTBox = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", TBoxName );

    Mark_Pos;
    DbGetPage( "", FndTBox + _db_tbx_PageExt, RecNo, Flags );
    Goto_Mark;
    }
  DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
  Refresh = TRefresh;
  return ( Result );

}  // DbGetToolBox

int DbDelToolBox( str FName[128], str &TBoxName, int &Flags ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbDelToolBox

  Function: Delete a toolbox record matching TBoxName using search Flags from
            the BOXLIST.DB page in the db file FName and also delete all
            associated buttons. Returns the deleted toolbox record in TBoxName
            and the number of deleted buttons in Flags.

  Syntax  : Result = DbDelToolBox( FName, TBoxName, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str TBoxName  - The toolbox to delete
            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from start of db page
                              Find section that exactly matches TBoxName
                              Search is not sensitive to case
                              Will return first record if record not found

              _sf_RegExp        - Search for the regular expression in TBoxName
              _sf_Contains      - Search for a match that contains TBoxName
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found Section before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Default - 0
                            FName will not be save after changes
                            Entry window will be current window upon exit
                            Window with Db file will be deleted upon exit

              _dbf_SaveFile     - Save the db file FName before returning
              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, toolbox deleted
                str TBoxName      - The deleted toolbox record
                int Flags         - The number of deleted buttons

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, WCMDMAP.DB page not found in FName
              _ErrorNoDbRecord  - Failure, no matching section found

  Globals : None

  Macros  : int  DbGetRecord
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( TBoxName != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int RecNo = 0;

    Refresh = False;
    Flags |= _sf_FirstField | _dbf_NoDelWin | _dbf_NoSwitchWin;
    Result = DbGetRecord( FName, _db_tbx_TBPage, _db_tbx_BoxId, TBoxName, RecNo,
        Flags, "" );
    if ( Result == _NoError ) {

      str FndTBox = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", TBoxName );

      Del_Line;
      Mark_Pos;
      if ( DbGetPage( "", FndTBox + _db_tbx_PageExt, RecNo, Flags ) ==
          _NoError ) {
        Block_Begin;
        Goto_Line( C_Line + Flags );
        Delete_Block;
      }
      Goto_Mark;
      if ( DbFlags & _dbf_SaveFile ) {
        Save_File;
      }
    }
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbDelToolBox

int DbPutToolBox( str FName[128], str &TBoxName, int &Flags, str NewTBRec ) {
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbPutToolBox

  Function: Insert a new toolbox or update a specified toolbox matching
            TBoxName, using search Flags, from the BOXLIST.DB page in the db
            file FName with NewTBRec. Returns the found and/or updated toolbox
            record in TBoxName and the number of buttons in Flags.

  Syntax  : Result = DbDelToolBox( FName, TBoxName, Flags, NewTBRec );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str TBoxName  - The toolbox to delete
            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from start of db page
                              Find section that exactly matches TBoxName
                              Search is not sensitive to case
                              Will return first record if record not found

              _sf_RegExp        - Search for the regular expression in TBoxName
              _sf_Contains      - Search for a match that contains TBoxName
              _sf_CaseSensitive - Search will be CaseSensitive
              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found Section before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Placement and other db flags:  Defaults - 0
                            Insert NewTBRec
                            After found toolbox or as last toolbox in BOXLIST.DB
                            Will not save file FName after each update
                            Entry window will be current window upon exit
                            Window with Db file will be deleted upon exit
                            Toolbox page will not be create if not found

              _dbf_ReplaceRec   - Replace the found toolbox record with NewTBRec
              _dbf_InsertBefore - Insert NewTBRec before found toolbox or as
                                  the first toolbox in BOXLIST.DB
              _dbf_SaveFile     - Save the db file FName after each update
              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note only used when _dbf_NoDelWin is set)
              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted
              _dbf_CreatePage   - Create toolbox page if it does not exist

            str NewTBRec  - The new toolbox record to add or update

  Exit    : int
              _NoError          - Success, toolbox deleted
                str TBoxName      - The found toolbox record
                int Flags         - The number of buttons in found toolbox

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, BOXLIST.DB page not found in FName
              _ErrorNoDbRecord  - Failure, no matching section found
              _ErrorDupRecord   - Failure, record not added, would be duplicate
                str TBoxName      - The found toolbox record
                int Flags         - The total number of buttons in toolbox

  Globals : None

  Macros  : int  DbGetToolBox
            void DbToolsExit

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  str NewTBox = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", NewTBRec );

  if ( NewTBox != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int TInsert_Mode = Insert_Mode;
    int Junk;

    Refresh = False;
    Insert_Mode = True;
    Flags |= _dbf_NoDelWin | _dbf_NoSwitchWin;
    if ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) {

      int TFlags = Flags;

      Flags &= 0xFFFF ^_sf_Contains;
      if ( DbGetToolBox( FName, NewTBox, Flags ) == _NoError ) {
        Result = _ErrorDupRecord;
        TBoxName = NewTBox;
        Goto Exit;
      }
      FName = "";
      Flags = TFlags;
    }
    if ( TBoxName == "" ) {
      if ( DbFlags & _dbf_ReplaceRec ) {
        Goto Exit;
      }
      Flags &= 0xFFFF ^ _sf_Contains;
    }
    Result = DbGetToolBox( FName, TBoxName, Flags );
    switch ( Result ) {

      case _NoError :
        if ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) {
          if ( DbFlags & _dbf_InsertBefore ) {
            Up;
          }
          Eol;
          Cr;
          Flags = 0;
        }
        break;

      case _ErrorNoDbRecord :
        if ( DbFlags & _dbf_ReplaceRec ) {
          break;
        }
        if ( DbFlags & _dbf_InsertBefore ) {
          Up;
        }
        else {
          if ( Find_Text( "^\f", 0, _RegExp ) == True ) {
            Up;
          }
          else {
            Eof;
            if ( C_Col == 1 ) {
              Up;
            }
          }
        }
        Eol;
        Cr;
        Flags = 0;
        Result = _NoError;
        break;
    }
    if ( Result == _NoError ) {

      str OldTBox = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", TBoxName ) +
              _db_tbx_PageExt;

      Put_Line( NewTBRec );
      Mark_Pos;
      NewTBox += _db_tbx_PageExt;
      if ( ( ( DbFlags & _dbf_ReplaceRec ) == 0 ) ||
          ( DbGetPage( "", OldTBox, Junk, Flags ) != _NoError ) ) {
        Eof;
        if ( C_Col != 1 ) {
          Cr;
        }
        Flags = 0;
      }
      Put_Line( "\f" + NewTBox );
      Goto_Mark;
      if ( DbFlags & _dbf_SaveFile )  {
        Save_File;
      }
    }

Exit:
    DbToolsExit( Result, DbFlags, OrgWin );  // Del and switch windows if needed
    Insert_Mode = TInsert_Mode;
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbPutToolBox

int DbGetTBButton( str FName[128], str &TBoxName, int &WCmd, int &BtnNo,
        int &Flags )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbGetTBButton

  Function: Find and return a specified toolbox button record from the TBoxName
            toolbox in the db file FName.

  Syntax  : Result = DbGetTBButton( FName, TBoxName, WCmd, BtnNo, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str TBoxName  - The name or record of the toolbox to search
            int WCmd      - The WCmd of the button to get (0 to get any button)
            int BtnNo     - The button number to get (overrides WCmd search)
            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from first button in toolbox
                              Will return first button if record not found

              _sf_Backwards     - Search Backwards from stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position to last found button before doing
                                  new search. (Default is to search forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Default - 0
                            Entry window will be current window upon exit.
                            Window with Db file will be deleted upon exit.

              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note: only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, button found and variables updated
                str TBoxName      - The toolbox page
                int WCmd          - The WCmd of the found button
                int BtnNo         - The number of the found button
                int Flags         - The number of buttons in toolbox

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, toolbox db page not found in FName
              _ErrorNoDbRecord  - Failure, no matching button found
                                    (Note: Variables updated only when
                                    _sf_ErrorNoRec is not set)

                str TBoxName      - The toolbox page
                int WCmd          - The WCmd of the firt button
                int BtnNo         - 1
                int Flags         - The number of buttons in toolbox

  Globals : None

  Macros  : int  DbGetRecord

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( XPos( _db_Delimit, TBoxName, 1 ) ) {  // See if toolbox record
    TBoxName = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", TBoxName );
  }
  if ( TBoxName != "" ) {

    int TRefresh = Refresh;

    str WCmdData = "";

    Refresh = False;
    if ( Get_Extension( TBoxName ) == "" ) {
      TBoxName += _db_tbx_PageExt;      // Add page extension
    }
    Flags |= _sf_Contains | _sf_FirstField;
    if ( WCmd != 0 ) {
      WCmdData = Str( WCmd );
      Flags &= 0xFFFF ^ ( _sf_Contains | _sf_RegExp );  // Force exact match
    }
    Result = DbGetRecord( FName, TBoxName, _db_tbb_WCmd, WCmdData, BtnNo, Flags,
        "" );
    if ( Result == _NoError ) {
      WCmd = Parse_Int( _db_Delimit + _db_tbb_WCmd + "=", WCmdData );
    }
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbGetTBButton

int DbDelTBButton( str FName[128], str &TBoxName, int &WCmd, int &BtnNo,
        int &Flags )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbDelTBButton

  Function: Delete a specified toolbox button record from the TBoxName toolbox
            in the db file FName.

  Syntax  : Result = DbDelTBButton( FName, TBoxName, WCmd, BtnNo, Flags );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str TBoxName  - The name or record of the toolbox to search
            int WCmd      - The WCmd of the button to delete (0 for any)
            int BtnNo     - The button number to delete (overrides WCmd search)
            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from first button in toolbox
                              Will return first button if record not found

              _sf_Backwards     - Search Backwards from BtnNo or stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position BtnNo or to last found button before
                                  doing new search. (Default is to search
                                  forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Other Db flags: Defaults - 0
                            Db file FName will not be save after changes
                            Window with Db file will be deleted upon exit
                            Entry window will be current window upon exit

              _dbf_SaveFile     - Save the db file FName after changes made
              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note: only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

  Exit    : int
              _NoError          - Success, button found and variables updated
                str TBoxName      - The toolbox page
                int WCmd          - The WCmd of the found button
                int BtnNo         - The number of the found button
                int Flags         - The number of buttons in toolbox

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, toolbox db page not found in FName
              _ErrorNoDbRecord  - Failure, no matching button found
                                    (Note: Variables updated only when
                                    _sf_ErrorNoRec is not set)

                str TBoxName      - The toolbox page
                int WCmd          - The WCmd of the firt button
                int BtnNo         - 1
                int Flags         - The number of buttons in toolbox

  Globals : None

  Macros  : int  DbDelRecord

               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( XPos( _db_Delimit, TBoxName, 1 ) ) {  // See if toolbox record
    TBoxName = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", TBoxName );
  }
  if ( TBoxName != "" ) {

    int DbFlags = Flags;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;

    str WCmdData = "";

    Refresh = False;
    if ( Get_Extension( TBoxName ) == "" ) {
      TBoxName += _db_tbx_PageExt;    // Add page extension
    }
    Flags |= _sf_FirstField;
    if ( WCmd != 0 ) {
      WCmdData = Str( WCmd );
      Flags &= 0xFFFF ^ ( _sf_Contains | _sf_RegExp );  // Force exact match
    }
    Result = DbDelRecord( FName, TBoxName, _db_tbb_WCmd, WCmdData, BtnNo,
        Flags, "" );
    if ( Result == _NoError ) {
      WCmd = Parse_Int( _db_Delimit + _db_tbb_WCmd + "=", WCmdData );
      --Flags;
    }
    Refresh = TRefresh;
  }
  return ( Result );

}  // DbDelCmdSection

int DbPutTBButton( str FName[128], str &TBoxName, int &WCmd, int &BtnNo,
        int &Flags, int NewWCmd )
{
/******************************************************************************
                               Multi-Edit Macro
                               14-Dec-94  15:27

  Name    : DbPutTBButton

  Function: Insert or replace a specified toolbox button record in the toolbox
            TBoxName in the db file FName.

  Syntax  : Result = DbPutTBButton( FName, TBoxName, WCmd, BtnNo, Flags,
                NewWCmd );

  Entry   : str FName     - The db file to search
                            (Note: use "" to search the current file)

            str TBoxName  - The name or record of the toolbox to search
            int WCmd      - The WCmd of the button to replace (0 for any)
            int BtnNo     - The button number to replace (overrides WCmd search)
            int Flags     - Search mode and other db flags. (ORed together)

                            Search mode flags: Defaults - 0
                              Search forward from first button in toolbox
                              Will return first button if record not found

              _sf_Backwards     - Search Backwards from BtnNo or stored position
                                  (Only used when _sf_Position is set)

              _sf_Position      - Position BtnNo or to last found button before
                                  doing new search. (Default is to search
                                  forward)

              _sf_ErrorNoRec    - Will cause no record to be returned on error

                          Placement and other db flags:  Defaults - 0
                            Will allow duplicate buttons to be added
                            Insert new button
                            After found button or as last button in toolbox
                            Db file FName will not be save after changes
                            Window with db file will be deleted upon exit
                            Entry window will be current window upon exit
                            Toolbox page will not be created

              _dbf_NoDups       - Will not insert new button when it is a
                                  duplicate.

              _dbf_ReplaceRec   - Replace the found button with NewWCmd
              _dbf_InsertBefore - Insert new button before found button or as
                                  the first button in toolbox

              _dbf_SaveFile     - Save the db file FName after changes made
              _dbf_NoSwitchWin  - Will return with the db window being current
                                  (Note: only used when _dbf_NoDelWin is set)

              _dbf_NoDelWin     - Will cause the the window the db is loaded in
                                  to not be deleted

            int NewWCmd   - The WCmd for the inserted or replaced button

  Exit    : int
              _NoError          - Success, button found and variables updated
                str TBoxName      - The toolbox page
                int WCmd          - The WCmd of the found button
                int BtnNo         - The number of the found button
                int Flags         - The number of buttons in toolbox

              _ErrorNoFile      - Failure, file FName not found
              _ErrorNoDbPage    - Failure, toolbox db page not found in FName
              _ErrorNoDbRecord  - Failure, no matching button found
                                    (Note: Variables updated only when
                                    _sf_ErrorNoRec is not set)

                str TBoxName      - The toolbox page
                int WCmd          - The WCmd of the firt button
                int BtnNo         - 1
                int Flags         - The number of buttons in toolbox

  Globals : None

  Macros  : int  DbPutRecord


               Copyright (C) 1994 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  int Result = _ErrorNoDbRecord;

  if ( NewWCmd != 0 ) {
    if ( XPos( _db_Delimit, TBoxName, 1 ) ) {  // See if toolbox record
      TBoxName = Parse_Str( _db_Delimit + _db_tbx_BoxId + "=", TBoxName );
    }
    if ( TBoxName != "" ) {

      int TRefresh = Refresh;

      str WCmdData = "";
      str NewWCmdData = _db_Delimit + _db_tbb_WCmd + "=" + Str( NewWCmd );

      Refresh = False;
      if ( Get_Extension( TBoxName ) == "" ) {
        TBoxName += _db_tbx_PageExt;    // Add page extension
      }
      Flags |= _sf_FirstField;
      if ( WCmd != 0 ) {
        WCmdData = Str( WCmd );
        Flags &= 0xFFFF ^ ( _sf_Contains | _sf_RegExp );  // Force exact match
      }
      Result = DbPutRecord( FName, TBoxName, _db_tbb_WCmd, WCmdData, BtnNo,
          Flags, "", NewWCmdData );
      if ( Result == _NoError ) {
        WCmd = Parse_Int( _db_Delimit + _db_tbb_WCmd + "=", WCmdData );
      }
      Refresh = TRefresh;
    }
  }
  return ( Result );

}  // DbPutTBButton
