Showing posts with label Foxtools. Show all posts
Showing posts with label Foxtools. Show all posts

Fox-Editor Functions: An Overview

Version: 01.50.00 - last Update: Tuesday, October 13, 2009, 12:30:00

Visual FoxPro – Foxtools.fll Vers 9.00 (Home)Visual FoxPro – Foxtools.fll Vers 9.00 (Home)NavForward_48_RGBA OffSiteLinkExamples | Good2Know | Tips&Tricks


Intro

VFP Editor API Foxtools editor-related functions let us access VFP’s underlying Editor-API. Calls into VFP’s API are implemented in FLL libraries which are created with the help of FoxPro’s Library Construction Kit and a C/C++ compiler. For those who are not that familiar with C/C++ (like me) using the Foxtools editor functions is a handy way to access VFP’s Editor-API directly without having to write C/C++ code.

The only drawback in using a prefabricated set of FLL-based functions is that there is no way to fix bugs without having the sources. Thus, it is essential for a successful application of Foxtools’ editor functions to be aware of all bugs, even lurking oddities! Because this documentation demands to be a complete one, it cannot be sufficient to show how to properly use each function. There should be realistic examples and additional information as well.

Function Sub-Grouping

All 31 editor-related Foxtools functions can be sub-grouped into following categories:

  • Display
  • Content
  • Clipboard
  • Queries
  • Undo
  • Environment
  • Error

Display

_EdActive | _EdSetPos | _EdSToPos | _EdSToSel

Display-related editor functions do not alter the editor’s content. They can show, hide and move the caret or scroll the textual content up and down in the edit area.

Content

_EdOpenFil | _EdCloseFi | _EdRevert | _EdSelect | _EdIndent | _EdInsert | _EdSendKey | _EdDelete | _EdComment

Content-related editor functions do alter the editor’s content, obviously. They let us open and close files, insert and delete text and save and revert our changes.

Clipboard

_EdCopy | _EdCut | _EdPaste

Clipboard-related editor functions enable us to retrieve content from (and store it to) the Windows clipboard.

Queries

_EdGetChar | _EdGetLNum | _EdGetLPos | _EdGetPos | _EdGetStr | _EdPosInVi | _EdSkipLin

Some of the queries retrieve caret-related information, other return a character or strings or calculate offsets. All those function have one thing in common: they always calculate their offsets from the beginning of the editor’s text buffer and use zero-based counting.

Undo

_EdUndo | _EdRedo | _EdUndoOn

Undo-related commands let us group editor actions to undo/redo blocks. Apart from that, they map to the well known CTRL+Z & CTRL+Y shortcuts, that most of the Windows applications support.

Environment

_EdGetEnv | _EdSetEnv | _EdProcList | _EdProperties

Environment-related functions can be separated into those with a GUI and those without. _EDGetEnv and _EdSetEnv() are working with an internal array (without a GUI). _EdProcList() and _EdProperties() are used to launch the appropriate dialog forms.

Error

_EdLastErr

_EdLastErr() is the only error-related Foxtools function. In point of fact, errors that may be introduced by using invalid handles or pointers/offsets, can be trapped using TRY CATCH ENDTRY or any other VFP error handling because the Foxtools editor functions are “translating” editor-API errors into native VFP errors.

Common Terms

In this chapter I will explain some expressions used all over when talking about Foxtools’ editor functions.

Editor (Text-)Buffer

Opening a new editor instance using _EdOpenFil() for example, or by typing a MODIFY COMMAND ? into VFP’s Command window lets us select a file from our disk. The content of the file is then loaded into the editor session’s (text-)buffer. Each line of the file (on the disk) ends at least with an Carriage Return (CR := CHR(13)) but can also has an additional Line Feed (LF := CHR(10)). This depends on the Edit Properties setting shown below. BTW this setting can also be read/written using _EdGetEnv() and _EdSetEnv() – aEnv[7] holds the corresponding flag value.

Enabling Line Feeds

During file load FoxPro strips off any additional Line Feeds so that all lines in the editor’s buffer only have a CR at their end. This is exactly what you will see when turning on display white spaces (see screenshot below).

image

You can determine the actual buffer content length using _EdGetEnv() – aEnv[2] holds that byte count (see below).

Editor buffer lenght = 12

What we also see is that the CRs at the end of each line are counted! This is important to know when we have to calculate an offset within the text buffer.

The Caret

There are some other words for the caret which are used interchangeably; sometimes the caret is called Cursor, sometimes Insertion Point depending on the context. Anyway, the caret (I tried to use this name all over) plays a central role when it comes to programmatically modify an editor’s buffer. You can hide the caret using _EdActive(nWH, .F.) as long as the referenced editor session isn’t the active one. More important, you have to know exactly how the caret position (which is a simple integer value) is determined!

Counting From Zero

Let’s start with a new, empty editor session (with display white spaces enabled!). The text buffer length still is zero but the caret already is displayed! Therefore, this caret position value apparently can only be <0>! Same is true for line numbering: there still is no line content, the caret is on the empty line <0>. Now, let’s type in the letter “A”. The caret blinks behind the A; its position now is <1>. Press Carriage Return and the caret gets moved down to the next line. Behind the A we see a new CR-mark. What’s the position value of the caret now? You’re right, the new caret offset is <2> (on line <1>).

Offsets and Positions

Programming VFP’s string functions all day long, we got used to count the characters in our strings starting with <1>. In contrast, all editor functions start counting with <0>! Therefore, we have to keep in mind, that all offsets and line item specifications that are used by Foxtools’ editor functions are seen from a caret’s point of view!

During my documentation I noticed, I was using some position terms more often:

  • BOF (begin of file)
  • EOF (end of file)
  • BOL (begin of line)
  • EOL (end of line)

Using the first two may be a little bit confusing. To be precise, they should read BOB (begin of buffer) and EOB (end of buffer) because that’s where they really point to. During an editor session we add and/or delete words and lines. Thus, the EOB pointer will differ from the EOF pointer pretty fast – they equal each other only just after loading or saving the file. Nevertheless, I decided to prefer the better-known BOF and EOF abbreviations. Keep in mind, that we never talk about pointers to file contents, but always referring to the editor text buffers. Okay, now for a short description of the four…

BOF (Begin of File/Buffer)

This is no real, variable pointer. Its value is a fixed <0> (column/character #0, line #0)

EOF (End of File/Buffer)

The value of this pointer can be retrieved either using _EdGetEnv(nWhnd, @aEnv) (the buffer-size returned in aEnv[2] holds the EOF value) or by using a nested function call like this: _EdSkipLin(nWhnd, _EDGETLPOS(nWhnd, -1),1). The EOF pointer always holds the value we would position the caret if we wanted to add new text to the end of our editor buffer.

BOL (Begin of Line)

The value of this pointer can be easily retrieved using _EdGetLPos(nWhnd, nLineNo). Again, keep in mind line numbering is zero-based! Thus, _EdGetLPos(nWhnd, 0) will return the offset position before the fist line which equals BOF := <0>. The BOL pointer holds the value we would position the caret if we wanted to start adding new text before any existing one on a given line.

EOL (End of Line)

As there is no “native” Foxtools editor function to retrieve the value of an EOL pointer, we have to construct one ourselves. Fortunately, that is not really complicated. Assuming that <nLineNo> holds the (zero-based) line number we want to get the EOL value from,  _EdGetLPos(nWhnd, nLineNo+1)-1 does the job. The EOL pointer holds the value we would position the caret if we wanted to add text at the end of a given line. After setting the caret to an EOL position like this:
_EdSetPos(nWHnd,_EdGetLPos(nWhnd, nLineNo +1)-1), we could see the caret blinking between the last character and the CR-mark (with display white spaces set ON, of course).

The Editor (Session-) Handle

There’s one thing all Foxtools editor functions have in common: they require a valid (session-)handle! Fortunately, passing an invalid handle today creates a trappable FoxPro error #2028 “API call caused an exception”. There’s only one way to test if a handle belongs to an active editor session: we have to check _EdGetEnv()’s return value. Because this involves some undesired overhead (we have to create an array first), my current solution is to wrap my editor functions in TRY-CATCH-ENDTRY statements if I’m not sure about my editor session handle’s validity. Naturally, you can use any other VFP error-trapping, too.

I’ve seen many code fragments used to demonstrate how to retrieve a valid editor session handle. Sometimes I’d got the notion that some of the authors didn’t know the difference between an editor session handle and a FoxPro window handle! The only truth is: there is none! At the moment you’ve retrieved the handle of a FoxPro window running an editor session you have the session handle as well! For example, the Foxtools window-related function _WONTOP() will return such an internal “old-fashioned” FoxPro windows handle. Now, if the expression: _EdGetEnv(_WOnTop(), @aEnv) = 1 is TRUE, then you’re already done: the current _WONTOP() window handle is a valid editor session handle! Naturally, the _EdOpenFil() function will always return a valid valid session handle, if its return value is not zero.

Boundary Checking

There are some Foxtools editor functions that allow us to move the caret or to retrieve text from the editor’s buffer, as well as writing text to it. These functions are working with offset parameters that tell the called function where to position the caret, or where to insert the new text. Unfortunately, there is no sufficient boundary-checking built in internally (if at all)! In other words, in some cases we are able to write/read over the editor buffer’s memory boundaries! Be aware of that when calculating offset values in your code. It seems to be a good idea to check them against valid boundary values twice before passing them in :-)

 


Fox-Editor Functions: Examples

Version: 00.20.00 - last Update: Thuesday, October 13, 2009, 13:40:00

Fox-Editor Functions: An OverviewFoxtools Home (TOC)Fox-Editor Functions: Good2Know


Editor How-To Examples  Editor How-To Examples

Basics

How can I retrieve an editor session handle?

How can I test if an editor session handle still is valid?

How can I get the whole content of an editor buffer?

How can I replace the whole content of an editor buffer?

How can I calculate the total lines count?

How can I get a Modify Command session handle?

How can I replace some text in an editor buffer?

How can I select a block of text in an editor buffer?

How can I determine what text is highlighted in an editor buffer?

Enhanced

How can I monitor an editor session?

How can I get the Win-Handle of an editor session window?

How can I refresh an editor session window?

How can I create a dockable editor session window?

How can I apply another style to my editor session windows?

How can I run my editor sessions outside VFP’s screen?

How can I beautify code in my editor session buffer programmatically?

How can I revert my editing in my editor session buffer programmatically?

How can I monitor user keystrokes in my editor sessions?

How can I monitor scrolling in my editor sessions?

How can I find an editor session window without knowing its title?

How can I synchronise two or more editor sessions?

 


Fox-Editor Functions: An OverviewFoxtools Home (TOC)Fox-Editor Functions: Good2Know

Foxtools – How to Start

Version: 01.00.00 - last Update: Saturday, October 10, 2009, 16:30:00

Foxtools Home (TOC)Foxtools Home (TOC)Foxtools – Alphabetical Reference


How to start?

I started with a dump of all Foxtools functions. This listing is the basis for the alphabetical reference you can find here.

Next, I created a meaningful top-level grouping which I am using in my secondary reference you can find here.

At the moment I’m working on a 2nd level grouping I’m going to use for function cross-referencing within each top level group (the famous “see also” links).

Finally, I will create a separate documentation for each top level group containing a comprehensive collection of “How-To” examples, “Good2Know” secrets and a “Tips & Tricks“ section. These documents will be added to my blog pretty soon but I’m going to fill them with content by and by.

Documentation Consistence

During my testing and writing (while I’m writing these lines, I’ve just finished the editor related Foxtools functions) I found that it would be a good idea to establish a set of documentation rules to achieve a consistent style and naming conventions for all entries.

 

<to be continued…>


Foxtools Home (TOC)Foxtools Home (TOC)Foxtools – Alphabetical Reference

Foxtools – Editor _EDUNDOON

Version: 01.10.10 - last Update: Tuesday, October 13, 2009, 13:05:00

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter See also:_EdUndo | _EdRedo


Foxtools Editor Support Functions

_EDUNDOON

_EdUndoOn() Creates a group of undo-/redo-able actions in the editor session window passed in <nWHAND> parameter.

VFP Syntax

= _EdUndoOn(nWHAND, lOpenClose)

Parameters

[in] nWHAND

Fox-window handle of the editor session in question. If nWHANDL is no valid editor-session handle, an error “API call caused an exception” (Error 2028) is raised.

[in] lOpenClose

Controls the grouping: TRUE opens a new group, FALSE closes the (last opened) group

Returns

VOID - no evaluable return value, coz always TRUE.

Remarks

With _EdUndoOn() one can group an arbitrary set of editor actions. Groups cannot be nested.

Background:

Every editor action, either interactive or programmatic is pushed on an internal action-stack which has a typical FIFO (first in, first out) layout. _EdUndo() pops the last action from that action-stack, reverts the action’s outcome in the editor’s text buffer and then pushes the action on a second undo-stack which has the same FIFO layout. _EdRedo() reverts this process by popping the last action from that undo-stack, re-applies its outcome to the text buffer and then pushes the action back on the action-stack again.

_EdUndoON(wh, .T.) creates some kind of basket (or envelop) holding multiple actions that gets pushed on the action-stack when _EdUndoON(wh, .F.)  or _EdUndo() is called. Internally the group-container is handled like a single action while being pushed and popped on and from the stacks. The only difference is, that more than on action has to be applied/reverted to the editor’s text buffer in case of a group.

VFP Example(s)

Opening an editor session, activating multiple undo-grouping, finally issuing some _EdUndo()s and _EdRedo()s to roll the whole sequence back and forth:

*\\ Open text editor session
nWHAND =_EDOPENFIL("TEST.TXT", 1)
lcText = "1.) This is a single line inserted without undo-grouping"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
lcText = "2.) Another single line inserted without undo-grouping"+CHR(13) 
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
lcText = "3.) After this line 1st undo-group will be created"+CHR(13) 
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
*\\ Create undo-group ----------------------
=_EDUNDOON(m.nWHAND,.T.)
lcText = "4a) Line inserted while 1st undo-grouping is active"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
lcText = "4b) Line inserted while 1st undo-grouping is active"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
lcText = "4c) After this line 1st undo-group will be closed"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
*\\ Close undo-group ----------------------
=_EDUNDOON(m.nWHAND,.F.)
*\\ Create another undo-group ----------------------
=_EDUNDOON(m.nWHAND,.T.)
lcText = "5a) Line inserted while 2nd undo-grouping is active"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
lcText = "5b) Line inserted while 2nd undo-grouping is active"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
lcText = "5c) After this line 2nd undo-group will be closed"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
*\\ Close undo-group ----------------------
=_EDUNDOON(m.nWHAND,.F.)
lcText = "6.) This is a single line inserted without undo-grouping"+CHR(13)
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
lcText = "7.) This is the last line inserted without undo-grouping" + CHR(13) + ;
	 "     What do you think - how many times we have to call "  + CHR(13) + ;
	 "     EdUndo() to clear the editor session completely?"
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
*//
WAIT WINDOW "Press any key to UNDO changes (1)"
= _EDUNDO(m.nWHAND)
WAIT WINDOW "Press any key to UNDO changes (2)"
= _EDUNDO(m.nWHAND)
WAIT WINDOW "Press any key to UNDO changes (3)"
= _EDUNDO(m.nWHAND)
WAIT WINDOW "Press any key to UNDO changes (4)"
= _EDUNDO(m.nWHAND)
WAIT WINDOW "Press any key to UNDO changes (5)"
= _EDUNDO(m.nWHAND)
WAIT WINDOW "Press any key to UNDO changes (6)"
= _EDUNDO(m.nWHAND)
WAIT WINDOW "Press any key to UNDO changes (7)"
= _EDUNDO(m.nWHAND)
*//
WAIT WINDOW "Press any key to REDO changes (1)"
= _EDREDO(m.nWHAND)
WAIT WINDOW "Press any key to REDO changes (2)"
= _EDREDO(m.nWHAND)
WAIT WINDOW "Press any key to REDO changes (3)"
= _EDREDO(m.nWHAND)
WAIT WINDOW "Press any key to REDO changes (4)"
= _EDREDO(m.nWHAND)
WAIT WINDOW "Press any key to REDO changes (5)"
= _EDREDO(m.nWHAND)
WAIT WINDOW "Press any key to REDO changes (6)"
= _EDREDO(m.nWHAND)
WAIT WINDOW "Press any key to REDO changes (7)"
= _EDREDO(m.nWHAND)

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter

Foxtools – Editor _EDUNDO

Version: 01.10.10 - last Update: Tuesday, October 13, 2009, 13:00:00

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter See also:_EdRedo | _EdUndoOn


Foxtools Editor Support Functions

_EDUNDO

_EdUndo() undoes the most recent changes/edits in the editor session window passed in <nWHAND> parameter.

VFP Syntax

= _EdUndo(nWHAND)

Parameters

[in] nWHAND

Fox-window handle of the editor session in question. If nWHANDL is no valid editor-session handle, an error “API call caused an exception” (Error 2028) is raised.

Returns

VOID - no evaluable return value, coz always TRUE.

Remarks

_EdUndo() may be called more than once in a row to roll back more than one action. Edit actions that can be undone or reverted (using _EdUndo() and _EdRedo()) may be grouped enclosing them between _EdUndoOn() commands.

VFP Example(s)

Opening an editor session, activating undo-grouping, adding some text, finally doing one _EdUndo() to roll back the whole sequence:

*\\ Open editor session
nWHAND =_EDOPENFIL("TEST.TXT", 1)
*\\ set undo-grouping ON
=_EDUNDOON(m.nWHAND,.T.)
*//
lcText = "NEW TEST"
*\\ insert 1st word
= _EDINSERT(m.nWHAND,m.lcText,3)
*\\ new line
= _EDSENDKEY(m.nWHAND,13)
*\\ insert 2 words
= _EDINSERT(m.nWHAND, m.lcText, LEN(m.lcText))
*\\ new line
= _EDSENDKEY(m.nWHAND,13)
*\\ more words
lcText = "Much more TEXT"
= _EDINSERT(m.nWHAND,m.lcText, LEN(m.lcText))
= _EDINSERT(m.nWHAND,"!",1)
*\\ new line
= _EDSENDKEY(m.nWHAND,13)
*\\ Caret on row#1
= _EDSETPOS(m.nWHAND,0)
*\\ Indent row#1 with 1 tab stop
= _EDINDENT(m.nWHAND,1) 
*\\ set undo-grouping OFF
=_EDUNDOON(m.nWHAND,.F.)
*//
WAIT WINDOW "Press any key to UNDO all changes"
= _EDUNDO(m.nWHAND)

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter

Foxtools – Editor _EDSTOSEL

Version: 01.01.00 - last Update: Tuesday, October 13, 2009, 11:35:00

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter See also:_EdActive | _EdSetPos | _EdSToPos


Foxtools Editor Support Functions

_EDSTOSEL

_EdSToSel() Scrolls editor session window passed in <nWHAND> parameter so that the highlighted area becomes visible. The function name is an abbreviation for “Editor Scroll To Selection” and has nothing to do with “storing” something (like one can read in other documentations out in the dark :-)

VFP Syntax

= _EdSToSel(nWHAND, lCenter)

Parameters

[in] nWHAND

Fox-window handle of the editor session in question. If nWHANDL is no valid editor-session handle, an error “API call caused an exception” (Error 2028) is raised.

[in] lCenter

If TRUE, then the highlighted text is vertically centred in the editor session window. If FALSE, then the highlighted text is made visible without vertical centring. Note: If you use FALSE and have highlighted more than a single line of text, then _EdSToSel() does NOT make the whole text block visible, but only scrolls as long as no selected line is visible! As soon as the first highlighted line becomes visible, scrolling stops like shown below:

Scrolling Selected Block Without Vertical Centring

Returns

VOID - no evaluable return value, coz always TRUE.

Remarks

The _EdSToSel() does not move the caret. If the highlighted text is already visible (must be fully displayed), then calling  _EdSToSel() with <lCenter> = .F. does nothing. Calling  _EdSToSel() with <lCenter> = .T. may move the highlighted text to vertical centre if it isn’t already centred. If the editor session window doesn’t have a vertical scroll bar displayed, the _EdSToSel() does nothing, coz there is nothing to scroll :-)

VFP Example(s)

Opening an editor session, selecting some text, finally scrolling text so that the highlighted block will be displayed centred:

*\\ Open editor session
nWHAND =_EDOPENFIL("TEST.TXT", 1)
nLineNo = 09 && from line 10
nFromLine = _EdGetLPos(nWHAND, m.nLineNo)
nLineNo = 15 && to line 15
nToLine = _EdGetLPos(nWHAND, m.nLineNo)-1
*\\ select the text block
_EDSELECT(m.nWHAND, m.nFromLine, m.nToLine)
= _EdSToSel(m.nWHAND, .F.)

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter

Foxtools – Editor _EDSTOPOS

Version: 01.00.10 - last Update: Tuesday, October 13, 2009, 11:40:00

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter See also:_EdActive | _EdSetPos | _EdSToSel


Foxtools Editor Support Functions

_EDSTOPOS

_EdSToPos() Scrolls editor session window passed in <nWHAND> parameter so that a given position is visible. The function name is an abbreviation for “Editor Scroll To Position” and has nothing to do with “storing” something (like one can read in other documentations out in the dark :-)

VFP Syntax

= _EdSToPos(nWHAND, nOffset, lCenter)

Parameters

[in] nWHAND

Fox-window handle of the editor session in question. If nWHANDL is no valid editor-session handle, an error “API call caused an exception” (Error 2028) is raised.

[in] nOffset

Offset position from beginning of file that should be made visible. The <nOffset> value is zero-based. CRs @ EOL are counted, too.

[in] lCenter

If TRUE, then the offset position <nOffset> is vertically centred in the editor session window. If FALSE, then the offset position <nOffset> only is made visible (without vertical centring) within the editor session window.

Returns

VOID - no evaluable return value, coz always TRUE.

Remarks

The _EdSToPos() does not move the caret. If the target line (the one containing the <nOffset> offset position) is already visible (must be fully displayed), then calling  _EdSToPos() with <lCenter> = .F. does nothing. Calling  _EdSToPos() with <lCenter> = .T. may move the target line to vertical centre if it isn’t already centred. If the editor session window doesn’t have a vertical scroll bar displayed, the _EdSToPos() does nothing, coz there is nothing to scroll :-)

VFP Example(s)

Opening an editor session, scrolling down so that line#30 will be displayed centred:

*\\ Open editor session
nWHAND =_EDOPENFIL("TEST.TXT", 1)
nLineNo = 29 && line 30
nBOLposLineX = _EdGetLPos(nWHAND, m.nLineNo)
= _EdSToPos(m.nWHAND, nBOLposLineX, .T.)
*\\ Typically _EdSToPos() is used in conjunction with _EDPOSINVI()
IF NOT _EDPOSINVI(m.nWHAND, m.nBOLposLineX) 
   =_EDSTOPOS(m.nWHAND, m.nBOLposLineX, .F.)
ENDIF

Previous ChapterFoxtools Home (Alphabetical TOC)Foxtools Home (Grouped TOC)Next Chapter