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