上一次曾經發布過一篇如何實現一個代碼編輯器。今年工作中得空,所以對這個編輯器進一步做了些更新,把名字改成了從CuteC改成了CEditor。主要是重寫了軟件的界面(最終還原朴素),重寫了編輯控件語法高亮的着色方式,還有增加了一個簡單的SSH客戶端和SFTP文件編輯的功能。感覺基本的功能已經實現了,所以再次寫點東西記錄一下。並且發布一下編輯控件的源代碼,有興趣的可下載下來看看,雖然代碼寫得比較亂。
上個版本:http://www.cnblogs.com/linxr/archive/2011/10/30/2229256.html
編輯控件源碼鏈接:http://files.cnblogs.com/linxr/LEdit.rar
軟件下載鏈接:http://files.cnblogs.com/linxr/CEditor.rar
軟件界面:
一、編輯控件
除了上一次寫到的一些內容外,主要在編輯控件的語法高亮上做了修改。
1. 原來的顏色信息是在繪制每行時,動態分詞查找關鍵字,形成一個顏色數組供繪制模塊使用。這種方式的優點就是邏輯簡單,繪制代碼很容易編寫。但是缺點就是,每次繪制一行,都要重新產生顏色數組,影響效率;其二,在一些場合下,高亮不是依賴於關鍵字,這時候這種方法就無能為力了。
2. 考慮到上面的缺點,對編輯控件做了修改。去除了顏色數組,改用標注信息來標注顏色字體信息。所以行數據經過着色之后不再是原來的內容了。
例如一行數據:
int main( int argc, char ** argv );
那么經過着色后,該行的數據會變成:
\ec3,0~int\ezc~ main( \ec3,0~int\ezc~ argc, \ec3,0~char\ezc~ ** argv );
其中,int和char被着色,標注信息為:
\ec3,0~ 和 \ezc~
着色信息以\e(0x1b)開始,以~結束。c表示顏色,z表示還原格式格式。
着色完成后,繪制模塊在進行繪制文本信息時,從頭到尾,掃描字符串,根據着色信息,不斷的設置還原DC的顏色信息,直到繪制完成。
3. 標注顏色帶來了一些額外的問題,主要表現在:
a.光標位置到字符串中的位置的轉換的計算。
b.獲取編輯器的內容時,要清除所有的標注信息,影響一定的性能。
c.計算tab鍵的寬度時,不能用tab鍵在字符串中的位置來計算,要考慮標注信息。
d.光標在屏幕中的位置的計算,要根據光標前面數據的字體來實時計算寬度。
二、函數列表
對於代碼編輯軟件來說,函數符號列表功能是必備的,就算是純寫C的人來說,有一個函數列表會大大提高滾動查找代碼的效率。我雖然寫了一個C語言的解釋器,對符號的解析稍作修改就可以實現,但是各種各樣的語言,我就無能為力了。好在有ctags.exe,他可以支持非常的語言符號分析。我還是直接拿來用吧,然后再加上一個樹形控件,就能實現簡單實用的功能。
我調用ctags.exe的代碼片段,主要是調用了ctags.exe,將結果保存到一個文件,然后我們再解析這個文件:
CString strParam;
CString strTags = strFilePath + _T(".tags.txt");
strParam.Format( _T("-f \"%s\" --language-force=C++ -n \"%s\"" ), strTags.GetBuffer(0), strFilePath.GetBuffer(0) );
SHELLEXECUTEINFO sei;
ZeroMemory( &sei, sizeof(SHELLEXECUTEINFO) );
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpFile = "ctags.exe";
sei.lpParameters = strParam.GetBuffer(0);
sei.lpDirectory = CLxrFile::GetExecutePath().GetBuffer(0);
sei.nShow = SW_HIDE;
sei.hInstApp = NULL;
ShellExecuteEx(&sei);
WaitForSingleObject( sei.hProcess, INFINITE );
/*
** 可以看到就是調用了ShellExecuteEx,但是有幾個地方可以提一下:
** 1. sei.nShow = SW_HIDE; 這使得進程啟動時不會顯示控制台窗口。
** 2. WaitForSingleObject( sei.hProcess, INFINITE );
** 等待進程結束,這個很重要,不然ctags啟動后,我們無法同步獲取結果。
*/
ctags.exe支持的語言,可以用命令 ctags.exe --list-languages 查看:
Asm
Asp
Awk
Basic
BETA
C
C++
C#
Cobol
Eiffel
Erlang
Fortran
HTML
Java
JavaScript
Lisp
Lua
Make
Pascal
Perl
PHP
Python
REXX
Ruby
Scheme
Sh
SLang
SML
SQL
Tcl
Vera
Verilog
Vim
YACC
可以看到,他幾乎涵蓋了所有流行的語言,而他的執行文件大小只有256kb,太強悍了,讓我非常的佩服。
三、腳本管理
讓編輯軟件支持腳本是必要的,不僅僅可以對常用的功能提供擴展。我實現了類C的解析執行,所以對簡單的計算功能,軟件的功能,都能給外部腳本提供接口函數,讓腳本輕松的操作編輯器,或者做一些好玩的事情。我主要做的是將腳本直接映射到右鍵菜單,當添加一個腳本時,他將直接被添加進右鍵菜單。並且支持多級目錄。
例如,我實現了幾個接口供腳本使用:
int ceditor_exe_2( char * cmd, char * out );
該函數用於執行cmd指令,out為輸出結果。cmd為編輯器的的命令,形如rep_sel$hello world$。
int ceditor_exe_4( char * cmd, char * p1, char *p2, char * out );
該函數效果同ceditor_exe_2,但是cmd僅是命令,p1,p2分別是兩個參數。
int clear();
該函數用於清除輸出框的內容。
int ceditor_hotkey( char * ctrlKeys, int vKey, char * scriptPath );
該函數用於注冊熱鍵。
C的解釋器,大家可以看我以前發過的文章,代碼可以在CSDN上面找到,搜索"xrc C語言解釋器"就能找到,或者試試這個鏈接:http://download.csdn.net/download/linxren/4204728。在cnblogs上可以看看相關的實現方法,算是講得比較清楚的吧。
四、數據存儲
數據存儲在不同的軟件中都必須用到,我這里主要是配置的存儲和腳本的存儲,正好我寫了個key-value存儲系統,所以這個直接拿來用就非常合適了,效率也不錯。跟直接讀寫硬盤沒什么區別,省去了煩人的fopen,fread,fwrite,fclose調用,直接用windows的api更是煩人,所以寫這樣一個簡單的庫,非常方便。
http://www.cnblogs.com/linxr/p/3252541.html,在這里可以看到實現方法和下載到源代碼。我覺得這個簡單的key-value存儲庫,比我寫的解釋器,和這個編輯器本身更加實用,所有的軟件都可以用,接口也很簡單。無法就是open,set,get,close四個函數。省去了文件操作的各種麻煩。