home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
me34src.zip
/
me3
/
mutt
/
builtin
/
popup.mut
< prev
next >
Wrap
Lisp/Scheme
|
1995-01-14
|
10KB
|
377 lines
;; popup.mut : put a popup window on the screen
;; The window is transient - it goes away on redraw.
;; ME knows nothing about the window
;; C Durland
(include max.mut)
(include me.mh)
(const
UPPER-LEFT-CORNER "." UPPER-RIGHT-CORNER "."
LEFT-SIDE "|" RIGHT-SIDE "|"
LOWER-LEFT-CORNER "`" LOWER-RIGHT-CORNER "'"
HEDGES "--------------------------------------------------------------------------------"
BLANKS " "
)
(const MPICKER ">") ;; query menu pointer
(small-int ulrow ulcol brow bcol)
(defun
popup-window (int row col width length)
{
(int j r)
(ulrow (brow (+ row 1)))(ulcol (bcol (+ col 1)))
(move-cursor row col)
(puts UPPER-LEFT-CORNER (extract-elements HEDGES 0 width)
UPPER-RIGHT-CORNER)
(for {(r ulrow)(j 0)} (< j length) {(+= j 1)(+= r 1)}
{
(move-cursor r col)
(puts LEFT-SIDE (extract-elements BLANKS 0 width) RIGHT-SIDE)
})
(move-cursor r col)
(puts LOWER-LEFT-CORNER (extract-elements HEDGES 0 width)
LOWER-RIGHT-CORNER)
}
wputs (string msg)
{
(move-cursor brow bcol)(puts msg)
(+= brow 1)
}
)
(defun
xpopup-window (int row col width length)
{
(int j r)
(ulrow (brow (+ row 1)))(ulcol (bcol (+ col 1)))
(move-cursor row col
(concat UPPER-LEFT-CORNER (extract-elements HEDGES 0 width)
UPPER-RIGHT-CORNER))
(for {(r ulrow)(j 0)} (< j length) {(+= j 1)(+= r 1)}
(move-cursor r col
(concat LEFT-SIDE (extract-elements BLANKS 0 width) RIGHT-SIDE)))
(move-cursor r col
(concat LOWER-LEFT-CORNER (extract-elements HEDGES 0 width)
LOWER-RIGHT-CORNER))
}
xwputs (string msg)
{
(move-cursor brow bcol msg)
(+= brow 1)
}
)
;******************************************************************************;
;*** ***;
;** . . M E N U - B O X **;
;*** ***;
;******************************************************************************;
; Desc: Draw one or more boxes justified to the top right corner of the screen.
; Each parameter represents a line in the box.
; The box width is ajusted to the max width of the lines to be
; contained in the current box.
; If a box does not fit vertically, it is broken in 2 boxes.
; Some lines (parameters) have special effect:
; '' Close current box and open a new box in the next column.
; To have a blank line, just use ' '.
; '-' Is replaced by a solid line across the box.
; '>xxxx' xxxx is centered in the box.
;
; Use : For popup menus
; Call: (menu-box text text ...)
; Author: Original idea and code from Michel St-Louis, rewritten by C Durland
(const
BOX-OVERLAP 2 ;; 1 (share borders) or 2 (don't share)
BOX-MAX-LENGTH 3 ;; 4 (don't cover modeline), 3 (go ahead)
)
(defun
menu-box { (do-menu-box (floc popup-window) (floc wputs) (push-args 0)) }
xmenu-box { (do-menu-box (floc xpopup-window) (floc xwputs) (push-args 0)) }
)
(array small-int box-width 10 box-length 10)
(int boxes popup-left-edge)
(defun do-menu-box (pointer defun popup-window wputs) HIDDEN
{
(int i j k w l max-length left-edge total-width)
(max-length (- (screen-length) BOX-MAX-LENGTH))
(for {(j 2) (total-width (boxes (w (l 0))))} (< j (nargs)) (+= j 1)
{
(w (max w (length-of (arg j))))
(if (or (== "" (arg j)) (== (+= l 1) max-length)) ;; need another box
{
(box-width boxes w)(box-length boxes l)
(if (== (nargs) (+ j 1)) (continue)) ;; last entry
(+= boxes 1)
(+= total-width (+ w BOX-OVERLAP))
(w (l 0))
})
})
(box-width boxes w)(box-length boxes l)(+= boxes 1)
(+= total-width (+ w 2))
(popup-left-edge (left-edge (max 0 (- (screen-width) total-width))))
(for {(i 0)(j 2)} (< i boxes) (+= i 1)
{
(popup-window 0 left-edge (box-width i) (box-length i))
(+= left-edge (box-width i) BOX-OVERLAP)
(if (== "" (arg j)) (+= j 1))
(for (k 0) (< k (box-length i)) { (+= k 1)(+= j 1) }
(wputs
(cond
(== '-' (arg j)) (extract-elements HEDGES 0 (box-width i))
(== '>' (extract-elements (arg j) 0 1))
(concat
(extract-elements BLANKS 0
(/ (- (box-width i) (length-of (arg j))) 2))
(extract-elements (arg j) 1 100))
TRUE (arg j)
)))
})
})
;******************************************************************************
;*** ***
;** Popup Menus **
;*** ***
;******************************************************************************
;; Use it like so:
;; (query-menu <entry-to-start-cusor-on>
;; (floc "<get-action>") (floc "<call-back>") entry ...)
;; TRUE is returned if an entry is selected, FALSE otherwise.
;; The call-back routine is called when an entry is selected. It is a
;; routine you define:
;; (defun my-call-back (int nth-entry)(string entry-name)
;; {
;; (msg "Entry selected: " entry-name)
;; })
;; Input:
;; get-action : Pointer to routine used to query user and return an
;; action. You can use (floc "menu-get-action") for a default.
;; call-back : Pointer to routine that is called when a menu entry is
;; selected.
;; entry : A bunch of strings that make up the menu entries. Same format
;; as for menu-box.
;; Returns:
;; TRUE : Entry selected, call-back called, etc.
;; FALSE : User quit
;; abort :
(const
MENU-NOOP 0
MENU-SELECT 1
MENU-SELECTED 2
)
(bool menu-not-done menu-return-code)
(small-int row column the-box menu-keymap global-keymap menu-do-what)
(defun
MAIN
{
(bind-key (menu-keymap (create-keymap))
"menu-down" "j"
"menu-down" "C-n"
"menu-down" "F-D" ;; down arrow
"menu-up" "k"
"menu-up" "C-p"
"menu-up" "F-C" ;; up arrow
"menu-end" "M->"
"menu-end" "F-B" ;; end
"menu-top" "M-<"
"menu-top" "F-A" ;; home
"menu-quit" "q"
"menu-abort" "Q"
"menu-abort" "C-g"
"menu-select" "C-m"
"menu-select" "F-N" ;; select
"ack-do-mouse" "S-m" ;; From the mouse driver
"menu-mouse-select" "S-1" ;; mouse button 1
)
}
xquery-menu (int first)
(pointer defun get-action call-back) (string text) ; ...
{ (query-menu first call-back (push-args 3)) }
query-menu (int first) (pointer defun call-back) (string text) ; ...
{
(int b)
(if (pgm-exists "keymap-special") (keymap-special menu-keymap))
(xmenu-box (push-args 2))
(the-box 0)(row 0)(column popup-left-edge)
(move-pick first 1)
(global-keymap (install-keymap GLOBAL-KEYMAP))
(install-keymap menu-keymap GLOBAL-KEYMAP)
;(install-keymap NULL-KEYMAP LOCAL-KEYMAP)
(current-buffer (create-buffer "*menu*"))
(buffer-read-only TRUE)
(menu-do-what MENU-NOOP)(menu-return-code FALSE)(menu-not-done TRUE)
(while { (exe-key (get-key)) menu-not-done } ())
(menu-restore)
(switch menu-do-what
MENU-SELECT (send-the-pick (push-args 1))
MENU-SELECTED
(menu-send-selected call-back (arg-prefix) (arg (+ 2 (arg-prefix))))
)
menu-return-code
}
ack-do-mouse
{
(install-keymap global-keymap GLOBAL-KEYMAP)
(if (load-code "mouse" FALSE TRUE)
{
(install-keymap menu-keymap GLOBAL-KEYMAP)
(floc "do-mouse" ())
}
{
(install-keymap menu-keymap GLOBAL-KEYMAP)
(msg "popup: Could not load mouse")
})
}
menu-restore
{
(install-keymap global-keymap GLOBAL-KEYMAP)
}
menu-down { (move-pick 1 1) }
menu-up { (move-pick 1 -1) }
menu-end { (move-pick-to-end) }
menu-top { (move-pick-to-start) }
menu-quit { (menu-not-done FALSE) }
menu-stop { (msg "Exiting menu system")(menu-restore)(halt) }
menu-abort { (menu-restore)(abort) }
menu-select
{
(menu-do-what MENU-SELECT)
(menu-return-code TRUE)
(menu-quit)
}
menu-selected
{
(menu-do-what MENU-SELECTED)
(menu-return-code TRUE)
(menu-quit)
}
menu-mouse-select
{
(small-int button mrow mcol state modifiers) ;; MouseInfo
(int dir last-row)
(mouse-info (loc button))
(-= mrow 2) ;; 1 for menu border, 1 because first row is 0
;(msg ">>>" row " " mrow)(get-key)
(dir (if (< mrow row) -1 1))(last-row row)
(while (!= mrow row)
{
(move-pick 1 dir)
(if (== last-row row) (done))
(last-row row)
})
(menu-select)
}
picket (int r c)(string thing) HIDDEN { (move-cursor (+ 1 r) c thing) }
move-pick (int n tick) HIDDEN
{
(int i)
(picket row column LEFT-SIDE)
(i n)
(while (!= 0 i)
{
(-= i 1)
(+= row tick)
(cond
(< row 0)
{
(if (< 0 the-box)
{
(-= the-box 1)
(-= column (box-width the-box) 2)
(row (- (box-length the-box) 1))
}
(row 0))
}
(== row (box-length the-box))
{
(if (< the-box (- boxes 1))
{
(row 0)
(+= column (box-width the-box) 2)
(+= the-box 1)
}
(row (- (box-length the-box) 1)))
}
)
})
(picket row column MPICKER)
}
move-pick-to-end HIDDEN
{
(picket row column LEFT-SIDE)
(row (- (box-length the-box) 1))
(picket row column MPICKER)
}
move-pick-to-start HIDDEN
{
(picket row column LEFT-SIDE)
(row 0)
(picket row column MPICKER)
}
menu-send-selected (pointer defun call-back) (int n) (string selection)
HIDDEN
{
(call-back n
(if (== '>' (extract-elements selection 0 1))
(extract-elements selection 1 100)
selection))
}
send-the-pick (pointer defun call-back) ; (string ...)
HIDDEN
{
(int j n b)
(n 0)(b 0)
(for (j 1) (< j (nargs)) (+= j 1)
{
(if (== "" (arg j)) (continue))
(if (== n (box-length b)) { (+= b 1) (n 0) })
(if (and (== b the-box)(== n row))
{
(menu-send-selected call-back (- j 1) (arg j))
(done)
})
(+= n 1)
})
(call-back -1 "")
}
)