home *** CD-ROM | disk | FTP | other *** search
- UNIT pagelist; {$project vt}
- { Verwaltung der verketteten Seitenliste zum Programm VideoText }
- { Es wird darauf geachtet, daß die Auswahlzeiger <thispage> und <visblpage> }
- { immer einen sinnvollen Inhalt haben und daß <thispage> nur bei leerer }
- { Liste NIL ist. }
-
- INTERFACE; FROM vt USES global;
-
- VAR root,thispage,visblpage: p_onepage;
- listsize: Word;
-
- PROCEDURE kill_list;
- PROCEDURE del_from_list(target: p_onepage);
- PROCEDURE ins_to_list(item: p_onepage);
- PROCEDURE add_to_list(item: p_onepage);
- FUNCTION hunt_in_list(pg,sp: Integer; exact: Boolean): p_onepage;
- FUNCTION next_magazine(item: p_onepage): p_onepage;
- FUNCTION prev_magazine(item: p_onepage): p_onepage;
- FUNCTION posn_in_list(item: p_onepage): Integer;
- FUNCTION page_on_posn(n: Integer): p_onepage;
-
- { ---------------------------------------------------------------------- }
-
- IMPLEMENTATION;
-
- {$opt q,s+,i+ } { keine Laufzeitprüfungen außer Stack und Feldindizes }
-
- PROCEDURE kill_list;
- { Alle Seiten wegwerfen. }
- VAR hilf: p_onepage;
- BEGIN
- hilf := root;
- WHILE root<>Nil DO BEGIN
- root := root^.next;
- Dispose(hilf);
- hilf := root;
- END;
- thispage := root; visblpage := Nil;
- listsize := 0;
- END;
-
- PROCEDURE del_from_list{(target: p_onepage)};
- { Die bezeichnete Seite aus der Liste herauslösen UND löschen (Dispose). }
- { Falls <thispage> auf die gelöschte Seite zeigt, wird sichergestellt, daß }
- { <thispage> anschließend wieder auf einen sinnvollen Inhalt zeigt: }
- { - auf den Nachfolger der gelöschten Seite, falls sie einen hat, sonst }
- { - auf ihren Vorgänger (d. h. Listenende oder Nil) }
- BEGIN
- IF target^.prev<>Nil THEN
- target^.prev^.next := target^.next ELSE root := target^.next;
- IF target^.next<>Nil THEN
- target^.next^.prev := target^.prev;
- IF target=visblpage THEN visblpage := Nil;
- IF target=thispage THEN BEGIN
- thispage := target^.next;
- IF thispage = Nil THEN thispage := target^.prev;
- END;
- Dispose(target);
- Dec(listsize);
- END;
-
- FUNCTION hunt_in_list{(pg,sp: Integer; exact: Boolean): p_onepage};
- { Liefert einen Zeiger auf die durch <pg>, <sp> beschriebene Seite in der }
- { Liste. Falls eine entsprechende Seite nicht gefunden wird, ist das }
- { Resultat für exact=False der nächsthöhere existierende Eintrag (bzw. das }
- { Listenende, wenn es keinen höheren Eintrag gibt), für exact=True einfach }
- { Nil. Letztere Variante funktioniert dafür auch auf unsortierten Listen, }
- { d. h. solchen, die mit add_to_list() statt ins_to_list() aufgebaut wurden. }
- VAR hilf: p_onepage;
- BEGIN
- hilf := root;
- IF hilf<>Nil THEN
- IF exact THEN BEGIN
- { richtige Seitennummer finden }
- WHILE ((hilf^.pg<>pg) OR (hilf^.sp<>sp)) AND (hilf^.next<>Nil) DO
- hilf := hilf^.next;
- IF ((hilf^.pg<>pg) OR (hilf^.sp<>sp)) THEN
- hilf := Nil; {=hilf^.next}
- END ELSE BEGIN
- { richtige oder nächsthöhere Seitennummer finden }
- WHILE (hilf^.pg<pg) AND (hilf^.next<>Nil) DO
- hilf := hilf^.next;
- { Wenn die Seitennummer stimmt, noch die Unterseite finden }
- WHILE (hilf^.pg=pg) AND (hilf^.sp<sp) AND (hilf^.next<>Nil) DO
- hilf := hilf^.next;
- END;
- hunt_in_list := hilf;
- END;
-
- PROCEDURE ins_to_list{(item: p_onepage)};
- { Neue Seite nach Seiten- und Unterseitennummer in die Liste einsortieren. }
- { Wenn bereits gleichartige Einträge existieren, wird die neue Seite hinter }
- { diesen eingefügt. }
- VAR hilf: p_onepage;
- BEGIN
- IF root=Nil THEN BEGIN
- root := item;
- item^.next := Nil;
- item^.prev := Nil;
- END ELSE BEGIN
- hilf := hunt_in_list(item^.pg,item^.sp,False);
- WHILE (hilf^.pg=item^.pg) AND (hilf^.sp=item^.sp) AND (hilf^.next<>Nil) DO
- hilf := hilf^.next;
- { hilf zeigt jetzt auf die Seite, vor der eingefügt werden sollte, bzw. }
- { auf das Listenende, falls die neue Seite die höchste aller Nummern hat. }
- IF (hilf^.pg>item^.pg) OR ((hilf^.pg=item^.pg) AND (hilf^.sp>item^.sp))
- THEN BEGIN { Normalfall, vor hilf einfügen }
- item^.prev := hilf^.prev;
- item^.next := hilf;
- IF hilf^.prev<>Nil THEN hilf^.prev^.next := item ELSE root := item;
- hilf^.prev := item;
- END ELSE BEGIN { Sonderfall, hinter hilf anhängen }
- item^.prev := hilf;
- item^.next := hilf^.next;
- IF hilf^.next<>Nil THEN hilf^.next^.prev := item;
- hilf^.next := item;
- END;
- END;
- IF thispage=Nil THEN thispage := item;
- Inc(listsize);
- END;
-
- PROCEDURE add_to_list{(item: p_onepage)};
- { Hängt eine Seite ans Ende der Liste an. }
- VAR hilf: p_onepage;
- BEGIN
- IF root=Nil THEN BEGIN
- root := item
- item^.next := Nil;
- item^.prev := Nil;
- END ELSE BEGIN
- hilf := root;
- WHILE hilf^.next<>Nil DO
- hilf := hilf^.next;
- { Hinter hilf anhängen: }
- hilf^.next := item;
- item^.prev := hilf;
- item^.next := Nil;
- END;
- IF thispage=Nil THEN thispage := item;
- Inc(listsize);
- END;
-
- FUNCTION next_magazine{(item: p_onepage): p_onepage};
- { Erste Seite finden, die hinter <item> in der Liste steht und eine andere }
- { Magazinnummer trägt. Absichtlich so vorsichtig formuliert, damit das auch }
- { auf unsortierten Listen sinnvolle Resultate liefert. }
- VAR mag: integer;
- BEGIN
- IF item<>Nil THEN BEGIN
- mag := item^.pg SHR 8;
- { zum nächsten Magazin vorrücken }
- WHILE (item^.next<>Nil) AND (item^.pg SHR 8 = mag) DO
- item := item^.next;
- END;
- next_magazine := item;
- END;
-
- FUNCTION prev_magazine{(item: p_onepage): p_onepage};
- { Die in Richtung Listenanfang nächstliegende Seite, die einen Magazinanfang }
- { markiert und nicht <item> selbst ist. }
- VAR mag: integer;
- BEGIN
- IF item<>Nil THEN IF item^.prev<>Nil THEN BEGIN
- item := item^.prev;
- mag := item^.pg SHR 8;
- { zum vorigen Magazin }
- WHILE (item^.prev<>Nil) AND (item^.pg SHR 8 = mag) DO
- item := item^.prev;
- { Hoppla, eins zu weit ... }
- IF (item^.next<>Nil) AND (item^.pg SHR 8 <> mag) THEN
- item := item^.next;
- END;
- prev_magazine := item;
- END;
-
- FUNCTION posn_in_list{(item: p_onepage): Integer};
- { herausfinden, die wievielte in der Liste <seite> ist (ab 0 gezählt) }
- VAR n: Integer;
- hilf: p_onepage;
- BEGIN
- hilf := root; n := 0;
- WHILE (hilf<>Nil) AND (hilf<>item) DO BEGIN
- hilf := hilf^.next; Inc(n); END;
- posn_in_list := n;
- END;
-
- FUNCTION page_on_posn{(n: Integer): p_onepage};
- { Zeiger auf die <n>-te Seite besorgen }
- VAR i: Integer;
- hilf: p_onepage;
- BEGIN
- hilf := root;
- FOR i := 1 TO n DO
- IF hilf<>Nil THEN hilf := hilf^.next;
- page_on_posn := hilf;
- END;
-
- BEGIN { Intialisierungsteil }
- root := Nil; thispage := Nil; visblpage := Nil;
- listsize := 0;
- END.
-
-