home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a009 / 6.ddi / SAMPLE.LIF / FILEMAN.PRG < prev    next >
Encoding:
Text File  |  1991-04-14  |  35.1 KB  |  1,185 lines

  1. /***
  2. *  Fileman.prg
  3. *  Sample file manager that can be linked into your programs.
  4. *
  5. *  Copyright (c) 1990, Nantucket Corp.  All rights reserved.
  6. *  David R. Alison
  7. *
  8. *  Note:   Compile with /W /N switches.
  9. *
  10. *  Syntax:
  11. *          FileMan( <nRowTop>, <nColumnTop>, <nRowBottom>,
  12. *                   [<cColorString>],
  13. *                   [<cDefaultPath>] ) -> cDOSFileName
  14. *  Arguments:
  15. *          <nRowTop>, <nColumnTop> and <nRowBottom> are the upper left
  16. *          and lower window coordinates for FileMan().
  17. *
  18. *          <cColorString> is the optional color string to be used for
  19. *          FileMan().  Files are displayed in the standard color,
  20. *          the highlight is in enhanced color and hidden/system files
  21. *          are displayed in the unselected color.  If <cColorString> is
  22. *          not specified, the current default color string will be used.
  23. *
  24. *          <cDefaultPath> is an optional initial file path.  For example,
  25. *          the following FileMan() call:
  26. *
  27. *             FileMan( 1, 5, 18, "C:\DBFILES\*.EXE" )
  28. *
  29. *          displays a FileMan() file chooser from row 1, column 5 to
  30. *          row 18.  The FileMan() menu only displays the files in the
  31. *          C:\DBFILES\ directory that have an EXE extension.
  32. *
  33. *  Returns:
  34. *          FileMan() returns the full path and file name of the file
  35. *          selected.  For example, selecting DBU.EXE from the
  36. *          \DBFILES directory on the C: drive would result in a return
  37. *          character string of:
  38. *
  39. *             "C:\DBFILES\DBU.EXE"
  40. *
  41. *          If no file was selected a null ("") string is returned.
  42. *
  43. *  Description:
  44. *          FileMan() is a high-level function that displays a list of
  45. *          files in a scrolling pick list.  It is best implemented when
  46. *          a user is required to select a file from a disk and perform
  47. *          some type of action on it.
  48. *
  49. *          Navigating through the list of files is accomplished by the
  50. *          up and down arrow keys.  The left and right arrow keys are
  51. *          used to move through the menu options.  Pressing Return will
  52. *          activate the highlighted menu option for the file that is
  53. *          highlighted from the pick list.  The Copy and
  54. *          Delete options can also be performed on tagged files.  Tagging
  55. *          a file is accomplished by pressing the Space Bar while the
  56. *          file is highlighted.  A "tag all" toggle, F5, can be used to
  57. *          tag and untag all the files in the current pick list.
  58. *
  59. *          The menu items in FileMan() are:
  60. *
  61. *          Look, Copy, Rename, Delete, Print and Options
  62. *
  63. *          a brief description of each follows:
  64. *
  65. *          Look:    Views the currently highlighted file in a "raw text"
  66. *                   window, allowing the user to scroll though it.  If
  67. *                   their is a file viewer for the extension of that
  68. *                   file, a file viewer is loaded and the file is viewed
  69. *                   in it's native form.  This version has viewers for:
  70. *                   DBF (Clipper/dBASE database file), NTX (Clipper index),
  71. *                   LBL (Label form) and FRM (Report form).
  72. *
  73. *          Copy:    Copies the selected file(s) to a specific location,
  74. *                   either on another drive or in another directory.
  75. *
  76. *          Rename:  Renames the selected file to a new name.
  77. *
  78. *          Delete:  Deletes the selected file(s).
  79. *
  80. *          Print:   Prints the selected files to the printer in raw form.
  81. *
  82. *          Options: Displays a second menu with choices for sorting the
  83. *                   files, a call to internal help and an "about
  84. *                   FileMan()" screen.
  85. */
  86.  
  87. #include "Fileman.ch"
  88. #include "Directry.ch"
  89. #include "Inkey.ch"
  90. #include "Memoedit.ch"
  91. #include "Achoice.ch"
  92.  
  93. STATIC aFileMan, aFileList
  94. STATIC hScrollBar, nMenuItem, nTagged
  95. STATIC nEl, nRel, lReloadDir, nFileItem
  96. MEMVAR GetList
  97.  
  98. /***
  99. *  FileMan( <nRowTop>, <nColumnTop>, <nRowBottom>, 
  100. *     [<cColorString>], [<cDefaultPath>] ) --> cDOSFileName
  101. *
  102. */
  103. FUNCTION FileMan( nRowTop, nColumnTop, nRowBottom, ;
  104.                   cColorString, cDefaultPath )
  105.    LOCAL lSetScore
  106.  
  107.    // Set the default values
  108.    nMenuItem   := 1
  109.    nTagged     := 0
  110.    nFileItem   := 1
  111.    nEl         := 1
  112.    nRel        := 1
  113.    lReloadDir  := .T.
  114.    aFileMan    := {}
  115.    aFileList   := {}
  116.  
  117.    // Create the array
  118.    aFileMan := ARRAY( FM_ELEMENTS )
  119.  
  120.    // Resolve parameters
  121.    IF nRowTop = NIL
  122.       nRowTop := 0
  123.    ELSE
  124.       IF nRowTop > (MAXROW() - 7)
  125.          nRowTop := MAXROW() - 7
  126.       ENDIF
  127.    ENDIF
  128.    aFileMan[ FM_ROWTOP ] := nRowTop
  129.  
  130.    IF nColumnTop = NIL
  131.       nColumnTop := 0
  132.    ELSE
  133.       IF nColumnTop > (MAXCOL() - 52)
  134.          nColumnTop := MAXROW() - 52
  135.       ENDIF
  136.    ENDIF
  137.    aFileMan[ FM_COLTOP ] := nColumnTop
  138.  
  139.    IF nRowBottom = NIL
  140.       nRowBottom := 0
  141.    ELSE
  142.       IF nRowBottom > MAXROW()
  143.          nRowBottom := MAXROW()
  144.       ENDIF
  145.    ENDIF
  146.    aFileMan[ FM_ROWBOTTOM ] := nRowBottom
  147.    aFileMan[ FM_COLBOTTOM ] := nColumnTop + 51
  148.  
  149.    // Color string for FileMan()
  150.    IF cColorString = NIL
  151.       cColorString := SETCOLOR()
  152.    ENDIF
  153.    aFileMan[ FM_COLOR ] := cColorString
  154.  
  155.    // Initial path information
  156.    IF cDefaultPath = NIL
  157.       cDefaultPath := "\" + CURDIR() + "\*.*"
  158.       cDefaultPath := STRTRAN( cDefaultPath, "\\", "\" ) 
  159.    ENDIF
  160.    aFileMan[ FM_PATH ] := cDefaultPath
  161.  
  162.    // Save the old color
  163.    aFileMan[ FM_OLDCOLOR ] := SETCOLOR( aFileMan[ FM_COLOR ] )
  164.  
  165.    // Save the old work area
  166.    aFileMan[ FM_OLDSELECT ] := SELECT()
  167.  
  168.    // Set the scoreboard
  169.    lSetScore := SET( _SET_SCOREBOARD, .F. )
  170.  
  171.    // Save the screen
  172.    aFileMan[ FM_OLDSCREEN ] := SAVESCREEN( aFileMan[ FM_ROWTOP    ], ;
  173.                                            aFileMan[ FM_COLTOP    ], ;
  174.                                            aFileMan[ FM_ROWBOTTOM ], ;
  175.                                            aFileMan[ FM_COLBOTTOM ] )
  176.  
  177.    CreateScreen()                   // Create the initial screen, etc.
  178.    GetFiles()                       // Call the actual file chooser
  179.  
  180.    // Restore the screen
  181.    RESTSCREEN( aFileMan[ FM_ROWTOP    ], ;
  182.                aFileMan[ FM_COLTOP    ], ;
  183.                aFileMan[ FM_ROWBOTTOM ], ;
  184.                aFileMan[ FM_COLBOTTOM ], ;
  185.                aFileMan[ FM_OLDSCREEN ] )
  186.    // Restore the color
  187.    SetColor( aFileMan[ FM_OLDCOLOR ] )
  188.  
  189.    // Reset the old scoreboard stuff
  190.    SET( _SET_SCOREBOARD, lSetScore )
  191.  
  192.    // Restore the work area
  193.    SELECT ( aFileMan[ FM_OLDSELECT ] )
  194.  
  195.    // Back to the real world!
  196.    RETURN( aFileMan[ FM_RETURNFILE ] )
  197.  
  198. /***
  199. *  GetFiles() --> NIL
  200. *
  201. *
  202. */
  203. STATIC FUNCTION GetFiles
  204.    LOCAL lDone       := .F.            // Primary loop point
  205.    LOCAL nCurrent    := 0              // ACHOICE() result
  206.    LOCAL nLastKey    := 0              // Last value in LASTKEY()
  207.  
  208.    DO WHILE !lDone
  209.       IF lReloadDir
  210.          nEl   := 1
  211.          nRel  := 1
  212.          IF !LoadFiles()
  213.             // A problem occured loading the file names; tell the user
  214.             ErrorBeep()
  215.             Message( "ERROR: No files found!  Press any key..." )
  216.             INKEY( 300 )
  217.             IF YesOrNo( "Would you like to try another path? (Y/N)", "Y" )
  218.                GetNewPath( aFileMan[ FM_PATH ] )
  219.                IF LASTKEY() == K_ESC
  220.                   lDone := .T.
  221.                ELSE
  222.                   LOOP
  223.                ENDIF
  224.             ELSE
  225.                lDone := .T.
  226.             ENDIF
  227.          ELSE
  228.             lReloadDir := .F.
  229.          ENDIF
  230.       ENDIF
  231.       // Time to display the files and act on the response's
  232.       TabUpdate( hScrollBar, nEl, LEN( aFileList ), .T. )
  233.       nCurrent := ACHOICE( aFileMan[ FM_ROWTOP ] + 3, ;
  234.                            aFileMan[ FM_COLTOP ] + 2, ;
  235.                            aFileMan[ FM_ROWBOTTOM ] - 3, ;
  236.                            aFileMan[ FM_COLBOTTOM ] - 4, ;
  237.                            aFileList, .T., "ProcessKey", nEl, nRel )
  238.  
  239.       nFileItem := nCurrent
  240.       nLastKey := LASTKEY()
  241.  
  242.       DO CASE
  243.          CASE UPPER(CHR(nLastKey)) $ "LCRDPO"
  244.             // They selected a menu item ; move the highlight
  245.             nMenuItem := AT( UPPER(CHR(nLastKey)), "LCRDPO" )
  246.             DisplayMenu()
  247.  
  248.          CASE nLastKey == K_RIGHT
  249.             nMenuItem++
  250.             IF nMenuItem > 6
  251.                TONE( 900, 1 )
  252.                nMenuItem := 6
  253.             ENDIF
  254.             DisplayMenu()
  255.  
  256.          CASE nLastKey == K_LEFT
  257.             nMenuItem--
  258.             IF nMenuItem < 1
  259.                TONE( 900, 1 )
  260.                nMenuItem := 1
  261.             ENDIF
  262.             DisplayMenu()
  263.  
  264.          CASE nLastKey == K_ESC
  265.             aFileMan[ FM_RETURNFILE ] := ""
  266.             lDone := .T.
  267.  
  268.          CASE nLastKey == K_ENTER
  269.             // First let's assign the filename and path to aFileMan
  270.             aFileMan[ FM_RETURNFILE ] := ;
  271.                      SUBSTR( aFileMan[ FM_PATH ], 1, ;
  272.                      RAT( "\", aFileMan[ FM_PATH ] ) ) + ;
  273.                      TRIM( SUBSTR( aFileList[ nCurrent ], 1, 12 ) )
  274.  
  275.             // Ok, here's the biggee
  276.             DO CASE
  277.                CASE nMenuItem == MN_LOOK
  278.                   LookAtFile()
  279.  
  280.                CASE nMenuItem == MN_COPY
  281.                   CopyFile()
  282.  
  283.                CASE nMenuItem == MN_RENAME
  284.                   RenameFile()
  285.  
  286.                CASE nMenuItem == MN_DELETE
  287.                   DeleteFile()
  288.  
  289.                CASE nMenuItem == MN_PRINT
  290.                   PrintFile()
  291.  
  292.                CASE nMenuItem == MN_OPEN
  293.                   IF AT( '<dir>', aFileList[ nFileItem ] ) = 0
  294.                      lDone := .T.
  295.                   ELSE
  296.                      LookAtFile()
  297.                   ENDIF
  298.  
  299.             ENDCASE
  300.  
  301.          CASE nLastKey == K_DEL
  302.             DeleteFile()
  303.  
  304.          CASE nLastKey == K_F5
  305.             TagAllFiles()
  306.  
  307.          CASE nLastKey == K_F6
  308.             UnTagAllFiles()
  309.  
  310.          CASE nLastKey == K_SPACE
  311.             // Can't tag directories
  312.             IF AT( "D", SUBSTR( aFileList[ nCurrent ], 43, 6 ) ) == 0
  313.                IF SUBSTR( aFileList[ nCurrent ], 14, 1 ) == " "
  314.                   // It isn't tagged, let's tag it
  315.                   aFileList[ nCurrent ] := STUFF( aFileList[ nCurrent ], ;
  316.                                            14, 1, FM_CHECK )
  317.                   nTagged++
  318.                ELSE
  319.                   // It's already tagged, let's remove the check mark
  320.                   aFileList[ nCurrent ] := STUFF( aFileList[ nCurrent ], ;
  321.                                            14, 1, " " )
  322.                   nTagged--
  323.                ENDIF
  324.             ENDIF
  325.  
  326.       ENDCASE
  327.    ENDDO
  328.  
  329.    RETURN NIL
  330.  
  331. /***
  332. *  LoadFiles() --> lReturnValue 
  333. *
  334. *
  335. */
  336. STATIC FUNCTION LoadFiles
  337.    LOCAL aDirectory := {}, nItem := 0, lReturnValue := .T.
  338.    LOCAL nNumberOfItems := 0, cFileString := ""
  339.  
  340.    // Let the user know what's going on
  341.    Message( "Loading the current directory..." )
  342.    @ aFileMan[ FM_ROWTOP ] + 3, aFileMan[ FM_COLTOP ] + 2 CLEAR TO ;
  343.      aFileMan[ FM_ROWBOTTOM ] - 3, aFileMan[ FM_COLBOTTOM ] - 4
  344.  
  345.    // Load up aFileList with the current directory information
  346.    aDirectory := DIRECTORY( aFileMan[ FM_PATH ], "D" )
  347.    nNumberOfItems := IF( VALTYPE( aDirectory ) != "A", 0, LEN( aDirectory ) )
  348.    aFileList := {}                  // Wipe out the old aFileList
  349.  
  350.    // Check to see if any files actually made it
  351.    IF nNumberOfItems < 1
  352.       // Problem!
  353.       lReturnValue := .F.
  354.  
  355.    ELSE
  356.       // Let the user know what's going on
  357.       Message( "Sorting the current directory..." )
  358.  
  359.       // Sort the current aDirectory array
  360.       ASORT( aDirectory,,, { | x, y | x[ F_NAME ] < y[ F_NAME ] } )
  361.  
  362.       // Let the user know what's going on
  363.       Message( "Processing the current directory..." )
  364.  
  365.       // Now drop it into the array to be displayed with ACHOICE()
  366.       FOR nItem := 1 TO nNumberOfItems
  367.          AADD( aFileList, PADR( aDirectory[ nItem, F_NAME ], 15 ) + ;
  368.                           IF( SUBSTR( aDirectory[ nItem, F_ATTR ], ;
  369.                           1, 1 ) == "D", "   <dir>", ;
  370.                           STR( aDirectory[ nItem, F_SIZE ], 8 ) ) + "  " + ;
  371.                           DTOC( aDirectory[ nItem, F_DATE ] ) + "  " + ;
  372.                           SUBSTR( aDirectory[ nItem, F_TIME ], 1, 5) + "  " + ;
  373.                           SUBSTR( aDirectory[ nItem, F_ATTR ], 1, 4 ) + "  " )
  374.       NEXT
  375.  
  376.    ENDIF
  377.  
  378.    // Clean up the message area before we leave
  379.    Message( aFileMan[ FM_PATH ] )
  380.  
  381.    RETURN( lReturnValue )
  382.  
  383. /***
  384. *  ProcessKey( <nStatus>, <nElement>, <nRelative> ) --> nReturnValue
  385. *
  386. *
  387. */
  388. FUNCTION ProcessKey( nStatus, nElement, nRelative )
  389.    LOCAL nReturnValue := AC_CONT    // Set the default handler to continue
  390.  
  391.    // Update the global element/relative with the passed versions
  392.    nEl  := nElement
  393.    nRel := nRelative
  394.  
  395.    DO CASE
  396.    CASE nStatus == AC_IDLE
  397.       // Update the scroll bar
  398.       TabUpdate( hScrollBar, nElement, LEN( aFileList ) )
  399.       Message( aFileMan[ FM_PATH ] )
  400.  
  401.    CASE nStatus == AC_HITTOP .OR. nStatus == AC_HITBOTTOM
  402.       // Tried to go too far!
  403.       TONE( 900, 1 )
  404.  
  405.    CASE nStatus == AC_EXCEPT
  406.       // Keystroke exception
  407.       DO CASE
  408.       CASE LASTKEY() == K_ESC
  409.          nReturnValue := AC_ABORT
  410.  
  411.       CASE LASTKEY() == K_HOME
  412.          KEYBOARD CHR( K_CTRL_PGUP )
  413.          nReturnValue := AC_CONT
  414.  
  415.       CASE LASTKEY() == K_END
  416.          KEYBOARD CHR( K_CTRL_PGDN )
  417.          nReturnValue := AC_CONT
  418.  
  419.       CASE LASTKEY() == K_LEFT .OR. LASTKEY() == K_RIGHT
  420.          nReturnValue := AC_SELECT
  421.  
  422.       CASE UPPER(CHR(LASTKEY())) $ ;
  423.          "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 " .OR. ;
  424.          LASTKEY() == K_DEL .OR. LASTKEY() == K_ENTER .OR. ;
  425.          LASTKEY() == K_F5 .OR. LASTKEY() == K_F6
  426.  
  427.          nReturnValue := AC_SELECT
  428.  
  429.       ENDCASE
  430.  
  431.    ENDCASE
  432.  
  433.    RETURN (nReturnValue)
  434.  
  435. /***
  436. *  Message( cString ) --> nil
  437. *
  438. *
  439. */
  440. STATIC FUNCTION Message( cString )
  441.    LOCAL cOldColor := SETCOLOR( aFileMan[ FM_COLOR ] )
  442.    ClearMessage()
  443.    @ aFileMan[ FM_ROWBOTTOM ] - 1, aFileMan[ FM_COLTOP ] + 2 SAY ;
  444.       SUBSTR( cString, 1, (aFileMan[FM_COLBOTTOM] - aFileMan[FM_COLTOP] - 6 ))
  445.  
  446.    SETCOLOR( cOldColor )
  447.  
  448.    RETURN NIL
  449.  
  450. /***
  451. *  GetNewPath( <cPath> ) --> cNewPath
  452. *
  453. *
  454. */
  455. STATIC FUNCTION GetNewPath( cPath )
  456.    LOCAL cOldColor := SETCOLOR( aFileMan[ FM_COLOR ] )
  457.    ClearMessage()
  458.    cPath := PADR( cPath, 45 )
  459.    @ aFileMan[ FM_ROWBOTTOM ] - 1, aFileMan[ FM_COLTOP ] + 2 GET ;
  460.      cPath PICTURE "@!@S45@K"
  461.    READ
  462.  
  463.    cPath := LTRIM(TRIM(cPath))
  464.  
  465.    IF RIGHT( cPath, 1 ) == "\"
  466.       cPath += "*.*"
  467.    ENDIF
  468.    IF RIGHT( cPath, 1 ) == ":"
  469.       cPath += "\*.*"
  470.    ENDIF
  471.  
  472.    aFileMan[ FM_PATH ] := cPath
  473.  
  474.    Message( cPath )
  475.  
  476.    SETCOLOR( cOldColor )
  477.    RETURN( TRIM( cPath ) )
  478.  
  479. /***
  480. *  YesOrNo( <cMessage>, <cDefault> ) --> lYesOrNo
  481. *
  482. *
  483. */
  484. STATIC FUNCTION YesOrNo( cMessage, cDefault )
  485.    LOCAL cOldColor := SETCOLOR( aFileMan[ FM_COLOR ] )
  486.    LOCAL lYesOrNo
  487.  
  488.    @ aFileMan[ FM_ROWBOTTOM ] - 1, aFileMan[ FM_COLTOP ] + 2 SAY ;
  489.      TRIM( SUBSTR( cMessage, 1, ;
  490.          (aFileMan[FM_COLBOTTOM] - aFileMan[FM_COLTOP] - 8 )) ) GET ;
  491.          cDefault PICTURE "Y"
  492.    READ
  493.  
  494.    lYesOrNo := (UPPER( cDefault ) == "Y")
  495.    SETCOLOR( cOldColor )
  496.  
  497.    RETURN (lYesOrNo)
  498.  
  499. /***
  500. *  ClearMessage() --> NIL
  501. *
  502. *
  503. */
  504. STATIC FUNCTION ClearMessage
  505.    LOCAL cOldColor := SETCOLOR( aFileMan[ FM_COLOR ] )
  506.    @ aFileMan[ FM_ROWBOTTOM ] - 1, aFileMan[ FM_COLTOP ] + 2 CLEAR TO ;
  507.      aFileMan[ FM_ROWBOTTOM ] - 1, aFileMan[ FM_COLBOTTOM ] - 4
  508.  
  509.    SETCOLOR( cOldColor )
  510.  
  511.    RETURN NIL
  512.  
  513. /***
  514. *  ErrorBeep() --> NIL
  515. *
  516. *
  517. */
  518. STATIC FUNCTION ErrorBeep
  519.    LOCAL nCount := 0
  520.  
  521.    FOR nCount := 1 TO 2
  522.       TONE( 300, 1 )
  523.       TONE( 499, 1 )
  524.    NEXT
  525.  
  526.    RETURN NIL
  527.  
  528. /***
  529. *  CreateScreen() --> NIL
  530. *
  531. *
  532. */
  533. STATIC FUNCTION CreateScreen
  534.  
  535.    LOCAL cFrameType  := FM_SINGLEFRAME
  536.    LOCAL cBorderType := FM_SINGLEBORDER
  537.    LOCAL nRow        := 0
  538.  
  539.    // Draw the primary box
  540.    @ aFileMan[ FM_ROWTOP ], aFileMan[ FM_COLTOP ] CLEAR TO ;
  541.      aFileMan[ FM_ROWBOTTOM ], aFileMan[ FM_COLBOTTOM ]
  542.    @ aFileMan[ FM_ROWTOP ], aFileMan[ FM_COLTOP ], ;
  543.      aFileMan[ FM_ROWBOTTOM ], aFileMan[ FM_COLBOTTOM ] BOX cFrameType
  544.  
  545.    // Draw the horizontal line under the menus
  546.    @ aFileMan[ FM_ROWTOP ] + 2, aFileMan[ FM_COLTOP ];
  547.      SAY SUBSTR( cBorderType, FM_LEFT, 1 )
  548.    @ aFileMan[ FM_ROWTOP ] + 2, aFileMan[ FM_COLBOTTOM ];
  549.      SAY SUBSTR( cBorderType, FM_RIGHT, 1 )
  550.    @ aFileMan[ FM_ROWTOP ] + 2, aFileMan[ FM_COLTOP ] + 1;
  551.      SAY REPLICATE( SUBSTR( cFrameType, FM_HORIZONTAL, 1 ),;
  552.          ( aFileMan[ FM_COLBOTTOM ] - aFileMan[ FM_COLTOP ] - 1 )  )
  553.  
  554.    // Draw the vertical line next to the scroll bar
  555.    FOR nRow := (aFileMan[ FM_ROWTOP ] + 3) TO (aFileMan[ FM_ROWBOTTOM ] - 1)
  556.       @ nRow, aFileMan[ FM_COLBOTTOM ] - 2 ;
  557.         SAY SUBSTR( cFrameType, FM_VERTICAL, 1 )
  558.    NEXT
  559.    @ aFileMan[ FM_ROWTOP ] + 2, aFileMan[ FM_COLBOTTOM ] - 2 SAY ;
  560.      SUBSTR( cBorderType, FM_TOP, 1 )
  561.    @ aFileMan[ FM_ROWBOTTOM ], aFileMan[ FM_COLBOTTOM ] - 2 SAY ;
  562.      SUBSTR( cBorderType, FM_BOTTOM, 1 )
  563.  
  564.    // Draw the horizontal line under the file display area
  565.    @ aFileMan[ FM_ROWBOTTOM ] - 2, aFileMan[ FM_COLTOP ] ;
  566.      SAY SUBSTR( cBorderType, FM_LEFT, 1 )
  567.    @ aFileMan[ FM_ROWBOTTOM ] - 2, aFileMan[ FM_COLBOTTOM ] -2 ;
  568.      SAY SUBSTR( cBorderType, FM_RIGHT, 1 )
  569.    @ aFileMan[ FM_ROWBOTTOM ] - 2, aFileMan[ FM_COLTOP ] + 1 ;
  570.      SAY REPLICATE( SUBSTR( cFrameType, FM_HORIZONTAL, 1 ), ;
  571.          ( aFileMan[ FM_COLBOTTOM ] - aFileMan[ FM_COLTOP ] - 3 )  )
  572.  
  573.    // Create the scrolling thumb tab and assign it to our global static
  574.    hScrollBar := TabNew( aFileMan[ FM_ROWTOP ] + 3, ;
  575.                          aFileMan[ FM_COLBOTTOM ] - 1, ;
  576.                          aFileMan[ FM_ROWBOTTOM ] - 1, ;
  577.                          aFileMan[ FM_COLOR ], 1 )
  578.    TabDisplay( hScrollBar )
  579.  
  580.    DisplayMenu()
  581.  
  582.    RETURN NIL
  583.  
  584. /***
  585. *  DisplayMenu() --> NIL
  586. *
  587. *
  588. */
  589. STATIC FUNCTION DisplayMenu
  590.  
  591.    LOCAL cOldColor := SETCOLOR(), nCol := aFileMan[ FM_COLTOP ] + 2
  592.    LOCAL cItemName
  593.  
  594.    @ aFileMan[ FM_ROWTOP ] + 1, aFileMan[ FM_COLTOP ] + 2 SAY ;
  595.      "Look  Copy  Rename  Delete  Print  Open"
  596.    SETCOLOR( "I" )
  597.    DO CASE
  598.    CASE nMenuItem == MN_LOOK
  599.       nCol := aFileMan[ FM_COLTOP ] + 2
  600.       cItemName := "Look"
  601.  
  602.    CASE nMenuItem == MN_COPY
  603.       nCol := aFileMan[ FM_COLTOP ] + 8
  604.       cItemName := "Copy"
  605.  
  606.    CASE nMenuItem == MN_RENAME
  607.       nCol := aFileMan[ FM_COLTOP ] + 14
  608.       cItemName := "Rename"
  609.  
  610.    CASE nMenuItem == MN_DELETE
  611.       nCol := aFileMan[ FM_COLTOP ] + 22
  612.       cItemName := "Delete"
  613.  
  614.    CASE nMenuItem == MN_PRINT
  615.       nCol := aFileMan[ FM_COLTOP ] + 30
  616.       cItemName := "Print"
  617.  
  618.    CASE nMenuItem == MN_OPEN
  619.       nCol := aFileMan[ FM_COLTOP ] + 37
  620.       cItemName := "Open"
  621.  
  622.    ENDCASE
  623.  
  624.    @ aFileMan[ FM_ROWTOP ] + 1, nCol SAY cItemName
  625.    Message( aFileMan[ FM_PATH ] )
  626.  
  627.    SETCOLOR( cOldColor )
  628.  
  629.    RETURN NIL
  630.  
  631.  
  632. /***
  633. *    TabNew()
  634. */
  635.  
  636. STATIC FUNCTION TabNew( nTopRow, nTopColumn, nBottomRow, ;
  637.                         cColorString, nInitPosition )
  638.    // Creates a new "thumb tab" or scroll bar for the specified coordinates
  639.    LOCAL aTab := ARRAY( TB_ELEMENTS )
  640.  
  641.    aTab[ TB_ROWTOP ]    := nTopRow
  642.    aTab[ TB_COLTOP ]    := nTopColumn
  643.    aTab[ TB_ROWBOTTOM ] := nBottomRow
  644.    aTab[ TB_COLBOTTOM ] := nTopColumn
  645.  
  646.    // Set the default color to White on Black if none specified
  647.    IF cColorString == NIL
  648.       cColorString := "W/N"
  649.    ENDIF
  650.    aTab[ TB_COLOR ]     := cColorString
  651.  
  652.    // Set the starting position
  653.    IF nInitPosition == NIL
  654.       nInitPosition := 1
  655.    ENDIF
  656.    aTab[ TB_POSITION ]    := nInitPosition
  657.  
  658.    RETURN aTab
  659.  
  660.  
  661. /***
  662. *    TabDisplay()
  663. */
  664.  
  665. STATIC FUNCTION TabDisplay( aTab )
  666.    LOCAL cOldColor, nRow
  667.  
  668.    cOldColor := SETCOLOR( aTab[ TB_COLOR ] )
  669.  
  670.    // Draw the arrows
  671.    @ aTab[ TB_ROWTOP ], aTab[ TB_COLTOP ] SAY TB_UPARROW
  672.    @ aTab[ TB_ROWBOTTOM ], aTab[ TB_COLBOTTOM ] SAY TB_DNARROW
  673.  
  674.    // Draw the background
  675.    FOR nRow := (aTab[ TB_ROWTOP ] + 1) TO (aTab[ TB_ROWBOTTOM ] - 1)
  676.       @ nRow, aTab[ TB_COLTOP ] SAY TB_BACKGROUND
  677.    NEXT
  678.  
  679.    SETCOLOR( cOldColor )
  680.  
  681.    RETURN aTab
  682.  
  683.  
  684. /***
  685. *    TabUpdate()
  686. */
  687.  
  688. STATIC FUNCTION TabUpdate( aTab, nCurrent, nTotal, lForceUpdate )
  689.    LOCAL cOldColor, nNewPosition
  690.    LOCAL nScrollHeight := (aTab[TB_ROWBOTTOM]-1)-(aTab[TB_ROWTOP])
  691.  
  692.    IF nTotal < 1
  693.       nTotal := 1
  694.    ENDIF
  695.  
  696.    IF nCurrent < 1
  697.       nCurrent := 1
  698.    ENDIF
  699.  
  700.    IF nCurrent > nTotal
  701.       nCurrent := nTotal
  702.    ENDIF
  703.  
  704.    IF lForceUpdate == NIL
  705.       lForceUpdate := .F.
  706.    ENDIF
  707.  
  708.    cOldColor := SETCOLOR( aTab[ TB_COLOR ] )
  709.  
  710.    // Determine the new position
  711.    nNewPosition := ROUND( (nCurrent / nTotal) * nScrollHeight, 0 )
  712.  
  713.    // Resolve algorythm oversights
  714.    nNewPosition := IF( nNewPosition < 1, 1, nNewPosition )
  715.    nNewPosition := IF( nCurrent == 1, 1, nNewPosition )
  716.    nNewPosition := IF( nCurrent >= nTotal, nScrollHeight, nNewPosition )
  717.  
  718.    // Overwrite the old position (if different), then draw in the new one
  719.    IF nNewPosition <> aTab[ TB_POSITION ] .OR. lForceUpdate
  720.       @ (aTab[ TB_POSITION ] + aTab[ TB_ROWTOP ]), aTab[ TB_COLTOP ] SAY ;
  721.         TB_BACKGROUND
  722.       @ (nNewPosition + aTab[ TB_ROWTOP ]), aTab[ TB_COLTOP ] SAY;
  723.         TB_HIGHLIGHT
  724.       aTab[ TB_POSITION ] := nNewPosition
  725.    ENDIF
  726.  
  727.    SETCOLOR( cOldColor )
  728.  
  729.    RETURN aTab
  730.  
  731.  
  732. /***
  733. *  UpPath( <cPath> ) --> ?
  734. *
  735. *
  736. */
  737. STATIC FUNCTION UpPath( cPath )
  738.    LOCAL cFileSpec
  739.  
  740.    cFileSpec := RIGHT( cPath, LEN( cPath ) - RAT( "\", cPath ) )
  741.    cPath     := LEFT( cPath, RAT( "\", cPath ) - 1 )
  742.    cPath     := LEFT( cPath, RAT( "\", cPath ) )
  743.    cPath     += cFileSpec
  744.  
  745.    RETURN (cPath)
  746.  
  747. /***
  748. *  GetFileExtension( <cFile> ) --> cFileExtension
  749. *
  750. *
  751. */
  752. STATIC FUNCTION GetFileExtension( cFile )
  753.    RETURN( UPPER( SUBSTR( cFile, AT( ".", cFile ) + 1, 3 ) ) )
  754.  
  755. /***
  756. *  LookAtFile() --> NIL
  757. *
  758. *
  759. */
  760. STATIC FUNCTION LookAtFile
  761.    LOCAL cExtension := ""
  762.    LOCAL cOldScreen := SAVESCREEN( 0, 0, MAXROW(), MAXCOL() )
  763.  
  764.    IF AT( "D", SUBSTR( aFileList[ nFileItem ], 43, 6 ) ) <> 0
  765.       // Looks like a directory, let's load it...
  766.       DO CASE
  767.       CASE SUBSTR( aFileList[ nFileItem ], 1, 3 ) == ".  "
  768.          // That's the current directory!
  769.          GetNewPath( aFileMan[ FM_PATH ] )
  770.       CASE SUBSTR( aFileList[ nFileItem ], 1, 3 ) == ".. "
  771.          GetNewPath( UpPath( aFileMan[ FM_PATH ]))
  772.  
  773.       OTHERWISE
  774.          GetNewPath( SUBSTR( aFileMan[ FM_PATH ], 1, ;
  775.             RAT( "\", aFileMan[ FM_PATH ])) + ;
  776.             TRIM(SUBSTR(aFileList[nFileItem],1,12)) + "\*.*")
  777.       ENDCASE
  778.       lReloadDir := .T.
  779.    ELSE
  780.       // Must be a file.  Let's load the proper viewer and take a look
  781.       cExtension := GetFileExtension( SUBSTR(aFileList[nFileItem],1,12) )
  782.  
  783.       DO CASE
  784.       CASE cExtension == "DBF"
  785.          DBFViewer( aFileMan[ FM_RETURNFILE ] )
  786.  
  787.       OTHERWISE
  788.          GenericViewer( aFileMan[ FM_RETURNFILE ] )
  789.  
  790.       ENDCASE
  791.  
  792.       // Restore the screen
  793.       RESTSCREEN( 0, 0, MAXROW(), MAXCOL(), cOldScreen )
  794.  
  795.    ENDIF
  796.    RETURN NIL
  797.  
  798. /***
  799. *  CopyFile() --> NIL
  800. *
  801. *
  802. */
  803. STATIC FUNCTION CopyFile
  804.    LOCAL cNewName := "", cOldName := "", lKeepGoing := .F., cNewFile := ""
  805.    LOCAL nCurrent := 0, cCurrentFile := "", nCount := 0
  806.    LOCAL cOldScreen := SAVESCREEN( aFileMan[ FM_ROWTOP ] + 3,;
  807.                                    aFileMan[ FM_COLTOP ] + 2,;
  808.                                    aFileMan[ FM_ROWTOP ] + 6,;
  809.                                    aFileMan[ FM_COLTOP ] + 51 )
  810.    
  811.    IF AT( "<dir>", aFileList[ nFileItem ] ) = 0
  812.  
  813.       TONE( 800, 1 )
  814.  
  815.       IF nTagged > 0
  816.          IF YesOrNo( "Copy marked files? (Y/N)", "N" )
  817.             lKeepGoing := .T.
  818.          ENDIF
  819.       ELSE
  820.          @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLTOP ] + 1 SAY;
  821.            CHR( 16 )
  822.          @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLBOTTOM ] - 3 SAY;
  823.            CHR( 17 )
  824.          IF YesOrNo( "Copy this file? (Y/N)", "N" )
  825.             lKeepGoing := .T.
  826.          ENDIF
  827.       ENDIF
  828.  
  829.       ClearMessage()
  830.  
  831.       // Draw the box
  832.       @ aFileMan[ FM_ROWTOP ] + 3, aFileMan[ FM_COLTOP ] + 2, ;
  833.         aFileMan[ FM_ROWTOP ] + 6, aFileMan[ FM_COLTOP ] + 51 BOX;
  834.         FM_DOUBLEFRAME
  835.       @ aFileMan[ FM_ROWTOP ] + 4, aFileMan[ FM_COLTOP ] + 3 CLEAR TO ;
  836.         aFileMan[ FM_ROWTOP ] + 5, aFileMan[ FM_COLTOP ] + 50
  837.  
  838.       cNewName := cOldName := PADR( SUBSTR( aFileMan[ FM_PATH ], 1, ;
  839.                               RAT( "\", aFileMan[ FM_PATH ] ) ) + ;
  840.                               TRIM( SUBSTR( aFileList[ nFileItem ], 1, 12 ) ),;
  841.                               45 )
  842.  
  843.       IF lKeepGoing
  844.  
  845.          IF nTagged > 0
  846.  
  847.             cNewName := PADR( SUBSTR( aFileMan[ FM_PATH ], 1, RAT( "\", ;
  848.                                 aFileMan[ FM_PATH ] ) ), 45 )
  849.             @ aFileMan[ FM_ROWTOP ]+4, aFileMan[ FM_COLTOP ]+4 SAY;
  850.               "Copy marked files to..."
  851.             @ aFileMan[ FM_ROWTOP ]+5, aFileMan[ FM_COLTOP ]+4 GET;
  852.               cNewName PICTURE "@!@S46@K"
  853.             READ
  854.             IF LASTKEY() <> K_ESC
  855.                cNewName := TRIM( cNewName )
  856.                IF RIGHT( cNewName, 1 ) <> "\"
  857.                   cNewName += "\"
  858.                ENDIF
  859.                FOR nCurrent := 1 TO LEN( aFileList )
  860.                   IF SUBSTR( aFileList[ nCurrent ], 14, 1 ) == FM_CHECK
  861.                      cCurrentFile := SUBSTR( aFileMan[ FM_PATH ], 1, ;
  862.                                      RAT( "\", aFileMan[ FM_PATH ])) + ;
  863.                                      TRIM( SUBSTR( aFileList[ nCurrent ], 1, 12))
  864.                      cNewFile := cNewName + ;
  865.                                  TRIM( SUBSTR( aFileList[ nCurrent ], 1, 12))
  866.                      Message( "Copying " + TRIM( cCurrentFile ) )
  867.                      COPY FILE ( cCurrentFile ) TO ( cNewFile )
  868.                      aFileList[ nCurrent ] := STUFF( aFileList[ nCurrent ], ;
  869.                                               14, 1, " " )
  870.                      nTagged--
  871.                      nCount++
  872.                      IF INKEY() = K_ESC
  873.                         EXIT
  874.                      ENDIF
  875.                   ENDIF
  876.                NEXT
  877.                @ aFileMan[ FM_ROWTOP ] + 4, aFileMan[ FM_COLTOP ] + 3 CLEAR TO ;
  878.                  aFileMan[ FM_ROWTOP ] + 5, aFileMan[ FM_COLTOP ] + 50
  879.                @ aFileMan[ FM_ROWTOP ]+4, aFileMan[ FM_COLTOP ]+4 SAY;
  880.                  LTRIM(STR( nCount )) + IF( nCount > 1, " files copied.  ", ;
  881.                                         " file copied.  " ) + "Press any key..."
  882.                INKEY(0)
  883.             ENDIF
  884.          ELSE
  885.             @ aFileMan[ FM_ROWTOP ]+4, aFileMan[ FM_COLTOP ]+4 SAY;
  886.               "Copy current file to..."
  887.             @ aFileMan[ FM_ROWTOP ]+5, aFileMan[ FM_COLTOP ]+4 GET;
  888.               cNewName PICTURE "@!@S46@K"
  889.             READ
  890.             IF LASTKEY() <> K_ESC
  891.                IF RIGHT( cNewName, 1 ) == "\"
  892.                   cNewName += TRIM( SUBSTR( cOldName, RAT( "\", cOldName) ;
  893.                               + 1, 12 ))
  894.                ENDIF
  895.                COPY FILE ( cOldName ) TO ( cNewName )
  896.                @ aFileMan[ FM_ROWTOP ] + 4, aFileMan[ FM_COLTOP ] + 3 CLEAR TO ;
  897.                  aFileMan[ FM_ROWTOP ] + 5, aFileMan[ FM_COLTOP ] + 50
  898.                @ aFileMan[ FM_ROWTOP ]+4, aFileMan[ FM_COLTOP ]+4 SAY;
  899.                  "1 file copied.  Press any key..."
  900.                INKEY(0)
  901.             ENDIF
  902.  
  903.          ENDIF
  904.  
  905.          lReloadDir := .T.
  906.       ENDIF
  907.    ENDIF
  908.  
  909.  
  910.    RESTSCREEN( aFileMan[ FM_ROWTOP ] + 3, ;
  911.                aFileMan[ FM_COLTOP ] + 2, ;
  912.                aFileMan[ FM_ROWTOP ] + 6, ;
  913.                aFileMan[ FM_COLTOP ] + 51,;
  914.                cOldScreen )
  915.  
  916.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLTOP ] + 1 SAY;
  917.      CHR( 32 )
  918.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLBOTTOM ] - 3 SAY;
  919.      CHR( 32 )
  920.  
  921.    RETURN NIL
  922.  
  923. /***
  924. *  RenameFile() --> NIL
  925. *
  926. *
  927. */
  928. STATIC FUNCTION RenameFile
  929.    LOCAL cNewName := "", cOldName := ""
  930.    LOCAL cOldScreen := SAVESCREEN( aFileMan[ FM_ROWTOP ] + 3,;
  931.                                    aFileMan[ FM_COLTOP ] + 2,;
  932.                                    aFileMan[ FM_ROWTOP ] + 6,;
  933.                                    aFileMan[ FM_COLTOP ] + 51 )
  934.  
  935.    IF AT( "<dir>", aFileList[ nFileItem ] ) = 0
  936.  
  937.       // Draw the box
  938.       @ aFileMan[ FM_ROWTOP ] + 3, aFileMan[ FM_COLTOP ] + 2, ;
  939.         aFileMan[ FM_ROWTOP ] + 6, aFileMan[ FM_COLTOP ] + 51 BOX;
  940.         FM_DOUBLEFRAME
  941.       @ aFileMan[ FM_ROWTOP ] + 4, aFileMan[ FM_COLTOP ] + 3 CLEAR TO ;
  942.         aFileMan[ FM_ROWTOP ] + 5, aFileMan[ FM_COLTOP ] + 50
  943.  
  944.       cNewName := cOldName := PADR( SUBSTR( aFileMan[ FM_PATH ], 1, ;
  945.                               RAT( "\", aFileMan[ FM_PATH ] ) ) + ;
  946.                               TRIM( SUBSTR( aFileList[ nFileItem ], 1, 12 ) ),;
  947.                               45 )
  948.  
  949.       TONE( 800, 1 )
  950.  
  951.       @ aFileMan[ FM_ROWTOP ] + 4, aFileMan[ FM_COLTOP ] + 4 SAY "Rename " +;
  952.         SUBSTR( cNewName, 1, 38 )
  953.       @ aFileMan[ FM_ROWTOP ] + 5, aFileMan[ FM_COLTOP ] + 4 SAY "To" GET;
  954.         cNewName PICTURE "@!@S43@K"
  955.       READ
  956.  
  957.       IF LASTKEY() <> K_ESC
  958.          IF FILE( cNewName )
  959.             ErrorBeep()
  960.             @ aFileMan[ FM_ROWTOP ] + 4, aFileMan[ FM_COLTOP ] + 3 CLEAR TO ;
  961.               aFileMan[ FM_ROWTOP ] + 5, aFileMan[ FM_COLTOP ] + 50
  962.             @ aFileMan[ FM_ROWTOP ] + 4, aFileMan[ FM_COLTOP ] + 4 SAY ;
  963.               "ERROR: That file already exists!"
  964.             @ aFileMan[ FM_ROWTOP ] + 5, aFileMan[ FM_COLTOP ] + 4 SAY ;
  965.                "Press any key..."
  966.             INKEY( 0 )
  967.          ELSE
  968.             lReloadDir := .T.
  969.             RENAME ( TRIM( cOldName ) ) TO ( TRIM( cNewName ) )
  970.          ENDIF
  971.       ENDIF
  972.  
  973.    ENDIF
  974.  
  975.    RESTSCREEN( aFileMan[ FM_ROWTOP ] + 3, ;
  976.                aFileMan[ FM_COLTOP ] + 2, ;
  977.                aFileMan[ FM_ROWTOP ] + 6, ;
  978.                aFileMan[ FM_COLTOP ] + 51,;
  979.                cOldScreen )
  980.  
  981.    RETURN NIL
  982.  
  983. /***
  984. *  DeleteFile() --> NIL
  985. *
  986. *
  987. */
  988. STATIC FUNCTION DeleteFile
  989.  
  990.    LOCAL nCurrentFile := 0, cFile := ""
  991.  
  992.    TONE( 800, 1 )
  993.    IF nTagged > 0
  994.       IF YesOrNo( "Delete marked files? (Y/N)", "N" )
  995.          lReloadDir := .T.
  996.          FOR nCurrentFile := 1 TO LEN( aFileList )
  997.             cFile := SUBSTR( aFileMan[ FM_PATH ], 1, ;
  998.                      RAT( "\", aFileMan[ FM_PATH ] ) ) + ;
  999.                      TRIM( SUBSTR( aFileList[ nCurrentFile ], 1, 12 ) )
  1000.             IF SUBSTR( aFileList[ nCurrentFile ], 14, 1 ) == FM_CHECK
  1001.                ERASE ( cFile )
  1002.                Message( "Deleting " + TRIM( cFile ) )
  1003.             ENDIF
  1004.          NEXT
  1005.          Message( LTRIM( STR( nTagged ) ) + " file(s) deleted.  Press any key..." )
  1006.          INKEY( 300 )
  1007.          nTagged := 0
  1008.       ENDIF
  1009.    ELSE
  1010.       IF AT( "<dir>", aFileList[ nFileItem ] ) = 0
  1011.          cFile := SUBSTR( aFileMan[ FM_PATH ], 1, ;
  1012.                   RAT( "\", aFileMan[ FM_PATH ] ) ) + ;
  1013.                   TRIM( SUBSTR( aFileList[ nFileItem ], 1, 12 ) )
  1014.          @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLTOP ] + 1 SAY;
  1015.            CHR( 16 )
  1016.          @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLBOTTOM ] - 3 SAY;
  1017.            CHR( 17 )
  1018.          IF YesOrNo( "Delete this file? (Y/N)", "N" )
  1019.             ERASE ( cFile )
  1020.             lReloadDir := .T.
  1021.          ENDIF
  1022.       ENDIF
  1023.    ENDIF
  1024.  
  1025.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLTOP ] + 1 SAY;
  1026.      CHR( 32 )
  1027.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLBOTTOM ] - 3 SAY;
  1028.      CHR( 32 )
  1029.  
  1030.    Message( aFileMan[ FM_PATH ] )
  1031.  
  1032.    RETURN NIL
  1033.  
  1034. /***
  1035. *  PrintFile() --> NIL
  1036. *
  1037. *
  1038. */
  1039. STATIC FUNCTION PrintFile
  1040.    LOCAL cFile := SUBSTR( aFileMan[ FM_PATH ], 1, ;
  1041.                   RAT( "\", aFileMan[ FM_PATH ] ) ) + ;
  1042.                   TRIM( SUBSTR( aFileList[ nFileItem ], 1, 12 ) )
  1043.  
  1044.    TONE( 800, 1 )
  1045.  
  1046.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLTOP ] + 1 SAY;
  1047.      CHR( 16 )
  1048.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLBOTTOM ] - 3 SAY;
  1049.      CHR( 17 )
  1050.  
  1051.    IF YesOrNo( "Print this file?", "N" )
  1052.  
  1053.       IF ISPRINTER()
  1054.          Message( "Printing " + TRIM( cFile ) )
  1055.          COPY FILE ( cFile ) TO PRN
  1056.          EJECT
  1057.       ELSE
  1058.          ErrorBeep()
  1059.          Message( "ERROR: Printer not responding!" )
  1060.          INKEY( 20 )
  1061.       ENDIF
  1062.  
  1063.    ENDIF
  1064.  
  1065.    ClearMessage()
  1066.  
  1067.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLTOP ] + 1 SAY;
  1068.      CHR( 32 )
  1069.    @ aFileMan[ FM_ROWTOP ] + 3 + nRel, aFileMan[ FM_COLBOTTOM ] - 3 SAY;
  1070.      CHR( 32 )
  1071.  
  1072.    Message( aFileMan[ FM_PATH ] )
  1073.  
  1074.    RETURN NIL
  1075.  
  1076. /***
  1077. *  DBFViewer( <cDatabase> ) --> cDatabase
  1078. *  View the contents of a database file in a window
  1079. *
  1080. */
  1081. STATIC FUNCTION DBFViewer( cDatabase )
  1082.    LOCAL cRecords := ""
  1083.  
  1084.    USE (cDatabase) ALIAS LookFile SHARED NEW READONLY
  1085.  
  1086.    IF !NETERR()
  1087.  
  1088.       @ 0, 0, MAXROW(), MAXCOL() BOX FM_DOUBLEFRAME
  1089.       cRecords := "Number of records: " + LTRIM( STR( RECCOUNT() ) )
  1090.       @ 0, MAXCOL() - 2 SAY "]"
  1091.       @ 0, (MAXCOL()-2)-LEN( cRecords )-3 SAY "[" + SPACE( LEN( cRecords ) + 2 )
  1092.       @ 0, (MAXCOL()-2)-LEN( cRecords )-1 SAY cRecords
  1093.       @ 0, 1 SAY "[ " + TRIM(cDatabase) + " ]"
  1094.       @ MAXROW(),  INT((MAXCOL()-48)/2) SAY ;
  1095.       "[ Use " + CHR(27) + CHR(18) + CHR(26)+" to move through data.  (Esc to Exit) ]"
  1096.  
  1097.       DBEDIT( 1, 1, MAXROW()-1, MAXCOL()-1 )
  1098.  
  1099.       // Close the file and select the old work area
  1100.       USE
  1101.       SELECT ( aFileMan[ FM_OLDSELECT ] )
  1102.  
  1103.    ENDIF
  1104.  
  1105.    RETURN (cDatabase)
  1106.  
  1107. /***
  1108. *  GenericViewer( <cFile> ) --> cFile
  1109. *  View the contents of a text file (?)
  1110. *
  1111. */
  1112. #define GV_BLOCKSIZE    50000
  1113.  
  1114. STATIC FUNCTION GenericViewer( cFile )
  1115.  
  1116.    LOCAL cBuffer := "", nHandle := 0, nBytes := 0
  1117.  
  1118.    cBuffer := SPACE( GV_BLOCKSIZE )
  1119.    nHandle := FOPEN( cFile )
  1120.  
  1121.    IF FERROR() != 0
  1122.       cBuffer := "Error reading file!"
  1123.    ELSE
  1124.       nBytes = FREAD( nHandle, @cBuffer, GV_BLOCKSIZE )
  1125.    ENDIF
  1126.    FCLOSE( nHandle )
  1127.  
  1128.    cBuffer := RTRIM( cBuffer )
  1129.  
  1130.    @ 0, 0 CLEAR TO MAXROW(), MAXCOL()
  1131.    @ 0, 0, MAXROW(), MAXCOL() BOX FM_DOUBLEFRAME
  1132.    @ 0, 1 SAY "[ " + TRIM(cFile) + " ]"
  1133.    @ MAXROW(),  INT((MAXCOL()-48)/2) SAY ;
  1134.    "[ Use "+CHR(27)+CHR(18)+CHR(26)+" to move through data.  (Esc to Exit) ]"
  1135.    MEMOEDIT( cBuffer, 1, 2, MAXROW() - 1, MAXCOL() - 1, .F., "MemoUDF" , 300 )
  1136.  
  1137.    RETURN( cFile )
  1138.  
  1139. #undef GV_BLOCKSIZE
  1140.  
  1141. /***
  1142. *  MemoUDF( <nMode>, <nLine>, <nColumn> ) --> 
  1143. *  
  1144. *
  1145. */
  1146. FUNCTION MemoUDF( nMode, nLine, nColumn )
  1147.    RETURN( ME_DEFAULT )
  1148.  
  1149. /***
  1150. *  TagAllFiles() --> NIL
  1151. *  Tag all files in the current directory
  1152. *
  1153. */
  1154. STATIC FUNCTION TagAllFiles
  1155.    
  1156.    LOCAL nCurrent
  1157.    nTagged := 0
  1158.    
  1159.    FOR nCurrent := 1 TO LEN( aFileList )
  1160.       IF AT( "D", SUBSTR( aFileList[ nCurrent ], 43, 6 ) ) == 0
  1161.          aFileList[ nCurrent ] := STUFF( aFileList[ nCurrent ], ;
  1162.                                          14, 1, FM_CHECK )
  1163.          nTagged++
  1164.       ENDIF
  1165.    NEXT
  1166.    
  1167.    RETURN NIL
  1168.  
  1169. /***
  1170. *  UnTagAllFiles() --> NIL
  1171. *  Untag all tagged files in the current directory
  1172. *
  1173. */
  1174. STATIC FUNCTION UnTagAllFiles
  1175.  
  1176.    LOCAL nCurrent
  1177.    nTagged := 0
  1178.  
  1179.    FOR nCurrent := 1 TO LEN( aFileList )
  1180.       aFileList[ nCurrent ] := STUFF( aFileList[ nCurrent ], 14, 1, " " )
  1181.    NEXT
  1182.  
  1183.    RETURN NIL
  1184.  
  1185.