home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / contrib / menu / xmenu.S < prev   
Text File  |  1993-04-29  |  5KB  |  190 lines

  1. #
  2. # xmenu.icn
  3. # copyright 1992 Ronald Florence
  4. # @(#) version 1.1 (ron@mlfarm.com, 12 May 1992)
  5. #
  6. # main window:  
  7. #    left button to select recipe
  8. #    q, ^c, ^d to quit
  9. # recipe windows:
  10. #    <space>, m, or left button for more
  11. #    b or middle button for less
  12. #    p to print
  13. #    q or right button to return to main screen
  14. # .Xdefaults options:
  15. #    Xmenu.maxwin
  16. #    Xmenu.index
  17. #    Xmenu.datadir
  18. #    Xmenu.font
  19. # Configuration:
  20. #    Maxwin :    maximum # of lines in the windows
  21. #    indexfile:    full path of the indexfile
  22. #    Data_dir:    full path of directory with recipe files
  23. #    Font:        X-Windows display font
  24. #    Print_cmd:    pretty-printer and/or spooler; the name of
  25. #            the recipe will be substituted for %s
  26. #
  27.  
  28. link evmux, button, xdefault
  29. record rec_record (win, title, recipe, proc, but)
  30. global Data_dir, Maxwin, Font, Print_cmd, R, W
  31.  
  32. procedure main(arg)
  33.   local indexfile, pchar, hits, online, meta_keys, keys, xres,
  34.         egrep_cmd, k, m, found, r, index, winsize, title, but
  35.  
  36.   "X Windows" == &features | stop("Sorry, requires X-Windows.")
  37.   xres := xdefault("Xmenu")
  38.   Maxwin := \xres["maxwin"] | %MAXWIN%
  39.   indexfile := \xres["index"] | "%INDEXFILE%"
  40.   Data_dir := \xres["datadir"] | "%DATADIR%"
  41.   Font := \xres["font"] | "%FONT%"
  42.   Print_cmd := "%PRINTCMD%"
  43.  
  44.   (*arg > 0) | stop("usage: menu keyword [keyword,...]")
  45.   close(open(indexfile)) | stop("can't read indexfile")
  46.   pchar := &ascii[32:127]
  47.   hits := []
  48.   online := []
  49.   meta_keys := []
  50.   keys := []
  51.   egrep_cmd := "cat " || indexfile 
  52.   every k := !arg do put(if metas(k) then meta_keys else keys, map(k))
  53.   \meta_keys[1] | put(meta_keys, pop(keys))
  54.   every k := !meta_keys do egrep_cmd ||:= " | egrep -i '" || k || "'"
  55.   index := open(egrep_cmd || " 2>&1", "rp") 
  56.   every !index ? {
  57.     find("error"|"grep") & stop("search expression error")
  58.     m := map(&subject)
  59.     found := 1
  60.     every k := !keys do { find(k, m) | break found := &null }
  61.     \found & {
  62.       put(if match("Comp-", &subject) then online else hits, 
  63.       left(tab(many(pchar)), 20) || (tab(upto(pchar)), tab(many(pchar))))
  64.       tab(0)
  65.     }
  66.   }
  67.   *hits + *online = 0 & stop("No matching recipes.")
  68.   (winsize := *online * 2 + *hits + 1) <= Maxwin | {
  69.     hits |||:= online
  70.     online := []
  71.     winsize := *hits + 1
  72.   }
  73.   winsize >=:= Maxwin
  74.   W := open("menu", "x", "font=" || Font, "cursor=off", "lines=" || winsize,
  75.         "columns=80") | stop("no window")
  76.   quitsensor(W)
  77.   if *hits > winsize then page(W, hits, "menu")
  78.   else {
  79.     every write(W, !hits)
  80.    (*online > 0) | evhandle(W)
  81.   }
  82.   R := table()
  83.  
  84.   every !online ? {
  85.     ="Comp-"
  86.     r := tab(many(&digits))
  87.     title := (tab(many(' \t')), tab(0))
  88.     but := button(W, r, setup, r, XAttrib(W, "x"), XAttrib(W, "y"), 70, 20)
  89.     XGotoRC(W, XAttrib(W, "row"), 21)
  90.     write(W, title)
  91.     R[r] := rec_record (&null, title, [], &null, but)
  92.   }
  93.   if *online > 0 then evmux(W)
  94. end 
  95.  
  96.  
  97. procedure setup(win, r)
  98.   local rpath, rf, heading
  99.  
  100.   if *R[r].recipe = 0 then {
  101.     rpath := Data_dir || r
  102.     rf := open(rpath) | open("zcat " || rpath || ".Z", "rp") | 
  103.     return writes("\^g")
  104.     every put(R[r].recipe, !rf)
  105.     close(rf)
  106.   }
  107.   if /R[r].win then {
  108.     heading := R[r].title || " [" || r || "]"
  109.     R[r].win := open(heading, "x", "font=" || Font, "cursor=off",
  110.          "lines=" || (Maxwin > (*R[r].recipe + 2) | Maxwin), 
  111.          "columns=80") | stop("no page window")
  112.     shadebutton(R[r].but)
  113.     R[r].proc := create page(R[r].win, R[r].recipe, R[r].title)
  114.   }
  115.   @R[r].proc | (R[r].win := &null)
  116. end
  117.   
  118.  
  119. procedure page(win, rec, title)
  120.   local base, x, k, i, e, lines
  121.  
  122.   lines := XAttrib(win, "lines")
  123.   base := 0
  124.   repeat {
  125.     XClearArea(win)
  126.     XGotoRC(win,1,1)
  127.     every i := 0 to lines - 2 do {
  128.       if i + base < *rec then writes(win, rec[i+base+1])
  129.       write(win)
  130.     }
  131.     if lines = Maxwin then {
  132.       XAttrib(win, "reverse=on")
  133.       writes(win, "--More--(", ((100 > (base+lines-2) * 100/*rec) | 100), "%)")
  134.       XAttrib(win, "reverse=off")
  135.     }
  136.     case (x := XActive()) of {
  137.       win : &null
  138.       W : @&main
  139.       default: every k := key(R) do if (x === R[k].win) then break @R[k].proc
  140.     }
  141.     if type(e := XEvent(win)) == "integer" then XEvent(win)
  142.     else e := map(e)
  143.     case e of {
  144.       " "|"m"|&lpress: base := *rec > (base+lines-2)
  145.       "b"|&mpress: base := (0 < (base-lines+2) | 0)
  146.       "q"|&rpress: close(win) & fail
  147.       "p": print(rec, title)
  148.     }
  149.   }
  150. end
  151.         
  152.  
  153. procedure print(recipe, head)
  154.   local prn, rp
  155.  
  156.   Print_cmd ? {
  157.     prn := (\tab(find("%s")) || head) | tab(0)
  158.     move(2) & prn ||:= tab(0)
  159.   }
  160.   rp := open(prn, "wp")
  161.   every write(rp, !recipe)
  162.   return close(rp)
  163. end
  164.  
  165.  
  166. procedure metas(str)
  167.  
  168.   str ? {
  169.     tab(many('*+?|'))        # initials don't count
  170.     while tab(upto('\\*+()|?.$^[')) do {
  171.                 # a naked backslash is NG
  172.       if ="\\" then move(1) | stop("badly-formed search string")
  173.       else return .&pos
  174.     }
  175.   }
  176.   fail
  177. end
  178.  
  179.  
  180. procedure shadebutton(b)
  181.  
  182.   XAttrib(W, "fillstyle=opaquestippled")
  183.   XSetStipple(W, 4, 10, 7, 5, 15)
  184.   XFillRectangle(b.win, b.x+1, b.y+1, b.w-1, b.h-1)
  185.   XGotoXY(b.win, b.lx, b.ly)
  186.   writes(b.win, b.label)
  187. end
  188.  
  189.  
  190.