Bookmarks.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include "Bookmarks.h"
  6. #include "HierarchicalStorage.h"
  7. #include "TextsCore.h"
  8. //---------------------------------------------------------------------------
  9. #pragma package(smart_init)
  10. //---------------------------------------------------------------------------
  11. #define IS_NUMBER(STR) (StrToIntDef(STR, -123) != -123)
  12. //---------------------------------------------------------------------------
  13. __fastcall TBookmarks::TBookmarks(): TObject()
  14. {
  15. FBookmarkLists = new TStringList();
  16. FBookmarkLists->Sorted = true;
  17. FBookmarkLists->CaseSensitive = false;
  18. FBookmarkLists->Duplicates = dupError;
  19. }
  20. //---------------------------------------------------------------------------
  21. __fastcall TBookmarks::~TBookmarks()
  22. {
  23. Clear();
  24. SAFE_DESTROY(FBookmarkLists);
  25. }
  26. //---------------------------------------------------------------------------
  27. void __fastcall TBookmarks::Clear()
  28. {
  29. for (int i = 0; i < FBookmarkLists->Count; i++)
  30. {
  31. delete FBookmarkLists->Objects[i];
  32. }
  33. FBookmarkLists->Clear();
  34. }
  35. //---------------------------------------------------------------------------
  36. void __fastcall TBookmarks::Load(THierarchicalStorage * Storage)
  37. {
  38. bool Local = false;
  39. do
  40. {
  41. Local = !Local;
  42. if (Storage->OpenSubKey(Local ? "Local" : "Remote", false))
  43. {
  44. TStrings * BookmarkKeys = new TStringList();
  45. try
  46. {
  47. Storage->GetSubKeyNames(BookmarkKeys);
  48. for (int Index = 0; Index < BookmarkKeys->Count; Index++)
  49. {
  50. AnsiString Key = BookmarkKeys->Strings[Index];
  51. if (Storage->OpenSubKey(Key, false))
  52. {
  53. TBookmarkList * BookmarkList = Bookmarks[Key];
  54. if (!BookmarkList)
  55. {
  56. BookmarkList = new TBookmarkList();
  57. FBookmarkLists->AddObject(Key, BookmarkList);
  58. }
  59. LoadLevel(Storage, "", Local, BookmarkList);
  60. Storage->CloseSubKey();
  61. }
  62. }
  63. }
  64. __finally
  65. {
  66. delete BookmarkKeys;
  67. }
  68. Storage->CloseSubKey();
  69. }
  70. }
  71. while (Local);
  72. ModifyAll(false);
  73. }
  74. //---------------------------------------------------------------------------
  75. void __fastcall TBookmarks::LoadLevel(THierarchicalStorage * Storage, const AnsiString Key,
  76. bool Local, TBookmarkList * BookmarkList)
  77. {
  78. TStrings * Names = new TStringList();
  79. try
  80. {
  81. Storage->GetValueNames(Names);
  82. AnsiString Name, Directory;
  83. for (int i = 0; i < Names->Count; i++)
  84. {
  85. Name = Names->Strings[i];
  86. Directory = Storage->ReadString(Name, "");
  87. TBookmark * Bookmark;
  88. if (IS_NUMBER(Name))
  89. {
  90. Name = Directory;
  91. }
  92. if (!Name.IsEmpty())
  93. {
  94. Bookmark = BookmarkList->FindByName(Key, Name);
  95. bool New;
  96. New = (Bookmark == NULL);
  97. if (New)
  98. {
  99. Bookmark = new TBookmark();
  100. Bookmark->Node = Key;
  101. Bookmark->Name = Name;
  102. }
  103. if (Local)
  104. {
  105. Bookmark->Local = Directory;
  106. }
  107. else
  108. {
  109. Bookmark->Remote = Directory;
  110. }
  111. if (New)
  112. {
  113. BookmarkList->Add(Bookmark);
  114. }
  115. }
  116. }
  117. Storage->GetSubKeyNames(Names);
  118. for (int i = 0; i < Names->Count; i++)
  119. {
  120. Name = Names->Strings[i];
  121. if (Storage->OpenSubKey(Name, false))
  122. {
  123. LoadLevel(Storage, Key + (Key.IsEmpty() ? "" : "/") + Name, Local, BookmarkList);
  124. Storage->CloseSubKey();
  125. }
  126. }
  127. }
  128. __finally
  129. {
  130. delete Names;
  131. }
  132. }
  133. //---------------------------------------------------------------------------
  134. void __fastcall TBookmarks::Save(THierarchicalStorage * Storage)
  135. {
  136. bool Local = false;
  137. do
  138. {
  139. Local = !Local;
  140. if (Storage->OpenSubKey(Local ? "Local" : "Remote", true))
  141. {
  142. for (int Index = 0; Index < FBookmarkLists->Count; Index++)
  143. {
  144. TBookmarkList * BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[Index]);
  145. if (BookmarkList->Modified)
  146. {
  147. AnsiString Key;
  148. Key = FBookmarkLists->Strings[Index];
  149. Storage->RecursiveDeleteSubKey(Key);
  150. if (Storage->OpenSubKey(Key, true))
  151. {
  152. for (int IndexB = 0; IndexB < BookmarkList->Count; IndexB++)
  153. {
  154. TBookmark * Bookmark = BookmarkList->Bookmarks[IndexB];
  155. AnsiString Directory = Local ? Bookmark->Local : Bookmark->Remote;
  156. if (!Bookmark->Node.IsEmpty())
  157. {
  158. if (Storage->OpenSubKey(Bookmark->Node, true))
  159. {
  160. Storage->WriteString(Bookmark->Name, Directory);
  161. Storage->CloseSubKey();
  162. }
  163. }
  164. else
  165. {
  166. Storage->WriteString(Bookmark->Name, Directory);
  167. }
  168. }
  169. Storage->CloseSubKey();
  170. }
  171. }
  172. }
  173. Storage->CloseSubKey();
  174. }
  175. }
  176. while (Local);
  177. ModifyAll(false);
  178. }
  179. //---------------------------------------------------------------------------
  180. void __fastcall TBookmarks::ModifyAll(bool Modify)
  181. {
  182. TBookmarkList * BookmarkList;
  183. for (int i = 0; i < FBookmarkLists->Count; i++)
  184. {
  185. BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[i]);
  186. assert(BookmarkList);
  187. BookmarkList->Modified = Modify;
  188. }
  189. }
  190. //---------------------------------------------------------------------------
  191. TBookmarkList * __fastcall TBookmarks::GetBookmarks(AnsiString Index)
  192. {
  193. int I = FBookmarkLists->IndexOf(Index);
  194. if (I >= 0)
  195. {
  196. return dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[I]);
  197. }
  198. else
  199. {
  200. return NULL;
  201. }
  202. }
  203. //---------------------------------------------------------------------------
  204. void __fastcall TBookmarks::SetBookmarks(AnsiString Index, TBookmarkList * value)
  205. {
  206. int I = FBookmarkLists->IndexOf(Index);
  207. if (I >= 0)
  208. {
  209. TBookmarkList * BookmarkList;
  210. BookmarkList = dynamic_cast<TBookmarkList *>(FBookmarkLists->Objects[I]);
  211. BookmarkList->Assign(value);
  212. }
  213. else
  214. {
  215. TBookmarkList * BookmarkList = new TBookmarkList();
  216. BookmarkList->Assign(value);
  217. FBookmarkLists->AddObject(Index, BookmarkList);
  218. }
  219. }
  220. //---------------------------------------------------------------------------
  221. //---------------------------------------------------------------------------
  222. __fastcall TBookmarkList::TBookmarkList(): TPersistent()
  223. {
  224. FModified = false;
  225. FBookmarks = new TStringList();
  226. FBookmarks->CaseSensitive = false;
  227. }
  228. //---------------------------------------------------------------------------
  229. __fastcall TBookmarkList::~TBookmarkList()
  230. {
  231. Clear();
  232. SAFE_DESTROY(FBookmarks);
  233. }
  234. //---------------------------------------------------------------------------
  235. void __fastcall TBookmarkList::Clear()
  236. {
  237. for (int i = 0; i < FBookmarks->Count; i++)
  238. {
  239. delete FBookmarks->Objects[i];
  240. }
  241. FBookmarks->Clear();
  242. }
  243. //---------------------------------------------------------------------------
  244. void __fastcall TBookmarkList::Assign(TPersistent * Source)
  245. {
  246. TBookmarkList * SourceList;
  247. SourceList = dynamic_cast<TBookmarkList *>(Source);
  248. if (SourceList)
  249. {
  250. Clear();
  251. for (int i = 0; i < SourceList->FBookmarks->Count; i++)
  252. {
  253. TBookmark * Bookmark = new TBookmark();
  254. Bookmark->Assign(dynamic_cast<TBookmark *>(SourceList->FBookmarks->Objects[i]));
  255. Add(Bookmark);
  256. }
  257. Modified = SourceList->Modified;
  258. }
  259. else
  260. {
  261. TPersistent::Assign(Source);
  262. }
  263. }
  264. //---------------------------------------------------------------------------
  265. void __fastcall TBookmarkList::Add(TBookmark * Bookmark)
  266. {
  267. Insert(Count, Bookmark);
  268. }
  269. //---------------------------------------------------------------------------
  270. void __fastcall TBookmarkList::InsertBefore(TBookmark * BeforeBookmark, TBookmark * Bookmark)
  271. {
  272. assert(BeforeBookmark);
  273. int I = FBookmarks->IndexOf(BeforeBookmark->Key);
  274. assert(I >= 0);
  275. Insert(I, Bookmark);
  276. }
  277. //---------------------------------------------------------------------------
  278. void __fastcall TBookmarkList::MoveBefore(TBookmark * BeforeBookmark, TBookmark * Bookmark)
  279. {
  280. assert(BeforeBookmark);
  281. int NewIndex = FBookmarks->IndexOf(BeforeBookmark->Key);
  282. assert(Bookmark);
  283. int OldIndex = FBookmarks->IndexOf(Bookmark->Key);
  284. if (NewIndex > OldIndex)
  285. {
  286. NewIndex--;
  287. }
  288. FModified = true;
  289. FBookmarks->Move(OldIndex, NewIndex);
  290. }
  291. //---------------------------------------------------------------------------
  292. void __fastcall TBookmarkList::MoveAtEnd(TBookmark * Bookmark)
  293. {
  294. assert(Bookmark);
  295. int OldIndex = FBookmarks->IndexOf(Bookmark->Key);
  296. FModified = true;
  297. FBookmarks->Move(OldIndex, Count - 1);
  298. }
  299. //---------------------------------------------------------------------------
  300. void __fastcall TBookmarkList::Insert(int Index, TBookmark * Bookmark)
  301. {
  302. assert(Bookmark);
  303. assert(!Bookmark->FOwner);
  304. assert(!Bookmark->Name.IsEmpty());
  305. FModified = true;
  306. Bookmark->FOwner = this;
  307. if (FBookmarks->IndexOf(Bookmark->Key) >= 0)
  308. {
  309. throw Exception(FMTLOAD(DUPLICATE_BOOKMARK, (Bookmark->Name)));
  310. }
  311. FBookmarks->InsertObject(Index, Bookmark->Key, Bookmark);
  312. }
  313. //---------------------------------------------------------------------------
  314. void __fastcall TBookmarkList::Delete(TBookmark * Bookmark)
  315. {
  316. assert(Bookmark);
  317. assert(Bookmark->FOwner == this);
  318. int I = IndexOf(Bookmark);
  319. assert(I >= 0);
  320. FModified = true;
  321. Bookmark->FOwner = NULL;
  322. FBookmarks->Delete(I);
  323. }
  324. //---------------------------------------------------------------------------
  325. int __fastcall TBookmarkList::IndexOf(TBookmark * Bookmark)
  326. {
  327. return FBookmarks->IndexOf(Bookmark->Key);
  328. }
  329. //---------------------------------------------------------------------------
  330. void __fastcall TBookmarkList::KeyChanged(int Index)
  331. {
  332. assert(Index < Count);
  333. TBookmark * Bookmark = dynamic_cast<TBookmark *>(FBookmarks->Objects[Index]);
  334. assert(FBookmarks->Strings[Index] != Bookmark->Key);
  335. if (FBookmarks->IndexOf(Bookmark->Key) >= 0)
  336. {
  337. throw Exception(FMTLOAD(DUPLICATE_BOOKMARK, (Bookmark->Name)));
  338. }
  339. FBookmarks->Strings[Index] = Bookmark->Key;
  340. }
  341. //---------------------------------------------------------------------------
  342. TBookmark * __fastcall TBookmarkList::FindByName(const AnsiString Node, const AnsiString Name)
  343. {
  344. int I = FBookmarks->IndexOf(TBookmark::BookmarkKey(Node, Name));
  345. TBookmark * Bookmark = I >= 0 ? dynamic_cast<TBookmark *>(FBookmarks->Objects[I]) : NULL;
  346. assert(!Bookmark || (Bookmark->Node == Node && Bookmark->Name == Name));
  347. return Bookmark;
  348. }
  349. //---------------------------------------------------------------------------
  350. int __fastcall TBookmarkList::GetCount()
  351. {
  352. return FBookmarks->Count;
  353. }
  354. //---------------------------------------------------------------------------
  355. TBookmark * __fastcall TBookmarkList::GetBookmarks(int Index)
  356. {
  357. TBookmark * Bookmark = dynamic_cast<TBookmark *>(FBookmarks->Objects[Index]);
  358. assert(Bookmark);
  359. return Bookmark;
  360. }
  361. //---------------------------------------------------------------------------
  362. //---------------------------------------------------------------------------
  363. __fastcall TBookmark::TBookmark()
  364. {
  365. FOwner = NULL;
  366. }
  367. //---------------------------------------------------------------------------
  368. void __fastcall TBookmark::Assign(TPersistent * Source)
  369. {
  370. TBookmark * SourceBookmark;
  371. SourceBookmark = dynamic_cast<TBookmark *>(Source);
  372. if (SourceBookmark)
  373. {
  374. Name = SourceBookmark->Name;
  375. Local = SourceBookmark->Local;
  376. Remote = SourceBookmark->Remote;
  377. Node = SourceBookmark->Node;
  378. }
  379. else
  380. {
  381. TPersistent::Assign(Source);
  382. }
  383. }
  384. //---------------------------------------------------------------------------
  385. void __fastcall TBookmark::SetName(const AnsiString value)
  386. {
  387. if (Name != value)
  388. {
  389. int OldIndex = FOwner ? FOwner->IndexOf(this) : -1;
  390. AnsiString OldName = FName;
  391. FName = value;
  392. try
  393. {
  394. Modify(OldIndex);
  395. }
  396. catch(...)
  397. {
  398. FName = OldName;
  399. throw;
  400. }
  401. }
  402. }
  403. //---------------------------------------------------------------------------
  404. void __fastcall TBookmark::SetLocal(const AnsiString value)
  405. {
  406. if (Local != value)
  407. {
  408. FLocal = value;
  409. Modify(-1);
  410. }
  411. }
  412. //---------------------------------------------------------------------------
  413. void __fastcall TBookmark::SetRemote(const AnsiString value)
  414. {
  415. if (Remote != value)
  416. {
  417. FRemote = value;
  418. Modify(-1);
  419. }
  420. }
  421. //---------------------------------------------------------------------------
  422. void __fastcall TBookmark::SetNode(const AnsiString value)
  423. {
  424. if (Node != value)
  425. {
  426. int OldIndex = FOwner ? FOwner->IndexOf(this) : -1;
  427. FNode = value;
  428. Modify(OldIndex);
  429. }
  430. }
  431. //---------------------------------------------------------------------------
  432. void __fastcall TBookmark::Modify(int OldIndex)
  433. {
  434. if (FOwner)
  435. {
  436. FOwner->Modified = true;
  437. if (OldIndex >= 0)
  438. {
  439. FOwner->KeyChanged(OldIndex);
  440. }
  441. }
  442. }
  443. //---------------------------------------------------------------------------
  444. AnsiString __fastcall TBookmark::BookmarkKey(const AnsiString Node, const AnsiString Name)
  445. {
  446. return FORMAT("%s\1%s", (Node, Name));
  447. }
  448. //---------------------------------------------------------------------------
  449. AnsiString __fastcall TBookmark::GetKey()
  450. {
  451. return BookmarkKey(Node, Name);
  452. }