// The example shows an extensive MemoEdit() routine using a
// user function. From the user function a search routine
// can be started with Alt+S. In the UDF MemoSeek(), a search
// expression is input by the user. When the expression
// is found, the cursor is positioned in the MemoEdit() text buffer
// on the first character in the search expression. Note the
// STATIC file-wide variables.
#include "Inkey.ch"
#include "Setcurs.ch"
#include "Memoedit.ch"
STATIC snWinRow , snWinCol, snBuffRow, snBuffCol
STATIC snTop , snLeft , snBottom , snRight
STATIC slExit := .F.
STATIC snTabsize := 3
STATIC snLineLen := 128
**************
PROCEDURE Main
? FileEdit( "TEST.PRG", 2, 2, 22, 76 )
Inkey(0)
RETURN
*****************
FUNCTION FileEdit( cFilename, nTop, nLeft, nBottom, nRight )
LOCAL lUpdated := .F.
LOCAL cString := MemoRead( cFilename )
LOCAL cScreen := SaveScreen( nTop, nLeft, nBottom, nRight )
snTop := nTop + 1 // initialize
snLeft := nLeft + 1 // static variables
snBottom := nBottom - 1
snRight := nRight - 1
snWinRow := 0
snWinCol := 0
snBuffRow := 1
snBuffCol := 0
slExit := .F.
SET SCOREBOARD OFF
DO WHILE .NOT. slExit
// display box with title
DispBox( nTop, nLeft, nBottom, nRight, 2 )
@ nTop, nLeft+1 SAY ;
PadC(cFileName, nRight-nLeft-1, Chr(205) )
// edit text
cString := MemoEdit( cString , ;
snTop , ;
snLeft , ;
snBottom , ;
snRight , ;
.T. , ;
"UserFunc" , ;
snLineLen , ;
snTabSize , ;
snBuffRow , ;
snBuffCol , ;
snWinRow , ;
snWinCol )
IF ! slExit
MemoSeek( cString ) // call search function
ENDIF
ENDDO
SET SCOREBOARD ON
RestScreen( nTop, nLeft, nBottom, nRight, cScreen )
RETURN MemoWrit( cFilename, cString )
******************
PROCEDURE MemoSeek( cString )
LOCAL cSeek := Space( 40 ), nPos, aPos, nFound
// Get search expression
@ snBottom+1, snLeft SAY "Search:" GET cSeek
READ
cSeek := Upper( Trim( cSeek ) )
IF ! Empty( cSeek )
// find current position in the text buffer
nPos := MlCtoPos( cString , ;
snLineLen, ;
snBuffRow, ;
snBuffCol, ;
snTabSize )
// search forward only for expression
nFound := At( cSeek, SubStr( Upper( cString ), nPos+1 ) )
IF nFound > 0
nPos += nFound
// find corresponding row and column
// in the text buffer
aPos := MPostoLc( cString , ;
snLineLen, ;
nPos , ;
snTabSize )
// new position in the window of MemoEdit()
snWinRow += ( aPos[1] - snBuffRow )
snWinCol += ( aPos[2] - snBuffCol )
// new position in the text buffer for MemoEdit()
snBuffRow := aPos[1]
snBuffCol := aPos[2]
ELSE
@ snBottom+1, snLeft SAY ;
PadR("Not found!",snRight-snLeft-1, Chr(205) )
Inkey(0)
ENDIF
ENDIF
RETURN
******************
FUNCTION UserFunc( nMode, nRow, nCol )
LOCAL nKey := LastKey()
LOCAL nReturn := ME_DEFAULT // default return value
snBuffRow := nRow
snBuffCol := nCol
snWinRow := Row() - snTop
snWinCol := Col() - snTop
DO CASE
CASE nMode == ME_IDLE // display position in
nRow := Row() // the text buffer
nCol := Col()
SetPos( snBottom+1, snLeft )
?? "Row:" , Str(snBuffRow,4)
?? " Column:", Str(snBuffCol,2)
SetPos( nRow, nCol )
CASE nMode == ME_UNKEY .OR. nMode == ME_UNKEYX
DO CASE
CASE nKey == K_F7 // next word with F7
nReturn:= ME_WORDRIGHT
CASE nKey == K_F8 // last character in the
nReturn:= ME_BOTTOMRIGHT // window with F8
CASE nKey == K_F9 // switch word wrap
nReturn:= ME_TOGGLEWRAP // with F9
CASE nKey == K_F10 // switch scroll
nReturn:= ME_TOGGLESCROLL // with F10
CASE nKey == K_CTRL_RET .OR. ; // save on Ctrl-Return
nKey == K_CTRL_W
slExit := .T.
nReturn:= K_CTRL_W
CASE nKey == K_ESC
slExit := .T.
CASE nKey == K_ALT_S // terminate and search
nReturn:= K_CTRL_W
CASE nKey == K_INS // set cursor based on
IF SetCursor() == SC_SPECIAL1 // insertion mode
SetCursor( SC_NORMAL )
ELSE
SetCursor( SC_SPECIAL1 )
ENDIF
ENDCASE
OTHERWISE // on initialization
nReturn := IIf( ReadInsert(), 0, K_INS )
// switch to insertion
SetCursor( SC_SPECIAL1 ) // mode by default
ENDCASE
RETURN nReturn