目标
排除Notepad(下文简称NP)作者各种言行不谈,Notepad是一个优秀的开源项目,且使用人数众多。本文希望学习Notepad的架构,同时学习其对于C++的使用方式。
学习模块
- 文件管理
- 查找/替换功能
- 消息通知模块
文件管理
从功能上分析,NP每次启动会加载上次未关闭页面,那他是怎么做到的呢。
首先NP设置了两个文件读取路径:1.在个人目录的临时文件;2.在自定义空间的
那如何判定是否存在历史文件,那就得说到Session这个概念。
Session定义如下:
struct Session
{
size_t nbMainFiles() const {return _mainViewFiles.size();};
size_t nbSubFiles() const {return _subViewFiles.size();};
size_t _activeView = 0;
size_t _activeMainIndex = 0;
size_t _activeSubIndex = 0;
bool _includeFileBrowser = false;
generic_string _fileBrowserSelectedItem;
std::vector<sessionFileInfo> _mainViewFiles;
std::vector<sessionFileInfo> _subViewFiles;
std::vector<generic_string> _fileBrowserRoots;
};
其中_mainViewFiles用于存储上次打开文件列表,每个文件打开的位置,这里不细说。
在初始化程序时,找到了Session文件,则说明有未关闭文件,走文件打开流程。
文件的打开
在加载了Session后,就接着进行文件的打开。FileManager主要负责字节流的处理。在FileManager的loadFile函数中进行了文件内容的加载。
打开一个文件首先调用框架执行命令SCI_CREATEDOCUMENT。
if (!doc)
{
doc = (Document)_pscratchTilla->execute(SCI_CREATEDOCUMENT);
ownDoc = true;
}
而后进入文字部分的加载,文字的加载主要在loadFileData函数中进行。
加载文字主要有几个考量:
- 有没有超出缓存范围。NP设置的上限为1MB。
- Scintilla会需要文件大小六分之一的空间作为编辑空间。而NP则将此空间大小限制在1MB
- 语言的设置
- 编码的处理
- 通过fread系统接口进行文件的读取。每次接着上次读取结束的位置继续读取字节;
lenFile = fread(data+incompleteMultibyteChar, 1, blockSize-incompleteMultibyteChar, fp) + incompleteMultibyteChar;
- 文字编码的处理(这块不做介绍)
最后进行字节流的拼接
_pscratchTilla->execute(SCI_APPENDTEXT, lenFile, reinterpret_cast<LPARAM>(data));
以上就是文件加载的大致流程。