tagging release
[dasher.git] / trunk / Src / Win32 / Widgets / FilenameGUI.cpp
blob64f719ec03defdc434b09ab6ca5fffcf8b775c7e
1 // FilenameGUI.cpp
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2002 Iain Murray, Inference Group, Cavendish, Cambridge.
6 //
7 /////////////////////////////////////////////////////////////////////////////
9 /*
10 TODO: For some reason I can't get VC++ 6 SP4 or SP5 (I upgraded just to see) on win2k SP1
11 to debug this module without raising "user breakpoints". While this can be due to
12 deliberate int3 instructions, in my experience it is normally indicative of junk code
13 being loaded due to a buffer overrun. I am concerned.
15 There seem to be a few common gotchas using the OPENFILNAME structure, but I don't see
16 what I'm doing wrong. In fact the WINUI\CMDDLG\COMDLG32 SDK sample suffers from exactly
17 the same problem on my system, I even downloaded the latest SDK to see if it has been
18 fixed. Now I really don't know what to do, short of reinstalling Windows and Devstudio,
19 which I really don't want to do.
21 I have wasted faar too much time fiddlying and Googling already. Could someone tell me
22 what the problem is? Could they also tell me if it will be just fine on other computers?
24 Update - on another computer (also win2k) with VC++ the problem isn't there.
25 I don't have time to work out the difference, I'll just try and compile any releases on
26 that computer (uist for inference group members).
28 IAM 08/02
31 #include "WinCommon.h"
33 #include "FilenameGUI.h"
34 #include "../resource.h"
36 #ifndef _MAX_FNAME
37 #define _MAX_FNAME 64
38 #endif
40 using namespace std;
42 // Track memory leaks on Windows to the line that new'd the memory
43 #ifdef _WIN32
44 #ifdef _DEBUG
45 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
46 #define new DEBUG_NEW
47 #undef THIS_FILE
48 static char THIS_FILE[] = __FILE__;
49 #endif
50 #endif
52 const Tstring CFilenameGUI::Empty = TEXT("");
54 CFilenameGUI::CFilenameGUI(HWND WindowWithTitlebar, Tstring AppName, bool NewWithDate)
55 :WindowWithTitlebar(WindowWithTitlebar), AppName(AppName), NewWithDate(NewWithDate), Dirty(false), FileAndPath(TEXT("")) {
57 #ifndef DASHER_WINCE
58 TCHAR CurrentDirectory[_MAX_DIR];
59 if(GetCurrentDirectory(_MAX_DIR, CurrentDirectory) > 0) {
60 OriginalPath = CurrentDirectory;
61 string foo;
62 if(OriginalPath[OriginalPath.size() - 1] != TEXT('\\')) // Yuck. Can't find a call to get
63 OriginalPath += TEXT('\\'); // the directory separator
65 else
66 #endif
67 OriginalPath = TEXT("");
69 if(NewWithDate) {
70 New();
72 else
73 SetWindowTitle();
76 const Tstring & CFilenameGUI::New() {
77 if(!NewWithDate) {
78 FileAndPath = TEXT("");
80 else {
81 SYSTEMTIME SystemTime;
82 GetLocalTime(&SystemTime);
84 // I don't care that different countries write dates differently.
85 // It's not as if the following is even how I would write a date normally.
86 // The point is that this is a _filename_ - and filenames sort in the
87 // correct order iff you format the date with this ordering.
88 TCHAR Buffer[32];
89 _stprintf(Buffer, TEXT("%04d-%02d-%02d_%02d-%02d-%02d.txt"), SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);
91 FileAndPath = OriginalPath + Buffer;
94 Dirty = false;
95 SetWindowTitle();
97 return FileAndPath;
100 const Tstring & CFilenameGUI::Open() {
101 OPENFILENAME OpenDialogStructure;
102 TCHAR FullOpenFilename[_MAX_PATH] = TEXT("");
104 // Initialize OPENFILENAME
105 ZeroMemory(&OpenDialogStructure, sizeof(OpenDialogStructure));
106 #ifdef OPENFILENAME_SIZE_VERSION_400
107 OpenDialogStructure.lStructSize = OPENFILENAME_SIZE_VERSION_400;
108 #else
109 OpenDialogStructure.lStructSize = sizeof(OpenDialogStructure);
110 #endif
111 OpenDialogStructure.hwndOwner = WindowWithTitlebar;
112 OpenDialogStructure.lpstrFile = FullOpenFilename;
113 OpenDialogStructure.nMaxFile = MAX_PATH;
114 OpenDialogStructure.lpstrFilter = TEXT("All Files\0*.*\0Text Documents (*.txt)\0*.txt\0");
115 OpenDialogStructure.nFilterIndex = 1;
116 OpenDialogStructure.lpstrDefExt = TEXT("txt");
117 OpenDialogStructure.lpstrInitialDir = NULL;
118 OpenDialogStructure.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
120 // Display the Open dialog box.
121 if(GetOpenFileName(&OpenDialogStructure) != TRUE)
122 return Empty;
124 // Remember file details if we have them
125 FileAndPath = OpenDialogStructure.lpstrFile;
127 return FileAndPath;
130 const Tstring & CFilenameGUI::Save() {
131 if(FileAndPath != TEXT(""))
132 return FileAndPath; // Return current filename if there is one
133 else
134 // Or as fairly standard in Windows apps, we revert to SaveAs behaviour
135 return SaveAs();
138 const Tstring & CFilenameGUI::SaveAs() {
139 // Lots of this is copy and pasted from FileOpen(), which means my programing style has gone to pot
140 // TODO make this better
141 OPENFILENAME OpenDialogStructure;
142 TCHAR FullOpenFilename[MAX_PATH] = TEXT("");
144 // Initialize OPENFILENAME
145 ZeroMemory(&OpenDialogStructure, sizeof(OpenDialogStructure));
146 #ifdef OPENFILENAME_SIZE_VERSION_400
147 OpenDialogStructure.lStructSize = OPENFILENAME_SIZE_VERSION_400;
148 #else
149 OpenDialogStructure.lStructSize = sizeof(OpenDialogStructure);
150 #endif
151 OpenDialogStructure.hwndOwner = WindowWithTitlebar;
152 OpenDialogStructure.lpstrFile = FullOpenFilename;
153 OpenDialogStructure.nMaxFile = MAX_PATH;
154 OpenDialogStructure.lpstrFilter = TEXT("All Files\0*.*\0Text Documents (*.txt)\0*.txt\0");
155 OpenDialogStructure.nFilterIndex = 1;
156 OpenDialogStructure.lpstrDefExt = TEXT("txt");
157 OpenDialogStructure.lpstrInitialDir = NULL;
158 OpenDialogStructure.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
160 // Display the SaveAs dialog box.
161 if(GetSaveFileName(&OpenDialogStructure) != TRUE)
162 return Empty;
164 // Remember file details if we have them
165 FileAndPath = OpenDialogStructure.lpstrFile;
167 return FileAndPath;
170 void CFilenameGUI::SetNewWithDate(bool Value) {
171 NewWithDate = Value;
174 void CFilenameGUI::SetDirty(bool Value) {
175 if(Dirty != Value) {
176 Dirty = Value;
177 SetWindowTitle();
181 void CFilenameGUI::SetWindowTitle() {
182 Tstring TitleText;
184 #ifndef DASHER_WINCE
185 TCHAR PrettyName[_MAX_FNAME];
186 if(GetFileTitle(FileAndPath.c_str(), PrettyName, _MAX_FNAME) == 0)
187 TitleText = PrettyName;
188 else
189 #endif
190 WinLocalisation::GetResourceString(IDS_UNTITLED_FILE, &TitleText);
192 if(Dirty)
193 TitleText += TEXT("*");
194 TitleText += TEXT(" - ");
195 TitleText += AppName;
196 SendMessage(WindowWithTitlebar, WM_SETTEXT, 0, (LPARAM) TitleText.c_str());
199 int CFilenameGUI::QuerySaveFirst() {
200 if(Dirty) {
201 Tstring ResourceString;
202 Tstring Title;
203 WinLocalisation::GetResourceString(IDS_QUERY_SAVE_CHANGES, &ResourceString);
204 WinLocalisation::GetResourceString(IDS_UNSAVED_CHANGES, &Title);
206 return MessageBox(WindowWithTitlebar, ResourceString.c_str(), Title.c_str(), MB_YESNOCANCEL | MB_ICONWARNING | MB_DEFBUTTON1 | MB_APPLMODAL);
209 return IDNO;
212 void CFilenameGUI::SetFilename(const Tstring &FileName) {
213 FileAndPath = FileName;
214 Dirty = false;
215 SetWindowTitle();