Subversion Repositories stackman

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 1
unit global;
2
 
3
interface
4
 
5
uses
6
  SysUtils, Classes, Dialogs, Forms, Windows, ShellAPI, Controls,
7
  ComCtrls, WinInet;
8
 
9
type
10
  TAMode = (emUnknown, emFolder, emText, emAppender, emForeign);
11
 
12
// TODO: So viel wie möglich in den implementation Teil schieben
13
function allFiles(folder: string): string;
14
function FilenameToCatname(fil: string): string;
15
procedure StrokeFromFile(filename: string; index: integer; expected_text: string);
16
procedure AddToJournal(text: string);
17
function RemoveForbiddenChars(fn: string; dir: boolean): string;
18
procedure JournalDeleteEntry(fn: string);
19
function commonDelete(fn: string): boolean;
20
procedure commonExternalOpen(fn: string);
21
function GetUserFriendlyElementName(fn: string): string;
22
procedure openCategoriesWindow();
23
procedure newDialog(folder: string);
24
procedure OpenTextEditor(folder, cat: string);
25
procedure OpenAppenderEditor(folder, cat: string);
26
procedure renameDialog(Node: TTreeNode);
27
function DelTree(DirName : string): Boolean;
28
function MyAddTrailingPathDelimiter(folder: string): string;
29
function getDataPath(): string;
30
function getJournalFileName(): string;
31
function getAppenderFileName(Folder, Name: string): string;
32
function getTextFileName(Folder, Name: string): string;
33
function getFolderName(Folder, Name: string): string;
34
function GetRelativeNameFromNode(Node: TTreeNode): string;
35
function GetRelativeFileName(Filename: string): string;
36
function GetFileNameFromNode(Node: TTreeNode): string;
37
function GetFolderFromNode(Node: TTreeNode): string;
38
function IsTextNode(Node: TTreeNode): boolean;
39
function IsFolderNode(Node: TTreeNode): boolean;
40
function IsAppenderNode(Node: TTreeNode): boolean;
41
function IsForeignNode(Node: TTreeNode): boolean;
42
function IsRootNode(Node: TTreeNode): boolean;
43
// function GetPersonalFolder(Default: string): string; overload;
44
function GetPersonalFolder(): string; overload;
45
function GetCatFromNode(Node: TTreeNode): string;
46
Function GetHTML(AUrl: string): string;
47
procedure explode(delim: char; s: string; sl: TStringList);
48
 
49
type
50
  EStrokeUnknown = class(Exception);
51
  EStrokeMismatch = class(Exception);
52
  ENodeError = class(Exception);
53
  EInternalError = class(Exception);
54
 
55
resourcestring
56
  lng_cap_new = 'Neue Datei anlegen';
57
  lng_cap_rename = 'Umbennen';
58
  lng_jnl_renamed = 'Umbenannt: "%s" zu "%s".';
59
  lng_already_exists = 'Fehler! Die Datei "%s" existiert bereits.';
60
  lng_move_error = 'Fehler! Konnte nicht von "%s" nach "%s" verschieben.';
61
  lng_jnl_delete = 'LÖSCHE %s';
62
  lng_content_was = 'Der Inhalt war:';
63
  lng_no_content = 'Die Datei war leer.';
64
  lng_jnl_open_external = 'Öffne mit externem Programm: %s';
65
  lng_jnl_created = 'Erstellt: %s';
66
  lng_jnl_stroke_from = 'Streiche von %s:';
67
  lng_jnl_add_to = 'Füge hinzu: %s';
68
  lng_jnl_textchange = 'Textinhalt geändert: %s';
69
  lng_filenotfound = 'Datei wurde nicht gefunden.';
70
  lng_editor_title = '%s - Streichlisteneditor';
71
  lng_texteditor_title = '%s - AUTOSAVE Texteditor';
72
  lng_stroker_really = 'Möchten Sie diese %d Zeilen wirklich streichen?';
73
  lng_refresh_strokes_loss = 'Warnung: Beim Neu-Laden werden alle Streich-Vormerkungen (%d) entfernt. Wirklich neu laden?';
74
  lng_appendfirst = 'Neue Zeile vor dem Schließen in "%s" ablegen?';
75
  lng_savefirst = 'Die Änderungen an "%s" abspeichern?';
76
  lng_strokefirst = '%d markierte Zeilen in "%s" vor dem Schließen streichen?';
77
  lng_notdeleted = 'Fehler: Datei konnte nicht gelöscht werden!';
78
  lng_error = 'Ein Fehler ist aufgetreten.';
79
  lng_journal_error = 'Es konnte nicht in das Journal geschrieben werden!';
80
  lng_deletethis = 'Datensatz "%s" wirklich löschen?';
81
  lng_notcreated = 'Fehler: Datei konnte nicht erstellt werden!';
82
  lng_alreadyexists_open = 'Die Datei existiert bereits. Sie wird nun geöffnet.';
83
  lng_stroke_mismatch = 'Die zu streichende Zeile stimmt nicht mit der angezeigten Fassung überein.';
84
  lng_stroke_error = 'Unbekannter Fehler beim Streichen.';
85
  lng_root = 'Datensätze';
86
  lng_text = 'Text';
87
  lng_appender = 'Streichliste';
88
 
89
const
90
  app_pfx = 'app_';
91
  txt_pfx = 'tex_';
92
  c_length_of_pfx = Length(app_pfx); // = Length(txt_pfx)
93
  II_APPENDER = 0;
94
  II_TEXT = 1;
95
  II_FOLDER = 2;
96
  II_FOREIGN = 3;
97
  II_ROOT = 4;
98
  FOLDER_VIEWER = 'Explorer';
99
 
100
// Konfiguration
101
const
102
  CfgExpandNodesAtBeginning = false;
103
  CfgOpenCatWhenEverythingClosed = false;
104
  CfgAppenderAllowEmptyLines = true;
105
 
106
implementation
107
 
108
uses
109
  categories, journal, name, appender, texteditor;
110
 
111
resourcestring
112
  lng_internal_prefix_length_error = 'Entwicklungstechnischer Fehler! Präfixe dürfen nicht unterschiedlich lang sein!';
113
  lng_internal_unknown_node_type_error = 'Programminterner Fehler! Node-Typ unbekannt!';
114
 
115
function GetModeFromNode(ANode: TTreeNode): TAMode; forward;
116
function getFileName(mode: TAMode; folder, name: string): string; forward;
117
function ExtractFileNameWithoutExt(fil: string): string; forward;
118
function getRawFileName(folder, name: string): string; forward;
119
function Quote(arg: string): string; forward;
120
 
121
function allFiles(folder: string): string;
122
begin
123
  result := getRawFilename(folder, '*');
124
end;
125
 
126
function ExtractFileNameWithoutExt(fil: string): string;
127
begin
128
  result := Copy(ExtractFileName(fil), 1, Length(ExtractFileName(fil))-Length(ExtractFileExt(fil)));
129
end;
130
 
131
function FilenameToCatname(fil: string): string;
132
begin
133
  result := ExtractFileNameWithoutExt(fil);
134
  result := Copy(result, 1+c_length_of_pfx, length(result)-c_length_of_pfx);
135
  result := ExtractFilePath(fil) + result;
136
end;
137
 
138
procedure StrokeFromFile(filename: string; index: integer; expected_text: string);
139
var
140
  str: TStrings;
141
begin
142
  str := TStringList.Create;
143
  try
144
    try
145
      str.LoadFromFile(filename);
146
      if str.Strings[index] = expected_text then
147
        str.Delete(index)
148
      else
149
        raise EStrokeMismatch.Create(lng_stroke_mismatch);
150
      str.SaveToFile(filename);
151
    except
152
      on E: EStrokeMismatch do
153
        raise
154
      else
155
        raise EStrokeUnknown.Create(lng_stroke_error);
156
    end;
157
  finally
158
    str.Free;
159
  end;
160
end;
161
 
162
procedure AddToJournal(text: string);
163
var
164
  f: TextFile;
165
  l: string;
166
  i: integer;
167
begin
168
  l := Format('[%s] %s', [DateTimeToStr(Now()), text]);
169
 
170
  try
171
    AssignFile(f, getJournalFileName());
172
    try
173
      if FileExists(getJournalFileName()) then
174
        Append(f)
175
      else
176
        ReWrite(f);
177
      WriteLn(f, l);
178
    finally
179
      CloseFile(f);
180
    end;
181
  except
182
    ShowMessage(lng_journal_error);
183
  end;
184
 
185
  // Andere Forms benachrichtigen
186
 
187
  for i := Screen.FormCount - 1 downto 0 do
188
  begin
189
    if Screen.Forms[i] is TMDIJournalForm then
190
    begin
191
      TMDIJournalForm(Screen.Forms[i]).DoRefresh;
192
      break;
193
    end
194
  end;
195
end;
196
 
197
function RemoveForbiddenChars(fn: string; dir: boolean): string;
198
begin
199
  result := fn;
200
  fn := StringReplace(fn, '<', '_', [rfReplaceAll]);
201
  fn := StringReplace(fn, '>', '_', [rfReplaceAll]);
202
  fn := StringReplace(fn, '|', '_', [rfReplaceAll]);
203
  fn := StringReplace(fn, '"', '_', [rfReplaceAll]);
204
  fn := StringReplace(fn, '?', '_', [rfReplaceAll]);
205
  fn := StringReplace(fn, ':', '_', [rfReplaceAll]);
206
  fn := StringReplace(fn, '/', '_', [rfReplaceAll]);
207
  if not dir then fn := StringReplace(fn, '\', '_', [rfReplaceAll]);
208
  fn := StringReplace(fn, '*', '_', [rfReplaceAll]);
209
end;
210
 
211
procedure JournalDeleteEntry(fn: string);
212
var
213
  dump: TStringList;
214
  i: integer;
215
begin
216
  if not fileexists(fn) then exit;
217
 
218
  AddToJournal(Format(lng_jnl_delete, [GetUserFriendlyElementName(fn)]));
219
 
220
  dump := TStringList.Create;
221
  try
222
    dump.LoadFromFile(fn);
223
 
224
    if dump.Count > 0 then
225
    begin
226
      AddToJournal(lng_content_was);
227
      for i := 0 to dump.Count - 1 do
228
      begin
229
        AddToJournal('- ' + dump.Strings[i]);
230
      end;
231
    end
232
    else
233
    begin
234
      AddToJournal(lng_no_content);
235
    end;
236
  finally
237
    dump.Free;
238
  end;
239
end;
240
 
241
function commonDelete(fn: string): boolean;
242
var
243
  userResponse: integer;
244
begin
245
  result := false;
246
 
247
  userResponse := MessageDlg(Format(lng_deletethis, [GetRelativeFileName(fn)]),
248
    mtConfirmation, mbYesNoCancel, 0);
249
 
250
  if userResponse = idYes then
251
  begin
252
    JournalDeleteEntry(fn);
253
 
254
    if fileexists(fn) then
255
    begin
256
      DeleteFile(PChar(fn));
257
    end
258
    else if directoryexists(fn) then
259
    begin
260
      DelTree(fn);
261
    end;
262
 
263
    if FileExists(fn) or DirectoryExists(fn) then
264
    begin
265
      ShowMessage(lng_notdeleted);
266
      Exit;
267
    end;
268
 
269
    result := true;
270
  end;
271
end;
272
 
273
function GetUserFriendlyElementName(fn: string): string;
274
begin
275
  result := GetRelativeFileName(fn); // TODO: Benutzer soll was anderes sehen als die Dateinamenserweiterungen
276
end;
277
 
278
procedure commonExternalOpen(fn: string);
279
begin
280
  AddToJournal(Format(lng_jnl_open_external, [GetUserFriendlyElementName(fn)]));
281
 
282
  if FileExists(fn) then
283
  begin
284
    ShellExecute(Application.Handle, 'open', PChar(fn), '',
285
      PChar(Quote(fn)), SW_NORMAL);
286
  end
287
  else if DirectoryExists(fn) then
288
  begin
289
    ShellExecute(Application.Handle, 'open', FOLDER_VIEWER,
290
      PChar(Quote(fn)), '', SW_NORMAL);
291
  end
292
  else
293
  begin
294
    ShowMessage(lng_filenotfound);
295
  end;
296
end;
297
 
298
procedure openCategoriesWindow();
299
var
300
  i: integer;
301
  somethingfound: boolean;
302
begin
303
  somethingfound := false;
304
 
305
  for i := Screen.FormCount - 1 downto 0 do
306
  begin
307
    if Screen.Forms[i] is TMDICategories then
308
    begin
309
      TMDICategories(Screen.Forms[i]).RefreshList;
310
      Screen.Forms[i].BringToFront;
311
      Screen.Forms[i].WindowState := wsNormal;
312
      somethingfound := true;
313
      break;
314
    end
315
  end;
316
 
317
  if not somethingfound then
318
  begin
319
    TMDICategories.Create(Application);
320
  end;
321
end;
322
 
323
procedure newDialog(folder: string);
324
var
325
  f: TextFile;
326
  realfolder, new_folder, new_cat: string;
327
  i: integer;
328
  new_fn: string;
329
  em: TAMode;
330
  beschreibung: string;
331
begin
332
  NameDlg.Caption := lng_cap_new;
333
  NameDlg.NameEdt.Text := '';
334
  NameDlg.Textmode.Checked := false;
335
  NameDlg.Textmode.Enabled := true;
336
 
337
  if NameDlg.ShowModal = mrOk then
338
  begin
339
    new_cat := ExtractFileName(namedlg.NameEdt.Text);
340
    new_cat := RemoveForbiddenChars(new_cat, false);
341
 
342
    folder := MyAddTrailingPathDelimiter(folder);
343
 
344
    new_folder := ExtractFilePath(namedlg.NameEdt.Text);
345
    new_folder := RemoveForbiddenChars(folder + new_folder, true);
346
 
347
    if NameDlg.Textmode.Checked then
348
    begin
349
      new_fn := getTextFileName(new_folder, new_cat);
350
      em := emText;
351
      beschreibung := lng_text;
352
    end
353
    else
354
    begin
355
      new_fn := getAppenderFileName(new_folder, new_cat);
356
      em := emAppender;
357
      beschreibung := lng_appender;
358
    end;
359
 
360
    new_fn := RemoveForbiddenChars(new_fn, false);
361
 
362
    realfolder := ExtractFilePath(new_fn);
363
    ForceDirectories(realfolder);
364
 
365
    if FileExists(new_fn) then
366
    begin
367
      ShowMessage(lng_alreadyexists_open);
368
      if em = emText then
369
        OpenTextEditor(new_folder, new_cat)
370
      else
371
        OpenAppenderEditor(new_folder, new_cat);
372
      Exit;
373
    end;
374
 
375
    AssignFile(f, new_fn);
376
    ReWrite(f);
377
    CloseFile(f);
378
 
379
    if not FileExists(new_fn) then
380
    begin
381
      ShowMessage(lng_notcreated);
382
      Exit;
383
    end;
384
 
385
    AddToJournal(Format(lng_jnl_created, [GetUserFriendlyElementName(new_fn)]));
386
 
387
    for i := Screen.FormCount - 1 downto 0 do
388
    begin
389
      if Screen.Forms[i] is TMDICategories then
390
      begin
391
        // TMDICategories(Screen.Forms[i]).RefreshList;
392
 
393
        TMDICategories(Screen.Forms[i]).InsertNode(new_folder, new_cat, em);
394
      end
395
    end;
396
 
397
    if em = emText then
398
      OpenTextEditor(new_folder, new_cat)
399
    else
400
      OpenAppenderEditor(new_folder, new_cat);
401
  end;
402
end;
403
 
404
procedure OpenTextEditor(folder, cat: string);
405
var
406
  somethingfound: boolean;
407
  i: integer;
408
begin
409
  somethingfound := false;
410
 
411
  for i := Screen.FormCount - 1 downto 0 do
412
  begin
413
    if Screen.Forms[i] is TMDITextEditor then
414
    begin
415
      if (TMDITextEditor(Screen.Forms[i]).cat = cat) and
416
         (TMDITextEditor(Screen.Forms[i]).folder = folder) then
417
      begin
418
        Screen.Forms[i].BringToFront;
419
        Screen.Forms[i].WindowState := wsNormal;
420
        somethingfound := true;
421
        break;
422
      end;
423
    end
424
  end;
425
 
426
  if not somethingfound then
427
  begin
428
    TMDITextEditor.Create(Application, folder, cat);
429
  end;
430
end;
431
 
432
procedure OpenAppenderEditor(folder, cat: string);
433
var
434
  somethingfound: boolean;
435
  i: integer;
436
begin
437
  somethingfound := false;
438
 
439
  for i := Screen.FormCount - 1 downto 0 do
440
  begin
441
    if Screen.Forms[i] is TMDIAppender then
442
    begin
443
      if (TMDIAppender(Screen.Forms[i]).cat = cat) and
444
         (TMDIAppender(Screen.Forms[i]).folder = folder) then
445
      begin
446
        Screen.Forms[i].BringToFront;
447
        Screen.Forms[i].WindowState := wsNormal;
448
        somethingfound := true;
449
        break;
450
      end;
451
    end
452
  end;
453
 
454
  if not somethingfound then
455
  begin
456
    TMDIAppender.Create(Application, folder, cat);
457
  end;
458
end;
459
 
460
function GetModeFromNode(ANode: TTreeNode): TAMode;
461
begin
462
  result := emUnknown;
463
 
464
  if IsAppenderNode(ANode) then
465
  begin
466
    result := emAppender;
467
  end
468
  else if IsTextNode(ANode) then
469
  begin
470
    result := emText;
471
  end
472
  else if IsFolderNode(ANode) then
473
  begin
474
    result := emFolder;
475
  end else if IsForeignNode(ANode) then
476
  begin
477
    result := emForeign;
478
  end;
479
 
480
  if result = emUnknown then
481
  begin
482
    raise ENodeError.Create(lng_internal_unknown_node_type_error);
483
  end;
484
end;
485
 
486
function getFileName(mode: TAMode; folder, name: string): string;
487
begin
488
  if (mode = emFolder) or (mode = emForeign) then
489
  begin
490
    result := getFolderName(folder, name);
491
    result := RemoveForbiddenChars(result, true);
492
  end
493
  else if mode = emText then
494
  begin
495
    result := getTextFileName(folder, name);
496
    result := RemoveForbiddenChars(result, false);
497
  end
498
  else if mode = emAppender then
499
  begin
500
    result := getAppenderFileName(folder, name);
501
    result := RemoveForbiddenChars(result, false);
502
  end
503
  else
504
  begin
505
    raise ENodeError.Create(lng_internal_unknown_node_type_error);
506
  end;
507
end;
508
 
509
procedure renameDialog(Node: TTreeNode);
510
var
511
  realfolder, new_cat, new_folder: string;
512
  i: integer;
513
  tofile, fromfile: string;
514
  old_folder, old_cat: string;
515
  old_em, new_em: TAMode;
516
const
517
  folder = ''; // Wir gehen beim Umbenennen von der Wurzel aus
518
begin
519
  old_em := GetModeFromNode(Node);
520
  old_folder := GetFolderFromNode(Node);
521
  old_cat := GetCatFromNode(Node);
522
 
523
  NameDlg.Caption := lng_cap_rename;
524
  NameDlg.NameEdt.Text := old_folder + old_cat;
525
  NameDlg.Textmode.Checked := IsTextNode(Node);
526
  NameDlg.Textmode.Enabled := not IsFolderNode(Node) and not IsForeignNode(Node);
527
 
528
  if NameDlg.ShowModal = mrOk then
529
  begin
530
    if IsFolderNode(Node) or IsForeignNode(Node) then
531
    begin
532
      new_em := old_em;
533
    end
534
    else
535
    begin
536
      if NameDlg.Textmode.Checked then
537
        new_em := emText
538
      else
539
        new_em := emAppender;
540
    end;
541
 
542
    new_cat := ExtractFileName(namedlg.NameEdt.Text);
543
    new_cat := RemoveForbiddenChars(new_cat, false);
544
 
545
    // folder := MyAddTrailingPathDelimiter(folder);
546
 
547
    new_folder := ExtractFilePath(namedlg.NameEdt.Text);
548
    new_folder := RemoveForbiddenChars(folder + new_folder, true);
549
 
550
    realfolder := ExtractFilePath(getFileName(old_em, new_folder, new_cat));
551
    if not IsFolderNode(Node) then ForceDirectories(realfolder);
552
 
553
    // Enthält RemoveForbiddenChars()
554
    fromfile := getFileName(old_em, old_folder, old_cat);
555
    tofile := getFileName(new_em, new_folder, new_cat);
556
 
557
    if fromfile = tofile then exit;
558
 
559
    if fileExists(tofile) then
560
    begin
561
      ShowMessageFmt(lng_already_exists, [GetUserFriendlyElementName(tofile)]);
562
      Exit;
563
    end;
564
 
565
    if not moveFile(pchar(fromfile), pchar(tofile)) then
566
    begin
567
      ShowMessageFmt(lng_move_error, [GetUserFriendlyElementName(fromfile), GetUserFriendlyElementName(tofile)]);
568
      Exit;
569
    end;
570
 
571
    AddToJournal(Format(lng_jnl_renamed, [GetUserFriendlyElementName(fromfile), GetUserFriendlyElementName(tofile)]));
572
 
573
    for i := Screen.FormCount - 1 downto 0 do
574
    begin
575
      if Screen.Forms[i] is TMDICategories then
576
      begin
577
        // TMDICategories(Screen.Forms[i]).RefreshList;
578
 
579
        TMDICategories(Screen.Forms[i]).DeleteNode(old_folder, old_cat);
580
        TMDICategories(Screen.Forms[i]).InsertNode(new_folder, new_cat, new_em);
581
      end
582
    end;
583
 
584
    Node.Selected := true;
585
  end;
586
end;
587
 
588
// http://delphi.about.com/cs/adptips1999/a/bltip1199_2.htm
589
// Modifiziert
590
Function DelTree(DirName : string): Boolean;
591
var
592
  SHFileOpStruct : TSHFileOpStruct;
593
  DirBuf : array [0..MAX_PATH] of char;
594
begin
595
  // Backslash am Ende entfernen
596
  if Copy(DirName, length(DirName), 1) = PathDelim then
597
    DirName := Copy(DirName, 1, Length(DirName)-1);
598
 
599
  try
600
    Fillchar(SHFileOpStruct, SizeOf(SHFileOpStruct), 0);
601
    FillChar(DirBuf, SizeOf(DirBuf), 0);
602
    StrPCopy(DirBuf, DirName);
603
    with SHFileOpStruct do
604
    begin
605
      Wnd := 0;
606
      pFrom := @DirBuf;
607
      wFunc := FO_DELETE;
608
      fFlags := FOF_ALLOWUNDO;
609
      fFlags := fFlags or FOF_NOCONFIRMATION;
610
      fFlags := fFlags or FOF_SILENT;
611
    end;
612
    Result := (SHFileOperation(SHFileOpStruct) = 0);
613
  except
614
    Result := False;
615
  end;
616
end;
617
 
618
function MyAddTrailingPathDelimiter(folder: string): string;
619
begin
620
  result := folder;
621
 
622
  if folder = '' then exit;
623
 
624
  result := IncludeTrailingPathDelimiter(folder);
625
 
626
  //if Copy(folder, length(folder), 1) <> PathDelim then
627
  //  result := result + PathDelim;
628
end;
629
 
630
function getDataPath(): string;
631
const
632
  DataDirName = 'StackMan-Data';
633
begin
634
  if directoryExists(DataDirName) then
635
    result := DataDirName + PathDelim
636
  else
637
    result := GetPersonalFolder() + DataDirName + PathDelim;
638
end;
639
 
640
function getJournalFileName(): string;
641
const
642
  JournalFile = 'Journal.txt';
643
begin
644
  result := getDataPath() + JournalFile;
645
end;
646
 
647
function getRawFileName(folder, name: string): string;
648
begin
649
  Folder := MyAddTrailingPathDelimiter(folder);
650
  result := getDataPath() + Folder + name;
651
end;
652
 
653
function getAppenderFileName(Folder, Name: string): string;
654
begin
655
  result := getRawFileName(folder, app_pfx + Name + '.txt');
656
end;
657
 
658
function getTextFileName(Folder, Name: string): string;
659
begin
660
  result := getRawFileName(folder, txt_pfx + Name + '.txt');
661
end;
662
 
663
function getFolderName(Folder, Name: string): string;
664
begin
665
  result := getRawFileName(folder, Name);
666
end;
667
 
668
function GetRelativeFileName(Filename: string): string;
669
var
670
  datadir: string;
671
begin
672
  result := filename;
673
  datadir := getDataPath();
674
 
675
  if LowerCase(copy(result, 1, length(datadir))) = LowerCase(datadir) then
676
  begin
677
    result := copy(result, 1+length(datadir), length(result)-length(datadir));
678
  end;
679
end;
680
 
681
function GetRelativeNameFromNode(Node: TTreeNode): string;
682
begin
683
  result := getFilenameFromNode(Node);
684
  result := GetRelativeFileName(result);
685
  // result := FilenameToCatname(result);
686
end;
687
 
688
function IsTextNode(Node: TTreeNode): boolean;
689
begin
690
  result := Node.ImageIndex = II_TEXT;
691
end;
692
 
693
function IsFolderNode(Node: TTreeNode): boolean;
694
begin
695
  result := Node.ImageIndex = II_FOLDER;
696
end;
697
 
698
function IsAppenderNode(Node: TTreeNode): boolean;
699
begin
700
  result := Node.ImageIndex = II_APPENDER;
701
end;
702
 
703
function IsForeignNode(Node: TTreeNode): boolean;
704
begin
705
  result := Node.ImageIndex = II_FOREIGN;
706
end;
707
 
708
function IsRootNode(Node: TTreeNode): boolean;
709
begin
710
  result := Node.ImageIndex = II_ROOT;
711
end;
712
 
713
function GetFileNameFromNode(Node: TTreeNode): string;
714
var
715
  folder: string;
716
begin
717
  folder := GetFolderFromNode(Node);
718
 
719
  if IsTextNode(Node) then
720
  begin
721
    result := GetTextFileName(folder, GetCatFromNode(Node));
722
  end
723
  else if IsAppenderNode(Node) then
724
  begin
725
    result := GetAppenderFileName(folder, GetCatFromNode(Node));
726
  end
727
  else if IsForeignNode(Node) then
728
  begin
729
    result := GetRawFileName(folder, GetCatFromNode(Node));
730
  end
731
  else if isRootNode(Node) then
732
  begin
733
    result := getDataPath();
734
  end
735
  else if IsFolderNode(Node) then
736
  begin
737
    result := GetRawFileName(folder, '');
738
  end
739
  else
740
  begin
741
    raise ENodeError.Create(lng_internal_unknown_node_type_error);
742
  end;
743
end;
744
 
745
function GetFolderFromNode(Node: TTreeNode): string;
746
var
747
  par: TTreeNode;
748
begin
749
  if isRootNode(node) then exit;
750
  if isFolderNode(node) then
751
    par := node
752
  else
753
    par := node.Parent;
754
  while not isRootNode(par) do
755
  begin
756
    result := par.Text + PathDelim + result;
757
    par := par.Parent;
758
  end;
759
end;
760
 
761
function Quote(arg: string): string;
762
begin
763
  result := '"' + arg + '"';
764
end;
765
 
766
(* function GetPersonalFolder: string;
767
var
768
  path : array [0..MAX_PATH] of char;
769
begin
770
  SHGetSpecialFolderPath(0, @path, CSIDL_PERSONAL, false);
771
  if path = '' then
772
    result := ExtractFilePath(Application.ExeName)
773
  else
774
    result := IncludeTrailingPathDelimiter(path);
775
end; *)
776
 
777
function GetPersonalFolder(DefaultPath: string): string; overload;
778
// This function replaces SHGetSpecialFolderPath from ShlObj.pas .
779
// It dynamically loads the DLL, so that also Windows 95 without
780
// Internet Explorer 4 Extension can work with it.
781
type
782
  TSHGetSpecialFolderPath = function(hwndOwner: HWND; lpszPath: PChar;
783
    nFolder: Integer; fCreate: BOOL): BOOL; stdcall;
784
 
785
  procedure Fail;
786
  begin
787
    if DefaultPath = '' then
788
      result := ExtractFilePath(ParamStr(0))
789
    else
790
      result := IncludeTrailingPathDelimiter(DefaultPath);
791
  end;
792
 
793
const
794
{$IFDEF MSWINDOWS}
795
  shell32 = 'shell32.dll';
796
{$ENDIF}
797
{$IFDEF LINUX}
798
  shell32 = 'libshell32.borland.so';
799
{$ENDIF}
800
CSIDL_PERSONAL = $0005;
801
var
802
  SpecialFolder: TSHGetSpecialFolderPath;
803
  Handle: THandle;
804
  path: array [0..MAX_PATH] of char;
805
begin
806
  result := '';
807
  Handle := LoadLibrary(shell32);
808
  if Handle <> 0 then
809
  begin
810
    {$IFDEF UNICODE}
811
    @SpecialFolder := GetProcAddress(Handle, 'SHGetSpecialFolderPathW');
812
    {$ELSE}
813
    @SpecialFolder := GetProcAddress(Handle, 'SHGetSpecialFolderPathA');
814
    {$ENDIF}
815
    if @SpecialFolder <> nil then
816
    begin
817
      FillChar(path, sizeof(path), 0);
818
      if SpecialFolder(0, @path, CSIDL_PERSONAL, false) and (path <> '') then
819
      begin
820
        result := IncludeTrailingPathDelimiter(path)
821
      end
822
      else
823
      begin
824
        Fail;
825
      end;
826
    end
827
    else
828
    begin
829
      Fail;
830
    end;
831
    FreeLibrary(Handle);
832
  end
833
  else
834
  begin
835
    Fail;
836
  end;
837
end;
838
 
839
function GetPersonalFolder(): string;
840
begin
841
  result := GetPersonalFolder('C:\');
842
end;
843
 
844
function GetCatFromNode(Node: TTreeNode): string;
845
begin
846
  if IsFolderNode(Node) then
847
    result := ''
848
  else
849
    result := Node.Text;
850
end;
851
 
852
// http://www.delphipraxis.net/post43515.html
853
Function GetHTML(AUrl: string): string;
854
var
855
  databuffer : array[0..4095] of char;
856
  ResStr : string;
857
  hSession, hfile: hInternet;
858
  dwindex,dwcodelen,dwread,dwNumber: cardinal;
859
  dwcode : array[1..20] of char;
860
  res    : pchar;
861
  Str    : pchar;
862
begin
863
  ResStr:='';
864
  if system.pos('http://',lowercase(AUrl))=0 then
865
     AUrl:='http://'+AUrl;
866
 
867
  // Hinzugefügt
868
  application.ProcessMessages;
869
 
870
  hSession:=InternetOpen('InetURL:/1.0',
871
                         INTERNET_OPEN_TYPE_PRECONFIG,
872
                         nil,
873
                         nil,
874
                         0);
875
  if assigned(hsession) then
876
  begin
877
    // Hinzugefügt
878
    application.ProcessMessages;
879
 
880
    hfile:=InternetOpenUrl(
881
           hsession,
882
           pchar(AUrl),
883
           nil,
884
           0,
885
           INTERNET_FLAG_RELOAD,
886
           0);
887
    dwIndex  := 0;
888
    dwCodeLen := 10;
889
 
890
    // Hinzugefügt
891
    application.ProcessMessages;
892
 
893
    HttpQueryInfo(hfile,
894
                  HTTP_QUERY_STATUS_CODE,
895
                  @dwcode,
896
                  dwcodeLen,
897
                  dwIndex);
898
    res := pchar(@dwcode);
899
    dwNumber := sizeof(databuffer)-1;
900
    if (res ='200') or (res ='302') then
901
    begin
902
      while (InternetReadfile(hfile,
903
                              @databuffer,
904
                              dwNumber,
905
                              DwRead)) do
906
      begin
907
 
908
        // Hinzugefügt
909
        application.ProcessMessages;
910
 
911
        if dwRead =0 then
912
          break;
913
        databuffer[dwread]:=#0;
914
        Str := pchar(@databuffer);
915
        resStr := resStr + Str;
916
      end;
917
    end
918
    else
919
      ResStr := 'Status:'+res;
920
    if assigned(hfile) then
921
      InternetCloseHandle(hfile);
922
  end;
923
 
924
  // Hinzugefügt
925
  application.ProcessMessages;
926
 
927
  InternetCloseHandle(hsession);
928
  Result := resStr;
929
end;
930
 
931
procedure explode(delim: char; s: string; sl: TStringList);
932
var
933
  i: integer;
934
  tmp: string;
935
begin
936
  tmp := '';
937
  for i := 1 to length(s) do
938
  begin
939
    if s[i] = delim then
940
    begin
941
      sl.Add(tmp);
942
      tmp := '';
943
    end
944
    else
945
      tmp := tmp + s[i];
946
  end;
947
  sl.Add(tmp);
948
end;
949
 
950
begin
951
  if Length(app_pfx) <> Length(txt_pfx) then
952
  begin
953
    raise EInternalError.Create(lng_internal_prefix_length_error);
954
    Halt;
955
  end;
956
end.
957
 
958
 
959
 
960