utils.ss
#lang scheme/base

(require scheme/gui)

(provide (all-defined-out))

;; y position of the current line
(define (current-line master)
  (send master find-line 
        (let ([x (box 0)]
              [y (box 0)])
          (send master position-location
                (send master get-start-position)
                x y)
          (unbox y))))

;; starting position of the given line
(define (find-line-start master line)
  (send master line-start-position line))

;; starting position of the current line
(define (find-line-start-current master)
  (find-line-start master (current-line master)))

;; ending position of the given line
(define (find-line-end master line)
  (add1
    (send master line-end-position line)))

;; ending position of the current line
(define (find-line-end-current master)
  (find-line-end master (current-line master)))

;; move the cursor until the predicate matches
(define (find-until master matcher start mover)
  (let* ([limit (send master last-position)])
    (let loop ([here start])
      (cond
        [(<= here 0) 0]
        [(>= here limit) limit]
        [(matcher (send master get-character here))
         (loop (mover here))]
        [else here]))))

;; find the previous word
;; returns position
(define (previous-word master start)
  (case (send master get-character start)
    [(#\( #\[ #\) #\]) start]
    [(#\space #\tab) (find-until master
                                 (lambda (c)
                                   (or (equal? #\space c)
                                       (equal? #\tab c)))
                                 start
                                 sub1)]
    [else (find-until master
                      (lambda (c)
                        (not (member c '(#\( #\[ #\) #\]
                                         #\newline #\space #\tab))))
                      start
                      sub1)]))

(define (next-word master start)
  (case (send master get-character start)
    [(#\( #\[ #\) #\]) start]
    [(#\space #\tab) (find-until master
                                 (lambda (c)
                                   (or (equal? #\space c)
                                       (equal? #\tab c)))
                                 start
                                 add1)]
    [else (find-until master
                      (lambda (c)
                        (not (member c '(#\( #\[ #\) #\]
                                         #\newline #\space #\tab))))
                      start
                      add1)]))

(define (repeat num proc)
           (for ([i (in-range 0 num)])
                (proc i)))