;;; ;;; 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-integrables (begin (define-integrable inferior:x-start cddr) (define-integrable inferior:y-start cadr) (define-integrable inferior:line caar) (define-integrable inferior:y-size cdar) (define-integrable set-inferior:x-start! (lambda (inferior val) (set-cdr! (cdr inferior) val))) (define-integrable set-inferior:y-start! (lambda (inferior val) (set-car! (cdr inferior) val))) (define-integrable set-inferior:line! (lambda (inferior val) (set-car! (car inferior) val))) (define-integrable set-inferior:y-size! (lambda (inferior val) (set-cdr! (car inferior) val))) (define-integrable screen:cursor-y 0) (define-integrable screen:cursor-x 1) (define-integrable screen:x-size 5) (define-integrable screen:y-size 4) (define-integrable window:point 0) (define-integrable window:lines 1) (define-integrable window:map 2) (define-integrable window:screen 3) (define-integrable window:y-size 4) (define-integrable window:start 5) (define-integrable window:end 6) (define-integrable window:buffer 7) (define-integrable window:cursor-x 8) (define-integrable window:cursor-y 9) (define-integrable window:redisplay-window-flag 10) (define-integrable window:redisplay-cursor-flag 11) (define-integrable window:start-mark 12) (define-integrable window:end-mark 13) (define-integrable window:last-inferior-y 14) (define-integrable window-point (lambda (window) (vector-ref window window:point))) (define-integrable window-point-x (lambda (window) (vector-ref window window:cursor-x))) (define-integrable window-point-y (lambda (window) (vector-ref window window:cursor-y))) (define-integrable window-buffer (lambda (window) (vector-ref window window:buffer))) (define-integrable window-screen (lambda (window) (vector-ref window window:screen))) (define-integrable window-y-size (lambda (window) (vector-ref window window:y-size))) (define-integrable window-x-size (lambda (window) 80)) ) (define update-cursor! (lambda (window) (let ((screen (vector-ref window window:screen)) (x (vector-ref window window:cursor-x)) (y (vector-ref window window:cursor-y))) (vector-set! window window:redisplay-cursor-flag #!false) (if (and (not (negative? x)) (not (negative? y))) (set-screen-cursor! screen x y))))) (define (set-screen-cursor! screen x y) (%reify-port! screen screen:cursor-x x) (%reify-port! screen screen:cursor-y y)) (define set-cursor-pos (lambda (window x y) (vector-set! window window:cursor-x x) (vector-set! window window:cursor-y y) (vector-set! window window:redisplay-cursor-flag #!true))) (define write-string! (lambda (screen string x y) (set-screen-cursor! screen x y) (princ string screen))) (define (make-buffer-window screen buffer) (define (setup-inferior-table table y-size) (do ((i 0 (1+ i)) (table table)) ((= i y-size) table) (vector-set! table i (cons (cons #!false #!false) (cons i 0))))) (define initialize! (lambda (window buffer) (add-buffer-window! buffer window) ;;;; this is for the speed up hack insertch.scm (%create-char-daemon window) (let ((group (buffer-group buffer))) (add-group-delete-daemon! group (make-delete-daemon window)) (add-group-insert-daemon! group (make-insert-daemon window))) (vector-set! window window:point (buffer-point buffer)))) (let ((window (make-vector 15 #!false)) (start-buffer (buffer-start buffer)) (y-size (%reify-port screen screen:y-size))) (let ((table (setup-inferior-table (make-vector y-size) y-size))) (vector-set! window window:y-size y-size) (vector-set! window window:lines table) (vector-set! window window:screen screen) (vector-set! window window:buffer buffer) (update-bottom-inferior! (mark-line start-buffer) 0 0 (vector-ref table 0) table y-size) (map-changed! window) (vector-set! window window:start 0) (vector-set! window window:end 0) (vector-set! window window:cursor-x 0) (vector-set! window window:cursor-y 0) (vector-set! window window:start-mark start-buffer) (vector-set! window window:end-mark start-buffer) (vector-set! window window:last-inferior-y 0) (initialize! window buffer) window))) (define window-y-size-changed (lambda (window) (vector-set! window window:y-size (%reify-port (vector-ref window window:screen) screen:y-size)) (vector-set! window window:map '()) (window-redraw! window))) (define line->y (lambda (window line) (let ((entry (assq line (vector-ref window window:map)))) (and entry (cdr entry))))) (define set-window-point! (lambda (window mark) (let ((buffer (vector-ref window window:buffer))) (set-buffer-point! buffer mark) (vector-set! window window:point (buffer-point buffer)) (cursor-moved! window)))) (define cursor-moved! (lambda (window) (let ((point (vector-ref window window:point))) (if (window-mark-visible? window point) (set-cursor-coordinates window point) (window-redraw! window))))) (define (map-changed! window) (define (loop tail n table y-size) (if (or (>= n y-size) (null? (inferior:line (vector-ref table n)))) tail (let ((inferior (vector-ref table n))) (loop (cons (cons (inferior:line inferior) n) tail) (+ (inferior:y-start inferior) (inferior:y-size inferior)) table y-size)))) (let ((map (loop '() 0 (vector-ref window window:lines) (vector-ref window window:y-size)))) (vector-set! window window:map map) (vector-set! window window:last-inferior-y (cdar map)))) (define clear-subscreen! (lambda (screen xl yl lin col) (let ((sxl (%reify-port screen 3)) (syl (%reify-port screen 2)) (slin (%reify-port screen 4)) (scol (%reify-port screen 5)) (change-cord (lambda (x y l c) (%reify-port! screen 3 x) (%reify-port! screen 2 y) (%reify-port! screen 4 l) (%reify-port! screen 5 c)))) (change-cord (+ sxl xl) (+ syl yl) lin col) (%clear-window screen) (change-cord sxl syl slin scol)))) (define (redisplay window table start end) (let loop ((screen (window-screen window)) (n start) (end end) (table table) (y-size (vector-ref window window:y-size))) (if (> n end) '() (let ((inferior (vector-ref table n))) (if (inferior:line inferior) (begin (let ((y-start (inferior:y-start inferior)) (ys (inferior:y-size inferior)) (string (line-string (inferior:line inferior)))) (set-screen-cursor! screen 0 (max 0 y-start)) (%substring-display string 0 (string-length string) y-start screen) (loop screen (+ y-start ys) end table y-size))) (clear-subscreen! screen 0 n (1+ (- end n)) 80)))))) (define update-window! (lambda (window) (let ((table (vector-ref window window:lines)) (start (vector-ref window window:start)) (end (vector-ref window window:end))) (redisplay window table start end) (vector-set! window window:redisplay-window-flag #!false)))) (define update-display! (lambda (window) (if (vector-ref window window:redisplay-window-flag) (update-window! window)) (if (vector-ref window window:redisplay-cursor-flag) (update-cursor! window)))) (define reset-buffer-window (lambda (window) (vector-set! window window:start 0) (vector-set! window window:end (-1+ (vector-ref window window:y-size))) (vector-set! window window:redisplay-window-flag #!true) (vector-set! window window:redisplay-cursor-flag #!true) (update-display! window))) ;;; redisp2 (define window-redraw! (letrec ((%receiver (lambda (w) (error "window-redraw")))) (lambda (window) (let ((mark (vector-ref window window:point)) (y (quotient (vector-ref window window:y-size) 2))) (set-start-end! window 0 (-1+ (vector-ref window window:y-size))) (redraw-screen! window mark y) (everything-changed! window %receiver))))) (define redraw-screen! (lambda (window mark y) (let ((line (mark-line mark)) (table (vector-ref window window:lines)) (y-size (vector-ref window window:y-size)) (position (mark-position mark)) (string (line-string (mark-line mark)))) (let ((y* (index->y (char->x string position) 80 position string))) (let ((start (max 0 (- y y*))) (ys (find-y-size line)) (y-start (- y y*))) (clean-up-table table 0 y-size) (update-inferior! line 0 y-start ys (vector-ref table start)) (if (> ys 1) (fill-entries (1+ start) (min y-size (+ y-start ys)) start table y-size)) (fill-top! window line table y-size start #!TRUE)))))) (define everything-changed! (lambda (window if-not-visible) (map-changed! window) (start-mark-changed! window) (end-mark-changed! window) (if (window-mark-visible? window (vector-ref window window:point)) (begin (cursor-moved! window)) (if-not-visible window)))) (define (window-mark-visible? window mark) (and (mark<= (vector-ref window window:start-mark) mark) (mark<= mark (vector-ref window window:end-mark)))) (define (line-visible? window point) (assq (mark-line point) (vector-ref window window:map))) ;;; coordinates (define window-coordinates->mark (lambda (window x y) (let* ((table (vector-ref window window:lines)) (inferior (vector-ref table y))) (make-mark (inferior:line inferior) (x->char (line-string (inferior:line inferior)) (+ x (* (- y (inferior:y-start inferior)) 79))))))) (define (start-mark-changed! window) (vector-set! window window:start-mark (window-coordinates->mark window 0 0))) (define (end-mark-changed! window) (let ((inferior (vector-ref (vector-ref window window:lines) (vector-ref window window:last-inferior-y))) (y-size (vector-ref window window:y-size))) (let ((line (inferior:line inferior)) (y-start (inferior:y-start inferior)) (ys (inferior:y-size inferior))) (vector-set! window window:end-mark (make-mark line (end-column->index (line-string line) (+ 79 (* (- (-1+ (min y-size (+ y-start ys))) y-start) 79)))) )))) (define (maybe-marks-changed window y) (if (= y 0) (start-mark-changed! window)) (if (= y (vector-ref window window:last-inferior-y)) (end-mark-changed! window))) ;;; index->column (define (char->x string char-no) (let loop ((start 0)(tot 0)(end char-no)(string string)) (let ((index (substring-find-next-char-in-set string start end non-graphic-chars))) (if index (let ((tot (+ tot (- index start)))) (loop (1+ index) (+ tot (if (char-ci=? #\tab (string-ref string index)) (- 8 (remainder tot 8)) 2)) end string)) (+ tot (- end start)))))) ;;; column->index (define (x->char string column) (let loop ((string string)(start 0)(c 0)(end (string-length string)) (column column)) (let ((i (substring-find-next-char-in-set string start end non-graphic-chars))) (if i (let ((new-c (+ c (- i start)))) (if (<= column new-c) (+ start (- column c)) (let ((new-c (+ new-c (if (char-ci=? #\tab (string-ref string i)) (- 8 (remainder new-c 8)) 2)))) (if (<= column new-c) (1+ i) (loop string (1+ i) new-c end column))))) (min (+ start (- column c)) end))))) (define (end-column->index string column) (let loop ((string string)(start 0)(c 0)(end (string-length string)) (column column)) (let ((i (substring-find-next-char-in-set string start end non-graphic-chars))) (if i (let ((new-c (+ c (- i start)))) (if (<= column new-c) (+ start (- column c)) (let ((new-c (+ new-c (if (char-ci=? #\tab (string-ref string i)) (- 8 (remainder new-c 8)) 2)))) (cond ((