![]() |
INTRO:
|
+------------------+ +-------------------+ 4.FOX widget -> | FXStyledText |--bridge--| ScintillaFX | <- 3.communication layer +------------------+ +-------------------+ | ScintillaBase | +-------------------+ <- 2.Scintilla proper | Editor | +-------------------+ | PlatFOX | <- 1.platform layer +-------------------+ |
The following discussion assumes that the Scintille has been installed
in $SCINTILLA (e.g.: /usr/local/scintilla)
1. The platform layer:
Scintilla achives the platform independece by providing a Portability
library (defined in file $SCINTILLA/include/Platform.h). The Portability
library is a thin layer over the platform's native capabilities. The objects
defined by this layer are:
2. The Scintilla proper:
Developers of a platform implementation will access the Scintilla capabilities
via two classes: the Editor and the ScintillaBase. The Editor
object is central to Scintilla. It is responsible for displaying a document
and responding to user actions and requests from the container. ScintillaBase
is a subclass of Editor and adds extra windowing features including display
of calltips, autocompletion lists and context menus.
These two classes are implemented in files $SCINTILLA/src/Editor.cxx
and
$SCINTILLA/src/ScintillaBase.cxx.
3. The communication layer:
For each platform, a class is derived from ScintillaBase (and thus
from Editor). These classes are responsible for connecting to the platforms
event mechanism and also to implement some virtual methods in Editor and
ScintillaBase.
The current implementation of the FOX communication layer uses messages.
(In theory a different API, where the Scintilla events are directly translated
into FOX events, could be implemented.)
The FOX implementation is in the file $SCINTILLA/fox/ScintillaFOX.cpp.
For more info on the Scintilla design please see http://www.scintilla.org/Design.html
4. The FOX styled widget:
The FXStyledText is derived from FXScrollArea which provides the drawing
surface Scintilla will draw upon. When the FXStyledText is constructed
it instanciates a ScintillaFX object and passes it itself as the argument:
ScintillaFX* m_sfx = new ScintillaFX(this);
The FXStyledText will use the ScintillaFX object to access the 'low level' Editor functions exposed via public functions implemented in the ScintillaFOX.cpp e.g:
m_sfx->DoAddChar(ch);
The ScintillaFX class will use the pointer to to the FXStyledText (received as a argument) to manipulate the container on behalf of the Scintilla proper, e.g.:
ScintillaFX::ScintillaFX(FXStyledText*
win) {stc=win};
stc->moveContents(stc->pos_x, new_y);
The FXStyledText is implemented in the file $SCINTILLA/fox/stc.cpp,
the ScintillaFX is implemented in the file $SCINTILLA/fox/ScintillaFOX.cpp.
5. The bridge:
To access the 'high level' (user) functions in the Scintilla, FXStyledText
sends messages to the Scintilla proper. (These are similar to the
Windows messages.) This is the mechanism used by both the WXWindows and
the GTK version of the Scintilla.
The messages are wrapped in FXStyledText public functions e.g.:
public void FXStyledText::ClearAll() {SendMsg(2004, 0, 0);}
These wrappers are the only functions the user of the FXStyledText should
use to access the Scintilla capabilities!
The message wrappers are implemented in the file $SCINTILLA/fox/Messages.h.
This file is #include-d in $SCINTILLA/fox/stc.h.
The Scintilla proper sends status messages back to FXStyledText, via
FOX event mechanism! (Note: in the current version (0.2) the functions
are impemented, but the status information is not used.)
The relevant code:
In ScintillaFox.cpp:
void ScintillaFX::NotifyParent(SCNotification
scn) {
stc->handle(FXSciObject(wMain.GetID()),
MKUINT(ID_SCINTILLA, SCIMSG_NOTIFY), &scn);
}
Where:
#define FXSciObject(a) ((FXObject* ) a)
//in $SCINTILLA/fox/ScintillaFOX.h
Window wMain;
//in $SCINTILLA/src/Editor.h
And in stc.cpp:
long FXStyledText::onSciNotify(FXObject*,
FXSelector, void*){...}
EXAMPLE1:
The following pseudo-code will attempt to ilustrate the design by investigating
what happens on a key press. Using the 'seditor' example aplication.
A. The 'seditor' is started and a FXSTyledText object (editor) is instantiated (file seditor.cpp):
editor = new FXStyledText(textbox, this, ID_TEXT);
B. The FXStyledText constructor will instantiate a ScintillaFX object (m_sfx) (file stc.cpp):
m_sfx = new ScintillaFX(this);
C. Key press is detected by FXStyledText. The onKeyPress() function is called. From within onKeyPress() FOX calls the ScintillaFX function DoKeyDown(), and sends itself an ID_INSERT_CHAR message (file stc.cpp):
long FXStyledText::onKeyPress(FXObject*,
FXSelector, void*) {
code = ...;
key
= ...;
m_sfx->DoKeyDown(code);
handle(this,
MKUINT(ID_INSERT_CHAR, SEL_COMMAND), key);
}
D. FXStyledText handles the message in onCmdInsertChar() by calling the ScintillaFX function DoAddChar() (file stc.cpp):
long FXStyledText::onCmdInsertChar(FXObject*, FXSelector, void*)
{
ch = ...;
m_sfx->DoAddChar(ch);
}
E. ScintillaFX executes the DoAddChar() function by calling the Editor::AddChar(ch) function (file ScintillaFOX.cpp):
void ScintillaFX::DoAddChar(char
ch) {
AddChar(ch);
}
F. Editor'll add the character to its internal buffer, do the styling, display and all the magic, and sends a notification message to ScintillaFX with the details about the changes (file Editor.cpp):
void Editor::AddChar(char
ch) {
Document*
pdoc = ...;
pdoc->InsertString(ch);
NotifyParent(SCN_CHARADDED);
}
G. ScintillFX receives the notification and forwards it to FOX as a FOX event (file ScintillaFOX.cpp):
void ScintillaFX::NotifyParent(SCNotification
scn) {
stc->handle(FXSciObject(wMain.GetID()),
MKUINT(ID_SCINTILLA, SCIMSG_NOTIFY), &scn);
}
H. FXStyledText receives the event and handles it in onSciNotify() (file stc.cpp):
long FXStyledText::onSciNotify(FXObject*, FXSelector, void*){...}
Please note that in the above example 'seditor' didn't use the message mechanism to access Scintilla, instead the FOX events were used to comunicate the request to the FXStyledText, which delegated the request to ScintillaFX, which on turn called the Editor functions directly.
The request:
seditor -[FOX
event]-> FXStyledText -> ScintillaFX -> Editor
The response:
Editor -> ScintillaFX -[FOX
event]-> FXStyledText
EXAMPLE2:
The second ilustration will show how a message is used by the
aplication to access Scintilla. We will investigate what happens when the
example aplication 'seditor' opens a disk file for editing.
A. The 'seditor' is started and a FXSTyledText object (editor) is instantiated (file seditor.cpp):
editor = new FXStyledText(textbox, this, ID_TEXT);
B. The FXStyledText constructor will instantiate a ScintillaFX object (m_sfx) (file stc.cpp):
m_sfx = new ScintillaFX(this);
C. The user selects the 'Open' menu item. Seditor calls the function LoadFile(), where it reads the disk file into a buffer and calls the FXStyledText function SetText() (file seditor.cpp):
FXbool StyledTextWindow::LoadFile(const
FXString& file) {
fread(buffer,
file);
editor->SetText(buffer);
}
D. The called function FXStyledText::SetText() is a wrapper function which will send a message to Scintilla proper requesting the 'buffer' to be styled and displayed (file Messages.h):
void SetText(const FXString&
buffer) {
SendMsg(2181,
0, (long)buffer.text());
}
E. The messages 2181 (defined as SCI_SETTEXT in file $SCINTILLA/include/Scintilla.h) is received by the Editor and the requested action is performed (file Editor.cxx):
Document* pdoc = ...;
switch (iMessage) {
case SCI_SETTEXT:
pdoc->InsertString(0, lParam);
...
}
F. Finally Editor will display the text and send a notification to ScintillaFX, which forwards the message to FXStyledText as a FOX event - as in F. G. H. in the previous example.
The request:
seditor -> FXStyledText -[Scintilla
message]-> Editor
The response:
Editor -> ScintillaFX -[FOX
event]-> FXStyledText
1. Platform.h ($SCINTILLA/include/Platform.h): This file is part of the Scintilla distribution, and it needs to modified for each platform the control is being implemented for (see section DESIGN, paragraph 1). The following mapping between the Scintilla and the FOX objects has been made:
2. PlatFox.cpp ($SCINTILLA/fox/PlatFox.cpp): This file implemets the mapping defined in the Platform.h file, and a few additional utility functions. This file is based on PlatWX.cpp from the WXWindows implementation.
Note for developers: Please verify the above two files. I (SB) have marked all functions I was not sure about with "//SB ?", where the number of question marks indicate my level of confusion :). Some of the functions are already exercised by the example 'seditor', and they appears to be working, but somebody who is more intimate with the FOX internals could probably improve those. Also the ListBox has not been implemented yet (The commented out WXWindow implementation has been left there as a clue.)
3. ScintillaFOX.h, ScintillaFOX.cpp ($SCINTILLA/fox/*): These files implement the required Scintilla virtuall functions and the 'delegate' functions DoXXX(). This file is based on ScintillaWX.cpp from the WXWindows implementation.
Note for developers: Please verify the functions implementing
the scrolling. The vertical scrolling seems to be OK, but the horizontal
scrolling needs some work. Scintilla doesn't provide the means for determining
the width of the displayed contents (w_contents). Both the WXWindows and
the GTK implementation are using hard-coded values, so does our code.
CallTipWindow is not implemented yet - the commented out code from
ScintillaWX.cpp is there as a guide.
The DoButtonUp() function would normally call Editor::ButtonUp(), but
the code in Editor conflicts with FOX DND, so we do our own handling here.
Our code will also change the default behaviour when clicking on a selected
area from NOP to removing the selection (With the default behaviour one
must click on a non-selected region to remove the selection.)
4. stc.h, stc.cpp ($SCINTILLA/fox/*): The implementation of the FXStyledText widget. This file was created using the FXText.cpp as a guide.
Note for developers: Commented out fragments of code taken from
FXText.cpp has been left in the file.
The LoadConfig() function is a temp, to load the CPP lexer, set the
syntax colors, fonts, and initialize margins.
The functions getViewportHeight() and getViewportWidth() are taken
from FXScrollArea.cpp - please check if this is the correct solution.
Scintilla doesn't have autoscroll-while-selecting and autoscroll-while-dragging.
FXStyledText implemets both, but the function Editor::ButtonMove() must
be patched. Please see the Editor.cpp and look for the "\\SB" comments.
5. Messages.h ($SCINTILLA/fox/Messages.h): This file implements the wrapper arround the Scintilla SendMsg() functions. This file has been extracted from stc.h in the WXWindows version.
Note for developers: Please verify the functions returning FXColor. (GetCaretForeground() etc)
6. seditor.h, seditor.cpp ($SCINTILLA/fox/*): An example editor to exercise the FXStyledText widget. The LoadFile() is taken from the fox textedit application.
7. Makefile ($SCINTILLA/fox/Makefile):
Makefile for compiling the modified scintilla library and the 'seditor'
application. Callable targets: dep - create .depend file, lib - create
the scintila.a library, lex - create the parser object files (not part
of the library), exe - create the 'seditor', and clean - delete object
files and the library. The default target is equivalent to make lib;
make lex; make exe.
$ cd /usr/local
$ gzip -dc scintillaXXX.tgz | tar xvf
-
(the XXX is the Scintilla version number)
2. Rename the new directory:
$ mv scintilla scintilla138 (or a name of your choice)
3. The FXStyledText source files are distributed as a compressed tar archive. Please change to the directory where you unpacked the Scintilla sources and execute
$ gzip -dc scintillafox-XX.tar.gz | tar xvf -
(the XX is the version number of the port, as of 06/25/01 the distribution file is scintillafox-0.2.tar.gz)
4. After unpacking the distro you
will have a file scifox.patch in the $SCINTILLA
directory,
and a subdirectory $SCINTILLA/fox.
Read the $SCINTILLA/fox/README.html file, and verify that
you are using the version of the FOX library and the version of the Scintilla
the scintillafox distribution was developed with.
5. Apply the scifox.patch to add the FOX support to the Scintilla files:
$ patch -p1 < scifox.patch
6. Change to the fox subdirectory and run:
$ make dep
$ make
7. Test the example aplication:
$ ./seditor
$ cd /usr/local
$ diff -c -r scintilla-old scintilla-new > scifox.patch
Alernative is a tar archive of all files you have made changes to, sent
to bokor@bc.edu as a email attachement. Credit to
the developers will be given on this page, and in the source files.
If we manage to assemble a small team I'll set up a mailing list. Until
than please feel free to contact me by email, or post a message to the
FOX newsgroup.
I hoped to do some more testing/cleaning before releasing the code,
but it looks like I won't be able to work on this project until September.
If anybody feels this work is worth spending time on, I would be glad to
update the distro with his/her modifications and make it available from
our server.
Stefan Bokor
bokor@bc.edu