summaryrefslogtreecommitdiff
path: root/ipl/gpacks/vib
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-01-27 23:51:56 +0000
committerIgor Pashev <pashev.igor@gmail.com>2013-01-27 23:51:56 +0000
commit6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1 (patch)
tree926065cf45450116098db664e3c61dced9e1f21a /ipl/gpacks/vib
downloadicon-6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1.tar.gz
Initial upstream version 9.4.3upstream/9.4.3
Diffstat (limited to 'ipl/gpacks/vib')
-rw-r--r--ipl/gpacks/vib/Makefile35
-rw-r--r--ipl/gpacks/vib/busy.icn144
-rw-r--r--ipl/gpacks/vib/dlog.icn40
-rw-r--r--ipl/gpacks/vib/vib.icn318
-rw-r--r--ipl/gpacks/vib/vibbttn.icn220
-rw-r--r--ipl/gpacks/vib/vibdefn.icn75
-rw-r--r--ipl/gpacks/vib/vibedit.icn922
-rw-r--r--ipl/gpacks/vib/vibfile.icn603
-rw-r--r--ipl/gpacks/vib/vibglbl.icn38
-rw-r--r--ipl/gpacks/vib/viblabel.icn125
-rw-r--r--ipl/gpacks/vib/vibline.icn197
-rw-r--r--ipl/gpacks/vib/viblist.icn168
-rw-r--r--ipl/gpacks/vib/vibmenu.icn468
-rw-r--r--ipl/gpacks/vib/vibradio.icn209
-rw-r--r--ipl/gpacks/vib/vibrect.icn135
-rw-r--r--ipl/gpacks/vib/vibsizer.icn197
-rw-r--r--ipl/gpacks/vib/vibslidr.icn207
-rw-r--r--ipl/gpacks/vib/vibtalk.icn193
-rw-r--r--ipl/gpacks/vib/vibtext.icn163
19 files changed, 4457 insertions, 0 deletions
diff --git a/ipl/gpacks/vib/Makefile b/ipl/gpacks/vib/Makefile
new file mode 100644
index 0000000..69283df
--- /dev/null
+++ b/ipl/gpacks/vib/Makefile
@@ -0,0 +1,35 @@
+# Makefile for vib, the Visual Interface Builder
+
+ICONT = icont
+IFLAGS = -us
+ITRAN = $(ICONT) $(IFLAGS)
+
+OBJ = vib.u2 vibbttn.u2 vibedit.u2 vibfile.u2 vibglbl.u2 \
+ viblabel.u2 vibline.u2 viblist.u2 vibmenu.u2 vibradio.u2 \
+ vibrect.u2 vibsizer.u2 vibslidr.u2 vibtalk.u2 vibtext.u2
+
+.SUFFIXES: .icn .u2 .gif .ps
+
+.icn.u2: ; $(ITRAN) -c $<
+.icn: ; $(ITRAN) $<
+
+.gif.ps:
+ giftoppm $< | ppmtopgm | pnmtops -scale .75 >$@
+
+vib: $(OBJ)
+ $(ITRAN) -o vib $(OBJ)
+
+$(OBJ): vibdefn.icn
+
+
+ipd doc: ipd265.ps
+
+ipd265.ps: ipd265.bibl fig1.ps fig2.ps
+ bib -t stdn -p /r/che/usr/ralph/docs/reg.index <ipd265.bibl | \
+ psfig | psroff -t >ipd265.ps
+
+Iexe: vib
+ cp vib ../../iexe/
+
+clean Clean:
+ rm -f vib *.ps *.u[12] app vibpro* core busy dlog
diff --git a/ipl/gpacks/vib/busy.icn b/ipl/gpacks/vib/busy.icn
new file mode 100644
index 0000000..da3095f
--- /dev/null
+++ b/ipl/gpacks/vib/busy.icn
@@ -0,0 +1,144 @@
+# busy.icn -- vib application demo and tester
+#
+# A complex user interface that does nothing useful
+# (except to assist in testing VIB)
+
+link vsetup
+
+global vidgets
+
+
+# main procedure
+
+procedure main(args)
+
+ vidgets := ui(args, cbk) # set up vidgets
+
+ VSetItems(vidgets["list1"],
+ ["Select", " your", "custom", "pizza", "below"])
+ VSetItems(vidgets["list2"],
+ ["individual", "small", "medium", "large", "family"])
+ VSetItems(vidgets["list3"],
+ ["anchovies", "bacon", "black olive", "bell pepper", "broccoli",
+ "capicolla", "garlic", "green olive", "linguisa", "mushroom", "onion",
+ "pepperoni", "pineapple", "sausage", "spinach", "tomato", "extra cheese"])
+
+ GetEvents(vidgets["root"], quitcheck) # enter event loop
+end
+
+
+# quitcheck() -- handle events that fall outside the vidgets
+
+procedure quitcheck(e)
+ if e === QuitEvents() then
+ exit()
+ else
+ write("unhandled event: ", image(e))
+end
+
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure ui_atts()
+ return ["size=490,401", "bg=pale gray", "label=An Icon Busy-Box"]
+end
+
+procedure ui(win, cbk)
+return vsetup(win, cbk,
+ [":Sizer:::0,0,490,401:An Icon Busy-Box",],
+ ["DUMP:Button:regular::11,31,73,20:DUMP",dump],
+ ["QUIT:Button:regular::11,56,73,20:QUIT",quit],
+ ["Toggles:Label:::25,159,49,13:Toggles",],
+ ["b1:Button:regular::129,189,28,27:1",],
+ ["b2:Button:regular::129,216,28,27:2",],
+ ["b3:Button:regular::129,243,28,27:3",],
+ ["b4:Button:regular::129,270,28,27:4",],
+ ["b5:Button:regular::129,297,28,27:5",],
+ ["check1:Button:xbox:1:21,282,37,37:",],
+ ["checko:Button:check:1:123,108,69,20:checko",],
+ ["circlo:Button:circle:1:123,83,69,20:circlo",],
+ ["line1:Line:::128,154,186,171:",],
+ ["line2:Line:::131,147,189,164:",],
+ ["line3:Line:::12,24,150,24:",],
+ ["list1:List:r::350,10,120,115:",],
+ ["list2:List:w::350,141,120,115:",],
+ ["list3:List:a::350,274,120,115:",],
+ ["menu1:Menu:pull::12,110,71,21:Food Menu",foodhandler,
+ ["American",
+ ["Burgers","Barbecue","Tex-Mex","Creole","New England"],
+ "Chinese",
+ ["Cantonese","Mandarin","Szechuan"],
+ "Greek","Italian",
+ ["Pasta","Pizza","Sandwiches",
+ ["Grinder","Hoagie","Poor Boy","Submarine"]],
+ "Mexican",
+ ["Sonoran","Chihuahuan","Angelino","Taco Bell"],
+ "Japanese","Korean","French","German","English",
+ "Scottish","Irish"]],
+ ["sbar1:Scrollbar:v:1:316,10,18,379:77,22,66",],
+ ["sbar2:Scrollbar:h::20,345,280,18:999,1,777",],
+ ["slider1:Slider:h::20,369,280,18:0,1000,200",],
+ ["slider2:Slider:v:1:290,10,18,312:33,67,44",],
+ ["stations:Choice::5:204,83,57,105:",,
+ ["KUAT","KUAZ","KXCI","KJZZ","WOI"]],
+ ["tcheck:Button:checkno:1:23,235,62,20:check",],
+ ["tcircle:Button:circleno:1:22,256,69,20:circle",],
+ ["text:Text::12:122,54,157,19:password:\\=swordfish",],
+ ["title1:Label:::11,10,126,13:Some VIB Experimen",],
+ ["title2:Label:::137,10,14,13:ts",],
+ ["tline:Line:::26,181,92,181:",],
+ ["tregular:Button:regular:1:23,189,56,20:regular",],
+ ["tsimple:Button:regularno:1:24,213,77,20:no-outline",],
+ ["xgrooved:Button:xboxno:1:64,284,33,33:",],
+ ["rectx:Rect:grooved::62,282,37,37:",],
+ ["rect1:Rect:grooved::188,202,30,50:",],
+ ["rect2:Rect:sunken::229,201,30,50:",],
+ ["rect3:Rect:raised::188,263,30,50:",],
+ ["rect4:Rect:invisible::230,263,30,50:",],
+ ["trect:Rect:grooved::12,151,98,176:",],
+ )
+end
+#===<<vib:end>>=== end of section maintained by vib
+
+
+procedure cbk(v, x)
+ writes("CALLBACK: ")
+ VEcho(v, x)
+ return
+end
+
+procedure foodhandler(v, x)
+ writes("FOOD: ")
+ every writes(" ", !x)
+ write()
+ return
+end
+
+procedure dump(v, x)
+ local l, id
+
+ write()
+ write("key v.id VGetState(v) image(v)")
+ write("--------- --------- ------------ -----------------------------")
+ l := sort(vidgets, 3)
+ while id := get(l) do {
+ v := get(l)
+ write(left(\id | "**NULL**", 12), left(\v.id | "**NULL**", 12),
+ left(vimage(VGetState(v)) | "---", 15), image(v))
+ }
+ write()
+ return
+end
+
+procedure vimage(a)
+ local s
+
+ if (type(a) ~== "list") then
+ return image(a)
+ s := "["
+ every s ||:= image(!a) || ","
+ return s[1:-1] || "]"
+end
+
+procedure quit(v, x)
+ exit()
+end
diff --git a/ipl/gpacks/vib/dlog.icn b/ipl/gpacks/vib/dlog.icn
new file mode 100644
index 0000000..13dc394
--- /dev/null
+++ b/ipl/gpacks/vib/dlog.icn
@@ -0,0 +1,40 @@
+# dlog.icn -- VIB dialog box demo and test program
+
+procedure main(args)
+ Window("font=sans,bold,24", args)
+ WAttrib("fillstyle=textured", "pattern=grains")
+ FillRectangle()
+ WAttrib("fillstyle=solid")
+ CenterString(247, 102, "Dialog Box Test")
+ Fg("white")
+ CenterString(250, 100, "Dialog Box Test")
+ while dl() ~== "quit"
+end
+
+link dsetup
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure dl(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ [":Sizer::1:0,0,270,300:",],
+ ["checkbox:Button:check:1:29,52,83,20:checkbox",],
+ ["line:Line:::15,233,255,233:",],
+ ["ne:Button:regular:1:235,0,35,20:ne",],
+ ["nw:Button:regular:1:0,0,35,20:nw",],
+ ["quit:Button:regular::137,257,49,20:quit",],
+ ["radio:Choice::4:180,49,57,84:",,
+ ["KUAT","KUAZ","KMCI","KJZZ"]],
+ ["repeat:Button:regular:-1:70,256,49,20:repeat",],
+ ["scroller:Scrollbar:h:1:35,183,200,18:0.0,1.0,0.5",],
+ ["se:Button:regular:1:235,280,35,20:se",],
+ ["slider:Slider:h:1:35,154,200,18:0.0,1.0,0.5",],
+ ["sw:Button:regular:1:0,280,35,20:sw",],
+ ["text:Text::11:34,112,122,19:Text:\\=",],
+ ["title:Label:::73,17,105,13:Dialog Box Test",],
+ ["xbox:Button:xbox:1:30,80,25,25:",],
+ ["xlabel:Label:::65,85,28,13:xbox",],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/vib.icn b/ipl/gpacks/vib/vib.icn
new file mode 100644
index 0000000..1423036
--- /dev/null
+++ b/ipl/gpacks/vib/vib.icn
@@ -0,0 +1,318 @@
+############################################################################
+#
+# File: vib.icn
+#
+# Subject: Program to build Icon interfaces
+#
+# Authors: Mary Cameron and Gregg M. Townsend
+#
+# Date: May 25, 2001
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+#
+# For documentation, see IPD284:
+# http://www.cs.arizona.edu/icon/docs/ipd284.htm
+#
+############################################################################
+
+# Version 1 (XIB): Original version
+# Version 2 (VIB): Compact specifications in same file as source
+# Version 3 (VIB, Dec 94): 3-D appearance, uses VIB for own dialogs
+# Oct 96: add list vidget
+
+$include "keysyms.icn"
+$include "vdefns.icn"
+$include "vibdefn.icn"
+
+link drag
+link dsetup
+link graphics
+link vsetup
+link interact
+
+link vibbttn
+link vibedit
+link vibfile
+link vibglbl
+link viblabel
+link vibline
+link viblist
+link vibmenu
+link vibradio
+link vibrect
+link vibsizer
+link vibslidr
+link vibtalk
+link vibtext
+
+global CHOSEN # object picked from Select menu
+
+############################################################################
+# main() opens a window, creates the palette and menus, initializes
+# global variables, and starts up the WIT event loop.
+############################################################################
+procedure main(args)
+ local edit_menu, file_menu, x, y
+
+ Window("size=640,480", "label= ", args)
+
+ &error := 1
+ WAttrib("resize=on")
+ &error := 0
+
+ VSetFont()
+ APPWIN := Clone() | stop("can't clone window")
+ XORWIN := Clone("drawop=reverse") | stop("can't clone window")
+
+ SESSION := def_extn("" ~== args[1]) | newname()
+ label_session()
+
+ PAD := WAttrib("fheight") + 6
+ LBMASK := &ascii[32+:95] -- '\"\\'
+ IDMASK := &ascii[32+:95] -- '\"\\:'
+ CBMASK := &letters ++ &digits ++ '_'
+
+ O_LIST := []
+ P_LIST := []
+ SIZER := create_sizer()
+
+ ROOT := Vroot_frame(&window)
+ edit_menu := Vsub_menu(&window,
+ "copy @C", menu_cb,
+ "delete @X", menu_cb,
+ "undelete @U", menu_cb,
+ "align vert @V", menu_cb,
+ "align horz @H", menu_cb)
+ file_menu := Vsub_menu(&window,
+ "new @N", menu_cb,
+ "open @O", menu_cb,
+ "save @S", menu_cb,
+ "save as ", menu_cb,
+ "refresh @R", menu_cb,
+ "prototype @P", menu_cb,
+ "quit @Q", menu_cb)
+ MENUBAR := Vmenu_bar(&window, "File ", file_menu, "Edit ", edit_menu)
+ VInsert(ROOT, MENUBAR, 0, 0)
+ SELECT := Vpane(&window, select_cb, , , TextWidth("Select") + 8, MENUBAR.ah)
+ VInsert(ROOT, SELECT, MENUBAR.aw, 0)
+
+ dialogue()
+
+ VResize(ROOT)
+ CANVASY := MENUBAR.ah + 3 + PAL_H + 4
+ Clip(APPWIN, 0, CANVASY, 9999, 9999)
+
+ DRAGWIN := Clone(APPWIN, "bg=blackish gray") | stop("can't clone APPWIN")
+
+ create_palette()
+
+ if not (args[1] & load_session(SESSION)) then {
+ draw_header()
+ draw_canvas()
+ }
+
+ GetEvents(ROOT, vib_event_loop)
+end
+
+############################################################################
+# menu_cb() is the callback routine for the file and edit menus.
+############################################################################
+procedure menu_cb(wit, value)
+ local cmd
+
+ cmd := trim(value[1] ? tab(upto('@') | 0))
+ case cmd of {
+
+ # file menu
+ "n" | "new" : new_session()
+ "o" | "open" : if flush_session() then open_session()
+ "s" | "save" : save_session(SESSION)
+ "save as" : vib_save_as("file to save: ", "")
+ "r" | "refresh" : redraw_screen()
+ "p" | "prototype" : prototype()
+ "q" | "quit" : if flush_session() then exit()
+
+ # edit menu
+ "c" | "d" | "copy" : copy_focus()
+ "x" | "\d" | "delete" : delete_focus()
+ "u" | "undelete" : undelete()
+ "v" | "align vert" : if \FOCUS then set_align("alignv")
+ "h" | "align horz" : if \FOCUS then set_align("alignh")
+ }
+end
+
+############################################################################
+# select_cb() is the callback routine for the Select pseudo-menu.
+############################################################################
+procedure select_cb(wit, ev)
+ local i, idlist, mlist, smenu, obj
+
+ if not (ev === (&lpress | &ldrag | &mpress | &mdrag | &rpress | &rdrag)) then
+ return
+
+ idlist := set()
+ every insert(idlist, (!O_LIST).id)
+ idlist := sort(idlist)
+
+ mlist := [&window]
+ every put(mlist, !idlist, choice_cb)
+ smenu := Vmenu_bar_item(&window, "Select", , , , , Vsub_menu ! mlist)
+ VInsert(ROOT, smenu, wit.ax, wit.ay)
+ VResize(smenu)
+
+ CHOSEN := &null
+ VEvent(smenu, &lpress)
+ VRemove(ROOT, smenu, 1)
+
+ if \CHOSEN then
+ every obj := !O_LIST do
+ if obj.id == CHOSEN then {
+ focus_object(obj)
+ break
+ }
+ return
+end
+
+############################################################################
+# choice_cb() is the callback routine for a chosen Select entry.
+############################################################################
+procedure choice_cb(wit, value)
+ CHOSEN := value[1]
+end
+
+############################################################################
+# vib_event_loop() is called by the WIT library whenever an event
+# occurs that does not correspond to WIT objects.
+############################################################################
+procedure vib_event_loop(e, x, y)
+ local f, obj, flag, diffx, diffy
+
+ case e of {
+ &meta & "I": snapshot()
+ &meta & !"nosrpqcdxuvh": menu_cb(, e)
+ "\d": menu_cb(, e)
+ Key_Left | Key_KP_Left: shift_focus(-1, 0)
+ Key_Right | Key_KP_Right: shift_focus(+1, 0)
+ Key_Up | Key_KP_Up: shift_focus(0, -1)
+ Key_Down | Key_KP_Down: shift_focus(0, +1)
+ &resize: {
+ if SIZER.x+10 > &x then
+ SIZER.x := &x - 11
+ if SIZER.y+10 > &y then
+ SIZER.y := maximum(&y - 11, CANVASY)
+ redraw_screen()
+ DIRTY := 1
+ }
+ &mpress: {
+ obj := object_of_event(x, y)
+ if type(obj) == "menu_obj" then {
+ focus_object(obj)
+ simulate_menu(obj)
+ }
+ }
+ &rpress: {
+ if on_target(SIZER, x, y) then
+ display_sizer_atts(SIZER)
+ else {
+ obj := object_of_event(x, y)
+ focus_object(\obj)
+ display_talk(\FOCUS)
+ }
+ }
+ &lpress: {
+ if \ALIGN then {
+ obj := object_of_event(x, y)
+ if \obj & \FOCUS then {
+ unfocus_object(f := FOCUS)
+ if ALIGN == "alignv" then
+ move_object(obj, obj.x, f.y)
+ else
+ move_object(obj, f.x, obj.y)
+ focus_object(f)
+ }
+ else
+ unset_align()
+ }
+ else { # not in ALIGN mode
+ if \(obj := palette_object_of_event(x, y)) then {
+ obj := create_object_instance(obj)
+ focus_object(obj)
+ &y := CANVASY + 4
+ drag_obj(APPWIN, obj)
+ }
+ else if on_target(SIZER, x, y) then
+ drag_sizer()
+ else if flag := on_focus(\FOCUS, x, y) then
+ resize_drag(FOCUS, flag)
+ else if \(obj := object_of_event(x, y)) then
+ drag_obj(DRAGWIN, obj)
+ else
+ unfocus_object(\FOCUS)
+ }
+ }
+ }
+end
+
+############################################################################
+# drag_obj() moves an object to follow the mouse pointer.
+############################################################################
+procedure drag_obj(win, obj)
+ unfocus_object(\FOCUS)
+ case type(obj) of {
+ "rect_obj": {
+ # use APPWIN, not DRAGWIN, to get XOR color correct
+ DragOutline(APPWIN, obj.x, obj.y, obj.w, obj.h)
+ }
+ "line_obj":
+ drag_line(obj)
+ default: {
+ EraseArea(APPWIN, obj.x, obj.y, obj.w, obj.h)
+ draw_object(obj)
+ Drag(win, obj.x, obj.y, obj.w, obj.h)
+ }
+ }
+
+ if obj.x ~= &x | obj.y ~= &y then
+ move_object(obj, &x, &y)
+ focus_object(obj)
+end
+
+############################################################################
+# resize_drag() resizes an object using the mouse pointer.
+############################################################################
+procedure resize_drag(obj, flag)
+ local e, orig, winw, winh
+
+ orig := copy(obj)
+ unfocus_object(obj)
+ draw_outline(obj)
+ winw := WAttrib("width")
+ winh := WAttrib("height")
+ repeat {
+ e := Event()
+ &x <:= 0
+ &x >:= winw - 1
+ &y <:= CANVASY
+ &y >:= winh - 1
+ case e of {
+ &ldrag: {
+ resize_object(obj, &x, &y, flag)
+ DIRTY := 1
+ }
+ &lrelease: {
+ draw_outline(obj)
+ erase_object(orig)
+ draw_overlap(orig)
+ if type(obj) ~== "line_obj" then
+ VResize(obj.v, obj.x, obj.y, obj.w, obj.h)
+ draw_object(obj)
+ focus_object(obj)
+ return
+ }
+ }
+ }
+end
diff --git a/ipl/gpacks/vib/vibbttn.icn b/ipl/gpacks/vib/vibbttn.icn
new file mode 100644
index 0000000..362b807
--- /dev/null
+++ b/ipl/gpacks/vib/vibbttn.icn
@@ -0,0 +1,220 @@
+############################################################################
+#
+# vibbttn.icn -- procedures for defining a button object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+
+##########################################################################
+# button_obj:
+# v : vidget used for drawing text input object
+# proc : name of user callback procedure
+# id : unique means of identifying instance
+# x,y,w,h : bounding box
+# label : button label
+# style : button style
+# toggle : is this a toggle button?
+# dflt : is this button the default in a dialog box?
+# focus : should focus lines be drawn around this object?
+##########################################################################
+record button_obj(v, proc, id, x, y, w, h,
+ label, style, toggle, dflt, focus)
+
+
+##########################################################################
+# create_button() creates a button instance and draws the button if
+# it is a first class object.
+##########################################################################
+procedure create_button(x, y, w, h, label, style, toggle, dflt)
+ local r, id
+
+ id := next_id("button")
+ /style := DEFAULT_BUTTON_STYLE
+ r := button_obj(, "button_cb" || id, "button" || id,
+ x, y, w, h, label, style, toggle, dflt, 0)
+ r.v := Vbutton(ROOT, x, y, APPWIN, label, , id, style, w, h)
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# draw_button() draws the given button in that button's style.
+##########################################################################
+procedure draw_button(r)
+ VResize(r.v, r.x, r.y, r.w, r.h)
+ VDraw(r.v)
+ if \r.dflt then
+ BevelRectangle(APPWIN, r.x - 4, r.y - 4, r.w + 8, r.h + 8, -2)
+ return r
+end
+
+##########################################################################
+# update_button_bb() updates various attributes of the button that
+# change when the button is resized, etc.
+##########################################################################
+procedure update_button_bb(r)
+ local tempy, temph, vpad, hpad, sp, sz
+
+ vpad := 4 # vertical padding
+ hpad := 7 # horizontal padding
+ sp := 11 # space between circle/box and text
+ r.w <:= MIN_W
+ r.h <:= MIN_H
+ case r.style of {
+ "check" | "circle" | "checkno" | "circleno": {
+ sz := integer(WAttrib(APPWIN, "fheight") * 0.75)
+ r.w <:= sz + sp + TextWidth(APPWIN, r.label) + hpad
+ r.h <:= WAttrib(APPWIN, "fheight") + vpad
+ }
+ "regular" | "regularno": {
+ r.w <:= TextWidth(APPWIN, r.label) + hpad
+ r.h <:= WAttrib(APPWIN, "fheight") + vpad
+ }
+ "xbox" | "xboxno": {
+ r.w <:= r.h
+ r.h <:= r.w
+ r.label := &null
+ }
+ }
+end
+
+##########################################################################
+# load_button() restores a button object from session code.
+##########################################################################
+procedure load_button(r, o)
+ r.label := o.lbl
+ r.style := o.sty
+ case o.num of {
+ "1": r.toggle := 1
+ "-1": r.dflt := 1
+ }
+ r.v := Vbutton(ROOT, r.x, r.y, APPWIN, r.label, , r.id, r.style, r.w, r.h)
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# load_xbox() makes an xbox button object from an old checkbox entry.
+##########################################################################
+procedure load_xbox(r, o)
+ r.label := ""
+ r.style := "xbox"
+ r.toggle := 1
+end
+
+##########################################################################
+# save_button() augments the record for saving a button object.
+##########################################################################
+procedure save_button(r, o)
+ r.typ := "Button"
+ r.lbl := o.label
+ r.sty := o.style
+ if \o.dflt then
+ r.num := -1
+ else
+ r.num := o.toggle
+ return
+end
+
+##########################################################################
+# display_button_atts() displays the attribute sheet with the current
+# attributes for the given button instance.
+##########################################################################
+procedure display_button_atts(object)
+ local s, o, t, d
+
+ d := object.dflt
+
+ s := object.style
+ o := 1
+ if s[-2:0] == "no" then {
+ s := s[1:-2]
+ o := &null
+ }
+
+ t := table()
+ t["_style"] := s
+ t["_outline"] := o
+ t["_toggle"] := object.toggle
+ t["_dflt"] := object.dflt
+ t["a_label"] := object.label
+ t["b_id"] := object.id
+ t["c_callback"] := object.proc
+ t["d_x"] := object.x
+ t["e_y"] := object.y - CANVASY
+ t["f_width"] := object.w
+ t["g_height"] := object.h
+
+ repeat {
+ if button_dialog(t) == "Cancel" then
+ fail
+
+ if illegal(t["a_label"], "Label", "l") |
+ illegal(t["b_id"], "ID", "s") |
+ illegal(t["c_callback"], "Callback", "p") |
+ illegal(t["d_x"], "X", "i") |
+ illegal(t["e_y"], "Y", "i") |
+ illegal(t["f_width"], "Width", MIN_W) |
+ illegal(t["g_height"], "Height", MIN_H)
+ then
+ next
+
+ if t["_style"] ? ="xbox" & *t["a_label"] > 0 then {
+ Notice("No text is allowed with xbox style")
+ next
+ }
+ if \t["_toggle"] & \t["_dflt"] then {
+ Notice("A toggle button cannot be a dialog default")
+ next
+ }
+
+ object.style := t["_style"]
+ if /t["_outline"] then
+ object.style ||:= "no"
+
+ object.dflt := t["_dflt"]
+ object.toggle := t["_toggle"]
+ object.label := t["a_label"]
+ object.id := t["b_id"]
+ object.proc := t["c_callback"]
+
+ object.v.style := object.style
+ object.v.s := object.label
+
+ unfocus_object(object)
+ if /object.dflt & \d then # remove default frame
+ EraseArea(object.x - 4, object.y - 4, object.w + 8, object.h + 8)
+ move_object(object,
+ t["d_x"], t["e_y"] + CANVASY, t["f_width"], t["g_height"])
+ focus_object(object)
+ break
+ }
+end
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure button_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["button_dialog:Sizer::1:0,0,392,240:",],
+ ["_cancel:Button:regular::211,189,50,30:Cancel",],
+ ["_dflt:Button:check:1:245,148,125,20:dialog default",],
+ ["_okay:Button:regular:-1:141,189,50,30:Okay",],
+ ["_outline:Button:check:1:245,85,76,20:outline",],
+ ["_style:Choice::4:142,85,78,84:",,
+ ["regular","check","circle","xbox"]],
+ ["_toggle:Button:check:1:245,116,76,20:toggle",],
+ ["a_label:Text::40:13,14,360,19:label: \\=",],
+ ["b_id:Text::40:13,35,360,19:ID: \\=",],
+ ["c_callback:Text::40:13,56,360,19:callback: \\=",],
+ ["d_x:Text::3:13,85,101,19: x: \\=",],
+ ["e_y:Text::3:13,106,101,19: y: \\=",],
+ ["f_width:Text::3:13,131,101,19: width: \\=",],
+ ["g_height:Text::3:13,152,101,19: height: \\=",],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/vibdefn.icn b/ipl/gpacks/vib/vibdefn.icn
new file mode 100644
index 0000000..02d8a04
--- /dev/null
+++ b/ipl/gpacks/vib/vibdefn.icn
@@ -0,0 +1,75 @@
+############################################################################
+#
+# vibdefn.icn -- manifest constants
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$define PAL_H 36 # height of palette entry
+$define PAL_W 48 # width of palette entry
+
+$define SZDIM 9 # sizer dimensions
+
+$define DEFAULT_BUTTON_STYLE "regular" # default button style
+$define MIN_W 10 # minimum object width
+$define MIN_H 10 # minimum object height
+
+$define TEXTCHARS 40 # size of hand-built text field
+$define TEXTWIDTH (20 + 7 * TEXTCHARS) # space used for same
+$define LONGTEXT 50 # size of long text fields
+
+
+# alternate keypad symbols not always set
+
+$ifndef Key_KP_Left
+ $define Key_KP_Left Key_Left
+$endif
+$ifndef Key_KP_Right
+ $define Key_KP_Right Key_Right
+$endif
+$ifndef Key_KP_Up
+ $define Key_KP_Up Key_Up
+$endif
+$ifndef Key_KP_Down
+ $define Key_KP_Down Key_Down
+$endif
+
+
+# file names and commands for prototyping
+
+$ifdef _UNIX
+ $define EXECPROTO ("./" || PROTOEXE || " && rm -f " || PROTOEXE || " &")
+$endif
+
+$ifdef _CYGWIN
+ $define EXECPROTO ("./" || PROTOEXE || " && rm -f " || PROTOEXE || " &")
+$endif
+
+$ifdef _MS_WINDOWS
+ $define PROTOEXE "vibproto.exe"
+$endif
+
+# defaults used if not set above
+
+$ifndef PROTOFILE # prototype file name
+ $define PROTOFILE "vibproto.icn"
+$endif
+
+$ifndef PROTOEXE # executable file name
+ $define PROTOEXE "vibproto"
+$endif
+
+$ifndef BUILDPROTO # build command
+ $ifdef _JAVA
+ $define BUILDPROTO ("jcont -s -o" || PROTOEXE || " " || PROTOFILE)
+ $else # _JAVA
+ $define BUILDPROTO ("icont -s -o" || PROTOEXE || " " || PROTOFILE)
+ $endif # _JAVA
+$endif
+
+$ifndef EXECPROTO # execute command
+ $define EXECPROTO PROTOEXE
+$endif
diff --git a/ipl/gpacks/vib/vibedit.icn b/ipl/gpacks/vib/vibedit.icn
new file mode 100644
index 0000000..b8f07e1
--- /dev/null
+++ b/ipl/gpacks/vib/vibedit.icn
@@ -0,0 +1,922 @@
+############################################################################
+#
+# vibedit.icn -- shared graphical editing routines
+#
+## #########################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+$include "vdefns.icn"
+
+record palette_obj(name, x, y, bwimage, colrimage)
+
+############################################################################
+# next_id() generates an ID number for a new object
+############################################################################
+procedure next_id(s)
+ local obj, n
+
+ n := 0
+ every obj := !O_LIST do
+ obj.id ?
+ if =s then
+ n <:= integer(tab(0)) # find highest used so far
+ return n + 1
+end
+
+############################################################################
+# strip() deletes trailing blanks from the incoming string.
+############################################################################
+procedure strip(s)
+ local index
+
+ index := 0
+ every index := *s to 1 by -1 do
+ if s[index] ~== " " then break
+ return s[1:index+1]
+end
+
+############################################################################
+# set_align() sets the align flag and changes the cursor to indicate that
+# the system is in align mode.
+############################################################################
+procedure set_align(kind)
+ ALIGN := kind
+ if kind == "alignv" then
+ WAttrib("pointer=" || ("top side" | "sb v double arrow" | "crosshair"))
+ else
+ WAttrib("pointer=" || ("left side" | "sb h double arrow" | "crosshair"))
+end
+
+############################################################################
+# unset_align() unsets the align flag and restores the cursor to its
+# original state.
+############################################################################
+procedure unset_align()
+ ALIGN := &null
+ WAttrib("pointer=" || ("left ptr" | "arrow"))
+end
+
+############################################################################
+# minimum() returns the smaller of two numeric values.
+############################################################################
+procedure minimum(x, y)
+ return x > y | x
+end
+
+############################################################################
+# maximum() returns the larger of two numeric values.
+############################################################################
+procedure maximum(x, y)
+ return x < y | x
+end
+
+############################################################################
+# draw_outline() draws an outline for the given object. Used for resizing.
+############################################################################
+procedure draw_outline(object)
+ case type(object) of {
+ "line_obj" : outline_line(object)
+ default : DrawRectangle(XORWIN,
+ object.x-1, object.y-1, object.w+1, object.h+1)
+ }
+end
+
+############################################################################
+# update_bb() calls update routines for the various object types so
+# that attributes correctly get updated when an object is
+# resized or a label changes, etc.
+############################################################################
+procedure update_bb(object)
+ case type(object) of {
+ "button_obj" : update_button_bb(object)
+ "radio_button_obj": update_radio_bb(object)
+ "line_obj" : update_line_bb(object)
+ "slider_obj" : update_slider_bb(object)
+ "text_input_obj" : update_text_input_bb(object)
+ "label_obj" : update_label_bb(object)
+ "menu_obj" : update_menu_bb(object)
+ "list_obj" : update_list_bb(object)
+ # nothing to do for rectangles
+ }
+end
+
+############################################################################
+# move_object() is called to reposition, resize, and redraw an object.
+############################################################################
+procedure move_object(object, x, y, w, h)
+
+ erase_object(object)
+ draw_overlap(object)
+
+ if type(object) == "line_obj" then {
+ object.x2 := object.x2 - object.x + x
+ object.y2 := object.y2 - object.y + y
+ object.x1 := object.x1 - object.x + x
+ object.y1 := object.y1 - object.y + y
+ update_bb(object)
+ }
+ else {
+ x <:= 0
+ y <:= CANVASY # ensure object does not overlap palette
+ object.x := x
+ object.y := y
+ object.w := \w
+ object.h := \h
+ update_bb(object)
+ VResize(object.v, object.x, object.y, object.w, object.h)
+ }
+
+ draw_object(object)
+ DIRTY := 1
+end
+
+############################################################################
+# resize_object() is called to resize the outline of an object. First,
+# draw_outline() is called to erase the outline, then the
+# attributes are updated, then draw_outline is called to
+# draw the new outline.
+############################################################################
+procedure resize_object(object, x, y, direction)
+ local neww, newh, newy, xcorner, ycorner
+
+ # move particular enpoint of line and adjust bounding box of line
+ if type(object) == "line_obj" then {
+ draw_outline(object)
+ if direction == "lpt" then {
+ object.x1 := x
+ object.y1 := maximum(CANVASY, y)
+ }
+ else if direction == "rpt" then {
+ object.x2 := x
+ object.y2 := maximum(CANVASY, y)
+ }
+ update_bb(object)
+ draw_outline(object)
+ return
+ }
+
+ # all other objects can be resized freely,
+ # subject to minimum width/height imposed in update_bb()
+
+ draw_outline(object)
+ y <:= CANVASY
+ ycorner := direction[1] # "u" or "l"
+ xcorner := direction[2] # "l" or "r"
+
+ if xcorner == "r" then {
+ neww := x - object.x
+ neww <:= MIN_W
+ }
+ else {
+ neww := object.w + object.x - x
+ neww <:= MIN_W
+ object.x +:= object.w - neww
+ }
+
+ if ycorner == "l" then {
+ newh := y - object.y
+ newh <:= MIN_H
+ }
+ else {
+ newh := object.h + object.y - y
+ newh <:= MIN_H
+ object.y +:= object.h - newh
+ }
+
+ object.h := newh
+ object.w := neww
+ update_bb(object)
+ if object.w ~= neww & xcorner == "l" then
+ object.x +:= neww - object.w
+ if object.h ~= newh & ycorner == "u" then
+ object.y +:= newh - object.h
+
+ VResize(object.v, object.x, object.y, object.w, object.h)
+ draw_outline(object)
+end
+
+############################################################################
+# display_talk() is called to display the attribute sheets of the various
+# object types.
+############################################################################
+procedure display_talk(object)
+ case type(object) of {
+ "button_obj" : display_button_atts(object)
+ "slider_obj" : display_slider_atts(object)
+ "text_input_obj" : display_text_input_atts(object)
+ "rect_obj" : display_rect_atts(object)
+ "menu_obj" : display_menu_atts(object)
+ "line_obj" : display_line_atts(object)
+ "label_obj" : display_label_atts(object)
+ "radio_button_obj": display_radio_button_atts(object)
+ "list_obj" : display_list_atts(object)
+ }
+end
+
+############################################################################
+# draw_object() is called to draw the various object types.
+############################################################################
+procedure draw_object(object)
+ update_bb(object)
+ case type(object) of {
+ "sizer_obj" : draw_sizer(object)
+ "button_obj" : draw_button(object)
+ "text_input_obj" : draw_text_input(object)
+ "radio_button_obj" : draw_radio_button(object)
+ "rect_obj" : draw_rect(object)
+ "slider_obj" : draw_slider(object)
+ "line_obj" : draw_line(object)
+ "label_obj" : draw_label(object)
+ "menu_obj" : draw_menu(object)
+ "list_obj" : draw_list(object)
+ }
+end
+
+############################################################################
+# erase_object() removes an object from the screen.
+############################################################################
+procedure erase_object(object)
+ if type(object) == "line_obj" then
+ DrawGroove(APPWIN, object.x1, object.y1, object.x2, object.y2, 0)
+ else if type(object) == "button_obj" & \object.dflt then
+ EraseArea(APPWIN, object.x - 4, object.y - 4, object.w + 8, object.h + 8)
+ else
+ EraseArea(APPWIN, object.x, object.y, object.w, object.h)
+end
+
+############################################################################
+# draw_focus() is called to draw focus lines around an object.
+############################################################################
+procedure draw_focus(o)
+ if type(o) == "line_obj" then {
+ FillRectangle(XORWIN, o.x1 - 3, o.y1 - 3, 6, 6)
+ FillRectangle(XORWIN, o.x2 - 3, o.y2 - 3, 6, 6)
+ } else {
+ DrawLine(XORWIN, o.x-2, o.y+2, o.x-2, o.y-2, o.x+2, o.y-2)
+ DrawLine(XORWIN, o.x-2, o.y+o.h-3, o.x-2, o.y+o.h+1, o.x+2, o.y+o.h+1)
+ DrawLine(XORWIN, o.x+o.w-3, o.y-2, o.x+o.w+1, o.y-2, o.x+o.w+1, o.y+2)
+ DrawLine(XORWIN,
+ o.x+o.w-3, o.y+o.h+1, o.x+o.w+1, o.y+o.h+1, o.x+o.w+1, o.y+o.h-3)
+ }
+end
+
+############################################################################
+# focus_object() sets the given object to be the object with the focus.
+# Focus lines are drawn around the object and the FOCUS
+# global is set to be the object.
+############################################################################
+procedure focus_object(object)
+ unfocus_object(\FOCUS)
+ draw_focus(object)
+ object.focus := 1
+ FOCUS := object
+ return object
+end
+
+############################################################################
+# unfocus_object() unsets the focus. The focus lines are erased about
+# the object and the FOCUS global is set to null.
+############################################################################
+procedure unfocus_object(object)
+ draw_focus(object)
+ object.focus := 0
+ FOCUS := &null
+ return object
+end
+
+############################################################################
+# on_focus() returns either
+# "lpt" : if object is a line and the mouse is on the left endpoint
+# "rpt" : if object is a line and the mouse is on the right endpoint
+# "ur" : if mouse is on upper-right focus point of object
+# "ul" : if mouse is on upper-left focus point of object
+# "lr" : if mouse is on lower-right focus point of object
+# "ll" : if mouse is on lower-left focus point of object
+# otherwise it fails
+############################################################################
+procedure on_focus(object, x, y)
+ local range
+
+ range := 5
+ if type(object) == "line_obj" then {
+ if (object.x1 - range < x < object.x1 + range) &
+ (object.y1 - range < y < object.y1 + range) then
+ return "lpt"
+ else if (object.x2 - range < x < object.x2 + range) &
+ (object.y2 - range < y < object.y2 + range) then
+ return "rpt"
+ else fail
+ }
+ if (object.x+object.w-range) < x < (object.x+object.w+range) &
+ (object.y - range) < y < (object.y + range) then
+ return "ur"
+ if (object.x - range) < x < (object.x + range) &
+ (object.y - range) < y < (object.y + range) then
+ return "ul"
+ if (object.x - range) < x < (object.x + range) &
+ (object.y+object.h-range) < y < (object.y+object.h+range) then
+ return "ll"
+ if (object.x+object.w-range) < x < (object.x+object.w+range) &
+ (object.y+object.h-range) < y < (object.y+object.h+range) then
+ return "lr"
+ fail
+end
+
+############################################################################
+# on_target() returns the object if the mouse is over the object.
+# Else fails.
+############################################################################
+procedure on_target(o, x, y)
+ local m, a, b, c, d
+
+ if y < CANVASY then fail
+ if not ((o.x <= x <= o.x + o.w) &
+ (o.y <= y <= o.y + o.h)) then
+ fail
+ if type(o) == "line_obj" & o.w > 6 & o.h > 6 then { # if skewed line
+ # make sure (x,y) is reasonably close to the line
+ m := (o.y2 - o.y1) / real(o.x2 - o.x1) # slope
+ a := o.y1 - m * o.x1 # y-intercept
+ b := o.x1 - o.y1 / m # x-intercept
+ c := -a * o.x1 - b * o.y1 # ax + by + c = 0
+ d := (a * x + b * y + c) / sqrt(a ^ 2 + b ^ 2) # distance
+ if abs(d) > 5 then
+ fail
+ }
+ return o
+end
+
+############################################################################
+# object_of_event() checks the canvas object list against the mouse event
+# coordinates to determine if the event correlates to
+# a canvas object. If multiple objects match, the
+# smallest is returned. (The area of a "line" is fudged.)
+# Null is returned if the event does not correlate.
+############################################################################
+procedure object_of_event(x, y)
+ local o, a, obj, area
+
+ every o := !O_LIST do
+ if on_target(o, x, y) then {
+ if type(o) == "line_obj" then
+ a := 5 * maximum(o.w, o.h)
+ else
+ a := o.w * o.h
+ if /obj | a < area then {
+ obj := o
+ area := a
+ }
+ }
+ return obj
+end
+
+############################################################################
+# clear_screen() empties the entire screen, redrawing just the palette
+# and sizer object. The canvas list is emptied.
+############################################################################
+procedure clear_screen()
+ O_LIST := list()
+ FOCUS := &null
+ DIRTY := &null
+ redraw_screen()
+end
+
+############################################################################
+# redraw_screen() clears the screen and redraws both the palette and canvas.
+############################################################################
+procedure redraw_screen()
+ EraseArea()
+ draw_header()
+ draw_canvas()
+end
+
+############################################################################
+# shift_focus() moves the object with the FOCUS by in the amount given.
+############################################################################
+procedure shift_focus(dx, dy)
+ local object
+
+ if object := \FOCUS then {
+ unfocus_object(object)
+ move_object(object, object.x + dx, object.y + dy)
+ focus_object(object)
+ }
+end
+
+############################################################################
+# copy_focus() makes a copy of the object with the focus.
+############################################################################
+procedure copy_focus()
+ local r, drawin, temp, obj
+
+ if obj := \FOCUS then {
+ unfocus_object(obj)
+ case type(obj) of {
+ "rect_obj": {
+ r := create_rect(obj.x + 10, obj.y + 10, obj.w, obj.h, obj.style)
+ }
+ "menu_obj": {
+ temp := copy(obj)
+ r := create_menu(obj.x + 10, obj.y + 10, obj.label, obj.style)
+ copy_menu(r, temp)
+ }
+ "button_obj": {
+ r := create_button(obj.x + 10, obj.y + 10, obj.w, obj.h,
+ obj.label, obj.style, obj.toggle)
+ }
+ "text_input_obj": {
+ r := create_text_input(obj.x + 10, obj.y + 10,
+ obj.label, obj.value, obj.length)
+ }
+ "label_obj": {
+ r := create_label(obj.x + 10, obj.y + 10, obj.label)
+ }
+ "radio_button_obj": {
+ r := create_radio_button(obj.x + 10, obj.y + 10, copy(obj.alts))
+ }
+ "slider_obj": {
+ r := create_slider(obj.x + 10, obj.y + 10, obj.w, obj.h,
+ obj.typ, obj.min, obj.max, obj.value, obj.filter)
+ }
+ "line_obj": {
+ r := create_line(obj.x1 + 10, obj.y1 + 10, obj.x2 + 10, obj.y2 + 10)
+ }
+ "list_obj": {
+ r := create_list(obj.x + 10, obj.y + 10, obj.w, obj.h,
+ obj.style, obj.scroll)
+ }
+ default: return
+ }
+ push(O_LIST, r)
+ draw_object(r)
+ focus_object(r)
+ DIRTY := 1
+ }
+end
+
+############################################################################
+# delete_focus() removes the object with the FOCUS from the canvas list.
+############################################################################
+procedure delete_focus()
+ local i
+
+ if \FOCUS then {
+ draw_focus(FOCUS)
+ erase_object(FOCUS)
+ DELETED := FOCUS
+ every i := 1 to *O_LIST do
+ if (O_LIST[i] === FOCUS) then
+ O_LIST := O_LIST[1:i] ||| O_LIST[i+1:*O_LIST+1]
+ FOCUS := &null
+ DELETED.focus := 0
+ DIRTY := 1
+ draw_overlap(DELETED)
+ }
+end
+
+############################################################################
+# undelete() restores the most recently deleted object.
+############################################################################
+procedure undelete()
+ if \DELETED then {
+ unfocus_object(\FOCUS)
+ push(O_LIST, DELETED)
+ draw_object(DELETED)
+ focus_object(DELETED)
+ DELETED := &null
+ DIRTY := 1
+ }
+end
+
+############################################################################
+# add_palette_entry() adds one entry to the palette
+############################################################################
+procedure add_palette_entry(name, bwimage, colrimage)
+ static x
+ initial x := 0
+
+ push(P_LIST, palette_obj(name, x, MENUBAR.ah + 3, bwimage, colrimage))
+ x +:= PAL_W
+end
+
+############################################################################
+# draw_decor() redraws the decorative lines that extend across the window.
+############################################################################
+procedure draw_decor()
+ DrawLine(0, MENUBAR.ah, 2000, MENUBAR.ah)
+ DrawLine(0, CANVASY-1, 2000, CANVASY-1)
+end
+
+############################################################################
+# draw_header() redraws the window header.
+############################################################################
+procedure draw_header()
+ local e, xpad, ypad, w, d, h, im
+
+ MENUBAR.V.draw(MENUBAR)
+ DrawString(SELECT.ax + 4, SELECT.ay + 15, "Select")
+ BevelRectangle(SELECT.ax, SELECT.ay, SELECT.aw, SELECT.ah)
+ draw_decor()
+ every e := !P_LIST do {
+ if WAttrib("depth") > 1 then (im := e.colrimage) ? {
+ w := tab(upto(',')) # width of image
+ move(1)
+ tab(upto(',') + 1) # skip over palette spec
+ h := *tab(0) / w # height of image
+ }
+ else (im := e.bwimage) ? {
+ w := tab(upto(',')) # width of image
+ d := ((w + 3) / 4) # digits per row
+ move(2)
+ h := *tab(0) / d # height of image
+ }
+ xpad := (PAL_W - w) / 2
+ ypad := (PAL_H - h) / 2
+ DrawImage(e.x + xpad, e.y + ypad, im)
+ }
+end
+
+############################################################################
+# draw_canvas() draws all the objects that exist within the canvas.
+############################################################################
+procedure draw_canvas()
+ every draw_object(O_LIST[*O_LIST to 1 by -1])
+ draw_sizer(SIZER)
+ draw_focus(\FOCUS)
+end
+
+############################################################################
+# draw_overlap() draws any objects that overlap the argument object.
+############################################################################
+procedure draw_overlap(object)
+ local f, o, d
+
+ if type(object) == "button_obj" & \object.dflt then
+ d := 8 # fudge factor for default box on both objects
+ else
+ d := 4 # only the other object can have default box
+
+ unfocus_object(f := \FOCUS)
+ every o := O_LIST[*O_LIST to 1 by -1] do {
+ if o.x >= object.x + object.w + d then next
+ if object.x >= o.x + o.w + d then next
+ if o.y >= object.y + object.h + d then next
+ if object.y >= o.y + o.h + d then next
+ if o === object then next
+ draw_object(o)
+ }
+ if object.x + object.w + d >= SIZER.x |
+ object.y + object.h + d >= SIZER.y then
+ draw_sizer(SIZER)
+ focus_object(\f)
+end
+
+############################################################################
+# palette_object_of_event() cycles through the list of palette objects
+# to determine if any of them were the target
+# of a mouse event.
+############################################################################
+procedure palette_object_of_event(x, y)
+ local o
+
+ every o := !P_LIST do
+ if o.x <= x <= o.x + PAL_W & o.y <= y <= o.y + PAL_H then
+ return o
+ return &null
+end
+
+############################################################################
+# create_object_instance() creates an instance of the given object.
+############################################################################
+procedure create_object_instance(obj)
+ local r, temp, x, y, w, h
+
+ x := &x
+ y := CANVASY
+ w := 32
+ h := 20
+ case obj.name of {
+ "line":
+ r := create_line(x, y + 3, x + PAL_W, y + 3)
+ "rect":
+ r := create_rect(x, y, w, h, "grooved")
+ "menu": {
+ r := create_menu(x, y, "Menu", "pull")
+ add_item(r, "three", 0)
+ add_item(r, "two", 0)
+ add_item(r, "one", 0)
+ }
+ "button":
+ r := create_button(x, y, w, h, "push")
+ "radio_button":
+ r := create_radio_button(x, y, ["one","two","three"])
+ "text":
+ r := create_text_input(x, y, "Text:", "", 3)
+ "label":
+ r := create_label(x, y, "Label")
+ "slider":
+ r := create_slider(x, y, VSlider_DefWidth, VSlider_DefLength,
+ "Slider", 0.0, 1.0, 0.5, 1)
+ "scroll":
+ r := create_slider(x, y, VSlider_DefWidth, VSlider_DefLength,
+ "Scrollbar", 0.0, 1.0, 0.5, 1)
+ "list":
+ r := create_list(x, y)
+ default: return &null
+ }
+ push(O_LIST, r)
+ DIRTY := 1
+ return r
+end
+
+############################################################################
+# create_palette() creates the palette objects.
+############################################################################
+procedure create_palette()
+
+ add_palette_entry("button",
+ "25,#1ffffff10000011000001115555110aaaa11155551100000110000011ffffff",
+ "25,c1,_
+ 6666666666666666666666666_
+ 6~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~222222222222222~~~~1_
+ 6~~~~222222222222222~~~~1_
+ 6~~~~222222222222222~~~~1_
+ 6~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6111111111111111111111111_
+ ")
+ add_palette_entry("radio_button",
+ "32,#FFFFFFFF8000000180000021800000518555508982AAA1058555508980000051_
+ 80000021800000018000000180000021800000518555508982AAA10585555089_
+ 800000518000002180000001800000018000002180000071855550F982AAA1FD_
+ 855550F9800000718000002180000001FFFFFFFF",
+ "33,c1,_
+ 666666666666666666666666666666661_
+ 6~~~~~6~~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~666~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~66~66~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~66~~~66~~~222222222222222~~~~1_
+ 6~66~~~~~66~~222222222222222~~~~1_
+ 6~~11~~~11~~~222222222222222~~~~1_
+ 6~~~11~11~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~111~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~1~~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~6~~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~666~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~66~66~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~66~~~66~~~222222222222222~~~~1_
+ 6~66~~~~~66~~222222222222222~~~~1_
+ 6~~11~~~11~~~222222222222222~~~~1_
+ 6~~~11~11~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~111~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~1~~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~6~~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~666~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~66066~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~6600066~~~222222222222222~~~~1_
+ 6~660000066~~222222222222222~~~~1_
+ 6~~1100011~~~222222222222222~~~~1_
+ 6~~~11011~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~111~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~1~~~~~~~~~~~~~~~~~~~~~~~~~1_
+ 611111111111111111111111111111111_
+ ")
+ add_palette_entry("menu",
+ "20,#1ffff1ffff1d5571eaaf1d5571fffffffff800018000180001955518aaa98000_
+ 18000180001955518aaa9800018000180001955518aaa9800018000180001955_
+ 518aaa98000180001fffff",
+ "20,c1,_
+ 1111111111111116~~~~_
+ 1000000000000006~~~~_
+ 1005555555550006~~~~_
+ 1005555555550006~~~~_
+ 1000000000000006~~~~_
+ 1000000000000006~~~~_
+ 66666666666666666666_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~22222222222222~~1_
+ 6~~22222222222222~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~22222222222222~~1_
+ 6~~22222222222222~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~22222222222222~~1_
+ 6~~22222222222222~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~22222222222222~~1_
+ 6~~22222222222222~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 6~~~~~~~~~~~~~~~~~~1_
+ 61111111111111111111_
+ ")
+ add_palette_entry("list",
+ "32,#FFFFFFFF92000001AA000001AA555551C62AAAA9FE0000018200000182555551_
+ FE2AAAA9C6000001C7FFFFFFC7AAAAAFC7D55557C7FFFFFFC6000001C6555551_
+ C62AAAA9FE0000018200000182555551822AAAA9820000018200000182555551_
+ 822AAAA982000001FE000001C6555551AA2AAAA9AA00000192000001FFFFFFFF",
+ "32,c1,_
+ 111111111111111111111111~1111111_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~~6~~6_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~6~1~6_
+ 1~~222222222222222222~~6~1~6~1~6_
+ 1~~222222222222222222~~6~16~~~16_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1611116_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~~~~~6_
+ 1~~222222222222222222~~6~1666666_
+ 1~~222222222222222222~~6~16~~~16_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~16~~~16_
+ 100000000000000000000006~16~~~16_
+ 100222222222222222222006~16~~~16_
+ 100222222222222222222006~16~~~16_
+ 100000000000000000000006~16~~~16_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~16~~~16_
+ 1~~222222222222222222~~6~16~~~16_
+ 1~~222222222222222222~~6~1611116_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~~~~~6_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~~~~~6_
+ 1~~222222222222222222~~6~1~~~~~6_
+ 1~~222222222222222222~~6~1~~~~~6_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~~~~~6_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~~~~~6_
+ 1~~222222222222222222~~6~1~~~~~6_
+ 1~~222222222222222222~~6~1~~~~~6_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1666666_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~16~~~16_
+ 1~~222222222222222222~~6~16~~~16_
+ 1~~222222222222222222~~6~1~6~1~6_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~6~1~6_
+ 1~~~~~~~~~~~~~~~~~~~~~~6~1~~6~~6_
+ 16666666666666666666666641666666_
+ ")
+ add_palette_entry("text",
+ "32,#ffffc00080004000800040008000400080004555800042aa9ffe455580004000_
+ 80004000ffffc000",
+ "32,c1,_
+ ~~~~~~~~~~~~~~111111111111111111_
+ ~~~~~~~~~~~~~~1~~~~~~~~~~~~~~~~6_
+ ~~~~~~~~~~~~~~1~~~~~~~~~~~~~~~~6_
+ ~~~~~~~~~~~~~~1~~~~~~~~~~~~~~~~6_
+ 22222222222~~~1~~~~~~~~~~~~~~~~6_
+ 22222222222~~~1~~~~~~~~~~~~~~~~6_
+ 22222222222~~~1~~~~~~~~~~~~~~~~6_
+ ~~~~~~~~~~~~~~1~~~~~~~~~~~~~~~~6_
+ ~~~~~~~~~~~~~~1~~~~~~~~~~~~~~~~6_
+ ~~~~~~~~~~~~~~166666666666666666_
+ ")
+ add_palette_entry("slider",
+ "9,#1FF1011011011011011011011011011011FF1831831831831831FF_
+ 1831831831831831FF1011011011011011011011FF",
+ "9,c1,_
+ 111111111_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 166666666_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 161111116_
+ 166666616_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 161111116_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 166666666_
+ ")
+ add_palette_entry("scroll",
+ "9,#1FF1111291291451451FF1011011011011FF1831831831831831FF_
+ 1011011011011011011011FF1451451291291111FF",
+ "9,c1,_
+ 111111111_
+ 1~~~6~~~6_
+ 1~~6~1~~6_
+ 1~~6~1~~6_
+ 1~6~~~1~6_
+ 1~6~~~1~6_
+ 16~~~~~16_
+ 161111116_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 166666666_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 16~~~~~16_
+ 161111116_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 1~~~~~~~6_
+ 166666666_
+ 16~~~~~16_
+ 1~6~~~1~6_
+ 1~6~~~1~6_
+ 1~~6~1~~6_
+ 1~~6~1~~6_
+ 1~~~6~~~6_
+ 166666666_
+ ")
+ add_palette_entry("rect",
+ "32,#ffffffff80000001800000018000000180000001800000018000000180000001_
+ 8000000180000001800000018000000180000001800000018000000180000001_
+ 800000018000000180000001ffffffff",
+ "32,c1,_
+ 33333333333333333333333333333333_
+ 36666666666666666666666666666666_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36~~~~~~~~~~~~~~~~~~~~~~~~~~~~36_
+ 36333333333333333333333333333336_
+ 36666666666666666666666666666666_
+ ")
+ add_palette_entry("label",
+ "13,#0040004000e000e000e001b00190019003180308030807fc060406040c061e0f",
+ "13,c1,_
+ ~~~~~~0~~~~~~_
+ ~~~~~~0~~~~~~_
+ ~~~~~000~~~~~_
+ ~~~~~000~~~~~_
+ ~~~~~000~~~~~_
+ ~~~~00~00~~~~_
+ ~~~~0~~00~~~~_
+ ~~~~0~~00~~~~_
+ ~~~00~~~00~~~_
+ ~~~0~~~~00~~~_
+ ~~~0~~~~~0~~~_
+ ~~000000000~~_
+ ~~0~~~~~~00~~_
+ ~~0~~~~~~00~~_
+ ~00~~~~~~~00~_
+ 0000~~~~~0000_
+ ")
+ add_palette_entry("line",
+ "32,#0000000f0000000f0000001f0000006f00000180000006000000180000006000_
+ 0001800000060000001800000060000001800000f6000000f8000000f0000000f0000000",
+ "30,c1,_
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~0000_
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~3300_
+ ~~~~~~~~~~~~~~~~~~~~~~~~336600_
+ ~~~~~~~~~~~~~~~~~~~~~~33660000_
+ ~~~~~~~~~~~~~~~~~~~~3366~~~~~~_
+ ~~~~~~~~~~~~~~~~~~3366~~~~~~~~_
+ ~~~~~~~~~~~~~~~~3366~~~~~~~~~~_
+ ~~~~~~~~~~~~~~3366~~~~~~~~~~~~_
+ ~~~~~~~~~~~~3366~~~~~~~~~~~~~~_
+ ~~~~~~~~~~3366~~~~~~~~~~~~~~~~_
+ ~~~~~~~~3366~~~~~~~~~~~~~~~~~~_
+ ~~~~~~3366~~~~~~~~~~~~~~~~~~~~_
+ 00003366~~~~~~~~~~~~~~~~~~~~~~_
+ 003366~~~~~~~~~~~~~~~~~~~~~~~~_
+ 0066~~~~~~~~~~~~~~~~~~~~~~~~~~_
+ 0000~~~~~~~~~~~~~~~~~~~~~~~~~~_
+ ")
+end
diff --git a/ipl/gpacks/vib/vibfile.icn b/ipl/gpacks/vib/vibfile.icn
new file mode 100644
index 0000000..da1dd43
--- /dev/null
+++ b/ipl/gpacks/vib/vibfile.icn
@@ -0,0 +1,603 @@
+############################################################################
+#
+# vibfile.icn -- procedures for reading and writing specs to files
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+$include "vdefns.icn"
+
+############################################################################
+# constants and globals that are used only in this file:
+############################################################################
+$define PTITLE "#===<<vib prototype file>>==="
+$define HEADER "#===<<vib:begin>>===\tmodify using vib; do not remove this marker line"
+$define TRAILER "#===<<vib:end>>===\tend of section maintained by vib"
+$define XHEADER "#===<<xie:begin>>===" # for detecting old files
+$define XTRAILER "#===<<xie:end>>==="
+$define HMATCH 20 # number of chars that must match in header
+$define TMATCH 18 # number of chars that must match in trailer
+global USER_PREFIX, # user code preceding spec
+ USER_SUFFIX # user code following spec
+
+############################################################################
+# new_session() creates a new, empty VIB session
+############################################################################
+procedure new_session()
+ local fname
+
+ if not flush_session() then fail
+ SIZER := create_sizer()
+ clear_screen()
+ SESSION := newname()
+ label_session()
+ USER_PREFIX := USER_SUFFIX := &null
+ return
+end
+
+############################################################################
+# load_session() reads in a saved VIB session file so that it can be
+# re-edited.
+############################################################################
+procedure load_session(s)
+ local line, ifile, l, o
+
+ ifile := open(s, "r") | fail
+ clear_screen()
+
+ USER_PREFIX := USER_SUFFIX := ""
+ while line := read(ifile) do {
+ if line ? match((HEADER | XHEADER)[1 +: HMATCH]) then
+ break
+ if line ? match("# Session Code:") then {
+ Notice("Old file format; use uix to convert")
+ USER_PREFIX := USER_SUFFIX := &null
+ fail
+ }
+ USER_PREFIX ||:= line
+ USER_PREFIX ||:= "\n"
+ line := &null
+ }
+
+ DIRTY := &null
+ if not (\line ? match((HEADER | XHEADER)[1 +: HMATCH])) then {
+ Notice("No interface section found; creating one")
+ USER_PREFIX ||:= "\n\n\n"
+ DIRTY := 1
+ }
+
+ while o := load_object(ifile) do case o.typ of {
+ "Button" : init_object(load_button, button_obj(), o)
+ "Text" : init_object(load_text_input, text_input_obj(), o)
+ "Scrollbar" : init_object(load_slider, slider_obj(), o)
+ "Slider" : init_object(load_slider, slider_obj(), o)
+ "Line" : init_object(load_line, line_obj(), o)
+ "Rect" : init_object(load_rect, rect_obj(), o)
+ "Label" : init_object(load_label, label_obj(), o)
+ "Message" : init_object(load_label, label_obj(), o)
+ "Choice" : init_object(load_radio_button, radio_button_obj(), o)
+ "Menu" : init_object(load_menu, menu_obj(), o)
+ "Sizer" : init_object(load_sizer, sizer_obj(), o)
+ "Check" : init_object(load_xbox, button_obj(), o)
+ "List" : init_object(load_list, list_obj(), o)
+ }
+
+ while USER_SUFFIX ||:= read(ifile) do
+ USER_SUFFIX ||:= "\n"
+ close(ifile)
+ return
+end
+
+#############################################################################
+# init_object() initializes an object record and calls a proc to register it.
+#############################################################################
+procedure init_object(proc, r, o)
+ r.id := o.id
+ r.proc := o.proc
+ r.x := integer(o.x)
+ r.y := o.y + CANVASY
+ r.w := integer(o.w)
+ r.h := integer(o.h)
+ r.focus := 0
+ push(O_LIST, r) # must precede proc call
+ proc(r, o) # call object-specific procedure
+ update_bb(r)
+ draw_object(r)
+end
+
+############################################################################
+# load_object() reads the next object from a saved session file.
+############################################################################
+procedure load_object(f)
+ local c, s, l, r
+
+ # find a line where the first nonblank character is a "["
+ repeat {
+ while (c := reads(f, 1)) & upto(' \t\f', c)
+ if \c == "[" then
+ break
+ s := (c || read(f)) | fail
+ if s ? match((TRAILER | XTRAILER)[1 +: TMATCH]) then
+ fail
+ }
+
+ # load the list of values
+ l := load_strings(f) | fail
+
+ # break them down into an ext_rec record
+ r := ext_rec()
+ s := get(l) | fail
+ s ? {
+ r.id := tab(upto(':')) | fail; move(1)
+ r.typ := tab(upto(':')) | fail; move(1)
+ r.sty := tab(upto(':')) | fail; move(1)
+ r.num := tab(upto(':')) | fail; move(1)
+ r.x := tab(upto(',')) | fail; move(1)
+ r.y := tab(upto(',')) | fail; move(1)
+ r.w := tab(upto(',')) | fail; move(1)
+ r.h := tab(upto(':')) | fail; move(1)
+ r.lbl := tab(0)
+ }
+ r.proc := get(l) | ""
+ r.etc := get(l) | []
+ return r
+end
+
+############################################################################
+# load_strings() reads a list of strings after "[" has already been consumed.
+############################################################################
+procedure load_strings(f)
+ local l, c, s, n
+
+ l := []
+ n := 0
+ while c := reads(f, 1) do case c of {
+
+ "]": return l # end of list
+ ",": (n <:= *l) | put(l, &null)
+ " ": next # whitespace: do nothing
+ "\t": next
+ "\r": next
+ "\n": next
+ "[": put(l, load_strings(f)) # nested list
+
+ "\"": { # string constant
+ s := ""
+ while (c := reads(f, 1)) & not upto('"\n"', c) do
+ if s == "\\" then
+ s ||:= reads(f, 1)
+ else
+ s ||:= c
+ put(l, s)
+ }
+
+ default: { # anything else: consume to separator
+ s := c
+ while (c := reads(f, 1)) & not upto(',] \t\r\n', c) do
+ s ||:= c
+ put(l, s)
+ if c == "]" then
+ return l
+ }
+ }
+
+ fail # EOF hit
+end
+
+############################################################################
+# save_session() saves the current session to a file. If "pflag" is set,
+# the standard prefix is used (for prototype mode).
+############################################################################
+procedure save_session(s, pflag)
+ local ofile
+
+ sanity_check() | fail
+ ofile := open(s, "w")
+ if /ofile then {
+ Notice("Could not open " || s, "(FILE WAS NOT SAVED)")
+ fail
+ }
+ if /SIZER.dlog then
+ save_app(ofile, pflag, s)
+ else
+ save_dlog(ofile, pflag, s)
+ close(ofile)
+ if /pflag then
+ DIRTY := &null
+ return
+end
+
+############################################################################
+# sanity_check() issues warnings if certain things don't look right.
+############################################################################
+procedure sanity_check()
+ local messages, npush, ndflt, nrect, nlist, o
+
+ messages := []
+ npush := ndflt := nrect := nlist := 0
+ every o := !O_LIST do {
+ case type(o) of {
+ "button_obj": {
+ if /o.toggle then npush +:= 1
+ if \o.dflt then ndflt +:= 1
+ }
+ "rect_obj": {
+ nrect +:= 1
+ }
+ "list_obj": {
+ nlist +:= 1
+ }
+ }
+ }
+
+ if \SIZER.dlog then {
+ if ndflt > 1 then
+ put(messages, "",
+ "More than one button is marked as the default.",
+ "Only one will be used.")
+ if npush = 0 then
+ put(messages, "",
+ "There is no non-toggle button, so it will not",
+ "be possible to dismiss the dialog box.")
+ if nrect > 0 | nlist > 0 then
+ put(messages, "",
+ "There are one or more regions or text lists,",
+ "but these do not function in dialog boxes.")
+ }
+ else {
+ if ndflt > 0 then
+ put(messages, "",
+ "A button is marked as a dialog default,",
+ "but this is not a dialog specification.")
+ }
+
+ if *messages = 0 then
+ return
+
+ push(messages, "Warning:")
+ case TextDialog(messages, , , , ["Continue", "Cancel"], 2) of {
+ "Continue": return
+ "Cancel": fail
+ }
+end
+
+############################################################################
+# save_app() saves the session as an application. If "pflag" is set,
+# the standard prefix is used (for prototype mode).
+############################################################################
+procedure save_app(ofile, pflag, filename)
+ local id
+
+ id := ("" ~== \SIZER.id) | "ui"
+
+ if \pflag then
+ write(ofile, PTITLE, "\n\n")
+ if \pflag | /USER_PREFIX then {
+ if /pflag then
+ ipl_header(ofile, filename, "Program to", "vsetup")
+ app_prologue(ofile, id, pflag)
+ if /pflag then
+ save_procs(ofile)
+ }
+ else
+ writes(ofile, USER_PREFIX)
+
+ write(ofile, HEADER)
+ write(ofile, "procedure ", id, "_atts()")
+ writes(ofile, " return [\"size=", SIZER.x + SIZER.w, ",",
+ SIZER.y - CANVASY + SIZER.h, "\", \"bg=", VBackground, "\"")
+ writes(ofile, ", \"label=", "" ~== SIZER.label, "\"")
+ write(ofile, "]")
+ write(ofile,"end")
+ write(ofile)
+ write(ofile, "procedure ", id, "(win, cbk)")
+ write(ofile, "return vsetup(win, cbk,")
+ output_spec(ofile, SIZER)
+ output_all(ofile, O_LIST)
+ write(ofile, " )")
+ write(ofile, "end")
+ write(ofile, TRAILER)
+
+ if /pflag & \USER_SUFFIX then
+ writes(ofile, USER_SUFFIX)
+ return
+end
+
+############################################################################
+# save_procs() generates empty callback procedures in lexical order.
+############################################################################
+procedure save_procs(ofile)
+ local o, t, l
+
+ t := table()
+ every o := !O_LIST do
+ t["" ~== \o.proc] := o
+ l := sort(t, 3)
+ while get(l) do {
+ o := get(l)
+ writes(ofile, "procedure ", o.proc, "(vidget, ")
+ if type(o) == "rect_obj" then
+ write(ofile, "e, x, y)")
+ else
+ write(ofile, "value)")
+ write(ofile, " return")
+ write(ofile, "end")
+ write(ofile)
+ }
+ return
+end
+
+############################################################################
+# save_dlog() saves the session as a dialog. If "pflag" is set,
+# the standard prefix is used (for prototype mode).
+############################################################################
+procedure save_dlog(ofile, pflag, filename)
+ local id
+
+ id := ("" ~== \SIZER.id) | "dl"
+
+ if \pflag then
+ dlog_prototype(ofile, id)
+ else if /USER_PREFIX then {
+ ipl_header(ofile, filename, "Procedure to", "dsetup")
+ dlog_prologue(ofile)
+ }
+ else
+ writes(ofile, USER_PREFIX)
+
+ write(ofile, HEADER)
+ write(ofile, "procedure ", id, "(win, deftbl)")
+ write(ofile, "static dstate")
+ write(ofile, "initial dstate := dsetup(win,")
+ output_spec(ofile, SIZER)
+ output_all(ofile, O_LIST)
+ write(ofile, " )")
+ write(ofile, "return dpopup(win, deftbl, dstate)")
+ write(ofile, "end")
+ write(ofile, TRAILER)
+
+ if /pflag & \USER_SUFFIX then
+ writes(ofile, USER_SUFFIX)
+ return
+end
+
+############################################################################
+# output_all() outputs the members of an object list, sorted by ID,
+# but with rectangles last so that they can enclose other objects.
+############################################################################
+record output_rec(obj, key)
+
+procedure output_all(f, l)
+ local t, e, k
+
+ t := []
+ every e := !l do {
+ if type(e) == "rect_obj" then
+ k := "~" || right(e.w * e.h, 20) || e.id # rects last, by area
+ else
+ k := e.id
+ put(t, output_rec(e, k))
+ }
+ t := sortf(t, 2)
+ every e := !t do
+ output_spec(f, e.obj)
+ return
+end
+
+############################################################################
+# output_spec() outputs the spec for an object.
+############################################################################
+procedure output_spec(f, o)
+ local r
+
+ # set standard fields
+ r := ext_rec(o)
+ r.id := o.id
+ r.proc := o.proc
+ r.x := o.x
+ r.y := o.y - CANVASY
+ r.w := o.w
+ r.h := o.h
+ # set type-dependent fields
+ case type(o) of {
+ "sizer_obj" : save_sizer(r, o)
+ "button_obj" : save_button(r, o)
+ "text_input_obj" : save_text_input(r, o)
+ "line_obj" : save_line(r, o)
+ "rect_obj" : save_rect(r, o)
+ "slider_obj" : save_slider(r, o)
+ "radio_button_obj" : save_radio_button(r, o)
+ "label_obj" : save_label(r, o)
+ "menu_obj" : save_menu(r, o)
+ "list_obj" : save_list_obj(r, o)
+ }
+ writes(f, " [\"")
+ writes(f, r.id, ":", r.typ, ":", r.sty, ":", r.num, ":")
+ writes(f, r.x, ",", r.y, ",", r.w, ",", r.h, ":")
+ writes(f, r.lbl, "\",")
+ if /SIZER.dlog then
+ writes(f, r.proc)
+ if \r.etc then
+ output_list(f, r.etc)
+ write(f, "],")
+ return
+end
+
+############################################################################
+# output_list() outputs a list in Icon form preceded by ",\n".
+############################################################################
+procedure output_list(f, a)
+ local prefix, elem, n
+ static indent
+ initial indent := " "
+
+ n := 0
+ indent ||:= " "
+ writes(f, ",\n", indent, "[")
+ prefix := ""
+ while elem := get(a) do
+ if type(elem) == "list" then {
+ output_list(f, elem)
+ prefix := ",\n" || indent
+ n := 0
+ }
+ else {
+ writes(f, prefix, image(elem))
+ if (n +:= 1) % 5 = 0 then
+ prefix := ",\n" || indent
+ else
+ prefix := ","
+ }
+ writes(f, "]")
+ indent := indent[1:-3]
+end
+
+############################################################################
+# prototype() saves, compiles, and executes the current session.
+############################################################################
+procedure prototype()
+ local f, line
+
+ if f := open(PROTOFILE) then {
+ line := read(f)
+ close(f)
+ if \line & not (line ? =PTITLE) then {
+ Notice("Cannot create prototype file " || PROTOFILE || ":",
+ "it already contains something that is not a VIB prototype")
+ fail
+ }
+ }
+
+ # write source file
+ if save_session(PROTOFILE, 1) then {
+ # translate and execute
+ WAttrib("pointer=" || ("wait" | "watch"))
+ system(BUILDPROTO)
+ remove(PROTOFILE)
+ WAttrib("pointer=" || ("left ptr" | "arrow"))
+ system(EXECPROTO)
+ }
+end
+
+############################################################################
+# newname() invents a name when creating a new file.
+############################################################################
+procedure newname()
+ local s, i, f
+
+ every i := seq() do {
+ s := "app" || i || ".icn" # invent "app<n>.icn" file name
+ if f := open(s) then
+ close(f) # can't use this name; already exists
+ else
+ return s # found a safe new name
+ }
+end
+
+############################################################################
+# ipl_header() writes a standard IPL application header.
+############################################################################
+procedure ipl_header(ofile, filename, subject, links)
+ local hline, date
+
+ hline := repl("#", 76)
+ &dateline ? {
+ tab(upto(',') + 2)
+ date := tab(upto(',') + 6)
+ }
+
+ write(ofile, hline)
+ write(ofile, "#\n#\tFile: ", filename)
+ write(ofile, "#\n#\tSubject: ", subject, " ...")
+ write(ofile, "#\n#\tAuthor: ")
+ write(ofile, "#\n#\tDate: ", date)
+ write(ofile, "#\n", hline)
+ write(ofile, "#\n#\n#\n", hline)
+ write(ofile, "#\n# Requires:\n#\n", hline)
+ write(ofile, "#\n# Links: ", links)
+ write(ofile, "#\n", hline)
+ write(ofile)
+ return
+end
+
+############################################################################
+# app_prologue() writes a main program and other code for a new application.
+############################################################################
+procedure app_prologue(f, id, pflag)
+ local vecho, e
+
+ if \pflag then
+ vecho := ", VEcho"
+ else
+ vecho := ""
+
+ every write(f, ![
+ "# This vib interface specification is a working program that responds",
+ "# to vidget events by printing messages. Use a text editor to replace",
+ "# this skeletal program with your own code. Retain the vib section at",
+ "# the end and use vib to make any changes to the interface.",
+ "",
+ "link vsetup",
+ "",
+ "procedure main(args)",
+ " local vidgets, root, paused",
+ "",
+ " (WOpen ! " || id || "_atts()) | stop(\"can't open window\")",
+ " vidgets := " || id || "(" || vecho || ")\t\t\t\t# set up vidgets",
+ " root := vidgets[\"root\"]"
+ ])
+
+ # generate a sample VSetItems call for every list object (prototyping only)
+ if \pflag then
+ every e := !O_LIST do
+ if type(e) == "list_obj" then
+ write(f, " VSetItems(vidgets[\"", e.id,
+ "\"], [\"a\", \"b\", \"c\", \"d\"])");
+
+ every write(f, ![
+ "",
+ " paused := 1\t\t\t\t\t# flag no work to do",
+ " repeat {",
+ " # handle any events that are available, or",
+ " # wait for events if there is no other work to do",
+ " while (*Pending() > 0) | \\paused do {",
+ " ProcessEvent(root, QuitCheck)",
+ " }",
+ " # if <paused> is set null, code can be added here",
+ " # to perform useful work between checks for input",
+ " }",
+ "end",
+ ""])
+end
+
+############################################################################
+# dlog_prologue() writes a header for a dialog file.
+############################################################################
+procedure dlog_prologue(f)
+every write(f, ![
+ "# Link this dialog specification with the rest of your program code.",
+ "# Use vib to make any changes.",
+ "",
+ "link dsetup",
+ ""])
+end
+
+############################################################################
+# dlog_prototype() writes a header for a dialog prototyping run.
+############################################################################
+procedure dlog_prototype(f, id)
+ write(f, PTITLE)
+ write(f)
+ write(f, "link dsetup, graphics")
+ write(f)
+ write(f, "procedure main(args)")
+ write(f, " remove(", image(PROTOEXE), ")")
+ write(f, " dproto(", id, ", , ",
+ SIZER.x + SIZER.w, ", ", SIZER.y - CANVASY + SIZER.h, ", args)")
+ write(f, "end")
+ write(f)
+end
diff --git a/ipl/gpacks/vib/vibglbl.icn b/ipl/gpacks/vib/vibglbl.icn
new file mode 100644
index 0000000..e226fe8
--- /dev/null
+++ b/ipl/gpacks/vib/vibglbl.icn
@@ -0,0 +1,38 @@
+############################################################################
+#
+# vibglbl.icn -- global variables
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+global SESSION # name of current editing session (file name)
+global DIRTY # dirty bit to inform user of unsaved changes
+global ALIGN # flag indicating current state of align mode
+
+global XORWIN # &window clone clone with "drawop=reverse"
+global APPWIN # &window clipped to application area
+global DRAGWIN # clone with dark background, for dragging
+
+global CANVASY # offset to app coordinate system (below menu bar)
+global PAD # vertical spacing in dialog boxes
+
+global ROOT # root frame for vidgets
+global MENUBAR # vidget for VIB's menu bar
+global SELECT # vidget for "Select" pseudo-menu button
+
+global P_LIST # list of palette objects
+global O_LIST # list of graphical object instances
+global SIZER # sizer object that gets dragged around the canvas
+
+global FOCUS # current object of focus (if any)
+global DELETED # last object deleted (if any)
+
+global LBMASK # cset of chars allowed in object label
+global IDMASK # cset of chars allowed in object index (table key)
+global CBMASK # cset of chars allowed in callback or other Icon ID
+
+# external representation record
+record ext_rec(id, typ, sty, num, x, y, w, h, lbl, proc, etc)
diff --git a/ipl/gpacks/vib/viblabel.icn b/ipl/gpacks/vib/viblabel.icn
new file mode 100644
index 0000000..54e71dd
--- /dev/null
+++ b/ipl/gpacks/vib/viblabel.icn
@@ -0,0 +1,125 @@
+############################################################################
+#
+# viblabel.icn -- procedures for defining a label object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+
+##########################################################################
+# label_obj:
+# v : vidget used for drawing label
+# proc : name of user callback procedure (unused for a label)
+# id : unique means of identifying instance
+# x,y,w,h : bounding box
+# label : label itself
+# focus : should focus lines be drawn around this object?
+##########################################################################
+record label_obj(v, proc, id, x, y, w, h, label, focus)
+
+##########################################################################
+# create_label() creates a label instance and draws the label if
+# it is a first class object.
+##########################################################################
+procedure create_label(x, y, label)
+ local r, id
+
+ id := next_id("label")
+ r := label_obj(, "", "label" || id, x, y, 0, 0, label, 0)
+ r.v := Vmessage(ROOT, x, y, APPWIN, label)
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# draw_label() draws the given label instance.
+##########################################################################
+procedure draw_label(r)
+ r.v.s := r.label
+ VDraw(r.v)
+end
+
+##########################################################################
+# update_label_bb() disallows resizing of a label.
+##########################################################################
+procedure update_label_bb(object)
+ object.w := TextWidth(APPWIN, object.label)
+ object.h := WAttrib(APPWIN, "fheight")
+end
+
+##########################################################################
+# load_label() restores a label object from session code.
+##########################################################################
+procedure load_label(r, o)
+ r.label := o.lbl
+ r.v := Vmessage(ROOT, r.x, r.y, APPWIN, r.label)
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# save_label() augments the record for saving a label object.
+##########################################################################
+procedure save_label(r, o)
+ r.typ := "Label"
+ r.lbl := image(o.label)[2:-1]
+ return
+end
+
+##########################################################################
+# display_label_atts() displays the attribute sheet with the current
+# attributes for the given label instance.
+##########################################################################
+procedure display_label_atts(object)
+ local t
+
+ t := table()
+ t["a_label"] := object.label
+ t["b_id"] := object.id
+ t["c_x"] := object.x
+ t["d_y"] := object.y - CANVASY
+
+ repeat {
+ if label_dialog(t) == "Cancel" then
+ fail
+
+ if illegal(t["a_label"], "Label", "l") |
+ illegal(t["b_id"], "ID", "s") |
+ illegal(t["c_x"], "X", "i") |
+ illegal(t["d_y"], "Y", "i")
+ then
+ next
+
+ if *t["a_label"] = 0 then {
+ Notice("Label value must be specified")
+ next
+ }
+
+ object.label := t["a_label"]
+ object.id := t["b_id"]
+
+ unfocus_object(object)
+ move_object(object, t["c_x"], t["d_y"] + CANVASY)
+ focus_object(object)
+ break
+ }
+end
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure label_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["label_dialog:Sizer::1:0,0,460,180:",],
+ ["_cancel:Button:regular::250,120,50,30:Cancel",],
+ ["_okay:Button:regular:-1:180,120,50,30:Okay",],
+ ["a_label:Text::50:13,14,430,19:label: \\=",],
+ ["b_id:Text::40:13,35,360,19:ID: \\=",],
+ ["c_x:Text::3:13,62,101,19: x: \\=",],
+ ["d_y:Text::3:13,83,101,19: y: \\=",],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/vibline.icn b/ipl/gpacks/vib/vibline.icn
new file mode 100644
index 0000000..16f3d89
--- /dev/null
+++ b/ipl/gpacks/vib/vibline.icn
@@ -0,0 +1,197 @@
+############################################################################
+#
+# vibline.icn -- procedures for defining a line object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+
+##########################################################################
+# line_obj:
+# proc : name of user callback procedure
+# v : vidget used for drawing line
+# id : unique means of identifying instance
+# x,y,w,h : bounding box
+# x1,y1 : one endpoint
+# y1,y2 : other endpoint
+# focus : should focus lines be drawn around this object?
+##########################################################################
+record line_obj(v, proc, id, x, y, w, h, x1, y1, x2, y2, focus)
+
+##########################################################################
+# create_line() creates a line instance and draws the line if
+# it is a first class object.
+##########################################################################
+procedure create_line(x1, y1, x2, y2)
+ local r, id
+
+ id := next_id("line")
+ r := line_obj(, "", "line" || id, , , , , x1, y1, x2, y2, 0)
+ r.v := Vline(APPWIN, x1, y1, x2, y2)
+ VInsert(ROOT, r.v, x1, y1)
+ VRemove(ROOT, r.v, 1)
+ update_line_bb(r)
+ return r
+end
+
+##########################################################################
+# update_line_bb() updates various attributes of the line that
+# change when the button is resized, etc.
+##########################################################################
+procedure update_line_bb(object)
+ if object.x1 < 0 then {
+ object.x2 -:= object.x1
+ object.x1 := 0
+ }
+ if object.x2 < 0 then {
+ object.x1 -:= object.x2
+ object.x2 := 0
+ }
+ if object.y1 < CANVASY then {
+ object.y2 -:= (object.y1 - CANVASY)
+ object.y1 := CANVASY
+ }
+ if object.y2 < CANVASY then {
+ object.y1 -:= (object.y2 - CANVASY)
+ object.y2 := CANVASY
+ }
+ object.x := minimum(object.x1, object.x2) - 2
+ object.y := minimum(object.y1, object.y2) - 2
+ object.w := abs(object.x1 - object.x2) + 4
+ object.h := abs(object.y1 - object.y2) + 4
+end
+
+##########################################################################
+# draw_line() draws the given line object.
+##########################################################################
+procedure draw_line(r)
+ r.v.ax1 := r.x1
+ r.v.ay1 := r.y1
+ r.v.ax2 := r.x2
+ r.v.ay2 := r.y2
+ VDraw(r.v)
+ return r
+end
+
+##########################################################################
+# outline_line() draws an outline for the given line. Outlines are
+# used when the object is moved or resized.
+##########################################################################
+procedure outline_line(r)
+ DrawLine(XORWIN, r.x1, r.y1, r.x2, r.y2)
+end
+
+##########################################################################
+# drag_line() is a special procedure for dragging line objects.
+##########################################################################
+procedure drag_line(r)
+ local xoff, yoff, x1, y1, dx, dy
+
+ x1 := r.x1
+ y1 := r.y1
+ dx := r.x2 - x1
+ dy := r.y2 - y1
+ xoff := x1 - &x
+ yoff := y1 - &y
+ DrawLine(XORWIN, x1, y1, x1 + dx, y1 + dy)
+ until Event(XORWIN) === (&lrelease | &mrelease | &rrelease) do {
+ DrawLine(XORWIN, x1, y1, x1 + dx, y1 + dy)
+ x1 := &x + xoff
+ y1 := &y + yoff
+ DrawLine(XORWIN, x1, y1, x1 + dx, y1 + dy)
+ }
+ DrawLine(XORWIN, x1, y1, x1 + dx, y1 + dy)
+ &x := r.x + x1 - r.x1
+ &y := r.y + y1 - r.y1
+end
+
+##########################################################################
+# load_line() restores a line object from session code.
+##########################################################################
+procedure load_line(r, o)
+ r.x1 := o.x
+ r.y1 := o.y + CANVASY
+ r.x2 := o.w
+ r.y2 := o.h + CANVASY
+ r.v := Vline(APPWIN, r.x1, r.y1, r.x2, r.y2)
+ VInsert(ROOT, r.v, r.x1, r.y1)
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# save_line() augments the record for saving a line object.
+##########################################################################
+procedure save_line(r, o)
+ r.typ := "Line"
+ r.x := o.x1
+ r.y := o.y1 - CANVASY
+ r.w := o.x2
+ r.h := o.y2 - CANVASY
+ r.proc := &null
+ return
+end
+
+##########################################################################
+# display_line_atts() displays the attribute sheet with the current
+# attributes for the given line instance.
+##########################################################################
+procedure display_line_atts(object)
+ local t, dx, dy
+
+ t := table()
+ t["a_id"] := object.id
+ t["c_x1"] := object.x1
+ t["d_y1"] := object.y1 - CANVASY
+ t["e_x2"] := object.x2
+ t["f_y2"] := object.y2 - CANVASY
+
+ repeat {
+ if line_dialog(t) == "Cancel" then
+ fail
+
+ if illegal(t["a_id"], "ID", "s") |
+ illegal(t["c_x1"], "X1", "i") |
+ illegal(t["d_y1"], "Y1", "i") |
+ illegal(t["e_x2"], "X2", "i") |
+ illegal(t["f_y2"], "Y2", "i")
+ then
+ next
+
+ unfocus_object(object)
+ erase_object(object)
+
+ object.id := t["a_id"]
+ object.x1 := t["c_x1"]
+ object.y1 := t["d_y1"] + CANVASY
+ object.x2 := t["e_x2"]
+ object.y2 := t["f_y2"] + CANVASY
+
+ # can't just do a move_object() here: doesn't work for line changes
+ update_line_bb(object)
+ draw_canvas()
+ focus_object(object)
+ DIRTY := 1
+ break
+ }
+end
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure line_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["line_dialog:Sizer::1:0,0,350,138:",],
+ ["_cancel:Button:regular::192,87,50,30:Cancel",],
+ ["_okay:Button:regular:-1:127,86,50,30:Okay",],
+ ["a_id:Text::40:13,14,318,19:ID: \\=",],
+ ["c_x1:Text::3:13,42,59,19:x1: \\=",],
+ ["d_y1:Text::3:81,42,59,19:y1: \\=",],
+ ["e_x2:Text::3:204,42,59,19:x2: \\=",],
+ ["f_y2:Text::3:272,42,59,19:y2: \\=",],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/viblist.icn b/ipl/gpacks/vib/viblist.icn
new file mode 100644
index 0000000..66fc813
--- /dev/null
+++ b/ipl/gpacks/vib/viblist.icn
@@ -0,0 +1,168 @@
+############################################################################
+#
+# viblist.icn -- procedures for defining a list object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vdefns.icn"
+$include "vibdefn.icn"
+
+$define MINIMUM_HEIGHT (VSlider_DefWidth * VSlider_MinAspect)
+$define MINIMUM_WIDTH (VFWidth + VSlider_DefWidth + 10)
+$define DEFAULT_HEIGHT 100
+$define DEFAULT_WIDTH 100
+$define DEFAULT_STYLE "w"
+$define DEFAULT_SCROLL 0
+
+##########################################################################
+# list_obj:
+# v : vidget used for drawing list object
+# proc : name of user callback procedure
+# id : unique means of identifying instance
+# x,y,w,h : bounding box
+# style : "r", "w", or "a" indicating list editing mode
+# scroll : 1 for passive scrolling that waits for mouse release
+##########################################################################
+record list_obj(v, proc, id, x, y, w, h, style, scroll, focus)
+
+##########################################################################
+# create_list() creates a list instance and draws it.
+##########################################################################
+procedure create_list(x, y, w, h, style, scroll)
+ local r, id
+
+ /w := DEFAULT_WIDTH
+ /h := DEFAULT_HEIGHT
+ /style := DEFAULT_STYLE
+ /scroll := DEFAULT_SCROLL
+ id := next_id("list")
+ r := list_obj(, "list_cb" || id, "list" || id, x, y, w, h, style, scroll)
+ r.v := Vlist(ROOT, x, y, APPWIN, , id, [], scroll, w, h, style)
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# draw_list() draws the given list object.
+##########################################################################
+procedure draw_list(r)
+ VResize(r.v)
+ VDraw(r.v)
+ return r
+end
+
+##########################################################################
+# update_list_bb() enforces a minimum size when resizing.
+##########################################################################
+procedure update_list_bb(object)
+ object.w <:= MINIMUM_WIDTH
+ object.h <:= MINIMUM_HEIGHT
+end
+
+##########################################################################
+# load_list() restores a list object from session code.
+##########################################################################
+procedure load_list(r, o)
+ r.style := o.sty
+ if integer(o.num) > 0 then
+ r.scroll := 1
+ else
+ r.scroll := &null
+ r.v := Vlist(ROOT, r.x, r.y,
+ APPWIN, , r.id, [], r.scroll, r.w, r.h, r.style)
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# save_list_obj() augments the record for saving a list object.
+# (_obj is in the name due to a name conflict with a library procedure.)
+##########################################################################
+procedure save_list_obj(r, o)
+ r.typ := "List"
+ r.sty := o.style
+ r.num := o.scroll
+ return
+end
+
+##########################################################################
+# display_list_atts() displays the attribute sheet with the current
+# attributes for the given list instance.
+##########################################################################
+procedure display_list_atts(object)
+ local t
+
+ t := table()
+ t["a_id"] := object.id
+ t["b_callback"] := object.proc
+ t["c_x"] := object.x
+ t["d_y"] := object.y - CANVASY
+ t["e_width"] := object.w
+ t["f_height"] := object.h
+
+ t["g_style"] := case object.style of {
+ "r" : "read only"
+ "w" : "select one"
+ "a" : "select many"
+ }
+
+ repeat {
+ if list_dialog(t) == "Cancel" then
+ fail
+
+ if illegal(t["a_id"], "ID", "s") |
+ illegal(t["b_callback"], "Callback", "p") |
+ illegal(t["c_x"], "X", "i") |
+ illegal(t["d_y"], "Y", "i") |
+ illegal(t["e_width"], "Width", MINIMUM_WIDTH) |
+ illegal(t["f_height"], "Height", MINIMUM_HEIGHT)
+ then
+ next
+
+ object.id := t["a_id"]
+ object.proc := t["b_callback"]
+
+ object.style := case t["g_style"] of {
+ "read only" : "r"
+ "select one" : "w"
+ "select many" : "a"
+ }
+
+ unfocus_object(object)
+ move_object(object,
+ t["c_x"], t["d_y"] + CANVASY, t["e_width"], t["f_height"])
+
+ # delete and recreate the vidget in case the style changed
+ erase_object(object)
+ object.v := Vlist(ROOT, object.x, object.y, APPWIN, , object.id,
+ [], object.scroll, object.w, object.h, object.style)
+ VRemove(ROOT, object.v)
+
+ draw_object(object)
+ focus_object(object)
+ break
+ }
+end
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure list_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["list_dialog:Sizer::1:0,0,383,198:",],
+ ["_cancel:Button:regular::197,148,50,30:Cancel",],
+ ["_okay:Button:regular:-1:130,148,50,30:Okay",],
+ ["a_id:Text::40:13,14,360,19:ID: \\=",],
+ ["b_callback:Text::40:13,35,360,19:callback: \\=",],
+ ["c_x:Text::3:13,62,101,19: x: \\=",],
+ ["d_y:Text::3:13,83,101,19: y: \\=",],
+ ["e_width:Text::3:129,63,101,19: width: \\=",],
+ ["f_height:Text::3:129,84,101,19: height: \\=",],
+ ["g_style:Choice::3:266,59,106,63:",,
+ ["read only","select one","select many"]],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/vibmenu.icn b/ipl/gpacks/vib/vibmenu.icn
new file mode 100644
index 0000000..d9d4c1e
--- /dev/null
+++ b/ipl/gpacks/vib/vibmenu.icn
@@ -0,0 +1,468 @@
+############################################################################
+#
+# vibmenu.icn -- procedures for defining a menu object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vdefns.icn"
+$include "vibdefn.icn"
+
+global startyMENU, MENU_TALK
+global MENU_VIDGET
+global reg_list, ins_list
+global SIM_TAB
+
+##########################################################################
+# menu_obj:
+# v : vidget used for drawing menu
+# proc : name of user callback procedure
+# id : unique means of identifying instance
+# x,y,w,h : bounding box
+# label : menu button label
+# lx,ly : label coordinates
+# style : style of menu ... currently only pull down is supported
+# focus : should focus lines be drawn around this object?
+# items : a list of menu items that make up the menu
+#
+# menu_item:
+# label : menu choice name
+# items : a list of menu_items for a submenu, or an empty list
+#
+# menu_id:
+# v : text vidget for label field
+# item : corresponding menu_item record
+##########################################################################
+
+record menu_obj(v, proc, id, x, y, w, h, label, lx, ly, style, focus, items)
+record menu_item(label, items)
+record menu_id(tv, item)
+
+##########################################################################
+# create_menu() creates a menu instance and draws the menu button.
+##########################################################################
+procedure create_menu(x, y, label, style)
+ local r, id
+
+ id := next_id("menu")
+ /style := "pull"
+ r := menu_obj(, "menu_cb" || id, "menu" || id,
+ x, y, 0, 0, label, 0, 0, style, 0, [])
+ r.v := Vbutton(ROOT, x, y, APPWIN, label, , id, V_RECT)
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# copy_submenu() recursively copies a cascading menu.
+##########################################################################
+procedure copy_submenu(old, temp)
+ local i
+
+ /temp := copy(old)
+ if *old.items > 0 then {
+ temp.items := []
+ every put(temp.items, copy_submenu(!old.items))
+ }
+ return temp
+end
+
+##########################################################################
+# copy_menu() makes a copy of a menu old and returns it in new.
+##########################################################################
+procedure copy_menu(new, old)
+ every put(new.items, copy_submenu(!old.items))
+end
+
+##########################################################################
+# add_item() adds a menu choice with name "label" to the menu at the
+# location indicated by "after".
+##########################################################################
+procedure add_item(menu, label, after)
+ local choice
+
+ after >:= *menu.items
+ choice := menu_item(label, [])
+ menu.items := menu.items[1:after+1] ||| [choice] ||| menu.items[after+1:0]
+end
+
+##########################################################################
+# update_menu_bb() updates various attributes of the menu that
+# change when the menu button label is altered.
+##########################################################################
+procedure update_menu_bb(object)
+ object.w := object.v.aw # disallow changes
+ object.h := object.v.ah
+ # .lx/.ly values must agree with locations drawn by menu vidgets
+ # else the simulation of a menu leaves the label in the wrong place
+ # and moving the menu then leaves debris behind on the screen
+ object.lx := object.x + 4
+ object.ly := object.y + WAttrib(APPWIN, "ascent") + 4
+end
+
+##########################################################################
+# draw_menu() draws the given menu button object.
+##########################################################################
+procedure draw_menu(r)
+ VResize(r.v, r.x, r.y, r.w, r.h)
+ VDraw(r.v)
+ return r
+end
+
+##########################################################################
+# load_menu() restores a menu object from session code.
+##########################################################################
+procedure load_menu(r, o)
+ r.style := o.sty
+ r.label := o.lbl
+ r.items := load_submenu(o.etc)
+ r.v := Vbutton(ROOT, r.x, r.y, APPWIN, r.label, , r.id, V_RECT)
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# load_submenu() restores a menu or submenu list.
+##########################################################################
+procedure load_submenu(spec)
+ local i, r, lst
+
+ lst := []
+ while i := get(spec) do {
+ r := menu_item()
+ r.label := i
+ if type(spec[1]) == "list" then {
+ r.items := load_submenu(get(spec))
+ }
+ else
+ r.items := []
+ put(lst, r)
+ }
+ return lst
+end
+
+##########################################################################
+# save_menu() augments the record for saving a menu object.
+##########################################################################
+procedure save_menu(r, o)
+ r.typ := "Menu"
+ r.lbl := o.label
+ r.sty := o.style
+ r.etc := save_submenu(o.items)
+ return
+end
+
+##########################################################################
+# save_submenu() builds a list representing a submenu.
+##########################################################################
+procedure save_submenu(items)
+ local l, i
+ l := []
+ every i := !items do {
+ put(l, i.label)
+ if *i.items > 0 then
+ put(l, save_submenu(i.items))
+ }
+ return l
+end
+
+##########################################################################
+# simulate_sub_menu() is called by simulate_menu to recursively construct
+# WIT submenus and place them in a table for reference
+# by simulate_menu().
+##########################################################################
+procedure simulate_sub_menu(obj, label)
+ local i, temp_list
+
+ every i := 1 to *obj.items do {
+ if *obj.items[i].items > 0 then
+ simulate_sub_menu(obj.items[i], label || "_" || obj.items[i].label)
+ }
+ temp_list := [&window]
+ every i := 1 to *obj.items do {
+ put(temp_list, obj.items[i].label)
+ if *obj.items[i].items > 0 then
+ put(temp_list, SIM_TAB["id_" || label || "_" || obj.items[i].label])
+ else
+ put(temp_list, &null) # null callback
+ }
+ SIM_TAB["id_" || label] := Vsub_menu ! temp_list
+end
+
+##########################################################################
+# simulate_menu() creates a complete WIT menu object so that the
+# VIB user can see what the menu looks like without
+# prototyping.
+##########################################################################
+procedure simulate_menu(obj)
+ local i, temp_list, sim_menu, tmp
+
+ SIM_TAB := table()
+ every i := 1 to *obj.items do {
+ if *obj.items[i].items > 0 then
+ simulate_sub_menu(obj.items[i], obj.items[i].label)
+ }
+ temp_list := [&window]
+ every i := 1 to *obj.items do {
+ put(temp_list, obj.items[i].label)
+ if *obj.items[i].items > 0 then
+ put(temp_list, SIM_TAB["id_" || obj.items[i].label])
+ else
+ put(temp_list, &null) # null callback
+ }
+ sim_menu := Vmenu_bar_item(&window, obj.label, , , , , Vsub_menu ! temp_list)
+ tmp := ScratchCanvas(ROOT.win, obj.w, obj.h)
+ CopyArea(ROOT.win, tmp, obj.x, obj.y, obj.w, obj.h)
+ VInsert(ROOT, sim_menu, obj.x, obj.y)
+ VResize(sim_menu)
+ VEvent(sim_menu, &mpress)
+ VRemove(ROOT, sim_menu, 1)
+ CopyArea(tmp, ROOT.win, 0, 0, obj.w, obj.h, obj.x, obj.y)
+ EraseArea(tmp)
+end
+
+##########################################################################
+# menu_atts() defines the attribute sheet template for a menu object.
+##########################################################################
+procedure menu_atts()
+ local tempy
+
+ MENU_TALK := Vdialog(&window, PAD, PAD)
+ tempy := 0
+ VRegister(MENU_TALK,
+ Vtext(&window, "menu label: ", , 1, TEXTCHARS, LBMASK), 0, tempy)
+ tempy +:= PAD
+ VRegister(MENU_TALK,
+ Vtext(&window, "ID: ", , 2, TEXTCHARS, IDMASK), 0, tempy)
+ tempy +:= PAD
+ VRegister(MENU_TALK,
+ Vtext(&window, "callback: ", , 3, TEXTCHARS, CBMASK), 0, tempy)
+
+ VRegister(MENU_TALK,
+ Vtext(&window, "x: ", , 4, 3, &digits), 80 + TEXTWIDTH + 10, 0)
+ VRegister(MENU_TALK,
+ Vtext(&window, "y: ", , 5, 3, &digits), 80 + TEXTWIDTH + 10, PAD)
+ VFormat(MENU_TALK)
+ startyMENU := tempy
+end
+
+##########################################################################
+# display_menu_atts() displays the attribute sheet with the current
+# attributes for the given menu instance.
+##########################################################################
+procedure display_menu_atts(object)
+ local i, data, send_data, new, v, dw, l
+ initial menu_atts()
+
+ new := copy(object)
+ new.y -:= CANVASY
+ new.items := []
+ copy_menu(new, object)
+
+ repeat {
+
+ menu_list_atts(MENU_TALK, startyMENU, new.items)
+ VFormat(MENU_TALK)
+
+ MENU_VIDGET := &null
+ send_data := [new.label, new.id, new.proc, new.x, new.y]
+ every put(send_data, (!new.items).label)
+ data := VOpenDialog(MENU_TALK, , "menu_dialog", send_data, "Okay")
+ every VUnregister(MENU_TALK, !reg_list)
+ every VRemove(MENU_TALK, !ins_list, 1)
+
+ if data === send_data then
+ fail # cancelled
+
+ new.label := strip(get(data))
+ new.id := strip(get(data))
+ new.proc := strip(get(data))
+ new.x := get(data)
+ new.y := get(data)
+ every (!new.items).label := get(data)
+
+ # if "add" or "del" was pressed, process it and loop to re-post dialog
+ if \MENU_VIDGET then {
+ l := []
+ every i := 1 to *new.items do {
+ v := reg_list[i]
+ if v.ay - PAD < MENU_VIDGET.ay-1 < v.ay then
+ put(l, menu_item("", []))
+ if v.ay ~= MENU_VIDGET.ay-1 then
+ put(l, new.items[i])
+ }
+ if MENU_VIDGET.ay-1 > reg_list[*new.items].ay | *l = 0 then
+ put(l, menu_item("", []))
+ new.items := l
+ next
+ }
+
+ # check for legal field values
+
+ if illegal(new.id, "ID", "s") |
+ illegal(new.label, "Label", "l") |
+ illegal(new.proc, "Callback", "p") |
+ illegal(new.x, "X", "i") |
+ illegal(new.y, "Y", "i")
+ then
+ fail
+
+ # everything is valid
+
+ dw := VFWidth * (*new.label - *object.label)
+
+ object.label := new.label
+ object.id := new.id
+ object.proc := new.proc
+ object.items := new.items
+
+ object.v.s := object.label
+ object.v.aw := object.w + dw
+
+ unfocus_object(object)
+ move_object(object, new.x, new.y + CANVASY, object.w, object.h)
+ focus_object(object)
+ break
+ }
+end
+
+##########################################################################
+# display_submenu_atts() displays the attribute sheet with the current
+# attributes for the given submenu instance.
+##########################################################################
+procedure display_submenu_atts(button, val)
+ local submenu_talk, send_data, data, old_reg, old_ins
+ local entry, items, s, i, v
+
+ old_reg := reg_list
+ old_ins := ins_list
+ entry := button.id.item
+ items := copy(entry.items)
+ if *items = 0 then
+ every 1 to 3 do
+ put(items, menu_item("", []))
+
+ repeat {
+
+ submenu_talk := Vdialog(&window, PAD, PAD)
+ v := Vmessage(&window, "\"" || button.id.tv.data || \"\" submenu entries")
+ VInsert(submenu_talk, v, 0, 0)
+ menu_list_atts(submenu_talk, 0, items)
+ VFormat(submenu_talk)
+
+ MENU_VIDGET := &null
+ send_data := []
+ every put(send_data, (!items).label)
+ data := VOpenDialog(submenu_talk, , "submenu_dialog", send_data, "Okay")
+ every VUnregister(MENU_TALK, !reg_list)
+ every VRemove(MENU_TALK, !ins_list, 1)
+
+ if data === send_data then {
+ reg_list := old_reg
+ ins_list := old_ins
+ fail # cancelled
+ }
+
+ every (!items).label := get(data) # update new labels
+
+ if *(items := update_menu_list(items)) > 0 then
+ next # loop to re-post dialog
+
+ # the revised list has been accepted
+
+ entry.items := items
+ VErase(button)
+ if *items = 0 then
+ s := "create submenu"
+ else
+ s := "edit submenu (" || *items || ")"
+ button.aw +:= VFWidth * (*s - *button.s)
+ button.s := s
+ VResize(button)
+ VDraw(button)
+ break
+ }
+ reg_list := old_reg
+ ins_list := old_ins
+end
+
+##########################################################################
+# menu_list_atts() adds the menu items (with add/del/submenu buttons)
+# and okay/cancel buttons to a dialog box.
+# ins_list and reg_list are set.
+##########################################################################
+procedure menu_list_atts(menu, y, itemlist)
+ local i, s, v, id
+
+ # construct text fields with "add", "del", and "submenu" buttons
+
+ reg_list := []
+ ins_list := []
+ every i := 0 to *itemlist do {
+ y +:= PAD
+
+ v := Vbutton(&window, "add", menu_mod_cb, V_OK, , 28, 17)
+ VInsert(menu, v, 0, y + PAD / 2)
+ put(ins_list, v)
+
+ if i = 0 then
+ next
+
+ v := Vbutton(&window, "del", menu_mod_cb, V_OK, , 28, 17)
+ VInsert(menu, v, 35 + TEXTWIDTH, y + 1)
+ put(ins_list, v)
+
+ v := Vtext(&window, "", , 100 + i, TEXTCHARS, LBMASK)
+ VRegister(menu, v, 35, y)
+ put(reg_list, v)
+ id := menu_id(v, itemlist[i])
+
+ if *itemlist[i].items = 0 then
+ s := "create submenu"
+ else
+ s := "edit submenu (" || *itemlist[i].items || ")"
+ v := Vbutton(&window, s, display_submenu_atts, id, , , 17)
+ VInsert(menu, v, 35 + TEXTWIDTH + 40, y + 1)
+ put(ins_list, v)
+ }
+
+ # add "Okay" and "Cancel"
+ y +:= 2 * PAD
+ v := Vbutton(&window, "Okay", , V_OK, , 50, 30)
+ VInsert(menu, v, TEXTWIDTH / 2 + 30, y)
+ put(ins_list, v)
+ v := Vbutton(&window, "Cancel", , V_CANCEL, , 50, 30)
+ VInsert(menu, v, TEXTWIDTH / 2 + 100, y)
+ put(ins_list, v)
+end
+
+##########################################################################
+# update_menu_list() creates a new item list reflecting adds and deletes.
+##########################################################################
+procedure update_menu_list(oldlist)
+ local newlist, v, i
+
+ if /MENU_VIDGET then
+ fail
+ newlist := []
+ every i := 1 to *oldlist do {
+ v := reg_list[i]
+ if v.ay - PAD < MENU_VIDGET.ay-1 < v.ay then
+ put(newlist, menu_item("", []))
+ if v.ay ~= MENU_VIDGET.ay-1 then
+ put(newlist, oldlist[i])
+ }
+ if MENU_VIDGET.ay-1 > reg_list[*oldlist].ay then
+ put(newlist, menu_item("", []))
+ MENU_VIDGET := &null
+ return newlist
+end
+
+##########################################################################
+# menu_mod_cb is called when an "add" or "del" button is pressed.
+##########################################################################
+procedure menu_mod_cb(v)
+ MENU_VIDGET := v
+end
diff --git a/ipl/gpacks/vib/vibradio.icn b/ipl/gpacks/vib/vibradio.icn
new file mode 100644
index 0000000..b164594
--- /dev/null
+++ b/ipl/gpacks/vib/vibradio.icn
@@ -0,0 +1,209 @@
+############################################################################
+#
+# vibradio.icn -- procedures for defining a radio button object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+
+global RB_starty, RADIO_TALK, RADIO_VIDGET
+
+##########################################################################
+# radio_button_obj:
+# v : vidget used for drawing radio button
+# proc : name of user callback procedure
+# id : unique means of identifying instance
+# x,y,w,h : bounding box
+# focus : should focus lines be drawn around this object?
+# alts : a list of button labels making up the radio button object
+##########################################################################
+record radio_button_obj(v, proc, id, x, y, w, h, focus, alts)
+
+##########################################################################
+# create_radio_button() creates a radio button instance and draws the
+# button if it is a first class object.
+##########################################################################
+procedure create_radio_button(x, y, alts)
+ local r, id
+
+ id := next_id("radio_button")
+ r := radio_button_obj(, "radio_button_cb" || id, "radio_button" || id,
+ x, y, 0, 0, 0, alts)
+ r.v := Vradio_buttons(ROOT, x, y, APPWIN, alts, , id, V_DIAMOND_NO)
+ r.w := r.v.aw
+ r.h := r.v.ah
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# update_radio_bb() disallows resizing of a radio button object.
+##########################################################################
+procedure update_radio_bb(object)
+ object.w := object.v.aw
+ object.h := object.v.ah
+end
+
+##########################################################################
+# draw_radio_button() draws the given radio button object.
+##########################################################################
+procedure draw_radio_button(r)
+ VDraw(r.v)
+ return r
+end
+
+##########################################################################
+# load_radio_button() restores a radio button object from session code.
+##########################################################################
+procedure load_radio_button(r, o)
+ r.alts := o.etc
+ r.v := Vradio_buttons(ROOT, r.x, r.y, APPWIN, r.alts, , r.id, V_DIAMOND_NO)
+ r.w := r.v.aw
+ r.h := r.v.ah
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# save_radio_button() augments the record for saving a radio_button object.
+##########################################################################
+procedure save_radio_button(r, o)
+ r.typ := "Choice"
+ r.num := *o.alts
+ r.etc := copy(o.alts)
+ return
+end
+
+##########################################################################
+# radio_button_atts() defines the attribute sheet template for a radio
+# button object.
+##########################################################################
+procedure radio_button_atts()
+ local tempy
+
+ RADIO_TALK := Vdialog(&window, PAD, PAD)
+ tempy := 0
+ VRegister(RADIO_TALK,
+ Vtext(&window, "ID: ",, 1, TEXTCHARS, IDMASK), 0, tempy)
+ tempy +:= PAD
+ VRegister(RADIO_TALK,
+ Vtext(&window, "callback: ",, 3, TEXTCHARS, CBMASK), 0, tempy)
+ tempy +:= (3 * PAD)/2
+ VRegister(RADIO_TALK, Vtext(&window, " x: ",, 4, 3, &digits), 0, tempy)
+ tempy +:= PAD
+ VRegister(RADIO_TALK, Vtext(&window, " y: ",, 5, 3, &digits), 0, tempy)
+ VFormat(RADIO_TALK)
+ RB_starty := tempy
+end
+
+##########################################################################
+# display_radio_button_atts() displays the attribute sheet with the current
+# attributes for the given radio button instance.
+##########################################################################
+procedure display_radio_button_atts(object)
+ local tempy, i, send_data, data, new, v, ok, nok, reg_list, ins_list, l
+ initial radio_button_atts()
+
+ new := copy(object)
+ new.y -:= CANVASY
+ new.alts := copy(object.alts)
+
+ repeat {
+ reg_list := []
+ ins_list := []
+ tempy := RB_starty
+
+ # construct text fields and "add" and "del" buttons
+ every i := 0 to *new.alts do {
+ tempy +:= PAD
+ v := Vbutton(&window, "add", radio_cb, V_OK, , 28, 17)
+ VInsert(RADIO_TALK, v, 0, tempy + PAD / 2)
+ put(ins_list, v)
+ if i = 0 then
+ next
+ v := Vbutton(&window, "del", radio_cb, V_OK, , 28, 17)
+ VInsert(RADIO_TALK, v, 35 + TEXTWIDTH, tempy + 1)
+ put(ins_list, v)
+ v := Vtext(&window, "", , 5 + i, TEXTCHARS, LBMASK)
+ VRegister(RADIO_TALK, v, 35, tempy)
+ put(reg_list, v)
+ }
+
+ # add "Okay" and "Cancel"
+ tempy +:= 2 * PAD
+ ok := Vbutton(&window, "Okay", , V_OK, , 50, 30)
+ nok := Vbutton(&window, "Cancel", , V_CANCEL, , 50, 30)
+ VInsert(RADIO_TALK, ok, TEXTWIDTH / 2 - 30, tempy)
+ VInsert(RADIO_TALK, nok, TEXTWIDTH / 2 + 40, tempy)
+ put(ins_list, ok, nok)
+
+ # post the dialog
+ RADIO_VIDGET := &null
+ VFormat(RADIO_TALK)
+ send_data := [new.id, new.proc, new.x, new.y] ||| new.alts
+ data := VOpenDialog(RADIO_TALK, , "radio_dialog", send_data, "Okay")
+ every VUnregister(RADIO_TALK, !reg_list)
+ every VRemove(RADIO_TALK, !ins_list, 1)
+
+ if data === send_data then
+ fail # cancelled
+
+ # save new values
+ new.id := strip(get(data))
+ new.proc := strip(get(data))
+ new.x := get(data)
+ new.y := get(data)
+ every !new.alts := get(data)
+
+ # if "add" or "del" was pressed, process it and loop to re-post dialog
+ if \RADIO_VIDGET then {
+ l := []
+ every v := reg_list[1 to *new.alts] do {
+ if v.ay - PAD < RADIO_VIDGET.ay-1 < v.ay then
+ put(l, "")
+ if v.ay ~= RADIO_VIDGET.ay-1 then
+ put(l, v.data)
+ }
+ if RADIO_VIDGET.ay-1 > reg_list[*new.alts].ay | *l = 0 then
+ put(l, "")
+ new.alts := l
+ next
+ }
+
+ # check for legal field values
+ if illegal(new.id, "ID", "s") |
+ illegal(new.proc, "Callback", "p") |
+ illegal(new.x, "X", "i") |
+ illegal(new.y, "Y", "i")
+ then
+ next
+
+ # everything is valid
+ object.proc := new.proc
+ object.id := new.id
+ object.alts := new.alts
+
+ unfocus_object(object)
+ EraseArea(object.x, object.y, object.w, object.h)
+
+ object.v := Vradio_buttons(ROOT,
+ object.x, object.y, APPWIN, new.alts, , object.v.id, V_DIAMOND_NO)
+ object.w := object.v.aw
+ object.h := object.v.ah
+ VRemove(ROOT, object.v, 1)
+
+ move_object(object, new.x, new.y + CANVASY, object.w, object.h)
+ focus_object(object)
+ break
+ }
+end
+
+##########################################################################
+# radio_cb is called when an "add" or "del" button is pressed.
+##########################################################################
+procedure radio_cb(v)
+ RADIO_VIDGET := v
+end
diff --git a/ipl/gpacks/vib/vibrect.icn b/ipl/gpacks/vib/vibrect.icn
new file mode 100644
index 0000000..5d98757
--- /dev/null
+++ b/ipl/gpacks/vib/vibrect.icn
@@ -0,0 +1,135 @@
+############################################################################
+#
+# vibrect.icn -- procedures for defining an area object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+
+##########################################################################
+# rect_obj:
+# v : vidget used for drawing rectangle
+# proc : name of user callback procedure
+# id : unique means of identifying a rectangle instance
+# x,y,w,h : bounding box
+# style : invisible, sunken, grooved, raised
+# focus : should focus lines be drawn around this object?
+##########################################################################
+record rect_obj(v, proc, id, x, y, w, h, style, focus)
+
+##########################################################################
+# create_rect() creates a rect instance and draws the rect if
+# it is a first class object.
+##########################################################################
+procedure create_rect(x, y, w, h, style)
+ local r, id
+
+ id := next_id("region")
+ r := rect_obj(, "region_cb" || id, "region" || id, x, y, w, h, style, 0)
+ r.v := Vpane(ROOT, x, y, APPWIN, , id, style, w, h)
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# draw_rect() draws the given rect instance.
+##########################################################################
+procedure draw_rect(r)
+ if r.style == "invisible" then {
+ WAttrib(APPWIN, "linestyle=dashed")
+ DrawRectangle(APPWIN, r.x, r.y, r.w - 1, r.h - 1)
+ WAttrib(APPWIN, "linestyle=solid")
+ }
+ else
+ VDraw(r.v)
+ return r
+end
+
+##########################################################################
+# load_rect() restores a rect object from session code.
+##########################################################################
+procedure load_rect(r, o)
+ if o.sty ~== "" then
+ r.style := o.sty
+ else if integer(o.num) > 0 then
+ r.style := "grooved"
+ else
+ r.style := "invisible"
+ r.v := Vpane(ROOT, r.x, r.y, APPWIN, , r.id, r.style, r.w, r.h)
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# save_rect() augments the record for saving a rect object.
+##########################################################################
+procedure save_rect(r, o)
+ r.typ := "Rect"
+ r.sty := o.style
+ return
+end
+
+##########################################################################
+# display_rect_atts() displays the attribute sheet with the current
+# attributes for the given rect instance.
+##########################################################################
+procedure display_rect_atts(object)
+ local t
+
+ t := table()
+ t["_style"] := object.style
+ t["a_id"] := object.id
+ t["b_callback"] := object.proc
+ t["c_x"] := object.x
+ t["d_y"] := object.y - CANVASY
+ t["e_width"] := object.w
+ t["f_height"] := object.h
+
+ repeat {
+ if rect_dialog(t) == "Cancel" then
+ fail
+
+ if illegal(t["a_id"], "ID", "s") |
+ illegal(t["b_callback"], "Callback", "p") |
+ illegal(t["c_x"], "X", "i") |
+ illegal(t["d_y"], "Y", "i") |
+ illegal(t["e_width"], "Width", MIN_W) |
+ illegal(t["f_height"], "Height", MIN_H)
+ then
+ next
+
+ object.v.style := object.style := t["_style"]
+ object.id := t["a_id"]
+ object.proc := t["b_callback"]
+ unfocus_object(object)
+ move_object(object,
+ t["c_x"], t["d_y"] + CANVASY, t["e_width"], t["f_height"])
+ focus_object(object)
+ break
+ }
+end
+
+
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure rect_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["rect_dialog:Sizer::1:0,0,388,216:",],
+ ["_cancel:Button:regular::216,167,50,30:Cancel",],
+ ["_okay:Button:regular:-1:146,167,50,30:Okay",],
+ ["_style:Choice::4:281,62,92,84:",,
+ ["invisible","sunken","grooved","raised"]],
+ ["a_id:Text::40:13,14,360,19:ID: \\=",],
+ ["b_callback:Text::40:13,35,360,19:callback: \\=",],
+ ["c_x:Text::3:13,62,101,19: x: \\=",],
+ ["d_y:Text::3:13,88,101,19: y: \\=",],
+ ["e_width:Text::3:132,62,101,19: width: \\=",],
+ ["f_height:Text::3:132,88,101,19: height: \\=",],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/vibsizer.icn b/ipl/gpacks/vib/vibsizer.icn
new file mode 100644
index 0000000..dcee0ac
--- /dev/null
+++ b/ipl/gpacks/vib/vibsizer.icn
@@ -0,0 +1,197 @@
+############################################################################
+#
+# vibsizer.icn -- procedures for defining a sizer object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+
+##########################################################################
+# sizer_obj:
+# x,y,w,h : bounding box
+# label : window label
+# id : procedure id (only significant when used as dialog)
+# dlog : is this a dialog box instead of a main window?
+# proc : name of user callback procedure (unused)
+# focus : should focus lines be drawn around this object? (not used)
+# compose : is the object part of another? (not used)
+##########################################################################
+record sizer_obj(x, y, w, h, label, id, dlog, proc, focus, compose)
+
+##########################################################################
+# create_sizer() creates a sizer instance.
+##########################################################################
+procedure create_sizer()
+ local x, y, r
+
+ x := 600 - SZDIM
+ y := 400 - SZDIM + 65
+ x >:= WAttrib("width") - SZDIM - 10
+ y >:= WAttrib("height") - SZDIM - 10
+ r := sizer_obj(x, y, SZDIM, SZDIM, "")
+ return r
+end
+
+##########################################################################
+# move_sizer() erases the sizer, updates its location, and redraws.
+##########################################################################
+procedure move_sizer(r, newx, newy)
+ erase_sizer(r)
+ newx <:= 0
+ newx >:= WAttrib("width") - 11
+ newy <:= CANVASY
+ newy >:= WAttrib("height") - 11
+ r.x := newx
+ r.y := newy
+ draw_sizer(r)
+ DIRTY := 1
+end
+
+############################################################################
+# drag_sizer() resizes the application window by dragging the sizer.
+############################################################################
+procedure drag_sizer()
+ local x, y
+
+ unfocus_object(\FOCUS)
+ x := &x
+ y := &y
+ DrawRectangle(XORWIN, 0, CANVASY, x, y - CANVASY)
+ repeat case Event() of {
+ &ldrag: {
+ DrawRectangle(XORWIN, 0, CANVASY, x, y - CANVASY)
+ x := &x
+ y := &y
+ x <:= SZDIM
+ y <:= SZDIM
+ DrawRectangle(XORWIN, 0, CANVASY, x, y - CANVASY)
+ }
+ &lrelease: {
+ DrawRectangle(XORWIN, 0, CANVASY, x, y - CANVASY)
+ move_sizer(SIZER, x - SZDIM, y - SZDIM)
+ draw_canvas()
+ return
+ }
+ }
+end
+
+##########################################################################
+# draw_sizer() draws the given sizer object.
+##########################################################################
+procedure draw_sizer(r)
+ DrawLine(APPWIN, 0, r.y+SZDIM, r.x+SZDIM, r.y+SZDIM, r.x+SZDIM, CANVASY)
+ BevelRectangle(APPWIN, r.x, r.y, SZDIM, SZDIM, -2)
+ return r
+end
+
+##########################################################################
+# erase_sizer() erases the given sizer object.
+##########################################################################
+procedure erase_sizer(r)
+ EraseArea(APPWIN, r.x, r.y, SZDIM + 1, SZDIM + 1,
+ 0, r.y + SZDIM, r.x, 1, r.x + SZDIM, CANVASY, 1, r.y)
+ return r
+end
+
+##########################################################################
+# load_sizer() restores the sizer object from session code.
+##########################################################################
+procedure load_sizer(r, o)
+ local winw, winh
+
+ winw := WAttrib("width")
+ winh := WAttrib("height")
+ pop(O_LIST) # remove sizer from object list
+ r.label := o.lbl
+ r.x := r.x + r.w - SZDIM
+ r.y := r.y + r.h - SZDIM
+ r.w := r.h := SZDIM
+ r.dlog := ("" ~== o.num)
+ erase_sizer(SIZER)
+ if (r.x + r.w + 11 > winw) | (r.y + r.h + 11 > winh) then {
+ winw <:= r.x + r.w + 11
+ winh <:= r.y + r.h + 11
+ WAttrib("width=" || (ROOT.aw := winw), "height=" || (ROOT.ah := winh))
+ draw_decor()
+ }
+ SIZER := r
+end
+
+##########################################################################
+# save_sizer() augments the record for saving the sizer object.
+##########################################################################
+procedure save_sizer(r, o)
+ r.typ := "Sizer"
+ r.lbl := o.label
+ r.w := r.x + r.w
+ r.h := r.y + r.h
+ r.x := r.y := 0
+ r.num := o.dlog
+ return
+end
+
+##########################################################################
+# display_sizer_atts() displays the attribute sheet with the current
+# attributes for the given sizer instance.
+# This amounts to the window dimensions ...
+##########################################################################
+procedure display_sizer_atts(object)
+ local t
+
+ t := table()
+ t["a_name"] := object.id
+ t["b_label"] := object.label
+ t["c_width"] := object.x + object.w
+ t["d_height"] := object.y + object.h - CANVASY
+ t["_dialog"] := object.dlog
+
+ repeat {
+ if sizer_dialog(t) == "Cancel" then
+ fail
+
+ if illegal(t["a_name"], "Procedure name", "p") |
+ illegal(t["b_label"], "Label", "l") |
+ illegal(t["c_width"], "Width", SZDIM) |
+ illegal(t["d_height"], "Height", SZDIM)
+ then
+ next
+
+ if t["c_width"] >= WAttrib("width") |
+ t["d_height"] >= WAttrib("height") then {
+ Notice("The VIB window is not large enough",
+ "to model a canvas of that size.")
+ next
+ }
+
+ erase_sizer(object)
+ object.id := t["a_name"]
+ object.label := t["b_label"]
+ object.x := t["c_width"] - object.w
+ object.y := t["d_height"] - object.h + CANVASY
+ object.dlog := t["_dialog"]
+ draw_sizer(object)
+ DIRTY := 1
+ break
+ }
+end
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure sizer_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["sizer_dialog:Sizer::1:0,0,500,180:",],
+ ["_cancel:Button:regular::265,125,50,30:Cancel",],
+ ["_dialog:Button:check:1:278,77,118,20:dialog window",],
+ ["_okay:Button:regular:-1:185,125,50,30:Okay",],
+ ["a_name:Text::40:13,14,402,19:procedure name: \\=",],
+ ["b_label:Text::50:13,35,472,19:window label: \\=",],
+ ["c_width:Text::3:13,60,143,19: width: \\=",],
+ ["d_height:Text::3:13,81,143,19: height: \\=",],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/vibslidr.icn b/ipl/gpacks/vib/vibslidr.icn
new file mode 100644
index 0000000..a7fca9e
--- /dev/null
+++ b/ipl/gpacks/vib/vibslidr.icn
@@ -0,0 +1,207 @@
+############################################################################
+#
+# vibslidr.icn -- procedures for defining slider and scrollbar objects
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+$include "vdefns.icn"
+
+##########################################################################
+# slider_obj:
+# v : vidget used for drawing
+# proc : name of user callback procedure
+# filter : filter out dragging events?
+# id : unique identifier
+# x,y,w,h : bounding box
+# min : min value of range
+# max : max value of range
+# value : current value within range
+# typ : "Slider" or "Scrollbar"
+# focus : should focus lines be drawn around this object?
+##########################################################################
+record slider_obj(v, proc, filter, id, x, y, w, h, min, max, value, typ, focus)
+
+##########################################################################
+# create_slider() creates a slider instance and draws the slider.
+##########################################################################
+procedure create_slider(x, y, w, h, typ, min, max, value, filter)
+ local r, id, prefix
+
+ if typ == "Scrollbar" then
+ prefix := "sbar"
+ else
+ prefix := "slider"
+ id := next_id(prefix)
+
+ r := slider_obj(, prefix || "_cb" || id, filter, prefix || id,
+ x, y, w, h, min, max, value, typ, 0)
+
+ r.v := slider_vidget(id, typ, x, y, w, h)
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# slider_vidget() creates the appropriate vidget for a slider or scrollbar.
+##########################################################################
+procedure slider_vidget(id, typ, x, y, w, h)
+ local dir
+
+ dir := if w > h then "h" else "v"
+ return case dir || typ of {
+ "vSlider": Vvert_slider(ROOT, x, y, APPWIN, , id, h, w, 1.0, 0.0)
+ "hSlider": Vhoriz_slider(ROOT, x, y, APPWIN, , id, w, h)
+ "vScrollbar": Vvert_scrollbar(ROOT, x, y, APPWIN, , id, h, w, 1.0, 0.0)
+ "hScrollbar": Vhoriz_scrollbar(ROOT, x, y, APPWIN, , id, w, h)
+ }
+end
+
+##########################################################################
+# update_slider_bb() updates attributes in response to resizing.
+##########################################################################
+procedure update_slider_bb(object)
+ if object.w > object.h then {
+ object.w <:= VSlider_MinAspect * VSlider_MinWidth
+ object.h >:= object.w / VSlider_MinAspect
+ }
+ else {
+ object.h <:= VSlider_MinAspect * VSlider_MinWidth
+ object.w >:= object.h / VSlider_MinAspect
+ }
+end
+
+##########################################################################
+# draw_slider() draws the given slider object.
+##########################################################################
+procedure draw_slider(r)
+ VSetState(r.v, abs((r.value - r.min) / (real(r.max - r.min))))
+ VDraw(r.v)
+ return r
+end
+
+##########################################################################
+# load_slider() restores a slider object from session code.
+##########################################################################
+procedure load_slider(r, o)
+ local dir
+
+ r.filter := ("" ~== o.num)
+ r.typ := o.typ
+ o.lbl ? {
+ r.min := tab(upto(",")); move(1)
+ r.max := tab(upto(",")); move(1)
+ r.value := tab(0)
+ }
+
+ r.v := slider_vidget(r.id, r.typ, r.x, r.y, r.w, r.h)
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# save_slider() augments the record for saving a slider object.
+##########################################################################
+procedure save_slider(r, o)
+ r.typ := o.typ
+ r.lbl := o.min || "," || o.max || "," || o.value
+ r.sty := if r.w > r.h then "h" else "v"
+ r.num := o.filter
+ return
+end
+
+##########################################################################
+# display_slider_atts() displays the attribute sheet with the current
+# attributes for the given slider instance.
+##########################################################################
+procedure display_slider_atts(object)
+ local t, s
+
+ t := table()
+ t["_filter"] := object.filter
+ t["a_id"] := object.id
+ t["b_callback"] := object.proc
+ t["c_x"] := object.x
+ t["d_y"] := object.y - CANVASY
+ t["g_lefttop"] := object.min
+ t["h_initial"] := object.value
+ t["i_rightbot"] := object.max
+
+ if object.w > object.h then {
+ t["j_orientation"] := "horizontal"
+ t["e_length"] := object.w
+ t["f_width"] := object.h
+ }
+ else {
+ t["j_orientation"] := "vertical"
+ t["e_length"] := object.h
+ t["f_width"] := object.w
+ }
+
+ repeat {
+ s := slider_dialog(t)
+ if s == "Cancel" then
+ fail
+
+ if illegal(t["a_id"], "ID", "s") |
+ illegal(t["b_callback"], "Callback", "p") |
+ illegal(t["c_x"], "X", "i") |
+ illegal(t["d_y"], "Y", "i") |
+ illegal(t["f_width"], "Width", VSlider_MinWidth) |
+ illegal(t["e_length"], "Length", t["f_width"] * VSlider_MinAspect) |
+ illegal(t["g_lefttop"], "Left / Top", "n") |
+ illegal(t["h_initial"], "Initial", "n") |
+ illegal(t["i_rightbot"], "Right / Bottom", "n")
+ then
+ next
+
+ if not ((t["g_lefttop"] <= t["h_initial"] <= t["i_rightbot"]) |
+ (t["g_lefttop"] >= t["h_initial"] >= t["i_rightbot"])) then {
+ Notice("Initial value is not between the two extremes")
+ next
+ }
+
+ object.filter := t["_filter"]
+ object.id := t["a_id"]
+ object.proc := t["b_callback"]
+ object.min := t["g_lefttop"]
+ object.value := t["h_initial"]
+ object.max := t["i_rightbot"]
+ unfocus_object(object)
+ if t["j_orientation"] == "horizontal" then
+ move_object(object,
+ t["c_x"], t["d_y"] + CANVASY, t["e_length"], t["f_width"])
+ else
+ move_object(object,
+ t["c_x"], t["d_y"] + CANVASY, t["f_width"], t["e_length"])
+ focus_object(object)
+ break
+ }
+end
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure slider_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["slider_dialog:Sizer::1:0,0,389,276:",],
+ ["_cancel:Button:regular::204,225,50,30:Cancel",],
+ ["_filter:Button:checkno:1:270,132,69,20:filter",],
+ ["_okay:Button:regular:-1:139,224,50,30:Okay",],
+ ["a_id:Text::40:13,14,360,19:ID: \\=",],
+ ["b_callback:Text::40:13,35,360,19:callback: \\=",],
+ ["c_x:Text::3:13,62,101,19: x: \\=",],
+ ["d_y:Text::3:13,83,101,19: y: \\=",],
+ ["e_length:Text::3:13,109,101,19: length: \\=",],
+ ["f_width:Text::3:13,130,101,19: width: \\=",],
+ ["g_lefttop:Text::10:181,62,192,19: top / left: \\=",],
+ ["h_initial:Text::10:181,83,192,19: initial: \\=",],
+ ["i_rightbot:Text::10:181,104,192,19:bottom / right: \\=",],
+ ["j_orientation:Choice::2:15,156,99,42:",,
+ ["vertical","horizontal"]],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib
diff --git a/ipl/gpacks/vib/vibtalk.icn b/ipl/gpacks/vib/vibtalk.icn
new file mode 100644
index 0000000..1ffa2d4
--- /dev/null
+++ b/ipl/gpacks/vib/vibtalk.icn
@@ -0,0 +1,193 @@
+############################################################################
+#
+# vibtalk.icn -- procedures involving dialogue windows
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vibdefn.icn"
+
+global ADD_TALK, DEL_TALK
+
+##########################################################################
+# dialogue() defines pop-up window templates for the various kinds
+# of pop-up windows utilized within VIB.
+##########################################################################
+procedure dialogue()
+ local tempx, tempy, howmany, where
+
+ ADD_TALK := Vdialog(&window, PAD, PAD)
+ howmany := Vtext(&window, "Insert ", , 1, 2, &digits)
+ where := Vtext(&window, "item(s) after item ", , 2, 2, &digits)
+ tempy := 0
+ tempx := 0
+ VRegister(ADD_TALK, howmany, tempx, tempy)
+ tempx +:= howmany.aw + 8
+ VRegister(ADD_TALK, where, tempx, tempy)
+ tempy +:= (3 * PAD)/2
+ VInsert(ADD_TALK, Vbutton(&window, "Okay", , V_OK, , 80, 20), 20, tempy)
+ VInsert(ADD_TALK, Vbutton(&window, "Cancel", , V_CANCEL, , 80, 20),120,tempy)
+ VFormat(ADD_TALK)
+
+ DEL_TALK := Vdialog(&window, PAD, PAD)
+ howmany := Vtext(&window, "delete item(s) ", , 1, 2, &digits)
+ where := Vtext(&window, "thru ", , 2, 2, &digits)
+ tempy := 0
+ tempx := 0
+ VRegister(DEL_TALK, howmany, tempx, tempy)
+ tempx +:= howmany.aw + 8
+ VRegister(DEL_TALK, where, tempx, tempy)
+ tempy +:= (3 * PAD)/2
+ VInsert(DEL_TALK, Vbutton(&window, "Okay", , V_OK, , 80, 20), 20, tempy)
+ VInsert(DEL_TALK, Vbutton(&window, "Cancel", , V_CANCEL, , 80, 20),120,tempy)
+ VFormat(DEL_TALK)
+end
+
+##########################################################################
+# open_session() asks for a file name and opens it as the current session.
+##########################################################################
+procedure open_session()
+ local fname
+
+ repeat {
+ case OpenDialog("file to open: ") of {
+ "Okay": {
+ fname := def_extn(dialog_value)
+ if load_session(fname) then {
+ SESSION := fname
+ label_session()
+ return
+ }
+ Notice("Cannot open file " || fname)
+ }
+ "Cancel":
+ fail
+ }
+ }
+ return
+end
+
+##########################################################################
+# flush_session() asks whether the current session should be saved first.
+# It fails if cancelled.
+##########################################################################
+procedure flush_session()
+
+ if /DIRTY then
+ return # nothing needs saving
+
+ return vib_save_as("save session first? ", SESSION) # fails if cancelled
+end
+
+##########################################################################
+# vib_save_as() asks for a file name and saves the session.
+##########################################################################
+procedure vib_save_as(prompt, def)
+ local fname
+
+ repeat {
+ case SaveDialog(prompt, def) of {
+ "Yes": {
+ fname := def_extn(dialog_value)
+ if close(open(fname)) & not ok_overwrite(fname) then
+ next
+ if save_session(fname) then {
+ SESSION := fname
+ label_session()
+ return
+ }
+ }
+ "No": return
+ "Cancel": fail
+ }
+ }
+end
+
+##########################################################################
+# def_extn(fname) adds a ".icn" extension to a file name, if appropriate.
+##########################################################################
+procedure def_extn(fname)
+
+ if not upto('.', fname) then
+ fname ||:= ".icn"
+ return fname
+end
+
+##########################################################################
+# ok_overwrite() is called to display a dialogue window for confirming
+# the over-writing of a file. It is assumed that it
+# is always okay to overwrite the current session.
+##########################################################################
+procedure ok_overwrite(fname)
+ if fname == SESSION then
+ return
+
+ return "Okay" == Dialog(
+ "File " || fname || " exists. Overwrite?", , , , ["Okay", "Cancel"])
+end
+
+##########################################################################
+# label_session() sets the window and icon labels.
+##########################################################################
+procedure label_session()
+ WAttrib("label=" || SESSION, "iconlabel=" || SESSION)
+end
+
+##########################################################################
+# illegal() posts a notice and succeeds if a value is illegal.
+#
+# val is the value to test.
+# label is its label.
+# how is how to test:
+# "p" procedure name, or empty
+# "s" general VIB string -- no : \ "
+# "l" label string -- can include :
+# "n" any numeric value
+# "i" any integer value
+# <min> any integer of at least <min>
+##########################################################################
+procedure illegal(val, label, how)
+ local m, s
+
+ if case how of {
+ "p": { m := CBMASK; s := "must be a valid identifier" }
+ "s": { m := IDMASK; s := "cannot contain `\\' or `\"' or `:'" }
+ "l": { m := LBMASK; s := "cannot contain `\\' or `\"'" }
+ }
+ then val ? {
+ tab(many(m))
+ if not pos(0) | (how == "p" & any(&digits, val)) then {
+ Notice(label || " value " || s)
+ return
+ }
+ else fail
+ }
+
+ if *val == 0 then {
+ Notice(label || " value must be specified")
+ return
+ }
+
+ if how === "n" then {
+ if not numeric(val) then {
+ Notice(label || " value must be numeric")
+ return
+ }
+ else fail
+ }
+
+ if not integer(val) then {
+ Notice(label || " value must be an integer")
+ return
+ }
+
+ if val < integer(how) then {
+ Notice(label || " value must not be less than " || how)
+ return
+ }
+
+ fail # that is, the value is legal
+end
diff --git a/ipl/gpacks/vib/vibtext.icn b/ipl/gpacks/vib/vibtext.icn
new file mode 100644
index 0000000..bdcfb9b
--- /dev/null
+++ b/ipl/gpacks/vib/vibtext.icn
@@ -0,0 +1,163 @@
+############################################################################
+#
+# vibtext.icn -- procedures for defining a text object
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+
+$include "vdefns.icn"
+$include "vibdefn.icn"
+
+##########################################################################
+# text_input_obj:
+# v : vidget used for drawing text input object
+# proc : name of user callback procedure
+# id : unique means of identifying instance
+# x,y,w,h : bounding box
+# label : label of text input object
+# value : (editable) value of text input object
+# length : max number of chars that value can hold
+# focus : should focus lines be drawn around this object?
+##########################################################################
+record text_input_obj(v, proc, id, x, y, w, h, label, value, length, focus)
+
+##########################################################################
+# create_text_input() creates a text instance and draws the text object if
+# it is a first class object.
+##########################################################################
+procedure create_text_input(x, y, label, value, length)
+ local r, id
+
+ id := next_id("text_input")
+ r := text_input_obj(, "text_input_cb" || id, "text_input" || id,
+ x, y, 0, 0, label, value, length, 0)
+ r.v := Vtext(ROOT, x, y, APPWIN, label || "\\=" || value, , id, length)
+ r.w := r.v.aw
+ r.h := r.v.ah
+ VRemove(ROOT, r.v, 1)
+ return r
+end
+
+##########################################################################
+# draw_text_input() draws the given text object.
+##########################################################################
+procedure draw_text_input(r)
+ r.length := r.v.MaxChars +:= (r.w - r.v.aw) / VFWidth
+ VResize(r.v)
+ VDraw(r.v)
+ return r
+end
+
+##########################################################################
+# update_text_input_bb() makes resizing work a character at a time.
+##########################################################################
+procedure update_text_input_bb(object)
+ local wxv, n
+
+ wxv := object.v.aw - VFWidth * object.v.MaxChars # width excluding value
+ n := (object.w - wxv) / VFWidth # num chars for value
+ n <:= 1
+ n <:= *object.value
+ object.w := wxv + VFWidth * n # force width to char boundary
+ object.h := object.v.ah # disallow height change
+end
+
+##########################################################################
+# load_text_input() restores a text object from session code.
+##########################################################################
+procedure load_text_input(r, o)
+ o.lbl ? {
+ r.label := tab(find("\\\\="))
+ move(3)
+ r.value := tab(0)
+ }
+ r.length := o.num
+ r.v := Vtext(ROOT, r.x,r.y, APPWIN, r.label||"\\="||r.value,, r.id, r.length)
+ r.w := r.v.aw
+ r.h := r.v.ah
+ VRemove(ROOT, r.v, 1)
+end
+
+##########################################################################
+# save_text_input() augments the record for saving a text_input object.
+##########################################################################
+procedure save_text_input(r, o)
+ r.typ := "Text"
+ r.lbl := image(o.label)[2:-1] || "\\\\=" || image(o.value)[2:-1]
+ r.num := o.length
+ return
+end
+
+##########################################################################
+# display_text_input_atts() displays the attribute sheet with the current
+# attributes for the given text instance.
+##########################################################################
+procedure display_text_input_atts(object)
+ local t
+
+ t := table()
+ t["a_id"] := object.id
+ t["b_callback"] := object.proc
+ t["c_x"] := object.x
+ t["d_y"] := object.y - CANVASY
+ t["e_label"] := object.label
+ t["f_value"] := object.value
+ t["g_length"] := object.length
+
+ repeat {
+ if text_dialog(t) == "Cancel" then
+ fail
+
+ if illegal(t["a_id"], "ID", "s") |
+ illegal(t["b_callback"], "Callback", "p") |
+ illegal(t["c_x"], "X", "i") |
+ illegal(t["d_y"], "Y", "i") |
+ illegal(t["e_label"], "Label", "l") |
+ illegal(t["f_value"], "Value", "l") |
+ illegal(t["g_length"], "Length", 1) |
+ illegal(t["g_length"], "Length", *t["f_value"])
+ then
+ next
+
+ object.id := t["a_id"]
+ object.proc := t["b_callback"]
+ object.label := t["e_label"]
+ object.value := t["f_value"]
+ object.length := t["g_length"]
+
+ unfocus_object(object)
+ EraseArea(object.x, object.y, object.w, object.h)
+
+ object.v.MaxChars := object.length
+ object.v.s := object.label
+ VSetState(object.v, object.value)
+ VResize(object.v)
+ object.w := object.v.aw
+
+ move_object(object, t["c_x"], t["d_y"] + CANVASY)
+ focus_object(object)
+ break
+ }
+end
+
+#===<<vib:begin>>=== modify using vib; do not remove this marker line
+procedure text_dialog(win, deftbl)
+static dstate
+initial dstate := dsetup(win,
+ ["text_dialog:Sizer::1:0,0,460,230:",],
+ ["_cancel:Button:regular::250,180,50,30:Cancel",],
+ ["_okay:Button:regular:-1:180,180,50,30:Okay",],
+ ["a_id:Text::40:13,14,360,19:ID: \\=",],
+ ["b_callback:Text::40:13,35,360,19:callback: \\=",],
+ ["c_x:Text::3:13,62,101,19: x: \\=",],
+ ["d_y:Text::3:13,83,101,19: y: \\=",],
+ ["e_label:Text::50:13,109,430,19: label: \\=",],
+ ["f_value:Text::50:13,130,430,19: value: \\=",],
+ ["g_length:Text::3:258,83,185,19:maximum value length: \\=",],
+ )
+return dpopup(win, deftbl, dstate)
+end
+#===<<vib:end>>=== end of section maintained by vib