2000-12-18 16:55 GMT+1 Maurilio Longo <maurilio.longo@libero.it>

* source/rtl/memoedit.prg
     + Added all missing functionalities. Should be 100% compatible (tested very little)
   * source/rtl/teditor.prg
     * little changes to make it work better with memoedit.prg. Removed cUdF parameter from
       ::New() method.
This commit is contained in:
Maurilio Longo
2000-12-18 15:56:01 +00:00
parent eee08cdcb5
commit c18a43c8aa
4 changed files with 212 additions and 12 deletions

View File

@@ -1,3 +1,10 @@
2000-12-18 16:55 GMT+1 Maurilio Longo <maurilio.longo@libero.it>
* source/rtl/memoedit.prg
+ Added all missing functionalities. Should be 100% compatible (tested very little)
* source/rtl/teditor.prg
* little changes to make it work better with memoedit.prg. Removed cUdF parameter from
::New() method.
2000-12-15 22:10 GMT -3 Luiz Rafael Culik <culik@sl.conex.net>
*utils/hbmake/radios.prg
utils/hbmake/checks.prg

View File

@@ -313,9 +313,8 @@ METHOD BrowseTable(lCanEdit, aExitKeys) CLASS TBrowseSQL
while lKeepGoing
if !::Stable
::ForceStable()
endif
while !::Stabilize() .and. NextKey() == 0
enddo
nKey := Inkey(0)

View File

@@ -33,12 +33,191 @@
*
*/
/* TODO: MemoEdit() is not compatible with clipper one.
Needs a lot more work to become */
#include "common.ch"
#include "hbclass.ch"
#include "memoedit.ch"
#include "inkey.ch"
// A specialized TEditor which can simulate MemoEdit() behaviour
CLASS TMemoEditor FROM TEditor
DATA xUserFunction // User Function called to change default MemoEdit() behaviour
METHOD MemoInit(cUserFunction) // This method is called after ::New() returns to perform ME_INIT actions
METHOD Edit() // Calls super:Edit(nKey) but is needed to handle configurable keys
METHOD KeyboardHook(nKey) // Gets called every time there is a key not handled directly by TEditor
METHOD IdleHook() // Gets called every time there are no more keys to hanlde just before TEditor blocks itself waiting for a char
ENDCLASS
METHOD MemoInit(cUserFunction) CLASS TMemoEditor
local nKey
default cUserFunction to nil
// Save/Init object internal representation of user function
::xUserFunction := cUserFunction
if ::xUserFunction <> nil
// Keep calling user function until it returns 0
while (nKey := Do(::xUserFunction, ME_INIT, ::nRow, ::nCol - 1)) <> ME_DEFAULT
do case
case nKey >= 1 .AND. nKey <= 31
super:Edit(nKey)
case nKey == ME_DATA
super:Edit(nKey)
case nKey == ME_TOGGLEWRAP
::lWordWrap := !::lWordWrap
case nKey == ME_TOGGLESCROLL
// Don't know what to do ;-)
case nKey == ME_WORDRIGHT
::MoveCursor(K_CTRL_RIGHT)
case nKey == ME_BOTTOMRIGHT
::MoveCursor(K_CTRL_END)
otherwise
endcase
enddo
endif
return Self
METHOD Edit() CLASS TMemoEditor
local nKey, nUserKey
local lKeepGoing := .T.
// NOTE: K_ALT_W is not compatible with clipper exit memo and save key, but I cannot discriminate
// K_CTRL_W and K_CTRL_END from harbour code.
local aConfigurableKeys := {K_CTRL_Y, K_CTRL_T, K_CTRL_B, K_CTRL_V, K_ALT_W, K_ESC }
// If I have an user function I need to trap configurable keys and ask to
// user function if handle them the standard way or not
if ::lEditAllow .AND. ::xUserFunction <> nil
while lKeepGoing
// I need to test this condition here since I never block inside TEditor:Edit()
// if there is an user function
if NextKey() == 0
::IdleHook()
endif
nKey := Inkey(0)
// Is it a configurable key ?
if AScan(aConfigurableKeys, nKey) > 0
nUserKey := Do(::xUserFunction, iif(::lDirty, ME_UNKEYX, ME_UNKEY), ::nRow, ::nCol - 1)
do case
case nUserKey == ME_DEFAULT
super:Edit(nKey)
if nKey == K_ESC .OR. ::lSaved
lKeepGoing := .F.
endif
case nUserKey >= 1 .AND. nUserKey <= 31
super:Edit(nUserKey)
case nUserKey == ME_DATA
super:Edit(nKey)
case nUserKey == ME_TOGGLEWRAP
::lWordWrap := !::lWordWrap
case nUserKey == ME_TOGGLESCROLL
// Don't know what to do ;-)
case nUserKey == ME_WORDRIGHT
::MoveCursor(K_CTRL_RIGHT)
case nUserKey == ME_BOTTOMRIGHT
::MoveCursor(K_CTRL_END)
otherwise
endcase
else
super:Edit(nKey)
endif
enddo
else
// If I can't edit text buffer or there is not a user function enter standard TEditor
// ::Edit() method which is able to handle everything
super:Edit()
endif
return Self
// I come here if I have an unknown key and it is not a configurable key
// if there is an user function I leave to it its handling
METHOD KeyboardHook(nKey) CLASS TMemoEditor
local nUserKey
if ::xUserFunction <> nil
nUserKey := Do(::xUserFunction, iif(::lDirty, ME_UNKEYX, ME_UNKEY), ::nRow, ::nCol - 1)
do case
case nUserKey >= 1 .AND. nUserKey <= 31
super:Edit(nUserKey)
case nUserKey == ME_DATA
//super:Edit(nKey)
case nUserKey == ME_TOGGLEWRAP
::lWordWrap := !::lWordWrap
case nUserKey == ME_TOGGLESCROLL
// Don't know what to do ;-)
case nUserKey == ME_WORDRIGHT
::MoveCursor(K_CTRL_RIGHT)
case nUserKey == ME_BOTTOMRIGHT
::MoveCursor(K_CTRL_END)
otherwise
endcase
endif
return Self
METHOD IdleHook() CLASS TMemoEditor
if ::xUserFunction <> nil
Do(::xUserFunction, ME_IDLE, ::nRow, ::nCol - 1)
endif
return Self
/*----------------------------------------------------------------------------------------*/
FUNCTION MemoEdit(cString,;
nTop, nLeft,;
nBottom, nRight,;
@@ -64,9 +243,12 @@ FUNCTION MemoEdit(cString,;
DEFAULT nTextBuffColumn TO 0
DEFAULT nWindowRow TO 0
DEFAULT nWindowColumn TO nTextBuffColumn
DEFAULT cUserFunction TO nil
DEFAULT cString TO ""
// Original MemoEdit() converts Tabs into spaces
oEd := TEditor():New(StrTran(cString, Chr(K_TAB), Space(1)), nTop, nLeft, nBottom, nRight, lEditMode, nil, nLineLength, nTabSize)
oEd := TMemoEditor():New(StrTran(cString, Chr(K_TAB), Space(1)), nTop, nLeft, nBottom, nRight, lEditMode, nLineLength, nTabSize)
oEd:MemoInit(cUserFunction)
oEd:RefreshWindow()
if ! ISLOGICAL(cUserFunction) .OR. cUserFunction == .T.
@@ -79,5 +261,5 @@ FUNCTION MemoEdit(cString,;
endif
endif
RETURN cString
RETURN cString

View File

@@ -74,13 +74,13 @@ CLASS TEditor
DATA lSaved INIT .F. // True if user exited editor with K_CTRL_W
DATA lWordWrap INIT .F. // True if word wrapping is active
DATA nWordWrapCol INIT 0 // At which column word wrapping occurs
DATA lDirty // .T. if there are changes not saved
DATA cColorSpec INIT SetColor() // Color string used for screen writes
METHOD New(cString, nTop, nLeft, nBottom,; // Converts a string to an array of strings splitting input string at EOL boundaries
nRight, lEditMode, cUdF, nLineLength,;
nTabSize)
nRight, lEditMode, nLineLength, nTabSize)
METHOD LoadFile(cFileName) // Load cFileName into active editor
METHOD LoadText(cString) // Load cString into active editor
@@ -227,7 +227,7 @@ METHOD GetText() CLASS TEditor
return cString
METHOD New(cString, nTop, nLeft, nBottom, nRight, lEditMode, cUdF, nLineLength, nTabSize) CLASS TEditor
METHOD New(cString, nTop, nLeft, nBottom, nRight, lEditMode, nLineLength, nTabSize) CLASS TEditor
default cString to ""
default nTop to 0
@@ -235,7 +235,6 @@ METHOD New(cString, nTop, nLeft, nBottom, nRight, lEditMode, cUdF, nLineLength,
default nBottom to MaxRow()
default nRight to MaxCol()
default lEditMode to .T.
default cUdF to nil
default nLineLength to nil
default nTabSize to nil
@@ -266,6 +265,9 @@ METHOD New(cString, nTop, nLeft, nBottom, nRight, lEditMode, cUdF, nLineLength,
::InsertState(::lInsert)
endif
// No need to save
::lDirty := .F.
// is word wrap required?
if nLineLength != NIL
::lWordWrap := .T.
@@ -336,6 +338,7 @@ METHOD LoadFile(cFileName) CLASS TEditor
::naTextLen++
endif
::lDirty := .F.
::MoveCursor(K_CTRL_PGUP)
return Self
@@ -351,6 +354,7 @@ METHOD LoadText(cString) CLASS TEditor
::naTextLen++
endif
::lDirty := .F.
::MoveCursor(K_CTRL_PGUP)
return Self
@@ -363,7 +367,9 @@ METHOD SaveFile() CLASS TEditor
if !Empty(::cFile)
cString := ::GetText()
return MemoWrit(::cFile, cString)
::lDirty := !MemoWrit(::cFile, cString)
return !::lDirty
endif
return .F.
@@ -817,6 +823,7 @@ METHOD Edit(nPassedKey) CLASS TEditor
do case
case nKey >= K_SPACE .AND. nKey < 256
::lDirty := .T.
// If I'm past EOL I need to add as much spaces as I need to reach ::nCol
if ::nCol > ::LineLen(::nRow)
::aText[::nRow]:cText += Space(::nCol - ::LineLen(::nRow))
@@ -832,6 +839,7 @@ METHOD Edit(nPassedKey) CLASS TEditor
::SplitLine(::nRow)
case nKey == K_RETURN
::lDirty := .T.
if ::lInsert .OR. ::nRow == ::naTextLen
if ::LineLen(::nRow) > 0
// Split current line at cursor position
@@ -851,6 +859,7 @@ METHOD Edit(nPassedKey) CLASS TEditor
::InsertState(!::lInsert)
case nKey == K_DEL
::lDirty := .T.
// If I'm on last char of a line and there are more lines, append next line to current one
lDelAppend := ::nCol > ::LineLen(::nRow)
::aText[::nRow]:cText := Stuff(::aText[::nRow]:cText, ::nCol, 1, "")
@@ -870,6 +879,7 @@ METHOD Edit(nPassedKey) CLASS TEditor
// insert char if in insert mode or at end of current line
if ::lInsert .OR. (::nCol == ::LineLen(::nRow))
::aText[::nRow]:cText := Stuff(::aText[::nRow]:cText, ::nCol, 0, Space(::nTabWidth))
::lDirty := .T.
endif
for i := 1 to ::nTabWidth
::MoveCursor(K_RIGHT)
@@ -877,6 +887,7 @@ METHOD Edit(nPassedKey) CLASS TEditor
::RefreshLine()
case nKey == K_BS
::lDirty := .T.
// delete previous character
::aText[::nRow]:cText := Stuff(::aText[::nRow]:cText, --::nCol, 1, "")
// correct column position for next call to MoveCursor()
@@ -885,6 +896,7 @@ METHOD Edit(nPassedKey) CLASS TEditor
::RefreshLine()
case nKey == K_CTRL_Y
::lDirty := .T.
if ::naTextLen > 1
::RemoveLine(::nRow)
// if we have less lines of text than our current position, up one line