############################################################################ # # File: fev.icn # # Subject: Program to display text in fisheye view # # Author: Clinton L. Jeffery # # Date: June 17, 1994 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # A text file browser that employs a fish-eye view. The # fish-eye view displays text in a larger font in the middle (focus) # gradually declining to tiny fonts at the top and bottom of the screen. # # "q" or ESC to quit. "n" slides the focus down one line # "p" slides the focus up one line. "w" widens the focus by one. # "W" narrows the focus by one. Mouse clicks move the focus to the line # on which the mouse is located; clicking in the left margin moves # in the file proportional to the mouse's y coordinate in the window. # ############################################################################ # # Requires: Version 9 graphics with X11R5 scalable fonts on the X server # ############################################################################ # # Links: wopen, xcompat # ############################################################################ link wopen link xcompat procedure main(av) local slope, fin, win, L, ht, focus, focuswidth, e, base slope := 2 if av[1] == "-s" then slope := (pop(av), pop(av)) fin := open(av[1]) | stop("no file") win := WOpen("label=" || av[1], "height=860") | stop("no window") L := [] every put(L,!fin) write(*L," lines") ht := 23 focus := *L/2 focuswidth := 1 fisheye(win,L,focus,ht,slope,,,focuswidth) repeat { e := Event(win) case e of { "q"|"\e": exit(0) "n" : focus := *L >= focus+1 "p" : focus := 1 <= focus - 1 "w" : focuswidth +:= 1 "W" : (1 < focuswidth) -:= 1 &lpress|&ldrag|&mpress|&mdrag|&rpress|&rdrag: { if &x < 17 then { focus := *L * &y / WAttrib(win,"height") } else { base := WAttrib(win,"height") / 2 focus := moveFocusToMouse(win,L,focus,base,ht,slope,focuswidth) } } default : next } fisheye(win,L,focus,ht,slope,,,focuswidth) } end procedure fisheye(w,L,focus,maxht,slope,family,weight,focuswidth) static fonttable local past_end, i, splt initial { fonttable := table() } /focuswidth := 1 /family := "helvetica" /weight := "bold" /fonttable[w] := [] past_end := *fonttable[w] + 1 every i := past_end to maxht do { put(fonttable[w], XBind(w,"font=-adobe-"||family||"-"||weight|| "-r-normal--"||i||"-*-*-*-*-*-*-*") | stop("no XBind")) } EraseArea(w) splt := WAttrib(w,"height") / 2 viewtop(fonttable[w],L,focus,splt,maxht,slope,focuswidth) viewbottom(fonttable[w],L,focus+1,splt+maxht,maxht-slope,slope,focuswidth) FillRectangle(w,0,(focus * WAttrib(w,"height") / *L)-WAttrib(w,"ascent"), 16,WAttrib(w,"fheight")) DrawLine(w,17,0,17,WAttrib(w,"height") * focuswidth) end procedure viewtop(w,L,focus,base,ht,slope,focuswidth) local wh wh := WAttrib(w[1],"height") | stop("no WAttrib") while focus >= 1 & base >= 1 do { if ht < 1 then ht := 1 GotoXY(w[1],20,base) writes(w[ht],L[focus]) base -:= ht if focus > 1 & base / focus < ht & focuswidth <= 1 then ht -:= slope focuswidth -:= 1 focus -:= 1 } if focus < 1 then return 1 return focus end procedure viewbottom(w,L,focus,base,ht,slope,focuswidth) local wh wh := WAttrib(w[1],"height") | stop("no WAttrib") while focus <= *L & base <= wh do { if ht < 1 then ht := 1 GotoXY(w[1],20,base) writes(w[ht],L[focus]) base +:= ht if focus < *L & (wh - base) / (*L - focus) < ht & focuswidth <= 1 then ht -:= slope focuswidth -:= 1 focus +:= 1 } if focus > *L then return *L return focus end procedure moveFocusToMouse(w,L,focus,base,ht,slope,focuswidth) local wh, fh wh := WAttrib(w,"height") | stop("no WAttrib") fh := WAttrib(w,"ascent") | stop("no WAttrib") if &y < base then { while focus >= 1 & base-fh >= &y do { if ht < 1 then ht := 1 base -:= ht if focus > 1 & base / focus < ht & focuswidth <= 1 then ht -:= slope focuswidth -:= 1 focus -:= 1 } } else { focus +:= 1 base +:= ht ht -:= slope while focus <= *L & base <= &y do { if ht < 1 then ht := 1 base +:= ht if focus < *L & (wh - base) / (*L - focus) < ht & focuswidth <= 1 then ht -:= slope focuswidth -:= 1 focus +:= 1 } } if focus < 1 then return 1 if focus > *L then return *L return focus end