Function DbEdit() Foundation

Browses records in a work area.

Syntax
DbEdit( [<nTop>]      , ;
        [<nLeft>]     , ;
        [<nBottom>]   , ;
        [<nRight>]    , ;
        [<aColumns>]  , ;
        [<bcUserFunc>], ;
        [<acPicture>] , ;
        [<acHeading>] , ;
        [<acHeadSep>] , ;
        [<acColSep>]  , ;
        [<acFootSep>] , ;
        [<acFooting>]   ) --> NIL
Parameters
<nTop>
<nTop> is a integer numeric value specifying the upper screen row where DbEdit() displays the browse window. The four arguments <nTop>, <nLeft>, <nBottom> and <nRight> determine the screen coordinates for the browse window. Row positions for the window can range from zero to MaxRow() and column positions can range from zero to MaxCol()
<nLeft>
<nLeft> is a integer numeric value specifying the left screen column of the browse window display. The default value is zero.
<nBottom>
<nBottom> is a integer numeric value specifying the bottom screen row of the browse window display. The default value is MaxRow().
<nRight>
<nRight> is a integer numeric value specifying the right screen column of the browse window display. The default value is MaxCol().
<aColumns>
<aColumns> is an array whose elements may contain only character strings. The character strings contain field names or expressions which can be macro expanded to determine the value displayed in each column. DbEdit() displays a column on screen for each element in <aColumns>. If <aColumns> is missing, all fields of the work area are displayed.
<bcUserFunc>
<bcUserFunc> can optionally specify a code block or a character string containing the name of a user-defined function. When <bcUserFunc> contains a code block, it is executed after each keypress not processed by DbEdit(). Similarly, if a name of a user function (without parentheses) is passed as a character string, the function is called after each keypress not processed by DBEdit(). If a function name is specified, the function cannot be declared STATIC. However, within a code block, a STATIC FUNCTION can be called as a user function.
<acPicture>
<acPicture> contains either a parallel array with PICTURE formats for formatting values in each individual column or a character string containing a PICTURE format for all columns.
<acHeading>
<acHeading> contains either a parallel array of character strings specifying the column headings for each individual column or a character string to be used as the heading for all columns. Multiple row column headings are created when a character string contains a semicolon. Where the semicolon appears, the column heading is wrapped. When <acHeading> is not included, the column headings are created from the elements of <aColumns>. If <aColumns> is also missing, the field names in the work area are displayed as column headings.
<acHeadSep>
<acHeadSep> contains either a parallel array of heading separators to appear between the heading and data area for each individual column, or a character expression which defines the heading separator for all columns. Chr(205) is used as the default character and displays a double line.
<acColSep>
<acColSep> contains either a parallel array of characters used to create a separator between each column or a character expression defining the heading separator for all columns. Chr(179) is used as the default character displays a single line.
<acFootSep>
<acFootSep> contains either a parallel array of footing separators to appear between the data area and footer line for each individual column or a character expression defining the footer separator for all columns. If <acFootSep> is missing, no footing separators are displayed.
<acFooting>
<acFooting> contains either a parallel array of character strings specifying the footer lines for each individual column or a character string specifying the footer line for all columns. Multiple footer lines are created when a character string contains a semicolon. Where this semicolon appears, the footer line is wrapped. When <acFooting> is not included, no footer lines are displayed.
Return

The return value of DbEdit() is always NIL.

Description

The function DbEdit() is purely a compatibility function which makes a database file browser available. The capabilities of a TBrowse object should be used instead of DbEdit() (see function TBrowseNew() or TBrowseDb()).

The dialog function DbEdit() displays the contents of fields from one or more work areas in columns. The columns are defined by the elements of the array<aColumns>. The appearance of the field contents can be modified by including PICTURE formatting in the array <acPicture>. The data is displayed within a window. When a work area has more records than the window has rows, the window contents are scrolled as soon as the user moves to a record outside the window using the arrow keys.

The color of records is determined by the system colors set with SetColor(). All data is displayed in the default color (first color value), except the current field (the current cell) which is displayed in the "highlight" color (second color value).

Cursor navigation within DbEdit() occurs using the following keys:

DbEdit() Navigation keys
Key Inkey constant Action
Up Arrow K_UP Previous record
Down Arrow K_DOWN Next record
Left Arrow K_LEFT One column to the left
Right Arrow K_RIGHT One column to the right
Home K_HOME Left column in the window
End K_END Right column in the window
Page Up K_PGUP Previous screen
Page Down K_PGDN Next screen
Ctrl+Left Arrow K_CTRL_LEFT Scroll columns to the left
Ctrl+Right Arrow K_CTRL_RIGHT Scroll columns to the right
Ctrl+Home K_CTRL_HOME First column
Ctrl+End K_CTRL_END Last column
Ctrl+Page Up K_CTRL_PGUP First record
Ctrl+Page Down K_CTRL_PGDN Last record
Return *) K_RETURN Terminate DbEdit()
Esc *) K_ESC Terminate DbEdit()
  1. Not active when a user function is specified

If the function SetMouse(.T.) was called before DbEdit(), the cursor can be positioned within the browse window by a click of the left mouse button. If DbEdit() is used with Xbase Parts in hybrid mode, events for an Xbase Part are automatically sent to the applicable Xbase Part and not processed by DbEdit().

The argument <bcUserFunc> modifies the functionality of DbEdit(). <bcUserFunc> contains either a character string with the name of a function or a code block.

When <bcUserFunc> contains a function name, the corresponding function cannot be declared STATIC and must be specified as a character string without () parentheses.

When <bcUserFunc> contains a code block, it must contain the function call of a user function. If called within a code block, a user function declared as STATIC can be used.

The user function allows DbEdit() behavior to be modified to be user specific. When a value for <bcUserFunc> is passed to DbEdit(), DbEdit() calls the user function (or evaluates the code block) every time a key is pressed that DbEdit() does not automatically process. DbEdit() automatically processes all keys from the above table until Return or Esc are processed. Unknown keys can be processed in the user function and the RETURN value of the user function informs DbEdit() how to react to the key.

When it calls the user function, DbEdit() passes two numeric values to the function or code block: the current DbEdit() mode and the number of the current column where the cursor or highlight is currently located. The column number corresponds to the element in the array <aColumns>.

The mode designates the present mode of DbEdit() and depends on the last pressed key or the last action DbEdit() executed before calling the user function. In the header file "Dbedit.ch" symbolic constants are defined which identify the various modes of DbEdit():

Modes of DbEdit() (see Dbedit.ch)
Constant Description
DE_IDLE Idle, all keys processed
DE_HITTOP Bof() was reached
DE_HITBOTTOM Eof() was reached
DE_EMPTY No records available
DE_EXCEPT Unknown key

The mode DE_IDLE means that no more keys are waiting to be processed and DbEdit() is waiting for a new keypress. Each time DbEdit() does not find another value in the keyboard buffer, the user function is called once and then DbEdit() waits for a new keypress.

DbEdit() uses the modes DE_HITTOP and DE_HITBOTTOM to signal that the user has attempted to position the highlight before the first or beyond the last record.

The mode DE_EXCEPT indicates that an unknown key code or an unknown event is waiting to be processed. The action DbEdit() should execute after an unknown keypress or event is defined by the return value of the user function. Returning DE_CONT causes DbEdit() to execute its default action. If a value not equal to DE_CONT is returned, DbEdit() executes a different action. Symbolic constants are defined in the header file "Dbedit.ch" for the possible return values of the user function. These identify the various DbEdit() actions which can be requested by the user function:

Return values of the DbEdit() user function (see Dbedit.ch)
Dbedit.ch Action
DE_ABORT Terminates DbEdit()
DE_CONT Continues DbEdit()
DE_REFRESH Rereads data and rebuilds screen

The value DE_REFRESH can be returned to DbEdit() only when the mode is DE_EXCEPT. Otherwise it may cause an infinite loop.

the source code for DbEdit() is in DBEDIT.PRG which is located in the directory ..\SOURCE\SYS.

Examples
DbEdit()
// The example shows a simple call to DbEdit() which 
// also saves and restores the screen. 

PROCEDURE Main 
   LOCAL  cScreen := SaveScreen( 2, 2, 22, 77) 

   USE Customer NEW 
   DbEdit( 2, 2, 22, 77) 
   RestScreen( 2, 2, 22, 77, cScreen ) 

   CLOSE Customer 
RETURN 

DbEdit() with a user function

// In the example, a simple database file editor is illustrated 
// using DbEdit() and a user function. Fields are displayed 
// and can be edited. For memo fields a character constant is 
// displayed when text is contained in the memo field. Normal 
// fields are edited with GET, memo fields with MemoEdit(). The 
// user function displays various additional status messages. 

#include "Dbedit.ch" 
#include "Inkey.ch" 

STATIC saColumns := {} 
STATIC snTop, snLeft, snBottom, snRight 

PROCEDURE Main 
   USE Address ALIAS Address 
   Address-> ( DbfEditor() )        // edit database file 
RETURN 

PROCEDURE DbfEditor()               // general DBF editor 
   LOCAL cScreen, n, nCount, aHeading, cPos 

   SetMouse(.T.)                    // turn on mouse navigation 
   nCount    := FCount() 
   saColumns := Array( nCount )     // columns 
   aHeading  := Array( nCount )     // headings 

   snTop     := 2 
   snLeft    := 2 
   snBottom  := 22 
   snRight   := 77 
                                     // create array for columns 
   FOR n:=1 TO nCount                // and column headings 
      IF Type( FieldName(n) ) == "M" 
         cPos   := LTrim(Str(n))     // column output for 
         saColumns[n] := ;           // memo fields 
         "IIf(Empty(FieldGet("+cPos+")),Space(11),'<Memofield>')" 
      ELSE 
         saColumns[n] := FieldName(n) 
      ENDIF 

      aHeading[n] := Left(FieldName(n),1) + ; 
                     SubStr( Lower( FieldName(n) ), 2 ) 
   NEXT 
                                     // save screen 
   cScreen := SaveScreen(snTop-1, snLeft-1, snBottom+1, snRight+1) 
                                     // display box 
   DispBox( snTop-1, snLeft-1, snBottom+1, snRight+1 ) 

                                     // display/edit 
   DbEdit( snTop  , snLeft, snBottom, snRight, ; 
           saColumns, "DBUSERFUNC", , aHeading ) 

                                     // restore screen 
   RestScreen(snTop-1, snLeft-1, snBottom+1, snRight+1, cScreen) 

RETURN 

FUNCTION DbUserFunc(nMode, nColPos)  // user function 
  STATIC slAppend:= .F. 
   LOCAL nKey    := LastKey() 
   LOCAL nReturn := DE_CONT          // default return value 

   DO CASE 
   CASE nMode == DE_IDLE .OR. ;      // status message below 
        nKey  == 255                 // message must be refreshed 
                                     // after K_DEL 
      @ snTop-1, snLeft+1 SAY PadR("", 20, Chr(196) ) 
      @ snBottom+1, snLeft+1 SAY ; 
        PadR("Record: "+ LTrim(Str(RecNo())) + ; 
             IIf( Deleted()," <deleted>","") , 30, Chr(196) ) 

   CASE nMode == DE_HITTOP           // status message above 
      Tone( 1000, 2 ) 
      @ snTop-1, snLeft+1 SAY ; 
        PadR("<Begin of File>", 20, Chr(196) ) 

   CASE nMode == DE_HITBOTTOM        // status message above 
      IF nKey == K_DOWN .AND. ! slAppend 
         Tone( 1500 ) 
         slAppend := .T. 
         DbAppend()                  // new record 
         @ snTop-1, snLeft+1 SAY ; 
           PadR("<New record>", 20, Chr(196) ) 
         KEYBOARD Chr(K_RETURN)      // switch to edit mode 
      ELSE 
         Tone( 500, 2 ) 
         @ snTop-1, snLeft+1 SAY ; 
           PadR("<End of File>", 20, Chr(196) ) 
      ENDIF 

   CASE nMode == DE_EMPTY 
      @ snTop-1, snLeft+1 SAY ; 
        PadR("<File is empty>", 20, Chr(196) ) 

   CASE nMode == DE_EXCEPT 
      DO CASE 
      CASE nKey == K_DEL              // (un)delete record 
         IF Deleted() 
            DbRecall() 
         ELSE 
            DbDelete() 
         ENDIF 
         KEYBOARD Chr(255)            // refresh status line 

      CASE nKey == K_ESC              // terminate 
         nReturn := DE_ABORT 

      CASE nKey == K_RETURN           // edit 
         SetCursor(1) 
         IF Type( FieldName(nColPos) ) == "M" 
            EditMemo( nColPos )       // edit memo field 
         ELSE 
            EditField( saColumns[nColPos] ) 
         ENDIF 
         SetCursor(0) 
         slAppend:=.F. 
         nReturn := DE_REFRESH 

      ENDCASE 
   ENDCASE 

RETURN nReturn 

PROCEDURE EditField( cFieldName ) 
   @ Row(), Col() GET &cFieldName 
   READ 
RETURN 

PROCEDURE EditMemo( nFieldPos ) 
   LOCAL cScreen := SaveScreen() 
   LOCAL cText   := FieldGet( nFieldPos ) 
   DispBox( snTop+2, snLeft+2, snBottom-2, snRight-2 ) 

   FieldPut( nFieldPos, ; 
             MemoEdit( FieldGet( nFieldPos ), ; 
                       snTop+3, snLeft+3, snBottom-3, snRight-3 ; 
           )         ) 
   RestScreen(,,,,cScreen) 
RETURN 

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.