Scintilla是一个富文本编辑器控件,支持GTK、QT、Cocoa等多种UI框架。其功能接口的调用主要以消息传递的方式执行,比如载入文本文件,可以使用消息
SCI_SETTEXT(, const char *text)
该消息的作用是将Scintilla控件所显示的文本替换为消息体里面的text文本。对于消息的具体传递过程,不同的平台(GTK、QT、Cocoa等)对应不同的调用方法,在后续的QT开发会做详细介绍,并给出使用样例。除了执行普通编辑控件操作的消息外,Scancilla还支持控制语法样式、折叠、标记、自动完成和调用提示。
目前Scintilla对从右向左的语言(如阿拉伯语和希伯来语)的支持尚未完善,可以正确显示,但是编辑操作可能会有问题。
SciTE编辑器是Scintilla开发组为了展示Scintilla功能所开源的一款软件,几乎用到了Scintilla的所有接口与功能,可以用作开发参考。
SciTE编辑器 图片引自再推荐一款编辑器:SciTE
Scintilla的类型定义以及接口定义头文件分别是ScintillaTypes.h, ScintillaMessages.h以及ScintillaStructures.h。
其中ScintillaTypes.h定义了消息中的各种属性枚举类型,以自动折行方式(Line wrapping)为例,在使用编辑器过程中,经常有行文字过长的情况,此时需要通过水平滚动条来看全完整一行内容,给使用者带来很大的不便。因此主流文本编辑器(如notepad++)都会提供自动折行功能。ScintillaTypes.h中的枚举类型Wrap即用于控制自动折行的方式:
enum class Wrap { None = 0, //非自动折行 Word = 1, //以完整单词为单位做折行 Char = 2, //以单个字符为单位做折行 WhiteSpace = 3, //以空格为单位做折行 };
在开发过程中,开发者可调用消息SCI_SETWRAPMODE(int wrapMode)完成自动折行功能,其中参数wrapMode即使用上述Wrap枚举类型。
ScintillaMessages.h中定义了所有消息枚举值(Message),这些枚举值应用在Scintilla代码文件Editor.cxx中:
sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam)
ScintillaMessages.h中的消息与开发者经常使用的消息命名不同,比如还是以自动折行方式(Line wrapping)为例,开发者使用消息为SCI_SETWRAPMODE,而对应ScintillaMessages.h中的消息则是Message::SetWrapMode。这是由于Scintilla提供给开发者的接口头文件为Scintilla.h,其采用宏定义的方式,定义了所有的消息,SCI_SETWRAPMODE在其中定义为:
#define SCI_SETWRAPMODE 2268
该宏定义的消息与ScintillaMessages.h中枚举消息SetWrapMode = 2268的值相等,因此在开发者发送的消息SCI_SETWRAPMODE同样可以进入Editor::WndProc函数里面case Message::SetWrapMode的处理逻辑中。
ScintillaStructures.h中定义了通知类型,主要用于将Scintilla控件中接收到的如鼠标点击,键盘输入等消息传递出去。以鼠标双击为例,Scintilla控件在接收到鼠标双击操作后,将双击位置以及键盘当前输入(如按住Ctrl双击)传递给外部容器。
void Editor::NotifyDoubleClick(Point pt, KeyMod modifiers) { NotificationData scn = {}; scn.nmhdr.code = Notification::DoubleClick; scn.line = LineFromLocation(pt); scn.position = PositionFromLocation(pt, true); scn.modifiers = modifiers; NotifyParent(scn); }
Scintilla功能接口的调用主要以消息传递的方式执行,在其官网的说明文档中,Scintilla给出了全部的消息说明。
比如自动折行,可调用消息:
SCI_SETWRAPMODE(int wrapMode)
再比如获取某一行的字符串,可调用消息:
SCI_GETLINE(line line, char *text)
在实际的开发中,具体的调用接口为ScintillaBase.h中ScintillaBase类(开发者可以通过继承该类的方式进行二次开发)的成员函数:
sptr_t ScintillaBase::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) ;
其中iMessage为消息类型,即可以设值为上面提到的SCI_SETWRAPMODE以及SCI_GETLINE,wParam与lParam是相关的附加参数。
SCI_SETWRAPMODE(int wrapMode)的调用方式具体为:
WndProc(SCI_SETWRAPMODE, static_cast(Wrap::Word));
SCI_GETLINE(line line, char *text)的调用方式具体为:
WndProc(SCI_GETLINE, static_cast(line), reinterpret_cast (text));
WndPro函数也具有返回值,一般返回为position,比如获取光标所在当前行,调用消息SCI_GETCURLINE(position length, char *text NUL-terminated) ,其返回值为光标所在的行数,入参text则保存了当前行的字符内容。
注:Scintilla中有些消息带的参数为
WndProc(SCI_SETTEXT, static_cast(0), reinterpret_cast (text)))
Scintilla在ScintillaStructures.h中定义了通知事件数据类型,如下所示:
struct NotificationData { NotifyHeader nmhdr; Position position; /* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */ /* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */ /* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */ /* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ /* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */ int ch; /* SCN_CHARADDED, SCN_KEY, SCN_AUTOCCOMPLETED, SCN_AUTOCSELECTION, */ /* SCN_USERLISTSELECTION */ KeyMod modifiers; /* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */ /* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ ModificationFlags modificationType; /* SCN_MODIFIED */ const char *text; /* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */ Position length; /* SCN_MODIFIED */ Position linesAdded; /* SCN_MODIFIED */ Message message; /* SCN_MACRORECORD */ uptr_t wParam; /* SCN_MACRORECORD */ sptr_t lParam; /* SCN_MACRORECORD */ Position line; /* SCN_MODIFIED */ FoldLevel foldLevelNow; /* SCN_MODIFIED */ FoldLevel foldLevelPrev; /* SCN_MODIFIED */ int margin; /* SCN_MARGINCLICK */ int listType; /* SCN_USERLISTSELECTION */ int x; /* SCN_DWELLSTART, SCN_DWELLEND */ int y; /* SCN_DWELLSTART, SCN_DWELLEND */ int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */ Position annotationLinesAdded; /* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */ Update updated; /* SCN_UPDATEUI */ CompletionMethods listCompletionMethod; /* SCN_AUTOCSELECTION, SCN_AUTOCCOMPLETED, SCN_USERLISTSELECTION, */ CharacterSource characterSource; /* SCN_CHARADDED */ };
该数据结构主要用于将Scintilla控件中接收到的如鼠标点击,键盘输入等消息传递出去。
以文本内容的修改为例,当有增删改的动作后,Scintilla控件即向外部容器发送待保存事件:Notification::SavePointLeft。此时外部容器可以做对应处理,比如可以将文件标题最后增加*号,表示需要保存。发送相关事件的代码在Editor.cxx中:
void Editor::NotifySavePoint(bool isSavePoint) { NotificationData scn = {}; if (isSavePoint) { scn.nmhdr.code = Notification::SavePointReached; } else { scn.nmhdr.code = Notification::SavePointLeft; //文本内容有修改后进入该语句 } NotifyParent(scn); //此处向外部容器发送事件 }
上面代码中的NotifyParent(scn)既是向外部容器发送事件的接口函数。在Editor类中,定义了如下纯虚函数:
virtual void NotifyParent(Scintilla::NotificationData scn) = 0;
因此在实际的开发中,开发者可以通过继承ScintillaBase类的方式进行二次开发。(ScintillaBase类继承Editor类)