├── Makefile
├── README
├── doc
├── SessionMgr.css
└── SessionMgr.html
├── license.txt
├── setenv.cmd
├── src
├── ContextMenu.cpp
├── ContextMenu.h
├── DlgDelete.cpp
├── DlgDelete.h
├── DlgNew.cpp
├── DlgNew.h
├── DlgRename.cpp
├── DlgRename.h
├── DlgSessions.cpp
├── DlgSessions.h
├── DlgSettings.cpp
├── DlgSettings.h
├── DllMain.cpp
├── Menu.cpp
├── Menu.h
├── Properties.cpp
├── Properties.h
├── SessionMgr.cpp
├── SessionMgr.h
├── SessionMgrApi.h
├── Settings.cpp
├── Settings.h
├── System.cpp
├── System.h
├── Util.cpp
├── Util.h
├── npp
│ ├── Notepad_plus_msgs.h
│ ├── PluginInterface.h
│ ├── Scintilla.h
│ └── menuCmdID.h
├── res
│ ├── resource.h
│ ├── resource.rc
│ ├── version.h
│ └── version.rc2
├── utf8
│ ├── checked.h
│ ├── core.h
│ └── unchecked.h
└── xml
│ ├── tinyxml.h
│ ├── tinyxml2.cpp
│ └── tinyxml2.h
└── x.cmd
/Makefile:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------------
2 | # SessionMgr nmake file
3 |
4 | # 1. Check that you have environment variables PATH, INCLUDE and LIB defined.
5 | # 2. Modify "setenv.cmd" with your toolchain paths.
6 | # 3. Open a DOS box in the directory containing this makefile.
7 | # 4. Run setenv, then run nmake.
8 |
9 | PRJ=SessionMgr
10 |
11 | O=obj
12 | S=src
13 | R=src\res
14 | N=src\npp
15 | X=src\xml
16 |
17 | # http://msdn.microsoft.com/en-us/library/fwkeyyhe.aspx
18 | CXX=cl
19 | CXXFLAGS=/O2 /EHs /GR- /MT /nologo /W3 /WX- /Gd /Gm- /Fo$O\ /fp:fast /wd4995 \
20 | /errorReport:none /Zc:wchar_t /DWIN32 /DNDEBUG /D_WINDOWS /D_USRDLL \
21 | /D_WINDLL /DUNICODE /D_UNICODE /c
22 |
23 | # http://msdn.microsoft.com/en-us/library/y0zzbyt4.aspx
24 | LD=link
25 | LIBS=user32.lib shell32.lib
26 | LDFLAGS=/DLL /nologo /OUT:$O\$(PRJ).dll /INCREMENTAL:NO /MANIFEST:NO \
27 | /MACHINE:X86 /ERRORREPORT:NONE
28 |
29 | RC=rc
30 | RCFLAGS=/nologo /fo$O\$(PRJ).res
31 | RESDEPS=$R\resource.rc $R\resource.h $R\version.rc2 $R\version.h
32 | NPPDEPS=$N\PluginInterface.h $N\Scintilla.h $N\Notepad_plus_msgs.h $N\menuCmdID.h
33 |
34 | #-------------------------------------------------------------------------------
35 | # Targets
36 |
37 | default: init $(PRJ)
38 |
39 | init:
40 | if not exist $O\ mkdir $O
41 |
42 | clean:
43 | if exist $O\ del $O\*.obj & del $O\$(PRJ).*
44 |
45 | #-------------------------------------------------------------------------------
46 | # Link obj files to make dll
47 |
48 | $(PRJ): $O\$(PRJ).obj $O\Settings.obj $O\DlgDelete.obj $O\DlgNew.obj $O\DlgRename.obj \
49 | $O\DlgSessions.obj $O\DlgSettings.obj $O\DllMain.obj $O\Menu.obj $O\Properties.obj \
50 | $O\ContextMenu.obj $O\System.obj $O\Util.obj $O\tinyxml2.obj $O\$(PRJ).res
51 | $(LD) $(LDFLAGS) $(LIBS) $?
52 |
53 | #-------------------------------------------------------------------------------
54 | # Compile cpp files
55 |
56 | $O\$(PRJ).obj: $S\$(@B).cpp $S\$(@B).h $(NPPDEPS)
57 | $(CXX) $(CXXFLAGS) %s
58 |
59 | $O\Settings.obj: $S\$(@B).cpp $S\$(@B).h
60 | $(CXX) $(CXXFLAGS) %s
61 |
62 | $O\DlgDelete.obj: $S\$(@B).cpp $S\$(@B).h
63 | $(CXX) $(CXXFLAGS) %s
64 |
65 | $O\DlgNew.obj: $S\$(@B).cpp $S\$(@B).h
66 | $(CXX) $(CXXFLAGS) %s
67 |
68 | $O\DlgRename.obj: $S\$(@B).cpp $S\$(@B).h
69 | $(CXX) $(CXXFLAGS) %s
70 |
71 | $O\DlgSessions.obj: $S\$(@B).cpp $S\$(@B).h
72 | $(CXX) $(CXXFLAGS) %s
73 |
74 | $O\DlgSettings.obj: $S\$(@B).cpp $S\$(@B).h
75 | $(CXX) $(CXXFLAGS) %s
76 |
77 | $O\DllMain.obj: $S\$(@B).cpp
78 | $(CXX) $(CXXFLAGS) %s
79 |
80 | $O\Menu.obj: $S\$(@B).cpp $S\$(@B).h $(NPPDEPS) $(RESDEPS)
81 | $(CXX) $(CXXFLAGS) %s
82 |
83 | $O\Properties.obj: $S\$(@B).cpp $S\$(@B).h
84 | $(CXX) $(CXXFLAGS) %s
85 |
86 | $O\ContextMenu.obj: $S\$(@B).cpp $S\$(@B).h
87 | $(CXX) $(CXXFLAGS) %s
88 |
89 | $O\System.obj: $S\$(@B).cpp $S\$(@B).h $(NPPDEPS)
90 | $(CXX) $(CXXFLAGS) %s
91 |
92 | $O\Util.obj: $S\$(@B).cpp $S\$(@B).h
93 | $(CXX) $(CXXFLAGS) %s
94 |
95 | $O\tinyxml2.obj: $X\$(@B).cpp $X\$(@B).h
96 | $(CXX) $(CXXFLAGS) %s
97 |
98 | #-------------------------------------------------------------------------------
99 | # Compile resource files
100 |
101 | $O\$(PRJ).res: $(RESDEPS)
102 | $(RC) $(RCFLAGS) %s
103 |
104 | #-------------------------------------------------------------------------------
105 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Session Manager
2 | A Plugin for Notepad++
3 | --------------------------------------------------------------------------------
4 |
5 | Project home: http://mfoster.com/npp/
6 | Project source: https://github.com/mike-foster/npp-session-manager
7 | User documentation: http://mfoster.com/npp/SessionMgr.html
8 | Build instructions: See "Makefile"
9 | License: See "license.txt"
10 | Discussion, feedback, bug reports:
11 | https://sourceforge.net/p/notepad-plus/discussion/482781/
12 |
13 |
--------------------------------------------------------------------------------
/doc/SessionMgr.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin:0;
3 | padding:0;
4 | }
5 | html, body {
6 | color: #333;
7 | background-color: #a7a09a;
8 | font-size: small;
9 | font-family: verdana,arial,helvetica,sans-serif;
10 | }
11 | body {
12 | min-width: 950px;
13 | text-align: center; /* to center layout-container in IE6 */
14 | }
15 | p {
16 | margin: 1em 0;
17 | line-height: 1.3em;
18 | }
19 | b {
20 | color:#666;
21 | font-weight: bold;
22 | }
23 | tt {
24 | font-size: small;
25 | font-family: 'courier new',monospace;
26 | }
27 | a {
28 | color:#333;
29 | }
30 | a:link, a:active {
31 | color:#366;
32 | }
33 | a:visited {
34 | color:#333;
35 | }
36 | a:hover {
37 | color: #fff;
38 | background-color: #a7a09a;
39 | text-decoration:none;
40 | }
41 | h1 {
42 | color: #555;
43 | font-size: xx-large;
44 | margin: .5em 0 .2em 0;
45 | }
46 | h2, h3, h4 {
47 | color: #555;
48 | margin: 1.2em 0 .5em 0;
49 | }
50 | h2 {
51 | font-size: x-large;
52 | }
53 | h3 {
54 | font-size: large;
55 | /* text-decoration: underline; */
56 | }
57 | h4 {
58 | font-size: medium;
59 | }
60 | pre {
61 | font-family: 'courier new',monospace;
62 | color: #666;
63 | background: transparent;
64 | border: 1px dotted #a7a09a;
65 | margin: .3em .12em .6em 0;
66 | padding: .6em;
67 | overflow: auto;
68 | font-size: small;
69 | max-height: 32em;
70 | }
71 | ul#contents li {
72 | /* font-size: smaller; */
73 | margin-top: 1px;
74 | margin-bottom: 1px;
75 | }
76 |
77 | .smaller {
78 | font-size: smaller;
79 | }
80 |
81 | #layout-container {
82 | position: relative;
83 | background-color: #eee;
84 | margin: 10px auto;
85 | width: 950px;
86 | text-align: left;
87 | overflow: hidden;
88 | }
89 | #layout-header {
90 | position: relative;
91 | background-color: #eee;
92 | padding: 5px 10px 5px 20px;
93 | }
94 | #layout-header p {
95 | /* font-style: italic; */
96 | font-weight: bold;
97 | /* font-size: smaller; */
98 | }
99 | #layout-hmenu {
100 | /* font-size: smaller; */
101 | position: relative;
102 | left: 1px;
103 | width: 918px;
104 | background-color: #c99;
105 | padding: 5px 10px 5px 20px;
106 | text-align: right;
107 | }
108 | #layout-main-col {
109 | padding: 10px 20px 20px 20px;
110 | background-color: #eee;
111 | overflow: hidden;
112 | }
113 | #layout-main-col ul {
114 | margin-left: 20px;
115 | }
116 | #layout-main-col ul ul {
117 | margin-top: 7px;
118 | }
119 | #layout-main-col ol {
120 | margin-left: 28px;
121 | }
122 | #layout-main-col li {
123 | line-height: 1.3em;
124 | margin-bottom: 7px;
125 | }
126 | #layout-footer {
127 | clear: both;
128 | position: relative;
129 | padding: 5px 20px 5px 20px;
130 | /* font-size: smaller; */
131 | background-color: #eee;
132 | border-top: 1px solid #fff;
133 | text-align: right;
134 | }
135 |
136 | #layout-container,
137 | #layout-header,
138 | #layout-hmenu,
139 | #layout-main-col,
140 | #layout-footer {
141 | -moz-border-radius: 5px;
142 | -webkit-border-radius: 5px;
143 | -khtml-border-radius: 5px;
144 | }
145 |
--------------------------------------------------------------------------------
/setenv.cmd:
--------------------------------------------------------------------------------
1 | :: Set paths for the "include" and "lib" directories of the toolchain and the
2 | :: Windows SDK. Note that "link" has a dependency on "common7\ide\mspdb*.dll".
3 |
4 | set PATH=c:\bin\msvs\vc\bin;c:\program files\microsoft sdks\windows\v7.1\bin;c:\bin\msvs\common7\ide;%PATH%
5 | set INCLUDE=c:\bin\msvs\vc\include;c:\program files\microsoft sdks\windows\v7.1\include;%INCLUDE%
6 | set LIB=c:\bin\msvs\vc\lib;c:\program files\microsoft sdks\windows\v7.1\lib;%LIB%
7 |
--------------------------------------------------------------------------------
/src/ContextMenu.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file ContextMenu.cpp
13 | @copyright Copyright 2014,2015 Michael Foster
14 |
15 | Session Manager creates a submenu in the context (right-click) menu if the
16 | useContextMenu setting is enabled. The submenu is only created or updated
17 | when a change is made to favorite sessions. Notepad++ must be restarted for
18 | the changes to appear in the menus. The menu labels used in the context
19 | submenu are the same as those used in the Plugins menu and favorite sessions
20 | are listed after the About item.
21 | */
22 |
23 | #include "System.h"
24 | #include "ContextMenu.h"
25 | #include "Menu.h"
26 | #include "Util.h"
27 |
28 | //------------------------------------------------------------------------------
29 |
30 | namespace NppPlugin {
31 |
32 | //------------------------------------------------------------------------------
33 |
34 | namespace {
35 |
36 | /// XML nodes
37 | #define XN_NOTEPADPLUS "NotepadPlus" ///< root node
38 | #define XN_SCINTILLACONTEXTMENU "ScintillaContextMenu"
39 | #define XN_ITEM "Item"
40 |
41 | /// XML attributes
42 | #define XA_FOLDERNAME "FolderName"
43 | #define XA_PLUGINENTRYNAME "PluginEntryName"
44 | #define XA_PLUGINCOMMANDITEMNAME "PluginCommandItemName"
45 | #define XA_ITEMNAMEAS "ItemNameAs"
46 | #define XA_ID "id"
47 |
48 | tXmlDocP _pCtxXmlDoc = NULL;
49 | tXmlEleP _pCtxLastFav = NULL;
50 |
51 | tXmlEleP getFavSeparator();
52 | tXmlEleP createContextMenu(tXmlEleP sciCtxMnuEle);
53 | tXmlEleP newItemElement(LPCWSTR itemName = NULL);
54 |
55 | } // end namespace
56 |
57 | //------------------------------------------------------------------------------
58 |
59 | namespace api {
60 |
61 | void ctx_onUnload()
62 | {
63 | ctx::unload();
64 | }
65 |
66 | } // end namespace NppPlugin::api
67 |
68 | //------------------------------------------------------------------------------
69 |
70 | namespace ctx {
71 |
72 | /** Deletes all favorite Item elements. Does not save the file after deleting.
73 | @return a pointer to the separator element preceeding the favorite elements */
74 | void deleteFavorites()
75 | {
76 | tXmlEleP ele, sepEle, favEle, sciCtxMnuEle;
77 |
78 | if (cfg::getBool(kUseContextMenu)) {
79 | LPSTR mbMain = str::utf16ToUtf8(mnu_getMenuLabel());
80 | if (mbMain) {
81 | sepEle = getFavSeparator();
82 | if (sepEle) {
83 | sciCtxMnuEle = sepEle->Parent()->ToElement();
84 | favEle = sepEle->NextSiblingElement(XN_ITEM);
85 | while (favEle && favEle->Attribute(XA_FOLDERNAME, mbMain)) {
86 | ele = favEle;
87 | favEle = favEle->NextSiblingElement(XN_ITEM);
88 | sciCtxMnuEle->DeleteChild(ele);
89 | }
90 | }
91 | sys_free(mbMain);
92 | }
93 | _pCtxLastFav = NULL;
94 | }
95 | }
96 |
97 | /** Adds a new favorite element in NPP's contextMenu.xml file. Does not save the file. */
98 | void addFavorite(LPCWSTR favName)
99 | {
100 | tXmlEleP sepEle, favEle, sciCtxMnuEle;
101 |
102 | if (cfg::getBool(kUseContextMenu)) {
103 | if (!_pCtxLastFav) {
104 | sepEle = getFavSeparator();
105 | if (sepEle) {
106 | favEle = newItemElement(favName);
107 | sciCtxMnuEle = sepEle->Parent()->ToElement();
108 | sciCtxMnuEle->InsertAfterChild(sepEle, favEle);
109 | _pCtxLastFav = favEle;
110 | }
111 | }
112 | else {
113 | favEle = newItemElement(favName);
114 | sciCtxMnuEle = _pCtxLastFav->Parent()->ToElement();
115 | sciCtxMnuEle->InsertAfterChild(_pCtxLastFav, favEle);
116 | _pCtxLastFav = favEle;
117 | }
118 | }
119 | }
120 |
121 | void saveContextMenu()
122 | {
123 | DWORD lastErr;
124 | tXmlError xmlErr;
125 |
126 | if (cfg::getBool(kUseContextMenu)) {
127 | if (_pCtxXmlDoc) {
128 | xmlErr = _pCtxXmlDoc->SaveFile(sys_getNppCtxMnuFile());
129 | if (xmlErr != kXmlSuccess) {
130 | lastErr = ::GetLastError();
131 | msg::error(lastErr, L"%s: Error %u saving the context menu file.", _W(__FUNCTION__), xmlErr);
132 | }
133 | }
134 | }
135 | }
136 |
137 | void unload()
138 | {
139 | if (_pCtxXmlDoc) {
140 | delete _pCtxXmlDoc;
141 | _pCtxXmlDoc = NULL;
142 | }
143 | }
144 |
145 | } // end namespace NppPlugin::ctx
146 |
147 | //------------------------------------------------------------------------------
148 |
149 | namespace {
150 |
151 | /** Creates the entire context menu if it is not found. Saves the file if any
152 | changes are made.
153 | @return a pointer to the separator element preceeding the favorite elements */
154 | tXmlEleP getFavSeparator()
155 | {
156 | DWORD lastErr;
157 | tXmlError xmlErr;
158 | bool changed = false;
159 | tXmlEleP sepEle = NULL;
160 | LPSTR mbMain, mbAbout;
161 |
162 | // Load the contextMenu file if not already loaded
163 | if (!_pCtxXmlDoc) {
164 | _pCtxXmlDoc = new tinyxml2::XMLDocument();
165 | xmlErr = _pCtxXmlDoc->LoadFile(sys_getNppCtxMnuFile());
166 | if (xmlErr != kXmlSuccess) {
167 | lastErr = ::GetLastError();
168 | msg::error(lastErr, L"%s: Error %u loading the context menu file.", _W(__FUNCTION__), xmlErr);
169 | return NULL;
170 | }
171 | }
172 | tXmlEleP sciCtxMnuEle, itemEle;
173 | tXmlHnd ctxDocHnd(_pCtxXmlDoc);
174 | sciCtxMnuEle = ctxDocHnd.FirstChildElement(XN_NOTEPADPLUS).FirstChildElement(XN_SCINTILLACONTEXTMENU).ToElement();
175 |
176 | // the main menu item label
177 | mbMain = str::utf16ToUtf8(mnu_getMenuLabel());
178 | // the About item label
179 | mbAbout = str::utf16ToUtf8(mnu_getMenuLabel(MNU_BASE_MAX_ITEMS - 1));
180 | if (mbMain && mbAbout) {
181 | // Iterate over the Item elements looking for our About item
182 | itemEle = sciCtxMnuEle->FirstChildElement(XN_ITEM);
183 | while (itemEle) {
184 | if (itemEle->Attribute(XA_FOLDERNAME, mbMain) && itemEle->Attribute(XA_ITEMNAMEAS, mbAbout)) {
185 | break; // found it
186 | }
187 | itemEle = itemEle->NextSiblingElement(XN_ITEM);
188 | }
189 | if (!itemEle) { // not found so need to create our entire context menu
190 | sepEle = createContextMenu(sciCtxMnuEle);
191 | changed = true;
192 | }
193 | else { // found it so check if a separator follows it, if not then add it
194 | sepEle = itemEle->NextSiblingElement(XN_ITEM);
195 | if (!sepEle->Attribute(XA_FOLDERNAME, mbMain) || !sepEle->Attribute(XA_ID, "0")) {
196 | sepEle = newItemElement();
197 | sciCtxMnuEle->InsertAfterChild(itemEle, sepEle);
198 | changed = true;
199 | }
200 | }
201 | if (changed) {
202 | ctx::saveContextMenu();
203 | }
204 | sys_free(mbMain);
205 | sys_free(mbAbout);
206 | }
207 |
208 | return sepEle;
209 | }
210 |
211 | /** Creates our context menu. Does not save the file.
212 | @return a pointer to the separator element preceeding the favorite elements */
213 | tXmlEleP createContextMenu(tXmlEleP sciCtxMnuEle)
214 | {
215 | tXmlEleP ele;
216 |
217 | for (INT mnuIdx = 0; mnuIdx < MNU_BASE_MAX_ITEMS; ++mnuIdx) {
218 | ele = newItemElement(mnuIdx == 4 ? NULL : mnu_getMenuLabel(mnuIdx));
219 | sciCtxMnuEle->InsertEndChild(ele);
220 | }
221 | // the separator preceeding the favorites
222 | ele = newItemElement();
223 | sciCtxMnuEle->InsertEndChild(ele);
224 |
225 | return ele;
226 | }
227 |
228 | /** @return a new Item element */
229 | tXmlEleP newItemElement(LPCWSTR itemName)
230 | {
231 | tXmlEleP ele = NULL;
232 |
233 | LPSTR mbMain = str::utf16ToUtf8(mnu_getMenuLabel());
234 | if (mbMain) {
235 | ele = _pCtxXmlDoc->NewElement(XN_ITEM);
236 | ele->SetAttribute(XA_FOLDERNAME, mbMain);
237 | if (!itemName) { // separator
238 | ele->SetAttribute(XA_ID, "0");
239 | }
240 | else {
241 | CHAR mbMainNoAmp[MNU_MAX_NAME_LEN], mbBufNoAmp[MNU_MAX_NAME_LEN];
242 | LPSTR mbBuf = str::utf16ToUtf8(itemName);
243 | if (mbBuf) {
244 | str::removeAmp(mbMain, mbMainNoAmp);
245 | str::removeAmp(mbBuf, mbBufNoAmp);
246 | ele->SetAttribute(XA_PLUGINENTRYNAME, mbMainNoAmp);
247 | ele->SetAttribute(XA_ITEMNAMEAS, mbBuf);
248 | ele->SetAttribute(XA_PLUGINCOMMANDITEMNAME, mbBufNoAmp);
249 | sys_free(mbBuf);
250 | }
251 | }
252 | sys_free(mbMain);
253 | }
254 |
255 | return ele;
256 | }
257 |
258 | } // end namespace
259 |
260 | } // end namespace NppPlugin
261 |
--------------------------------------------------------------------------------
/src/ContextMenu.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file ContextMenu.h
13 | @copyright Copyright 2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_CONTEXTMENU_H
17 | #define NPP_PLUGIN_CONTEXTMENU_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | //------------------------------------------------------------------------------
24 | /// @namespace NppPlugin::api Contains functions called only from DllMain.
25 |
26 | namespace api {
27 |
28 | void ctx_onUnload();
29 |
30 | } // end namespace NppPlugin::api
31 |
32 | //------------------------------------------------------------------------------
33 | /** @namespace NppPlugin::ctx Contains functions for creating the context menu
34 | items and managing the favorites there. */
35 |
36 | namespace ctx {
37 |
38 | void deleteFavorites();
39 | void addFavorite(LPCWSTR favName);
40 | void saveContextMenu();
41 | void unload();
42 |
43 | } // end namespace NppPlugin::ctx
44 |
45 | } // end namespace NppPlugin
46 |
47 | #endif // NPP_PLUGIN_CONTEXTMENU_H
48 |
--------------------------------------------------------------------------------
/src/DlgDelete.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgDelete.cpp
13 | @copyright Copyright 2011,2013-2015 Michael Foster
14 |
15 | The "Delete Session" dialog.
16 | */
17 |
18 | #include "System.h"
19 | #include "SessionMgr.h"
20 | #include "DlgSessions.h"
21 | #include "DlgDelete.h"
22 | #include "Util.h"
23 | #include "res\resource.h"
24 | #include
25 |
26 | //------------------------------------------------------------------------------
27 |
28 | namespace NppPlugin {
29 |
30 | //------------------------------------------------------------------------------
31 |
32 | namespace {
33 |
34 | ChildDialogData *_dialogData;
35 |
36 | void onInit(HWND hDlg);
37 | bool onOk(HWND hDlg);
38 |
39 | } // end namespace
40 |
41 | //------------------------------------------------------------------------------
42 |
43 | INT_PTR CALLBACK dlgDel_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
44 | {
45 | INT_PTR status = FALSE;
46 |
47 | if (uMessage == WM_COMMAND) {
48 | switch (LOWORD(wParam)) {
49 |
50 | case IDOK:
51 | if (onOk(hDlg)) {
52 | ::EndDialog(hDlg, 1);
53 | status = TRUE;
54 | }
55 | break;
56 |
57 | case IDCANCEL:
58 | ::EndDialog(hDlg, 0);
59 | status = TRUE;
60 | break;
61 | }
62 | }
63 | else if (uMessage == WM_INITDIALOG) {
64 | _dialogData = (ChildDialogData*)lParam;
65 | onInit(hDlg);
66 | }
67 |
68 | return status;
69 | }
70 |
71 | //------------------------------------------------------------------------------
72 |
73 | namespace {
74 |
75 | void onInit(HWND hDlg)
76 | {
77 | dlg::focus(hDlg, IDOK);
78 | dlg::centerWnd(hDlg, NULL, 150, -5);
79 | ::ShowWindow(hDlg, SW_SHOW);
80 | }
81 |
82 | bool onOk(HWND hDlg)
83 | {
84 | WCHAR sesPth[MAX_PATH];
85 | if (app_isValidSessionIndex(_dialogData->selectedSessionIndex)) {
86 | app_getSessionFile(_dialogData->selectedSessionIndex, sesPth);
87 | if (::DeleteFileW(sesPth)) {
88 | return true;
89 | }
90 | else {
91 | DWORD le = ::GetLastError();
92 | msg::error(le, L"%s: Error deleting \"%s\".", _W(__FUNCTION__), sesPth);
93 | }
94 | }
95 | return false;
96 | }
97 |
98 | } // end namespace
99 |
100 | } // end namespace NppPlugin
101 |
--------------------------------------------------------------------------------
/src/DlgDelete.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgDelete.h
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_DLGDELETE_H
17 | #define NPP_PLUGIN_DLGDELETE_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | INT_PTR CALLBACK dlgDel_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
24 |
25 | } // end namespace NppPlugin
26 |
27 | #endif // NPP_PLUGIN_DLGDELETE_H
28 |
--------------------------------------------------------------------------------
/src/DlgNew.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgNew.cpp
13 | @copyright Copyright 2011-2015 Michael Foster
14 |
15 | The "New Session" dialog.
16 | */
17 |
18 | #include "System.h"
19 | #include "SessionMgr.h"
20 | #include "DlgSessions.h"
21 | #include "DlgNew.h"
22 | #include "Util.h"
23 | #include "res\resource.h"
24 | #include
25 |
26 | //------------------------------------------------------------------------------
27 |
28 | namespace NppPlugin {
29 |
30 | //------------------------------------------------------------------------------
31 |
32 | namespace {
33 |
34 | ChildDialogData *_dialogData;
35 |
36 | void onInit(HWND hDlg);
37 | bool onOk(HWND hDlg);
38 | bool newAsEmpty(LPWSTR dstPathname);
39 | bool newFromOpen(LPWSTR dstPathname);
40 | bool newByCopy(LPWSTR dstPathname);
41 |
42 | } // end namespace
43 |
44 | //------------------------------------------------------------------------------
45 |
46 | INT_PTR CALLBACK dlgNew_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
47 | {
48 | INT_PTR status = FALSE;
49 |
50 | if (uMessage == WM_COMMAND) {
51 | switch (LOWORD(wParam)) {
52 |
53 | case IDOK:
54 | if (onOk(hDlg)) {
55 | ::EndDialog(hDlg, 1);
56 | status = TRUE;
57 | }
58 | break;
59 |
60 | case IDCANCEL:
61 | ::EndDialog(hDlg, 0);
62 | status = TRUE;
63 | break;
64 |
65 | case IDC_NEW_RAD_EMPTY:
66 | case IDC_NEW_RAD_OPEN:
67 | case IDC_NEW_RAD_COPY:
68 | if (HIWORD(wParam) == BN_CLICKED) {
69 | WCHAR buf[SES_NAME_BUF_LEN];
70 | buf[0] = 0;
71 | dlg::getText(hDlg, IDC_NEW_ETX_NAME, buf, SES_NAME_BUF_LEN);
72 | if (buf[0] == 0) {
73 | dlg::setText(hDlg, IDC_NEW_ETX_NAME, app_getSessionName(_dialogData->selectedSessionIndex));
74 | }
75 | dlg::focus(hDlg, IDC_NEW_ETX_NAME, false);
76 | status = TRUE;
77 | }
78 | break;
79 | }
80 | }
81 | else if (uMessage == WM_INITDIALOG) {
82 | _dialogData = (ChildDialogData*)lParam;
83 | onInit(hDlg);
84 | }
85 |
86 | return status;
87 | }
88 |
89 | //------------------------------------------------------------------------------
90 |
91 | namespace {
92 |
93 | void onInit(HWND hDlg)
94 | {
95 | dlg::setCheck(hDlg, IDC_NEW_RAD_EMPTY, true);
96 | dlg::focus(hDlg, IDC_NEW_ETX_NAME);
97 | dlg::centerWnd(hDlg, NULL, 150, -40);
98 | ::ShowWindow(hDlg, SW_SHOW);
99 | }
100 |
101 | bool onOk(HWND hDlg)
102 | {
103 | bool succ;
104 | WCHAR newName[SES_NAME_BUF_LEN];
105 | WCHAR dstPathname[MAX_PATH];
106 |
107 | // Set the destination file pathname.
108 | newName[0] = 0;
109 | dlg::getText(hDlg, IDC_NEW_ETX_NAME, newName, SES_NAME_BUF_LEN);
110 | if (newName[0] == 0) {
111 | msg::show(L"Missing file name.", M_WARN);
112 | return false;
113 | }
114 | ::StringCchCopyW(dstPathname, MAX_PATH, cfg::getStr(kSessionDirectory));
115 | ::StringCchCatW(dstPathname, MAX_PATH, newName);
116 | ::StringCchCatW(dstPathname, MAX_PATH, cfg::getStr(kSessionExtension));
117 |
118 | if (dlg::getCheck(hDlg, IDC_NEW_RAD_EMPTY)) {
119 | succ = newAsEmpty(dstPathname);
120 | }
121 | else if (dlg::getCheck(hDlg, IDC_NEW_RAD_OPEN)) {
122 | succ = newFromOpen(dstPathname);
123 | }
124 | else {
125 | succ = newByCopy(dstPathname);
126 | }
127 | if (succ) {
128 | ::StringCchCopyW(_dialogData->newSessionName, SES_NAME_BUF_LEN, newName);
129 | }
130 | return succ;
131 | }
132 |
133 | /** Creates a new, empty session. */
134 | bool newAsEmpty(LPWSTR dstPathname)
135 | {
136 | pth::createFileIfMissing(dstPathname, SES_DEFAULT_CONTENTS);
137 | return true;
138 | }
139 |
140 | /** Creates a new session containing the currently open files. */
141 | bool newFromOpen(LPWSTR dstPathname)
142 | {
143 | ::SendMessage(sys_getNppHandle(), NPPM_SAVECURRENTSESSION, 0, (LPARAM)dstPathname);
144 | return true;
145 | }
146 |
147 | /** Creates a new session by copying the selected session. */
148 | bool newByCopy(LPWSTR dstPathname)
149 | {
150 | bool status = false;
151 | WCHAR srcPathname[MAX_PATH];
152 |
153 | // Set the source file pathname.
154 | app_getSessionFile(_dialogData->selectedSessionIndex, srcPathname);
155 | // Copy the file.
156 | _dialogData->newSessionName[0] = 0;
157 | if (::CopyFileW(srcPathname, dstPathname, TRUE)) {
158 | status = true;
159 | }
160 | else {
161 | DWORD le = ::GetLastError();
162 | msg::error(le, L"%s: Error copying from \"%s\" to \"%s\".", _W(__FUNCTION__), srcPathname, dstPathname);
163 | }
164 | return status;
165 | }
166 |
167 | } // end namespace
168 |
169 | } // end namespace NppPlugin
170 |
--------------------------------------------------------------------------------
/src/DlgNew.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgNew.h
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_DLGNEW_H
17 | #define NPP_PLUGIN_DLGNEW_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | INT_PTR CALLBACK dlgNew_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
24 |
25 | } // end namespace NppPlugin
26 |
27 | #endif // NPP_PLUGIN_DLGNEW_H
28 |
--------------------------------------------------------------------------------
/src/DlgRename.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgRename.cpp
13 | @copyright Copyright 2011-2015 Michael Foster
14 |
15 | The "Rename Session" dialog.
16 | */
17 |
18 | #include "System.h"
19 | #include "SessionMgr.h"
20 | #include "DlgSessions.h"
21 | #include "DlgRename.h"
22 | #include "Util.h"
23 | #include "res\resource.h"
24 | #include
25 |
26 | //------------------------------------------------------------------------------
27 |
28 | namespace NppPlugin {
29 |
30 | //------------------------------------------------------------------------------
31 |
32 | namespace {
33 |
34 | ChildDialogData *_dialogData;
35 |
36 | void onInit(HWND hDlg);
37 | bool onOk(HWND hDlg);
38 |
39 | } // end namespace
40 |
41 | //------------------------------------------------------------------------------
42 |
43 | INT_PTR CALLBACK dlgRen_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
44 | {
45 | INT_PTR status = FALSE;
46 |
47 | if (uMessage == WM_COMMAND) {
48 | switch (LOWORD(wParam)) {
49 |
50 | case IDOK:
51 | if (onOk(hDlg)) {
52 | ::EndDialog(hDlg, 1);
53 | status = TRUE;
54 | }
55 | break;
56 |
57 | case IDCANCEL:
58 | ::EndDialog(hDlg, 0);
59 | status = TRUE;
60 | break;
61 | }
62 | }
63 | else if (uMessage == WM_INITDIALOG) {
64 | _dialogData = (ChildDialogData*)lParam;
65 | onInit(hDlg);
66 | }
67 |
68 | return status;
69 | }
70 |
71 | //------------------------------------------------------------------------------
72 |
73 | namespace {
74 |
75 | void onInit(HWND hDlg)
76 | {
77 | dlg::setText(hDlg, IDC_REN_ETX_NAME, app_getSessionName(_dialogData->selectedSessionIndex));
78 | dlg::focus(hDlg, IDC_REN_ETX_NAME);
79 | dlg::centerWnd(hDlg, NULL, 150, -35);
80 | ::ShowWindow(hDlg, SW_SHOW);
81 | }
82 |
83 | bool onOk(HWND hDlg)
84 | {
85 | bool status = false;
86 | WCHAR srcPathname[MAX_PATH];
87 | WCHAR dstPathname[MAX_PATH];
88 | WCHAR newName[SES_NAME_BUF_LEN];
89 |
90 | // Set the destination file pathname.
91 | newName[0] = 0;
92 | dlg::getText(hDlg, IDC_REN_ETX_NAME, newName, SES_NAME_BUF_LEN);
93 | if (newName[0] == 0) {
94 | msg::show(L"Missing file name.", M_WARN);
95 | return false;
96 | }
97 | ::StringCchCopyW(dstPathname, MAX_PATH, cfg::getStr(kSessionDirectory));
98 | ::StringCchCatW(dstPathname, MAX_PATH, newName);
99 | ::StringCchCatW(dstPathname, MAX_PATH, cfg::getStr(kSessionExtension));
100 |
101 | // Set the source file that will be renamed.
102 | app_getSessionFile(_dialogData->selectedSessionIndex, srcPathname);
103 |
104 | // Rename the file.
105 | _dialogData->newSessionName[0] = 0;
106 | if (::MoveFileExW(srcPathname, dstPathname, 0)) {
107 | ::StringCchCopyW(_dialogData->newSessionName, SES_NAME_BUF_LEN, newName);
108 | status = true;
109 | }
110 | else {
111 | DWORD le = ::GetLastError();
112 | msg::error(le, L"%s: Error renaming from \"%s\" to \"%s\".", _W(__FUNCTION__), srcPathname, dstPathname);
113 | }
114 |
115 | return status;
116 | }
117 |
118 | } // end namespace
119 |
120 | } // end namespace NppPlugin
121 |
--------------------------------------------------------------------------------
/src/DlgRename.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgRename.h
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_DLGRENAME_H
17 | #define NPP_PLUGIN_DLGRENAME_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | INT_PTR CALLBACK dlgRen_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
24 |
25 | } // end namespace NppPlugin
26 |
27 | #endif // NPP_PLUGIN_DLGRENAME_H
28 |
--------------------------------------------------------------------------------
/src/DlgSessions.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgSessions.h
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_DLGSESSIONS_H
17 | #define NPP_PLUGIN_DLGSESSIONS_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | typedef struct ChildDialogData_tag {
24 | INT selectedSessionIndex; ///< passed to child
25 | WCHAR newSessionName[SES_NAME_BUF_LEN]; ///< returned from child
26 | } ChildDialogData;
27 |
28 | INT_PTR CALLBACK dlgSes_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
29 |
30 | } // end namespace NppPlugin
31 |
32 | #endif // NPP_PLUGIN_DLGSESSIONS_H
33 |
--------------------------------------------------------------------------------
/src/DlgSettings.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgSettings.cpp
13 | @copyright Copyright 2011-2015 Michael Foster
14 |
15 | The "Settings" dialog.
16 | */
17 |
18 | #include "System.h"
19 | #include "SessionMgr.h"
20 | #include "DlgSettings.h"
21 | #include "Util.h"
22 | #include "ContextMenu.h"
23 | #include "res\resource.h"
24 | #include
25 | #include
26 |
27 | //------------------------------------------------------------------------------
28 |
29 | namespace NppPlugin {
30 |
31 | //------------------------------------------------------------------------------
32 |
33 | namespace {
34 |
35 | INT _minWidth = 0, _minHeight = 0;
36 | bool _inInit, _opChanged, _dirChanged;
37 |
38 | void onInit(HWND hDlg);
39 | void closeDialog(HWND hDlg, INT_PTR nResult);
40 | INT onOk(HWND hDlg);
41 | void onResize(HWND hDlg, INT w = 0, INT h = 0);
42 | void onGetMinSize(HWND hDlg, LPMINMAXINFO p);
43 | bool getFolderName(HWND parent, LPWSTR buf);
44 |
45 | } // end namespace
46 |
47 | //------------------------------------------------------------------------------
48 |
49 | INT_PTR CALLBACK dlgCfg_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
50 | {
51 | INT okStatus;
52 | INT_PTR status = FALSE;
53 |
54 | if (uMessage == WM_COMMAND) {
55 | WORD ctrl = LOWORD(wParam);
56 | WORD ntfy = HIWORD(wParam);
57 | switch (ctrl) {
58 | case IDOK:
59 | okStatus = onOk(hDlg);
60 | if (okStatus == 2) {
61 | msg::show(L"An error occurred while creating the new session directory.\nThis setting was not changed.", M_WARN);
62 | }
63 | closeDialog(hDlg, 1);
64 | status = TRUE;
65 | break;
66 | case IDCANCEL:
67 | closeDialog(hDlg, 0);
68 | status = TRUE;
69 | break;
70 | case IDC_CFG_CHK_ASV:
71 | case IDC_CFG_CHK_ALD:
72 | case IDC_CFG_CHK_LIC:
73 | case IDC_CFG_CHK_LWC:
74 | case IDC_CFG_CHK_SITB:
75 | case IDC_CFG_CHK_SISB:
76 | case IDC_CFG_CHK_GBKM:
77 | if (!_inInit && ntfy == BN_CLICKED) {
78 | _opChanged = true;
79 | }
80 | status = TRUE;
81 | break;
82 | case IDC_CFG_CHK_CTXM:
83 | if (!_inInit && ntfy == BN_CLICKED) {
84 | _opChanged = true;
85 | if (cfg::getBool(kUseContextMenu) && !dlg::getCheck(hDlg, IDC_CFG_CHK_CTXM)) {
86 | ctx::unload();
87 | }
88 | }
89 | status = TRUE;
90 | break;
91 | case IDC_CFG_ETX_DIR:
92 | case IDC_CFG_ETX_EXT:
93 | if (!_inInit && ntfy == EN_CHANGE) {
94 | _dirChanged = true;
95 | }
96 | status = TRUE;
97 | break;
98 | case IDC_CFG_BTN_BRW:
99 | if (!_inInit && ntfy == BN_CLICKED) {
100 | WCHAR pthBuf[MAX_PATH];
101 | if (getFolderName(hDlg, pthBuf)) {
102 | _dirChanged = true;
103 | dlg::setText(hDlg, IDC_CFG_ETX_DIR, pthBuf);
104 | }
105 | }
106 | status = TRUE;
107 | break;
108 | } // end switch
109 | }
110 | else if (uMessage == WM_WINDOWPOSCHANGED) {
111 | LPWINDOWPOS wp = (LPWINDOWPOS)lParam;
112 | if (!(wp->flags & SWP_NOSIZE)) {
113 | onResize(hDlg);
114 | }
115 | }
116 | else if (uMessage == WM_GETMINMAXINFO) {
117 | onGetMinSize(hDlg, (LPMINMAXINFO)lParam);
118 | }
119 | else if (uMessage == WM_INITDIALOG) {
120 | onInit(hDlg);
121 | }
122 |
123 | return status;
124 | }
125 |
126 | //------------------------------------------------------------------------------
127 |
128 | namespace {
129 |
130 | /** Determines minimum dialog size. Populates controls with current values from
131 | settings. Resizes, centers and displays the dialog window. */
132 | void onInit(HWND hDlg)
133 | {
134 | RECT r;
135 |
136 | LOG("Opening settings dialog.");
137 | _inInit = true;
138 | _opChanged = false;
139 | _dirChanged = false;
140 | if (_minWidth == 0) {
141 | ::GetWindowRect(hDlg, &r);
142 | _minWidth = r.right - r.left;
143 | _minHeight = r.bottom - r.top;
144 | }
145 | // init control values
146 | dlg::setCheck(hDlg, IDC_CFG_CHK_ASV, cfg::getBool(kAutomaticSave));
147 | dlg::setCheck(hDlg, IDC_CFG_CHK_ALD, cfg::getBool(kAutomaticLoad));
148 | dlg::setCheck(hDlg, IDC_CFG_CHK_LIC, cfg::getBool(kLoadIntoCurrent));
149 | dlg::setCheck(hDlg, IDC_CFG_CHK_LWC, cfg::getBool(kLoadWithoutClosing));
150 | dlg::setCheck(hDlg, IDC_CFG_CHK_SITB, cfg::getBool(kShowInTitlebar));
151 | dlg::setCheck(hDlg, IDC_CFG_CHK_SISB, cfg::getBool(kShowInStatusbar));
152 | dlg::setCheck(hDlg, IDC_CFG_CHK_GBKM, cfg::getBool(kUseGlobalProperties));
153 | dlg::setCheck(hDlg, IDC_CFG_CHK_CTXM, cfg::getBool(kUseContextMenu));
154 | dlg::setText(hDlg, IDC_CFG_ETX_DIR, cfg::getStr(kSessionDirectory));
155 | dlg::setText(hDlg, IDC_CFG_ETX_EXT, cfg::getStr(kSessionExtension));
156 | // focus the first edit control
157 | dlg::focus(hDlg, IDC_CFG_ETX_DIR);
158 | // resize, center and show the window
159 | INT w = cfg::getInt(kSettingsDialogWidth), h = cfg::getInt(kSettingsDialogHeight);
160 | if (w <= 0 || h <= 0) {
161 | w = 0;
162 | h = 0;
163 | }
164 | dlg::centerWnd(hDlg, sys_getNppHandle(), 0, 0, w, h, true);
165 | onResize(hDlg);
166 | ::ShowWindow(hDlg, SW_SHOW);
167 | _inInit = false;
168 | }
169 |
170 | void closeDialog(HWND hDlg, INT_PTR nResult)
171 | {
172 | LOG("Closing settings dialog with %u.", nResult);
173 | ::EndDialog(hDlg, nResult);
174 | }
175 |
176 | /** Gets values, if changed, from dialog box controls. Updates the global
177 | config object and save them to the ini file. */
178 | INT onOk(HWND hDlg)
179 | {
180 | INT stat = 0;
181 | bool change = false;
182 | WCHAR buf[MAX_PATH];
183 |
184 | if (_opChanged) {
185 | change = true;
186 | cfg::putBool(kAutomaticSave, dlg::getCheck(hDlg, IDC_CFG_CHK_ASV));
187 | cfg::putBool(kAutomaticLoad, dlg::getCheck(hDlg, IDC_CFG_CHK_ALD));
188 | cfg::putBool(kLoadIntoCurrent, dlg::getCheck(hDlg, IDC_CFG_CHK_LIC));
189 | cfg::putBool(kLoadWithoutClosing, dlg::getCheck(hDlg, IDC_CFG_CHK_LWC));
190 | cfg::putBool(kShowInTitlebar, dlg::getCheck(hDlg, IDC_CFG_CHK_SITB));
191 | cfg::putBool(kShowInStatusbar, dlg::getCheck(hDlg, IDC_CFG_CHK_SISB));
192 | cfg::putBool(kUseGlobalProperties, dlg::getCheck(hDlg, IDC_CFG_CHK_GBKM));
193 | cfg::putBool(kUseContextMenu, dlg::getCheck(hDlg, IDC_CFG_CHK_CTXM));
194 | }
195 | if (_dirChanged) {
196 | change = true;
197 | dlg::getText(hDlg, IDC_CFG_ETX_DIR, buf, MAX_PATH);
198 | if (!cfg::setSessionDirectory(buf)) {
199 | stat = 2; // error creating ses dir
200 | }
201 | dlg::getText(hDlg, IDC_CFG_ETX_EXT, buf, MAX_PATH);
202 | cfg::setSessionExtension(buf);
203 | }
204 |
205 | if (change) {
206 | cfg::saveSettings();
207 | if (_dirChanged) {
208 | app_readSessionDirectory();
209 | }
210 | }
211 | else {
212 | stat = 1; // no changes
213 | }
214 |
215 | return stat;
216 | }
217 |
218 | /** Resizes and repositions dialog controls. */
219 | void onResize(HWND hDlg, INT dlgW, INT dlgH)
220 | {
221 | RECT r;
222 |
223 | if (dlgW == 0) {
224 | ::GetClientRect(hDlg, &r);
225 | dlgW = r.right;
226 | dlgH = r.bottom;
227 | }
228 | // Resize the Directory and Extension edit boxes
229 | dlg::adjToEdge(hDlg, IDC_CFG_ETX_DIR, dlgW, dlgH, 4, IDC_CFG_ETX_WRO, 0);
230 | dlg::adjToEdge(hDlg, IDC_CFG_ETX_EXT, dlgW, dlgH, 4, IDC_CFG_ETX_WRO, 0);
231 | // Move the OK and Cancel buttons
232 | dlg::adjToEdge(hDlg, IDOK, dlgW, dlgH, 1|2, IDC_CFG_BTN_OK_XRO, IDC_CFG_BTN_YBO);
233 | dlg::adjToEdge(hDlg, IDCANCEL, dlgW, dlgH, 1|2, IDC_CFG_BTN_CAN_XRO, IDC_CFG_BTN_YBO, true);
234 | // Save new dialog size
235 | ::GetWindowRect(hDlg, &r);
236 | cfg::putInt(kSettingsDialogWidth, r.right - r.left);
237 | cfg::putInt(kSettingsDialogHeight, r.bottom - r.top);
238 | }
239 |
240 | /** Sets the minimum size the user can resize to. */
241 | void onGetMinSize(HWND hDlg, LPMINMAXINFO p)
242 | {
243 | p->ptMinTrackSize.x = _minWidth;
244 | p->ptMinTrackSize.y = _minHeight;
245 | }
246 |
247 | /** Copied and slightly modifed from: npp.6.2.3.src\PowerEditor\src\MISC\Common\Common.cpp */
248 | bool getFolderName(HWND parent, LPWSTR buf)
249 | {
250 | bool ok = false;
251 | LPMALLOC pShellMalloc = 0;
252 |
253 | if (::SHGetMalloc(&pShellMalloc) == NO_ERROR) {
254 | BROWSEINFOW info;
255 | ::memset(&info, 0, sizeof(info));
256 | info.hwndOwner = parent;
257 | info.pidlRoot = NULL;
258 | WCHAR displayName[MAX_PATH];
259 | info.pszDisplayName = displayName;
260 | info.lpszTitle = L"Select a sessions folder";
261 | info.ulFlags = BIF_NEWDIALOGSTYLE;
262 | LPITEMIDLIST pidl = ::SHBrowseForFolderW(&info);
263 | // pidl will be null if they cancel the browse dialog, else not null if they select a folder.
264 | if (pidl) {
265 | if (::SHGetPathFromIDListW(pidl, buf)) {
266 | ok = true;
267 | }
268 | pShellMalloc->Free(pidl);
269 | }
270 | pShellMalloc->Release();
271 | }
272 | return ok;
273 | }
274 |
275 | } // end namespace
276 |
277 | } // end namespace NppPlugin
278 |
--------------------------------------------------------------------------------
/src/DlgSettings.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DlgSettings.h
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_DLGSETTINGS_H
17 | #define NPP_PLUGIN_DLGSETTINGS_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | INT_PTR CALLBACK dlgCfg_msgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
24 |
25 | } // end namespace NppPlugin
26 |
27 | #endif // NPP_PLUGIN_DLGSETTINGS_H
28 |
--------------------------------------------------------------------------------
/src/DllMain.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file DllMain.cpp
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 |
15 | The DLL entry point.
16 | */
17 |
18 | #include "System.h"
19 | #include "SessionMgr.h"
20 | #include "Menu.h"
21 | #include "Settings.h"
22 | #include "Properties.h"
23 | #include "ContextMenu.h"
24 |
25 | using namespace NppPlugin::api;
26 |
27 | //------------------------------------------------------------------------------
28 |
29 | namespace {
30 |
31 | INT _dllCount = 0;
32 |
33 | } // end namespace
34 |
35 | //------------------------------------------------------------------------------
36 |
37 | BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
38 | {
39 | switch (dwReason) {
40 | case DLL_PROCESS_ATTACH:
41 | if (++_dllCount == 1) {
42 | sys_onLoad(hInstance);
43 | app_onLoad();
44 | mnu_onLoad();
45 | }
46 | break;
47 | case DLL_PROCESS_DETACH:
48 | if (--_dllCount == 0) {
49 | ctx_onUnload();
50 | mnu_onUnload();
51 | app_onUnload();
52 | cfg_onUnload();
53 | sys_onUnload();
54 | }
55 | break;
56 | }
57 |
58 | return TRUE;
59 | }
60 |
61 | extern "C" __declspec(dllexport) void setInfo(NppData nppd)
62 | {
63 | sys_init(nppd);
64 | app_init();
65 | mnu_init();
66 | prp_init();
67 | }
68 |
69 | extern "C" __declspec(dllexport) LPCWSTR getName()
70 | {
71 | return app_getName();
72 | }
73 |
74 | extern "C" __declspec(dllexport) FuncItem* getFuncsArray(INT *pnbFuncItems)
75 | {
76 | return mnu_getItems(pnbFuncItems);
77 | }
78 |
79 | extern "C" __declspec(dllexport) void beNotified(SCNotification *pscn)
80 | {
81 | app_onNotify(pscn);
82 | }
83 |
84 | extern "C" __declspec(dllexport) LRESULT messageProc(UINT Message, WPARAM wParam, LPARAM lParam)
85 | {
86 | return app_msgProc(Message, wParam, lParam);
87 | }
88 |
89 | extern "C" __declspec(dllexport) BOOL isUnicode()
90 | {
91 | return TRUE;
92 | }
93 |
--------------------------------------------------------------------------------
/src/Menu.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Menu.cpp
13 | @copyright Copyright 2011,2013-2015 Michael Foster
14 |
15 | Session Manager creates a submenu in the Notepad++ Plugins menu. Those items
16 | can be customized via settings. Favorite sessions are listed after the About
17 | item.
18 | */
19 |
20 | #include "System.h"
21 | #include "SessionMgr.h"
22 | #include "DlgSessions.h"
23 | #include "DlgSettings.h"
24 | #include "Menu.h"
25 | #include "Util.h"
26 | #include "res\resource.h"
27 | #include
28 |
29 | //------------------------------------------------------------------------------
30 |
31 | namespace NppPlugin {
32 |
33 | //------------------------------------------------------------------------------
34 |
35 | namespace {
36 |
37 | #define PLUGIN_ABOUT PLUGIN_FULL_NAME SPACE_STR PLUGIN_VERSION L"\nA plugin for Notepad++\nhttp://mfoster.com/npp/"
38 | #define HELP_FILE_SUFFIX L"doc\\" PLUGIN_DLL_NAME L".html"
39 |
40 | /// Menu callback functions
41 | extern "C" {
42 | void cbSessions();
43 | void cbSettings();
44 | void cbSaveCurrent();
45 | void cbLoadPrevious();
46 | void cbHelp();
47 | void cbAbout();
48 | void cbFav1();
49 | void cbFav2();
50 | void cbFav3();
51 | void cbFav4();
52 | void cbFav5();
53 | void cbFav6();
54 | void cbFav7();
55 | void cbFav8();
56 | void cbFav9();
57 | void cbFav10();
58 | void cbFav11();
59 | void cbFav12();
60 | void cbFav13();
61 | void cbFav14();
62 | void cbFav15();
63 | void cbFav16();
64 | void cbFav17();
65 | void cbFav18();
66 | void cbFav19();
67 | void cbFav20();
68 | };
69 |
70 | /// Menu config
71 | INT _menuItemsCount = MNU_BASE_MAX_ITEMS;
72 | WCHAR _menuMainLabel[MNU_MAX_NAME_LEN + 1];
73 | FuncItem _menuItems[] = {
74 | { EMPTY_STR, cbSessions, 0, false, NULL },
75 | { EMPTY_STR, cbSettings, 0, false, NULL },
76 | { EMPTY_STR, cbSaveCurrent, 0, false, NULL },
77 | { EMPTY_STR, cbLoadPrevious, 0, false, NULL },
78 | { EMPTY_STR, NULL, 0, false, NULL },
79 | { EMPTY_STR, cbHelp, 0, false, NULL },
80 | { EMPTY_STR, cbAbout, 0, false, NULL },
81 | { EMPTY_STR, NULL, 0, false, NULL },
82 | { EMPTY_STR, cbFav1, 0, false, NULL },
83 | { EMPTY_STR, cbFav2, 0, false, NULL },
84 | { EMPTY_STR, cbFav3, 0, false, NULL },
85 | { EMPTY_STR, cbFav4, 0, false, NULL },
86 | { EMPTY_STR, cbFav5, 0, false, NULL },
87 | { EMPTY_STR, cbFav6, 0, false, NULL },
88 | { EMPTY_STR, cbFav7, 0, false, NULL },
89 | { EMPTY_STR, cbFav8, 0, false, NULL },
90 | { EMPTY_STR, cbFav9, 0, false, NULL },
91 | { EMPTY_STR, cbFav10, 0, false, NULL },
92 | { EMPTY_STR, cbFav11, 0, false, NULL },
93 | { EMPTY_STR, cbFav12, 0, false, NULL },
94 | { EMPTY_STR, cbFav13, 0, false, NULL },
95 | { EMPTY_STR, cbFav14, 0, false, NULL },
96 | { EMPTY_STR, cbFav15, 0, false, NULL },
97 | { EMPTY_STR, cbFav16, 0, false, NULL },
98 | { EMPTY_STR, cbFav17, 0, false, NULL },
99 | { EMPTY_STR, cbFav18, 0, false, NULL },
100 | { EMPTY_STR, cbFav19, 0, false, NULL },
101 | { EMPTY_STR, cbFav20, 0, false, NULL }
102 | };
103 |
104 | } // end namespace
105 |
106 | //------------------------------------------------------------------------------
107 |
108 | namespace api {
109 |
110 | void mnu_onLoad()
111 | {
112 | }
113 |
114 | void mnu_onUnload()
115 | {
116 | }
117 |
118 | void mnu_init()
119 | {
120 | INT mnuIdx, cfgIdx = 0;
121 |
122 | // plugin menu
123 | cfg::getStr(kMenuLabelMain, _menuMainLabel, MNU_MAX_NAME_LEN);
124 | cfg::getStr(kMenuLabelSub1, _menuItems[0]._itemName, MNU_MAX_NAME_LEN);
125 | cfg::getStr(kMenuLabelSub2, _menuItems[1]._itemName, MNU_MAX_NAME_LEN);
126 | cfg::getStr(kMenuLabelSub3, _menuItems[2]._itemName, MNU_MAX_NAME_LEN);
127 | cfg::getStr(kMenuLabelSub4, _menuItems[3]._itemName, MNU_MAX_NAME_LEN);
128 | cfg::getStr(kMenuLabelSub5, _menuItems[5]._itemName, MNU_MAX_NAME_LEN);
129 | cfg::getStr(kMenuLabelSub6, _menuItems[6]._itemName, MNU_MAX_NAME_LEN);
130 | // favorites
131 | cfgIdx = 0;
132 | for (mnuIdx = MNU_FIRST_FAV_IDX; mnuIdx <= MNU_LAST_FAV_IDX; ++mnuIdx) {
133 | if (!cfg::getStr(kFavorites, cfgIdx++, _menuItems[mnuIdx]._itemName, MNU_MAX_NAME_LEN)) {
134 | break;
135 | }
136 | ++_menuItemsCount;
137 | }
138 | if (cfgIdx > 0) {
139 | ++_menuItemsCount; // for the 2nd separator if any fav was added
140 | }
141 | }
142 |
143 | FuncItem* mnu_getItems(INT *pNum)
144 | {
145 | *pNum = _menuItemsCount;
146 | return _menuItems;
147 | }
148 |
149 | } // end namespace NppPlugin::api
150 |
151 | //------------------------------------------------------------------------------
152 |
153 | /** @return a pointer to the main or the 0-based mnuIdx'th sub label. */
154 | LPCWSTR mnu_getMenuLabel(INT mnuIdx)
155 | {
156 | LPCWSTR lbl = NULL;
157 |
158 | if (mnuIdx == -1) {
159 | lbl = _menuMainLabel;
160 | }
161 | else if (mnuIdx >= 0 && mnuIdx < MNU_BASE_MAX_ITEMS) {
162 | lbl = _menuItems[mnuIdx]._itemName;
163 | }
164 | return lbl;
165 | }
166 |
167 | //------------------------------------------------------------------------------
168 |
169 | namespace {
170 |
171 | extern "C" void cbSessions()
172 | {
173 | app_readSessionDirectory();
174 | ::DialogBox(sys_getDllHandle(), MAKEINTRESOURCE(IDD_SES_DLG), sys_getNppHandle(), dlgSes_msgProc);
175 | }
176 |
177 | extern "C" void cbSettings()
178 | {
179 | ::DialogBox(sys_getDllHandle(), MAKEINTRESOURCE(IDD_CFG_DLG), sys_getNppHandle(), dlgCfg_msgProc);
180 | }
181 |
182 | extern "C" void cbSaveCurrent()
183 | {
184 | app_saveSession(SI_CURRENT);
185 | }
186 |
187 | extern "C" void cbLoadPrevious()
188 | {
189 | app_loadSession(SI_PREVIOUS);
190 | }
191 |
192 | extern "C" void cbHelp()
193 | {
194 | WCHAR helpFile[MAX_PATH];
195 |
196 | ::GetModuleFileNameW((HMODULE)sys_getDllHandle(), helpFile, MAX_PATH);
197 | pth::removeName(helpFile, MAX_PATH);
198 | ::StringCchCatW(helpFile, MAX_PATH, HELP_FILE_SUFFIX);
199 |
200 | HINSTANCE h = ::ShellExecuteW(NULL, L"open", helpFile, NULL, NULL, SW_SHOW);
201 | if ((int)h <= 32) {
202 | DWORD le = ::GetLastError();
203 | msg::error(le, L"%s: Error shelling to default browser.", _W(__FUNCTION__));
204 | }
205 | }
206 |
207 | extern "C" void cbAbout()
208 | {
209 | const size_t s = 450;
210 | WCHAR m[s];
211 |
212 | ::StringCchCopyW(m, s, PLUGIN_ABOUT);
213 | ::StringCchCatW(m, s, L"\n\nSpecial thanks to....\n\n- Don Ho and team, for Notepad++\n- You! for using Session Manager\n- Dave Brotherstone, for PluginManager\n- Jack Handy, for wildcardMatch\n- Jens Lorenz and Thell Fowler, for example code\n- Julien Audo, for ResEdit\n- Lee Thomason, for TinyXML2\n- Nemanja Trifunovic, for UTF8-CPP\n- Users at the plugin forum, for testing and feedback");
214 | msg::show(m, L"About Session Manager", MB_ICONINFORMATION);
215 | //LOG("strlen = %u", ::wcslen(m));
216 | }
217 |
218 | void loadFavorite(INT mnuOfs)
219 | {
220 | app_loadSession(app_getSessionIndex(_menuItems[mnuOfs + MNU_BASE_MAX_ITEMS]._itemName));
221 | }
222 |
223 | extern "C" void cbFav1() { loadFavorite(1); }
224 | extern "C" void cbFav2() { loadFavorite(2); }
225 | extern "C" void cbFav3() { loadFavorite(3); }
226 | extern "C" void cbFav4() { loadFavorite(4); }
227 | extern "C" void cbFav5() { loadFavorite(5); }
228 | extern "C" void cbFav6() { loadFavorite(6); }
229 | extern "C" void cbFav7() { loadFavorite(7); }
230 | extern "C" void cbFav8() { loadFavorite(8); }
231 | extern "C" void cbFav9() { loadFavorite(9); }
232 | extern "C" void cbFav10() { loadFavorite(10); }
233 | extern "C" void cbFav11() { loadFavorite(11); }
234 | extern "C" void cbFav12() { loadFavorite(12); }
235 | extern "C" void cbFav13() { loadFavorite(13); }
236 | extern "C" void cbFav14() { loadFavorite(14); }
237 | extern "C" void cbFav15() { loadFavorite(15); }
238 | extern "C" void cbFav16() { loadFavorite(16); }
239 | extern "C" void cbFav17() { loadFavorite(17); }
240 | extern "C" void cbFav18() { loadFavorite(18); }
241 | extern "C" void cbFav19() { loadFavorite(19); }
242 | extern "C" void cbFav20() { loadFavorite(20); }
243 |
244 | } // end namespace
245 |
246 | } // end namespace NppPlugin
247 |
--------------------------------------------------------------------------------
/src/Menu.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Menu.h
13 | @copyright Copyright 2011,2013-2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_MENU_H
17 | #define NPP_PLUGIN_MENU_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | const int MNU_BASE_MAX_ITEMS = 7; ///< see _menuItemsCount
24 | const int MNU_MAX_FAVS = 20;
25 | const int MNU_FIRST_FAV_IDX = MNU_BASE_MAX_ITEMS + 1;
26 | const int MNU_LAST_FAV_IDX = MNU_BASE_MAX_ITEMS + MNU_MAX_FAVS;
27 | const int MNU_MAX_NAME_LEN = 63; ///< see nbChar in npp\PluginInterface.h
28 |
29 | //------------------------------------------------------------------------------
30 | /// @namespace NppPlugin::api Contains functions called only from DllMain.
31 |
32 | namespace api {
33 |
34 | void mnu_onLoad();
35 | void mnu_onUnload();
36 | void mnu_init();
37 | FuncItem* mnu_getItems(INT *pNum);
38 |
39 | } // end namespace NppPlugin::api
40 |
41 | //------------------------------------------------------------------------------
42 |
43 | LPCWSTR mnu_getMenuLabel(INT mnuIdx = -1);
44 |
45 | } // end namespace NppPlugin
46 |
47 | #endif // NPP_PLUGIN_MENU_H
48 |
--------------------------------------------------------------------------------
/src/Properties.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Properties.cpp
13 | @copyright Copyright 2014,2015 Michael Foster
14 |
15 | Notepad++ saves a file's bookmarks (and other properties) in the session
16 | file, so the same file in different sessions will not have the same
17 | bookmarks. Session Manager can keep files' bookmarks (and a little more)
18 | synchronized across different sessions. These are referred to as "global
19 | properties". The file "global.xml", in the Session Manager configuration
20 | directory, stores bookmarks, firstVisibleLine and language for each unique
21 | pathname in all sessions.
22 | */
23 |
24 | #include "System.h"
25 | #include "Properties.h"
26 | #include "Util.h"
27 |
28 | //------------------------------------------------------------------------------
29 |
30 | namespace NppPlugin {
31 |
32 | //------------------------------------------------------------------------------
33 |
34 | namespace {
35 |
36 | /// XML nodes
37 | #define XN_NOTEPADPLUS "NotepadPlus" ///< root node
38 | #define XN_SESSION "Session"
39 | #define XN_MAINVIEW "mainView"
40 | #define XN_SUBVIEW "subView"
41 | #define XN_FILE "File"
42 | #define XN_MARK "Mark"
43 | #define XN_FOLD "Fold"
44 | #define XN_FILEPROPERTIES "FileProperties"
45 |
46 | /// XML attributes
47 | #define XA_FILENAME "filename"
48 | #define XA_LANG "lang"
49 | #define XA_FIRSTVISIBLELINE "firstVisibleLine"
50 | #define XA_LINE "line"
51 |
52 | void removeMissingFilesFromGlobal();
53 | void deleteChildren(tXmlEleP parent, LPCSTR eleName);
54 |
55 | } // end namespace
56 |
57 | //------------------------------------------------------------------------------
58 |
59 | namespace api {
60 |
61 | void prp_init()
62 | {
63 | if (cfg::getBool(kCleanGlobalProperties)) {
64 | removeMissingFilesFromGlobal();
65 | }
66 | }
67 |
68 | } // end namespace NppPlugin::api
69 |
70 | //------------------------------------------------------------------------------
71 |
72 | namespace prp {
73 |
74 | /** Updates global file properties from local (session) file properties.
75 | After a session is saved, the global bookmarks, firstVisibleLine and
76 | language are updated from the session properties. */
77 | void updateGlobalFromSession(LPWSTR sesFile)
78 | {
79 | DWORD lastErr;
80 | tXmlError xmlErr;
81 | LPCSTR target;
82 |
83 | LOGF("%S", sesFile);
84 |
85 | // Load the properties file (global file properties)
86 | tXmlDoc globalDoc;
87 | xmlErr = globalDoc.LoadFile(sys_getGlobalFile());
88 | if (xmlErr != kXmlSuccess) {
89 | lastErr = ::GetLastError();
90 | msg::error(lastErr, L"%s: Error %u loading the global properties file.", _W(__FUNCTION__), xmlErr);
91 | return;
92 | }
93 | tXmlEleP globalPropsEle, globalFileEle, globalMarkEle, globalFoldEle;
94 | tXmlHnd globalDocHnd(&globalDoc);
95 | globalPropsEle = globalDocHnd.FirstChildElement(XN_NOTEPADPLUS).FirstChildElement(XN_FILEPROPERTIES).ToElement();
96 |
97 | // Load the session file (file properties local to a session)
98 | tXmlDoc localDoc;
99 | xmlErr = localDoc.LoadFile(sesFile);
100 | if (xmlErr != kXmlSuccess) {
101 | lastErr = ::GetLastError();
102 | msg::error(lastErr, L"%s: Error %u loading session file \"%s\".", _W(__FUNCTION__), xmlErr, sesFile);
103 | return;
104 | }
105 | tXmlEleP localViewEle, localFileEle, localMarkEle, localFoldEle;
106 | tXmlHnd localDocHnd(&localDoc);
107 |
108 | // Iterate over the local View elements
109 | localViewEle = localDocHnd.FirstChildElement(XN_NOTEPADPLUS).FirstChildElement(XN_SESSION).FirstChildElement(XN_MAINVIEW).ToElement();
110 | while (localViewEle) {
111 | // Iterate over the local File elements
112 | localFileEle = localViewEle->FirstChildElement(XN_FILE);
113 | while (localFileEle) {
114 | // Find the global File element corresponding to the current local File element
115 | target = localFileEle->Attribute(XA_FILENAME);
116 | LOGG(21, "File = %s", target);
117 | globalFileEle = globalPropsEle->FirstChildElement(XN_FILE);
118 | while (globalFileEle) {
119 | if (globalFileEle->Attribute(XA_FILENAME, target)) {
120 | break; // found it
121 | }
122 | globalFileEle = globalFileEle->NextSiblingElement(XN_FILE);
123 | }
124 | if (!globalFileEle) { // not found so create one
125 | globalFileEle = globalDoc.NewElement(XN_FILE);
126 | globalFileEle->SetAttribute(XA_FILENAME, target);
127 | }
128 | globalPropsEle->InsertFirstChild(globalFileEle); // an existing element will get moved to the top
129 | // Update global File attributes with values from the current local File attributes
130 | globalFileEle->SetAttribute(XA_LANG, localFileEle->Attribute(XA_LANG));
131 | globalFileEle->SetAttribute(XA_FIRSTVISIBLELINE, localFileEle->Attribute(XA_FIRSTVISIBLELINE));
132 | LOGG(21, "lang = '%s', firstVisibleLine = %s", localFileEle->Attribute(XA_LANG), localFileEle->Attribute(XA_FIRSTVISIBLELINE));
133 | // Iterate over the local Mark elements for the current local File element
134 | deleteChildren(globalFileEle, XN_MARK);
135 | localMarkEle = localFileEle->FirstChildElement(XN_MARK);
136 | while (localMarkEle) {
137 | globalMarkEle = globalDoc.NewElement(XN_MARK);
138 | globalFileEle->InsertEndChild(globalMarkEle);
139 | // Update global Mark attributes with values from the current local Mark attributes
140 | globalMarkEle->SetAttribute(XA_LINE, localMarkEle->Attribute(XA_LINE));
141 | LOGG(21, "Mark = %s", localMarkEle->Attribute(XA_LINE));
142 | localMarkEle = localMarkEle->NextSiblingElement(XN_MARK);
143 | }
144 | // Iterate over the local Fold elements for the current local File element
145 | deleteChildren(globalFileEle, XN_FOLD);
146 | localFoldEle = localFileEle->FirstChildElement(XN_FOLD);
147 | while (localFoldEle) {
148 | globalFoldEle = globalDoc.NewElement(XN_FOLD);
149 | globalFileEle->InsertEndChild(globalFoldEle);
150 | // Update global Fold attributes with values from the current local Fold attributes
151 | globalFoldEle->SetAttribute(XA_LINE, localFoldEle->Attribute(XA_LINE));
152 | LOGG(21, "Fold = %s", localFoldEle->Attribute(XA_LINE));
153 | localFoldEle = localFoldEle->NextSiblingElement(XN_FOLD);
154 | }
155 | // Next local File element
156 | localFileEle = localFileEle->NextSiblingElement(XN_FILE);
157 | }
158 | localViewEle = localViewEle->NextSiblingElement(XN_SUBVIEW);
159 | }
160 |
161 | // Add XML declaration if missing
162 | if (memcmp(globalDoc.FirstChild()->Value(), "xml", 3) != 0) {
163 | globalDoc.InsertFirstChild(globalDoc.NewDeclaration());
164 | }
165 | // Save changes to the properties file
166 | xmlErr = globalDoc.SaveFile(sys_getGlobalFile());
167 | if (xmlErr != kXmlSuccess) {
168 | lastErr = ::GetLastError();
169 | msg::error(lastErr, L"%s: Error %u saving the global properties file.", _W(__FUNCTION__), xmlErr);
170 | }
171 | }
172 |
173 | /** Updates local (session) file properties from global file properties.
174 | When a session is about to be loaded, the session bookmarks and language
175 | are updated from the global properties, then the session is loaded. */
176 | void updateSessionFromGlobal(LPWSTR sesFile)
177 | {
178 | LPSTR buf;
179 | DWORD lastErr;
180 | tXmlError xmlErr;
181 | bool save = false;
182 | LPCSTR target;
183 |
184 | LOGF("%S", sesFile);
185 |
186 | // Load the properties file (global file properties)
187 | tXmlDoc globalDoc;
188 | xmlErr = globalDoc.LoadFile(sys_getGlobalFile());
189 | if (xmlErr != kXmlSuccess) {
190 | lastErr = ::GetLastError();
191 | msg::error(lastErr, L"%s: Error %u loading the global properties file.", _W(__FUNCTION__), xmlErr);
192 | return;
193 | }
194 | tXmlEleP globalPropsEle, globalFileEle, globalMarkEle, globalFoldEle;
195 | tXmlHnd globalDocHnd(&globalDoc);
196 | globalPropsEle = globalDocHnd.FirstChildElement(XN_NOTEPADPLUS).FirstChildElement(XN_FILEPROPERTIES).ToElement();
197 |
198 | // Load the session file (file properties local to a session)
199 | tXmlDoc localDoc;
200 | xmlErr = localDoc.LoadFile(sesFile);
201 | if (xmlErr != kXmlSuccess) {
202 | lastErr = ::GetLastError();
203 | msg::error(lastErr, L"%s: Error %u loading session file \"%s\".", _W(__FUNCTION__), xmlErr, sesFile);
204 | return;
205 | }
206 | tXmlEleP localViewEle, localFileEle, localMarkEle, localFoldEle;
207 | tXmlHnd localDocHnd(&localDoc);
208 |
209 | // Iterate over the local View elements
210 | localViewEle = localDocHnd.FirstChildElement(XN_NOTEPADPLUS).FirstChildElement(XN_SESSION).FirstChildElement(XN_MAINVIEW).ToElement();
211 | while (localViewEle) {
212 | // Iterate over the local File elements
213 | localFileEle = localViewEle->FirstChildElement(XN_FILE);
214 | while (localFileEle) {
215 | // Find the global File element corresponding to the current local File element
216 | target = localFileEle->Attribute(XA_FILENAME);
217 | LOGG(22, "File = %s", target);
218 | globalFileEle = globalPropsEle->FirstChildElement(XN_FILE);
219 | while (globalFileEle) {
220 | if (globalFileEle->Attribute(XA_FILENAME, target)) {
221 | break; // found it
222 | }
223 | globalFileEle = globalFileEle->NextSiblingElement(XN_FILE);
224 | }
225 | if (globalFileEle) {
226 | save = true;
227 | // Update current local File attributes with values from the global File attributes
228 | buf = (LPSTR)sys_alloc(str::utf8ToAscii(target) * sizeof CHAR);
229 | if (buf == NULL) {
230 | return;
231 | }
232 | str::utf8ToAscii(target, buf); // NPP expects the pathname to be encoded like this
233 | localFileEle->SetAttribute(XA_FILENAME, buf);
234 | sys_free(buf);
235 | localFileEle->SetAttribute(XA_LANG, globalFileEle->Attribute(XA_LANG));
236 | LOGG(22, "lang = '%s'", globalFileEle->Attribute(XA_LANG));
237 | // Iterate over the global Mark elements for the current global File element
238 | deleteChildren(localFileEle, XN_MARK);
239 | globalMarkEle = globalFileEle->FirstChildElement(XN_MARK);
240 | while (globalMarkEle) {
241 | localMarkEle = localDoc.NewElement(XN_MARK);
242 | localFileEle->InsertEndChild(localMarkEle);
243 | // Update local Mark attributes with values from the current global Mark attributes
244 | localMarkEle->SetAttribute(XA_LINE, globalMarkEle->Attribute(XA_LINE));
245 | LOGG(22, "Mark = %s", globalMarkEle->Attribute(XA_LINE));
246 | globalMarkEle = globalMarkEle->NextSiblingElement(XN_MARK);
247 | }
248 | // Iterate over the global Fold elements for the current global File element
249 | deleteChildren(localFileEle, XN_FOLD);
250 | globalFoldEle = globalFileEle->FirstChildElement(XN_FOLD);
251 | while (globalFoldEle) {
252 | localFoldEle = localDoc.NewElement(XN_FOLD);
253 | localFileEle->InsertEndChild(localFoldEle);
254 | // Update local Fold attributes with values from the current global Fold attributes
255 | localFoldEle->SetAttribute(XA_LINE, globalFoldEle->Attribute(XA_LINE));
256 | LOGG(22, "Fold = %s", globalFoldEle->Attribute(XA_LINE));
257 | globalFoldEle = globalFoldEle->NextSiblingElement(XN_FOLD);
258 | }
259 | }
260 | //else {
261 | // TODO: not found
262 | // This indicates global needs to be updated from this session,
263 | // but we can't call updateGlobalFromSession here.
264 | //}
265 | localFileEle = localFileEle->NextSiblingElement(XN_FILE);
266 | }
267 | localViewEle = localViewEle->NextSiblingElement(XN_SUBVIEW);
268 | }
269 |
270 | if (save) {
271 | // Add XML declaration if missing
272 | if (memcmp(localDoc.FirstChild()->Value(), "xml", 3) != 0) {
273 | localDoc.InsertFirstChild(localDoc.NewDeclaration());
274 | }
275 | // Save changes to the session file
276 | xmlErr = localDoc.SaveFile(sesFile);
277 | if (xmlErr != kXmlSuccess) {
278 | lastErr = ::GetLastError();
279 | msg::error(lastErr, L"%s: Error %u saving session file \"%s\".", _W(__FUNCTION__), xmlErr, sesFile);
280 | }
281 | }
282 | }
283 |
284 | /** Updates document properties from global file properties.
285 | When an existing document is added to a session, its bookmarks and
286 | firstVisibleLine are updated from the global properties. */
287 | void updateDocumentFromGlobal(INT bufferId)
288 | {
289 | LPSTR mbPathname;
290 | WCHAR pathname[MAX_PATH];
291 | INT line, pos, view;
292 | HWND hNpp = sys_getNppHandle();
293 |
294 | LOGF("%i", bufferId);
295 |
296 | // Get pathname for bufferId
297 | ::SendMessage(hNpp, NPPM_GETFULLPATHFROMBUFFERID, bufferId, (LPARAM)pathname);
298 | mbPathname = str::utf16ToUtf8(pathname);
299 | if (mbPathname == NULL) {
300 | return;
301 | }
302 | LOGG(20, "File = %s", mbPathname);
303 | // Load the properties file (global file properties)
304 | tXmlDoc globalDoc;
305 | tXmlError xmlErr = globalDoc.LoadFile(sys_getGlobalFile());
306 | if (xmlErr != kXmlSuccess) {
307 | DWORD lastErr = ::GetLastError();
308 | msg::error(lastErr, L"%s: Error %u loading the global properties file.", _W(__FUNCTION__), xmlErr);
309 | sys_free(mbPathname);
310 | return;
311 | }
312 | tXmlEleP globalFileEle, globalMarkEle, globalFoldEle;
313 | tXmlHnd globalDocHnd(&globalDoc);
314 | globalFileEle = globalDocHnd.FirstChildElement(XN_NOTEPADPLUS).FirstChildElement(XN_FILEPROPERTIES).FirstChildElement(XN_FILE).ToElement();
315 |
316 | // Find the global File element corresponding to mbPathname
317 | while (globalFileEle) {
318 | if (globalFileEle->Attribute(XA_FILENAME, mbPathname)) {
319 | break; // found it
320 | }
321 | globalFileEle = globalFileEle->NextSiblingElement(XN_FILE);
322 | }
323 | sys_free(mbPathname);
324 | if (!globalFileEle) { // not found
325 | return;
326 | }
327 |
328 | // TODO: Need to set lang here
329 |
330 | // Determine containing view and tab for bufferId
331 | pos = ::SendMessage(hNpp, NPPM_GETPOSFROMBUFFERID, bufferId, 0);
332 | LOGG(20, "Pos = 0x%X", pos);
333 | view = (pos & (1 << 30)) == 0 ? 1 : 2;
334 |
335 | // Iterate over the global Mark elements and set them in the active document
336 | globalMarkEle = globalFileEle->FirstChildElement(XN_MARK);
337 | while (globalMarkEle) {
338 | line = globalMarkEle->IntAttribute(XA_LINE);
339 | // Go to line and set mark
340 | ::SendMessage(sys_getSciHandle(view), SCI_GOTOLINE, line, 0);
341 | ::SendMessage(hNpp, NPPM_MENUCOMMAND, 0, IDM_SEARCH_TOGGLE_BOOKMARK);
342 | LOGG(20, "Mark = %i", line);
343 | globalMarkEle = globalMarkEle->NextSiblingElement(XN_MARK);
344 | }
345 |
346 | // Iterate over the global Fold elements and set them in the active document
347 | globalFoldEle = globalFileEle->FirstChildElement(XN_FOLD);
348 | while (globalFoldEle) {
349 | line = globalFoldEle->IntAttribute(XA_LINE);
350 | // Go to line and set fold
351 | ::SendMessage(sys_getSciHandle(view), SCI_GOTOLINE, line, 0);
352 | ::SendMessage(hNpp, NPPM_MENUCOMMAND, 0, IDM_VIEW_FOLD_CURRENT);
353 | LOGG(20, "Fold = %i", line);
354 | globalFoldEle = globalFoldEle->NextSiblingElement(XN_FOLD);
355 | }
356 |
357 | // Move cursor to the last known firstVisibleLine
358 | line = globalFileEle->IntAttribute(XA_FIRSTVISIBLELINE);
359 | ::SendMessage(sys_getSciHandle(view), SCI_GOTOLINE, line, 0);
360 | LOGG(20, "firstVisibleLine = %i", line);
361 | }
362 |
363 | } // end namespace NppPlugin::prp
364 |
365 | //------------------------------------------------------------------------------
366 |
367 | namespace {
368 |
369 | /** Removes global File elements whose files do not exist on disk. */
370 | void removeMissingFilesFromGlobal()
371 | {
372 | DWORD lastErr;
373 | tXmlError xmlErr;
374 | bool save = false;
375 | LPWSTR wPathname;
376 | LPCSTR mbPathname;
377 | tXmlEleP propsEle, fileEle, currentFileEle;
378 |
379 | LOGF("");
380 |
381 | // Load the properties file (global file properties)
382 | tXmlDoc globalDoc;
383 | xmlErr = globalDoc.LoadFile(sys_getGlobalFile());
384 | if (xmlErr != kXmlSuccess) {
385 | lastErr = ::GetLastError();
386 | msg::error(lastErr, L"%s: Error %u loading the global properties file.", _W(__FUNCTION__), xmlErr);
387 | return;
388 | }
389 | tXmlHnd globalDocHnd(&globalDoc);
390 | propsEle = globalDocHnd.FirstChildElement(XN_NOTEPADPLUS).FirstChildElement(XN_FILEPROPERTIES).ToElement();
391 | fileEle = propsEle->FirstChildElement(XN_FILE);
392 |
393 | // Iterate over the File elements and remove those whose files do not exist
394 | while (fileEle) {
395 | mbPathname = fileEle->Attribute(XA_FILENAME);
396 | wPathname = str::utf8ToUtf16(mbPathname);
397 | if (wPathname == NULL) {
398 | continue; // XXX was: return;
399 | }
400 | currentFileEle = fileEle;
401 | fileEle = fileEle->NextSiblingElement(XN_FILE);
402 | if (!pth::fileExists(wPathname)) {
403 | save = true;
404 | propsEle->DeleteChild(currentFileEle);
405 | LOGG(20, "File = %s", mbPathname);
406 | }
407 | sys_free(wPathname);
408 | }
409 |
410 | if (save) {
411 | // Add XML declaration if missing
412 | if (memcmp(globalDoc.FirstChild()->Value(), "xml", 3) != 0) {
413 | globalDoc.InsertFirstChild(globalDoc.NewDeclaration());
414 | }
415 | // Save changes to the properties file
416 | xmlErr = globalDoc.SaveFile(sys_getGlobalFile());
417 | if (xmlErr != kXmlSuccess) {
418 | lastErr = ::GetLastError();
419 | msg::error(lastErr, L"%s: Error %u saving the global properties file.", _W(__FUNCTION__), xmlErr);
420 | }
421 | }
422 | }
423 |
424 | /** Deletes parent's child elements having the given element name. */
425 | void deleteChildren(tXmlEleP parent, LPCSTR eleName)
426 | {
427 | tXmlEleP ele, tmp;
428 |
429 | ele = parent->FirstChildElement(eleName);
430 | while (ele) {
431 | tmp = ele;
432 | ele = ele->NextSiblingElement(eleName);
433 | parent->DeleteChild(tmp);
434 | }
435 | }
436 |
437 | } // end namespace
438 |
439 | } // end namespace NppPlugin
440 |
--------------------------------------------------------------------------------
/src/Properties.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Properties.h
13 | @copyright Copyright 2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_PROPERTIES_H
17 | #define NPP_PLUGIN_PROPERTIES_H
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | namespace NppPlugin {
22 |
23 | //------------------------------------------------------------------------------
24 | /// @namespace NppPlugin::api Contains functions called only from DllMain.
25 |
26 | namespace api {
27 |
28 | void prp_init();
29 |
30 | } // end namespace NppPlugin::api
31 |
32 | //------------------------------------------------------------------------------
33 | /// @namespace NppPlugin::prp Implements global file properties.
34 |
35 | namespace prp {
36 |
37 | void updateGlobalFromSession(LPWSTR sesFile);
38 | void updateSessionFromGlobal(LPWSTR sesFile);
39 | void updateDocumentFromGlobal(INT bufferId);
40 |
41 | } // end namespace NppPlugin::prp
42 |
43 | } // end namespace NppPlugin
44 |
45 | #endif // NPP_PLUGIN_PROPERTIES_H
46 |
--------------------------------------------------------------------------------
/src/SessionMgr.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file SessionMgr.h
13 | @copyright Copyright 2011,2013-2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_APPLICATION_H
17 | #define NPP_PLUGIN_APPLICATION_H
18 |
19 | #include "res\version.h"
20 |
21 | //------------------------------------------------------------------------------
22 |
23 | namespace NppPlugin {
24 |
25 | #define PLUGIN_DLL_NAME L"SessionMgr"
26 | #define PLUGIN_FULL_NAME L"Session Manager"
27 | #define SES_NAME_NONE L"None"
28 | #define SES_NAME_DEFAULT L"Default"
29 | #define SES_NAME_BUF_LEN 100
30 | /// Used as virtual session indexes
31 | #define SI_NONE -1
32 | #define SI_CURRENT -2
33 | #define SI_PREVIOUS -3
34 | #define SI_DEFAULT -4
35 |
36 | /// @class Session
37 | class Session
38 | {
39 | public:
40 | INT index;
41 | bool isVisible;
42 | bool isFavorite;
43 | FILETIME modified;
44 | WCHAR name[SES_NAME_BUF_LEN];
45 | Session(LPCWSTR sesName, FILETIME modTime);
46 | };
47 |
48 | //------------------------------------------------------------------------------
49 | /// @namespace NppPlugin::api Contains functions called only from DllMain.
50 |
51 | namespace api {
52 |
53 | void app_onLoad();
54 | void app_onUnload();
55 | void app_init();
56 | LPCWSTR app_getName();
57 | void app_onNotify(SCNotification *pscn);
58 | LRESULT app_msgProc(UINT Message, WPARAM wParam, LPARAM lParam);
59 |
60 | } // end namespace NppPlugin::api
61 |
62 | //------------------------------------------------------------------------------
63 |
64 | void app_readSessionDirectory(bool firstLoad = false);
65 | void app_loadSession(INT si);
66 | void app_loadSession(INT si, bool lic, bool lwc, bool firstLoad = false);
67 | void app_saveSession(INT si = SI_CURRENT);
68 | bool app_isValidSessionIndex(INT si);
69 | INT app_getSessionCount();
70 | INT app_getSessionIndex(LPCWSTR name);
71 | INT app_getCurrentIndex();
72 | INT app_getPreviousIndex();
73 | INT app_getDefaultIndex();
74 | void app_resetPreviousIndex();
75 | void app_renameSession(INT si, LPWSTR newName);
76 | LPCWSTR app_getSessionName(INT si = SI_CURRENT);
77 | void app_getSessionFile(INT si, LPWSTR buf);
78 | Session* app_getSessionObject(INT si);
79 | void app_confirmDefaultSession();
80 | void app_updateNppBars();
81 | void app_updateFavorites(bool clearAll = false);
82 | INT app_getLbIdxStartingWith(WCHAR targetChar);
83 |
84 | } // end namespace NppPlugin
85 |
86 | #endif // NPP_PLUGIN_APPLICATION_H
87 |
--------------------------------------------------------------------------------
/src/SessionMgrApi.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file SessionMgrApi.h
13 | @copyright Copyright 2014,2015 Michael Foster
14 |
15 | Session Manager P2P API
16 |
17 | Clients should send NPPM_MSGTOPLUGIN to NPP with wParam pointing to
18 | L"SessionMgr.dll" and lParam pointing to a SessionMgrApiData object.
19 | */
20 |
21 | #ifndef NPP_PLUGIN_SESSIONMGRAPI_H
22 | #define NPP_PLUGIN_SESSIONMGRAPI_H
23 |
24 | #define SM_NULL 0
25 | #define SM_OK -1
26 | #define SM_BUSY -2
27 | #define SM_ERROR -3
28 | #define SM_INVMSG -4
29 | #define SM_INVARG -5
30 |
31 | /** This is compatible with casting to NPP's CommunicationInfo struct.
32 | @see npp\Notepad_plus_msgs.h */
33 | struct SessionMgrApiData {
34 | long message; ///< one of the SMM_ message codes
35 | LPCWSTR caller; ///< for NPP but not used as of v6.6.9
36 | INT iData; ///< input and output API usage
37 | WCHAR wData[MAX_PATH]; ///< input or output API usage
38 | };
39 |
40 | enum SettingId {
41 | kAutomaticSave = 0,
42 | kAutomaticLoad,
43 | kLoadIntoCurrent,
44 | kLoadWithoutClosing,
45 | kShowInTitlebar,
46 | kShowInStatusbar,
47 | kUseGlobalProperties,
48 | kCleanGlobalProperties,
49 | kUseContextMenu,
50 | kBackupOnStartup,
51 | kSessionSaveDelay,
52 | kSettingsSavePoll,
53 | kSessionDirectory,
54 | kSessionExtension,
55 | kCurrentMark,
56 | kCurrentFavMark,
57 | kPreviousMark,
58 | kPreviousFavMark,
59 | kDefaultMark,
60 | kDefaultFavMark,
61 | kFavoriteMark,
62 | kUseFilterWildcards,
63 | kSessionSortOrder,
64 | kCurrentSession,
65 | kPreviousSession,
66 | kDefaultSession,
67 | kMenuLabelMain,
68 | kMenuLabelSub1,
69 | kMenuLabelSub2,
70 | kMenuLabelSub3,
71 | kMenuLabelSub4,
72 | kMenuLabelSub5,
73 | kMenuLabelSub6,
74 | kSessionsDialogWidth,
75 | kSessionsDialogHeight,
76 | kSettingsDialogWidth,
77 | kSettingsDialogHeight,
78 | kDebugLogLevel,
79 | kDebugLogFile,
80 | kSettingsCount
81 | };
82 |
83 | //------------------------------------------------------------------------------
84 |
85 | /** Loads a session from the current sessions list.
86 | @pre wData = session name, no path or extension
87 | @pre iData = SM_NULL
88 | @post iData = SM_OK else SM_BUSY or SM_INVARG */
89 | #define SMM_SES_LOAD (WM_APP + 1)
90 |
91 | /** Loads the previous session.
92 | @pre iData = SM_NULL
93 | @post iData = SM_OK else SM_BUSY */
94 | #define SMM_SES_LOAD_PRV (WM_APP + 2)
95 |
96 | /** Loads the default session.
97 | @pre iData = SM_NULL
98 | @post iData = SM_OK else SM_BUSY */
99 | #define SMM_SES_LOAD_DEF (WM_APP + 3)
100 |
101 | /** Saves the current session.
102 | @pre iData = SM_NULL
103 | @post iData = SM_OK else SM_BUSY */
104 | #define SMM_SES_SAVE (WM_APP + 4)
105 |
106 | /** Gets the current session name, no path or extension.
107 | @pre iData = SM_NULL
108 | @post iData = SM_OK else SM_BUSY
109 | @post wData = name */
110 | #define SMM_SES_GET_NAME (WM_APP + 5)
111 |
112 | /** Gets the fully qualified name of the current session file.
113 | @pre iData = SM_NULL
114 | @post iData = SM_OK else SM_BUSY
115 | @post wData = fqn */
116 | #define SMM_SES_GET_FQN (WM_APP + 6)
117 |
118 | /** Gets the integer value of a setting.
119 | @pre iData = SettingId
120 | @post iData = SM_OK else SM_BUSY or SM_INVARG
121 | @post wData[0] = value of setting */
122 | #define SMM_CFG_GET_INT (WM_APP + 7)
123 |
124 | /** Sets the integer value of a setting.
125 | @pre iData = SettingId
126 | @pre wData[0] = value to set
127 | @post iData = SM_OK else SM_BUSY or SM_INVARG */
128 | #define SMM_CFG_PUT_INT (WM_APP + 8)
129 |
130 | /** Gets the string value of a setting.
131 | @pre iData = SettingId
132 | @post iData = SM_OK else SM_BUSY or SM_INVARG
133 | @post wData = value of setting */
134 | #define SMM_CFG_GET_STR (WM_APP + 9)
135 |
136 | /** Sets the string value of a setting.
137 | @pre iData = SettingId
138 | @pre wData = value to set
139 | @post iData = SM_OK else SM_BUSY, SM_INVARG or SM_ERROR */
140 | #define SMM_CFG_PUT_STR (WM_APP + 10)
141 |
142 | /** Removes all favorites.
143 | @pre iData = SM_NULL
144 | @post iData = SM_OK else SM_BUSY */
145 | #define SMM_FAV_CLR (WM_APP + 11)
146 |
147 | /** Adds or removes a session as a favorite.
148 | @pre wData = session name, no path or extension
149 | @pre iData = 0: remove, 1: add
150 | @post iData = SM_OK else SM_BUSY, SM_INVARG or SM_ERROR */
151 | #define SMM_FAV_SET (WM_APP + 12)
152 |
153 | /** Removes all filters.
154 | @pre iData = SM_NULL
155 | @post iData = SM_OK else SM_BUSY */
156 | #define SMM_FIL_CLR (WM_APP + 13)
157 |
158 | /** Adds a filter. It is moved to the top if it is already in the list.
159 | @pre wData = filter
160 | @pre iData = SM_NULL
161 | @post iData = SM_OK else SM_BUSY */
162 | #define SMM_FIL_ADD (WM_APP + 14)
163 |
164 | /** Gets NPP's configuration directory.
165 | @pre iData = SM_NULL
166 | @post iData = SM_OK else SM_BUSY or SM_ERROR
167 | @post wData = path */
168 | #define SMM_NPP_CFG_DIR (WM_APP + 15)
169 |
170 |
171 | #endif // NPP_PLUGIN_SESSIONMGRAPI_H
172 |
--------------------------------------------------------------------------------
/src/Settings.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Settings.cpp
13 | @copyright Copyright 2014,2015 Michael Foster
14 |
15 | Implements management of configuration settings.
16 | */
17 |
18 | #include "System.h"
19 | #include "SessionMgr.h"
20 | #include "Menu.h"
21 | #include "Util.h"
22 | #include
23 | #include
24 |
25 | //------------------------------------------------------------------------------
26 |
27 | namespace NppPlugin {
28 |
29 | INT gDbgLvl = 0;
30 |
31 | //------------------------------------------------------------------------------
32 |
33 | namespace {
34 |
35 | /// Initial contents of a new settings.xml file
36 | #define INITIAL_CONTENTS "\n\n"
37 | /// XML node and attribute names
38 | #define XN_ROOT "SessionMgr"
39 | #define XN_ITEM "item"
40 | #define XA_VALUE "value"
41 | /// Defaults
42 | #define DEFAULT_SES_DIR L"sessions\\"
43 | #define DEFAULT_SES_EXT L".npp-session"
44 |
45 | tXmlDocP _xmlDocument = NULL;
46 | WCHAR _tmpBuffer[MAX_PATH];
47 | bool _isDirty = false;
48 |
49 | /** These must be in the same order as the ContainerId enums. */
50 | LPCSTR _containerNames[] = {
51 | "Settings",
52 | "Favorites",
53 | "Filters"
54 | };
55 |
56 | tXmlEleP _containerElements[kContainersCount];
57 |
58 | typedef struct Setting_tag {
59 | LPSTR cName;
60 | LPSTR cDefault;
61 | bool isInt;
62 | INT iCache;
63 | LPWSTR wCache;
64 | tXmlEleP element;
65 | INT wCacheSize; // character size of the wCache buffer, 0 if isInt
66 | } Setting;
67 |
68 | /** These must be in the same order as the SettingId enums. */
69 | Setting _settings[] = {
70 | { "automaticSave", "1", true, 0, 0, 0, 0 },
71 | { "automaticLoad", "0", true, 0, 0, 0, 0 },
72 | { "loadIntoCurrent", "0", true, 0, 0, 0, 0 },
73 | { "loadWithoutClosing", "0", true, 0, 0, 0, 0 },
74 | { "showInTitlebar", "0", true, 0, 0, 0, 0 },
75 | { "showInStatusbar", "0", true, 0, 0, 0, 0 },
76 | { "useGlobalProperties", "1", true, 0, 0, 0, 0 },
77 | { "cleanGlobalProperties","0", true, 0, 0, 0, 0 },
78 | { "useContextMenu", "1", true, 0, 0, 0, 0 },
79 | { "backupOnStartup", "1", true, 0, 0, 0, 0 },
80 | { "sessionSaveDelay", "3", true, 0, 0, 0, 0 },
81 | { "settingsSavePoll", "2", true, 0, 0, 0, 0 },
82 | { "sessionDirectory", "", false, 0, 0, 0, MAX_PATH },
83 | { "sessionExtension", ".npp-session", false, 0, 0, 0, MAX_PATH }, // 25 },
84 | { "currentMark", "9674", true, 0, 0, 0, 0 },
85 | { "currentFavMark", "9830", true, 0, 0, 0, 0 },
86 | { "previousMark", "9702", true, 0, 0, 0, 0 },
87 | { "previousFavMark", "8226", true, 0, 0, 0, 0 },
88 | { "defaultMark", "9653", true, 0, 0, 0, 0 },
89 | { "defaultFavMark", "9652", true, 0, 0, 0, 0 },
90 | { "favoriteMark", "183", true, 0, 0, 0, 0 },
91 | { "useFilterWildcards", "0", true, 0, 0, 0, 0 },
92 | { "sessionSortOrder", "1", true, 0, 0, 0, 0 },
93 | { "currentSession", "Default", false, 0, 0, 0, MAX_PATH }, // SES_NAME_BUF_LEN },
94 | { "previousSession", "Default", false, 0, 0, 0, MAX_PATH }, // SES_NAME_BUF_LEN },
95 | { "defaultSession", "Default", false, 0, 0, 0, MAX_PATH }, // SES_NAME_BUF_LEN },
96 | { "menuLabelMain", "&Session Manager", false, 0, 0, 0, MAX_PATH }, // MNU_MAX_NAME_LEN + 1 },
97 | { "menuLabelSub1", "&Sessions...", false, 0, 0, 0, MAX_PATH }, // MNU_MAX_NAME_LEN + 1 },
98 | { "menuLabelSub2", "Se&ttings...", false, 0, 0, 0, MAX_PATH }, // MNU_MAX_NAME_LEN + 1 },
99 | { "menuLabelSub3", "Sa&ve current", false, 0, 0, 0, MAX_PATH }, // MNU_MAX_NAME_LEN + 1 },
100 | { "menuLabelSub4", "Load &previous", false, 0, 0, 0, MAX_PATH }, // MNU_MAX_NAME_LEN + 1 },
101 | { "menuLabelSub5", "&Help", false, 0, 0, 0, MAX_PATH }, // MNU_MAX_NAME_LEN + 1 },
102 | { "menuLabelSub6", "&About...", false, 0, 0, 0, MAX_PATH }, // MNU_MAX_NAME_LEN + 1 },
103 | { "sessionsDialogWidth", "0", true, 0, 0, 0, 0 },
104 | { "sessionsDialogHeight", "0", true, 0, 0, 0, 0 },
105 | { "settingsDialogWidth", "0", true, 0, 0, 0, 0 },
106 | { "settingsDialogHeight", "0", true, 0, 0, 0, 0 },
107 | { "debugLogLevel", "0", true, 0, 0, 0, 0 },
108 | { "debugLogFile", "", false, 0, 0, 0, MAX_PATH }
109 | };
110 |
111 | bool readSettingsFile();
112 | void initContainers();
113 | void initSettings();
114 | void updateCache(Setting *setting);
115 | void afterLoad();
116 | void upgradeIniToXml();
117 |
118 | } // end namespace
119 |
120 | //------------------------------------------------------------------------------
121 |
122 | namespace api {
123 |
124 | void cfg_onUnload()
125 | {
126 | INT i;
127 |
128 | if (_isDirty) {
129 | cfg::saveSettings();
130 | }
131 | for (i = 0; i < kSettingsCount; ++i) {
132 | if (!_settings[i].isInt && _settings[i].wCache) {
133 | sys_free(_settings[i].wCache);
134 | }
135 | }
136 | for (i = 0; i < kContainersCount; ++i) {
137 | _containerElements[i] = NULL;
138 | }
139 | if (_xmlDocument) {
140 | delete _xmlDocument;
141 | _xmlDocument = NULL;
142 | }
143 | }
144 |
145 | } // end namespace NppPlugin::api
146 |
147 | //------------------------------------------------------------------------------
148 |
149 | namespace cfg {
150 |
151 | void loadSettings()
152 | {
153 | if (readSettingsFile()) {
154 | initContainers();
155 | initSettings();
156 | afterLoad();
157 | if (_isDirty) {
158 | saveSettings();
159 | }
160 | }
161 | }
162 |
163 | void saveSettings()
164 | {
165 | DWORD lastErr;
166 | tXmlError xmlErr;
167 |
168 | if (_xmlDocument) {
169 | xmlErr = _xmlDocument->SaveFile(sys_getSettingsFile());
170 | if (xmlErr != kXmlSuccess) {
171 | lastErr = ::GetLastError();
172 | msg::error(lastErr, L"%s: Error %u saving the settings file.", _W(__FUNCTION__), xmlErr);
173 | }
174 | else {
175 | _isDirty = false;
176 | LOG("Settings saved.");
177 | }
178 | }
179 | }
180 |
181 | bool isDirty()
182 | {
183 | return _isDirty;
184 | }
185 |
186 | //------------------------------------------------------------------------------
187 | // Functions that read or write child elements of the Settings container.
188 |
189 | /** @return a pointer to the value of the cfgId element of the Settings container. */
190 | LPCWSTR getStr(SettingId cfgId)
191 | {
192 | return _settings[cfgId].wCache;
193 | }
194 |
195 | /** Copies to buf the value of the cfgId element of the Settings container. */
196 | void getStr(SettingId cfgId, LPWSTR buf, INT bufLen)
197 | {
198 | ::StringCchCopyW(buf, bufLen, _settings[cfgId].wCache);
199 | }
200 |
201 | /** @return the boolean value of the cfgId element of the Settings container. */
202 | bool getBool(SettingId cfgId)
203 | {
204 | return _settings[cfgId].iCache != 0;
205 | }
206 |
207 | /** @return the integer value of the cfgId element of the Settings container. */
208 | INT getInt(SettingId cfgId)
209 | {
210 | return _settings[cfgId].iCache;
211 | }
212 |
213 | /** Copies value to the cfgId element of the Settings container. */
214 | void putStr(SettingId cfgId, LPCSTR value)
215 | {
216 | if (value && *value) {
217 | _settings[cfgId].element->SetAttribute(XA_VALUE, value);
218 | updateCache(&_settings[cfgId]);
219 | _isDirty = true;
220 | }
221 | }
222 |
223 | /** Copies value to the cfgId element of the Settings container. */
224 | void putStr(SettingId cfgId, LPCWSTR value)
225 | {
226 | LPSTR mbValue = str::utf16ToUtf8(value);
227 | if (mbValue) {
228 | putStr(cfgId, mbValue);
229 | sys_free(mbValue);
230 | }
231 | }
232 |
233 | /** Writes the boolean value to the cfgId element of the Settings container. */
234 | void putBool(SettingId cfgId, bool value)
235 | {
236 | putStr(cfgId, value ? "1" : "0");
237 | }
238 |
239 | /** Writes the integer value to the cfgId element of the Settings container. */
240 | void putInt(SettingId cfgId, INT value)
241 | {
242 | CHAR buf[MAX_PATH];
243 | ::_itoa_s(value, buf, MAX_PATH, 10);
244 | putStr(cfgId, buf);
245 | }
246 |
247 | //------------------------------------------------------------------------------
248 | // Functions that read or write child elements of any container.
249 |
250 | /** @return a pointer to the value of the 0-based childIndex'th element of the
251 | conId container, or NULL if the element doesn't exist. */
252 | LPCSTR getCStr(ContainerId conId, INT childIndex)
253 | {
254 | tXmlEleP childEle;
255 | childEle = _containerElements[conId]->FirstChildElement();
256 | while (childEle && childIndex-- > 0) {
257 | childEle = childEle->NextSiblingElement();
258 | }
259 | if (childEle) {
260 | return childEle->Attribute(XA_VALUE);
261 | }
262 | return NULL;
263 | }
264 |
265 | /** @return a pointer to the value of the 0-based childIndex'th element of the
266 | conId container, or NULL if the element doesn't exist. It points to a
267 | temporary buffer which will be overwritten the next time this function
268 | is called. */
269 | LPCWSTR getStr(ContainerId conId, INT childIndex)
270 | {
271 | LPCSTR mbStr = getCStr(conId, childIndex);
272 | if (!mbStr) {
273 | return NULL;
274 | }
275 | return str::utf8ToUtf16(mbStr, _tmpBuffer, MAX_PATH);
276 | }
277 |
278 | /** Copies to buf the value of the 0-based childIndex'th element of the conId container.
279 | @return true if the element exists else false */
280 | bool getStr(ContainerId conId, INT childIndex, LPWSTR buf, INT bufLen)
281 | {
282 | LPCSTR mbStr = getCStr(conId, childIndex);
283 | if (!mbStr) {
284 | return false;
285 | }
286 | return str::utf8ToUtf16(mbStr, buf, bufLen) != NULL;
287 | }
288 |
289 | /** @return a pointer to the first child of conId with value, else NULL */
290 | tXmlEleP getChild(ContainerId conId, LPCSTR value)
291 | {
292 | if (value && *value) {
293 | tXmlEleP childEle = _containerElements[conId]->FirstChildElement();
294 | while (childEle) {
295 | if (childEle->Attribute(XA_VALUE, value)) {
296 | return childEle;
297 | }
298 | childEle = childEle->NextSiblingElement();
299 | }
300 | }
301 | return NULL;
302 | }
303 |
304 | /** Adds a new element to the conId container and copies value to it. Appends
305 | if append is true else prepends. Does nothing if conId is kSettings, or
306 | value is null or empty, or a child with value already exists. */
307 | void addChild(ContainerId conId, LPCWSTR value, bool append)
308 | {
309 | if (conId != kSettings && value && *value) {
310 | LPSTR mbValue = str::utf16ToUtf8(value);
311 | if (mbValue && !getChild(conId, mbValue)) {
312 | tXmlEleP cfgEle = _xmlDocument->NewElement(XN_ITEM);
313 | cfgEle->SetAttribute(XA_VALUE, mbValue);
314 | if (append) {
315 | _containerElements[conId]->InsertEndChild(cfgEle);
316 | }
317 | else {
318 | _containerElements[conId]->InsertFirstChild(cfgEle);
319 | }
320 | sys_free(mbValue);
321 | _isDirty = true;
322 | }
323 | }
324 | }
325 |
326 | /** If a child of conId with value exists, moves it to the top, else adds a new
327 | element at the top and copies value to it. If it already exists at the top,
328 | does nothing. Does nothing if conId is kSettings or value is null or empty.
329 | @return true if any change was made, else false */
330 | bool moveToTop(ContainerId conId, LPCWSTR value)
331 | {
332 | if (conId != kSettings && value && *value) {
333 | LPSTR mbValue = str::utf16ToUtf8(value);
334 | if (mbValue) {
335 | tXmlEleP childEle = getChild(conId, mbValue);
336 | sys_free(mbValue);
337 | if (!childEle) { // not found so add it at the top
338 | addChild(conId, value, false);
339 | return true;
340 | }
341 | if (childEle->PreviousSiblingElement()) { // found and not at top so move it to the top
342 | _containerElements[conId]->InsertFirstChild(childEle);
343 | _isDirty = true;
344 | return true;
345 | }
346 | }
347 | }
348 | return false;
349 | }
350 |
351 | /** Deletes all child elements of the conId container. Does nothing if conId
352 | is kSettings. */
353 | void deleteChildren(ContainerId conId)
354 | {
355 | if (conId != kSettings) {
356 | _containerElements[conId]->DeleteChildren();
357 | _isDirty = true;
358 | }
359 | }
360 |
361 | //------------------------------------------------------------------------------
362 | // Application-specific functions built on top of the generic cfg functions.
363 |
364 | bool setSessionDirectory(LPCWSTR sesDir, bool confirmDefSes)
365 | {
366 | WCHAR buf[MAX_PATH];
367 |
368 | if (!sesDir || !*sesDir) {
369 | ::StringCchCopyW(buf, MAX_PATH, sys_getCfgDir());
370 | ::StringCchCatW(buf, MAX_PATH, DEFAULT_SES_DIR);
371 | }
372 | else {
373 | ::StringCchCopyW(buf, MAX_PATH, sesDir);
374 | pth::appendSlash(buf, MAX_PATH);
375 | if (!pth::dirExists(buf)) {
376 | if (::SHCreateDirectoryExW(NULL, buf, NULL) != ERROR_SUCCESS ) {
377 | DWORD le = ::GetLastError();
378 | msg::error(le, L"%s: Error creating session directory \"%s\".", _W(__FUNCTION__), buf);
379 | return false; // ses dir not changed
380 | }
381 | }
382 | }
383 | putStr(kSessionDirectory, buf);
384 | /* TODO: What if both kSessionDirectory and kSessionExtension are changing?
385 | Then app_confirmDefaultSession doesn't need to be called until after both have changed. */
386 | if (confirmDefSes) {
387 | app_confirmDefaultSession();
388 | }
389 | return true;
390 | }
391 |
392 | void setSessionExtension(LPCWSTR sesExt, bool confirmDefSes)
393 | {
394 | WCHAR buf[MAX_PATH];
395 |
396 | if (!sesExt || !*sesExt) {
397 | ::StringCchCopyW(buf, MAX_PATH, DEFAULT_SES_EXT);
398 | }
399 | else {
400 | buf[0] = L'\0';
401 | if (*sesExt != L'.') {
402 | buf[0] = L'.';
403 | buf[1] = L'\0';
404 | }
405 | ::StringCchCatW(buf, MAX_PATH, sesExt);
406 | }
407 | putStr(kSessionExtension, buf);
408 | if (confirmDefSes) {
409 | app_confirmDefaultSession();
410 | }
411 | }
412 |
413 | void setShowInTitlebar(bool enable)
414 | {
415 | putBool(kShowInTitlebar, enable);
416 | if (enable) {
417 | app_updateNppBars();
418 | }
419 | }
420 |
421 | void setShowInStatusbar(bool enable)
422 | {
423 | putBool(kShowInStatusbar, enable);
424 | if (enable) {
425 | app_updateNppBars();
426 | }
427 | }
428 |
429 | void getMarkStr(SettingId cfgId, LPWSTR buf)
430 | {
431 | buf[0] = getInt(cfgId);
432 | buf[1] = L'\t';
433 | buf[2] = 0;
434 | }
435 |
436 | bool isSortAlpha()
437 | {
438 | return getInt(kSessionSortOrder) == SORT_ORDER_ALPHA;
439 | }
440 |
441 | bool isFavorite(LPCWSTR fav)
442 | {
443 | bool isFav = false;
444 | LPSTR mbFav = str::utf16ToUtf8(fav);
445 | if (mbFav) {
446 | isFav = getChild(kFavorites, mbFav) != NULL;
447 | sys_free(mbFav);
448 | }
449 | return isFav;
450 | }
451 |
452 | } // end namespace NppPlugin::cfg
453 |
454 | //------------------------------------------------------------------------------
455 |
456 | namespace {
457 |
458 | /** Loads the settings.xml file if it has not already been loaded. Creates it if
459 | it doesn't exist. */
460 | bool readSettingsFile()
461 | {
462 | DWORD lastErr;
463 | tXmlError xmlErr;
464 | LPCWSTR settingsFile;
465 |
466 | if (!_xmlDocument) {
467 | settingsFile = sys_getSettingsFile();
468 | if (!pth::fileExists(settingsFile)) {
469 | pth::createFileIfMissing(settingsFile, INITIAL_CONTENTS);
470 | _isDirty = true;
471 | }
472 | _xmlDocument = new tinyxml2::XMLDocument();
473 | xmlErr = _xmlDocument->LoadFile(settingsFile);
474 | if (xmlErr != kXmlSuccess) {
475 | lastErr = ::GetLastError();
476 | msg::error(lastErr, L"%s: Error %u loading the settings file.", _W(__FUNCTION__), xmlErr);
477 | return false;
478 | }
479 | }
480 |
481 | return true;
482 | }
483 |
484 | /** Initializes the _containerElements array with pointers to the ContainerId
485 | elements. Creates missing elements. */
486 | void initContainers()
487 | {
488 | INT conId;
489 | tXmlEleP conEle, rootEle;
490 |
491 | rootEle = _xmlDocument->FirstChildElement(XN_ROOT);
492 | for (conId = 0; conId < kContainersCount; ++conId) {
493 | conEle = rootEle->FirstChildElement(_containerNames[conId]);
494 | if (!conEle) {
495 | conEle = _xmlDocument->NewElement(_containerNames[conId]);
496 | rootEle->InsertEndChild(conEle);
497 | _isDirty = true;
498 | }
499 | _containerElements[conId] = conEle;
500 | }
501 | }
502 |
503 | /** Initializes the _settings array. Creates missing elements. */
504 | void initSettings()
505 | {
506 | INT cfgId;
507 | tXmlEleP settingsEle, cfgEle, prvCfgEle = NULL;
508 |
509 | settingsEle = _containerElements[kSettings];
510 | for (cfgId = 0; cfgId < kSettingsCount; ++cfgId) {
511 | cfgEle = settingsEle->FirstChildElement(_settings[cfgId].cName);
512 | if (!cfgEle) {
513 | cfgEle = _xmlDocument->NewElement(_settings[cfgId].cName);
514 | cfgEle->SetAttribute(XA_VALUE, _settings[cfgId].cDefault);
515 | if (prvCfgEle) {
516 | settingsEle->InsertAfterChild(prvCfgEle, cfgEle);
517 | }
518 | else {
519 | settingsEle->InsertEndChild(cfgEle);
520 | }
521 | _isDirty = true;
522 | }
523 | if (!_settings[cfgId].isInt) {
524 | _settings[cfgId].wCache = (LPWSTR)sys_alloc(_settings[cfgId].wCacheSize * sizeof WCHAR);
525 | _settings[cfgId].wCache[0] = 0;
526 | }
527 | prvCfgEle = cfgEle;
528 | _settings[cfgId].element = cfgEle;
529 | updateCache(&_settings[cfgId]);
530 | }
531 | }
532 |
533 | /** Refreshes the cached value of the given setting. */
534 | void updateCache(Setting *setting)
535 | {
536 | LPCSTR value = setting->element->Attribute(XA_VALUE);
537 | if (!value || !*value) {
538 | value = setting->cDefault;
539 | }
540 | if (setting->isInt) {
541 | setting->iCache = ::atoi(value);
542 | }
543 | else {
544 | str::utf8ToUtf16(value, setting->wCache, setting->wCacheSize);
545 | }
546 | }
547 |
548 | /** Things that may need to be done after the configuration is loaded and initialized. */
549 | void afterLoad()
550 | {
551 | if (!*cfg::getStr(kSessionDirectory)) { // If needed, set default session directory.
552 | cfg::setSessionDirectory(NULL, false);
553 | }
554 | cfg::addChild(kFilters, L"*"); // Add "*" filter if it doesn't already exist.
555 | gDbgLvl = cfg::getInt(kDebugLogLevel); // Use a global for fastest access.
556 | }
557 |
558 | } // end namespace
559 |
560 | } // end namespace NppPlugin
561 |
--------------------------------------------------------------------------------
/src/Settings.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Settings.h
13 | @copyright Copyright 2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_SETTINGS_H
17 | #define NPP_PLUGIN_SETTINGS_H
18 |
19 | #include "SessionMgrApi.h"
20 | #include "xml\tinyxml.h"
21 |
22 | //------------------------------------------------------------------------------
23 |
24 | namespace NppPlugin {
25 |
26 | extern INT gDbgLvl;
27 |
28 | enum ContainerId {
29 | kSettings = 0,
30 | kFavorites,
31 | kFilters,
32 | kContainersCount
33 | };
34 |
35 | // See SessionMgrApi.h for enum SettingId
36 |
37 | #define SORT_ORDER_ALPHA 1
38 | #define SORT_ORDER_DATE 2
39 | #define FILTER_BUF_LEN 50
40 | #define FILTERS_MAX 100
41 |
42 | //------------------------------------------------------------------------------
43 | /// @namespace NppPlugin::api Contains functions called only from DllMain.
44 |
45 | namespace api {
46 |
47 | void cfg_onUnload();
48 |
49 | } // end namespace NppPlugin::api
50 |
51 | //------------------------------------------------------------------------------
52 | /// @namespace NppPlugin::cfg Implements management of configuration settings.
53 |
54 | namespace cfg {
55 |
56 | void loadSettings();
57 | void saveSettings();
58 | bool isDirty();
59 |
60 | // Functions that read or write child elements of the Settings container.
61 | LPCWSTR getStr(SettingId cfgId);
62 | void getStr(SettingId cfgId, LPWSTR buf, INT bufLen);
63 | bool getBool(SettingId cfgId);
64 | INT getInt(SettingId cfgId);
65 | void putStr(SettingId cfgId, LPCSTR value);
66 | void putStr(SettingId cfgId, LPCWSTR value);
67 | void putBool(SettingId cfgId, bool value);
68 | void putInt(SettingId cfgId, INT value);
69 |
70 | // Functions that read or write child elements of any container.
71 | LPCSTR getCStr(ContainerId conId, INT childIndex);
72 | LPCWSTR getStr(ContainerId conId, INT childIndex);
73 | bool getStr(ContainerId conId, INT childIndex, LPWSTR buf, INT bufLen);
74 | tXmlEleP getChild(ContainerId conId, LPCSTR value);
75 | void addChild(ContainerId conId, LPCWSTR value, bool append = true);
76 | bool moveToTop(ContainerId conId, LPCWSTR value);
77 | void deleteChildren(ContainerId conId);
78 |
79 | // Application-specific functions built on top of the generic cfg functions.
80 | bool setSessionDirectory(LPCWSTR sesDir, bool confirmDefSes = true);
81 | void setSessionExtension(LPCWSTR sesExt, bool confirmDefSes = true);
82 | void setShowInTitlebar(bool enable);
83 | void setShowInStatusbar(bool enable);
84 | void getMarkStr(SettingId cfgId, LPWSTR buf);
85 | bool isSortAlpha();
86 | bool isFavorite(LPCWSTR fav);
87 |
88 | } // end namespace NppPlugin::cfg
89 |
90 | } // end namespace NppPlugin
91 |
92 | #endif // NPP_PLUGIN_SETTINGS_H
93 |
--------------------------------------------------------------------------------
/src/System.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file System.cpp
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 | */
15 |
16 | #include "System.h"
17 | #include "SessionMgr.h"
18 | #include "Util.h"
19 | #include
20 | //#include // for findNppCtxMnuFile
21 |
22 | //------------------------------------------------------------------------------
23 |
24 | namespace NppPlugin {
25 |
26 | //------------------------------------------------------------------------------
27 |
28 | namespace {
29 |
30 | #define INI_FILE_NAME L"settings.ini"
31 | #define CFG_FILE_NAME L"settings.xml"
32 | #define CTX_FILE_NAME L"contextMenu.xml"
33 | #define GLB_FILE_NAME L"global.xml"
34 | #define GLB_DEFAULT_CONTENT "\n\n"
35 | #define BAK_DIR_NAME L"backup"
36 | #define BAK_SES_DIR_NAME L"sessions"
37 |
38 | HWND _hNpp;
39 | HWND _hSci1;
40 | HWND _hSci2;
41 | HANDLE _hHeap;
42 | HINSTANCE _hDll;
43 | UINT _nppVersion;
44 | UINT _winVersion;
45 | LPWSTR _cfgDir; ///< SessionMgr's config directory, includes trailing slash
46 | LPWSTR _cfgFile; ///< pathname of settings.xml
47 | LPWSTR _glbFile; ///< pathname of global.xml
48 | LPWSTR _ctxFile; ///< pathname of NPP's contextMenu.xml file
49 |
50 | //void findNppCtxMnuFile();
51 | void backupFiles();
52 | void backupConfigFiles(LPCWSTR backupDir);
53 | void backupSessionFiles(LPCWSTR backupDir);
54 |
55 | } // end namespace
56 |
57 | //------------------------------------------------------------------------------
58 |
59 | namespace api {
60 |
61 | void sys_onLoad(HINSTANCE hDLLInstance)
62 | {
63 | _hDll = hDLLInstance;
64 | }
65 |
66 | void sys_onUnload()
67 | {
68 | sys_free(_ctxFile);
69 | sys_free(_glbFile);
70 | sys_free(_cfgFile);
71 | sys_free(_cfgDir);
72 | }
73 |
74 | void sys_init(NppData nppd)
75 | {
76 | // Save NPP handles
77 | _hNpp = nppd._nppHandle;
78 | _hSci1 = nppd._scintillaMainHandle;
79 | _hSci2 = nppd._scintillaSecondHandle;
80 | _hHeap = ::GetProcessHeap();
81 |
82 | // Allocate buffers
83 | _cfgDir = (LPWSTR)sys_alloc(MAX_PATH * sizeof WCHAR);
84 | _cfgFile = (LPWSTR)sys_alloc(MAX_PATH * sizeof WCHAR);
85 | _glbFile = (LPWSTR)sys_alloc(MAX_PATH * sizeof WCHAR);
86 | _ctxFile = (LPWSTR)sys_alloc(MAX_PATH * sizeof WCHAR);
87 |
88 | _nppVersion = ::SendMessage(_hNpp, NPPM_GETNPPVERSION, 0, 0);
89 | _winVersion = ::SendMessage(_hNpp, NPPM_GETWINDOWSVERSION, 0, 0);
90 |
91 | // Get NPP's "plugins\Config" directory.
92 | ::SendMessage(_hNpp, NPPM_GETPLUGINSCONFIGDIR, MAX_PATH, (LPARAM)_ctxFile);
93 |
94 | // Get SessionMgr config directory and create it if missing.
95 | ::StringCchCopyW(_cfgDir, MAX_PATH, _ctxFile);
96 | pth::appendSlash(_cfgDir, MAX_PATH);
97 | ::StringCchCatW(_cfgDir, MAX_PATH, PLUGIN_DLL_NAME);
98 | ::StringCchCatW(_cfgDir, MAX_PATH, L"\\");
99 | ::CreateDirectoryW(_cfgDir, NULL);
100 |
101 | // Get the global.xml file pathname and create it if missing.
102 | ::StringCchCopyW(_glbFile, MAX_PATH, _cfgDir);
103 | ::StringCchCatW(_glbFile, MAX_PATH, GLB_FILE_NAME);
104 | pth::createFileIfMissing(_glbFile, GLB_DEFAULT_CONTENT);
105 |
106 | // Get the settings.xml file pathname and load the configuration.
107 | ::StringCchCopyW(_cfgFile, MAX_PATH, _cfgDir);
108 | ::StringCchCatW(_cfgFile, MAX_PATH, CFG_FILE_NAME);
109 | cfg::loadSettings();
110 | // Create sessions directory if missing.
111 | ::CreateDirectoryW(cfg::getStr(kSessionDirectory), NULL);
112 | // Create default session file if missing.
113 | app_confirmDefaultSession();
114 |
115 | // Get NPP's contextMenu.xml pathname (two directories up from "plugins\Config").
116 | LPWSTR p = ::wcsstr(_ctxFile, L"plugins\\Config");
117 | ::StringCchCopyW(p, MAX_PATH, CTX_FILE_NAME);
118 |
119 | // Backup existing config and session files.
120 | if (cfg::getBool(kBackupOnStartup)) {
121 | backupFiles();
122 | }
123 | }
124 |
125 | } // end namespace NppPlugin::api
126 |
127 | //------------------------------------------------------------------------------
128 |
129 | LPWSTR sys_getCfgDir()
130 | {
131 | return _cfgDir;
132 | }
133 |
134 | LPWSTR sys_getSettingsFile()
135 | {
136 | return _cfgFile;
137 | }
138 |
139 | LPWSTR sys_getGlobalFile()
140 | {
141 | return _glbFile;
142 | }
143 |
144 | LPCWSTR sys_getNppCtxMnuFile()
145 | {
146 | return _ctxFile;
147 | }
148 |
149 | HINSTANCE sys_getDllHandle()
150 | {
151 | return _hDll;
152 | }
153 |
154 | HWND sys_getNppHandle()
155 | {
156 | return _hNpp;
157 | }
158 |
159 | HWND sys_getSciHandle(INT v)
160 | {
161 | if (v == 1) return _hSci1;
162 | else if (v == 2) return _hSci2;
163 | else return NULL;
164 | }
165 |
166 | /** @return NPP version with major in hiword and minor in loword */
167 | DWORD sys_getNppVer()
168 | {
169 | return _nppVersion;
170 | }
171 |
172 | /** @return a winVer enum
173 | @see npp/Notepad_plus_msgs.h */
174 | UINT sys_getWinVer()
175 | {
176 | return _winVersion;
177 | }
178 |
179 | LPVOID sys_alloc(INT bytes)
180 | {
181 | LPVOID p = ::HeapAlloc(_hHeap, HEAP_ZERO_MEMORY, bytes);
182 | if (p == NULL) {
183 | LOG("Error allocating %u bytes.", bytes);
184 | msg::show(L"Memory allocation failed.", M_ERR);
185 | }
186 | return p;
187 | }
188 |
189 | void sys_free(LPVOID p)
190 | {
191 | if (p) ::HeapFree(_hHeap, 0, p);
192 | }
193 |
194 | //------------------------------------------------------------------------------
195 |
196 | namespace {
197 |
198 | /* Gets the pathname of NPP's contextMenu.xml. Now not used. Just assume the
199 | file is two directories up from "plugins\Config".
200 | void findNppCtxMnuFile()
201 | {
202 | ITEMIDLIST *pidl;
203 | bool isLocal = false;
204 | WCHAR tmp[MAX_PATH], nppDir[MAX_PATH];
205 |
206 | ::SendMessage(_hNpp, NPPM_GETNPPDIRECTORY, MAX_PATH, (LPARAM)nppDir);
207 | pth::appendSlash(nppDir, MAX_PATH);
208 | ::StringCchCopyW(tmp, MAX_PATH, nppDir);
209 | ::StringCchCatW(tmp, MAX_PATH, L"doLocalConf.xml");
210 | if (pth::fileExists(tmp)) {
211 | isLocal = true;
212 | LOGG(12, "Found doLocalConf.xml");
213 | }
214 |
215 | // See NppParameters::load in NPP's Parameters.cpp...
216 | if (isLocal && _winVersion >= WV_VISTA) {
217 | if (::SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAM_FILES, &pidl) == S_OK) {
218 | if (::SHGetPathFromIDList(pidl, tmp)) {
219 | LOGG(12, "prg=\"%S\", npp=\"%S\"", tmp, nppDir);
220 | if (::_wcsnicmp(tmp, nppDir, wcslen(tmp)) == 0) {
221 | isLocal = false;
222 | }
223 | }
224 | else LOGG(12, "SHGetPathFromIDList failed for CSIDL_PROGRAM_FILES");
225 | //::CoTaskMemFree(pidl);
226 | }
227 | else LOGG(12, "SHGetSpecialFolderLocation failed for CSIDL_PROGRAM_FILES");
228 | }
229 | ::StringCchCopyW(_ctxFile, MAX_PATH, nppDir);
230 | if (!isLocal) {
231 | if (::SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl) == S_OK) {
232 | if (::SHGetPathFromIDList(pidl, tmp)) {
233 | pth::appendSlash(tmp, MAX_PATH);
234 | ::StringCchCatW(tmp, MAX_PATH, L"Notepad++");
235 | if (pth::dirExists(tmp)) {
236 | LOGG(12, "Found \"%S\"", tmp);
237 | ::StringCchCopyW(_ctxFile, MAX_PATH, tmp);
238 | }
239 | else LOGG(12, "Could not find \"%S\"", tmp);
240 | }
241 | else LOGG(12, "SHGetPathFromIDList failed for CSIDL_APPDATA");
242 | //::CoTaskMemFree(pidl);
243 | }
244 | else LOGG(12, "SHGetSpecialFolderLocation failed for CSIDL_APPDATA");
245 | }
246 |
247 | pth::appendSlash(_ctxFile, MAX_PATH);
248 | ::StringCchCatW(_ctxFile, MAX_PATH, CTX_FILE_NAME);
249 | LOGG(12, "Will use \"%S\"", _ctxFile);
250 | }
251 | */
252 |
253 | void backupFiles()
254 | {
255 | WCHAR backupDir[MAX_PATH];
256 |
257 | // Create main backup directory if missing and copy config files.
258 | ::StringCchCopyW(backupDir, MAX_PATH, _cfgDir);
259 | ::StringCchCatW(backupDir, MAX_PATH, BAK_DIR_NAME);
260 | if (!pth::dirExists(backupDir)) {
261 | ::CreateDirectoryW(backupDir, NULL);
262 | }
263 | if (pth::dirExists(backupDir)) {
264 | ::StringCchCatW(backupDir, MAX_PATH, L"\\");
265 | backupConfigFiles(backupDir);
266 | // Create backup directory for session files if missing and copy session files.
267 | ::StringCchCatW(backupDir, MAX_PATH, BAK_SES_DIR_NAME);
268 | if (!pth::dirExists(backupDir)) {
269 | ::CreateDirectoryW(backupDir, NULL);
270 | }
271 | if (pth::dirExists(backupDir)) {
272 | ::StringCchCatW(backupDir, MAX_PATH, L"\\");
273 | backupSessionFiles(backupDir);
274 | }
275 | }
276 | }
277 |
278 | void backupConfigFiles(LPCWSTR backupDir)
279 | {
280 | WCHAR dstFile[MAX_PATH];
281 |
282 | // Copy settings.xml
283 | if (pth::fileExists(_cfgFile)) {
284 | ::StringCchCopyW(dstFile, MAX_PATH, backupDir);
285 | ::StringCchCatW(dstFile, MAX_PATH, CFG_FILE_NAME);
286 | ::CopyFileW(_cfgFile, dstFile, FALSE);
287 | }
288 | // Copy global.xml
289 | if (pth::fileExists(_glbFile)) {
290 | ::StringCchCopyW(dstFile, MAX_PATH, backupDir);
291 | ::StringCchCatW(dstFile, MAX_PATH, GLB_FILE_NAME);
292 | ::CopyFileW(_glbFile, dstFile, FALSE);
293 | }
294 | // Copy NPP's contextMenu.xml
295 | if (pth::fileExists(_ctxFile)) {
296 | ::StringCchCopyW(dstFile, MAX_PATH, backupDir);
297 | ::StringCchCatW(dstFile, MAX_PATH, CTX_FILE_NAME);
298 | ::CopyFileW(_ctxFile, dstFile, FALSE);
299 | }
300 | }
301 |
302 | void backupSessionFiles(LPCWSTR backupDir)
303 | {
304 | HANDLE hFind;
305 | WIN32_FIND_DATAW ffd;
306 | WCHAR fileSpec[MAX_PATH];
307 | WCHAR srcFile[MAX_PATH];
308 | WCHAR dstFile[MAX_PATH];
309 |
310 | // Create the file spec.
311 | ::StringCchCopyW(fileSpec, MAX_PATH, cfg::getStr(kSessionDirectory));
312 | ::StringCchCatW(fileSpec, MAX_PATH, L"*.*");
313 | // Loop over files in the session directory and copy them to the backup directory.
314 | hFind = ::FindFirstFileW(fileSpec, &ffd);
315 | if (hFind == INVALID_HANDLE_VALUE) {
316 | return;
317 | }
318 | do {
319 | ::StringCchCopyW(srcFile, MAX_PATH, cfg::getStr(kSessionDirectory));
320 | ::StringCchCatW(srcFile, MAX_PATH, ffd.cFileName);
321 | ::StringCchCopyW(dstFile, MAX_PATH, backupDir);
322 | ::StringCchCatW(dstFile, MAX_PATH, ffd.cFileName);
323 | ::CopyFileW(srcFile, dstFile, FALSE);
324 | }
325 | while (::FindNextFileW(hFind, &ffd) != 0);
326 | ::FindClose(hFind);
327 | }
328 |
329 | } // end namespace
330 |
331 | } // end namespace NppPlugin
332 |
333 |
--------------------------------------------------------------------------------
/src/System.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file System.h
13 | @copyright Copyright 2011,2014,2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_SYSTEM_H
17 | #define NPP_PLUGIN_SYSTEM_H
18 |
19 | #define SES_DEFAULT_CONTENTS "\n\n"
20 |
21 | #include
22 | #include "npp\PluginInterface.h"
23 |
24 | //------------------------------------------------------------------------------
25 |
26 | namespace NppPlugin {
27 |
28 | //------------------------------------------------------------------------------
29 | /// @namespace NppPlugin::api Contains functions called only from DllMain.
30 |
31 | namespace api {
32 |
33 | void sys_onLoad(HINSTANCE hDLLInstance);
34 | void sys_onUnload();
35 | void sys_init(NppData nppd);
36 |
37 | } // end namespace NppPlugin::api
38 |
39 | //------------------------------------------------------------------------------
40 |
41 | LPWSTR sys_getCfgDir();
42 | LPWSTR sys_getSettingsFile();
43 | LPWSTR sys_getGlobalFile();
44 | LPCWSTR sys_getNppCtxMnuFile();
45 | HINSTANCE sys_getDllHandle();
46 | HWND sys_getNppHandle();
47 | HWND sys_getSciHandle(INT v);
48 | DWORD sys_getNppVer();
49 | UINT sys_getWinVer();
50 | LPVOID sys_alloc(INT bytes);
51 | void sys_free(LPVOID p);
52 |
53 | } // end namespace NppPlugin
54 |
55 | #endif // NPP_PLUGIN_SYSTEM_H
56 |
--------------------------------------------------------------------------------
/src/Util.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Util.cpp
13 | @copyright Copyright 2011-2015 Michael Foster
14 | */
15 |
16 | #include "System.h"
17 | #include "SessionMgr.h"
18 | #include "Util.h"
19 | #include "utf8\unchecked.h"
20 | #include
21 |
22 | //------------------------------------------------------------------------------
23 |
24 | namespace NppPlugin {
25 |
26 | //------------------------------------------------------------------------------
27 |
28 | namespace msg {
29 |
30 | /** Displays a simple message box. For title/options see the M_* constants. */
31 | INT show(LPCWSTR msg, LPWSTR title, UINT options)
32 | {
33 | return ::MessageBoxW(sys_getNppHandle(), msg, title != NULL ? title : PLUGIN_FULL_NAME, options);
34 | }
35 |
36 | /** Displays an error message and logs it. lastError is expected to be from GetLastError. */
37 | void error(DWORD lastError, LPCWSTR format, ...)
38 | {
39 | INT len;
40 | va_list argptr;
41 | LPWSTR buf, buf1, buf2 = NULL, lem, lastErrorMsg = NULL;
42 |
43 | va_start(argptr, format);
44 | len = ::_vscwprintf(format, argptr);
45 | buf1 = (LPWSTR)sys_alloc((len + 2) * sizeof(WCHAR));
46 | if (buf1 == NULL) {
47 | log("Error allocating %u bytes for: \"%S\".", (len + 2) * sizeof(WCHAR), format);
48 | return;
49 | }
50 | ::vswprintf_s(buf1, len + 1, format, argptr);
51 | va_end(argptr);
52 | buf = buf1;
53 |
54 | if (lastError) {
55 | FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
56 | NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lastErrorMsg, 0, NULL);
57 | lem = lastErrorMsg == NULL ? EMPTY_STR : lastErrorMsg;
58 | LPCWSTR fmt = L"%s\nError %lu: %s";
59 | len = ::_scwprintf(fmt, buf1, lastError, lem);
60 | buf2 = (LPWSTR)sys_alloc((len + 2) * sizeof(WCHAR));
61 | if (buf2) {
62 | ::swprintf_s(buf2, len + 1, fmt, buf1, lastError, lem);
63 | buf = buf2;
64 | }
65 | }
66 |
67 | show(buf, M_ERR);
68 | log("%S", buf);
69 | sys_free(buf1);
70 | sys_free(buf2);
71 | if (lastErrorMsg) {
72 | LocalFree((HLOCAL)lastErrorMsg);
73 | }
74 | }
75 |
76 | /** Writes a formatted UTF-8 string to the debug log file. In format, use "%s"
77 | for ASCII strings and "%S" for wide strings. */
78 | void log(LPCSTR format, ...)
79 | {
80 | if (gDbgLvl) {
81 | LPCWSTR logFile = cfg::getStr(kDebugLogFile);
82 | if (logFile && *logFile) {
83 | FILE *fp;
84 | ::_wfopen_s(&fp, logFile, L"a+");
85 | if (fp) {
86 | va_list argptr;
87 | va_start(argptr, format);
88 | ::vfprintf(fp, format, argptr); // Expects 'format' to be UTF-8, vfwprintf would write UTF-16
89 | va_end(argptr);
90 | ::fputwc(L'\n', fp);
91 | ::fflush(fp);
92 | ::fclose(fp);
93 | }
94 | }
95 | }
96 | }
97 |
98 | } // end namespace NppPlugin::msg
99 |
100 | //------------------------------------------------------------------------------
101 |
102 | namespace pth {
103 |
104 | /** Removes the file name extension.
105 | @return non-zero on error */
106 | errno_t removeExt(LPWSTR buf, size_t bufLen)
107 | {
108 | errno_t err;
109 | WCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME];
110 | err = ::_wsplitpath_s(buf, drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, NULL, 0);
111 | if (err == 0) {
112 | err = ::_wmakepath_s(buf, bufLen, drive, dir, fname, NULL);
113 | }
114 | return err;
115 | }
116 |
117 | /** Removes the file name, leaving only the path and trailing slash.
118 | @return non-zero on error */
119 | errno_t removeName(LPWSTR buf, size_t bufLen)
120 | {
121 | errno_t err;
122 | WCHAR drive[_MAX_DRIVE], dir[_MAX_DIR];
123 | err = ::_wsplitpath_s(buf, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
124 | if (err == 0) {
125 | err = ::_wmakepath_s(buf, bufLen, drive, dir, NULL, NULL);
126 | }
127 | return err;
128 | }
129 |
130 | /** Removes the path, leaving only the file name.
131 | @return non-zero on error */
132 | errno_t removePath(LPWSTR buf, size_t bufLen)
133 | {
134 | errno_t err;
135 | WCHAR fname[_MAX_FNAME], ext[_MAX_EXT];
136 | err = ::_wsplitpath_s(buf, NULL, 0, NULL, 0, fname, _MAX_FNAME, ext, _MAX_EXT);
137 | if (err == 0) {
138 | err = ::_wmakepath_s(buf, bufLen, NULL, NULL, fname, ext);
139 | }
140 | return err;
141 | }
142 |
143 | /** Appends a backslash if a trailing backslash or foreslash is not already present. */
144 | void appendSlash(LPWSTR buf, size_t bufLen)
145 | {
146 | LPWSTR p;
147 | if (buf != NULL) {
148 | p = ::wcsrchr(buf, L'\0');
149 | if (p != NULL) {
150 | p = ::CharPrevW(buf, p);
151 | if (p != NULL && *p != L'\\' && *p != L'/') {
152 | ::StringCchCatW(buf, bufLen, L"\\");
153 | }
154 | }
155 | }
156 | }
157 |
158 | /** @return true if path is an existing directory */
159 | bool dirExists(LPCWSTR path)
160 | {
161 | DWORD a = ::GetFileAttributesW(path);
162 | return (bool)(a != INVALID_FILE_ATTRIBUTES && (a & FILE_ATTRIBUTE_DIRECTORY));
163 | }
164 |
165 | /** @return true if pathname is an existing file */
166 | bool fileExists(LPCWSTR pathname)
167 | {
168 | DWORD a = ::GetFileAttributesW(pathname);
169 | return (bool)(a != INVALID_FILE_ATTRIBUTES && !(a & FILE_ATTRIBUTE_DIRECTORY));
170 | }
171 |
172 | /** Creates a new file with initial contents, if the file doesn't already exist. */
173 | void createFileIfMissing(LPCWSTR pathname, LPCSTR contents)
174 | {
175 | BOOL suc;
176 | HANDLE hFile;
177 | DWORD len, bytes;
178 |
179 | hFile = ::CreateFileW(pathname, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
180 | if (hFile != INVALID_HANDLE_VALUE) {
181 | len = ::strlen(contents);
182 | suc = ::WriteFile(hFile, contents, len, &bytes, NULL);
183 | if (!suc || bytes != len) {
184 | WCHAR msg[MAX_PATH];
185 | ::StringCchCopyW(msg, MAX_PATH, L"Failed creating file: ");
186 | ::StringCchCatW(msg, MAX_PATH, pathname);
187 | msg::show(msg, M_ERR);
188 | }
189 | ::CloseHandle(hFile);
190 | }
191 | }
192 |
193 | } // end namespace NppPlugin::pth
194 |
195 | //------------------------------------------------------------------------------
196 |
197 | namespace str {
198 |
199 | /** Writes src to dst with ampersands removed. */
200 | void removeAmp(LPCWSTR src, LPWSTR dst)
201 | {
202 | while (*src != 0) {
203 | if (*src != L'&') {
204 | *dst++ = *src;
205 | }
206 | ++src;
207 | }
208 | *dst = 0;
209 | }
210 |
211 | /** Writes src to dst with ampersands removed. */
212 | void removeAmp(LPCSTR src, LPSTR dst)
213 | {
214 | while (*src != 0) {
215 | if (*src != '&') {
216 | *dst++ = *src;
217 | }
218 | ++src;
219 | }
220 | *dst = 0;
221 | }
222 |
223 | /** Case-insensitive wildcard match. */
224 | bool wildcardMatchI(LPCWSTR wild, LPCWSTR str)
225 | {
226 | WCHAR lcWild[MAX_PATH], lcStr[MAX_PATH];
227 |
228 | ::StringCchCopyW(lcWild, MAX_PATH, wild);
229 | ::StringCchCopyW(lcStr, MAX_PATH, str);
230 | ::CharLower(lcWild);
231 | ::CharLower(lcStr);
232 | return wildcardMatch(lcWild, lcStr);
233 | }
234 |
235 | /** Originally written by Jack Handy and slightly modified by Mike Foster.
236 | @see http://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing */
237 | bool wildcardMatch(LPCWSTR wild, LPCWSTR str)
238 | {
239 | LPCWSTR cp = NULL, mp = NULL;
240 |
241 | while (*str && *wild != L'*') {
242 | if (*wild != *str && *wild != L'?') {
243 | return false;
244 | }
245 | wild++;
246 | str++;
247 | }
248 |
249 | while (*str) {
250 | if (*wild == L'*') {
251 | if (!*++wild) {
252 | return true;
253 | }
254 | mp = wild;
255 | cp = str + 1;
256 | }
257 | else if (*wild == *str || *wild == L'?') {
258 | wild++;
259 | str++;
260 | }
261 | else {
262 | wild = mp;
263 | str = cp++;
264 | }
265 | }
266 |
267 | while (*wild == L'*') {
268 | wild++;
269 | }
270 |
271 | return !*wild;
272 | }
273 |
274 | /** Converts a UTF-8 string to a string where all chars < 32 or > 126 are
275 | converted to entities. Pass NULL for buf to get the size needed for buf.
276 | @return the number of bytes in the converted string including the terminator */
277 | INT utf8ToAscii(LPCSTR str, LPSTR buf)
278 | {
279 | INT bytes = 0;
280 | LPSTR b = buf;
281 | LPCSTR s = str;
282 | utf8::uint32_t cp;
283 | while (*s) {
284 | cp = utf8::unchecked::next(s);
285 | if (cp < 32 || cp > 126) {
286 | if (buf) {
287 | ::sprintf_s(b, 9, "%04X;", cp);
288 | b += 8;
289 | }
290 | bytes += 8;
291 | }
292 | else {
293 | if (buf) {
294 | *b++ = (unsigned char)cp;
295 | }
296 | ++bytes;
297 | }
298 | }
299 | if (buf) {
300 | *b = 0;
301 | }
302 | return bytes + 1;
303 | }
304 |
305 | /** cStr must be zero-terminated.
306 | @return a pointer to an allocated buffer which caller must free, else NULL
307 | on error */
308 | LPWSTR utf8ToUtf16(LPCSTR cStr)
309 | {
310 | return utf8ToUtf16(cStr, NULL, 0);
311 | }
312 |
313 | /** cStr must be zero-terminated.
314 | @return if buf is NULL, a pointer to an allocated buffer which caller must
315 | free, else buf, or NULL on error */
316 | LPWSTR utf8ToUtf16(LPCSTR cStr, LPWSTR buf, size_t bufLen)
317 | {
318 | size_t wLen;
319 | DWORD lastError;
320 | LPWSTR wBuf = NULL;
321 |
322 | wLen = ::MultiByteToWideChar(CP_UTF8, 0, cStr, -1, NULL, 0);
323 | if (wLen > 0) {
324 | if (buf) {
325 | if (bufLen >= wLen) {
326 | if (::MultiByteToWideChar(CP_UTF8, 0, cStr, -1, buf, bufLen)) {
327 | wBuf = buf;
328 | }
329 | else {
330 | lastError = ::GetLastError();
331 | LOG("Error %lu for \"%s\".", lastError, cStr);
332 | }
333 | }
334 | else {
335 | LOG("Error. Provided buffer size (%i) is smaller than required (%i) for \"%s\".", bufLen, wLen, cStr);
336 | }
337 | }
338 | else {
339 | wBuf = (LPWSTR)sys_alloc(wLen * sizeof(WCHAR));
340 | if (wBuf) {
341 | if (!::MultiByteToWideChar(CP_UTF8, 0, cStr, -1, wBuf, wLen)) {
342 | lastError = ::GetLastError();
343 | LOG("Error %lu for \"%s\".", lastError, cStr);
344 | sys_free(wBuf);
345 | wBuf = NULL;
346 | }
347 | }
348 | else {
349 | LOG("Error allocating %u bytes for \"%s\".", wLen * sizeof(WCHAR), cStr);
350 | }
351 | }
352 | }
353 | else {
354 | lastError = ::GetLastError();
355 | LOG("Error %lu. Invalid characters in \"%s\".", lastError, cStr);
356 | }
357 |
358 | return wBuf;
359 | }
360 |
361 | /** wStr must be zero-terminated.
362 | @return a pointer to an allocated buffer which caller must free, else NULL
363 | on error */
364 | LPSTR utf16ToUtf8(LPCWSTR wStr)
365 | {
366 | return utf16ToUtf8(wStr, NULL, 0);
367 | }
368 |
369 | /** wStr must be zero-terminated.
370 | @return if buf is NULL, a pointer to an allocated buffer which caller must
371 | free, else buf, or NULL on error */
372 | LPSTR utf16ToUtf8(LPCWSTR wStr, LPSTR buf, size_t bufLen)
373 | {
374 | size_t cLen;
375 | DWORD lastError;
376 | LPSTR cBuf = NULL;
377 |
378 | cLen = ::WideCharToMultiByte(CP_UTF8, 0, wStr, -1, NULL, 0, NULL, NULL);
379 | if (cLen > 0) {
380 | if (buf) {
381 | if (bufLen >= cLen) {
382 | if (::WideCharToMultiByte(CP_UTF8, 0, wStr, -1, buf, bufLen, NULL, NULL)) {
383 | cBuf = buf;
384 | }
385 | else {
386 | lastError = ::GetLastError();
387 | LOG("Error %lu for \"%S\".", lastError, wStr);
388 | }
389 | }
390 | else {
391 | LOG("Error. Provided buffer size (%i) is smaller than required (%i) for \"%S\".", bufLen, cLen, wStr);
392 | }
393 | }
394 | else {
395 | cBuf = (LPSTR)sys_alloc(cLen * sizeof(CHAR));
396 | if (cBuf) {
397 | if (!::WideCharToMultiByte(CP_UTF8, 0, wStr, -1, cBuf, cLen, NULL, NULL)) {
398 | lastError = ::GetLastError();
399 | LOG("Error %lu for \"%S\".", lastError, wStr);
400 | sys_free(cBuf);
401 | cBuf = NULL;
402 | }
403 | }
404 | else {
405 | LOG("Error allocating %u bytes for \"%S\".", cLen * sizeof(WCHAR), wStr);
406 | }
407 | }
408 | }
409 | else {
410 | lastError = ::GetLastError();
411 | LOG("Error %lu. Invalid characters in \"%S\".", lastError, wStr);
412 | }
413 |
414 | return cBuf;
415 | }
416 |
417 | } // end namespace NppPlugin::str
418 |
419 | //------------------------------------------------------------------------------
420 |
421 | namespace dlg {
422 |
423 | void setText(HWND hDlg, UINT idCtrl, LPCWSTR text)
424 | {
425 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
426 | if (hCtrl) {
427 | ::SetWindowTextW(hCtrl, text);
428 | redrawControl(hDlg, hCtrl);
429 | }
430 | }
431 |
432 | void getText(HWND hDlg, UINT idCtrl, LPWSTR buf, size_t bufLen)
433 | {
434 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
435 | if (hCtrl) {
436 | buf[0] = 0;
437 | ::GetWindowTextW(hCtrl, buf, bufLen);
438 | //::SendMessage(hCtrl, WM_GETTEXT, bufLen, (LPARAM)buf);
439 | }
440 | }
441 |
442 | bool edtModified(HWND hDlg, UINT idCtrl)
443 | {
444 | bool modified = false;
445 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
446 | if (hCtrl) {
447 | if (::SendMessage(hCtrl, EM_GETMODIFY, 0, 0)) {
448 | modified = true;
449 | }
450 | }
451 | return modified;
452 | }
453 |
454 | void setCheck(HWND hDlg, UINT idCtrl, bool bChecked)
455 | {
456 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
457 | if (hCtrl) {
458 | ::SendMessage(hCtrl, BM_SETCHECK, (WPARAM) (bChecked ? BST_CHECKED : BST_UNCHECKED), 0);
459 | }
460 | }
461 |
462 | bool getCheck(HWND hDlg, UINT idCtrl)
463 | {
464 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
465 | if (hCtrl) {
466 | return (::SendMessage(hCtrl, BM_GETCHECK, 0, 0) == BST_CHECKED) ? true : false;
467 | }
468 | return false;
469 | }
470 |
471 | void focus(HWND hDlg, UINT idCtrl, bool inInit)
472 | {
473 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
474 | if (hCtrl) {
475 | if (inInit) {
476 | ::SetFocus(hCtrl);
477 | }
478 | else {
479 | ::SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hCtrl, TRUE);
480 | }
481 | }
482 | }
483 |
484 | void lbReplaceSelItem(HWND hDlg, UINT idCtrl, LPCWSTR text, LPARAM data)
485 | {
486 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
487 | if (hCtrl) {
488 | ::SendMessage(hCtrl, WM_SETREDRAW, FALSE, 0);
489 | WPARAM lbItemIdx = ::SendMessage(hCtrl, LB_GETCURSEL, 0, 0);
490 | if (::SendMessage(hCtrl, LB_DELETESTRING, lbItemIdx, 0) != LB_ERR) {
491 | if (::SendMessage(hCtrl, LB_INSERTSTRING, lbItemIdx, (LPARAM)text) != LB_ERR) {
492 | ::SendMessage(hCtrl, LB_SETITEMDATA, lbItemIdx, (LPARAM)data);
493 | ::SendMessage(hCtrl, WM_SETREDRAW, TRUE, 0);
494 | ::SendMessage(hCtrl, LB_SETCURSEL, lbItemIdx, 0);
495 | }
496 | }
497 | }
498 | }
499 |
500 | LRESULT getLbSelData(HWND hDlg, UINT idCtrl)
501 | {
502 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
503 | if (hCtrl) {
504 | WPARAM i = ::SendMessage(hCtrl, LB_GETCURSEL, 0, 0);
505 | return ::SendMessage(hCtrl, LB_GETITEMDATA, i, 0);
506 | }
507 | return NULL;
508 | }
509 |
510 | void getCbSelText(HWND hDlg, UINT idCtrl, LPWSTR buf)
511 | {
512 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
513 | if (hCtrl) {
514 | WPARAM i = ::SendMessage(hCtrl, CB_GETCURSEL, 0, 0);
515 | ::SendMessage(hCtrl, CB_GETLBTEXT, i, (LPARAM)buf);
516 | }
517 | }
518 |
519 | /** @see http://stackoverflow.com/questions/1823883/updating-text-in-a-c-win32-api-static-control-drawn-with-ws-ex-transparent */
520 | void redrawControl(HWND hDlg, HWND hCtrl)
521 | {
522 | RECT r;
523 | ::GetClientRect(hCtrl, &r);
524 | ::InvalidateRect(hCtrl, &r, TRUE);
525 | ::MapWindowPoints(hCtrl, hDlg, (POINT *)&r, 2);
526 | ::RedrawWindow(hDlg, &r, NULL, RDW_ERASE | RDW_INVALIDATE);
527 | }
528 |
529 | /** Centers window hWnd relative to window hParentWnd with the given sizes and offsets. */
530 | void centerWnd(HWND hWnd, HWND hParentWnd, INT xOffset, INT yOffset, INT width, INT height, bool bRepaint)
531 | {
532 | RECT rect, rectParent;
533 | INT x, y;
534 | if (hParentWnd == NULL) {
535 | hParentWnd = ::GetParent(hWnd);
536 | }
537 | ::GetWindowRect(hParentWnd, &rectParent);
538 | ::GetWindowRect(hWnd, &rect);
539 | width = width > 0 ? width : rect.right - rect.left;
540 | height = height > 0 ? height : rect.bottom - rect.top;
541 | x = ((rectParent.right - rectParent.left) - width) / 2;
542 | x += rectParent.left + xOffset;
543 | y = ((rectParent.bottom - rectParent.top) - height) / 2;
544 | y += rectParent.top + yOffset;
545 | ::MoveWindow(hWnd, x, y, width, height, bRepaint);
546 | }
547 |
548 | /** Sets the control's position and/or size relative to the right and bottom
549 | edges of the dialog.
550 | @param toChange X=1, Y=2, W=4, H=8
551 | @param duoRight offset from dialog right edge in dialog units
552 | @param duoBottom offset from dialog bottom edge in dialog units
553 | @param redraw if true, the control will be redrawn, sometimes needed for
554 | the last row of controls on a dialog
555 | */
556 | void adjToEdge(HWND hDlg, INT idCtrl, INT dlgW, INT dlgH, INT toChange, INT duoRight, INT duoBottom, bool redraw)
557 | {
558 | HWND hCtrl = ::GetDlgItem(hDlg, idCtrl);
559 | if (hCtrl) {
560 | RECT ro = {0, 0, duoRight, duoBottom};
561 | ::MapDialogRect(hDlg, &ro);
562 | RECT rc;
563 | POINT p;
564 | ::GetWindowRect(hCtrl, &rc);
565 |
566 | p.x = rc.left;
567 | p.y = rc.top;
568 | ::ScreenToClient(hDlg, &p);
569 | rc.left = p.x;
570 | rc.top = p.y;
571 |
572 | p.x = rc.right;
573 | p.y = rc.bottom;
574 | ::ScreenToClient(hDlg, &p);
575 | rc.right = p.x;
576 | rc.bottom = p.y;
577 |
578 | INT x = rc.left;
579 | INT y = rc.top;
580 | INT w = rc.right - rc.left;
581 | INT h = rc.bottom - rc.top;
582 |
583 | // change x with offset from client right
584 | if (toChange & 1) {
585 | if (duoRight) {
586 | x = dlgW - ro.right;
587 | }
588 | }
589 | // or change width with offset from client right
590 | else if (toChange & 4) {
591 | if (duoRight) {
592 | w = dlgW - ro.right - x;
593 | }
594 | }
595 | // change y with offset from client bottom
596 | if (toChange & 2) {
597 | if (duoBottom) {
598 | y = dlgH - ro.bottom;
599 | }
600 | }
601 | // or change height with offset from client bottom
602 | else if (toChange & 8) {
603 | if (duoBottom) {
604 | h = dlgH - ro.bottom - y;
605 | }
606 | }
607 |
608 | ::MoveWindow(hCtrl, x, y, w, h, true);
609 | if (redraw) {
610 | redrawControl(hDlg, hCtrl);
611 | }
612 | }
613 | }
614 |
615 | } // end namespace NppPlugin::dlg
616 |
617 | } // end namespace NppPlugin
618 |
619 |
--------------------------------------------------------------------------------
/src/Util.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file Util.h
13 | @copyright Copyright 2011-2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_UTIL_H
17 | #define NPP_PLUGIN_UTIL_H
18 |
19 | #include "Settings.h"
20 |
21 | //------------------------------------------------------------------------------
22 |
23 | namespace NppPlugin {
24 |
25 | #define LOG(fmt, ...) msg::log(__FUNCTION__ ": " fmt, __VA_ARGS__)
26 | #define LOGF(fmt, ...) msg::log(__FUNCTION__ "(" fmt ")", __VA_ARGS__)
27 | #define LOGG(lvl, fmt, ...) if (gDbgLvl >= lvl) { LOG(fmt, __VA_ARGS__); }
28 | #define LOGE(lvl, fmt, ...) if (gDbgLvl == lvl) { LOG(fmt, __VA_ARGS__); }
29 | #define LOGR(l1, l2, fmt, ...) if (gDbgLvl >= l1 && gDbgLvl <= l2) { LOG(fmt, __VA_ARGS__); }
30 | #define LOGNN(ntf) LOG("%-20s\t%8u\t%u", ntf, bufferId, _bidBufferActivated)
31 | #define LOGSN(ntf) LOG("%-20s\t%8s\t%u", ntf, "", _bidBufferActivated)
32 | #define __W(x) L ## x
33 | #define _W(x) __W(x)
34 | #define EMPTY_STR L""
35 | #define SPACE_STR L" "
36 | // msg::show title and options
37 | #define M_DBG PLUGIN_FULL_NAME SPACE_STR L"Debug", (MB_OK | MB_ICONWARNING)
38 | #define M_ERR PLUGIN_FULL_NAME SPACE_STR L"Error", (MB_OK | MB_ICONERROR)
39 | #define M_WARN PLUGIN_FULL_NAME SPACE_STR L"Warning", (MB_OK | MB_ICONWARNING)
40 | #define M_INFO PLUGIN_FULL_NAME, (MB_OK | MB_ICONINFORMATION)
41 |
42 | inline LPCWSTR boolToStr(const bool b) { return b ? L"true" : L"false"; }
43 | inline const bool uintToBool(UINT n) { return n == 0 ? false : true; }
44 |
45 | //------------------------------------------------------------------------------
46 | /** @namespace NppPlugin::msg Contains functions for displaying error and
47 | informational messages to the user and for logging to the debug log file. */
48 |
49 | namespace msg {
50 |
51 | INT show(LPCWSTR msg, LPWSTR title = NULL, UINT options = MB_OK);
52 | void error(DWORD lastError, LPCWSTR format, ...);
53 | void log(LPCSTR format, ...);
54 |
55 | } // end namespace NppPlugin::msg
56 |
57 | //------------------------------------------------------------------------------
58 | /** @namespace NppPlugin::pth Contains functions for manipulating file paths,
59 | checking the existence of directories and files, and creating new files. */
60 |
61 | namespace pth {
62 |
63 | errno_t removeExt(LPWSTR buf, size_t bufLen);
64 | errno_t removeName(LPWSTR buf, size_t bufLen);
65 | errno_t removePath(LPWSTR buf, size_t bufLen);
66 | void appendSlash(LPWSTR buf, size_t bufLen);
67 | bool dirExists(LPCWSTR path);
68 | bool fileExists(LPCWSTR pathname);
69 | void createFileIfMissing(LPCWSTR pathname, LPCSTR contents);
70 |
71 | } // end namespace NppPlugin::pth
72 |
73 | //------------------------------------------------------------------------------
74 | /// @namespace NppPlugin::str Contains string utility functions.
75 |
76 | namespace str {
77 |
78 | void removeAmp(LPCWSTR src, LPWSTR dst);
79 | void removeAmp(LPCSTR src, LPSTR dst);
80 | bool wildcardMatchI(LPCWSTR wild, LPCWSTR str);
81 | bool wildcardMatch(LPCWSTR wild, LPCWSTR str);
82 | INT utf8ToAscii(LPCSTR str, LPSTR buf = NULL);
83 | LPWSTR utf8ToUtf16(LPCSTR cStr);
84 | LPWSTR utf8ToUtf16(LPCSTR cStr, LPWSTR buf, size_t bufLen);
85 | LPSTR utf16ToUtf8(LPCWSTR wStr);
86 | LPSTR utf16ToUtf8(LPCWSTR wStr, LPSTR buf, size_t bufLen);
87 |
88 | } // end namespace NppPlugin::str
89 |
90 | //------------------------------------------------------------------------------
91 | /// @namespace NppPlugin::dlg Contains functions for managing dialog controls.
92 |
93 | namespace dlg {
94 |
95 | void setText(HWND hDlg, UINT idCtrl, LPCWSTR text);
96 | void getText(HWND hDlg, UINT idCtrl, LPWSTR buf, size_t bufLen);
97 | bool edtModified(HWND hDlg, UINT idCtrl);
98 | void setCheck(HWND hDlg, UINT idCtrl, bool bChecked);
99 | bool getCheck(HWND hDlg, UINT idCtrl);
100 | void focus(HWND hDlg, UINT idCtrl, bool inInit = true);
101 | void lbReplaceSelItem(HWND hDlg, UINT idCtrl, LPCWSTR text, LPARAM data);
102 | LRESULT getLbSelData(HWND hDlg, UINT idCtrl);
103 | void getCbSelText(HWND hDlg, UINT idCtrl, LPWSTR buf);
104 | void redrawControl(HWND hDlg, HWND hCtrl);
105 | void centerWnd(HWND hWnd, HWND hParentWnd, INT xOffset = 0, INT yOffset = 0, INT width = 0, INT height = 0, bool bRepaint = FALSE);
106 | void adjToEdge(HWND hDlg, INT idCtrl, INT dlgW, INT dlgH, INT toChange, INT duoRight, INT duoBottom, bool redraw = false);
107 |
108 | } // end namespace NppPlugin::dlg
109 |
110 | } // end namespace NppPlugin
111 |
112 | #endif // NPP_PLUGIN_UTIL_H
113 |
--------------------------------------------------------------------------------
/src/npp/PluginInterface.h:
--------------------------------------------------------------------------------
1 | // This file is part of Notepad++ project
2 | // Copyright (C)2003 Don HO
3 | //
4 | // This program is free software; you can redistribute it and/or
5 | // modify it under the terms of the GNU General Public License
6 | // as published by the Free Software Foundation; either
7 | // version 2 of the License, or (at your option) any later version.
8 | //
9 | // Note that the GPL places important restrictions on "derived works", yet
10 | // it does not provide a detailed definition of that term. To avoid
11 | // misunderstandings, we consider an application to constitute a
12 | // "derivative work" for the purpose of this license if it does any of the
13 | // following:
14 | // 1. Integrates source code from Notepad++.
15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable
16 | // installer, such as those produced by InstallShield.
17 | // 3. Links to a library or executes a program that does any of the above.
18 | //
19 | // This program is distributed in the hope that it will be useful,
20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | // GNU General Public License for more details.
23 | //
24 | // You should have received a copy of the GNU General Public License
25 | // along with this program; if not, write to the Free Software
26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 |
28 |
29 | #ifndef PLUGININTERFACE_H
30 | #define PLUGININTERFACE_H
31 |
32 | #ifndef SCINTILLA_H
33 | #include "Scintilla.h"
34 | #endif //SCINTILLA_H
35 |
36 | #ifndef NOTEPAD_PLUS_MSGS_H
37 | #include "Notepad_plus_msgs.h"
38 | #endif //NOTEPAD_PLUS_MSGS_H
39 |
40 | #ifndef MENUCMDID_H
41 | #include "menuCmdID.h"
42 | #endif //MENUCMDID_H
43 |
44 | const int nbChar = 64;
45 |
46 | typedef const TCHAR * (__cdecl * PFUNCGETNAME)();
47 |
48 | struct NppData {
49 | HWND _nppHandle;
50 | HWND _scintillaMainHandle;
51 | HWND _scintillaSecondHandle;
52 | };
53 |
54 | typedef void (__cdecl * PFUNCSETINFO)(NppData);
55 | typedef void (__cdecl * PFUNCPLUGINCMD)();
56 | typedef void (__cdecl * PBENOTIFIED)(SCNotification *);
57 | typedef LRESULT (__cdecl * PMESSAGEPROC)(UINT Message, WPARAM wParam, LPARAM lParam);
58 |
59 |
60 | struct ShortcutKey {
61 | bool _isCtrl;
62 | bool _isAlt;
63 | bool _isShift;
64 | UCHAR _key;
65 | };
66 |
67 | struct FuncItem {
68 | TCHAR _itemName[nbChar];
69 | PFUNCPLUGINCMD _pFunc;
70 | int _cmdID;
71 | bool _init2Check;
72 | ShortcutKey *_pShKey;
73 | };
74 |
75 | typedef FuncItem * (__cdecl * PFUNCGETFUNCSARRAY)(int *);
76 |
77 | // You should implement (or define an empty function body) those functions which are called by Notepad++ plugin manager
78 | extern "C" __declspec(dllexport) void setInfo(NppData);
79 | extern "C" __declspec(dllexport) const TCHAR * getName();
80 | extern "C" __declspec(dllexport) FuncItem * getFuncsArray(int *);
81 | extern "C" __declspec(dllexport) void beNotified(SCNotification *);
82 | extern "C" __declspec(dllexport) LRESULT messageProc(UINT Message, WPARAM wParam, LPARAM lParam);
83 |
84 | #ifdef UNICODE
85 | extern "C" __declspec(dllexport) BOOL isUnicode();
86 | #endif //UNICODE
87 |
88 | #endif //PLUGININTERFACE_H
89 |
--------------------------------------------------------------------------------
/src/res/resource.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file resource.h
13 | @copyright Copyright 2011-2014 Michael Foster
14 | */
15 |
16 | #ifndef IDC_STATIC
17 | #define IDC_STATIC (-1)
18 | #endif
19 |
20 | // Dialog IDs
21 | #define IDD_SES_DLG 100
22 | #define IDD_NEW_DLG 110
23 | #define IDD_REN_DLG 120
24 | #define IDD_DEL_DLG 130
25 | #define IDD_CFG_DLG 140
26 |
27 | // Control IDs
28 | #define IDC_SES_LST_SES 1000
29 | #define IDC_SES_CMB_FIL 1001
30 | #define IDC_SES_CHK_WILD 1002
31 | #define IDC_SES_BTN_LOAD 1003
32 | #define IDC_SES_BTN_PRV 1004
33 | #define IDC_SES_BTN_SAVE 1005
34 | #define IDC_SES_BTN_NEW 1006
35 | #define IDC_SES_BTN_REN 1007
36 | #define IDC_SES_BTN_DEL 1008
37 | #define IDC_SES_BTN_FAV 1009
38 | #define IDC_SES_BTN_CANCEL 1010
39 | #define IDC_SES_RAD_ALPHA 1011
40 | #define IDC_SES_RAD_DATE 1012
41 | #define IDC_SES_CHK_LIC 1013
42 | #define IDC_SES_CHK_LWC 1014
43 | #define IDC_NEW_ETX_NAME 1100
44 | #define IDC_NEW_RAD_EMPTY 1101
45 | #define IDC_NEW_RAD_COPY 1102
46 | #define IDC_NEW_RAD_OPEN 1103
47 | #define IDC_REN_ETX_NAME 1200
48 | #define IDC_CFG_CHK_ASV 1400
49 | #define IDC_CFG_CHK_ALD 1401
50 | #define IDC_CFG_CHK_LIC 1402
51 | #define IDC_CFG_CHK_LWC 1403
52 | #define IDC_CFG_CHK_SITB 1404
53 | #define IDC_CFG_CHK_SISB 1405
54 | #define IDC_CFG_CHK_GBKM 1406
55 | #define IDC_CFG_CHK_CTXM 1407
56 | #define IDC_CFG_BTN_BRW 1408
57 | #define IDC_CFG_ETX_DIR 1409
58 | #define IDC_CFG_ETX_EXT 1410
59 |
60 | // Common sizes
61 | #define IDC_MAR_1 6
62 | #define IDC_MAR_2 2
63 | #define IDC_MAR_3 3
64 | #define IDC_BTN_W 34
65 | #define IDC_BTN_H 13
66 | #define IDC_ETX_H 13
67 | #define IDC_LTX_H 8
68 | #define IDC_CHK_H 8
69 |
70 | /*
71 | The Sessions dialog
72 | */
73 |
74 | #define IDD_SES_W 187
75 | #define IDD_SES_H 230
76 |
77 | // Right and bottom offsets (for moving/resizing)
78 | #define IDC_SES_CMB_WRO (IDC_MAR_1 + IDC_BTN_W + IDC_MAR_1)
79 | #define IDC_SES_LST_WRO IDC_SES_CMB_WRO
80 | #define IDC_SES_LST_HBO (IDC_MAR_1 + IDC_CHK_H + IDC_MAR_2 + IDC_CHK_H + IDC_MAR_1)
81 | #define IDC_SES_BTN_XRO (IDC_MAR_1 + IDC_BTN_W)
82 | #define IDC_SES_OPT_R1_YBO (IDC_MAR_1 + IDC_CHK_H + IDC_MAR_3 + IDC_CHK_H)
83 | #define IDC_SES_OPT_R2_YBO (IDC_MAR_1 + IDC_CHK_H)
84 |
85 | #define IDC_SES_CMB_FIL_X IDC_MAR_1
86 | #define IDC_SES_CMB_FIL_Y IDC_MAR_1
87 | #define IDC_SES_CMB_FIL_W (IDD_SES_W - IDC_SES_CMB_FIL_X - IDC_SES_CMB_WRO)
88 | #define IDC_SES_CMB_FIL_H IDC_ETX_H
89 |
90 | #define IDC_SES_LST_SES_X IDC_MAR_1
91 | #define IDC_SES_LST_SES_Y (IDC_SES_CMB_FIL_Y + IDC_SES_CMB_FIL_H + IDC_MAR_3)
92 | #define IDC_SES_LST_SES_W (IDD_SES_W - IDC_SES_LST_SES_X - IDC_SES_LST_WRO)
93 | #define IDC_SES_LST_SES_H (IDD_SES_H - IDC_SES_LST_SES_Y - IDC_SES_LST_HBO)
94 |
95 | #define IDC_SES_OPT_R1_Y (IDD_SES_H - IDC_SES_OPT_R1_YBO)
96 | #define IDC_SES_OPT_R2_Y (IDD_SES_H - IDC_SES_OPT_R2_YBO)
97 |
98 | #define IDC_SES_CHK_WILD_Y (IDC_MAR_1 + 2)
99 |
100 | #define IDC_SES_BTN_X (IDD_SES_W - IDC_SES_BTN_XRO)
101 | #define IDC_SES_BTN_LOAD_Y IDC_SES_LST_SES_Y
102 | #define IDC_SES_BTN_PRV_Y (IDC_SES_BTN_LOAD_Y + IDC_MAR_1 + IDC_BTN_H)
103 | #define IDC_SES_BTN_SAVE_Y (IDC_SES_BTN_PRV_Y + IDC_MAR_1 + IDC_BTN_H)
104 | #define IDC_SES_BTN_NEW_Y (IDC_SES_BTN_SAVE_Y + IDC_MAR_1 + IDC_BTN_H)
105 | #define IDC_SES_BTN_REN_Y (IDC_SES_BTN_NEW_Y + IDC_MAR_1 + IDC_BTN_H)
106 | #define IDC_SES_BTN_DEL_Y (IDC_SES_BTN_REN_Y + IDC_MAR_1 + IDC_BTN_H)
107 | #define IDC_SES_BTN_FAV_Y (IDC_SES_BTN_DEL_Y + IDC_MAR_1 + IDC_BTN_H)
108 | #define IDC_SES_BTN_CANCEL_Y (IDC_SES_BTN_FAV_Y + IDC_MAR_1 + IDC_BTN_H)
109 |
110 | // Child dialogs of the Sessions dialog
111 | #define IDD_CDLG_W 164
112 | #define IDC_CDLG_TXT_W 150
113 | #define IDC_CDLG_RAD_W 120
114 |
115 | /*
116 | The Settings dialog
117 | */
118 |
119 | #define IDD_CFG_W 315
120 | #define IDD_CFG_H 120
121 |
122 | // Right and bottom offsets (for moving/resizing)
123 | #define IDC_CFG_ETX_WRO IDC_MAR_1
124 | #define IDC_CFG_BTN_YBO (IDC_MAR_1 + IDC_BTN_H)
125 | #define IDC_CFG_BTN_OK_XRO (IDC_MAR_1 + IDC_BTN_W + IDC_MAR_1 + IDC_BTN_W)
126 | #define IDC_CFG_BTN_CAN_XRO (IDC_MAR_1 + IDC_BTN_W)
127 |
128 | #define IDC_CFG_ETX_DIR_X 25
129 | #define IDC_CFG_ETX_DIR_Y 50
130 | #define IDC_CFG_ETX_DIR_W (IDD_CFG_W - IDC_CFG_ETX_DIR_X - IDC_CFG_ETX_WRO)
131 | #define IDC_CFG_ETX_DIR_H IDC_ETX_H
132 |
133 | #define IDC_CFG_ETX_EXT_X IDC_MAR_1
134 | #define IDC_CFG_ETX_EXT_Y 78
135 | #define IDC_CFG_ETX_EXT_W (IDD_CFG_W - IDC_CFG_ETX_EXT_X - IDC_CFG_ETX_WRO)
136 | #define IDC_CFG_ETX_EXT_H IDC_ETX_H
137 |
138 | #define IDC_CFG_BTN_OK_X (IDD_CFG_W - IDC_CFG_BTN_OK_XRO)
139 | #define IDC_CFG_BTN_OK_Y (IDD_CFG_H - IDC_CFG_BTN_YBO)
140 | #define IDC_CFG_BTN_CAN_X (IDD_CFG_W - IDC_CFG_BTN_CAN_XRO)
141 | #define IDC_CFG_BTN_CAN_Y IDC_CFG_BTN_OK_Y
142 |
143 |
144 |
--------------------------------------------------------------------------------
/src/res/resource.rc:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file resource.rc
13 | @copyright Copyright 2011-2014 Michael Foster
14 | */
15 |
16 | #include
17 | #include
18 | #include "resource.h"
19 | #include "version.rc2"
20 |
21 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
22 | IDD_SES_DLG DIALOGEX 0, 0, IDD_SES_W, IDD_SES_H
23 | STYLE WS_SIZEBOX | DS_SHELLFONT | WS_CAPTION | WS_POPUP
24 | EXSTYLE WS_EX_TOOLWINDOW
25 | CAPTION " Session Manager"
26 | FONT 8, "MS Shell Dlg", 400, 0, 0
27 | {
28 | COMBOBOX IDC_SES_CMB_FIL, IDC_SES_CMB_FIL_X, IDC_SES_CMB_FIL_Y, IDC_SES_CMB_FIL_W, IDC_SES_CMB_FIL_H, WS_TABSTOP | CBS_DROPDOWN | CBS_HASSTRINGS | CBS_AUTOHSCROLL, WS_EX_LEFT
29 | LISTBOX IDC_SES_LST_SES, IDC_SES_LST_SES_X, IDC_SES_LST_SES_Y, IDC_SES_LST_SES_W, IDC_SES_LST_SES_H, WS_TABSTOP | WS_VSCROLL | LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_USETABSTOPS | LBS_WANTKEYBOARDINPUT
30 | AUTOCHECKBOX "* ?", IDC_SES_CHK_WILD, IDC_SES_BTN_X, IDC_SES_CHK_WILD_Y, IDC_BTN_W, IDC_CHK_H, BS_VCENTER, WS_EX_LEFT
31 | DEFPUSHBUTTON "&Load", IDC_SES_BTN_LOAD, IDC_SES_BTN_X, IDC_SES_BTN_LOAD_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
32 | PUSHBUTTON "&Previous", IDC_SES_BTN_PRV, IDC_SES_BTN_X, IDC_SES_BTN_PRV_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
33 | PUSHBUTTON "&Save", IDC_SES_BTN_SAVE, IDC_SES_BTN_X, IDC_SES_BTN_SAVE_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
34 | PUSHBUTTON "New", IDC_SES_BTN_NEW, IDC_SES_BTN_X, IDC_SES_BTN_NEW_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
35 | PUSHBUTTON "Rename", IDC_SES_BTN_REN, IDC_SES_BTN_X, IDC_SES_BTN_REN_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
36 | PUSHBUTTON "Delete", IDC_SES_BTN_DEL, IDC_SES_BTN_X, IDC_SES_BTN_DEL_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
37 | PUSHBUTTON "&Favorite", IDC_SES_BTN_FAV, IDC_SES_BTN_X, IDC_SES_BTN_FAV_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
38 | PUSHBUTTON "Close", IDC_SES_BTN_CANCEL, IDC_SES_BTN_X, IDC_SES_BTN_CANCEL_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
39 | AUTOCHECKBOX "Load &into current", IDC_SES_CHK_LIC, IDC_MAR_1, IDC_SES_OPT_R1_Y, 69, IDC_CHK_H, BS_VCENTER, WS_EX_LEFT
40 | AUTOCHECKBOX "Load &without closing", IDC_SES_CHK_LWC, IDC_MAR_1, IDC_SES_OPT_R2_Y, 81, IDC_CHK_H, BS_VCENTER, WS_EX_LEFT
41 | AUTORADIOBUTTON "Sort by &alpha", IDC_SES_RAD_ALPHA, 89, IDC_SES_OPT_R1_Y, 57, IDC_CHK_H, 0, WS_EX_LEFT
42 | AUTORADIOBUTTON "Sort by &date", IDC_SES_RAD_DATE, 89, IDC_SES_OPT_R2_Y, 54, IDC_CHK_H, 0, WS_EX_LEFT
43 | }
44 |
45 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
46 | IDD_NEW_DLG DIALOGEX 0, 0, IDD_CDLG_W, 98
47 | STYLE DS_MODALFRAME | DS_SHELLFONT | WS_POPUP
48 | FONT 8, "MS Shell Dlg", 400, 0, 1
49 | {
50 | LTEXT "Create New Session", IDC_STATIC, IDC_MAR_1, IDC_MAR_1, IDC_CDLG_TXT_W, IDC_LTX_H, SS_LEFT
51 | EDITTEXT IDC_NEW_ETX_NAME, IDC_MAR_1, 19, 154, IDC_ETX_H, ES_AUTOHSCROLL
52 | AUTORADIOBUTTON "As an empty session", IDC_NEW_RAD_EMPTY, IDC_MAR_1, 36, IDC_CDLG_RAD_W, IDC_CHK_H, WS_GROUP | WS_TABSTOP
53 | AUTORADIOBUTTON "As a copy of the current session", IDC_NEW_RAD_OPEN, IDC_MAR_1, 49, IDC_CDLG_RAD_W, IDC_CHK_H, WS_TABSTOP
54 | AUTORADIOBUTTON "As a copy of the selected session", IDC_NEW_RAD_COPY, IDC_MAR_1, 62, IDC_CDLG_RAD_W, IDC_CHK_H, WS_TABSTOP
55 | DEFPUSHBUTTON "OK", IDOK, 83, 77, IDC_BTN_W, IDC_BTN_H, BS_CENTER
56 | PUSHBUTTON "Cancel", IDCANCEL, 124, 77, IDC_BTN_W, IDC_BTN_H, BS_CENTER
57 | }
58 |
59 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
60 | IDD_REN_DLG DIALOGEX 0, 0, IDD_CDLG_W, 62
61 | STYLE DS_MODALFRAME | DS_SHELLFONT | WS_POPUP | WS_SYSMENU
62 | FONT 8, "MS Shell Dlg", 400, 0, 1
63 | {
64 | LTEXT "Rename Selected Session", IDC_STATIC, IDC_MAR_1, IDC_MAR_1, IDC_CDLG_TXT_W, IDC_LTX_H, SS_LEFT
65 | EDITTEXT IDC_REN_ETX_NAME, IDC_MAR_1, 19, IDC_CDLG_TXT_W, IDC_ETX_H, ES_AUTOHSCROLL
66 | DEFPUSHBUTTON "OK", IDOK, 83, 41, IDC_BTN_W, IDC_BTN_H, BS_CENTER
67 | PUSHBUTTON "Cancel", IDCANCEL, 123, 41, IDC_BTN_W, IDC_BTN_H, BS_CENTER
68 | }
69 |
70 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
71 | IDD_DEL_DLG DIALOGEX 0, 0, IDD_CDLG_W, 44
72 | STYLE DS_MODALFRAME | DS_SHELLFONT | WS_POPUP | WS_SYSMENU
73 | FONT 8, "MS Shell Dlg", 400, 0, 1
74 | {
75 | LTEXT "Delete Selected Session", IDC_STATIC, IDC_MAR_1, IDC_MAR_1, IDC_CDLG_TXT_W, IDC_LTX_H, SS_LEFT
76 | DEFPUSHBUTTON "OK", IDOK, 82, 23, IDC_BTN_W, IDC_BTN_H, BS_CENTER
77 | PUSHBUTTON "Cancel", IDCANCEL, 123, 23, IDC_BTN_W, IDC_BTN_H, BS_CENTER
78 | }
79 |
80 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
81 | IDD_CFG_DLG DIALOGEX 0, 0, IDD_CFG_W, IDD_CFG_H
82 | STYLE WS_SIZEBOX | DS_SHELLFONT | WS_CAPTION | WS_POPUP
83 | EXSTYLE WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_STATICEDGE
84 | CAPTION " Session Manager Settings"
85 | FONT 8, "MS Shell Dlg", 400, 0, 1
86 | {
87 | AUTOCHECKBOX "Auto save", IDC_CFG_CHK_ASV, IDC_MAR_1, IDC_MAR_1, 45, IDC_CHK_H, 0, WS_EX_LEFT
88 | AUTOCHECKBOX "Auto load", IDC_CFG_CHK_ALD, IDC_MAR_1, 23, 45, IDC_CHK_H, 0, WS_EX_LEFT
89 | AUTOCHECKBOX "Load into current", IDC_CFG_CHK_LIC, 63, IDC_MAR_1, 65, IDC_CHK_H, 0, WS_EX_LEFT
90 | AUTOCHECKBOX "Load without closing", IDC_CFG_CHK_LWC, 63, 23, 75, IDC_CHK_H, 0, WS_EX_LEFT
91 | AUTOCHECKBOX "Show in title bar", IDC_CFG_CHK_SITB, 154, IDC_MAR_1, 65, IDC_CHK_H, 0, WS_EX_LEFT
92 | AUTOCHECKBOX "Show in status bar", IDC_CFG_CHK_SISB, 154, 23, 75, IDC_CHK_H, 0, WS_EX_LEFT
93 | AUTOCHECKBOX "Global properties", IDC_CFG_CHK_GBKM, 238, IDC_MAR_1, 65, IDC_CHK_H, 0, WS_EX_LEFT
94 | AUTOCHECKBOX "Use context menu", IDC_CFG_CHK_CTXM, 238, 23, 70, IDC_CHK_H, 0, WS_EX_LEFT
95 | LTEXT "Session files folder", IDC_STATIC, IDC_MAR_1, 40, 60, IDC_LTX_H, SS_LEFT
96 | PUSHBUTTON "...", IDC_CFG_BTN_BRW, IDC_MAR_1, 50, 13, IDC_BTN_H - 1, BS_CENTER
97 | EDITTEXT IDC_CFG_ETX_DIR, IDC_CFG_ETX_DIR_X, IDC_CFG_ETX_DIR_Y, IDC_CFG_ETX_DIR_W, IDC_CFG_ETX_DIR_H, ES_AUTOHSCROLL
98 | LTEXT "Session file extension", IDC_STATIC, IDC_MAR_1, 68, 80, IDC_LTX_H, SS_LEFT
99 | EDITTEXT IDC_CFG_ETX_EXT, IDC_CFG_ETX_EXT_X, IDC_CFG_ETX_EXT_Y, IDC_CFG_ETX_EXT_W, IDC_ETX_H, ES_AUTOHSCROLL
100 | DEFPUSHBUTTON "OK", IDOK, IDC_CFG_BTN_OK_X, IDC_CFG_BTN_OK_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
101 | PUSHBUTTON "Cancel", IDCANCEL, IDC_CFG_BTN_CAN_X, IDC_CFG_BTN_CAN_Y, IDC_BTN_W, IDC_BTN_H, BS_CENTER
102 | }
103 |
--------------------------------------------------------------------------------
/src/res/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of SessionMgr, A Plugin for Notepad++. SessionMgr is free
3 | software: you can redistribute it and/or modify it under the terms of the
4 | GNU General Public License as published by the Free Software Foundation,
5 | either version 3 of the License, or (at your option) any later version.
6 | This program is distributed in the hope that it will be useful, but WITHOUT
7 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 | more details. You should have received a copy of the GNU General Public
10 | License along with this program. If not, see .
11 | *//**
12 | @file version.h
13 | @copyright Copyright 2011-2015 Michael Foster
14 | */
15 |
16 | #ifndef NPP_PLUGIN_VERSION_H
17 | #define NPP_PLUGIN_VERSION_H
18 |
19 |
20 | #define RES_VERSION_B 1,4,2,0
21 | #define RES_VERSION_S "1.4.2.0"
22 | #define PLUGIN_VERSION _W(RES_VERSION_S)
23 | #define RES_COPYRIGHT "Copyright 2011-2015 Michael Foster. Distributed under the terms of the GNU GPL."
24 |
25 |
26 | #endif // NPP_PLUGIN_VERSION_H
27 |
--------------------------------------------------------------------------------
/src/res/version.rc2:
--------------------------------------------------------------------------------
1 | #include "version.h"
2 |
3 | VS_VERSION_INFO VERSIONINFO
4 | FILEVERSION RES_VERSION_B
5 | PRODUCTVERSION RES_VERSION_B
6 | FILEFLAGSMASK 0x3fL
7 | #ifdef _DEBUG
8 | FILEFLAGS 0x1L
9 | #else
10 | FILEFLAGS 0x0L
11 | #endif
12 | FILEOS 0x40004L
13 | FILETYPE 0x2L
14 | FILESUBTYPE 0x0L
15 | BEGIN
16 | BLOCK "StringFileInfo"
17 | BEGIN
18 | BLOCK "040904b0"
19 | BEGIN
20 | VALUE "CompanyName", "Michael Foster (http://mfoster.com/npp/)"
21 | VALUE "FileDescription", "A plugin for Notepad++"
22 | VALUE "FileVersion", RES_VERSION_S
23 | VALUE "InternalName", "SessionMgr"
24 | VALUE "LegalCopyright", RES_COPYRIGHT
25 | VALUE "OriginalFilename", "SessionMgr.dll"
26 | VALUE "ProductName", "Session Manager"
27 | VALUE "ProductVersion", RES_VERSION_S
28 | END
29 | END
30 | BLOCK "VarFileInfo"
31 | BEGIN
32 | VALUE "Translation", 0x409, 1200
33 | END
34 | END
35 |
--------------------------------------------------------------------------------
/src/utf8/checked.h:
--------------------------------------------------------------------------------
1 | // Copyright 2006 Nemanja Trifunovic
2 |
3 | /*
4 | Permission is hereby granted, free of charge, to any person or organization
5 | obtaining a copy of the software and accompanying documentation covered by
6 | this license (the "Software") to use, reproduce, display, distribute,
7 | execute, and transmit the Software, and to prepare derivative works of the
8 | Software, and to permit third-parties to whom the Software is furnished to
9 | do so, all subject to the following:
10 |
11 | The copyright notices in the Software and this entire statement, including
12 | the above license grant, this restriction and the following disclaimer,
13 | must be included in all copies of the Software, in whole or in part, and
14 | all derivative works of the Software, unless such copies or derivative
15 | works are solely in the form of machine-executable object code generated by
16 | a source language processor.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 | DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 |
28 | #ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
29 | #define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
30 |
31 | #include "core.h"
32 | #include
33 |
34 | namespace utf8
35 | {
36 | // Base for the exceptions that may be thrown from the library
37 | class exception : public ::std::exception {
38 | };
39 |
40 | // Exceptions that may be thrown from the library functions.
41 | class invalid_code_point : public exception {
42 | uint32_t cp;
43 | public:
44 | invalid_code_point(uint32_t cp) : cp(cp) {}
45 | virtual const char* what() const throw() { return "Invalid code point"; }
46 | uint32_t code_point() const {return cp;}
47 | };
48 |
49 | class invalid_utf8 : public exception {
50 | uint8_t u8;
51 | public:
52 | invalid_utf8 (uint8_t u) : u8(u) {}
53 | virtual const char* what() const throw() { return "Invalid UTF-8"; }
54 | uint8_t utf8_octet() const {return u8;}
55 | };
56 |
57 | class invalid_utf16 : public exception {
58 | uint16_t u16;
59 | public:
60 | invalid_utf16 (uint16_t u) : u16(u) {}
61 | virtual const char* what() const throw() { return "Invalid UTF-16"; }
62 | uint16_t utf16_word() const {return u16;}
63 | };
64 |
65 | class not_enough_room : public exception {
66 | public:
67 | virtual const char* what() const throw() { return "Not enough space"; }
68 | };
69 |
70 | /// The library API - functions intended to be called by the users
71 |
72 | template
73 | octet_iterator append(uint32_t cp, octet_iterator result)
74 | {
75 | if (!utf8::internal::is_code_point_valid(cp))
76 | throw invalid_code_point(cp);
77 |
78 | if (cp < 0x80) // one octet
79 | *(result++) = static_cast(cp);
80 | else if (cp < 0x800) { // two octets
81 | *(result++) = static_cast((cp >> 6) | 0xc0);
82 | *(result++) = static_cast((cp & 0x3f) | 0x80);
83 | }
84 | else if (cp < 0x10000) { // three octets
85 | *(result++) = static_cast((cp >> 12) | 0xe0);
86 | *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
87 | *(result++) = static_cast((cp & 0x3f) | 0x80);
88 | }
89 | else { // four octets
90 | *(result++) = static_cast((cp >> 18) | 0xf0);
91 | *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80);
92 | *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
93 | *(result++) = static_cast((cp & 0x3f) | 0x80);
94 | }
95 | return result;
96 | }
97 |
98 | template
99 | output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
100 | {
101 | while (start != end) {
102 | octet_iterator sequence_start = start;
103 | internal::utf_error err_code = utf8::internal::validate_next(start, end);
104 | switch (err_code) {
105 | case internal::UTF8_OK :
106 | for (octet_iterator it = sequence_start; it != start; ++it)
107 | *out++ = *it;
108 | break;
109 | case internal::NOT_ENOUGH_ROOM:
110 | throw not_enough_room();
111 | case internal::INVALID_LEAD:
112 | out = utf8::append (replacement, out);
113 | ++start;
114 | break;
115 | case internal::INCOMPLETE_SEQUENCE:
116 | case internal::OVERLONG_SEQUENCE:
117 | case internal::INVALID_CODE_POINT:
118 | out = utf8::append (replacement, out);
119 | ++start;
120 | // just one replacement mark for the sequence
121 | while (start != end && utf8::internal::is_trail(*start))
122 | ++start;
123 | break;
124 | }
125 | }
126 | return out;
127 | }
128 |
129 | template
130 | inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
131 | {
132 | static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
133 | return utf8::replace_invalid(start, end, out, replacement_marker);
134 | }
135 |
136 | template
137 | uint32_t next(octet_iterator& it, octet_iterator end)
138 | {
139 | uint32_t cp = 0;
140 | internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
141 | switch (err_code) {
142 | case internal::UTF8_OK :
143 | break;
144 | case internal::NOT_ENOUGH_ROOM :
145 | throw not_enough_room();
146 | case internal::INVALID_LEAD :
147 | case internal::INCOMPLETE_SEQUENCE :
148 | case internal::OVERLONG_SEQUENCE :
149 | throw invalid_utf8(*it);
150 | case internal::INVALID_CODE_POINT :
151 | throw invalid_code_point(cp);
152 | }
153 | return cp;
154 | }
155 |
156 | template
157 | uint32_t peek_next(octet_iterator it, octet_iterator end)
158 | {
159 | return utf8::next(it, end);
160 | }
161 |
162 | template
163 | uint32_t prior(octet_iterator& it, octet_iterator start)
164 | {
165 | // can't do much if it == start
166 | if (it == start)
167 | throw not_enough_room();
168 |
169 | octet_iterator end = it;
170 | // Go back until we hit either a lead octet or start
171 | while (utf8::internal::is_trail(*(--it)))
172 | if (it == start)
173 | throw invalid_utf8(*it); // error - no lead byte in the sequence
174 | return utf8::peek_next(it, end);
175 | }
176 |
177 | /// Deprecated in versions that include "prior"
178 | template
179 | uint32_t previous(octet_iterator& it, octet_iterator pass_start)
180 | {
181 | octet_iterator end = it;
182 | while (utf8::internal::is_trail(*(--it)))
183 | if (it == pass_start)
184 | throw invalid_utf8(*it); // error - no lead byte in the sequence
185 | octet_iterator temp = it;
186 | return utf8::next(temp, end);
187 | }
188 |
189 | template
190 | void advance (octet_iterator& it, distance_type n, octet_iterator end)
191 | {
192 | for (distance_type i = 0; i < n; ++i)
193 | utf8::next(it, end);
194 | }
195 |
196 | template
197 | typename std::iterator_traits::difference_type
198 | distance (octet_iterator first, octet_iterator last)
199 | {
200 | typename std::iterator_traits::difference_type dist;
201 | for (dist = 0; first < last; ++dist)
202 | utf8::next(first, last);
203 | return dist;
204 | }
205 |
206 | template
207 | octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
208 | {
209 | while (start != end) {
210 | uint32_t cp = utf8::internal::mask16(*start++);
211 | // Take care of surrogate pairs first
212 | if (utf8::internal::is_lead_surrogate(cp)) {
213 | if (start != end) {
214 | uint32_t trail_surrogate = utf8::internal::mask16(*start++);
215 | if (utf8::internal::is_trail_surrogate(trail_surrogate))
216 | cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
217 | else
218 | throw invalid_utf16(static_cast(trail_surrogate));
219 | }
220 | else
221 | throw invalid_utf16(static_cast(cp));
222 |
223 | }
224 | // Lone trail surrogate
225 | else if (utf8::internal::is_trail_surrogate(cp))
226 | throw invalid_utf16(static_cast(cp));
227 |
228 | result = utf8::append(cp, result);
229 | }
230 | return result;
231 | }
232 |
233 | template
234 | u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
235 | {
236 | while (start != end) {
237 | uint32_t cp = utf8::next(start, end);
238 | if (cp > 0xffff) { //make a surrogate pair
239 | *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET);
240 | *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
241 | }
242 | else
243 | *result++ = static_cast(cp);
244 | }
245 | return result;
246 | }
247 |
248 | template
249 | octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
250 | {
251 | while (start != end)
252 | result = utf8::append(*(start++), result);
253 |
254 | return result;
255 | }
256 |
257 | template
258 | u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
259 | {
260 | while (start != end)
261 | (*result++) = utf8::next(start, end);
262 |
263 | return result;
264 | }
265 |
266 | // The iterator class
267 | template
268 | class iterator : public std::iterator {
269 | octet_iterator it;
270 | octet_iterator range_start;
271 | octet_iterator range_end;
272 | public:
273 | iterator () {}
274 | explicit iterator (const octet_iterator& octet_it,
275 | const octet_iterator& range_start,
276 | const octet_iterator& range_end) :
277 | it(octet_it), range_start(range_start), range_end(range_end)
278 | {
279 | if (it < range_start || it > range_end)
280 | throw std::out_of_range("Invalid utf-8 iterator position");
281 | }
282 | // the default "big three" are OK
283 | octet_iterator base () const { return it; }
284 | uint32_t operator * () const
285 | {
286 | octet_iterator temp = it;
287 | return utf8::next(temp, range_end);
288 | }
289 | bool operator == (const iterator& rhs) const
290 | {
291 | if (range_start != rhs.range_start || range_end != rhs.range_end)
292 | throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
293 | return (it == rhs.it);
294 | }
295 | bool operator != (const iterator& rhs) const
296 | {
297 | return !(operator == (rhs));
298 | }
299 | iterator& operator ++ ()
300 | {
301 | utf8::next(it, range_end);
302 | return *this;
303 | }
304 | iterator operator ++ (int)
305 | {
306 | iterator temp = *this;
307 | utf8::next(it, range_end);
308 | return temp;
309 | }
310 | iterator& operator -- ()
311 | {
312 | utf8::prior(it, range_start);
313 | return *this;
314 | }
315 | iterator operator -- (int)
316 | {
317 | iterator temp = *this;
318 | utf8::prior(it, range_start);
319 | return temp;
320 | }
321 | }; // class iterator
322 |
323 | } // namespace utf8
324 |
325 | #endif //header guard
326 |
327 |
328 |
--------------------------------------------------------------------------------
/src/utf8/core.h:
--------------------------------------------------------------------------------
1 | // Copyright 2006 Nemanja Trifunovic
2 |
3 | /*
4 | Permission is hereby granted, free of charge, to any person or organization
5 | obtaining a copy of the software and accompanying documentation covered by
6 | this license (the "Software") to use, reproduce, display, distribute,
7 | execute, and transmit the Software, and to prepare derivative works of the
8 | Software, and to permit third-parties to whom the Software is furnished to
9 | do so, all subject to the following:
10 |
11 | The copyright notices in the Software and this entire statement, including
12 | the above license grant, this restriction and the following disclaimer,
13 | must be included in all copies of the Software, in whole or in part, and
14 | all derivative works of the Software, unless such copies or derivative
15 | works are solely in the form of machine-executable object code generated by
16 | a source language processor.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 | DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 |
28 | #ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
29 | #define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
30 |
31 | #include
32 |
33 | namespace utf8
34 | {
35 | // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
36 | // You may need to change them to match your system.
37 | // These typedefs have the same names as ones from cstdint, or boost/cstdint
38 | typedef unsigned char uint8_t;
39 | typedef unsigned short uint16_t;
40 | typedef unsigned int uint32_t;
41 |
42 | // Helper code - not intended to be directly called by the library users. May be changed at any time
43 | namespace internal
44 | {
45 | // Unicode constants
46 | // Leading (high) surrogates: 0xd800 - 0xdbff
47 | // Trailing (low) surrogates: 0xdc00 - 0xdfff
48 | const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
49 | const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
50 | const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
51 | const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
52 | const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
53 | const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
54 |
55 | // Maximum valid value for a Unicode code point
56 | const uint32_t CODE_POINT_MAX = 0x0010ffffu;
57 |
58 | template
59 | inline uint8_t mask8(octet_type oc)
60 | {
61 | return static_cast(0xff & oc);
62 | }
63 | template
64 | inline uint16_t mask16(u16_type oc)
65 | {
66 | return static_cast(0xffff & oc);
67 | }
68 | template
69 | inline bool is_trail(octet_type oc)
70 | {
71 | return ((utf8::internal::mask8(oc) >> 6) == 0x2);
72 | }
73 |
74 | template
75 | inline bool is_lead_surrogate(u16 cp)
76 | {
77 | return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
78 | }
79 |
80 | template
81 | inline bool is_trail_surrogate(u16 cp)
82 | {
83 | return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
84 | }
85 |
86 | template
87 | inline bool is_surrogate(u16 cp)
88 | {
89 | return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
90 | }
91 |
92 | template
93 | inline bool is_code_point_valid(u32 cp)
94 | {
95 | return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
96 | }
97 |
98 | template
99 | inline typename std::iterator_traits::difference_type
100 | sequence_length(octet_iterator lead_it)
101 | {
102 | uint8_t lead = utf8::internal::mask8(*lead_it);
103 | if (lead < 0x80)
104 | return 1;
105 | else if ((lead >> 5) == 0x6)
106 | return 2;
107 | else if ((lead >> 4) == 0xe)
108 | return 3;
109 | else if ((lead >> 3) == 0x1e)
110 | return 4;
111 | else
112 | return 0;
113 | }
114 |
115 | template
116 | inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
117 | {
118 | if (cp < 0x80) {
119 | if (length != 1)
120 | return true;
121 | }
122 | else if (cp < 0x800) {
123 | if (length != 2)
124 | return true;
125 | }
126 | else if (cp < 0x10000) {
127 | if (length != 3)
128 | return true;
129 | }
130 |
131 | return false;
132 | }
133 |
134 | enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
135 |
136 | /// Helper for get_sequence_x
137 | template
138 | utf_error increase_safely(octet_iterator& it, octet_iterator end)
139 | {
140 | if (++it == end)
141 | return NOT_ENOUGH_ROOM;
142 |
143 | if (!utf8::internal::is_trail(*it))
144 | return INCOMPLETE_SEQUENCE;
145 |
146 | return UTF8_OK;
147 | }
148 |
149 | #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
150 |
151 | /// get_sequence_x functions decode utf-8 sequences of the length x
152 | template
153 | utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
154 | {
155 | if (it == end)
156 | return NOT_ENOUGH_ROOM;
157 |
158 | code_point = utf8::internal::mask8(*it);
159 |
160 | return UTF8_OK;
161 | }
162 |
163 | template
164 | utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
165 | {
166 | if (it == end)
167 | return NOT_ENOUGH_ROOM;
168 |
169 | code_point = utf8::internal::mask8(*it);
170 |
171 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
172 |
173 | code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
174 |
175 | return UTF8_OK;
176 | }
177 |
178 | template
179 | utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
180 | {
181 | if (it == end)
182 | return NOT_ENOUGH_ROOM;
183 |
184 | code_point = utf8::internal::mask8(*it);
185 |
186 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
187 |
188 | code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
189 |
190 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
191 |
192 | code_point += (*it) & 0x3f;
193 |
194 | return UTF8_OK;
195 | }
196 |
197 | template
198 | utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
199 | {
200 | if (it == end)
201 | return NOT_ENOUGH_ROOM;
202 |
203 | code_point = utf8::internal::mask8(*it);
204 |
205 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
206 |
207 | code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
208 |
209 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
210 |
211 | code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
212 |
213 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
214 |
215 | code_point += (*it) & 0x3f;
216 |
217 | return UTF8_OK;
218 | }
219 |
220 | #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
221 |
222 | template
223 | utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
224 | {
225 | // Save the original value of it so we can go back in case of failure
226 | // Of course, it does not make much sense with i.e. stream iterators
227 | octet_iterator original_it = it;
228 |
229 | uint32_t cp = 0;
230 | // Determine the sequence length based on the lead octet
231 | typedef typename std::iterator_traits::difference_type octet_difference_type;
232 | const octet_difference_type length = utf8::internal::sequence_length(it);
233 |
234 | // Get trail octets and calculate the code point
235 | utf_error err = UTF8_OK;
236 | switch (length) {
237 | case 0:
238 | return INVALID_LEAD;
239 | case 1:
240 | err = utf8::internal::get_sequence_1(it, end, cp);
241 | break;
242 | case 2:
243 | err = utf8::internal::get_sequence_2(it, end, cp);
244 | break;
245 | case 3:
246 | err = utf8::internal::get_sequence_3(it, end, cp);
247 | break;
248 | case 4:
249 | err = utf8::internal::get_sequence_4(it, end, cp);
250 | break;
251 | }
252 |
253 | if (err == UTF8_OK) {
254 | // Decoding succeeded. Now, security checks...
255 | if (utf8::internal::is_code_point_valid(cp)) {
256 | if (!utf8::internal::is_overlong_sequence(cp, length)){
257 | // Passed! Return here.
258 | code_point = cp;
259 | ++it;
260 | return UTF8_OK;
261 | }
262 | else
263 | err = OVERLONG_SEQUENCE;
264 | }
265 | else
266 | err = INVALID_CODE_POINT;
267 | }
268 |
269 | // Failure branch - restore the original value of the iterator
270 | it = original_it;
271 | return err;
272 | }
273 |
274 | template
275 | inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
276 | uint32_t ignored;
277 | return utf8::internal::validate_next(it, end, ignored);
278 | }
279 |
280 | } // namespace internal
281 |
282 | /// The library API - functions intended to be called by the users
283 |
284 | // Byte order mark
285 | const uint8_t bom[] = {0xef, 0xbb, 0xbf};
286 |
287 | template
288 | octet_iterator find_invalid(octet_iterator start, octet_iterator end)
289 | {
290 | octet_iterator result = start;
291 | while (result != end) {
292 | utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
293 | if (err_code != internal::UTF8_OK)
294 | return result;
295 | }
296 | return result;
297 | }
298 |
299 | template
300 | inline bool is_valid(octet_iterator start, octet_iterator end)
301 | {
302 | return (utf8::find_invalid(start, end) == end);
303 | }
304 |
305 | template
306 | inline bool starts_with_bom (octet_iterator it, octet_iterator end)
307 | {
308 | return (
309 | ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
310 | ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
311 | ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
312 | );
313 | }
314 |
315 | //Deprecated in release 2.3
316 | template
317 | inline bool is_bom (octet_iterator it)
318 | {
319 | return (
320 | (utf8::internal::mask8(*it++)) == bom[0] &&
321 | (utf8::internal::mask8(*it++)) == bom[1] &&
322 | (utf8::internal::mask8(*it)) == bom[2]
323 | );
324 | }
325 | } // namespace utf8
326 |
327 | #endif // header guard
328 |
329 |
330 |
--------------------------------------------------------------------------------
/src/utf8/unchecked.h:
--------------------------------------------------------------------------------
1 | // Copyright 2006 Nemanja Trifunovic
2 |
3 | /*
4 | Permission is hereby granted, free of charge, to any person or organization
5 | obtaining a copy of the software and accompanying documentation covered by
6 | this license (the "Software") to use, reproduce, display, distribute,
7 | execute, and transmit the Software, and to prepare derivative works of the
8 | Software, and to permit third-parties to whom the Software is furnished to
9 | do so, all subject to the following:
10 |
11 | The copyright notices in the Software and this entire statement, including
12 | the above license grant, this restriction and the following disclaimer,
13 | must be included in all copies of the Software, in whole or in part, and
14 | all derivative works of the Software, unless such copies or derivative
15 | works are solely in the form of machine-executable object code generated by
16 | a source language processor.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 | DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 |
28 | #ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
29 | #define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
30 |
31 | #include "core.h"
32 |
33 | namespace utf8
34 | {
35 | namespace unchecked
36 | {
37 | template
38 | octet_iterator append(uint32_t cp, octet_iterator result)
39 | {
40 | if (cp < 0x80) // one octet
41 | *(result++) = static_cast(cp);
42 | else if (cp < 0x800) { // two octets
43 | *(result++) = static_cast((cp >> 6) | 0xc0);
44 | *(result++) = static_cast((cp & 0x3f) | 0x80);
45 | }
46 | else if (cp < 0x10000) { // three octets
47 | *(result++) = static_cast((cp >> 12) | 0xe0);
48 | *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
49 | *(result++) = static_cast((cp & 0x3f) | 0x80);
50 | }
51 | else { // four octets
52 | *(result++) = static_cast((cp >> 18) | 0xf0);
53 | *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80);
54 | *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80);
55 | *(result++) = static_cast((cp & 0x3f) | 0x80);
56 | }
57 | return result;
58 | }
59 |
60 | template
61 | uint32_t next(octet_iterator& it)
62 | {
63 | uint32_t cp = utf8::internal::mask8(*it);
64 | typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it);
65 | switch (length) {
66 | case 1:
67 | break;
68 | case 2:
69 | it++;
70 | cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
71 | break;
72 | case 3:
73 | ++it;
74 | cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
75 | ++it;
76 | cp += (*it) & 0x3f;
77 | break;
78 | case 4:
79 | ++it;
80 | cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
81 | ++it;
82 | cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
83 | ++it;
84 | cp += (*it) & 0x3f;
85 | break;
86 | }
87 | ++it;
88 | return cp;
89 | }
90 |
91 | template
92 | uint32_t peek_next(octet_iterator it)
93 | {
94 | return utf8::unchecked::next(it);
95 | }
96 |
97 | template
98 | uint32_t prior(octet_iterator& it)
99 | {
100 | while (utf8::internal::is_trail(*(--it))) ;
101 | octet_iterator temp = it;
102 | return utf8::unchecked::next(temp);
103 | }
104 |
105 | // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
106 | template
107 | inline uint32_t previous(octet_iterator& it)
108 | {
109 | return utf8::unchecked::prior(it);
110 | }
111 |
112 | template
113 | void advance (octet_iterator& it, distance_type n)
114 | {
115 | for (distance_type i = 0; i < n; ++i)
116 | utf8::unchecked::next(it);
117 | }
118 |
119 | template
120 | typename std::iterator_traits::difference_type
121 | distance (octet_iterator first, octet_iterator last)
122 | {
123 | typename std::iterator_traits::difference_type dist;
124 | for (dist = 0; first < last; ++dist)
125 | utf8::unchecked::next(first);
126 | return dist;
127 | }
128 |
129 | template
130 | octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
131 | {
132 | while (start != end) {
133 | uint32_t cp = utf8::internal::mask16(*start++);
134 | // Take care of surrogate pairs first
135 | if (utf8::internal::is_lead_surrogate(cp)) {
136 | uint32_t trail_surrogate = utf8::internal::mask16(*start++);
137 | cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
138 | }
139 | result = utf8::unchecked::append(cp, result);
140 | }
141 | return result;
142 | }
143 |
144 | template
145 | u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
146 | {
147 | while (start < end) {
148 | uint32_t cp = utf8::unchecked::next(start);
149 | if (cp > 0xffff) { //make a surrogate pair
150 | *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET);
151 | *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
152 | }
153 | else
154 | *result++ = static_cast(cp);
155 | }
156 | return result;
157 | }
158 |
159 | template
160 | octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
161 | {
162 | while (start != end)
163 | result = utf8::unchecked::append(*(start++), result);
164 |
165 | return result;
166 | }
167 |
168 | template
169 | u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
170 | {
171 | while (start < end)
172 | (*result++) = utf8::unchecked::next(start);
173 |
174 | return result;
175 | }
176 |
177 | // The iterator class
178 | template
179 | class iterator : public std::iterator {
180 | octet_iterator it;
181 | public:
182 | iterator () {}
183 | explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
184 | // the default "big three" are OK
185 | octet_iterator base () const { return it; }
186 | uint32_t operator * () const
187 | {
188 | octet_iterator temp = it;
189 | return utf8::unchecked::next(temp);
190 | }
191 | bool operator == (const iterator& rhs) const
192 | {
193 | return (it == rhs.it);
194 | }
195 | bool operator != (const iterator& rhs) const
196 | {
197 | return !(operator == (rhs));
198 | }
199 | iterator& operator ++ ()
200 | {
201 | ::std::advance(it, utf8::internal::sequence_length(it));
202 | return *this;
203 | }
204 | iterator operator ++ (int)
205 | {
206 | iterator temp = *this;
207 | ::std::advance(it, utf8::internal::sequence_length(it));
208 | return temp;
209 | }
210 | iterator& operator -- ()
211 | {
212 | utf8::unchecked::prior(it);
213 | return *this;
214 | }
215 | iterator operator -- (int)
216 | {
217 | iterator temp = *this;
218 | utf8::unchecked::prior(it);
219 | return temp;
220 | }
221 | }; // class iterator
222 |
223 | } // namespace utf8::unchecked
224 | } // namespace utf8
225 |
226 |
227 | #endif // header guard
228 |
229 |
--------------------------------------------------------------------------------
/src/xml/tinyxml.h:
--------------------------------------------------------------------------------
1 | #ifndef NPP_PLUGIN_TINYXML_H
2 | #define NPP_PLUGIN_TINYXML_H
3 |
4 | #include "tinyxml2.h"
5 |
6 | typedef tinyxml2::XMLHandle tXmlHnd;
7 | typedef tinyxml2::XMLDocument tXmlDoc;
8 | typedef tinyxml2::XMLDocument* tXmlDocP;
9 | typedef tinyxml2::XMLElement* tXmlEleP;
10 | typedef tinyxml2::XMLError tXmlError;
11 | const INT kXmlSuccess = tinyxml2::XML_SUCCESS;
12 |
13 | #endif // NPP_PLUGIN_TINYXML_H
14 |
--------------------------------------------------------------------------------
/x.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set sesmgr_old_ver=1.4.1
4 | set sesmgr_new_ver=1.4.2
5 | set release_dir=c:\prj\npp-session-manager\dist\%sesmgr_new_ver%
6 | set zip_exe="c:\Program Files\7-Zip\7z.exe"
7 | set md5_exe=c:\bin\md5sums\md5sums.exe
8 | set npp_plugin_dir=c:\bin\npp\plugins
9 |
10 | set do_c=0
11 | set do_b=0
12 | set do_d=0
13 | set do_r=0
14 | set args="x%*"
15 | if not %args:c=%==%args% set do_c=1
16 | if not %args:b=%==%args% set do_b=1
17 | if not %args:d=%==%args% set do_d=1
18 | if not %args:r=%==%args% set do_r=1
19 |
20 | if %do_c% equ 1 goto clean
21 | if %do_b% equ 1 goto build
22 | if %do_d% equ 1 goto deploy
23 | if %do_r% equ 1 goto release
24 |
25 | echo Usage: x (c|b|d|r)[ ]...
26 | echo where c = clean, b = build, d = deploy, r = release
27 | goto silent_exit
28 |
29 | ::------------------------------------------------------------------------------
30 | :clean
31 |
32 | echo Cleaning...
33 | nmake clean
34 | if %do_b% equ 1 goto build
35 | if %do_d% equ 1 goto deploy
36 | goto success_exit
37 |
38 | ::------------------------------------------------------------------------------
39 | :build
40 |
41 | echo Building...
42 | nmake > nmake.log
43 | if errorlevel 1 (
44 | echo Build ERROR
45 | type nmake.log
46 | goto error_exit
47 | )
48 | if %do_d% equ 1 goto deploy
49 | goto success_exit
50 |
51 | ::------------------------------------------------------------------------------
52 | :deploy
53 |
54 | echo Deploying...
55 | if exist %npp_plugin_dir%\SessionMgr.dll (
56 | if not exist %npp_plugin_dir%\SessionMgr-%sesmgr_old_ver%.dll (
57 | ren %npp_plugin_dir%\SessionMgr.dll SessionMgr-%sesmgr_old_ver%.dll
58 | if errorlevel 1 (
59 | echo Backup ERROR 1
60 | goto error_exit
61 | )
62 | ) else (
63 | echo Backup ERROR 2
64 | goto error_exit
65 | )
66 | )
67 | if exist %npp_plugin_dir%\SessionMgr-%sesmgr_old_ver%.dll (
68 | if not exist %npp_plugin_dir%\SessionMgr-%sesmgr_old_ver%.dll.bak (
69 | ren %npp_plugin_dir%\SessionMgr-%sesmgr_old_ver%.dll SessionMgr-%sesmgr_old_ver%.dll.bak
70 | if errorlevel 1 (
71 | echo Backup ERROR 3
72 | goto error_exit
73 | )
74 | ) else (
75 | echo Backup ERROR 4
76 | goto error_exit
77 | )
78 | )
79 | xcopy /y /q obj\SessionMgr.dll %npp_plugin_dir%\SessionMgr-%sesmgr_new_ver%.dll
80 | if errorlevel 1 (
81 | echo Deploy ERROR
82 | goto error_exit
83 | )
84 | if %do_r% equ 1 goto release
85 | goto success_exit
86 |
87 | ::------------------------------------------------------------------------------
88 | :release
89 |
90 | echo Releasing...
91 | if exist %release_dir% (
92 | rmdir /s %release_dir%
93 | )
94 | xcopy /t /e /q dist\template %release_dir%\
95 | if errorlevel 1 (
96 | echo Release ERROR 1
97 | goto error_exit
98 | )
99 | xcopy /q obj\SessionMgr.dll %release_dir%\plugin\
100 | xcopy /q doc\* %release_dir%\plugin\doc\
101 | %zip_exe% a -r -tzip %release_dir%\SessionMgr-%sesmgr_new_ver%-plugin.zip %release_dir%\plugin\*
102 | if errorlevel 1 (
103 | echo Release ERROR 2
104 | goto error_exit
105 | )
106 | xcopy /q license.txt %release_dir%\source\npp-session-manager\
107 | xcopy /q Makefile %release_dir%\source\npp-session-manager\
108 | xcopy /q README %release_dir%\source\npp-session-manager\
109 | xcopy /q setenv.cmd %release_dir%\source\npp-session-manager\
110 | xcopy /q x.cmd %release_dir%\source\npp-session-manager\
111 | xcopy /s /q src\* %release_dir%\source\npp-session-manager\src\
112 | xcopy /q doc\* %release_dir%\source\npp-session-manager\doc\
113 | %zip_exe% a -r -tzip %release_dir%\SessionMgr-%sesmgr_new_ver%-source.zip %release_dir%\source\*
114 | if errorlevel 1 (
115 | echo Release ERROR 3
116 | goto error_exit
117 | )
118 | %md5_exe% %release_dir%\*.zip > %release_dir%\md5sums.txt
119 |
120 | ::------------------------------------------------------------------------------
121 |
122 | :success_exit
123 |
124 | echo SUCCESS
125 | exit /b 0
126 |
127 | :error_exit
128 |
129 | exit /b 1
130 |
131 | :silent_exit
132 |
133 | exit /b 0
134 |
--------------------------------------------------------------------------------