OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
rcntfile.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1995, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of class TRecentFiles
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9
10//#if !defined(__GNUC__) //JJH added removal of pragma hdrstop for gcc
11#pragma hdrstop
12//#endif
13
14#include <owl/framewin.h>
15#include <owl/rcntfile.h>
16#include <owl/pointer.h>
17#include <owl/profile.h>
18#include <owl/registry.h>
19#include <owl/window.rh>
20#include <owl/editfile.rh>
21#include <stdio.h>
22
23#include <algorithm>
24
25#include <owl/rcntfile.rh> //for CM_MRU_FIRST
26
27namespace owl {
28
30
34
35#if defined(WINELIB) //JJH's work
36static const tchar* CountKey = _T("Count");
37static const tchar* MruPrefix = _T("File");
38static const tchar* MenuItemDefault= _T("Default");
39static const tchar* Section = _T("Recent File List");
40static const tchar* MaxCountKey = _T("MaxCount");
41#else
42const tchar* CountKey = _T("Count");
43const tchar* MruPrefix = _T("File");
44const tchar* MenuItemDefault= _T("Default");
45const tchar* Section = _T("Recent File List");
46const tchar* MaxCountKey = _T("MaxCount");
47#endif
48const int MaxMenuItemLen = 255;
50uint TRecentFiles::MruMessage = 0;
51
52//
53// Response Table to catch the items selected from the menu.
54//
68
69
70static int
71TRecentFiles__ReadMaxNum(bool useRegistry, const tstring& mruName,
72 int defaultCount)
73{
74 const auto getMaxCount = [&]() -> int
75 {
76 if (useRegistry)
77 {
78 if (const auto k = TRegKey::GetCurrentUser().GetSubkey(mruName))
79 if (const auto v = k->GetValue(MaxCountKey))
80 return static_cast<int>(static_cast<uint32>(*v));
81 return defaultCount;
82 }
83 else
85 };
86 return std::min(getMaxCount(), static_cast<int>(TRecentFiles::MaxMenuItems));
87}
88
89
90
91//
92/// Constructor to initialize the external storage and the maximum number of items
93/// to save in the most-recently-used (MRU) list.
94//
96 int namelen, bool useRegistry, bool keepFullNameInMenu)
97:
98 MaxFilesToSave(0),
99 MaxDispLen(namelen),
100 AddedSeparator(false),
101 UseRegistry(useRegistry),
102 LastHMenu(nullptr),
103 MruCount(0),
104 keepFullNameInMenu(keepFullNameInMenu)
105{
106 int filestosave = std::min(numSavedFiles, static_cast<int>(MaxMenuItems));
107 MruName = iniName;
108 if(UseRegistry){
109 MruName += _T("\\");
110 MruName += Section;
111 }
112 else
113 MruName = TFileName(iniName).Canonical();
114
115 if(filestosave < 0)
116 filestosave = TRecentFiles__ReadMaxNum(UseRegistry, MruName, filestosave);
117
120
121 Read();
122}
123
124//
125/// Deletes the allocated profile.
126//
128{
129 Write();
130}
131
132//
133/// Sets the maximum number of items that can be saved with this MRU.
134//
135void
137{
138 if(numItems > MaxFilesToSave){
139 TFileName* items = new TFileName[numItems];
140 for(int i = 0; i < MaxFilesToSave && i < numItems; i++)
141 items[i] = MruNames[i];
142 MruNames = items;
143 }
144 MaxFilesToSave = numItems;
145}
146
147//
148/// Responds to a menu item selection.
149//
150void
152{
154 TFrameWindow* window = app ? app->GetMainWindow() : nullptr;
155
156 if (window) {
157 // Foward menu selection command to specified target
158 //
159 window->SendMessage(MruMessage, id, 0);
160 }
161}
162
163//
164/// Searches the menu to find the position of a menu item.
165//
166int
168{
169 for (int i = ::GetMenuItemCount(menu) - 1; i >= 0; i--)
170 if (::GetMenuItemID(menu, i) == id)
171 return i;
172 return -1;
173}
174
175//
176/// Retrieves the menu position of the CM_EXIT menu item. Returns -1 if not found.
177//
178int
184
185//
186/// Returns true if the menu has any MRU items in it.
187//
188bool
194
195//
196/// Removes the MRU items from the menu.
197//
198void
200{
202 if (exitPos > 1)
203 if (::GetMenuItemID(hMenu, exitPos - 1) == 0 && AddedSeparator) {
204 AddedSeparator = false;
205 if (LastHMenu == hMenu)
206 ::RemoveMenu(hMenu, exitPos - 1, MF_BYPOSITION);
207 }
208
209 // remove MRU items
210 //
212 for (int i = CM_MRU_FIRST; i < CM_MRU_LAST; i++) {
213 int menuPos = GetMenuPos(hMenu, i);
214 if (menuPos != -1) {
215 ::RemoveMenu(hMenu, i, MF_BYCOMMAND);
216 }
217 }
218 }
219}
220
221//
222/// Reads external information and adds the MRU items into the menu. Adds a
223/// separator between the MRU items and the exit menu item.
224//
225void
227{
229
230 TMenu menu(hMenu);
232 //int count = GetMruCount();
233 int i;
234 int numItemsAdded = 0;
235
237
238 for (i = 0; i < MruCount; i++) {
239 //if(!MruNames[i].IsValid()) //?????????????
240 // break;
241
243
244 tstring curname = MruNames[i].GetParts(FullFileName);
245 if(curdir == MruNames[i].GetParts(FullPathName))
246 curname = MruNames[i].GetParts(TFileName::File|TFileName::Ext);
247 curname = TFileName(curname).Squeezed(MaxDispLen, keepFullNameInMenu);
248 // insert mnemonic + the file name
249 if((i+1) >= 10)
250 wsprintf(menuItemBuffer, _T("%d&%d %s"), (i+1)/10, (i+1)%10, curname.c_str());
251 else
252 wsprintf(menuItemBuffer, _T("&%d %s"), (i+1), curname.c_str());
253
255 }
256
257 if (numItemsAdded > 0) {
258 if (AddedSeparator == false) {
259 LastHMenu = hMenu;
260 AddedSeparator = true;
261 menuItemBuffer[0] = 0;
263 }
264 }
265}
266
267//
268/// Reads information in the TProfile to display the menu choices.
269//
270void
272{
273 ce.Enable(true);
274
276 if (me == nullptr)
277 return;
278
279 HMENU hMenu = me->GetMenu();
282}
283
284/// Retrieves the text of the choice based on the ID.
287{
288 id -= CM_MRU_FIRST;
289 if (id < 0 || MruCount <= id)
290 return tstring(_T(""));
291 return MruNames[id].GetParts(FullFileName);
292}
293
294//
295/// Retrieves the text of the choice based on the ID.
296//
297bool
299{
300 id -= CM_MRU_FIRST;
301 //int count = GetMruCount();
302 if (id < 0 || MruCount <= id)
303 return false;
304 tstring menuText = MruNames[id].GetParts(FullFileName);
305 if(::_tcslen(menuText.c_str()) > (size_t)maxTextLen){
306 _tcsncpy(text, menuText.c_str(), maxTextLen-1);
307 text[maxTextLen] = _T('\0');
308 }
309 else
310 ::_tcscpy(text, menuText.c_str());
311 return true;
312}
313
314//
315/// Saves the menu choice into the profile.
316//
317void
324
325//
326// Remove the menu choice.
327//
328void
333
334//
335/// Removes the MRU item at index. Shuffles the items below index up.
336//
337void
339{
340 //int count = GetMruCount();
341 if (index < 0 || MruCount <= index)
342 return;
343
344 if (index != MruCount - 1) {
345 // shuffle so the item to be deleted is at index count-1
346 //
347 for(int i = index; i < MruCount - 1; i++)
348 MruNames[i] = MruNames[i+1];
349 }
350
351 // delete the last item
352 //
353 MruNames[MruCount-1] = _T("");
354 MruCount--; // decrease MRUCount
355}
356
357//
358/// Adds an item to the top of the MRU list. If there is a duplicate, the item is
359/// moved from its current position to the top of the list.
360//
361void
363{
364 if (MaxFilesToSave <= 0)
365 return;
367 if (sFullFilePath.empty())
368 return;
369 if(MruCount < MaxFilesToSave)
370 MruCount++;
371 if (MruCount > 1){
372 // Shuffle items down to make room at index 0
373 //
374 for (int i = MruCount - 2; i >= 0; i--)
375 MruNames[i+1] = MruNames[i];
376 }
377
378 // Add item to the top of the list
379 //
380 MruNames[0] = sFullFilePath;
381}
382
383//
384/// Returns true if there are any items in the MRU list that match the text.
385//
386bool
391
392//
393/// Returns the index of the MRU item containing text. Returns -1 if not found.
394//
395int
397{
398 TFileName filename(TFileName(text).Canonical());
399 for (int i = 0; i < MruCount; i++) {
400 if(MruNames[i] == filename)
401 return i;
402 }
403 return -1;
404}
405//
406// Read Data from registry or file
407//
408void
409TRecentFiles::Read()
410{
411 if (UseRegistry)
412 {
413 const auto k = TRegKey::GetCurrentUser().GetSubkey(MruName);
414 WARN(!k, _T("Registry key is missing for MRU: HKEY_CURRENT_USER\\") << MruName);
415 if (!k) return;
416 const auto c = k->GetValue(CountKey);
417 WARN(!c, _T("Registry value is missing for MRU: ") << CountKey);
418 if (!c) return;
419 MruCount = std::min(static_cast<int>(static_cast<uint32>(*c)), MaxFilesToSave);
420 for (auto i = 0; i != MruCount; ++i)
421 {
422 const auto f = k->GetValue(MruPrefix + to_tstring(i));
423 WARN(!f, _T("Registry value is missing for MRU: " << MruPrefix << i));
424 if (!f) return;
425 MruNames[i] = *f;
426 }
427 }
428 else
429 {
432 TProfile profile(Section, MruName.c_str());
433 MruCount = profile.GetInt(CountKey, 0);
434 if (MruCount > MaxFilesToSave)
435 MruCount = MaxFilesToSave;
436 for (int i = 0; i < MruCount; i++){
437 wsprintf(srcKeyBuffer, _T("%s%d"), MruPrefix, i);
439 MruNames[i] = (tchar*)menuText;
440 }
441 }
442}
443//
444// Write data to registry or file
445//
446void
447TRecentFiles::Write()
448{
449 if (UseRegistry)
450 {
451 auto& c = TRegKey::GetCurrentUser();
452 [[maybe_unused]] const auto r = c.DeleteKey(MruName);
454 auto k = TRegKey{c, MruName}; CHECK(k.GetHandle());
455 TRegValue{k, CountKey} = static_cast<uint32>(MruCount);
456 for (auto i = 0; i != MruCount; ++i)
457 TRegValue{k, MruPrefix + to_tstring(i)} = MruNames[i].GetParts(FullFileName);
458 }
459 else
460 {
462 TProfile profile(Section, MruName.c_str());
463 profile.WriteInt(CountKey, MruCount);
464 for (int i = 0; i < MruCount; i++){
465 wsprintf(dstKeyBuffer, _T("%s%d"), MruPrefix, i);
466 profile.WriteString(dstKeyBuffer, MruNames[i].GetParts(FullFileName));
467 }
468 }
469}
470
471} // OWL namespace
472
473/* ========================================================================== */
474
#define CHECK(condition)
Definition checks.h:239
#define WARN(condition, message)
Definition checks.h:273
Derived from TModule and TMsgThread and virtually derived from TEventHandler, TApplication acts as an...
Definition applicat.h:141
Base class for an extensible interface for auto enabling/disabling of commands (menu items,...
Definition window.h:209
TEventHandler is a base class from which you can derive classes that handle messages.
Definition eventhan.h:162
The TFileName class constructs filenames.
Definition filename.h:37
@ Device
Logical device or sharename.
Definition filename.h:127
@ Path
Directory path to the file.
Definition filename.h:128
@ Ext
Extension.
Definition filename.h:130
@ File
Filename part without the extension.
Definition filename.h:129
@ Server
Server name.
Definition filename.h:126
const tstring & Canonical(bool forceUNC=false) const
Return normal fully qualified path string.
Definition filename.cpp:520
const tchar * Squeezed(int maxLen, bool keepName=true) const
Obtains a human-readable form of the filename.
Definition filename.cpp:682
const tchar * GetParts(uint p) const
Reassembles any logical subset of filename parts.
Definition filename.cpp:759
@ CurrentDir
Current working directory if any.
Definition filename.h:94
Derived from TWindow, TFrameWindow controls such window-specific behavior as keyboard navigation and ...
Definition framewin.h:96
The TMenu class encapsulates window menus.
Definition menu.h:77
bool InsertMenu(uint item, uint flags, TMenuItem newItem=-1, LPCTSTR newStr=nullptr)
Inserts a new text menu item or pop-up menu into the menu after the menu item specified in item.
Definition menu.h:458
Derived from TCommandEnabler, TMenuItemEnabler is a command enabler for menu items.
Definition framewin.h:39
An instance of TProfile encapsulates a setting within a system file, often referred to as a profile o...
Definition profile.h:44
TRecentFiles implements a most-recent files list, designed to be mixed in with TApplication.
Definition rcntfile.h:39
void CeExit(TCommandEnabler &ce)
Reads information in the TProfile to display the menu choices.
Definition rcntfile.cpp:271
void SaveMenuChoice(LPCTSTR text)
Saves the menu choice into the profile.
Definition rcntfile.cpp:318
void InsertMruItemsToMenu(HMENU hMenu)
Reads external information and adds the MRU items into the menu.
Definition rcntfile.cpp:226
int GetMenuPos(HMENU hMenu, uint id)
Searches the menu to find the position of a menu item.
Definition rcntfile.cpp:167
int GetExitMenuPos(HMENU hMenu)
Retrieves the menu position of the CM_EXIT menu item. Returns -1 if not found.
Definition rcntfile.cpp:179
bool GetMenuText(int id, TCHAR *text, int maxTextLen)
Retrieves the text of the choice based on the ID.
Definition rcntfile.cpp:298
void RemoveMruIndex(int index)
Removes the MRU item at index. Shuffles the items below index up.
Definition rcntfile.cpp:338
virtual ~TRecentFiles()
Deletes the allocated profile.
Definition rcntfile.cpp:127
void SetMaxMruItems(int maxValue)
Sets the maximum number of items that can be saved with this MRU.
Definition rcntfile.cpp:136
void CmFile(uint id)
Responds to a menu item selection.
Definition rcntfile.cpp:151
bool ExistMruItem(LPCTSTR text)
Returns true if there are any items in the MRU list that match the text.
Definition rcntfile.cpp:387
int GetMruItemIndex(LPCTSTR text)
Returns the index of the MRU item containing text. Returns -1 if not found.
Definition rcntfile.cpp:396
TRecentFiles(const tstring &iniOrKeyName, int numSavedFiles=MaxMenuItems, int namelen=30, bool useRegistry=false, bool keepFullNameInMenu=true)
Constructor to initialize the external storage and the maximum number of items to save in the most-re...
Definition rcntfile.cpp:95
void RemoveMruItemsFromMenu(HMENU hMenu)
Removes the MRU items from the menu.
Definition rcntfile.cpp:199
void RemoveMenuChoice(LPCTSTR text)
Definition rcntfile.cpp:329
bool MruItemsInsertedIntoMenu(HMENU hMenu)
Returns true if the menu has any MRU items in it.
Definition rcntfile.cpp:189
void AddMruItem(LPCTSTR text)
Adds an item to the top of the MRU list.
Definition rcntfile.cpp:362
static auto GetCurrentUser() -> TRegKey &
Special predefined root key defining the preferences of the current user (HKEY_CURRENT_USER).
Definition registry.cpp:72
TResult SendMessage(TMsgId, TParam1=0, TParam2=0) const
Sends a message (msg) to a specified window or windows.
Definition window.cpp:3288
#define _tcsncpy
Definition cygwin.h:80
#define _tcslen
Definition cygwin.h:74
#define _T(x)
Definition cygwin.h:51
#define DEFINE_RESPONSE_TABLE1(cls, base)
Macro to define a response table for a class with one base.
Definition eventhan.h:492
Definition of class TFrameWindow.
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
const tchar * MruPrefix
Definition rcntfile.cpp:43
const int CM_MRU_LAST
Definition rcntfile.cpp:31
const tchar * Section
Definition rcntfile.cpp:45
unsigned long uint32
Definition number.h:34
const tchar * MaxCountKey
Definition rcntfile.cpp:46
const uint FullPathName
Definition rcntfile.cpp:32
char tchar
Definition defs.h:77
const tchar * CountKey
Definition rcntfile.cpp:42
OWL_DIAGINFO
Definition animctrl.cpp:14
const uint FullFileName
Definition rcntfile.cpp:33
END_RESPONSE_TABLE
Definition button.cpp:26
std::string tstring
Definition defs.h:79
const int MaxMenuItemLen
Definition rcntfile.cpp:48
unsigned int uint
Definition number.h:25
const int MaxRegValueLen
Definition rcntfile.cpp:49
auto to_tstring(const T &v) -> tstring
Definition defs.h:82
const tchar * MenuItemDefault
Definition rcntfile.cpp:44
#define TYPESAFE_DOWNCAST(object, toClass)
Definition defs.h:269
Various types of smart pointer templatized classes.
Definition of TProfile class.
Definition of TRecentFiles class.
#define MruFileMessage
Derived classes should catch the following registered message to know when an item in the recent list...
Definition rcntfile.h:27
General Registry access & registration implementation TRegKey, TRegValue, TRegKeyIterator,...
#define EV_COMMAND_ENABLE(id, method)
Response table entry for enabling a command.
Definition windowev.h:193
#define EV_COMMAND_AND_ID(id, method)
Response table entry for a menu/accelerator/push button message The menu id is passed in as an argume...
Definition windowev.h:182