The V C++ GUI Framework:vTextEditor

From EDM2
Jump to: navigation, search

A complete text editing canvas pane.

Synopsis

Header:
<v/vtexted.h>
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. First, you create an instance of your derived class from your vCmdWindow 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 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 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 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 worry about the buffering.

The following code shows how to add the contents of a text file to the vTextEditor buffer, and display it in the canvas for the first time. Calls to vTextEditor 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 to initialize the buffer, then add a line at a time with calls to addLine, and finally display the text by calling displayBuff.

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

Then, to use the editor, you pass keystrokes from the KeyIn method of your vCmdWindow to the EditKeyIn method of the vTextEditor. EditKeyIn 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 EditCommand method.

VTextEditor 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 vTextEditor 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.

Constructor

vTextEditor(vBaseWindow* parent)

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

Utility Methods

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 vTextEditor to determine the specifications of the methods you'd need to override.

virtual void displayBuff()

After you have added the complete file, call displayBuff to display the text in the window.

virtual int getLine(char* line, int maxChars, long lineNum)

virtual int getFirstLine(char* line, int maxChars)

virtual int getNextLine(char* line, int maxChars)

These are used to retrieve the edited text from the buffer. You can use getFirstLine with getNextLine for easy sequential retrieval, or getLine 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 vTextEditor. While the basic editing functions are also handled by EditKeyIn, EditCommand 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 vTextEditor has an associated id (symbolically defined in v/vtexted.h), each beginning with ed. 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 val 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 edLineGoto.

EditCommand 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 vTextEditor is evolving, it is likely more commands will be added. Check the v/vtexted.h file for specification of new editor commands. In the following descriptions, the note ``no val'' means that the val parameter is not used. A notation of ``+/-'' means the sign of val 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 EditCommand is to use the ed* id's to define the associated menu items and controls, and then call EditCommand as the default case of the switch in the WindowCommand method of your vCmdWindow. 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 KeyIn method of your derived vCmdWindow class. See the above code example.

The default implementation of EditKeyIn 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.

edState GetEdState()

void SetEdState()

VTextEditor maintains a state structure with relevant state information associated with various operating options of vTextEditor. It is defined in v/vtexted.h, 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 GetEdState and SetEdState.

long GetLines()

Returns the number of lines in the current buffer.

Methods to Override

virtual void ChangeLoc(long line, int col)

This method is called by vTextEditor 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 vTextEditor whenever the insert mode is changed. If IsInsMode 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.

See Also

vTextCanvasPane