(module mred-state mzscheme
(require (lib "class.ss")
(lib "struct.ss")
(lib "mred.ss" "mred")
"utilities.ss"
"structures.ss"
"rope.ss")
(provide MrEd-state% MrEd-state<%>)
(define MrEd-state<%>
(interface ()
pull-world
push-world))
(define MrEd-state%
(class* object% (MrEd-state<%>)
(super-instantiate ())
(init window-text-init)
(define window-text window-text-init)
(define (get-rope)
(send window-text diva:-get-rope))
(define (update-text rope)
(send window-text diva:-update-text rope))
(define (get-cursor-position)
(index->pos (send window-text get-start-position)))
(define (set-cursor-position pos)
(send window-text diva:set-selection-position (pos->index pos)))
(define (set-selection pos len)
(if (<= 0 len)
(begin (send window-text set-position
(pos->index pos)
(+ len (pos->index pos))
#f #f 'local)
(send window-text scroll-to-position
(pos->index pos)
#f
(+ len (pos->index pos))
'start))
(set-selection (+ pos len) (- len))))
(define (get-selection-len)
(let ([start-pos (send window-text get-start-position)]
[end-pos (send window-text get-end-position)])
(- end-pos start-pos)))
(define (get-mark-position)
(index->pos (send window-text diva:-get-mark-start-position)))
(define (get-mark-length)
(let ([mark-start-pos (send window-text diva:-get-mark-start-position)]
[mark-end-pos (send window-text diva:-get-mark-end-position)])
(- mark-end-pos mark-start-pos)))
(define (set-mark pos len)
(if (>= len 0)
(send window-text diva:-set-mark (pos->index pos) (+ (pos->index pos) len))
(set-mark (+ pos len) (- len))))
(define/public (pull-world original-world)
(update-world-path
(update-world-mark
(update-world-select
(update-world-text original-world)))))
(define (update-world-path original-world)
(copy-struct World original-world
[World-path (send window-text get-filename)]))
(define (update-world-text original-world)
(cond
[(rope=? (World-rope original-world) (get-rope))
(copy-struct World original-world
[World-rope (get-rope)]
[World-syntax-list/lazy
(World-syntax-list/lazy original-world)])]
[else
(copy-struct World original-world
[World-rope (get-rope)]
[World-syntax-list/lazy #f])]))
(define (update-world-select original-world)
(let*-values
([(p l) (values (get-cursor-position) (get-selection-len))]
[(stop-extending)
(or clear-extension
(not (and
(= p (World-cursor-position original-world))
(= l (World-selection-length original-world)))))])
(copy-struct World original-world
[World-cursor-position (get-cursor-position)]
[World-selection-length (get-selection-len)]
[World-extension (if stop-extending #f (World-extension original-world))])))
(define (update-world-mark original-world)
(if (World-extension original-world)
original-world
(copy-struct World original-world
[World-mark-position (get-mark-position)]
[World-mark-length (get-mark-length)])))
(define clear-extension #f)
(define/public (push-world world)
(unless (rope=? (World-rope world) (get-rope))
(update-text (World-rope world)))
(set-selection (World-cursor-position world) (World-selection-length world))
(cond [(World-extension world)
(let ([e (World-extension world)])
(set-mark (extension-puck e)
(extension-puck-length e))
(send window-text scroll-to-position
(extension-puck e)
#f
(+ (extension-puck e) (extension-puck-length e))
'none)
(set! clear-extension #f)
(send window-text diva:-insertion-after-set-position-callback-set
(lambda ()
(send window-text diva-message "")
(set! clear-extension #t)
(set-mark 1 0))))]
[else
(set-mark (World-mark-position world) (World-mark-length world))
(send window-text diva:-insertion-after-set-position-callback-set
(lambda () (void)))])
(send window-text diva-message (World-success-message world))))))