/collects/mred/private/wxme/wordbreak.rkt
http://github.com/gmarceau/PLT · Racket · 155 lines · 140 code · 15 blank · 0 comment · 38 complexity · d300b46fc723e6f359a7ceb83a0f3154 MD5 · raw file
- #lang scheme/base
- (require scheme/class
- "../syntax.rkt"
- "cycle.rkt")
- (provide editor-wordbreak-map%
- the-editor-wordbreak-map
- standard-wordbreak)
- (defclass editor-wordbreak-map% object%
- (define char-map (make-hash))
- (super-new)
- (hash-set! char-map #\- '(line))
- (def/public (set-map [char? ch] [(make-list (symbol-in caret line selection user1 user2)) mask])
- (hash-set! char-map ch mask))
- (def/public (get-map [char? ch])
- (or (hash-ref char-map ch #f)
- (cond
- [(or (char-alphabetic? ch)
- (char-numeric? ch))
- '(caret line selection)]
- [(not (char-whitespace? ch))
- '(line)]
- [else null]))))
- (define the-editor-wordbreak-map (new editor-wordbreak-map%))
- (define MAX-DIST-TRY 30)
- (define wb-get-map (generic editor-wordbreak-map% get-map))
- (define (string-ref* str n)
- (if (n . >= . (string-length str))
- #\nul
- (string-ref str n)))
- (define/top (standard-wordbreak [text% win]
- [(make-or-false (make-box exact-nonnegative-integer?)) startp]
- [(make-or-false (make-box exact-nonnegative-integer?)) endp]
- [(symbol-in caret line selection user1 user2) reason])
- (let ([wb (send win get-wordbreak-map)])
- (when wb
- (with-method ([get-map (wb get-map)])
- (define (nonbreak? ch) (memq reason (get-map ch)))
- (when startp
- (let* ([start (unbox startp)]
- [pstart start]
- [lstart (send win find-newline 'backward start 0)]
- [lstart (if lstart
- (if (eq? 'caret reason)
- (or (and (positive? lstart)
- (send win find-newline 'backward (sub1 lstart) 0))
- 0)
- lstart)
- 0)]
- [lend (min (+ start 1) (send win last-position))]
- [tstart (if ((- start lstart) . > . MAX-DIST-TRY)
- (- start MAX-DIST-TRY)
- lstart)]
- [text (send win get-text tstart lend)]
- [start (- start tstart)]
- [pstart (- pstart tstart)])
- (let ploop ([phase1-complete? #f]
- [phase2-complete? #f]
- [start start]
- [pstart pstart]
- [text text]
- [tstart tstart])
- (let*-values ([(start phase1-complete?)
- (if phase1-complete?
- (values start #t)
- (let ([start (if (and (positive? start)
- (nonbreak? (string-ref* text start)))
- (sub1 start)
- start)])
- (values start
- (not (nonbreak? (string-ref* text start))))))]
- [(start phase2-complete?)
- (if (not (eq? 'selection reason))
- (if (not phase2-complete?)
- (let loop ([start start])
- (if (and (positive? start)
- (not (nonbreak? (string-ref* text start))))
- (loop (sub1 start))
- (if (nonbreak? (string-ref* text start))
- (values start #t)
- (values start #f))))
- (values start #t))
- (values start phase2-complete?))])
- (let loop ([start start])
- (if (and (positive? start)
- (nonbreak? (string-ref* text start)))
- (loop (sub1 start))
- (let ([start (if (and (start . < . pstart)
- (not (nonbreak? (string-ref* text start))))
- (add1 start)
- start)])
- (if (and (zero? start)
- (not (= lstart tstart)))
- (ploop phase1-complete?
- phase2-complete?
- (+ start (- tstart lstart))
- (+ pstart (- tstart lstart))
- (send win get-text lstart lend)
- lstart)
- (set-box! startp (+ start tstart))))))))))
-
- (when endp
- (let* ([end (unbox endp)]
- [lstart end]
- [lend (send win find-newline 'forward end)]
- [lend (if lend
- (if (eq? 'caret reason)
- (or (send win find-newline 'forward (+ lend 1))
- (send win last-position))
- lend)
- (send win last-position))]
- [tend (if ((- lend end) . > . MAX-DIST-TRY)
- (+ end MAX-DIST-TRY)
- lend)]
- [text (send win get-text lstart tend)]
- [end (- end lstart)]
- [lend (- lend lstart)]
- [tend (- tend lstart)])
-
- (let ploop ([phase1-complete? #f]
- [text text]
- [tend tend]
- [end end])
- (let-values ([(end phase1-complete?)
- (if phase1-complete?
- (values end #t)
- (let loop ([end end])
- (if (and (end . < . tend)
- (not (nonbreak? (string-ref* text end))))
- (loop (add1 end))
- (if (end . < . tend)
- (values end #t)
- (values end #f)))))])
- (let loop ([end end])
- (if (and (end . < . tend)
- (nonbreak? (string-ref* text end)))
- (loop (add1 end))
- (if (and (= tend end) (not (= lend tend)))
- (ploop phase1-complete?
- (send win get-text lstart (+ lstart lend))
- lend
- end)
- (set-box! endp (+ end lstart)))))))))))))