+% Physical screen hacking cluster, for editors, etc.
+
+# extend
+
+screen = cluster is
+
+ % mode changing and initialization functions
+ init, % sets up (first time, or new terminal)
+ enter_image_mode, % set up terminal
+ leave_image_mode, % restores the terminal
+ destroy, % finishes up
+
+ % option setting functions
+ set_padding, % pad output
+ set_scroll, % do scrolling (if poss)
+ set_keypad_mode, % enter/exit alternate keypad mode
+ set_highlight, % underline/invert
+ recolor, % change colors
+
+ % display functions
+ clear, % clear screen and home up
+ display_line, % display a line of an environment
+ redisplay_line, % redisplay line as is
+ display_chars, % display chars at end of line
+ update_line, % update data to correspond with screen
+ set_cursor_pos, % set the cursor position
+ get_cursor_pos, % get the cursor position
+ scroll, % scroll a region
+ full_scroll, % scroll entire screen
+ bell, % bell
+ highlight, % highlight
+ redisplay, % hack redisplay
+ unmapped, % hack icon
+
+ % information returning functions
+ position, % pixel -> char coordinates
+ get_padding, % padding on ?
+ get_screen_size, % returns length and width of screen
+ fetch, % fetch a line
+ id_lines_poss, % ins/del lines possible ?
+ scrolling_poss, % full screen scrolling possible ?
+ should_id_lines, % makes decision about ins/del lines
+ should_scroll % makes decision about scrolling
+
+ ldata = record[line: act, % screen line, as chars
+ len: int, % len of real string
+ lim: int, % pos of last non-space char in line
+ str: string] % the actual string
+
+ % invariant property of ldatas:
+ % size(line) = hsize - 1
+ % len = _calc_hpos(str, string$size(str) + 1)
+ % lim < i < hsize => line[i] = ' '
+ % the chars in line correspond to the chars in str
+ % the chars in lines[j] correspond to the chars on the
+ % screen on line j (the presence of an ! determined by len)
+
+ rep = null
+ al = array[ldata]
+
+ qi = sequence[int]
+ qs = sequence[string]
+ zapc = array_zap[char]
+ shiftc = array_shift[char]
+ shiftl = array_shift[ldata]
+ repll = array_replace[ldata]
+
+ events = KeyPressed + ButtonPressed + ButtonReleased +
+ ExposeRegion + ExposeCopy + UnmapWindow
+
+ own done: bool := false
+
+ % screen data base
+
+ own lines: al % array of line data
+ own holder: act % for display_line (new line)
+ own hlim: int % limit for holder
+ own temp: al % for scrolling
+ own xline: act % display_chars hack
+ own xvpos: int
+ own xhpos: int
+ own xmpos: int
+
+ own image: bool % in image mode?
+ own f: x_font
+ own fheight: int
+ own fwidth: int
+ own of: x_font
+ own oheight: int
+ own owidth: int
+ own textpix: int
+ own clearpix: int
+ own planemask: int
+ own nobit: x_bitmap
+ own w: x_window
+ own ow: x_window
+ own mousepix: int
+ own mousefunc: int
+ own chpos: int
+ own cdisp: bool
+ own crcols: colordeflist
+ own hlcols: colordeflist
+ own hlmode: bool
+ own high: bool
+ own hvpos: int
+ own hhpos: int
+
+ % terminal properties
+
+ own vsize: int % # of lines (0 to vsize-1)
+ own hsize: int % # of cols (0 to hsize-1)
+ own vsize1: int % vsize-1
+ own hsize1: int % hsize-1
+
+ % cursor info (-1 means unknown)
+
+ own vpos: int % current vertical pos
+ own hpos: int % current horizontal pos
+
+ init = proc (options: qs)
+ if ~done
+ then lines := al$create(0)
+ holder := act$create(0)
+ hlim := -1
+ temp := al$create(0)
+ xhpos := 0
+ xmpos := -1
+ image := false
+ display: string := ""
+ myname: string := _get_xjname()
+ font: string := x_default(myname, "BodyFont")
+ except when not_found: font := "8x13" end
+ revvid: bool := x_default(myname, "ReverseVideo") = "on"
+ except when not_found: revvid := false end
+ bwidth: int := int$parse(x_default(myname, "BorderWidth"))
+ except when not_found, overflow, bad_format: bwidth := 2 end
+ spec: string := "=80x24"
+ cfore: string := x_default(myname, "Foreground")
+ except when not_found: cfore := "" end
+ cback: string := x_default(myname, "Background")
+ except when not_found: cback := "" end
+ ccurs: string := x_default(myname, "Cursor")
+ except when not_found: ccurs := "" end
+ chigh: string := x_default(myname, "Highlight")
+ except when not_found: chigh := "" end
+ cbdr: string := x_default(myname, "Border")
+ except when not_found: cbdr := "" end
+ mfore: string := x_default(myname, "Mouse")
+ except when not_found: mfore := "" end
+ mousefunc := int$parse(x_default(myname, "MouseFunction"))
+ except when not_found, overflow, bad_format: mousefunc := GXcopy end
+ icon: bool := x_default(myname, "BitmapIcon") = "on"
+ except when not_found: icon := false end
+ for opt: string in qs$elements(options) do
+ if opt = "-rv"
+ then revvid := true
+ elseif opt = "-i"
+ then icon := true
+ elseif string$indexs("-fn=", opt) = 1
+ then font := string$rest(opt, 5)
+ elseif string$indexs("-fg=", opt) = 1
+ then cfore := string$rest(opt, 5)
+ elseif string$indexs("-bg=", opt) = 1
+ then cback := string$rest(opt, 5)
+ elseif string$indexs("-cr=", opt) = 1
+ then ccurs := string$rest(opt, 5)
+ elseif string$indexs("-hl=", opt) = 1
+ then chigh := string$rest(opt, 5)
+ elseif string$indexs("-bd=", opt) = 1
+ then cbdr := string$rest(opt, 5)
+ elseif string$indexs("-ms=", opt) = 1
+ then mfore := string$rest(opt, 5)
+ elseif opt[1] = '='
+ then spec := opt
+ else if opt[1] = '-'
+ then opt := string$rest(opt, 2) end
+ if string$indexc(':', opt) ~= 0
+ then display := opt
+ else font := opt
+ end
+ end
+ end
+ x_display$init(display)
+ except when error, failure (why: string):
+ _chan$puts(_chan$error_output(), why || "\r\n",
+ false)
+ quit_()
+ end
+ f := x_font$create(font)
+ except when error (*):
+ _chan$puts(_chan$error_output(), "bad font\r\n",
+ false)
+ quit_()
+ end
+ clearmap, bdrmap: x_pixmap
+ if revvid
+ then textpix := WhitePixel
+ bdrmap := x_display$white()
+ clearpix := BlackPixel
+ clearmap := x_display$black()
+ else textpix := BlackPixel
+ bdrmap := x_display$black()
+ clearpix := WhitePixel
+ clearmap := x_display$white()
+ end
+ mousepix := textpix
+ crcols := colordeflist$new()
+ hlcols := colordeflist$new()
+ begin
+ if x_display$cells() > 2 cand
+ (~string$empty(cfore) cor ~string$empty(cback) cor
+ ~string$empty(ccurs) cor ~string$empty(chigh))
+ then pixs: pixellist
+ if string$empty(ccurs) cand string$empty(chigh)
+ then pixs, planemask := x_display$alloc_cells(
+ 1, 1, false)
+ clearpix := pixs[1]
+ textpix := clearpix + planemask
+ else pixs, planemask := x_display$alloc_cells(
+ 2, 1, false)
+ clearpix := pixs[1]
+ textpix := pixs[2]
+ end
+ mousepix := textpix
+ r, g, b: int
+ if string$empty(cback)
+ then r, g, b := x_display$query_color(clearpix)
+ else r, g, b := x_parse_color(cback)
+ end
+ x_display$store_color(clearpix, r, g, b)
+ if ~string$empty(ccurs) cor ~string$empty(chigh)
+ then x_display$store_color(textpix + planemask,
+ r, g, b)
+ end
+ clearmap := x_pixmap$tile(clearpix)
+ if string$empty(cfore)
+ then r, g, b := x_display$query_color(textpix)
+ else r, g, b := x_parse_color(cfore)
+ end
+ x_display$store_color(textpix, r, g, b)
+ if ~string$empty(chigh)
+ then hr, hg, hb: int := x_parse_color(chigh)
+ colordeflist$addh(hlcols,
+ colordef${pixel: clearpix +
+ planemask,
+ red: hr,
+ green: hg,
+ blue: hb})
+ end
+ if ~string$empty(ccurs)
+ then r, g, b := x_parse_color(ccurs) end
+ colordeflist$addh(crcols,
+ colordef${pixel: clearpix +
+ planemask,
+ red: r,
+ green: g,
+ blue: b})
+ if ~string$empty(ccurs) cor ~string$empty(chigh)
+ then x_display$store_color(clearpix + planemask,
+ r, g, b)
+ end
+ else planemask := 1
+ end
+ if x_display$cells() > 2
+ then if ~string$empty(cbdr)
+ then r, g, b: int := x_parse_color(cbdr)
+ bdrmap := x_pixmap$tile(x_display$alloc_color(
+ r, g, b))
+ end
+ if ~string$empty(mfore)
+ then r, g, b: int := x_parse_color(mfore)
+ mousepix := x_display$alloc_color(r, g, b)
+ end
+ end
+ end except when undefined, bad_format:
+ _chan$puts(_chan$error_output(), "bad color\r\n",
+ false)
+ quit_()
+ end
+ first, last: char
+ base: int
+ fixed: bool
+ fwidth, fheight, first, last, base, fixed := x_font$query(f)
+ w, hsize, vsize := x_tcons(myname, clearmap, bdrmap,
+ spec, "=80x24+1+1",
+ f, fwidth, fheight, 2,
+ 6, 6, bwidth)
+ if icon
+ then of := x_font$create("nil2")
+ owidth, oheight, first, last, base, fixed :=
+ x_font$query(of)
+ ow := x_window$create(0, 0, hsize * owidth + 2,
+ vsize * oheight + 2, clearmap,
+ x_display$root(), 2, bdrmap)
+ ow.input := events
+ w.icon := ow
+ else ow := x_window$none()
+ end except when error (*):
+ _chan$puts(_chan$error_output(), "bad font\r\n",
+ false)
+ quit_()
+ end
+ w.name := myname
+ x_window$set_resize(w, 2, fwidth, 2, fheight)
+ w.input := events - ExposeRegion
+ x_window$map(w)
+ w.input := events
+ new_cursor()
+ nobit := x_bitmap$none()
+ vsize1 := vsize - 1
+ hsize1 := hsize - 1
+ chpos := 0
+ cdisp := false
+ hlmode := false
+ high := false
+ done := true
+ else leave_image_mode()
+ end
+ enter_image_mode()
+ end init
+
+ enter_image_mode = proc ()
+ if image
+ then return end
+ sx, sy, sw, sh, wb, ms, wk: int, iw: x_window := x_window$query(w)
+ hsize := int$max((sw + fwidth - 3) / fwidth, 6)
+ hsize1 := hsize - 1
+ vsize := int$max((sh + fheight - 3) / fheight, 6)
+ vsize1 := vsize - 1
+ nw: int := hsize * fwidth + 2
+ nh: int := vsize * fheight + 2
+ if nh ~= sh cor nw ~= sw
+ then x_window$change(w, nw, nh)
+ if ow ~= x_window$none()
+ then x_window$change(ow, hsize * owidth + 2,
+ vsize * oheight + 2)
+ end
+ end
+ output$reset()
+ vpos := -1 % force positioning
+ hpos := -1
+ image := true
+ end enter_image_mode
+
+ leave_image_mode = proc ()
+ if image
+ then input$reset()
+ image := false
+ end
+ end leave_image_mode
+
+ destroy = proc ()
+ leave_image_mode()
+ x_window$destroy(w)
+ done := false
+ end destroy
+
+ set_padding = proc (b: bool)
+ end set_padding
+
+ set_scroll = proc (b: bool)
+ end set_scroll
+
+ set_keypad_mode = proc (b: bool) returns (bool)
+ return(false)
+ end set_keypad_mode
+
+ set_highlight = proc (h, b: bool)
+ hlmode := b
+ if h
+ then w.input := events + MouseMoved
+ if ~colordeflist$empty(hlcols)
+ then x_display$store_colors(hlcols) end
+ else w.input := events
+ if ~colordeflist$empty(hlcols)
+ then x_display$store_colors(crcols) end
+ end
+ end set_highlight
+
+ recolor = proc (white: bool) returns (bool)
+ if textpix > WhitePixel
+ then return(false) end
+ if white
+ then textpix := BlackPixel
+ clearpix := WhitePixel
+ w.background := x_display$white()
+ w.border := x_display$black()
+ else textpix := WhitePixel
+ clearpix := BlackPixel
+ w.background := x_display$black()
+ w.border := x_display$white()
+ end
+ mousepix := textpix
+ x_window$clear(w)
+ new_cursor()
+ return(true)
+ end recolor
+
+ clear = proc ()
+ ovsize: int := al$size(lines)
+ x_window$clear(w)
+ x_flush()
+ deltav: int := vsize - ovsize
+ deltah: int := hsize1 - act$size(holder)
+ limit: int := ovsize - 1
+ if deltav < 0
+ then limit := vsize1 end
+ % clear out char arrays, and auxiliary info
+ for i: int in int$from_to(0, limit) do
+ line: ldata := lines[i]
+ lim: int := line.lim
+ chars: act := line.line
+ zapc(chars, 0, lim+1, ' ')
+ if deltah < 0
+ then act$trim(chars, 0, hsize1)
+ else for j: int in int$from_to_by(deltah, 1, -1) do
+ act$addh(chars, ' ')
+ end
+ end
+ line.lim := -1
+ line.len := 0
+ line.str := ""
+ end
+ if deltav < 0
+ then al$trim(lines, 0, vsize)
+ else for i: int in int$from_to_by(deltav, 1, -1) do
+ line: ldata :=
+ ldata${line: act$fill(0, hsize1, ' '),
+ lim: -1,
+ len: 0,
+ str: ""}
+ al$addh(lines, line)
+ end
+ end
+ if deltah < 0
+ then act$trim(holder, 0, hsize1)
+ if hlim >= hsize1
+ then hlim := hsize - 2 end
+ else for i: int in int$from_to_by(deltah, 1, -1) do
+ act$addh(holder, ' ')
+ end
+ end
+ vpos := -1 % force positioning
+ cdisp := false
+ set_cursor_pos(0, 0, true)
+ end clear
+
+ display_line = proc (s: string, lpos: int) returns (bool) signals (bounds)
+ line: ldata := lines[lpos]
+ resignal bounds
+ if s = line.str
+ then return(false) end
+ if cdisp
+ then forget_cursor() end
+ new: act := holder
+ nlim, newlen: int := _calc_hpos_copy(s, new)
+ if hlim >= newlen
+ then zapc(new, newlen, hlim - newlen + 1, ' ') end
+ old: act := line.line
+ oldlen: int := line.len
+ olim: int := line.lim
+ excl: char := ' '
+ if oldlen >= hsize
+ then excl := '!' end
+ mlim: int := nlim
+ mpos: int := _diff_scan(new, old, 0, mlim)
+ if hpos ~= mpos cor vpos ~= lpos cor cdisp
+ then reposition(lpos, mpos) end
+ outa(new, mpos, mlim - mpos + 1)
+ hpos := mlim + 1
+ mpos := hpos
+
+ if mlim < olim
+ then % keol needed
+ vpos := lpos
+ hpos := mpos
+ chpos := mpos
+ if excl = ' '
+ then mlim := olim + 1
+ else mlim := hsize
+ excl := ' '
+ end
+ clear_region(lpos, mpos, 1, mlim - mpos)
+ end
+ dexcl: char := ' ' % desired excl place char
+ if newlen >= hsize
+ then dexcl := '!' end
+ if dexcl ~= excl
+ then reposition(lpos, hsize1)
+ outc(dexcl)
+ hpos := hsize
+ reposition(lpos, hsize1)
+ end
+ holder := old
+ hlim := olim
+ line.line := new
+ line.lim := nlim
+ line.len := newlen
+ line.str := s
+ return(true)
+ end display_line
+
+ redisplay_line = proc (lpos: int)
+ line: ldata := lines[lpos]
+ except when bounds: return end
+ if cdisp
+ then forget_cursor() end
+ vpos := -1
+ s: string := line.str
+ zapc(line.line, 0, hsize1, '\177')
+ if line.len >= hsize
+ then line.len := hsize1
+ else line.len := hsize
+ end
+ line.lim := hsize1
+ line.str := "\177"
+ display_line(s, lpos)
+ end redisplay_line
+
+ display_chars = proc (nvpos, ohpos, nhpos: int, chars: act, mhpos: int)
+ xline := chars
+ xvpos := nvpos
+ if xhpos > xmpos
+ then xhpos := ohpos end
+ xmpos := nhpos
+ reposition(nvpos, ohpos)
+ outa(chars, ohpos, nhpos - ohpos)
+ hpos := nhpos
+ if nhpos < mhpos
+ then clear_region(nvpos, nhpos, 1, mhpos - nhpos) end
+ display_cursor()
+ end display_chars
+
+ update_line = proc (s: string, lpos: int) signals (bounds)
+ xmpos := -1
+ line: ldata := lines[lpos]
+ resignal bounds
+ nlim, newlen: int := _calc_hpos_copy(s, line.line)
+ if line.lim >= newlen
+ then zapc(line.line, newlen, line.lim - newlen + 1, ' ') end
+ line.lim := nlim
+ line.len := newlen
+ line.str := s
+ end update_line
+
+ reposition = proc (nvpos, nhpos: int)
+ if nhpos >= hsize
+ then nhpos := hsize1 end
+ if cdisp
+ then forget_cursor() end
+ if vpos ~= nvpos cor hpos ~= nhpos
+ then vpos := nvpos
+ hpos := nhpos
+ chpos := hpos
+ end
+ end reposition
+
+ set_cursor_pos = proc (nvpos, nhpos: int, doit: bool)
+ if nhpos >= hsize
+ then nhpos := hsize1 end
+ if nvpos ~= vpos cor nhpos ~= hpos
+ then if cdisp
+ then forget_cursor() end
+ vpos := nvpos
+ hpos := nhpos
+ chpos := hpos
+ end
+ if ~cdisp
+ then display_cursor() end
+ if doit
+ then x_flush() end
+ end set_cursor_pos
+
+ forget_cursor = proc ()
+ x_window$pix_fill(w, 0, nobit, 1 + hpos * fwidth, 1 + vpos * fheight,
+ fwidth, fheight, GXinvert, planemask)
+ cdisp := false
+ end forget_cursor
+
+ display_cursor = proc ()
+ x_window$pix_fill(w, 0, nobit, 1 + hpos * fwidth, 1 + vpos * fheight,
+ fwidth, fheight, GXinvert, planemask)
+ cdisp := true
+ end display_cursor
+
+ get_cursor_pos = proc () returns (int, int)
+ return(vpos, hpos)
+ end get_cursor_pos
+
+ position = proc (x, y: int) returns (int, int)
+ return((x - 1) / fwidth, (y - 1) / fheight)
+ end position
+
+ get_padding = proc () returns (bool)
+ return(false)
+ end get_padding
+
+ get_screen_size = proc () returns (int, int)
+ return(vsize, hsize)
+ end get_screen_size
+
+ fetch = proc (lpos: int) returns (string) signals (bounds)
+ return(lines[lpos].str)
+ resignal bounds
+ end fetch
+
+ id_lines_poss = proc () returns (bool)
+ return(true)
+ end id_lines_poss
+
+ scrolling_poss = proc () returns (bool)
+ return(false)
+ end scrolling_poss
+
+ should_id_lines = proc (top, bot, delta, num_saved: int) returns (bool)
+ return(num_saved > 0)
+ end should_id_lines
+
+ scroll = proc (top, bot, delta: int)
+ d: int := int$abs(delta)
+ topd: int := top + d
+ pos: int := bot - d + 1
+ numshift: int := pos - top
+ input$copy_wait()
+ if cdisp
+ then forget_cursor() end
+ max: int := 0
+ for i: int in int$from_to(top, bot) do
+ line: ldata := lines[i]
+ if lines[i].len >= hsize
+ then max := hsize
+ break
+ end
+ max := int$max(max, line.lim)
+ end
+ max := max + 1
+ vpos := -1
+ if delta < 0
+ then % are scrolling up
+ copy_region(topd, 0, top, 0, pos - top, max)
+ clear_region(pos, 0, d, max)
+ repll(temp, 0, al$size(temp), lines, top, d)
+ for ltemp: ldata in al$elements(temp) do
+ zapc(ltemp.line, 0, ltemp.lim+1, ' ')
+ ltemp.lim := -1
+ ltemp.len := 0
+ ltemp.str := ""
+ end
+ shiftl(lines, topd, numshift, delta)
+ repll(lines, pos, d, temp, 0, d)
+ else % scrolling down
+ copy_region(top, 0, topd, 0, pos - top, max)
+ clear_region(top, 0, d, max)
+ repll(temp, 0, al$size(temp), lines, pos, d)
+ for ltemp: ldata in al$elements(temp) do
+ zapc(ltemp.line, 0, ltemp.lim+1, ' ')
+ ltemp.lim := -1
+ ltemp.len := 0
+ ltemp.str := ""
+ end
+ shiftl(lines, top, numshift, delta)
+ repll(lines, top, d, temp, 0, d)
+ end
+ end scroll
+
+ should_scroll = proc (delta, num_saved, num_saved0: int) returns (bool)
+ signals (clear, id_lines)
+ return(false)
+ end should_scroll
+
+ full_scroll = proc (delta: int) returns (bool)
+ return(false)
+ end full_scroll
+
+ bell = proc ()
+ x_feep(0)
+ end bell
+
+ highlight = proc (flag: bool)
+ if ~cdisp
+ then return end
+ if ~flag
+ then if high
+ then dohigh(vpos, hpos, hvpos, hhpos)
+ high := false
+ end
+ return
+ end
+ h, v: int, sw: x_window := x_window$query_mouse(w)
+ h := int$min(int$max(0, (h - 1) / fwidth), hsize)
+ v := int$min(int$max(0, (v - 1) / fheight), vsize)
+ if h > 0 cand ~(v = xvpos cand xmpos > xhpos cand h > xhpos)
+ then l: ldata := lines[v]
+ if h < l.len cand string$indexc(l.line[h - 1], " ^&!") > 0
+ then i: int := int$max(h + 2, string$size(l.str) + 1)
+ oh: int := h
+ while true do
+ h := _calc_hpos(l.str, i)
+ if h <= oh
+ then break end
+ i := i - 1
+ end
+ end
+ end except when bounds: end
+ if ~high
+ then dohigh(vpos, hpos, v, h)
+ elseif v = hvpos cand h = hhpos
+ then return
+ elseif (v > vpos cor (v = vpos cand h > hpos)) cand
+ (hvpos > vpos cor (hvpos = vpos cand hhpos > hpos))
+ then dohigh(hvpos, hhpos, v, h)
+ elseif (v < vpos cor (v = vpos cand h < hpos)) cand
+ (hvpos < vpos cor (hvpos = vpos cand hhpos < hpos))
+ then dohigh(v, h, hvpos, hhpos)
+ else dohigh(vpos, hpos, hvpos, hhpos)
+ dohigh(vpos, hpos, v, h)
+ end
+ high := true
+ hvpos := v
+ hhpos := h
+ end highlight
+
+ dohigh = proc (v1, h1, v2, h2: int)
+ if v1 = v2
+ then if h1 > h2
+ then h1, h2 := h2, h1 end
+ elseif v1 > v2
+ then v1, v2 := v2, v1
+ h1, h2 := h2, h1
+ end
+ if h1 < 0
+ then h1 := 0
+ elseif h1 > hsize1
+ then v1 := v1 + 1
+ h1 := 0
+ end
+ if v1 < 0
+ then v1 := 0
+ h1 := 0
+ elseif v1 > vsize1
+ then v1 := vsize1
+ h1 := hsize1
+ elseif v1 = vpos cand h1 = hpos
+ then h1 := h1 + 1 end
+ if v2 > vsize1
+ then v2 := vsize1
+ h2 := hsize1
+ elseif h2 > hsize
+ then h2 := hsize end
+ v: int
+ if hlmode
+ then v := 1 + v1 * fheight
+ else v := (v1 + 1) * fheight
+ end
+ while v1 < v2 do
+ h: int := lines[v1].len
+ if v1 = xvpos cand xmpos > xhpos
+ then h := xmpos end
+ if h1 < h
+ then dohigh1(v, h1, h) end
+ v := v + fheight
+ v1 := v1 + 1
+ h1 := 0
+ end
+ h2 := int$min(h2, lines[v2].len)
+ if v2 = xvpos cand xmpos > xhpos
+ then h2 := xmpos end
+ if h1 < h2
+ then dohigh1(v, h1, h2) end
+ end dohigh
+
+ dohigh1 = proc (v, h1, h2: int)
+ if hlmode
+ then x_window$pix_fill(w, 0, nobit, 1 + h1 * fwidth, v,
+ (h2 - h1) * fwidth, fheight, GXinvert,
+ planemask)
+ else x_window$line(w, 0, 1, 1,
+ 1 + h1 * fwidth, v, h2 * fwidth, v, GXinvert,
+ planemask)
+ end
+ end dohigh1
+
+ redisplay = proc (win: x_window, x, y, width, height: int)
+ if win ~= w
+ then return end
+ h1: int := int$max(0, (x - 1) / fwidth)
+ h2: int := (x + width - 2) / fwidth
+ if h2 < h1
+ then return end
+ v1: int := int$max(0, (y - 1) / fheight)
+ v2: int := (y + height - 2) / fheight
+ if cdisp cand
+ vpos >= v1 cand vpos <= v2 cand hpos >= h1 cand hpos <= h2
+ then clear_region(vpos, hpos, 1, 1)
+ cdisp := false
+ end
+ ovpos: int := vpos
+ ohpos: int := hpos
+ for lpos: int in int$from_to(v1, v2) do
+ line: ldata := lines[lpos]
+ if line.lim < h1
+ then continue end
+ reposition(lpos, h1)
+ outa(line.line, h1, int$min(line.lim, h2) - h1 + 1)
+ if h2 >= hsize1 cand line.len >= hsize
+ then reposition(lpos, hsize1)
+ outc('!')
+ end
+ end except when bounds: end
+ if xmpos > xhpos cand xmpos > h1 cand xhpos <= h2 cand
+ xvpos >= v1 cand xvpos <= v2
+ then pos: int := int$max(xhpos, h1)
+ reposition(xvpos, pos)
+ outa(xline, pos, int$min(xmpos - 1, h2) - pos + 1)
+ end
+ set_cursor_pos(ovpos, ohpos, true)
+ end redisplay
+
+ unmapped = proc (win: x_window)
+ if win = w cand ow ~= x_window$none()
+ then w, ow := ow, w
+ f, of := of, f
+ fheight, oheight := oheight, fheight
+ fwidth, owidth := owidth, fwidth
+ redisplay(w, 1, 1, fwidth * hsize, fheight * vsize)
+ end
+ end unmapped
+
+ copy_region = proc (ovpos, ohpos, nvpos, nhpos, height, width: int)
+ x_window$move_area(w, 1 + ohpos * fwidth, 1 + ovpos * fheight,
+ width * fwidth, height * fheight,
+ 1 + nhpos * fwidth, 1 + nvpos * fheight)
+ end copy_region
+
+ clear_region = proc (nvpos, nhpos, height, width: int)
+ x_window$pix_set(w, clearpix, 1 + nhpos * fwidth, 1 + nvpos * fheight,
+ width * fwidth, height * fheight)
+ end clear_region
+
+ outc = proc (c: char)
+ x_window$text(w, string$c2s(c), f, textpix, clearpix,
+ 1 + chpos * fwidth, 1 + vpos * fheight)
+ chpos := chpos + 1
+ end outc
+
+ outa = proc (a: act, i, z: int) signals (bounds, negative_size)
+ x_window$texta(w, a, i, z, f, textpix, clearpix,
+ 1 + chpos * fwidth, 1 + vpos * fheight)
+ chpos := chpos + z
+ end outa
+
+ new_cursor = proc ()
+ cursbits = "\003\000\005\000\011\000\021\000\041\000\101\000" ||
+ "\201\000\001\001\001\002\301\003\111\000\225\000" ||
+ "\223\000\040\001\040\001\300\000"
+ maskbits = "\003\000\007\000\017\000\037\000\077\000\177\000" ||
+ "\377\000\377\001\377\003\377\003\177\000\367\000" ||
+ "\363\000\340\001\340\001\300\000"
+
+ cursor: x_cursor := x_cursor$scons(11, 16,
+ cursbits, maskbits,
+ clearpix, mousepix, 1, 1, mousefunc)
+ w.cursor := cursor
+ if ow ~= x_window$none()
+ then ow.cursor := cursor end
+ x_cursor$destroy(cursor)
+ end new_cursor
+
+ end screen