VTextEditor

A complete text editing canvas pane.

Synopsis

 * Header:
 * 


 * Class name:
 * vTextEditor


 * Hierarchy:
 * [vcanvas.htm vCanvasPane] ->[vtextcnv.htm vTextCanvasPane] ->vTextEditor

Description
This class is a completely functional line oriented text editor. It can edit any file with lines less than 300 characters wide that use a linefeed, carriage return, or combination of those to mark the end of each line.

While you need to create your own class derived from vTextEditor, your class can be very minimal. You will need to provide some service methods for the parent vCmdWindow, such as methods to open, read, save, and close files. Other than actually working with the real text source and providing that source to vTextEditor, you can get a fully functional text editor with no additional work.

However, vTextEditor has been designed to allow you to extend and add functionality to the editor if you need to. The vTextEditor also sends messages that will allow you to place various status messages on a status bar if you wish. The hard stuff is done for you. You don't need to worry about mouse movements, scroll bars or scroll messages, updating the screen, handling keystrokes, or anything else associated with actual editing. The vTextEditor class takes care of all those details, and provides a standard editing interface.

The following steps are required to use vTextEditor</tt>. First, you create an instance of your derived class from your vCmdWindow</tt> class, something like this: ...   // The Text Editor Canvas vedCanvas = new vedTextEditor(this); AddPane(vedCanvas); ...   // Show Window ShowWindow; vedCanvas->ShowVScroll(1); // Show Vert Scroll for vTextEditor ...

Your derived vTextEditor</tt> class should provide the methods needed for opening and reading the text file you want to edit. (Actually, you can edit any text source you wish.) VTextEditor</tt> doesn't actually read or write any text itself. It maintains an internal line buffer. (The default version of the internal buffer is essentially limited by the amount of memory your system can provide. The buffer methods can be overridden to provide totally unlimited file size, if you wish.) The idea is to have your application control where the text comes from, and then add it a line at a time to the vTextEditor</tt> buffer. You retrieve the text a line at a time when you want to save the edited text. Thus, your if your code is working with disk files, it can read the text a line at a time, and let vTextEditor</tt> worry about the buffering.

The following code shows how to add the contents of a text file to the vTextEditor</tt> buffer, and display it in the canvas for the first time. Calls to vTextEditor</tt> methods are marked with **. //===================>>> vedTextEditor::ReadFile <<<==================== int vedTextEditor::ReadFile(char* name) {    const int maxBuff = 300;    // Line length char buff[maxBuff]; if (!name || !*name) return 0; ifstream inFile(name);     // Open the file if (!inFile) return 0;              // file not there resetBuff;               // ** Tell vTextEditor to init buffer while (inFile.getline(buff,maxBuff)) // read file {        if (!addLine(buff))     // ** Add the line to the buffer {            ERROR_MESSAGE("File too big -- only partially read."); break; }      }     inFile.close;             // Close the file displayBuff;             // ** Now, display the buffer return 1; }

To load text into the editor buffer, you first call resetBuff</tt> to initialize the buffer, then add a line at a time with calls to addLine</tt>, and finally display the text by calling displayBuff</tt>.

When your are editing (e.g., the user enters a Close command), you retrieve the text from the vTextEditor</tt> buffer with calls to getLine</tt>.

Then, to use the editor, you pass keystrokes from the KeyIn</tt> method of your vCmdWindow</tt> to the EditKeyIn</tt> method of the vTextEditor</tt>. <tt>EditKeyIn</tt> interprets the conventional meanings of the arrow keys, etc., and lets you edit the text in the buffer. You will also probably implement other commands, such as Find, by using the <tt>EditCommand</tt> method.

<tt>VTextEditor</tt> also calls several methods to notify of text state changes, such as current line, insert or overtype, etc. You can receive these messages by overriding the default methods, and display appropriate information on a status bar.

While <tt>vTextEditor</tt> is very complete, there are some things missing. The major hole is cut and paste support. This will be added when cut and paste support is added to V. There is also no real undo support. Maybe someday.

vTextEditor(vBaseWindow* parent)
The <tt>vTextEditor</tt> constructor requires that you specify the parent <tt>vCmdWindow</tt>. Since you usually create the text editor object in your <tt>vCmdWindow</tt> object, this is easy. You will probably need to cast the <tt>this</tt> to a <tt>vBaseWindow*</tt>.

resetBuff
Before you load new text into the buffer, you must first call this method. It initializes the internal state of the text buffer.

virtual int addLine(char* line)
This method is called repeatedly to add lines to the text buffer. The default method is limited by the amount of memory available on the system, and this method return 0 when it runs out of memory.

Note that the entire text buffer package can be overridden if you need to provide unlimited file size handling. You should examine the source code for <tt>vTextEditor</tt> to determine the specifications of the methods you'd need to override.

virtual void displayBuff
After you have added the complete file, call <tt>displayBuff</tt> to display the text in the window.

virtual int getNextLine(char* line, int maxChars)
These are used to retrieve the edited text from the buffer. You can use <tt>getFirstLine</tt> with <tt>getNextLine</tt> for easy sequential retrieval, or <tt>getLine</tt> for specific lines. These methods return -1 when all lines have been recovered.

virtual int EditCommand(int id, long val)
This method provides a complete interface to the functions provided by <tt>vTextEditor</tt>. While the basic editing functions are also handled by <tt>EditKeyIn</tt>, <tt>EditCommand</tt> gives access to functions that typically are either usually invoked from a menu command (such as Find), or don't have a standard mapping to a functions key (such as lineGoto). If you want the functionality of these commands in your application, you will have to provide an appropriate menu or command pane item to support them.

Each function supported by <tt>vTextEditor</tt> has an associated id (symbolically defined in <tt>v/vtexted.h</tt>), each beginning with <tt>ed</tt>. Many of the functions also take an associated value. Many editors allow a repetition count to be specified with many commands. For example, it is sometimes useful to be able to specify a command to move right some specific number of characters. The <tt>val</tt> parameter can be used to specify a value as desired. The only function that really need a value other than 1 (or -1 in the case of directional movement commands) is <tt>edLineGoto</tt>.

<tt>EditCommand</tt> returns 1 if the command was executed successfully, 0 if the command was recognized, but not successful (the find fails, for example), and -1 if the command was not recognized as valid.

At the time this manual was written, the following commands are supported. Because <tt>vTextEditor</tt> is evolving, it is likely more commands will be added. Check the <tt>v/vtexted.h</tt> file for specification of new editor commands. In the following descriptions, the note ``no val'' means that the <tt>val</tt> parameter is not used. A notation of ``+/-'' means the sign of <tt>val</tt> indicates direction.


 * edBalMatch
 * find matching paren (if val > 1, up to val lines away, otherwise within a reasonable range)


 * edBufferBottom
 * move to bottom of file (no val)


 * edCharDelete
 * delete +/- val chars


 * edCharFoldCase
 * swap case of +/- val letters


 * edCharInsert
 * insert char val


 * edCharRight
 * move +/- val chars right


 * edFind
 * invoke TextEd's find dialog (no val)


 * edFindNext
 * find next occurrence of prev (no val)


 * edLineBeginning
 * move to line beginning (no val)


 * edLineDown
 * move down +/- val lines in column


 * edLineDownBeg
 * move down +/- val lines


 * edLineDelete
 * delete +/- val lines


 * edLineDeleteFront
 * delete to beginning of line (no val)


 * edLineDeleteToEnd
 * delete to end of line (no val)


 * edLineEnd
 * move to end of line (no val)


 * edLineGoto
 * move cursor to line val


 * edLineOpen
 * open val new blank lines


 * edScrollDown
 * scroll +/- val lines without changing cursor


 * edVerify
 * force repaint of screen (no val)


 * edWordRight
 * move cursor +/- val words right

For a basic editor, the simplest way to use <tt>EditCommand</tt> is to use the <tt>ed*</tt> id's to define the associated menu items and controls, and then call <tt>EditCommand</tt> as the default case of the <tt>switch</tt> in the <tt>WindowCommand</tt> method of your <tt>vCmdWindow</tt>. Thus, you might have code that looks like this: ...  static vMenu EditMenu[] = { ...    {"Find", edFind, isSens,notChk,noKeyLbl,noKey,noSub}, {"Find Next", edFindNext, isSens,notChk,noKeyLbl,noKey,noSub}, {"Find Matching Paren", edBalMatch, isSens,notChk, noKeyLbl,noKey,noSub}, ...  };    ... //===========>>> vedCmdWindow::WindowCommand <<<==================== void vedCmdWindow::WindowCommand(ItemVal id, ItemVal val,      CmdType cType) {   switch (id) {     ...       default:  // route unhandled commands through editor {         if (vedCanvas->EditCommand(id, 1) < 0) vCmdWindow::WindowCommand(id, val, cType); break; }    }    ...  } //====================>>> vedCmdWindow::KeyIn <<<==================== void vedCmdWindow::KeyIn(vKey keysym, unsigned int shift) {    if (vedCanvas->EditKeyIn(keysym, shift) < 0) vCmdWindow::KeyIn(keysym, shift); }

virtual int EditKeyIn(vKey key, unsigned int shift)
This method is usually called from the <tt>KeyIn</tt> method of your derived <tt>vCmdWindow</tt> class. See the above code example.

The default implementation of <tt>EditKeyIn</tt> handles most of the standard keys, such as the arrow keys, the page keys, backspace, home, delete, insert, and end keys. It will also insert regular character keys into the text. It ignores function keys and non-printing control key values except tab and newline.

You can override this method to provide your own look and feel to the editor.

void SetEdState
<tt>VTextEditor</tt> maintains a state structure with relevant state information associated with various operating options of <tt>vTextEditor</tt>. It is defined in <tt>v/vtexted.h</tt>, and has the following fields:

typedef struct edState {        long changes,           // count of changes cmdCount;         // how many times to repeat command int findAtBeginning,   // leave find at beginning of pattern fixed_scroll,      // flag if using fixed scroll ins_mode,          // true if insert mode counter,           // counter for + insert echof,             // whether or not to echo action tabspc,            // tab spacing wraplm;            // right limit } edState;

You can query and set the state with <tt>GetEdState</tt> and <tt>SetEdState</tt>.

long GetLines
Returns the number of lines in the current buffer.

virtual void ChangeLoc(long line, int col)
This method is called by <tt>vTextEditor</tt> whenever the current line or current column is changed. This information could be displayed on a status bar, for example.

virtual void ChangeInsMode(int IsInsMode)
This method is called by <tt>vTextEditor</tt> whenever the insert mode is changed. If <tt>IsInsMode</tt> is true, then the editor is in insert mode. Otherwise, it is in overtype mode. The editor starts in insert mode. This information could be displayed on a status bar, for example.

virtual void StatusMessage(char* Msg)
The editor will call this message with a non-critical message such as Pattern Not Found for certain operations. This information could be displayed on a status bar, for example.

virtual void ErrorMessage(char* Msg)
The editor will call this message with a critical error message such as Bad parameter value for certain operations. This information could be displayed in a warning dialog, for example.