Menu

[r2000]: / trunk / Src / USaveSourceMgr.pas  Maximize  Restore  History

Download this file

345 lines (317 with data), 12.4 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
{
* USaveSourceMgr.pas
*
* Implements abstract base class for classes that manage generation, previewing
* and saving to disk of a source code files in various formats and encodings.
*
* Formerly named USourceFileOutputMgr.pas.
*
* $Rev$
* $Date$
*
* ***** BEGIN LICENSE BLOCK *****
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is USaveSourceMgr.pas
*
* The Initial Developer of the Original Code is Peter Johnson
* (http://www.delphidabbler.com/).
*
* Portions created by the Initial Developer are Copyright (C) 2006-2010 Peter
* Johnson. All Rights Reserved.
*
* Contributor(s)
* NONE
*
* ***** END LICENSE BLOCK *****
}
unit USaveSourceMgr;
interface
uses
// Project
UBaseObjects, UEncodings, USaveSourceDlg, USourceFileInfo, USourceGen;
type
/// <summary>
/// Abstract base class for classes that manage generation, previewing and
/// saving to disk of a source code files in various formats and encodings.
/// </summary>
TSaveSourceMgr = class abstract(TNoPublicConstructObject)
strict private
var
/// <summary>Records information about supported source file types.
/// </summary>
fSourceFileInfo: TSourceFileInfo;
/// <summary>Dialog box used to get information from user about type of
/// source file to be saved.</summary>
fSaveDlg: TSaveSourceDlg;
/// <summary>Handles custom save dialog box's OnHiliteQuery event.
/// Determines whether syntax highlighting is supported for a given file
/// extension.</summary>
/// <param name="Sender">TObject [in] Reference to object that triggered
/// event.</param>
/// <param name="Ext">string [in] Name of extension to check.</param>
/// <param name="CanHilite">Boolean [in/out] Set to True if highlighting
/// supported for extension or False if not.</param>
procedure HiliteQueryHandler(Sender: TObject; const Ext: string;
var CanHilite: Boolean);
/// <summary>Handles custom save dialog box's OnEncodingQuery event.
/// Provides array of encodings supported for a file extension.</summary>
/// <param name="Sender">TObject [in] Reference to object that triggered
/// event.</param>
/// <param name="Ext">string [in] Name of extension to check.</param>
/// <param name="Encodings">TSourceFileEncodings [in/out] Receives array of
/// supported encodings.</param>
procedure EncodingQueryHandler(Sender: TObject; const Ext: string;
var Encodings: TSourceFileEncodings);
/// <summary>Handles custom save dialog's OnPreview event. Displays source
/// code appropriately formatted in preview dialog box.</summary>
/// <param name="Sender">TObject [in] Reference to object that triggered
/// event.</param>
procedure PreviewHandler(Sender: TObject);
/// <summary>Handles custom save dialog's OnCanClose event. Permits dialog
/// to close if filename entered in dialog box is acceptable.</summary>
/// <param name="Sender">TObject [in] Reference to object that triggered
/// event.</param>
/// <param name="CanClose">Boolean [in/out] Set to True to allow dialog to
/// close or false to inhibit.</param>
procedure CanCloseHandler(Sender: TObject; var CanClose: Boolean);
/// <summary>Checks if file name entered in save dialog box is acceptable.
/// </summary>
/// <returns>True if file name is acceptable, False if not.</returns>
function CheckEnteredFileName: Boolean;
/// <summary>Checks if highlighting is supported for a file type.</summary>
/// <param name="FileType">TSourceFileType [in] File type to check.</param>
/// <returns>True if file type supports highlighting, False if not.
/// </returns>
function IsHilitingSupported(const FileType: TSourceFileType): Boolean;
/// <summary>Generates source code in desired format.</summary>
/// <param name="FileType">TSourceFileType [in] Type of file. Determines
/// output file format.</param>
/// <returns>TEncodedData - Formatted source code, syntax highlighted if
/// required.</returns>
function GenerateOutput(const FileType: TSourceFileType): TEncodedData;
strict protected
/// <summary>Internal constructor. Initialises managed save source dialog
/// box and records information about supported file types.</summary>
constructor InternalCreate;
/// <summary>Displays save dialog box and creates required type of source
/// code file if user OKs.</summary>
procedure DoExecute;
/// <summary>Gets description of given source code file type.</summary>
function GetFileTypeDesc(const FileType: TSourceFileType): string;
virtual; abstract;
/// <summary>Gets default file name to display in dialog box.</summary>
function GetDefaultFileName: string; virtual; abstract;
/// <summary>Gets dialog box title.</summary>
function GetDlgTitle: string; virtual; abstract;
/// <summary>Get dialog box's help keyword.</summary>
function GetDlgHelpKeyword: string; virtual; abstract;
/// <summary>Gets title to be used for source document.</summary>
function GetDocTitle: string; virtual; abstract;
/// <summary>Generates raw, un-highlighted, source code.</summary>
/// <param name="CommentStyle">TCommentStyle [in] Style of commenting to be
/// used in source code.</param>
/// <returns>String containing generated source code.</returns>
function GenerateSource(const CommentStyle: TCommentStyle): string;
virtual; abstract;
/// <summary>Checks if a file name is valid for the kind of file being
/// saved.</summary>
/// <param name="FileName">string [in] Name of file to check.</param>
/// <param name="NameOK">Boolean [out] Set True if file name OK, False if
/// not.</param>
/// <param name="ErrorMessage">string [out] Error message describing
/// problem with invalid file name. Undefined if NameOK is True.</param>
procedure CheckFileName(const FileName: string; out NameOK: Boolean;
out ErrorMessage: string); virtual; abstract;
public
/// <summary>Object descructor. Tears down object.</summary>
destructor Destroy; override;
end;
implementation
uses
// Delphi
SysUtils,
// Project
FmPreviewDlg, Hiliter.UFileHiliter, UIOUtils, UMessageBox, UOpenDialogHelper,
UPreferences;
{ TSaveSourceMgr }
procedure TSaveSourceMgr.CanCloseHandler(Sender: TObject;
var CanClose: Boolean);
begin
CanClose := CheckEnteredFileName;
end;
function TSaveSourceMgr.CheckEnteredFileName: Boolean;
var
ErrMsg: string; // error message displayed if name not OK
resourcestring
sDefaultErrMsg = 'Invalid file name'; // default error message
begin
// Assume file name is OK
Result := True;
ErrMsg := '';
// Ask caller about file name via event
CheckFileName(fSaveDlg.FileName, Result, ErrMsg);
if not Result then
begin
// File name not acceptable: display message aligned over dialog box
if ErrMsg = '' then
ErrMsg := sDefaultErrMsg;
TMessageBox.Error(fSaveDlg, ErrMsg);
end;
end;
destructor TSaveSourceMgr.Destroy;
begin
fSaveDlg.Free;
fSourceFileInfo.Free;
inherited;
end;
procedure TSaveSourceMgr.DoExecute;
var
Encoding: TEncoding; // encoding to use for output file
FileContent: string; // output file content before encoding
FileType: TSourceFileType; // type of source file
begin
// Set up dialog box
fSaveDlg.Filter := fSourceFileInfo.FilterString;
fSaveDlg.FilterIndex := ExtToFilterIndex(
fSaveDlg.Filter,
fSourceFileInfo.FileTypeInfo[Preferences.SourceDefaultFileType].Extension,
1
);
fSaveDlg.FileName := fSourceFileInfo.DefaultFileName;
// Display dialog box and save file if user OKs
if fSaveDlg.Execute then
begin
FileType := fSourceFileInfo.FileTypeFromExt(
ExtractFileExt(fSaveDlg.FileName)
);
FileContent := GenerateOutput(FileType).ToString;
Encoding := TEncodingHelper.GetEncoding(fSaveDlg.SelectedEncoding);
try
TFileIO.WriteAllText(fSaveDlg.FileName, FileContent, Encoding, True);
finally
TEncodingHelper.FreeEncoding(Encoding);
end;
end;
end;
procedure TSaveSourceMgr.EncodingQueryHandler(Sender: TObject;
const Ext: string; var Encodings: TSourceFileEncodings);
var
FileType: TSourceFileType; // type of file that has given extension
begin
FileType := fSourceFileInfo.FileTypeFromExt(Ext);
Encodings := fSourceFileInfo.FileTypeInfo[FileType].Encodings;
end;
function TSaveSourceMgr.GenerateOutput(const FileType: TSourceFileType):
TEncodedData;
var
RawSource: string; // raw source code
Hiliter: TFileHiliter; // object used to highlight source code
begin
RawSource := GenerateSource(fSaveDlg.CommentStyle);
// Highlight the raw source as required
Hiliter := TFileHiliter.Create(
fSaveDlg.UseSyntaxHiliting and IsHilitingSupported(FileType),
FileType
);
try
Result := Hiliter.Hilite(RawSource, GetDocTitle);
finally
Hiliter.Free;
end;
end;
procedure TSaveSourceMgr.HiliteQueryHandler(Sender: TObject; const Ext: string;
var CanHilite: Boolean);
begin
CanHilite := IsHilitingSupported(fSourceFileInfo.FileTypeFromExt(Ext));
end;
constructor TSaveSourceMgr.InternalCreate;
resourcestring
// descriptions of supported encodings
sANSIDefaultEncoding = 'ANSI (Default)';
sUTF8Encoding = 'UTF-8';
sUTF16LEEncoding = 'Unicode (Little Endian)';
sUTF16BEEncoding = 'Unicode (Big Endian)';
begin
inherited InternalCreate;
fSourceFileInfo := TSourceFileInfo.Create;
with fSourceFileInfo do
begin
FileTypeInfo[sfText] := TSourceFileTypeInfo.Create(
'.txt',
GetFileTypeDesc(sfText),
[
TSourceFileEncoding.Create(etSysDefault, sANSIDefaultEncoding),
TSourceFileEncoding.Create(etUTF8, sUTF8Encoding),
TSourceFileEncoding.Create(etUTF16LE, sUTF16LEEncoding),
TSourceFileEncoding.Create(etUTF16BE, sUTF16BEEncoding)
]
);
FileTypeInfo[sfPascal] := TSourceFileTypeInfo.Create(
'.pas',
GetFileTypeDesc(sfPascal),
[
TSourceFileEncoding.Create(etSysDefault, sANSIDefaultEncoding),
TSourceFileEncoding.Create(etUTF8, sUTF8Encoding)
]
);
FileTypeInfo[sfHTML] := TSourceFileTypeInfo.Create(
'.html',
GetFileTypeDesc(sfHTML),
[
TSourceFileEncoding.Create(etUTF8, sUTF8Encoding)
]
);
FileTypeInfo[sfRTF] := TSourceFileTypeInfo.Create(
'.rtf',
GetFileTypeDesc(sfRTF),
[
TSourceFileEncoding.Create(etSysDefault, sANSIDefaultEncoding)
]
);
DefaultFileName := GetDefaultFileName;
end;
fSaveDlg := TSaveSourceDlg.Create(nil);
fSaveDlg.Title := GetDlgTitle;
fSaveDlg.HelpKeyword := GetDlgHelpKeyword;
fSaveDlg.CommentStyle := Preferences.SourceCommentStyle;
fSaveDlg.UseSyntaxHiliting := Preferences.SourceSyntaxHilited;
fSaveDlg.OnPreview := PreviewHandler;
fSaveDlg.OnHiliteQuery := HiliteQueryHandler;
fSaveDlg.OnEncodingQuery := EncodingQueryHandler;
fSaveDlg.OnCanClose := CanCloseHandler;
end;
function TSaveSourceMgr.IsHilitingSupported(
const FileType: TSourceFileType): Boolean;
begin
Result := TFileHiliter.IsHilitingSupported(FileType);
end;
procedure TSaveSourceMgr.PreviewHandler(Sender: TObject);
const
// Map of source file type to preview document types
PreviewDocTypeMap: array[TSourceFileType] of TPreviewDocType = (
dtPlainText, dtPlainText, dtHTML, dtRTF
);
var
FileType: TSourceFileType; // type of source file to preview
begin
FileType := fSourceFileInfo.FileTypeFromExt(fSaveDlg.SelectedExt);
// Display preview dialog box. We use save dialog as owner to ensure preview
// dialog box is aligned over save dialog box
TPreviewDlg.Execute(
fSaveDlg,
GenerateOutput(FileType),
PreviewDocTypeMap[FileType],
GetDocTitle
);
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.