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 (Str[1] = ';') then Y := 1;
349 if (Y > 0) or (X > 0) then
350 begin
351 AOpt := NewOpt;
352 if Str[1] = ';' then
353 begin
354 AOpt^.Name := ';'; {Kommentarzeile}
355 AOpt^.Comment := Copy (Str,2,Length(Str)-1);
356 end
357 else
358 begin
359 If (x = 0) then
360 begin
361 AOpt^.Name := KillSpcs(Copy (Str, 1, y-1));
362 AOpt^.Value := '';
363 AOpt^.Comment := KillSpcs(Copy(Str, y+1, Length(str)-y));
364 end
365 else
366 begin
367 AOpt^.Name := KillSpcs(Copy (Str,1,X-1));
368 if Y <> 0 then
369 begin
370 AOpt^.Value := KillSpcs(Copy (Str,X+1,Y-X-1));
371 AOpt^.Comment := KillSpcs(Copy (Str,Y+1,Length(Str)-Y));
372 end
373 else
374 begin
375 AOpt^.Value := KillSpcs(Copy (Str,X+1,Length(Str)-X));
376 AOpt^.Comment := '';
377 end;
378 end;
379 end;
380 end
381 else
382 begin
383 AOpt^.Name := KillSpcs(Str);
384 AOpt^.Value := '';
385 AOpt^.Comment := '';
386 end;
387 if IniTree = NIL then
388 begin
389 IniTree := NewSec;
390 AktSec := IniTree;
391 end;
392 if AktSec^.Options = NIL then AktSec^.Options := AOpt
393 else AktOpt^.NextOpt := AOpt;
394 AOpt^.PrevOpt := AktOpt;
395 AktOpt := AOpt;
396 end;
397 end;
398 end;
399 Close (f);
400 end;
401 procedure IniObj.WriteIni;
402 const Comment : String = '';
403 OptVal : String = '';
404 begin
405 if IniTree = Nil then Exit;
406 { FileMode := 2;}
407 {$I-} Rewrite (f); {$I+}
408 If IOResult <> 0 then
409 Begin
410 { WriteLn('WriteIni: Couldn''t open file!');}
411 Exit;
412 End;
413 AktSec := IniTree;
414 AktOpt := AktSec^.Options;
415 {$I-}
416 while AktSec <> NIL do begin
417 if AktSec^.Name <> '' then WriteLn (f,'['+UpStr(AktSec^.Name)+']');
418 while AktOpt <> NIL do begin
419 if AktOpt^.Name = ';' then WriteLn (f,AktOpt^.Name+AktOpt^.Comment)
420 else begin
421 OptVal := AktOpt^.Name+'='+ AktOpt^.Value;
422 if AktOpt^.Comment <> '' then begin
423 if CommentPos <> 0 then OptVal := FillStr (OptVal,CommentPos,' ');
424 Comment := ' ;'+AktOpt^.Comment
425 end;
426 WriteLn (f, OptVal + Comment);
427 Comment := ''; OptVal := '';
428 end;
429 AktOpt := AktOpt^.NextOpt;
430 end;
431 AktSec := AktSec^.NextSec;
432 If AktSec <> Nil then AktOpt := AktSec^.Options;
433 end;
434 If IOResult <> 0 then
435 Begin
436 { WriteLn('WriteIni: Couldn''t write file!');}
437 End;
438
439 Close (f); {$I-}
440 If IOResult <> 0 then
441 Begin
442 { WriteLn('WriteIni: Couldn''t close file!');}
443 End;
444 end;
445 procedure IniObj.DelIni;
446 var ASec : pSecRec;
447 AOpt : pOptRec;
448 X : byte;
449 Str : String;
450 begin
451 if IniTree = Nil then Exit;
452 AktSec := IniTree;
453 AktOpt := AktSec^.Options;
454 while AktSec <> NIL do begin
455 ASec := AktSec^.NextSec;
456 if AktSec <> NIl then Dispose (AktSec);
457 while AktOpt <> NIL do begin
458 AOpt := AktOpt^.NextOpt;
459 if AktOpt <> NIL then Dispose (AktOpt);
460 AktOpt := AOpt;
461 end;
462 AktSec := ASec;
463 If AktSec <> Nil then AktOpt := AktSec^.Options;
464 end;
465 end;
466 {****************************************************************************}
IniObj.SearchSectionnull467 function IniObj.SearchSection (ASection : String;
468 Last : boolean ) : boolean;
469 { Suchen nach der Section. Ist Last auf true wird AktSec auf die Section
470 vor der gesuchten gesetzt, ist Last auf false wird AktSec auf die
471 gesuchte Section gesetzt, oder bei nicht finden auf die letzte der
472 Verkettung. Wird eine Section gefunde ist der Rueckgabewert der Function
473 true, ansonsten false.
474 Zur beschleunigung der Suche : ist AktSec schon das gesuchte wird nicht
475 gesucht, wie z.B. durch WriteSecEntry }
476 var Found : boolean;
477 ASec : pSecRec;
478 begin
479 if IniTree = Nil then begin
480 SearchSection := false;
481 Exit;
482 end;
483 found := false;
484 ASection := UpStr (ASection);
485 ASec := NIL;
486 If AktSec = NIL then AktSec := IniTree
487 Else
488 if (AktSec^.Name = ASection) and (not Last) then Found := true
489 else AktSec := IniTree;
490 while (AktSec <> NIL) and (not Found) do begin
491 if ASection = AktSec^.Name then Found := true
492 Else
493 begin
494 ASec := AktSec;
495 AktSec := AktSec^.NextSec;
496 end;
497 end;
498 if Last or (AktSec = NIL) then AktSec := ASec;
499 SearchSection := found;
500 end;
IniObj.SearchOptionnull501 function IniObj.SearchOption (AOption : String;
502 Last : boolean) : boolean;
503 { Suchen nach der Option. Ist Last auf true wird AktOpt auf die Option
504 vor der gesuchten gesetzt, ist Last auf false wird AktOpt auf die
505 gesuchte Option gesetzt, oder bei nicht finden auf die letzte der
506 Verkettung, Nur wenn gar keine Verkettung unter dieser Section
507 existiert wird AktOpt auf NIL gesetzt. Aber dann ist auch der
508 rueckgabewert der Function false
509 Zur beschleunigung der Suche : ist AktOpt schon das gesuchte wird nicht
510 gesucht}
511
512 var Found : boolean;
513 AOpt : pOptRec;
514 begin
515 if IniTree = Nil then begin
516 SearchOption := false;
517 Exit;
518 end;
519 found := false;
520 AOpt := NIL;
521 if (UpStr(AktOpt^.Name) = UpStr(AOption)) and (not Last) then Found := true
522 else AktOpt := AktSec^.Options;
523 while (AktOpt <> NIL) and (not Found) do begin
524 if UpStr(AOption) = UpStr(AktOpt^.Name) then Found := true;
525 if not Found then begin
526 AOpt := AktOpt;
527 AktOpt := AktOpt^.NextOpt;
528 end;
529 end;
530 If Last or (AktOpt = NIL) then AktOpt := AOpt;
531 SearchOption := found;
532 end;
533 {****************************************************************************}
IniObj.ReadEntrynull534 function IniObj.ReadEntry ( Section : String; Option : String ) : String;
535 Var Value : String;
536 begin
537 if SearchSection (Section,false) then
538 if SearchOption (Option,false) then
539 Value := AktOpt^.Value
540 else Value := NotFound;
541 ReadEntry := Value;
542 end;
543 procedure IniObj.WriteEntry(Section, Option, Value, Comment: String);
544 begin
545 if SearchSection (Section,false) then
546 if SearchOption (Option,false) then
547 begin
548 AktOpt^.Value := Value;
549 if Comment <> '' then AktOpt^.Comment := Comment;
550 end else
551 begin
552 AktOpt^.NextOpt := NewOpt;
553 AktOpt := AktOpt^.NextOpt;
554 AktOpt^.Name := Option;
555 AktOpt^.Value := Value;
556 AktOpt^.Comment := Comment;
557 end
558 else begin
559 if IniTree = NIL then begin
560 IniTree := NewSec;
561 AktSec := IniTree;
562 end else begin
563 AktSec^.NextSec := NewSec;
564 AktSec := AktSec^.NextSec;
565 end;
566 AktSec^.Name := UpStr(Section);
567 AktSec^.Options := NewOpt;
568 AktOpt := AktSec^.Options;
569 AktOpt^.Name := Option;
570 AktOpt^.Value := Value;
571 AktOpt^.Comment := Comment;
572 end;
573 end;
574 procedure IniObj.AddEntry(Section, Option, Value, Comment: String);
575 Var
576 AOpt : pOptRec;
577 begin
578 if SearchSection (Section,false) then
579 begin
580 AOpt := AktOpt;
581 While (AOpt^.NextOpt <> Nil) do AOpt := AOpt^.NextOpt;
582 AOpt^.NextOpt := NewOpt;
583 AOpt^.PrevOpt := AktOpt;
584 AOpt := AOpt^.NextOpt;
585 AOpt^.Name := Option;
586 AOpt^.Value := Value;
587 AOpt^.Comment := Comment;
588 end
589 else begin
590 if IniTree = NIL then begin
591 IniTree := NewSec;
592 AktSec := IniTree;
593 end else begin
594 AktSec^.NextSec := NewSec;
595 AktSec^.NextSec^.PrevSec := AktSec;
596 AktSec := AktSec^.NextSec;
597 end;
598 AktSec^.Name := UpStr(Section);
599 AktSec^.Options := NewOpt;
600 AktOpt := AktSec^.Options;
601 AktOpt^.Name := Option;
602 AktOpt^.Value := Value;
603 AktOpt^.Comment := Comment;
604 end;
605 end;
606 procedure IniObj.InsertEntry(Section, Option, Value, Comment: String);
607 Var
608 AOpt : pOptRec;
609 begin
610 if SearchSection (Section,false) then
611 begin
612 AOpt := AktOpt^.NextOpt;
613 AktOpt^.NextOpt := NewOpt;
614 AktOpt^.NextOpt^.PrevOpt := AktOpt;
615 AktOpt^.NextOpt^.NextOpt := AOpt;
616 AOpt := AktOpt^.NextOpt;
617 AOpt^.Name := Option;
618 AOpt^.Value := Value;
619 AOpt^.Comment := Comment;
620 end
621 else begin
622 if IniTree = NIL then begin
623 IniTree := NewSec;
624 AktSec := IniTree;
625 end else begin
626 AktSec^.NextSec := NewSec;
627 AktSec^.NextSec^.PrevSec := AktSec;
628 AktSec := AktSec^.NextSec;
629 end;
630 AktSec^.Name := UpStr(Section);
631 AktSec^.Options := NewOpt;
632 AktOpt := AktSec^.Options;
633 AktOpt^.Name := Option;
634 AktOpt^.Value := Value;
635 AktOpt^.Comment := Comment;
636 end;
637 end;
638 procedure IniObj.DelEntry ( Section : String;
639 Option : String;
640 DelSec : Boolean );
641 var AOpt : pOptRec;
642 ASec : pSecRec;
643 begin
644 if SearchSection (Section,false) then
645 if SearchOption (Option,false) then begin
646 AOpt := AktOpt;
647 SearchOption (Option,true);
648 if AktOpt <> NIL then
649 Begin
650 AktOpt^.NextOpt := AOpt^.NextOpt;
651 AOpt^.NextOpt^.PrevOpt := AktOpt;
652 End
653 else
654 Begin
655 AktSec^.Options := AOpt^.NextOpt;
656 AOpt^.NextOpt^.PrevOpt := Nil;
657 End;
658 if AOpt <> NIL then Dispose (AOpt);
659 if (AktSec^.Options = NIL) and DelSec then begin
660 ASec := AktSec;
661 SearchSection (Section,true);
662 if AktSec <> NIL then
663 Begin
664 AktSec^.NextSec := ASec^.NextSec;
665 ASec^.NextSec^.PrevSec := AktSec;
666 End
667 else
668 Begin
669 IniTree := ASec^.NextSec;
670 ASec^.NextSec^.PrevSec := Nil;
671 End;
672 if ASec <> NIL then Dispose (ASec);
673 end;
674 end;
675 end;
676 {****************************************************************************}
677 procedure IniObj.ShowTree;
678 const Comment : String = '';
679 OptVal : String = '';
680 begin
681 if IniTree = Nil then Exit;
682 AktSec := IniTree;
683 AktOpt := AktSec^.Options;
684 while AktSec <> NIL do begin
685 if AktSec^.Name <> '' then WriteLn ('['+AktSec^.Name+']');
686 while AktOpt <> NIL do begin
687 if AktOpt^.Name = ';' then WriteLn (AktOpt^.Name+AktOpt^.Comment)
688 else begin
689 OptVal := AktOpt^.Name+'='+ AktOpt^.Value;
690 if AktOpt^.Comment <> '' then begin
691 if CommentPos <> 0 then OptVal := FillStr (OptVal,CommentPos,' ');
692 Comment := ' ;'+AktOpt^.Comment
693 end;
694 WriteLn (OptVal + Comment);
695 Comment := ''; OptVal := '';
696 end;
697 AktOpt := AktOpt^.NextOpt;
698 end;
699 AktSec := AktSec^.NextSec;
700 If (AktSec <> Nil) then AktOpt := AktSec^.Options;
701 end;
702 end;
703
704 {****************************************************************************}
IniObj.SetPrevOptnull705 function IniObj.SetPrevOpt : boolean;
706
707 begin
708 if AktOpt^.PrevOpt <> Nil then begin
709 repeat AktOpt := AktOpt^.PrevOpt
710 until (AktOpt^.Name <> ';') or (AktOpt^.PrevOpt = Nil);
711 if (AktOpt^.PrevOpt = Nil) and ( AktOpt^.Name = ';')
712 then SetPrevOpt := false else SetPrevOpt := true;
713 end else SetPrevOpt := false;
714 end;
IniObj.SetNextOptnull715 function IniObj.SetNextOpt : boolean;
716
717 begin
718 if AktOpt^.NextOpt <> Nil then begin
719 repeat AktOpt := AktOpt^.NextOpt
720 until (AktOpt^.Name <> ';') or (AktOpt^.NextOpt = Nil);
721 if (AktOpt^.NextOpt = Nil) and ( AktOpt^.Name = ';')
722 then SetNextOpt := false else SetNextOpt := true;
723 end else SetNextOpt := false;
724 end;
IniObj.GetSecNumnull725 function IniObj.GetSecNum (Section : String ) : integer;
726 var Num : Integer;
727 AOpt : pOptRec;
728 begin
729 Num := 0;
730 AOpt := AktOpt;
731 if SearchSection (Section,false) then begin
732 AktOpt := AktSec^.Options;
733 while AktOpt <> NIL do begin
734 if AktOpt^.Name[1] <> ';' then Inc (Num);
735 if not SetNextOpt then AktOpt := NIL;
736 end;
737 end;
738 AktOpt := AOpt;
739 GetSecNum := Num;
740 end;
741 procedure IniObj.SetSection (Section : String);
742 begin
743 if not SearchSection (Section,false) then begin
744 WriteEntry (Section,';','','');
745 end;
746 ReSetSec;
747 end;
748 procedure IniObj.ReSetSec;
749 begin
750 AktOpt := AktSec^.Options;
751 if AktOpt^.Name = ';' then SetNextOpt;
752 end;
IniObj.ReSecEnNamenull753 function IniObj.ReSecEnName : String;
754 begin
755 if AktOpt = NIL then begin
756 ReSecEnName := NotFound;
757 Exit;
758 end;
759 ReSecEnName := AktOpt^.Name;
760 end;
761
IniObj.ReSecEnValuenull762 function IniObj.ReSecEnValue : String;
763 begin
764 if AktOpt = NIL then begin
765 ReSecEnValue := NotFound;
766 Exit;
767 end;
768 ReSecEnValue := AktOpt^.Value;
769 end;
IniObj.SearchSecEntrynull770 function IniObj.SearchSecEntry (Name : String ) : String;
771 var AOpt : pOptRec;
772 begin
773 if AktSec = NIL then begin
774 SearchSecEntry := NotFound;
775 Exit;
776 end;
777 AOpt := AktOpt;
778 SearchSecEntry := ReadEntry (AktSec^.Name,Name);
779 AktOpt := AOpt;
780 end;
781 procedure IniObj.WriteSecEntry (Name : String;
782 Value : String;
783 Comment : String);
784 var AOpt : pOptRec;
785 begin
786 if AktSec = NIL then Exit;
787 AOpt := AktOpt;
788 WriteEntry (AktSec^.Name,Name,Value,'');
789 AktOpt := AOpt;
790 end;
791 procedure IniObj.AddSecEntry (Name : String;
792 Value : String;
793 Comment : String);
794 var AOpt : pOptRec;
795 begin
796 if AktSec = NIL then Exit;
797 AOpt := AktOpt;
798 AddEntry (AktSec^.Name,Name,Value,'');
799 AktOpt := AOpt;
800 end;
801 procedure IniObj.InsertSecEntry (Name : String;
802 Value : String;
803 Comment : String);
804 var AOpt : pOptRec;
805 begin
806 if AktSec = NIL then Exit;
807 AOpt := AktOpt;
808 InsertEntry (AktSec^.Name,Name,Value,'');
809 AktOpt := AOpt;
810 end;
811 procedure IniObj.DelSecEntry (Name : String);
812 var AOpt : pOptRec;
813 begin
814 if AktSec = NIL then Exit;
815 AOpt := AktOpt;
816 DelEntry (AktSec^.Name,Name,false);
817 AktOpt := AOpt;
818 end;
819 procedure IniObj.DelCurEntry(DelSec: Boolean);
820 var AOpt : pOptRec;
821 ASec : pSecRec;
822 begin
823 If (AktOpt = Nil) then Exit
824 Else If (AktOpt = AktSec^.Options) Then
825 Begin
826 AktSec^.Options := AktOpt^.NextOpt;
827 AktOpt^.NextOpt^.PrevOpt := Nil;
828 End
829 Else If (AktOpt^.NextOpt = Nil) then
830 Begin
831 AktOpt^.PrevOpt^.NextOpt := Nil;
832 End
833 Else
834 Begin
835 AktOpt^.PrevOpt^.NextOpt := AktOpt^.NextOpt;
836 AktOpt^.NextOpt^.PrevOpt := AktOpt^.PrevOpt;
837 End;
838 Dispose(AktOpt);
839 if (AktSec^.Options = NIL) and DelSec then
840 Begin
841 If (AktSec^.PrevSec = Nil) then
842 Begin
843 If (AktSec^.NextSec <> Nil) then
844 Begin
845 AktSec^.NextSec^.PrevSec := Nil;
846 IniTree := AktSec^.NextSec;
847 End
848 Else IniTree := Nil;
849 End
850 Else
851 Begin
852 AktSec^.PrevSec^.NextSec := AktSec^.NextSec;
853 AktSec^.NextSec^.PrevSec := AktSec^.PrevSec;
854 End;
855 Dispose(AktSec);
856 End;
857 end;
858
859 {****************************************************************************}
860 end.
861 { Externale Prceduren,Functionen & Typen
862 FileStr (T) : String Type fuer Dateiname. (String[12])
863 UpStr (F) : wandelt alle Buchstaben in Grossbuchstaben.
864 CutStr (F) : Schneidet vorstehende Leerzeichen und Tabs ab.
865 StrCut (F) : Schneidet nachstehende Leerzeichen und Tabs ab.
866 FillStr (F) : Fuellt eine String mit eine Zeichen auf eine bestimmte Laenge
867 FileExists (F) : Prueft ob eine Datei Existiert (siehe Online Hilfe) mit
868 Attribut ueberpruefung
869 }
870 {05.04.96 : Begin mit der Grundstruktur, Aufbau eines Objectes, Bug Fixes
871 06.04.96 : BugFixes, Implementierung Comments,SetCommentPos,NotFound,
872 DelEntry, ausgiebiger Test der Unit
873 07.04.96 : DataBase Routinen (Tested)
874
875 Sascha Silbe:
876 12.07.98 : fixed some bugs
877 }
878