MODULE InfoLook;
(* Helmut Zinn *)
(* Use the Cross-Referenz List *)
	
	IMPORT
		InfoCmds, InfoDialog, TextCmds, TextControllers, TextModels, TextMappers, TextViews, TextRulers, Views,
		Containers, StdFolds, StdLinks, Fonts, Ports, Strings, Dialog;

	CONST
		maxLength = 256;
		linkcommand = 'InfoCmds.Start'; (* Alternativ: linkcommand = 'LibMisc.ShellExecute'; *)
		underline = FALSE;
	
	TYPE
		DynString* = POINTER TO ARRAY OF CHAR;

	VAR
		docCount: INTEGER; 
		docList: POINTER TO ARRAY OF RECORD
			path: DynString;
			name: DynString;
		END;
		
	PROCEDURE MakeDynString* (IN s: ARRAY OF CHAR): DynString;
	VAR d: DynString;
	BEGIN
		NEW(d, LEN(s)+1); d^ := s$; 
		RETURN d;
	END MakeDynString;

	PROCEDURE NewRuler (): TextRulers.Ruler;
		CONST mm = Ports.mm;
		VAR p: TextRulers.Prop;
	BEGIN
		NEW(p);
		p.valid := {TextRulers.right, TextRulers.tabs, TextRulers.opts};
		p.opts.val := {TextRulers.rightFixed}; p.opts.mask := p.opts.val;
		p.right := 100 * mm;
		p.tabs.len := 1;
		p.tabs.tab[0].stop := 80 * mm;
		p.tabs.tab[0].type := {TextRulers.rightTab};
		RETURN TextRulers.dir.NewFromProp(p)
	END NewRuler;

	PROCEDURE UnderlineBlue (VAR f: TextMappers.Formatter);
		VAR new: TextModels.Attributes;
	BEGIN
		new := f.rider.attr;
		new := TextModels.NewStyle(new, new.font.style + {Fonts.underline});
		new := TextModels.NewColor(new, Ports.blue);
		f.rider.SetAttr(new);	(* change current attributes of formatter *)
	END UnderlineBlue;

	PROCEDURE Black (VAR f: TextMappers.Formatter);
		VAR new: TextModels.Attributes;
	BEGIN
		new := f.rider.attr;
		new := TextModels.NewStyle(new, new.font.style - {Fonts.underline});
		new := TextModels.NewColor(new, Ports.black);
		f.rider.SetAttr(new);	(* change current attributes of formatter *)
	END Black;

	PROCEDURE WriteLink* (VARf:TextMappers.Formatter; IN label, cmdstr: ARRAY OF CHAR);
		VAR v: Views.View;
	BEGIN
		v := StdLinks.dir.NewLink(cmdstr);
		f.WriteView(v);	(* insert left link view in text *)
		UnderlineBlue(f);
		f.WriteString(label);	(* the string shown between the pair of link views *)
		Black(f);
		v := StdLinks.dir.NewLink("");
		f.WriteView(v);	(* insert right link view in text *)
	END WriteLink;

	PROCEDURE ReadUntilDelimiter (r: TextModels.Reader; delimiter: CHAR; VAR str: ARRAY OF CHAR);
		VAR
			i: INTEGER;
			ch: CHAR;
	BEGIN
		i := 0;
		r.ReadChar(ch);
		WHILE ~r.eot & (ch # delimiter) DO
			str[i] := ch; INC(i);
			r.ReadChar(ch)
		END;
		str[i] := 0X
	END ReadUntilDelimiter;

	PROCEDURE Decode (str: ARRAY OF CHAR; VAR pos: INTEGER): INTEGER;
		VAR
			start: INTEGER;
			intStr: ARRAY 8  OF CHAR;
			num, res : INTEGER;
	BEGIN
		start := pos;
		Strings.Find(str, " ", start, pos); IF pos = -1 THEN pos := LEN(str$) END;
		Strings.Extract(str, start, pos-start, intStr);
		Strings.StringToInt(intStr, num, res); ASSERT(res = 0);
		pos := pos + 1;
		RETURN num;
	END Decode;

	PROCEDURE LoadDocList;
		VAR
			c: TextControllers.Controller;
			r: TextModels.Reader;
			v: Views.View;
			t: TextModels.Model;
			i, res: INTEGER;
			str: ARRAY 256 OF CHAR;
	BEGIN
		c := TextControllers.Focus();
		StdFolds.CollapseFolds(c.text, FALSE, "Documents");	(* in case *)
		r := c.text.NewReader(NIL);
		r.SetPos(0);
		r.ReadView(v);	(* asking for a view, hoping for a fold *)
		WITH v: StdFolds.Fold DO
			t := v.HiddenText();	(* : TextModels.Model *)
			r := t.NewReader(NIL);	(* new use for an old reader *)
			r.SetPos(0);
			(* read docCount from fold *)
			ReadUntilDelimiter(r, TextModels.line, str);
			ReadUntilDelimiter(r, TextModels.line, str);
			Strings.StringToInt(str, docCount, res);
			(* read paths/names from fold *)
			NEW(docList, docCount+1);
			FOR i := 1 TO docCount DO
				ReadUntilDelimiter(r, TextModels.tab, str);
				docList[i].path := MakeDynString(str$); 
				ReadUntilDelimiter(r, TextModels.line, str);
				docList[i].name := MakeDynString(str$); 
			END
		END
	END LoadDocList;

	PROCEDURE Expand* (pat, docNumberList: ARRAY OF CHAR);
		VAR			
			t: TextModels.Model;
			f: TextMappers.Formatter;
			c: Containers.Controller;
			v: TextViews.View;
			title: Views.Title;
			a0: TextModels.Attributes;
			start, docNum, count: INTEGER;
			label: ARRAY 256 OF CHAR;
			cmd: ARRAY 384 OF CHAR;
	BEGIN
		IF (docList = NIL) OR (docList[1].path$ # InfoDialog.param.source$) THEN
			LoadDocList;
		END;
		t := TextModels.dir.New();	(* create a new, empty text *)
		f.ConnectTo(t);	(* connect a formatter to the text *)
		f.WriteView(NewRuler());
		a0 := f.rider.attr;
		f.rider.SetAttr(TextModels.NewWeight(f.rider.attr, Fonts.bold));
		Dialog.MapString("#Std:Location", cmd);
		f.WriteString(cmd); f.WriteTab;
		Dialog.MapString("#Std:Count", cmd);
		f.WriteString(cmd); f.WriteLn;
		f.rider.SetAttr(a0);
		start := 0;
		WHILE start < LEN(docNumberList$) DO
			docNum := Decode(docNumberList, start);
			count := Decode(docNumberList, start);
			IF docList = NIL THEN
				f.WriteInt(docNum)
			ELSE
				label := docList[docNum].path$ + docList[docNum].name$; 
				cmd := "InfoCmds.OpenDoc('" + label$ + "'); InfoCmds.Select('" +  pat$ + "')"; 
				WriteLink(f, label, cmd);
			END;
			f.WriteTab; f.WriteInt(count); f.WriteLn
		END;
		(* Open View in Browser mode ... *)
		v := TextViews.dir.New(t);
		Dialog.MapString("#Std:Looking for", title);
		title := title$ +'  "' + pat + '"';
		Views.OpenAux(v, title);
		c := v.ThisController();
		c.SetOpts(c.opts + {Containers.noCaret});
	END Expand;

	PROCEDURE FindInIndex*;
		VAR
			c: TextControllers.Controller;
			label: StdFolds.Label;
	BEGIN
		InfoDialog.ProofParam;
		InfoCmds.OpenDoc(InfoDialog.param.source+'Index');
		IF TextCmds.find.find # '' THEN
			label[0] := TextCmds.find.find[0];
			label[1] := 0X;
			IF label # '' THEN
				IF ('a' <= label[0]) & (label[1] <= 'z') THEN label[0] := CAP(label[0]); 
				ELSIF label[0] = '' THEN label[0] := '';
				ELSIF label[0] = '' THEN label[0] := '';
				ELSIF label[0] = '' THEN label[0] := '';
				END; 
				c := TextControllers.Focus();
				StdFolds.ExpandFolds(c.text, FALSE, label);
			END;
			TextCmds.FindFirst('');
		END;
		Dialog.Update(InfoDialog.param);
		Dialog.Update(TextCmds.find);
	END FindInIndex;

END InfoLook.
