notepad++源码读取(1)--序列化
今天看了一下notepad++的源码,本来想用vs来反向工程生成uml图,但发现得到的是一点多兆的空白文件,无语死。。这样就不能从结构上看notepad++了,只好从winmain.cpp开始查看咯。
winmain函数里,前期都是变量的设置,解析,然后就是一个大大的try……catch,里面包含着一个消息队列的循环。然后。。然后就没然后了,对这个不感什么兴趣就扔了。PS:主框架文件为三个大大的switch……case的NppBigSwitch.cpp文件,Notepad_plus跟Parameters是notepad++里最核心的东西,弄懂了这三个,这软件怎么样的应该都明白了。
“最近打开文件”和“保存会话”这两个功能不是很难,也不会很无聊,从此入手。这两个功能一看就知道是要将信息存储在本地,它们存放在C:\Users\Administrator\AppData\Roaming\Notepad++文件内,一个为config.xml尾部的history标签下,一个为session.xml。(找了半天。。。)
history的结构比较简单,主要是最近打开的文件名,而session.xml则是<mainView activeView="0">记录了最后关闭会话时工作的是第几个子窗口(记住账号用这种格式也可以,记录着最后一个登陆的账号),从0开始算,子标签记录关键的是文件的语言,编码,路径。
文件格式找到了,那么notepad++是通过什么读写的呢?答案是TinyXML,小巧的开源的xml解释器。等晚点再研究其源码。notepad++的文件读写都是通过NppIO.cpp文件(没有头文件,我猜想notepad++(下面简写为npp)没有对应头文件的cpp都是Notepad_plus.h是实现文件),主要用途是打开关闭文件的读写,配置文件的读写。而配置文件的读写就是用TinyXML的,其他文件是用vs内部的东西吧(没看~)。
“最近打开文件”是主要文件是lastRecentFileList,使用一个结构体来存储文件信息,而这又用队列来存储。
struct RecentItem { int _id; //该项是菜单上的id,由id来确定它的位置 generic_string _name; RecentItem(const TCHAR * name) : _name(name) {}; }; typedef std::deque<RecentItem> recentList; //队列来存储信息
class LastRecentFileList { public : LastRecentFileList() : _hasSeparators(false), _size(0), _locked(false) { _userMax = (NppParameters::getInstance())->getNbMaxRecentFile(); }; void initMenu(HMENU hMenu, int idBase, int posBase, bool doSubMenu = false); void switchMode(); void updateMenu(); void add(const TCHAR *fn); //增加新项到_lrfl void remove(const TCHAR *fn); //删除_lrfl元素 void remove(int index); //同上 void clear(); //清空_lrfl void saveLRFL(); //保存_lrfl到config.xml文件内 private: recentList _lrfl; int find(const TCHAR *fn); //查找是否存在该文件 };
而保存会话也是同样的做法,不过更加简单,只用两个接口。
//Parameters.cpp文件 接口不统一,怎能这样~ bool NppParameters::getSessionFromXmlTree(TiXmlDocument *pSessionDoc, Session *pSession) //读 void NppParameters::writeSession(const Session & session, const TCHAR *fileName) //写