     //////////////////////////////////////////////////////////////////////
     // WC_Subs v1.0 (C) Copyright 1995 David Wallace Croft.
     //
     // UserID_File needs to handle large user id's with filename extension
     // File_Is_Free may not work if any other flags set
     //////////////////////////////////////////////////////////////////////

     //////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////
     const DATE_MASK_ISO = "yyyy-mm-dd"

     const SYSOP_NO     = 0
     const SYSOP_YES    = 1
     const SYSOP_MASTER = 2
     const SYSOP_NET    = 3

     const FLAG_USER_NEVER_DELETE = 1

     const SECONDARY_MAX = 5

     //////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////

     declare function Boolean_Image ( \
       B as boolean ) \
       as string

     declare function Cost_Update (                         \
                byval Current_Cost              as integer, \
                byval Cost_Delta                as integer, \
                byval Cost_Min                  as integer, \
                byval Cost_Max                  as integer, \
                byval Prior_Income_Per_Day      as long   , \
                byval Usages_Since_Last_Update  as long   , \
                byval Cost_Previously_Decreased as boolean, \
                byval Days_Since_Last_Update    as long   ) as integer

     declare function Days_Since ( Old_DateTime as DateTime ) as long

     declare function Days_Since_Today ( \
       Old_Date as Date ) as long

     declare function Dir_Exists ( \
       byval Dir_Name as string ) \
       as boolean

     declare sub Dir_Del_File_By_File ( \
       byval Dir_Name as string )

     declare function Dir_Prune ( \
       byval Dir_Name as string ) \
       as boolean

     declare function Disk_File_Copy ( \
       byval Path_File_From as string, \
       byval Path_File_To   as string ) \
       as boolean

     declare sub Disk_File_Zero_Bytes_Kill ( \
       byval File_Mask as string, \
       byval Path_Name as string )

     declare function Dollars_Str ( \
       byval Cents as long ) \
       as string

     declare function File_Area_Ask ( \
       File_Area as integer )         \
       as boolean

     declare function File_Area_Has_File ( \
       byval File_Area as integer,         \
       byval File_Name as string )         \
       as boolean

     declare function File_Area_Name ( \
       byval File_Area as integer )    \
       as string

     declare function File_Area_Path_Found ( \
       File_Area_Path as string, \
       byval File_Area as integer ) \
       as boolean

     declare function File_Area_Transfer ( \
       File_Area_Old as integer, \
       File_Area_New as integer ) \
       as boolean

     declare sub File_Area_Transfer_Ask

     declare function File_Ask ( \
       File_Area as integer,     \
       File_Name as string )     \
       as boolean

     declare function File_Is_Free ( \
       FileRec as FileRecord ) \
       as boolean

     declare function File_Is_Marked ( \
       FileRec as FileRecord ) \
       as boolean

     declare function File_Is_Never_Delete ( \
       FileRec as FileRecord ) \
       as boolean

     declare function File_Never_Delete_Mark ( \
       FileRec as FileRecord ) as boolean

     declare function File_Never_Delete_Unmark ( \
       FileRec as FileRecord ) as boolean

     declare function File_Path_Found ( \
       File_Path as string, \
       FileRec as FileRecord ) \
       as boolean

     declare function File_Record_Found (  \
       File_Record as FileRecord,  \
       byval File_Area as integer, \
       byval File_Name as string ) \
       as boolean

     declare function File_Text_Append ( \
       byval Aft_File_Txt as string, \
       byval Original_Txt as string ) \
       as boolean

     declare function File_Text_Filter ( \
       byval Text_File_Name as string,   \
       byval Filter_Str as string )      \
       as boolean

     declare function File_Text_Insert ( \
       byval Pre_File_Txt as string, \
       byval Original_Txt as string ) \
       as boolean

     declare function File_Text_Replace_Line (  \
          byval FileName_Txt as string, \
          byval New_Line     as string, \
          byval Line_Number  as long )  \
             as boolean

     declare function File_Transfer (   \
       byval File_Area_Old as integer,  \
       byval File_Name as string,       \
       byval File_Area_New as integer ) \
       as boolean

     declare sub File_Transfer_Ask

     declare function Integer_Ask (  \
       Prompt  as string  = "",      \
       Min     as integer = -32768, \
       Max     as integer =  32767, \
       Default as integer =  0 )     \
       as integer

     declare function Long_Ask (         \
       Prompt  as string = "",           \
       Min     as long   = -2147483647,  \
       Max     as long   =  2147483647,  \
       Default as long   =  0         )  \
       as long

     declare function Maximum ( \
       A as integer, \
       B as integer ) \
       as integer

     declare function Minimum ( \
       A as integer, \
       B as integer ) \
       as integer

     declare sub Password_Change

     declare function Real_Ask (     \
       Prompt  as string  = "",      \
       Min     as real    = -3.4e38, \
       Max     as real    =  3.4e38, \
       Default as real    =  0.0 )   \
       as real

     declare function Str_Strip ( \
       byval Super_Str as string, \
       byval Sub_Str   as string ) \
       as string

     declare function String_Is_Integer ( \
       byval Str_Int as string ) \
       as boolean

     declare function String_Reverse ( \
       byval String_Normal as string ) \
       as string

     declare function User_Can_Upload_To_File_Area ( \
       byval File_Area as integer )                  \
       as boolean

     declare function User_File_Ratio \
       as real

     declare function User_Has_AccessFileDown ( \
       byval File_Area as integer )     \
       as boolean

     declare function User_Has_AccessFileList ( \
       byval File_Area as integer )     \
       as boolean

     declare function User_Is_Never_Delete ( \
       User_Rec as UserRecord ) \
       as boolean

     declare function User_Is_SysOp \
       as boolean

     declare function User_Is_Uploader ( \
       byval File_Area as integer,       \
       byval File_Name as string )       \
       as boolean

     declare function User_Over_File_Ratio \
       as boolean

     declare function User_Paid_Cost ( \
       Cents as integer )              \
       as boolean

     declare function User_Record_Found (  \
             User_Rec  as UserRecord, \
       byval User_Name as string,  \
       byval User_ID   as long )   \
       as boolean

     declare function UserID_From_UserName ( \
       byval UserName as string ) \
       as long

     declare function UserID_File ( \
       byval UserID as long ) \
       as string

     declare function UserName_File ( \
       byval UserName as string ) \
       as string

     declare function WCWork_Dir \
       as string

     declare function WorkFile_Tmp \
       as string

     //////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////

     function Boolean_Image ( B as boolean ) as string
     //////////////////////////////////////////////////////////////////////
       if B then
         Boolean_Image = "TRUE"
       else
         Boolean_Image = "FALSE"
       end if
     end function

     function Cost_Update (                                 \
                byval Current_Cost              as integer, \
                byval Cost_Delta                as integer, \
                byval Cost_Min                  as integer, \
                byval Cost_Max                  as integer, \
                byval Prior_Income_Per_Day      as long   , \
                byval Usages_Since_Last_Update  as long   , \
                byval Cost_Previously_Decreased as boolean, \
                byval Days_Since_Last_Update    as long   ) as integer
     //////////////////////////////////////////////////////////////////////
       dim Current_Income_Per_Day as long
       dim Future_Cost            as integer
     //////////////////////////////////////////////////////////////////////
       if Days_Since_Last_Update < 1 then
         Days_Since_Last_Update = 1
       end if
       Current_Income_Per_Day = Current_Cost * Usages_Since_Last_Update \
         / Days_Since_Last_Update
       if Usages_Since_Last_Update < 1 then
         Future_Cost = Current_Cost - Cost_Delta
       elseif Cost_Previously_Decreased then
         if Current_Income_Per_Day >= Prior_Income_Per_Day then
           Future_Cost = Current_Cost - Cost_Delta
         else
           Future_Cost = Current_Cost + Cost_Delta
         end if
       else
         if Current_Income_Per_Day >= Prior_Income_Per_Day then
           Future_Cost = Current_Cost + Cost_Delta
         else
           Future_Cost = Current_Cost - Cost_Delta
         end if
       end if
       if Future_Cost < Cost_Min then
         Future_Cost = Cost_Min
       elseif Future_Cost > Cost_Max then
         Future_Cost = Cost_Max
       end if
       Cost_Update = Future_Cost
     end function

     function Days_Since ( Old_DateTime as DateTime ) as long
     //////////////////////////////////////////////////////////////////////
       dim Now as DateTime
     //////////////////////////////////////////////////////////////////////
       CurrentDateTime ( Now )
       Days_Since = Now.D.Number - Old_DateTime.D.Number
     end function

     function Days_Since_Today ( \
       Old_Date as Date ) as long
     //////////////////////////////////////////////////////////////////////
       dim Now as DateTime
     //////////////////////////////////////////////////////////////////////
       CurrentDateTime ( Now )
       Days_Since_Today = Now.D.Number - Old_Date.Number
     end function

     sub Dir_Del_File_By_File ( \
       byval Dir_Name as string )
     //////////////////////////////////////////////////////////////////////
       dim SrchRec as SearchRec
     //////////////////////////////////////////////////////////////////////
       if FindFirst ( Dir_Name + "\*.*", 0, SrchRec ) = 0 then
         do
           ? "Delete "; Dir_Name; "\"; SrchRec.Name; "?";
           if InputYesNo ( " (y/N):  ", false ) then
             del Dir_Name + "\" + SrchRec.Name
             if not Exists ( Dir_Name + "\" + SrchRec.Name ) then
               ? "Killed "; Dir_Name; "\"; SrchRec.Name; "."
             else
               ? "Failed."
               WaitEnter
             end if
           end if
         loop while FindNext ( SrchRec ) = 0
         if InputYesNo ( "Remove " + Dir_Name + "? (y/N):  ", false ) then
           RmDir ( Dir_Name )
           if not Dir_Exists ( Dir_Name ) then
             ? "Removed."
           else
             ? "Failed."
             WaitEnter
           end if
         end if
       else
         ? Dir_Name; "\*.* files not found."
         WaitEnter
       end if
     end sub

     function Dir_Exists ( \
       byval Dir_Name as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim SrchRec as SearchRec
     //////////////////////////////////////////////////////////////////////
       Dir_Exists = false
       if FindFirst ( Dir_Name, 16, SrchRec ) = 0 then
         Dir_Exists = true
       end if
     end function

     function Dir_Prune ( \
       byval Dir_Name as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim SrchRec as SearchRec
       dim Dummy as boolean
     //////////////////////////////////////////////////////////////////////
       if not Dir_Exists ( Dir_Name ) then
         ? "Error:  unable to find directory to be pruned named"
         ? "        "; Dir_Name; "."
         delay ( 5 )
         Dir_Prune = false
         exit function
       end if
       if FindFirst ( Dir_Name + "\*.*", 0, SrchRec ) = 0 then
         do
           del Dir_Name + "\" + SrchRec.Name
         loop while FindNext ( SrchRec ) = 0
       end if
       if FindFirst ( Dir_Name + "\*.*", 16, SrchRec ) = 0 then
         do
           if ( SrchRec.Name <> "." ) and ( SrchRec.Name <> ".." ) then
             if not Dir_Prune ( Dir_Name + "\" + SrchRec.Name ) then
               Dir_Prune = false
               exit function
             end if
           end if
         loop while FindNext ( SrchRec ) = 0
       end if
       RmDir ( Dir_Name )
       Dir_Prune = not Dir_Exists ( Dir_Name )
     end function

     function Disk_File_Copy ( \
       byval Path_File_From as string, \
       byval Path_File_To   as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       Disk_File_Copy = CopyFile ( Path_File_From, Path_File_To )
     end function

     sub Disk_File_Zero_Bytes_Kill ( \
       byval File_Mask as string, \
       byval Path_Name as string )
     //////////////////////////////////////////////////////////////////////
     // Path_Name should have trailing backslash; it will not be added.
     //////////////////////////////////////////////////////////////////////
       dim SrchRec as SearchRec
     //////////////////////////////////////////////////////////////////////
       ? "Deleting files with zero bytes..."
       if FindFirst ( Path_Name + File_Mask, 0, SrchRec ) = 0 then
         do
           ? SrchRec.Name, SrchRec.Size
           if SrchRec.Size = 0 then
             ? "Deleting zero-bytes file "; Path_Name; SrchRec.Name; "..."
             del Path_Name + SrchRec.Name
           end if
         loop while FindNext ( SrchRec ) = 0
       else
         ? "No zero-bytes files found matching "; Path_Name; File_Mask; "."
       end if
     end sub

     function Dollars_Str ( byval Cents as long ) as string
     //////////////////////////////////////////////////////////////////////
       Dollars_Str = Trim ( FormatNumber ( Cents / 100.0, \
         "$##,###,###.##" ) )
     end function

     function File_Area_Ask ( \
       File_Area as integer ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim File_Area_Min as integer
       dim File_Area_Max as integer
       dim File_Area_Str as string
     //////////////////////////////////////////////////////////////////////
       File_Area_Ask = false
       File_Area_Min = 1
       File_Area_Max = MakeWild.MaxFileAreas
       do
         ? "Please choose one File Area ("; File_Area_Min; " to ";
         ? File_Area_Max; ", L for List, Q for Quit):  ";
         input File_Area_Str
         File_Area_Str = Ucase ( File_Area_Str )
         if File_Area_Str = "Q" then
           exit function
         elseif File_Area_Str = "L" then
           ? "File Area List currently not available."
           WaitEnter
rem           File_Area_List
         else
           File_Area = Val ( File_Area_Str )
           if ( File_Area_Min <= File_Area ) and \
              ( File_Area <= File_Area_Max ) then
             File_Area_Ask = true
             exit do
           else
             ? "Please enter a number between "; File_Area_Min; " and ";
             ? File_Area_Max; " inclusive."
             WaitEnter
           end if
         end if
       loop
     end function

     function File_Area_Path_Found ( \
       File_Area_Path as string, \
       byval File_Area as integer ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim FileAreaRec as FileAreaRecord
     //////////////////////////////////////////////////////////////////////
       File_Area_Path_Found = FALSE
       if GetFileArea ( FileAreaRec, File_Area ) then
         File_Area_Path = FileAreaRec.Path
         File_Area_Path_Found = TRUE
       end if
     end function

     function File_Area_Has_File ( \
       byval File_Area as integer, \
       byval File_Name as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim FileRec as FileRecord
     //////////////////////////////////////////////////////////////////////
       File_Area_Has_File \
         = File_Record_Found ( FileRec, File_Area, File_Name )
     end function

     function File_Area_Name ( byval File_Area as integer ) as string
     //////////////////////////////////////////////////////////////////////
       dim File_Area_Rec as FileAreaRecord
     //////////////////////////////////////////////////////////////////////
       File_Area_Name = ""
       if GetFileArea ( File_Area_Rec, File_Area ) then
         File_Area_Name = File_Area_Rec.Name
       end if
     end function

     function File_Area_Transfer ( \
                File_Area_Old as integer, \
                File_Area_New as integer ) \
                as boolean
     //////////////////////////////////////////////////////////////////////
       dim FileRec as FileRecord
     //////////////////////////////////////////////////////////////////////
       File_Area_Transfer = FALSE
       if File_Area_Old = File_Area_New then
         ? "Error:  the source file area and target file area are the same."
         exit function
       end if
       if not GetFirstFile ( FileRec, 1 ) then
         ? "Error:  unable to find any files!"
         exit function
       end if
       ? "Searching for first file in file area "; File_Area_Old; "...";
       do
         if FileRec.Area = File_Area_Old then
           exit do
         end if
         ? ".";
       loop while GetNextFile ( FileRec, 1 )
       ?
       File_Area_Transfer = TRUE
       do
         if FileRec.Area <> File_Area_Old then
           exit function
         end if
         ? "Transferring "; FileRec.Name; "...";
         if File_Transfer ( \
           File_Area_Old, FileRec.Name, File_Area_New ) then
           ? "done."
         else
           ? "failed."
           File_Area_Transfer = FALSE
           ? "An error has occurred.  Continue transferring files? (y/N):  ";
           if not InputYesNo ( "", FALSE ) then
             exit function
           end if
         end if
       loop while GetNextFile ( FileRec, 1 )
     end function

     sub File_Area_Transfer_Ask
     //////////////////////////////////////////////////////////////////////
       dim File_Area_Old as integer
       dim File_Area_New as integer
     //////////////////////////////////////////////////////////////////////
       ?
       ? "This will transfer all of the files from one file area to another."
       ? "For each file in the old file area, it follows these steps:"
       ? "(1) copies the file record from the old file area to the new file area,"
       ? "(2) copies the file from the old file area path or the stored path"
       ? "    to the new file area path, and"
       ? "(3) deletes the old file record and old copy of the file on disk."
       ? "It will not proceed for that file if there is already a file"
       ? "by the same name in the new file area."
       ?
       if not InputYesNo ( \
         "Do you want to transfer an entire file area? (y/N):  ",\
         FALSE ) then
         exit sub
       end if
       ? "Please choose the source (old) file area."
       if not File_Area_Ask ( File_Area_Old ) then
         exit sub
       end if
       ? "Please choose the target (new) file area."
       if not File_Area_Ask ( File_Area_New ) then
         exit sub
       end if
       ? "About to transfer all of the files from file area"
       ? File_Area_Old; ":  "; File_Area_Name ( File_Area_Old )
       ? "to the file area"
       ? File_Area_New; ":  "; File_Area_Name ( File_Area_New ); "."
       ?
       if not InputYesNo ( "Proceed? (y/N):  ", FALSE ) then
         exit sub
       end if
       if File_Area_Transfer ( File_Area_Old, File_Area_New ) then
         ? "File area transfer successful."
       else
         ? "Error:  the transfer of one or more files failed!"
       end if
       WaitEnter
     end sub

     function File_Is_Free ( FileRec as FileRecord ) as boolean
     //////////////////////////////////////////////////////////////////////
       File_Is_Free = FlagIsSet ( FileRec.Flags, 4 )
//       if FileRec.Flags >= 4 = 4 then
 //        File_Is_Free = true
 //      end if
 //      REM File_Is_Free = FlagIsSet ( FileRec.Flags, 4 )
     end function

     function File_Is_Marked ( \
       FileRec as FileRecord ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim Total as integer
       dim File_Index as integer
     //////////////////////////////////////////////////////////////////////
       File_Is_Marked = false
       Total = GetMarkedFiles
       if Total = 0 then
         exit function
       end if
       for File_Index = 1 to Total
         if ( FileRec.Name = GetMarkFileName ( File_Index ) ) and \
            ( FileRec.Area = GetMarkFileArea ( File_Index ) ) then
           File_Is_Marked = true
           exit function
         end if
       next File_Index
     end function

     function File_Is_Never_Delete ( FileRec as FileRecord ) as boolean
     //////////////////////////////////////////////////////////////////////
File_Is_Never_Delete = FlagIsSet ( FileRec.Flags, 2 )
//       File_Is_Never_Delete = true
//       if FileRec.Flags and 2 = 0 then
//         File_Is_Never_Delete = false
//       end if
//       REM File_Is_Free = FlagIsSet ( FileRec.Flags, 4 )
     end function

     function File_Never_Delete_Mark ( FileRec as FileRecord ) as boolean
     //////////////////////////////////////////////////////////////////////
       FlagSet ( FileRec.Flags, 2 )
       File_Never_Delete_Mark = UpdateFile ( FileRec )
     end function

     function File_Never_Delete_Unmark ( FileRec as FileRecord ) as boolean
     //////////////////////////////////////////////////////////////////////
       FlagClear ( FileRec.Flags, 2 )
       File_Never_Delete_Unmark = UpdateFile ( FileRec )
     end function

     function File_Ask (     \
       File_Area as integer, \
       File_Name as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim File_Rec as FileRecord
     //////////////////////////////////////////////////////////////////////
       File_Area = 0
       File_Name = ""
       File_Ask = false
       do
         ? "Please enter the file name [ENTER=abort]:  ";
         input File_Name
         File_Name = Ucase ( File_Name )
         if File_Name = "" then
           File_Ask = false
           exit function
         end if
         do while GetFileInfo ( File_Rec, File_Name )
           ? "Do you mean "; File_Name; " of file area ";
           ? File_Rec.Area; ", "; File_Area_Name ( File_Rec.Area );
           ? "? (Y/n):  ";
           if InputYesNo ( "? (Y/n):  ", true ) then
             File_Area = File_Rec.Area
             File_Ask = true
             exit function
           end if
         loop
         ? File_Name; " not found.  Please check your spelling."
         ?
       loop
     end function

     function File_Path_Found ( \
       File_Path as string, \
       FileRec as FileRecord ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       File_Path_Found = FALSE
       File_Path = FileRec.StoredPath
       if File_Path = "" then
         if File_Area_Path_Found ( File_Path, FileRec.Area ) then
           File_Path_Found = TRUE
         end if
       else
         File_Path_Found = TRUE
       end if
     end function

     function File_Ratio as real
     //////////////////////////////////////////////////////////////////////
       if User.Uploads > 0 then
         File_Ratio = User.Downloads / User.Uploads
       else
         File_Ratio = User.Downloads
       end if
     end function

     function File_Record_Found (  \
       File_Record as FileRecord,  \
       byval File_Area as integer, \
       byval File_Name as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       File_Record_Found = false
       File_Name = UCase ( Trim ( File_Name ) )
       if GetFirstFile ( File_Record, 2 ) then
         if GetFileInfo ( File_Record, File_Name ) then
           do
             if UCase ( Trim ( File_Record.Name ) ) <> File_Name then
               exit function
             end if
             if File_Record.Area = File_Area then
               File_Record_Found = true
               exit function
             end if
           loop while GetNextFile ( File_Record )
         end if
       end if
     end function

     function File_Text_Append ( \
       byval Aft_File_Txt as string, \
       byval Original_Txt as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
     // Appends one file to another.
     // If Original_Txt does not exist, it will be created (or crash).
     // Future fix:  does not check to see if FreeFile worked.
     //////////////////////////////////////////////////////////////////////
       dim Line as string
       dim File_Num_Aft, File_Num_Big as integer
     //////////////////////////////////////////////////////////////////////
       File_Num_Aft = FreeFile
       open Aft_File_Txt for input as File_Num_Aft
       File_Num_Big = FreeFile
       open Original_Txt for append as File_Num_Big
       while not EOF ( File_Num_Aft )
         input #File_Num_Aft, Line
         print #File_Num_Big, Line
       wend
       close ( File_Num_Aft )
       close ( File_Num_Big )
       File_Text_Append = true
     end function

     function File_Text_Filter ( \
       byval Text_File_Name as string, \
       byval Filter_Str as string ) as boolean
     //////////////////////////////////////////////////////////////////////
       dim Line as string
       dim File_Num_Old, File_Num_New as integer
     //////////////////////////////////////////////////////////////////////
       File_Text_Filter = false
       if Exists ( Text_File_Name ) then
         File_Num_Old = FreeFile
         if File_Num_Old = -1 then
           ? "Error:  unable to open a new file."
           delay 5
           exit function
         end if
         open Text_File_Name for input as File_Num_Old
         File_Num_New = FreeFile
         if File_Num_New = -1 then
           ? "Error:  unable to open a new file."
           delay 5
           exit function
         end if
         open WorkFile_Tmp for output as File_Num_New
         while not EOF ( File_Num_Old )
           input #File_Num_Old, Line
           Line = Str_Strip ( Line, Filter_Str )
           print #File_Num_New, Line
         wend
         close ( File_Num_New )
         close ( File_Num_Old )
         File_Text_Filter = CopyFile ( WorkFile_Tmp, Text_File_Name )
         Del ( WorkFile_Tmp )
       end if
     end function

     function File_Text_Insert ( \
       byval Pre_File_Txt as string, \
       byval Original_Txt as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
     // Inserts one file before another.
     // If Original_Txt does not exist, it will be created.
     // Future fix:  does not check to see if FreeFile worked.
     //////////////////////////////////////////////////////////////////////
       dim Line as string
       dim File_Num_Tmp, File_Num_Txt as integer
     //////////////////////////////////////////////////////////////////////
       File_Num_Tmp = FreeFile
       open WorkFile_Tmp for output as File_Num_Tmp
       File_Num_Txt = FreeFile
       open Pre_File_Txt for input as File_Num_Txt
       while not EOF ( File_Num_Txt )
         input #File_Num_Txt, Line
         print #File_Num_Tmp, Line
       wend
       close ( File_Num_Txt )
       if Exists ( Original_Txt ) then
         open Original_Txt for input as File_Num_Txt
         while not EOF ( File_Num_Txt )
           input #File_Num_Txt, Line
           print #File_Num_Tmp, Line
         wend
         close ( File_Num_Txt )
       end if
       close ( File_Num_Tmp )
       File_Text_Insert = CopyFile ( WorkFile_Tmp, Original_Txt )
       Del ( WorkFile_Tmp )
     end function

     function File_Text_Replace_Line (  \
          byval FileName_Txt as string, \
          byval New_Line     as string, \
          byval Line_Number  as long )  \
             as boolean
     //////////////////////////////////////////////////////////////////////
     // Future fix:  does not check to see if FreeFile worked.
     //////////////////////////////////////////////////////////////////////
       dim File_Num_New, File_Num_Old as integer
       dim Line as string
       dim Line_Count as long
     //////////////////////////////////////////////////////////////////////
       File_Num_New = FreeFile
       open WorkFile_Tmp for output as File_Num_New
       File_Num_Old = FreeFile
       open FileName_Txt for input as File_Num_Old
       Line_Count = 0
       while not EOF ( File_Num_Old )
         Line_Count = Line_Count + 1
         input #File_Num_Old, Line
         if Line_Count = Line_Number then
           print #File_Num_New, New_Line
         else
           print #File_Num_New, Line
         end if
       wend
       close ( File_Num_Old )
       while Line_Count < Line_Number
         Line_Count = Line_Count + 1
         if Line_Count = Line_Number then
           print #File_Num_New, New_Line
         else
           print #File_Num_New, ""
         end if
       wend
       close ( File_Num_New )
       File_Text_Replace_Line = CopyFile ( WorkFile_Tmp, FileName_Txt )
       Del ( WorkFile_Tmp )
     end function

     function File_Transfer (           \
       byval File_Area_Old as integer,  \
       byval File_Name as string,       \
       byval File_Area_New as integer ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim FileRec as FileRecord
       dim Path_Old as string
       dim Path_New as string
     //////////////////////////////////////////////////////////////////////
       File_Transfer = false
       if File_Record_Found ( FileRec, File_Area_Old, File_Name ) then
         if File_Path_Found ( Path_Old, FileRec ) then
           FileRec.Area = File_Area_New
           if AddFile ( FileRec ) then
             if File_Area_Path_Found ( Path_New, File_Area_New ) then
               if CopyFile ( Path_Old + File_Name, Path_New + File_Name ) then
                 File_Transfer = TRUE
                 if not DeleteFile ( File_Name, File_Area_Old, TRUE ) then
                   ? "Warning:  unable to delete file record in old file area."
                 end if
               else
                 ? "Unable to copy the file from"
                 ? Path_Old + File_Name
                 ? "to"
                 ? Path_New + File_Name; "."
               end if
             else
               ? "Unable to find path for new file area."
             end if
           else
             ? "Unable to add file record to new file area."
           end if
         else
           ? "Unable to find path for old file area."
         end if
       else
         ? "File record not found."
       end if
     end function

     sub File_Transfer_Ask
     //////////////////////////////////////////////////////////////////////
       dim File_Name as string
       dim File_Area_Old, File_Area_New as integer
     //////////////////////////////////////////////////////////////////////
       if File_Ask ( File_Area_Old, File_Name ) then
         if User_Is_Uploader ( File_Area_Old, File_Name ) then
           if File_Area_Ask ( File_Area_New ) then
             if User_Can_Upload_To_File_Area ( File_Area_New ) then
               if not File_Area_Has_File ( File_Area_New, File_Name ) then
                 if File_Transfer ( \
                   File_Area_Old, File_Name, File_Area_New ) then
                   ? "File transfer was successful."
                 else
                   ? "File transfer was NOT successful."
                 end if
               else
                 ? "The new file area already has a file with that name."
               end if
             else
               ? "You do not have upload access to that file area."
             end if
           else
             ? "File transfer aborted."
           end if
         else
           ? "You may only transfer files that you uploaded."
         end if
       else
         ? "File transfer aborted."
       end if
       WaitEnter
     end sub

     function Integer_Ask ( \
       Prompt  as string,   \
       Min     as integer,  \
       Max     as integer,  \
       Default as integer ) \
       as integer
     //////////////////////////////////////////////////////////////////////
       dim Reply as string
       dim Temp as integer
     //////////////////////////////////////////////////////////////////////
       Integer_Ask = Default
       do
         ? Prompt;
         ? "("; Min; " to "; Max; ") ["; Default; "]:  ";
         input Reply
         Temp = val ( Reply )
         if Reply = "" then
           exit do
         elseif ( Min <= Temp ) and ( Temp <= Max ) then
           Integer_Ask = Temp
           exit do
         else
           Beep
           ? "Please enter a number between "; Min; " and "; Max;
           ? " inclusive or"
           ? "just press ENTER for the default value of "; Default; "."
           WaitEnter
         end if
       loop
     end function

     function Long_Ask (  \
       Prompt  as string, \
       Min     as long,   \
       Max     as long,   \
       Default as long )  \
       as long
     //////////////////////////////////////////////////////////////////////
       dim Reply as string
       dim Temp  as long
     //////////////////////////////////////////////////////////////////////
       Long_Ask = Default
       do
         ? Prompt;
         ? "("; Min; " to "; Max; ") ["; Default; "]:  ";
         input Reply
         Temp = val ( Reply )
         if Reply = "" then
           exit do
         elseif ( Min <= Temp ) and ( Temp <= Max ) then
           Long_Ask = Temp
           exit do
         else
           Beep
           ? "Please enter a number between "; Min; " and "; Max;
           ? " inclusive or"
           ? "just press ENTER for the default value of "; Default; "."
           WaitEnter
         end if
       loop
     end function

     function Maximum ( \
       A as integer, \
       B as integer ) \
       as integer
     //////////////////////////////////////////////////////////////////////
       Maximum = A
       if B > A then Maximum = B
     end function

     function Minimum ( \
       A as integer, \
       B as integer ) \
       as integer
     //////////////////////////////////////////////////////////////////////
       Minimum = A
       if B < A then Minimum = B
     end function

     sub Password_Change
     //////////////////////////////////////////////////////////////////////
       dim UserTmp as UserRecord
       dim Confirm as UserRecord
     //////////////////////////////////////////////////////////////////////
       ?
       ? "Please enter your OLD password:  ";
       input UserTmp.Password
       if not ( EncodePassword ( UserTmp.Password ) = User.Password ) then
         ? "Invalid password."
         WaitEnter
         exit sub
       end if
       ?
       ? "Please enter your NEW password:  ";
       input UserTmp.Password
       ?
       ? "Please enter your NEW password once again to confirm:  ";
       input Confirm.Password
       if UserTmp.Password <> Confirm.Password then
         ? "Confirmation password does not match.  Password not changed."
         WaitEnter
         exit sub
       end if
       User.Password = EncodePassword ( UserTmp.Password )
       ? "Your password has been changed."
       WaitEnter
     end sub

     function Real_Ask ( \
       Prompt  as string,        \
       Min     as real,          \
       Max     as real,          \
       Default as real )         \
       as real
     //////////////////////////////////////////////////////////////////////
       dim Reply as string
       dim Temp as real
     //////////////////////////////////////////////////////////////////////
       do
         Real_Ask = Default
         ? Prompt;
         if ( abs ( Min ) < 9999999.999 ) \
           and ( abs ( Max ) < 9999999.999 ) then
           ? "("; Trim ( FormatNumber ( Min, "########.###" ) );
           ? " to "; Trim ( FormatNumber ( Max, "########.###" ) );
           ? ") ";
         end if
         if abs ( Default ) < 9999999.999 then
           ? "["; Trim ( FormatNumber ( Default, "########.###" ) ); "]";
         end if
         ? ":  ";
         input Reply
         if Reply = "" then
           exit do
         end if
         if not StrToReal ( Reply, Temp ) then
           Beep
           ? "Please enter a real number between "
           ? Min; " and ";
           ? Max; " inclusive or"
           ? "just press ENTER for the default value of "
           ? Default; "."
           WaitEnter
         end if
         if ( Min <= Temp ) and ( Temp <= Max ) then
           Real_Ask = Temp
           exit do
         else
           Beep
           ? "Please enter a number between "; Min; " and "; Max;
           ? " inclusive or"
           ? "just press ENTER for the default value of "; Default; "."
           WaitEnter
         end if
       loop
     end function

     function String_Is_Integer ( \
       byval Str_Int as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim Int_Str as integer
     //////////////////////////////////////////////////////////////////////
       Str_Int = UCase ( Trim ( Str_Int ) )
       Int_Str = Val ( Str_Int )
       String_Is_Integer = ( Str ( Int_Str ) = Str_Int )
     end function

     function String_Reverse ( \
       byval String_Normal as string ) \
       as string
     //////////////////////////////////////////////////////////////////////
       dim Index as integer
       dim Temp  as string
     //////////////////////////////////////////////////////////////////////
       Temp = ""
       for Index = Len ( String_Normal ) to 1 step -1
         Temp = Temp + String_Normal ( Index )
       next Index
       String_Reverse = Temp
     end function

     function Str_Strip ( \
       byval Super_Str as string, \
       byval Sub_Str   as string ) as string
     //////////////////////////////////////////////////////////////////////
     // Strips every instance of substring out of the superstring.
     //////////////////////////////////////////////////////////////////////
       while InStr ( Super_Str, Sub_Str ) > 0
         Super_Str = Left ( Super_Str, InStr ( Super_Str, Sub_Str ) - 1 ) \
           + Right ( Super_Str, Len ( Super_Str ) + 1 \
           - InStr ( Super_Str, Sub_Str ) - Len ( Sub_Str ) )
       wend
       Str_Strip = Super_Str
     end function

     function User_Can_Upload_To_File_Area ( \
       byval File_Area as integer )          \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim Sec as integer
       dim User_Secondary as SecurityProfile
     //////////////////////////////////////////////////////////////////////
       User_Can_Upload_To_File_Area = FALSE
       if UserSec.AccessFileUp ( File_Area ) = TRUE then
         User_Can_Upload_To_File_Area = TRUE
       else
         for Sec = 1 to SECONDARY_MAX
           if GetSecProfile ( User_Secondary, User.Secondary ( Sec ) ) then
             if User_Secondary.AccessFileUp ( File_Area ) = TRUE then
               User_Can_Upload_To_File_Area = TRUE
               exit for
             end if
           end if
         next Sec
       end if
     end function

     function User_Has_AccessFileDown ( \
       byval File_Area as integer )     \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim Sec as integer
       dim User_Secondary as SecurityProfile
     //////////////////////////////////////////////////////////////////////
       User_Has_AccessFileDown = FALSE
       if UserSec.AccessFileDown ( File_Area ) then
         User_Has_AccessFileDown = TRUE
       else
         for Sec = 1 to SECONDARY_MAX
           if GetSecProfile ( User_Secondary, User.Secondary ( Sec ) ) then
             if User_Secondary.AccessFileDown ( File_Area ) then
               User_Has_AccessFileDown = TRUE
               exit for
             end if
           end if
         next Sec
       end if
     end function

     function User_Has_AccessFileList ( \
       byval File_Area as integer )     \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim Sec as integer
       dim User_Secondary as SecurityProfile
     //////////////////////////////////////////////////////////////////////
       User_Has_AccessFileList = FALSE
       if UserSec.AccessFileList ( File_Area ) then
         User_Has_AccessFileList = TRUE
       else
         for Sec = 1 to SECONDARY_MAX
           if GetSecProfile ( User_Secondary, User.Secondary ( Sec ) ) then
             if User_Secondary.AccessFileList ( File_Area ) then
               User_Has_AccessFileList = TRUE
               exit for
             end if
           end if
         next Sec
       end if
     end function

     function User_File_Ratio \
       as real
     //////////////////////////////////////////////////////////////////////
       if User.Uploads <> 0 then
         User_File_Ratio = User.Downloads / User.Uploads
       else
         User_File_Ratio = User.Downloads
       end if
     end function

     function User_Is_Never_Delete ( \
       User_Rec as UserRecord ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       User_Is_Never_Delete \
         = FlagIsSet ( User_Rec.UFlags, Flag_User_Never_Delete )
     end function

     function User_Is_SysOp as boolean
     //////////////////////////////////////////////////////////////////////
     // Net Sysop status does not count.
     //////////////////////////////////////////////////////////////////////
       User_Is_SysOp = false
       if ( UserSec.SysOpStatus = SYSOP_MASTER ) or \
          ( UserSec.SysOpStatus = SYSOP_YES ) then
         User_Is_SysOp = true
       end if
     end function

     function User_Is_Uploader (   \
       byval File_Area as integer, \
       byval File_Name as string ) \
       as boolean
     //////////////////////////////////////////////////////////////////////
       dim File_Rec as FileRecord
     //////////////////////////////////////////////////////////////////////
       User_Is_Uploader = false
       if File_Record_Found ( File_Rec, File_Area, File_Name ) then
         if File_Rec.UploaderID = User.UserID then
           User_Is_Uploader = true
         end if
       end if
     end function

     function User_Over_File_Ratio as boolean
     //////////////////////////////////////////////////////////////////////
       User_Over_File_Ratio = false
       if UserSec.MaxRatio <> 0 then
         if User_File_Ratio > UserSec.MaxRatio then
           User_Over_File_Ratio = true
         end if
       end if
     end function

     function User_Paid_Cost ( Cents as integer ) as boolean
     //////////////////////////////////////////////////////////////////////
       User_Paid_Cost = false
       ? "You have an account balance of $";
       ? Trim ( FormatNumber ( User.SubscriptionBalance / 100, "###.##" ) );
       ? "."
       ? "The cost is $";
       ? Trim ( FormatNumber ( Cents / 100, "###.##" ) ); "."
       ?
       if User.SubscriptionBalance >= Cents then
         if InputYesNo ( "Will you pay the cost? (y/N):  ", false ) then
           User.SubscriptionBalance = User.SubscriptionBalance - Cents
           User_Paid_Cost = true
           ? "Thank you."
         else
           ? "Cost not paid."
         end if
       else
         ? "You will not be able to pay the cost."
       end if
       WaitEnter
     end function

     function User_Record_Found (  \
             User_Rec  as UserRecord, \
       byval User_Name as string,  \
       byval User_ID   as long )   \
       as boolean
     //////////////////////////////////////////////////////////////////////
     // This function assumes that if two users have the same name,
     // they will be adjacent in the database for GetUser() calls.
     // This may not be true.
     //////////////////////////////////////////////////////////////////////
       dim User_Name_Found as boolean
     //////////////////////////////////////////////////////////////////////
       User_Record_Found = false
       User_Name = UCase ( Trim ( User_Name ) )
       User_Name_Found = GetUser ( User_Rec, User_Name )
       do while User_Name_Found
         if User_Rec.UserID = User_ID then
           User_Record_Found = true
           exit do
         end if
         User_Name_Found = GetNextUser ( User_Rec )
       loop
     end function

     function UserID_From_UserName ( byval UserName as string ) as long
     //////////////////////////////////////////////////////////////////////
     // Returns -1 if username not found.
     // Assumes no two users have the same name.
     //////////////////////////////////////////////////////////////////////
       dim UserRec as UserRecord
     //////////////////////////////////////////////////////////////////////
       UserID_From_UserName = -1
       if GetUser ( UserRec, UserName ) then
         UserID_From_UserName = UserRec.UserID
       end if
     end function

     function UserName_File ( byval UserName as string ) as string
     //////////////////////////////////////////////////////////////////////
       dim UserRec as UserRecord
     //////////////////////////////////////////////////////////////////////
       UserName_File = ""
       if GetUser ( UserRec, UserName ) then
         UserName_File = UserID_File ( UserRec.UserID )
       end if
     end function

     function UserID_File ( byval UserID as long ) as string
     //////////////////////////////////////////////////////////////////////
       UserID_File = str ( UserID )
     end function

     function WCWork_Dir as string
     //////////////////////////////////////////////////////////////////////
       WCWork_Dir = "WCWORK\NODE" + Trim ( Str ( MakeWild.NodeID ) ) + "\"
     end function

     function WorkFile_Tmp as string
     //////////////////////////////////////////////////////////////////////
       WorkFile_Tmp = WCWork_Dir + "WORKFILE.TMP"
     end function