428 lines
14 KiB
Scheme
428 lines
14 KiB
Scheme
|
;;;
|
|||
|
;;; 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)))))
|
|||
|
|
|||
|
|
|||
|
|