% ============================= % % BROWSER.SIM % % Aout 97 v2.0 % ============================= ! Attention, ce programme suppose que les declarations de procedures et de classes ont leur prefixe, mot clef et suffixe sur la meme ligne. Exemples : integer procedure x myclass class myotherclass ------------------------------------------------------------------------; Begin EXTERNAL CLASS windowtools; EXTERNAL CLASS tokenizer; REF(dictionary) classes; REF(textarray) FileBuffer; FileTokenizer Class FILE_READER; BEGIN PROCEDURE get_sy; BEGIN getsy; IF symbol_is(comment_sy) THEN copy_to_pv; END; procedure copy_to_pv; begin while usc<>fdf_sy and then usc<>pv_sy do getsy; skip( pv_sy); end ** copy to pv ** ; Text procedure Standardize(T); text T; begin Text TT; Standardize :- TT :- lowcase(copy(T)); upcase(TT.sub(1,1)); end; procedure Readclass; BEGIN ref(classdcl) classObj; text Prefix; INTEGER niveau; BOOLEAN virt_attr; if symbol_is(ident_sy) then begin prefix :- Standardize(Token); get_sy; end; get_sy; classObj :- new classDcl( Standardize(Token) , prefix, nligne); classes.insert(classObj); copy_to_pv; WHILE symbol_in(virtual_spec) DO % WHILE symbol_in(simple_decl) OR symbol_in(spec_sy) DO copy_to_pv; IF symbol_is(virtual_sy) THEN BEGIN virt_attr:=TRUE; get_sy; !sauter le ':'; get_sy; WHILE virt_attr DO BEGIN virt_attr:=FALSE; IF symbol_is(decl_sy) OR symbol_is(ref_sy) THEN begin copy_to_pv; virt_attr:=TRUE; END ELSE IF symbol_is(procedure_sy) THEN BEGIN virt_attr:=TRUE; copy_to_pv; WHILE symbol_in(virtual_spec) DO % WHILE symbol_in(simple_decl) OR symbol_in(spec_sy) DO copy_to_pv; copy_to_pv; END; END; END; niveau:=1; IF symbol_is(begin_sy) THEN WHILE niveau>0 DO BEGIN get_sy; IF symbol_is(begin_sy) THEN niveau:=niveau+1 ELSE IF symbol_is(end_sy) THEN niveau:=niveau-1; END; classObj.lastline := nligne; copy_to_pv; END; PROCEDURE GetClasses; BEGIN WHILE NOT Symbol_is(fdf_sy) DO IF usc=external_sy THEN copy_to_pv ELSE IF (usc=class_sy) OR (usc = ident_sy AND PeekSy = class_sy) THEN BEGIN ReadClass; skip(pv_sy); END ELSE get_sy; Outline("============ File Read ==============="); Classes.dump; END; END --- FILE_READER --- ; tokenizer CLASS TextArrayTokenizer( FileBuffer, Line1, LineN ); ref( TextArray) FileBuffer; integer Line1, LineN; begin Integer LIne; Text procedure inLine; if Line <= LineN then begin inLIne :- FileBuffer.GET(line); Line := Line + 1; end --- inline ---; Boolean procedure EndFile; EndFile := Line > lineN ; procedure Reset; begin C := ' '; SymbCount := 0;; SQFirst :- SQLast :- none; Line := Line1; end; Reset; end ----- TextArrayTokenizer ------------ ; element class classDCL (ID,PrefixName,firstline); TEXT ID,PrefixName; INTEGER firstline; BEGIN INTEGER lastline; TEXT PROCEDURE key; key :- id; END; element CLASS class_name(classname);TEXT classname; BEGIN TEXT PROCEDURE key; key :- classname; REF(NodeButton) window_pointer; END; %include graph.sim menuscrollwindow CLASS StayMenuScrollWindow; BEGIN REF(button) quit; PROCEDURE ButtonClick_Handler(b);REF(Button) b; IF b==Cancel_button THEN parent.destroy; % PROCEDURE clickinbutton(b);REF(Button) b; % IF b==quit THEN parent.destroy; % PROCEDURE SelectionMade; % BEGIN % parent.LineChoice(choice); % parent.LineChoiceIn(choice, line, this ScrollWindow); % END; ok_button.SetHeading("Select"); Cancel_button.SetHeading("Quit"); % quit :- NEW Button(THIS XWindow,"Quit"); % quit.placebelow(ok_button); % quit.show; END; SideWindow CLASS ClassBrowserWindow; BEGIN REF(staymenuscrollwindow) menu; REF(scrollwindow) edit; PROCEDURE Selection_Handler(Window, Item, ItemN); Ref(XWindow) Window; Text Item; Integer ItemN; edit.ScrolllineTop(Item.Getint); % PROCEDURE LineChoice(choice);TEXT choice; % BEGIN % edit.ScrolllineTop(choice.Getint); % END; PROCEDURE handle_configure; IF menu =/= NONE THEN BEGIN menu.setwidth(width-2*subwindowspacing); edit.setsize(width - 2*subwindowspacing, height - 3*subwindowspacing-menu.height); END; PROCEDURE readclass(cl);REF(classdcl) cl; BEGIN TEXT textmenu; TEXT temp,w; BOOLEAN Readprocedure; BOOLEAN inComment; BOOLEAN InVirtual; INTEGER i,level,nblines; TEXT PROCEDURE getword(t);NAME t;TEXT t; BEGIN TEXT res,temp; CHARACTER c; BOOLEAN startword,endword; res :- Blanks(50); WHILE t.More AND NOT endword DO BEGIN c := t.GetChar; IF c='!' THEN InComment:=TRUE; IF c=';' THEN InComment:=FALSE; IF c <> ' ' AND c <> ';' AND c <> '(' AND NOT incomment THEN BEGIN startword := TRUE; IF NOT res.More THEN BEGIN temp:-Blanks(res.Length*1.5); temp:=res; res:-temp; END; res.PutChar(c); END ELSE IF startword THEN endword:=TRUE; END; getword:-res.strip; END; textmenu:-"+1:***BEGINNING***"; nblines:=1; FOR i:=cl.firstline STEP 1 UNTIL cl.lastline DO BEGIN temp :- filebuffer.get(i); IF temp.Length > 0 AND THEN temp.GetChar <> '%' THEN BEGIN temp.SetPos(1); WHILE temp.More DO BEGIN w :- getword(temp); IF LowCase(w)="virtual:" THEN invirtual:=TRUE; IF LowCase(w)="begin" THEN invirtual:=FALSE; IF readprocedure THEN BEGIN IF LowCase(w)="begin" THEN level:=level+1 ELSE IF LowCase(w)="end" THEN level:=level-1; IF level=0 THEN readprocedure:=FALSE; END; IF NOT invirtual AND THEN NOT readprocedure AND THEN level=0 AND THEN lowcase(w)="procedure" THEN BEGIN nblines:=nblines+1; readprocedure:=TRUE; textmenu :- textmenu&"+"&int_as_text(i-cl.firstline+1)&":"&getword(temp); END; END; END; edit.Initputline(temp); END; IF textmenu =/= NOTEXT THEN menu.SetMenu("Procedure",textmenu,NOTEXT); menu.setlines(if nblines < 3 then 3 else if nblines > 8 then 8 else nblines ); handle_configure; END; placecentered; setsubwindowspacing(0); menu :- NEW staymenuscrollwindow(THIS Xwindow); menu.setsize(600,300); menu.show; edit :- NEW scrollwindow(THIS XWindow); edit.setsize(600,300); edit.setTypeFace("courier",10,false,false); edit.placebelow(menu); edit.show; SetSizeToSubWindowSize; END; DrawWindow CLASS MapDrawWindow; BEGIN PROCEDURE refresh; parent QUA BrowserWindow.refreshmap; PROCEDURE handle_button_down(b);INTEGER b; parent QUA BrowserWindow.scroll(hor_invscale(x_of_event),ver_invscale(y_of_event)); button_sensitize; END; NodeWindow CLASS BrowserWindow; BEGIN REF(Button) quit,read; REF(MenuButton) switch_button; REF(directorymenu) menu; INTEGER virt_maxx,virt_maxy,virt_minx,virt_miny; INTEGER node_maxx,node_maxy,node_minx,node_miny; INTEGER scroff_x,scroff_y; REF(MapDrawWindow) MapWindow; BOOLEAN GraphCreated; PROCEDURE Selection_Handler(W,choix,N); Ref(XWindow) W; TEXT choix; INTEGER N; IF W==switch_button THEN BEGIN IF N=2 THEN allowdrag ELSE disallowdrag; END; % PROCEDURE Perform(choix);TEXT choix; % BEGIN % IF choix="graphe" THEN allowdrag % ELSE IF choix="classe" THEN disallowdrag; % END; PROCEDURE ButtonClick_Handler(b);REF(Button) b; % PROCEDURE ClickInButton(b);REF(Button) b; BEGIN TEXT choice; IF b==read THEN BEGIN choice :- GetFile("Choose File to Browse",notext); IF choice =/= NOTEXT THEN ReadFile(choice); IF choice =/= NOTEXT THEN CreateGraph; Clear; Refresh; IF graphcreated THEN switch_button.allow else switch_button.disallow END ELSE if (b in nodebutton) then BEGIN REF(classdcl) cl; IF NOT drag_allowed THEN BEGIN cl :- classes.find(b.heading); IF cl =/= NONE THEN launchclassbrowser(cl) ELSE TimedMessage("Description of this class is not in this file",2); END; END; END; PROCEDURE refreshmap; IF graphcreated THEN BEGIN INTEGER x1,y1,x2,y2; PROCEDURE DrawLineMap(x1,y1,x2,y2);INTEGER x1,y1,x2,y2; BEGIN MapWindow.DrawLineScaled(x1,y1,x2,y2); END; PROCEDURE maplink(e);REF(element) e; BEGIN e QUA nodebutton.upperpoint(x2,y2); Drawlinemap(x1,y1,x2,y2); END; PROCEDURE map(e);REF(element) e; BEGIN REF(Nodebutton) nw; nw :- e; Drawlinemap(nw.min_x,nw.min_y,nw.max_x,nw.min_y); Drawlinemap(nw.max_x,nw.min_y,nw.max_x,nw.max_y); Drawlinemap(nw.max_x,nw.max_y,nw.min_x,nw.max_y); Drawlinemap(nw.min_x,nw.max_y,nw.min_x,nw.min_y); nw.lowerpoint(x1,y1); nw.lower.for_each_element(maplink); END; MapWindow.Clear; Nodes.for_each_element(map); MapWindow.setforeground("gray25"); mapwindow.setlinewidth(2); Drawlinemap(0,0,width,0); Drawlinemap(width,0,width,height); Drawlinemap(width,height,0,height); Drawlinemap(0,height,0,0); mapwindow.setlinewidth(0); MapWindow.BlackGC; END; PROCEDURE scroll(x,y);INTEGER x,y; IF graphcreated then BEGIN INTEGER diff_x,diff_y; PROCEDURE move(e);REF(element) e; BEGIN REF(nodebutton) nb; nb :- e; nb.placeat(nb.min_x-diff_x,nb.min_y-diff_y); END; x:=Max(virt_minx,Min(virt_maxx-width,x-width//2)); y:=Max(virt_miny,Min(virt_maxy-height,y-height//2)); diff_x := x-virt_minx-scroff_x; diff_y := y-virt_miny-scroff_y; Nodes.for_each_element(move); RaiseWindows; scroff_x:=scroff_x+diff_x; scroff_y:=scroff_y+diff_y; node_minx:=node_minx-diff_x; node_maxx:=node_maxx-diff_x; node_miny:=node_miny-diff_y; node_maxy:=node_maxy-diff_y; SetScalesMapWindow; refresh; refreshmap; END; PROCEDURE CreateGraph; IF classes.is_empty THEN graphcreated:=FALSE ELSE BEGIN REF(dictionary) class_names; REF(sequence) top_nodes; INTEGER ARRAY Start(1:50); INTEGER i; BOOLEAN second_pass; PROCEDURE destroy_node(e);REF(element) e; e QUA Window.Destroy; PROCEDURE create_node(e);REF(element) e; BEGIN REF(classDcl) cl; REF(class_name) cn; cl :- e QUA classDcl; cn :- NEW class_name(cl.ID); cn.window_pointer :- MakeNodeButton(cl.ID); IF cl.prefixname==NOTEXT THEN top_nodes.insert(cn.window_pointer); class_names.insert(cn); END; PROCEDURE link_parent(e);REF(element) e; BEGIN REF(classDcl) cl; REF(class_name) cn; cl :- e QUA classDcl; IF cl.prefixname =/= NOTEXT THEN BEGIN cn :- class_names.find_element(cl.prefixname); IF cn==NONE THEN BEGIN cn :- NEW class_name(cl.prefixname); cn.window_pointer :- MakeNodeButton(cl.prefixname); top_nodes.insert(cn.window_pointer); class_names.insert(cn); END; class_names.find_element(cl.ID) QUA class_name. window_pointer.LinkParent(cn.window_pointer); END; END; INTEGER PROCEDURE Placer(nb,x,d);REF(NodeButton) nb;INTEGER x,d; BEGIN INTEGER total; INTEGER largeur; INTEGER decale_prof; INTEGER decale_x; PROCEDURE decale(e);REF(element) e; BEGIN REF(NodeButton) nb; nb :- e; % outtext("DECALE ***" & nb.heading); outimage; nb.placeat(nb.min_x+decale_x,nb.min_y); Start(decale_prof):=Max(Start(decale_prof),nb.mid_x+nb.width//2+nb.borderwidth+subwindowspacing); IF NOT nb.lower.is_empty THEN BEGIN decale_prof:=decale_prof+1; nb.lower.for_each(decale); decale_prof:=decale_prof-1; END; END; PROCEDURE cal_lar(e);REF(element) e; BEGIN largeur := largeur+e QUA nodebutton.width+e QUA nodebutton.borderwidth*2; END; PROCEDURE ess_pl(e);REF(element) e; BEGIN total := total+Placer(e,x-largeur//2+ (nb.lower.first QUA XWindow.width//2),d+1); END; x:=Max(x,Max(Start(d),subwindow_spacing)+nb.width//2+nb.borderwidth); IF NOT nb.lower.is_empty THEN BEGIN IF second_pass THEN largeur:=nb.lower.get(nb.lower.size) QUA nodebutton.max_x- nb.lower.First QUA nodebutton.min_x ELSE nb.lower.for_each(cal_lar); largeur:=largeur+(nb.lower.size-1)*subwindow_spacing; nb.lower.for_each(ess_pl); % IF NOT second_pass THEN x:=Max(total/nb.lower.size,Start(d)+nb.width//2+nb.borderwidth) % ELSE % BEGIN % x:=total/nb.lower.size; % IF Start(d)+nb.width//2+nb.borderwidth>x THEN % BEGIN % decale_prof:=d+1; % decale_x:=Start(d)+nb.width//2+nb.borderwidth-x; % nb.lower.for_each(decale); % x:=Start(d)+nb.width//2+nb.borderwidth; % END; % END; END; Start(d):=x+nb.width//2+nb.borderwidth+subwindow_spacing; nb.placeat(x-nb.width//2,d*(nb.height+subwindow_spacing+50)+20); Placer:=x; END; PROCEDURE show_node(e);REF (element) e; BEGIN REF(NodeButton) nb; nb:-e; Node_maxx := Max(Node_maxx,nb.max_x+nb.borderwidth+subwindow_spacing); Node_maxy := Max(Node_maxy,nb.max_y+nb.borderwidth+subwindow_spacing); Node_minx := Min(Node_minx,nb.min_x-nb.borderwidth-subwindow_spacing); Node_miny := Min(Node_miny,nb.min_y-nb.borderwidth-subwindow_spacing); nb.show; END; PROCEDURE pn(e);REF (element) e; Placer(e,0,1); class_names :- NEW dictionary; top_nodes :- NEW sequence; nodes.for_each_element(destroy_node); nodes :- NEW dictionary; Clear; classes.for_each_element(create_node); classes.for_each_element(link_parent); top_nodes.for_each_element(pn); i:=0; FOR i:=i+1 WHILE Start(i)>0 DO Start(i):=0; second_pass:=TRUE; node_maxx:=0; node_maxy:=0; node_minx:=MaxInt; node_miny:=MaxInt; top_nodes.for_each_element(pn); nodes.for_each_element(show_node); SetScalesMapWindow; scroff_x:=-virt_minx; scroff_y:=-virt_miny; RaiseWindows; GraphCreated:=TRUE; refreshmap; END; PROCEDURE SetScalesMapWindow; BEGIN INTEGER bordure=3; INTEGER rminx,rmaxx,rminy,rmaxy; REAL rappxy; INTEGER decale; virt_minx:=node_minx; virt_miny:=node_miny-quit.height-2*subwindowspacing; virt_maxx:=node_maxx; virt_maxy:=node_maxy; rminx:=bordure; rminy:=bordure; rmaxx:=mapwindow.width-bordure; rmaxy:=mapwindow.height-bordure; rappxy := ((virt_maxx-virt_minx)/(rmaxx-rminx))/((virt_maxy-virt_miny)/(rmaxy-rminy)); IF rappxy > 1.0 THEN !plus large; BEGIN decale:=(virt_maxy-virt_miny)*rappxy/2; virt_miny:=virt_miny-decale; virt_maxy:=virt_maxy+decale; END ELSE IF rappxy < 1.0 THEN !plus haut; BEGIN decale:=(virt_maxx-virt_minx)/rappxy/2; virt_minx:=virt_minx-decale; virt_maxx:=virt_maxx+decale; END; MapWindow.setscales(virt_minx,virt_miny,virt_maxx,virt_maxy,rminx,rminy,rmaxx,rmaxy); END; PROCEDURE StartDrag(sw);REF(SubWindow) sw; BEGIN EXTERNAL c PROCEDURE xungrabpointer IS PROCEDURE Xungrabpointer;; XUngrabPointer; sw.Raise; Drag:-sw; END; PROCEDURE StopDrag; IF drag=/=NONE THEN BEGIN INTEGER minx,miny; PROCEDURE check(e);REF(element) e; BEGIN REF(NodeButton) nb; nb :- e; node_minx:=Min(node_minx,nb.min_x-nb.borderwidth-subwindowspacing); node_miny:=Min(node_miny,nb.min_y-nb.borderwidth-subwindowspacing); node_maxx:=Max(node_maxx,nb.max_x+nb.borderwidth+subwindowspacing); node_maxy:=Max(node_maxy,nb.max_y+nb.borderwidth+subwindowspacing); END; node_minx:=MaxInt; node_miny:=MaxInt; node_maxx:=-MaxInt; node_maxy:=-Maxint; Nodes.for_each_element(check); minx:=virt_minx; miny:=virt_miny; SetScalesMapWindow; scroff_x:=scroff_x+minx-virt_minx; scroff_y:=scroff_y+miny-virt_miny; refreshmap; RaiseWindows; Drag :- NONE; END; PROCEDURE handle_configure; BEGIN refreshmap; END; PROCEDURE RaiseWindows; BEGIN mapwindow.raise; quit.raise; read.raise; switch_button.raise; END; PROCEDURE FillFileBuffer(filename);TEXT filename; BEGIN REF(InFile) input; TEXT t,ligne; Text Procedure InLigne; inspect input do begin Text T; Boolean OverFlow; OverFlow := inrecord; while OverFlow do begin T :- T & image; OverFlow := inrecord; end; InLigne :- T & image.sub(1,pos-1); end -- inligne -- ; input :- NEW Infile(filename); input.Open(Blanks(100)); FileBuffer :- NEW textarray; T :- inligne; WHILE not input.endfile do BEGIN fileBuffer.put(T); T :- inligne; END; input.Close; END --- FillFileBuffer ---; PROCEDURE ReadFile(filename);TEXT filename; BEGIN REF(InFile) input; REF(File_Reader) FR; Timedmessage("Reading File",1); FillFileBuffer(filename); classes :- NEW simple_set; input :- NEW Infile(filename); input.Open(Blanks(300)); FR :- new File_reader(input); FR.trace := 2; FR.get_sy; FR.getclasses; input.Close; END; PROCEDURE launchclassbrowser(cl); REF(Classdcl) cl; BEGIN REF(classBrowserWindow) clbwr; clbwr :- NEW ClassBrowserWindow("class : "&cl.ID,THIS mainwindow); clbwr.ReadClass(cl); clbwr.show; END; quit :- MakeButton("Quit"); read :- MakeButton("Read File"); switch_button :- NEW MenuButton(THIS XWindow,NOTEXT); switch_button.SetMenu("+Read Class+Edit Graph","Read Class"); switch_button.show.PlaceAfter(read); switch_button.Disallow; mapwindow :- NEW mapdrawwindow(THIS XWindow); mapwindow.setsize(200,75).placedownleft; mapwindow.show; END --- BrowserWindow --- ; INSPECT NEW BrowserWindow("Main") DO BEGIN SetSize(500,600); show; Message("Hi there suckers"); TimedMessage("WHY",1); quit.Wait; END; END