pcs/edwin/redisp2.scm

428 lines
14 KiB
Scheme
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;;
;;; 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)))))