pcs/edwin/redisp2.scm

428 lines
14 KiB
Scheme
Raw Normal View History

2023-05-20 05:57:04 -04:00
;;;
;;; Copyright (c) 1985 Massachusetts Institute of Technology
;;;
;;; This material was developed by the Scheme project at the
;;; Massachusetts Institute of Technology, Department of
;;; Electrical Engineering and Computer Science. Permission to
;;; copy this software, to redistribute it, and to use it for any
;;; purpose is granted, subject to the following restrictions and
;;; understandings.
;;;
;;; 1. Any copy made of this software must include this copyright
;;; notice in full.
;;;
;;; 2. Users of this software agree to make their best efforts (a)
;;; to return to the MIT Scheme project any improvements or
;;; extensions that they make, so that these may be included in
;;; future releases; and (b) to inform MIT of noteworthy uses of
;;; this software.
;;;
;;; 3. All materials developed as a consequence of the use of
;;; this software shall duly acknowledge such use, in accordance
;;; with the usual standards of acknowledging credit in academic
;;; research.
;;;
;;; 4. MIT has made no warrantee or representation that the
;;; operation of this software will be error-free, and MIT is
;;; under no obligation to provide any services, by way of
;;; maintenance, update, or otherwise.
;;;
;;; 5. In conjunction with products arising from the use of this
;;; material, there shall be no use of the name of the
;;; Massachusetts Institute of Technology nor of any adaptation
;;; thereof in any advertising, promotional, or sales literature
;;; without prior written consent from MIT in each case.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Modified by Texas Instruments Inc 10/21/85
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (window-scroll-y-absolute! window y-point)
(window-scroll-y-relative! window (- (window-point-y window) y-point)))
(define window-scroll-y-relative!
(letrec ((%receiver
(lambda (w)
(let ((buffer (vector-ref w window:buffer))
(table (vector-ref w window:lines)))
(set-buffer-point! buffer (window-coordinates->mark w 0 0))
(vector-set! w window:point (buffer-point buffer))
(cursor-moved! w)))))
(lambda (window y-delta)
(cond ((negative? y-delta) (scroll-down-y! window (- y-delta)))
((positive? y-delta) (scroll-up-y! window y-delta)))
(if (<> y-delta 0)
(begin
(set-start-end! window 0 (-1+ (vector-ref window window:y-size)))
(everything-changed! window %receiver))))))
;;; Scrolling
;;; Scrolling down
(define (scroll-down-y! window y-delta)
(define (check-y-start y-delta table y-size)
(let ((y-start (inferior:y-start (vector-ref table y-delta))))
(if (< y-start y-delta)
(let ((y (max 0 y-start)))
(fill-entries y y-delta y-delta table y-size)
y)
y-delta)))
(let ((table (vector-ref window window:lines))
(y-size (vector-ref window window:y-size)))
(if (< y-delta y-size)
(begin
(scroll-lines-down! window y-delta y-size table 0)
(let ((y (check-y-start y-delta table y-size)))
(fill-top! window (inferior:line (vector-ref table y))
table y-size y #!false)))
(redraw-screen! window
(line-start
(make-mark (inferior:line (vector-ref table 0)) 0)
(- 0 y-delta) 'ERROR)
0))))
(define (scroll-lines-down! window y-delta y-size table y)
(let loop ((n (-1+ (- y-size y-delta)))
(table table))
(if (< n y)
'()
(let ((inferior (vector-ref table n)))
(if (inferior:line inferior)
(begin
(set-inferior:line! (vector-ref table (+ n y-delta))
#!false)
(exchange-inferiors table n (+ n y-delta))))
(loop (-1+ n) table)))))
(define (scroll-up-y! window y-delta)
(let ((table (vector-ref window window:lines))
(y-size (vector-ref window window:y-size)))
(if (< y-delta y-size)
(if (inferior:line (vector-ref table y-delta))
(scroll-lines-up! window y-delta y-size table y-delta)
'())
(redraw-screen! window
(line-start
(make-mark (inferior:line (vector-ref table 0)) 0)
y-delta 'ERROR)
0))))
(define (scroll-lines-up! window y-delta y-size table y)
(define (loop n y-size table)
(let ((move-to (- n y-delta)))
(if (or (>= n y-size)
(not (inferior:line (vector-ref table n))))
(fill-bottom! move-to y-size table
(inferior:line (vector-ref table (-1+ move-to))))
(begin
(set-inferior:line! (vector-ref table move-to) #!false)
(exchange-inferiors table move-to n)
(loop (1+ n) y-size table)))))
(loop y y-size table))
;;; Fill top and Bottom
(define (fill-top! window %line table y-size n fill-bottom?)
(define (loop y table line)
(cond ((< y 0)
(if fill-bottom?
(let ((inferior (vector-ref table n)))
(let ((ys (inferior:y-size inferior))
(y-start (inferior:y-start inferior)))
(fill-bottom! (+ ys y-start) y-size table %line)))))
((null? line)
(scroll-lines-up! window (+ y 1) y-size table (+ y 1)))
(else
(let ((inferior (vector-ref table y)))
(update-top-inferior! 0 y line table inferior y-size)
(loop (- y (inferior:y-size inferior)) table
(line-previous line))))))
(loop (-1+ n) table (line-previous %line)))
(define (update-top-inferior! x y line table inferior ys)
(let ((y-size (find-y-size line)))
(update-inferior! line x (1+ (- y y-size)) y-size inferior)
(if (> y-size 1)
(fill-entries (max 0 (1+ (- y y-size))) y y table ys))))
;;; Fill Bottom
(define (fill-bottom! n y-size table line)
(define (loop n line y-size table)
(if (< n y-size)
(let ((inferior (vector-ref table n)))
(if (null? line)
(begin
(set-inferior:line! inferior #!false)
(loop (1+ n) '() y-size table))
(begin
(update-bottom-inferior! line 0 n inferior table y-size)
(loop (+ n (inferior:y-size inferior)) (line-next line)
y-size table))))))
(loop n (line-next line) y-size table))
(define (update-bottom-inferior! line x y inferior table ys)
(let ((y-size (find-y-size line)))
(update-inferior! line x y y-size inferior)
(if (> y-size 1)
(fill-entries (1+ y) (min ys (+ y y-size)) y table ys))))
(define (update-inferior! line x y y-size inferior)
(set-inferior:x-start! inferior x)
(set-inferior:y-start! inferior y)
(set-inferior:line! inferior line)
(set-inferior:y-size! inferior y-size))
;;; Fill enteries
(define (fill-entries start end copy-entry table ys)
(let ((copy-entry (vector-ref table copy-entry)))
(do ((x-start (inferior:x-start copy-entry))
(y-start (inferior:y-start copy-entry))
(y-size (inferior:y-size copy-entry))
(line (inferior:line copy-entry))
(n start (1+ n)))
((or (>= n ys) (= n end)) #!true)
(and (>= n 0)
(let ((entry (vector-ref table n)))
(set-inferior:x-start! entry x-start)
(set-inferior:y-start! entry y-start)
(set-inferior:y-size! entry y-size)
(set-inferior:line! entry line))))))
(define (exchange-inferiors table n1 n2)
(let ((inferior1 (vector-ref table n1))
(inferior2 (vector-ref table n2))
(diff (- n2 n1)))
(set-inferior:y-start! inferior1
(+ diff (inferior:y-start inferior1)))
(set-inferior:y-start! inferior2
(- (inferior:y-start inferior2) diff))
(vector-set! table n1 inferior2)
(vector-set! table n2 inferior1)))
(define (clean-up-table table n1 n2)
(do ((i n1 (1+ i))
(table table))
((= i n2) table)
(set-inferior:line! (vector-ref table i) #!false)))
(define (find-y-size line)
(let* ((string (line-string line))
(x (char->x string (string-length string))))
(if (zero? x)
1
(let ((q (quotient x 79))
(r (remainder x 79)))
(if (zero? r)
q
(1+ q))))))
(define (set-cursor-coordinates window mark)
(let ((line (mark-line mark))
(position (mark-position mark))
(string (line-string (mark-line mark)))
(x-size (window-x-size window))
(table (vector-ref window window:lines)))
(let ((y (inferior:y-start
(vector-ref table (line->y window line))))
(x (char->x string position)))
(set-cursor-pos window
(index->x x x-size position string)
(+ y (index->y x x-size position string))))))
(define (index->x column x-size index string)
(if (zero? column)
0
(let ((r (remainder column (-1+ x-size))))
(if (zero? r)
(if (=? index (string-length string))
(-1+ x-size)
r)
r))))
(define (index->y column x-size index string)
(if (zero? column)
0
(let ((q (quotient column (-1+ x-size)))
(r (remainder column (-1+ x-size))))
(if (zero? r)
(if (=? index (string-length string))
(-1+ q)
q)
q))))
(define make-insert-daemon
(lambda (window)
(letrec
((%receiver
(lambda (region)
(region-components region
(lambda (start-line start-position end-line end-position)
(let* ((table (vector-ref window window:lines))
(inferior (vector-ref table y)))
(let ((y-size (vector-ref window window:y-size))
(old-ys (inferior:y-size inferior))
(new-ys (find-y-size start-line)))
(cond
((eq? start-line end-line)
(if (= old-ys new-ys)
(begin
(maybe-marks-changed window y)
(set-start-end! window y y)
(cursor-moved! window))
(begin
(scroll-lines-down! window (- new-ys old-ys)
y-size table
(+ (inferior:y-start inferior) old-ys))
(set-inferior:y-size! inferior new-ys)
(fill-entries (1+ y)
(+ (inferior:y-start inferior) new-ys)
y table y-size)
(set-start-end! window y (-1+ y-size))
(everything-changed! window window-redraw!))))
(else
(update-bottom-inferior! start-line 0 y
inferior table y-size)
(fill-bottom! (+ y new-ys) y-size table start-line)
(set-start-end! window y (-1+ y-size))
(everything-changed! window window-redraw!)))))))))
(y '()))
(lambda (mark)
(if (line-visible? window mark)
(begin
(set! y (line->y window (mark-line mark)))
%receiver))))))
(define set-start-end!
(lambda (window start end)
(if (vector-ref window window:redisplay-window-flag)
(begin
(vector-set! window window:start
(min start (vector-ref window window:start)))
(vector-set! window window:end
(max end (vector-ref window window:end))))
(begin
(vector-set! window window:start start)
(vector-set! window window:end end)))
(vector-set! window window:redisplay-window-flag #!TRUE)))
(define make-delete-daemon
(lambda (window)
(letrec
((start-y '())
(end-y '())
(mark '())
(%receiver
(lambda (region)
(let ((table (vector-ref window window:lines))
(line (mark-line mark))
(y-size (vector-ref window window:y-size)))
(set! mark '()) ;; clean up
(cond ((not start-y) ;;; deleted top
(cond ((not end-y)
(window-redraw! window))
(else
(clean-up-table table 0 y-size)
(update-bottom-inferior! line 0 end-y
(vector-ref table end-y) table y-size)
(fill-top! window line table y-size end-y #!true)
(set-start-end! window 0 (-1+ y-size))
(everything-changed! window window-redraw!))))
((and end-y (=? start-y end-y))
(let ((inferior (vector-ref table start-y)))
(let ((old-ys (inferior:y-size inferior))
(new-ys (find-y-size line))
(y start-y))
(if (= old-ys new-ys)
(begin
(maybe-marks-changed window y)
(set-start-end! window y y)
(cursor-moved! window))
(begin
(scroll-lines-up! window (- old-ys new-ys)
y-size table
(+ (inferior:y-start inferior) old-ys))
(set-inferior:y-size! inferior new-ys)
(fill-entries (1+ y)
(+ (inferior:y-start inferior) new-ys)
y table y-size)
(set-start-end! window y (-1+ y-size))
(everything-changed! window window-redraw!))))))
(else
(let ((inferior (vector-ref table start-y)))
(let ((ys (find-y-size line))
(y start-y))
(update-bottom-inferior! line 0 y inferior table y-size)
(fill-bottom! (+ y ys) y-size table line)
(set-start-end! window y (-1+ y-size))
(everything-changed! window window-redraw!)))))))))
(lambda (region)
(let ((start (region-start region))
(end (region-end region)))
(let ((*line (mark-line start))
(*pos (mark-position start)))
(set! start-y (line->y window *line))
(set! end-y (line->y window (mark-line end)))
(set! mark (if (and start-y end-y (= start-y end-y))
start
(mark-permanent! start)))
%receiver))))))
(define direct-output-for-insert!
(lambda (window char)
(let ((x (vector-ref window window:cursor-x))
(y (vector-ref window window:cursor-y))
(screen (vector-ref window window:screen)))
(maybe-marks-changed window y)
(write-string! screen char x y )
(vector-set! window window:cursor-x
(1+ x)))))
(define direct-output-forward-character!
(lambda (window)
(let ((screen (vector-ref window window:screen))
(buffer (vector-ref window window:buffer))
(point (vector-ref window window:point))
(x (vector-ref window window:cursor-x)))
(set-buffer-point! buffer (mark1+ point #!false))
(vector-set! window window:point (buffer-point buffer))
(%reify-port! screen screen:cursor-x (1+ x))
(vector-set! window window:cursor-x (1+ x)))))
(define direct-output-backward-character!
(lambda (window)
(let ((screen (vector-ref window window:screen))
(buffer (vector-ref window window:buffer))
(point (vector-ref window window:point))
(x (vector-ref window window:cursor-x)))
(set-buffer-point! buffer (mark-1+ point #!false))
(vector-set! window window:point (buffer-point buffer))
(%reify-port! screen screen:cursor-x (-1+ x))
(vector-set! window window:cursor-x (-1+ x)))))