1 {
2 ���������������������������������������������������������������������������Ŀ
3 � �
4 � ��۰ ۰ ۰ ��۰ ��۰ ��۰ ۰ ��۰ ۰ ۰ ۰ ۰ ��۰ ��۰ �
5 � ۰ �۰ ۰ ۰ ۰ ۰ ۰ ۰ ۰ ۰ �۰ ۰ ۰ ۰ �
6 � ۰ ۰۰۰ ۰ �۰ ۰ ۰ �۰ ۰ ۰ ۰۰۰ ۰ ۰ �
7 � ۰ ۰ �۰ ۰ ۰ ۰ ۰ ۰ ۰ ۰ ۰ �۰ ۰ ۰ �
8 � ��۰ ۰ ۰ ��۰ ۰ ��۰ ��۰ ��۰ ���۰ ۰ ۰ ��۰ ۰ �
9 � �
10 � Ver. : 1.00b ...... (c) 1996 by Stephan Zehrer ...... FreeWare �
11 � �
12 ���������������������������������������������������������������������������Ĵ
13 � IniFile Unit dient zur verarbeitung von config Dateien in Textform wie �
14 � INI oder CFG. �
15 � Hier einige Features von IniFile Unit : �
16 � - Einfache Bedinung (4 Routinen fuer Grund Funktionen) �
17 � - Alles in einem Object, daduch mehrer Listen gleichzeitig nutzbar �
18 � - Aufleilung in Untergruppen (Sectionen) �
19 � - Kommentarverwaltung von jede Option (';') �
20 � - kommplette Einlesen der Ini File in eine einfach verkettete Liste �
21 � - schnelle Verarbeitung da keine lese/schreib zugriffe Waeren des �
22 � ein und auslesens. �
23 � - DataBase Funktionen �
24 � ( Aufbau von kleine Datenbanken in Textform wie z.B. PLZ Listen oder �
25 � Listen von Telefon Nummern ) �
26 � �
27 � !!! Achtung Version ohne externe Functionen (siehe Dateiende) !!! �
28 � �
29 ���������������������������������������������������������������������������Ĵ
30 � Diese Version wurde ausgibig von mir getestet. Es kann trotzdem vorkommen �
31 � das sich Fehler einschleichen. �
32 � Bitte schicken Sie einen Bug report an : Stephan Zehrer@2:2487/9001.14 �
33 � �
34 � Der Autor uebernimmt keine Haftung fuer Schaeden, die durch dieses Programm�
35 � entstanden sind. �
36 �����������������������������������������������������������������������������
37
38 changed by Sascha Silbe
39 }
40 {$X+}{$R-}{ $L-}{ $D-}{$Y-}{$X+}{$G+}
41 unit IniFile2;
42
43 interface
44
45 uses DOS;
46
47 type FileStr = {String [12]} String[128]; {Externer Typ}
48 pOptRec = ^tOptRec;
49 tOptRec = record {Record fuer die Optionen}
50 Name : String[20]; {Name, wenn ';' dann nur Kommentarzeile}
51 Value : String; {Wert}
52 Comment : String[100]; {Kommentar}
53 PrevOpt : pOptRec; {Zeiger auf vorherige Option}
54 NextOpt : pOptRec; {Zeiger auf naechste Option}
55 end;
56 pSecRec = ^tSecRec;
57 tSecRec = record {Record fuer die Sectionen}
58 Name : String[20]; {Name der Secion, immer grossbustaben}
59 Options : pOptRec; {Zeiger auf die Optionen}
60 PrevSec : pSecRec; {Zeiger auf vorherige Section}
61 NextSec : pSecRec; {Zeiger auf naechste Section}
62 end;
63
64 type IniObj = object
65 FileName : FileStr;
66 Sep : Char; {default = '='}
67 {Achtung aenderungen werden nicht
68 in der ini Datei gespeichert}
69 CommentPos : byte; {Wenn 0 dann deaktiviert, sonnst
70 position an der die Kommentare
71 ausgerichtet werden, natuerlich nur
72 wenn der normal Eintrag nicht laenger
73 ist. default = 0}
74 NotFound : String[20]; {String der zurueckgegeben wird wenn
75 ein eintrag nicht gefunden wurde
76 default = ''}
77 f : Text;
78 IniTree : pSecRec; {Zeiger auf die 1. Section}
79 AktSec : pSecRec; {nur intern benutzt}
80 AktOpt : pOptRec; {nur intern benutzt}
81 constructor Init (AFileName : FileStr);
82 { Initalisiert die Ini Datei }
83 destructor Done;
84 { Schreibt die Eintraege und loeschen den Verkettung }
85 procedure SetSeperator (ASep : Char);
86 { Aendert den Seperator, default (=) }
87 procedure SetNotFound (ANotFound : String);
88 { Aendert den NoFound String, default () }
89 procedure SetCommentPos (ACommentPos : byte);
90 { Aendert die CommentPos, default (0) }
ReadEntrynull91 function ReadEntry ( Section : String;
92 Option : String ) : String;
93 { Liefert den Wert des Eintrags }
94 procedure WriteEntry ( Section : String;
95 Option : String;
96 Value : String;
97 Comment : String);
98 { Aendert/ Definiert eine Eintrag }
99 procedure AddEntry ( Section : String;
100 Option : String;
101 Value : String;
102 Comment : String);
103 { Fuegt einen Eintrag ans Ende der Section an }
104 procedure InsertEntry ( Section : String;
105 Option : String;
106 Value : String;
107 Comment : String);
108 { Fuegt einen Eintrag an der aktuellen Position ein }
109 procedure DelEntry ( Section : String;
110 Option : String;
111 DelSec : Boolean );
112 { Loescht eine Eintrag }
113 { --------- Datenbank Routinen -------- }
114 { Mit den Datenbank Functionen ist es moeglich
115 auch Eintraege zu Lesen deren Options Name
116 man nicht kennt. Wie kleine Datenbanken, wie
117 z.B. eine kleine Liste von PLZ und ihren Ortnamen
118 oder Telefonnummern ...
119 Die Functionen sind Sections orientiert geschrieben,
120 es ist dadurch moeglich Eine Datenbank und Programm
121 Einstellungen zu kombinieren.
122 Die Daten werden nicht Sortiert, neue Eintraege werden
123 einfach hinten angehaengt.}
124 procedure SetSection (Section : String);
125 { Setzt die Interen Variabel AktSec, existierd die Section
126 nicht wird eine neu Section erstellet.
127 Setzt AktOpt auf den ersten gueltigen Eintrag
128 ( wenn es einen gibt !!) }
129 { DIESE PROCEDURE SOLLT ALS ERSTES AUFGREUFEN WERDEN}
130 procedure ReSetSec;
131 { Setzt AktOpt wirde auf den 1 Wert. }
GetSecNumnull132 function GetSecNum (Section : String ) : integer;
133 { gibt die Anzahl der Eintraegein einer Section }
134 { dabei werden Kommentarzeilen ingnoriert. }
135 { zurueck. Wenn Rueckgabewert 0 ist dann ist entweder kein }
136 { Eintrag vorhanden oder die Section existiert nicht.}
SetNextOptnull137 function SetNextOpt : boolean;
138 { Setzt AktSec auf die naechste Option und gibt false
139 zurueck falls wenn das ende Erreicht ist.
140 Kommentarzeilen werden uebergangen}
SetPrevOptnull141 function SetPrevOpt : boolean;
142 { Setzt AktSec auf die vorherige Option und gibt false
143 zurueck falls wenn der Anfang Erreicht ist.
144 Kommentarzeilen werden uebergangen}
ReSecEnNamenull145 function ReSecEnName : String;
146 { Was so viel heisst wie ReadSectionEntryName }
147 { gibt den Namen der Aktuellen Option zurueck }
148 { Ist AktOpt = NIL wird der NotFound String zurueck gegeben }
ReSecEnValuenull149 function ReSecEnValue : String;
150 { gibt den Wert der Aktuellen Option zurueck }
151 { Ist AktOpt = NIL wird der NotFound String zurueck gegeben }
SearchSecEntrynull152 function SearchSecEntry (Name : String ) : String;
153 { Sucht nach einen Eintrag und gibt seine Wert zurueck. }
154 { AktOpt wird nicht geaendert !! }
155 procedure WriteSecEntry (Name : String;
156 Value : String;
157 Comment : String);
158 { Schreibz den Eintrag neu oder aendert den Wert, der
159 Aktuellen Section
160 AktOpt wird nicht geaendert !!
161 Achtung !! wurde keine Section gesetzt wird der Eintrag
162 in eine falsche oder in keine Section geschrieben !!}
163 procedure AddSecEntry (Name : String;
164 Value : String;
165 Comment : String);
166 { Haengt einen neuen Eintrag hinten an, der Aktuellen Section
167 AktOpt wird nicht geaendert !!
168 Achtung !! wurde keine Section gesetzt wird der Eintrag
169 in eine falsche oder in keine Section geschrieben !!}
170 procedure InsertSecEntry (Name : String;
171 Value : String;
172 Comment : String);
173 { Fuegt einen neuen Eintrag ein, der Aktuellen Section
174 AktOpt wird nicht geaendert !!
175 Achtung !! wurde keine Section gesetzt wird der Eintrag
176 in eine falsche oder in keine Section geschrieben !!}
177 procedure DelSecEntry (Name : String);
178 { Loescht eine Eintrag in der Aktuellen Section
179 AktOpt wird nicht geaendert !!
180 Achtung !! wurde keine Section gesetzt wird kein oder
181 ein falscher Eintrag geloescht }
182 procedure DelCurEntry (DelSec : Boolean);
183 { Loescht eine Eintrag in der Aktuellen Section
184 AktOpt wird nicht geaendert !!
185 Achtung !! wurde keine Section gesetzt wird kein oder
186 ein falscher Eintrag geloescht }
187 { ---------- interen Routinen --------- }
SearchSectionnull188 function SearchSection (ASection : String;
189 Last : Boolean ) : boolean;
SearchOptionnull190 function SearchOption (AOption : String;
191 Last : Boolean ) : boolean;
192 procedure ReadIni;
193 procedure WriteIni;
194 procedure DelIni;
195 procedure ShowTree;
196 end;
197
198 implementation
199 {****************************** externe Routinen ****************************}
200 { Die hier externen Routinen stammen aus meiner Toolbox welche ich aus alle
201 moeglichen Quellen zusammen gestellt habe. Hier die Routinen die fuer
202 IniFile Unit noetig sind. Quellen : PRUSSG,SWAG,TOOLBOX,DOS,FIDO... }
203
204 {Function FileExists(FileName: string; attr : Word) : Boolean;
205 var f: SearchRec;
206 begin
207 findfirst(Filename, attr, f);
208 if doserror = 0 then Fileexists := true else Fileexists := false;
209 end;}
210
FillStrnull211 Function FillStr (AStr : String; Len : byte; Ch : Char) : String;
212 begin
213 if Length (AStr) > Len then Exit;
214 while Length (AStr) < Len do AStr := AStr + Ch;
215 FillStr := AStr;
216 end;
StrCutnull217 Function StrCut (AStr : String) : String;
218 begin
219 while (Length(AStr) - 1 >= 0) AND
220 (AStr [Length(AStr)] in [#32,#9]) DO
221 AStr[0] := chr(Length(AStr) - 1);
222 StrCut := AStr;
223 end;
CutStrnull224 Function CutStr (AStr : String) : String;
225 begin
226 while (Length(AStr) - 1 >= 0) AND
227 (AStr [1] in [#32,#9]) DO
228 AStr := Copy (AStr,2,Length(AStr) - 1);
229 CutStr := AStr;
230 end;
231
UpStrnull232 Function UpStr(S1:String) : String;
233 {Asm Code replaced by Sascha Silbe}
234 Var
235 s:String;
236 i:Byte;
237
238 Begin
239 s[0]:= S1[0];
240 For i:= 1 to Byte(s1[0]) do s[i]:= UpCase(s1[i]);
241 UpStr:= s;
242 End;
243
244
245 {****************************** externe Routinen ****************************}
NewSecnull246 function NewSec : pSecRec;
247 var ASec : pSecRec;
248 begin
249 New (ASec);
250 ASec^.Name := '';
251 ASec^.Options := NIL;
252 ASec^.PrevSec := NIL;
253 ASec^.NextSec := NIL;
254 NewSec := ASec;
255 end;
NewOptnull256 function NewOpt : pOptRec;
257 var AOpt : pOptRec;
258 begin
259 New (AOpt);
260 AOpt^.Name := '';
261 AOpt^.Value := '';
262 AOpt^.Comment := '';
263 AOpt^.PrevOpt := NIL;
264 AOpt^.NextOpt := NIL;
265 NewOpt := AOpt;
266 end;
267 {****************************************************************************}
268 constructor IniObj.Init(AFileName: FileStr);
269 begin
270 FileName := AFileName;
271 Assign (f,FileName);
272 Sep := '=';
273 NotFound := '';
274 CommentPos := 0;
275 IniTree := NIL;
276 AktSec := NIL;
277 AktOpt := NIL;
278 ReadIni;
279 end;
280 destructor IniObj.Done;
281 begin
282 WriteIni;
283 DelIni;
284 end;
285 {****************************************************************************}
286
287 procedure IniObj.SetSeperator(ASep : Char);
288 begin
289 Sep := ASep;
290 end;
291 procedure IniObj.SetNotFound(ANotFound: String);
292 begin
293 NotFound := ANotFound;
294 end;
295 procedure IniObj.SetCommentPos(ACommentPos: Byte);
296 begin
297 CommentPos := ACommentPos;
298 end;
299 {****************************************************************************}
300
301 procedure IniObj.ReadIni;
302 var ASec : pSecRec;
303 AOpt : pOptRec;
304 X,Y : byte;
305 Str : String;
306 begin
307 {$I-} Reset (F); {$I+}
308 If IOResult <> 0 then
309 Begin
310 { WriteLn('ReadIni: Couldn''t open file!');}
311 Exit;
312 end;
313 while not Eof(F) do
314 begin
315 ReadLn (f,Str);
316 if Length (Str) > 0 then begin
317 if Str[1] = '[' then begin
318 ASec := NewSec;
319 X := Pos (']',Str);
320 if X > 1 then Dec (X,2) else Dec(x, 1);
321 ASec^.Name := UpStr(Copy (Str,2,X));
322 if IniTree = NIL then IniTree := ASec;
323 if AktSec <> NIL then
324 Begin
325 AktSec^.NextSec := ASec;
326 ASec^.PrevSec := AktSec;
327 End;
328 AktSec := ASec;
329 end else begin
330 X := Pos (Sep,Str); Y := Pos (';',Str);
331 if (Y > 0) or (X > 0) then begin
332 AOpt := NewOpt;
333 if Str[1] = ';' then begin
334 AOpt^.Name := ';'; {Kommentarzeile}
335 AOpt^.Comment := Copy (Str,2,Length(Str)-1);
336 end else
337 begin
338 AOpt^.Name := StrCut(Copy (Str,1,X-1));
339 if Y <> 0 then begin
340 AOpt^.Value := StrCut(CutStr(Copy (Str,X+1,Y-X-1)));
341 AOpt^.Comment := StrCut(CutStr(Copy (Str,Y+1,Length(Str)-Y)));
342 end else
343 AOpt^.Value := CutStr(Copy (Str,X+1,Length(Str)-X));
344 end;
345 if IniTree = NIL then begin
346 IniTree := NewSec;
347 AktSec := IniTree;
348 end;
349 if AktSec^.Options = NIL then AktSec^.Options := AOpt
350 else AktOpt^.NextOpt := AOpt;
351 AOpt^.PrevOpt := AktOpt;
352 AktOpt := AOpt;
353 end;
354 end;
355 end;
356 end;
357 Close (f);
358 end;
359 procedure IniObj.WriteIni;
360 const Comment : String = '';
361 OptVal : String = '';
362 begin
363 if IniTree = Nil then Exit;
364 { FileMode := 2;}
365 {$I-} Rewrite (f); {$I+}
366 If IOResult <> 0 then
367 Begin
368 { WriteLn('WriteIni: Couldn''t open file!');}
369 Exit;
370 End;
371 AktSec := IniTree;
372 AktOpt := AktSec^.Options;
373 {$I-}
374 while AktSec <> NIL do begin
375 if AktSec^.Name <> '' then WriteLn (f,'['+UpStr(AktSec^.Name)+']');
376 while AktOpt <> NIL do begin
377 if AktOpt^.Name = ';' then WriteLn (f,AktOpt^.Name+AktOpt^.Comment)
378 else begin
379 OptVal := AktOpt^.Name+'='+ AktOpt^.Value;
380 if AktOpt^.Comment <> '' then begin
381 if CommentPos <> 0 then OptVal := FillStr (OptVal,CommentPos,' ');
382 Comment := ' ;'+AktOpt^.Comment
383 end;
384 WriteLn (f, OptVal + Comment);
385 Comment := ''; OptVal := '';
386 end;
387 AktOpt := AktOpt^.NextOpt;
388 end;
389 AktSec := AktSec^.NextSec;
390 If AktSec <> Nil then AktOpt := AktSec^.Options;
391 end;
392 If IOResult <> 0 then
393 Begin
394 { WriteLn('WriteIni: Couldn''t write file!');}
395 End;
396
397 Close (f); {$I-}
398 If IOResult <> 0 then
399 Begin
400 { WriteLn('WriteIni: Couldn''t close file!');}
401 End;
402 end;
403 procedure IniObj.DelIni;
404 var ASec : pSecRec;
405 AOpt : pOptRec;
406 X : byte;
407 Str : String;
408 begin
409 if IniTree = Nil then Exit;
410 AktSec := IniTree;
411 AktOpt := AktSec^.Options;
412 while AktSec <> NIL do begin
413 ASec := AktSec^.NextSec;
414 if AktSec <> NIl then Dispose (AktSec);
415 while AktOpt <> NIL do begin
416 AOpt := AktOpt^.NextOpt;
417 if AktOpt <> NIL then Dispose (AktOpt);
418 AktOpt := AOpt;
419 end;
420 AktSec := ASec;
421 If AktSec <> Nil then AktOpt := AktSec^.Options;
422 end;
423 end;
424 {****************************************************************************}
IniObj.SearchSectionnull425 function IniObj.SearchSection (ASection : String;
426 Last : boolean ) : boolean;
427 { Suchen nach der Section. Ist Last auf true wird AktSec auf die Section
428 vor der gesuchten gesetzt, ist Last auf false wird AktSec auf die
429 gesuchte Section gesetzt, oder bei nicht finden auf die letzte der
430 Verkettung. Wird eine Section gefunde ist der Rueckgabewert der Function
431 true, ansonsten false.
432 Zur beschleunigung der Suche : ist AktSec schon das gesuchte wird nicht
433 gesucht, wie z.B. durch WriteSecEntry }
434 var Found : boolean;
435 ASec : pSecRec;
436 begin
437 if IniTree = Nil then begin
438 SearchSection := false;
439 Exit;
440 end;
441 found := false;
442 ASection := UpStr (ASection);
443 ASec := NIL;
444 If AktSec = NIL then AktSec := IniTree
445 Else
446 if (AktSec^.Name = ASection) and (not Last) then Found := true
447 else AktSec := IniTree;
448 while (AktSec <> NIL) and (not Found) do begin
449 if ASection = AktSec^.Name then Found := true
450 Else
451 begin
452 ASec := AktSec;
453 AktSec := AktSec^.NextSec;
454 end;
455 end;
456 if Last or (AktSec = NIL) then AktSec := ASec;
457 SearchSection := found;
458 end;
IniObj.SearchOptionnull459 function IniObj.SearchOption (AOption : String;
460 Last : boolean) : boolean;
461 { Suchen nach der Option. Ist Last auf true wird AktOpt auf die Option
462 vor der gesuchten gesetzt, ist Last auf false wird AktOpt auf die
463 gesuchte Option gesetzt, oder bei nicht finden auf die letzte der
464 Verkettung, Nur wenn gar keine Verkettung unter dieser Section
465 existiert wird AktOpt auf NIL gesetzt. Aber dann ist auch der
466 rueckgabewert der Function false
467 Zur beschleunigung der Suche : ist AktOpt schon das gesuchte wird nicht
468 gesucht}
469
470 var Found : boolean;
471 AOpt : pOptRec;
472 begin
473 if IniTree = Nil then begin
474 SearchOption := false;
475 Exit;
476 end;
477 found := false;
478 AOpt := NIL;
479 if (UpStr(AktOpt^.Name) = UpStr(AOption)) and (not Last) then Found := true
480 else AktOpt := AktSec^.Options;
481 while (AktOpt <> NIL) and (not Found) do begin
482 if UpStr(AOption) = UpStr(AktOpt^.Name) then Found := true;
483 if not Found then begin
484 AOpt := AktOpt;
485 AktOpt := AktOpt^.NextOpt;
486 end;
487 end;
488 If Last or (AktOpt = NIL) then AktOpt := AOpt;
489 SearchOption := found;
490 end;
491 {****************************************************************************}
IniObj.ReadEntrynull492 function IniObj.ReadEntry ( Section : String; Option : String ) : String;
493 Var Value : String;
494 begin
495 if SearchSection (Section,false) then
496 if SearchOption (Option,false) then
497 Value := AktOpt^.Value
498 else Value := NotFound;
499 ReadEntry := Value;
500 end;
501 procedure IniObj.WriteEntry(Section, Option, Value, Comment: String);
502 begin
503 if SearchSection (Section,false) then
504 if SearchOption (Option,false) then
505 begin
506 AktOpt^.Value := Value;
507 if Comment <> '' then AktOpt^.Comment := Comment;
508 end else
509 begin
510 AktOpt^.NextOpt := NewOpt;
511 AktOpt := AktOpt^.NextOpt;
512 AktOpt^.Name := Option;
513 AktOpt^.Value := Value;
514 AktOpt^.Comment := Comment;
515 end
516 else begin
517 if IniTree = NIL then begin
518 IniTree := NewSec;
519 AktSec := IniTree;
520 end else begin
521 AktSec^.NextSec := NewSec;
522 AktSec := AktSec^.NextSec;
523 end;
524 AktSec^.Name := UpStr(Section);
525 AktSec^.Options := NewOpt;
526 AktOpt := AktSec^.Options;
527 AktOpt^.Name := Option;
528 AktOpt^.Value := Value;
529 AktOpt^.Comment := Comment;
530 end;
531 end;
532 procedure IniObj.AddEntry(Section, Option, Value, Comment: String);
533 Var
534 AOpt : pOptRec;
535 begin
536 if SearchSection (Section,false) then
537 begin
538 AOpt := AktOpt;
539 While (AOpt^.NextOpt <> Nil) do AOpt := AOpt^.NextOpt;
540 AOpt^.NextOpt := NewOpt;
541 AOpt^.PrevOpt := AktOpt;
542 AOpt := AOpt^.NextOpt;
543 AOpt^.Name := Option;
544 AOpt^.Value := Value;
545 AOpt^.Comment := Comment;
546 end
547 else begin
548 if IniTree = NIL then begin
549 IniTree := NewSec;
550 AktSec := IniTree;
551 end else begin
552 AktSec^.NextSec := NewSec;
553 AktSec^.NextSec^.PrevSec := AktSec;
554 AktSec := AktSec^.NextSec;
555 end;
556 AktSec^.Name := UpStr(Section);
557 AktSec^.Options := NewOpt;
558 AktOpt := AktSec^.Options;
559 AktOpt^.Name := Option;
560 AktOpt^.Value := Value;
561 AktOpt^.Comment := Comment;
562 end;
563 end;
564 procedure IniObj.InsertEntry(Section, Option, Value, Comment: String);
565 Var
566 AOpt : pOptRec;
567 begin
568 if SearchSection (Section,false) then
569 begin
570 AOpt := AktOpt^.NextOpt;
571 AktOpt^.NextOpt := NewOpt;
572 AktOpt^.NextOpt^.PrevOpt := AktOpt;
573 AktOpt^.NextOpt^.NextOpt := AOpt;
574 AOpt := AktOpt^.NextOpt;
575 AOpt^.Name := Option;
576 AOpt^.Value := Value;
577 AOpt^.Comment := Comment;
578 end
579 else begin
580 if IniTree = NIL then begin
581 IniTree := NewSec;
582 AktSec := IniTree;
583 end else begin
584 AktSec^.NextSec := NewSec;
585 AktSec^.NextSec^.PrevSec := AktSec;
586 AktSec := AktSec^.NextSec;
587 end;
588 AktSec^.Name := UpStr(Section);
589 AktSec^.Options := NewOpt;
590 AktOpt := AktSec^.Options;
591 AktOpt^.Name := Option;
592 AktOpt^.Value := Value;
593 AktOpt^.Comment := Comment;
594 end;
595 end;
596 procedure IniObj.DelEntry ( Section : String;
597 Option : String;
598 DelSec : Boolean );
599 var AOpt : pOptRec;
600 ASec : pSecRec;
601 begin
602 if SearchSection (Section,false) then
603 if SearchOption (Option,false) then begin
604 AOpt := AktOpt;
605 SearchOption (Option,true);
606 if AktOpt <> NIL then
607 Begin
608 AktOpt^.NextOpt := AOpt^.NextOpt;
609 AOpt^.NextOpt^.PrevOpt := AktOpt;
610 End
611 else
612 Begin
613 AktSec^.Options := AOpt^.NextOpt;
614 AOpt^.NextOpt^.PrevOpt := Nil;
615 End;
616 if AOpt <> NIL then Dispose (AOpt);
617 if (AktSec^.Options = NIL) and DelSec then begin
618 ASec := AktSec;
619 SearchSection (Section,true);
620 if AktSec <> NIL then
621 Begin
622 AktSec^.NextSec := ASec^.NextSec;
623 ASec^.NextSec^.PrevSec := AktSec;
624 End
625 else
626 Begin
627 IniTree := ASec^.NextSec;
628 ASec^.NextSec^.PrevSec := Nil;
629 End;
630 if ASec <> NIL then Dispose (ASec);
631 end;
632 end;
633 end;
634 {****************************************************************************}
635 procedure IniObj.ShowTree;
636 const Comment : String = '';
637 OptVal : String = '';
638 begin
639 if IniTree = Nil then Exit;
640 AktSec := IniTree;
641 AktOpt := AktSec^.Options;
642 while AktSec <> NIL do begin
643 if AktSec^.Name <> '' then WriteLn ('['+AktSec^.Name+']');
644 while AktOpt <> NIL do begin
645 if AktOpt^.Name = ';' then WriteLn (AktOpt^.Name+AktOpt^.Comment)
646 else begin
647 OptVal := AktOpt^.Name+'='+ AktOpt^.Value;
648 if AktOpt^.Comment <> '' then begin
649 if CommentPos <> 0 then OptVal := FillStr (OptVal,CommentPos,' ');
650 Comment := ' ;'+AktOpt^.Comment
651 end;
652 WriteLn (OptVal + Comment);
653 Comment := ''; OptVal := '';
654 end;
655 AktOpt := AktOpt^.NextOpt;
656 end;
657 AktSec := AktSec^.NextSec;
658 If (AktSec <> Nil) then AktOpt := AktSec^.Options;
659 end;
660 end;
661
662 {****************************************************************************}
IniObj.SetPrevOptnull663 function IniObj.SetPrevOpt : boolean;
664
665 begin
666 if AktOpt^.PrevOpt <> Nil then begin
667 repeat AktOpt := AktOpt^.PrevOpt
668 until (AktOpt^.Name <> ';') or (AktOpt^.PrevOpt = Nil);
669 if (AktOpt^.PrevOpt = Nil) and ( AktOpt^.Name = ';')
670 then SetPrevOpt := false else SetPrevOpt := true;
671 end else SetPrevOpt := false;
672 end;
IniObj.SetNextOptnull673 function IniObj.SetNextOpt : boolean;
674
675 begin
676 if AktOpt^.NextOpt <> Nil then begin
677 repeat AktOpt := AktOpt^.NextOpt
678 until (AktOpt^.Name <> ';') or (AktOpt^.NextOpt = Nil);
679 if (AktOpt^.NextOpt = Nil) and ( AktOpt^.Name = ';')
680 then SetNextOpt := false else SetNextOpt := true;
681 end else SetNextOpt := false;
682 end;
IniObj.GetSecNumnull683 function IniObj.GetSecNum (Section : String ) : integer;
684 var Num : Integer;
685 AOpt : pOptRec;
686 begin
687 Num := 0;
688 AOpt := AktOpt;
689 if SearchSection (Section,false) then begin
690 AktOpt := AktSec^.Options;
691 while AktOpt <> NIL do begin
692 if AktOpt^.Name[1] <> ';' then Inc (Num);
693 if not SetNextOpt then AktOpt := NIL;
694 end;
695 end;
696 AktOpt := AOpt;
697 GetSecNum := Num;
698 end;
699 procedure IniObj.SetSection (Section : String);
700 begin
701 if not SearchSection (Section,false) then begin
702 WriteEntry (Section,';','','');
703 end;
704 ReSetSec;
705 end;
706 procedure IniObj.ReSetSec;
707 begin
708 AktOpt := AktSec^.Options;
709 if AktOpt^.Name = ';' then SetNextOpt;
710 end;
IniObj.ReSecEnNamenull711 function IniObj.ReSecEnName : String;
712 begin
713 if AktOpt = NIL then begin
714 ReSecEnName := NotFound;
715 Exit;
716 end;
717 ReSecEnName := AktOpt^.Name;
718 end;
719
IniObj.ReSecEnValuenull720 function IniObj.ReSecEnValue : String;
721 begin
722 if AktOpt = NIL then begin
723 ReSecEnValue := NotFound;
724 Exit;
725 end;
726 ReSecEnValue := AktOpt^.Value;
727 end;
IniObj.SearchSecEntrynull728 function IniObj.SearchSecEntry (Name : String ) : String;
729 var AOpt : pOptRec;
730 begin
731 if AktSec = NIL then begin
732 SearchSecEntry := NotFound;
733 Exit;
734 end;
735 AOpt := AktOpt;
736 SearchSecEntry := ReadEntry (AktSec^.Name,Name);
737 AktOpt := AOpt;
738 end;
739 procedure IniObj.WriteSecEntry (Name : String;
740 Value : String;
741 Comment : String);
742 var AOpt : pOptRec;
743 begin
744 if AktSec = NIL then Exit;
745 AOpt := AktOpt;
746 WriteEntry (AktSec^.Name,Name,Value,'');
747 AktOpt := AOpt;
748 end;
749 procedure IniObj.AddSecEntry (Name : String;
750 Value : String;
751 Comment : String);
752 var AOpt : pOptRec;
753 begin
754 if AktSec = NIL then Exit;
755 AOpt := AktOpt;
756 AddEntry (AktSec^.Name,Name,Value,'');
757 AktOpt := AOpt;
758 end;
759 procedure IniObj.InsertSecEntry (Name : String;
760 Value : String;
761 Comment : String);
762 var AOpt : pOptRec;
763 begin
764 if AktSec = NIL then Exit;
765 AOpt := AktOpt;
766 InsertEntry (AktSec^.Name,Name,Value,'');
767 AktOpt := AOpt;
768 end;
769 procedure IniObj.DelSecEntry (Name : String);
770 var AOpt : pOptRec;
771 begin
772 if AktSec = NIL then Exit;
773 AOpt := AktOpt;
774 DelEntry (AktSec^.Name,Name,false);
775 AktOpt := AOpt;
776 end;
777 procedure IniObj.DelCurEntry(DelSec: Boolean);
778 var AOpt : pOptRec;
779 ASec : pSecRec;
780 begin
781 If (AktOpt = Nil) then Exit
782 Else If (AktOpt = AktSec^.Options) Then
783 Begin
784 AktSec^.Options := AktOpt^.NextOpt;
785 AktOpt^.NextOpt^.PrevOpt := Nil;
786 End
787 Else If (AktOpt^.NextOpt = Nil) then
788 Begin
789 AktOpt^.PrevOpt^.NextOpt := Nil;
790 End
791 Else
792 Begin
793 AktOpt^.PrevOpt^.NextOpt := AktOpt^.NextOpt;
794 AktOpt^.NextOpt^.PrevOpt := AktOpt^.PrevOpt;
795 End;
796 Dispose(AktOpt);
797 if (AktSec^.Options = NIL) and DelSec then
798 Begin
799 If (AktSec^.PrevSec = Nil) then
800 Begin
801 If (AktSec^.NextSec <> Nil) then
802 Begin
803 AktSec^.NextSec^.PrevSec := Nil;
804 IniTree := AktSec^.NextSec;
805 End
806 Else IniTree := Nil;
807 End
808 Else
809 Begin
810 AktSec^.PrevSec^.NextSec := AktSec^.NextSec;
811 AktSec^.NextSec^.PrevSec := AktSec^.PrevSec;
812 End;
813 Dispose(AktSec);
814 End;
815 end;
816
817 {****************************************************************************}
818 end.
819 { Externale Prceduren,Functionen & Typen
820 FileStr (T) : String Type fuer Dateiname. (String[12])
821 UpStr (F) : wandelt alle Buchstaben in Grossbuchstaben.
822 CutStr (F) : Schneidet vorstehende Leerzeichen und Tabs ab.
823 StrCut (F) : Schneidet nachstehende Leerzeichen und Tabs ab.
824 FillStr (F) : Fuellt eine String mit eine Zeichen auf eine bestimmte Laenge
825 FileExists (F) : Prueft ob eine Datei Existiert (siehe Online Hilfe) mit
826 Attribut ueberpruefung
827 }
828 {05.04.96 : Begin mit der Grundstruktur, Aufbau eines Objectes, Bug Fixes
829 06.04.96 : BugFixes, Implementierung Comments,SetCommentPos,NotFound,
830 DelEntry, ausgiebiger Test der Unit
831 07.04.96 : DataBase Routinen (Tested)
832
833 Sascha Silbe:
834 12.07.98 : fixed some bugs
835 }
836