OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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