diff --git a/doc/input-fiels-de.txt b/doc/input-fiels-de.txt new file mode 100644 index 0000000..b2b179a --- /dev/null +++ b/doc/input-fiels-de.txt @@ -0,0 +1,171 @@ + + Input-fields + ============ + +1. Erstellen und installieren +----------------------------- + +(make-input-field x-dim y-dim) -> + +erstellt ein Input-field mit x-dim Spalten und y-dim Zeilen. +Make-input-field können weitere optinale Parameter übergeben +werden: + +(make-input-field x-dim y-dim + [default-text + [behavior + [insert-active + [x-scroll-enabled + [y-scroll-enabled]]]]]) + +default-text: ist ein String, der am Anfang und nach einem Reset (s.u.) + der Inhalt des Input-fields ist. + (Default: "") +behavior: ist eine Liste von Paaren. Der car eines solchen Paares + ist die Nummer eines Zeichens oder einer Tastenkombination, + wie sie von wgetch (aus ncurses) zurückgegeben werden. + Der cdr des Paares ist ein Symbol, das eine Nachricht an ein + Input-field darstellt, so würde ein Input-field, das mit dem + Behvior + (list (cons 27 + 'clear)) + erzeugt worden ist beim drücken der ESC-Taste seinen Inhalt + löschen.Es stehen zwei Standardlisten zu Verfügung: + standard-behavior und standard-behavior-pro (s.u.). + (Default: standard-behavior) +insert-active: ist ein Boolean und gibt an ob das sich das Input-field am + Anfang im Insert- oder im Overwrite-Modus befindet. + (Default: #t) +x-scroll-enabled: ist ein Boolean und gibt an ob horizontales Scrollen + erlaubt ist. + (Default #f) +y-scroll-enabled: ist ein Boolean und gibt an, ob vertikales Scrollen erlaubt ist. + (Default #f) + + + +(install-input-field input-field + window + x-loc y-loc) +Ordnet das Input-field input-field dem (ncurses-)Fenter window zu und +platziert es mit der linken oberen Ecke in der Spalte x-loc und der +Zeile y-loc. +Will man das Input-field später nicht direkt verwenden, sondern nur +über cursor-over-input-field? (s.u.) so kann man es auch mittels +make&install-input-field auf einmal erzeugen und installieren: + +(make&install-input-field window + x-loc y-loc + x-dim y-dim + [...]) + + +2. Typpredikat und Feldselektoren +---------------------------------- + +Input-fields exportirt außerdem ein Typpredikat: + input-field? +und die folgenden Selektoren + input-field-default-text: default-text + input-field-text: der aktuelle Inhalt des Input-fields + als String + input-field-x-location: x-loc + input-field-y-location: y-loc + input-field-x-size: x-dim + input-field-y-size: y-dim + input-field-x-scroll: x-scroll-enabled + input-field-y-scroll: y-scroll-enabled + input-field-line: die Zeile, in der der Cursor steht + input-field-column: die Spalte, in der der Cursor steht + input-field-insert: insert-active + + +3. Bahaviors +---------------------- + +standard-behavior führt die folgenden Bindungen ein: +Pfeil-Hoch : Cursor um eine Zeile nach oben bewegen. +Pfeil-Runter: Cursor um eine Zeile nach unten bewegen. +Pfeil-links: Cursor nach links bewegen. +Pfeil-Rechts: Cursor nach rechts bewegen. +Home: An den Anfang der Zeile springen. +End: Ans Ende der Zeile springen. +Backspace: Zeichen vor dem Cursor löschen. +Delete: Zeichen unter dem Cursor löschen + +standard-behavior-pro erweitert standard-behavior um die +folgenden Bindungen: +C-p: Cursor um eine Zeile nach oben bewegen. +C-n: Cursor um eine Zeile nach unten bewegen. +C-b: Cursor nach links bewegen. +C-f: Cursor nach rechts bewegen. +C-a: An den Anfang der Zeile springen. +C-e: Ans Ende der Zeile springen. +C-d: Zeichen unter dem Cursor löschen. +C-k: alles rechts vom Cursor löschen. + +die folgenden (hoffentlich) selbsterklärenden Symbole stehen +zum Erstellen von Behaviors zu verfügung: + +'move-prev-line +'move-next-line +'move-left +'move-right + +'move-forawrd - wie move-right, springt aber nach Ende der Zeile + auf den Anfang der Nächsten. +'move-backward - equivalent zu 'move-forward + +'goto-begin-of-line +'goto-end-of-line +'goto-begin-of-first-line +'goto-begin-of-last-line +'goto-begin-of-word-forward +'goto-begin-of-word-backward + +'delete-left +'delete-right +'delete-all-left +'delete-all-right +'delete-line + +'restore: Synchronisiert inrterne Daten mit externer Darstellung + und Zeichent das Input-field neu. + (war bisher nicht nötig, aber sobald Sonderzeichen erlaubt + sind.... ;-) + +Außerdem zeichnet die Funktion +(input-field-refresh input-field) +das Input-field neu. + +4. Cursor-over-inputfield? und send-input-field +----------------------------------------------- + +(cursor-over-input-field? window) -> #f | input-field +liefert, wenn der Cursor im Fenster window über einem zuvor installiertem +Input-field steht, dieses Input-field zurück, ansonsten #f. + +(send-input-field input-field integer) -> (values boolean boolean) +übergibt dem Input-field input-field die Zahl integer. Das Input-field +schaut zuerst, ob es sich um eine im Behavior gebundene Zahl handelt und +führt, falls dies der Fall ist die entsprechende Aktion aus. Falls integer +nicht im Behavior gebunden ist überprüft das Input-field ob es sich um einen +gültigen zum Einfügen gültigen Ascii-code (32-126) handelt und fügt das +entsprechende Zeichen gegebenenfalls an der aktuellen Cursorposition ein. + + +5. Position, Größe, Scrolleigenschaften nachträglich verändern +-------------------------------------------------------------- + +;; TODOOO + +hierzu stehen folgende Funktionen zur Verfügung: + + (input-field-reset input-field) - stellt den default-text wieder her + (input-field-clear input-field) - löscht den Inhalt + (input-field-move input-field x-loc y-loc) - setzt die linke, obere Ecke auf (x-loc y-loc) + (input-field-resize input-field x-dim y-dim) - setzt ... + (input-field-toggle-x-scroll input-field) + (input-field-toggle-y-scroll input-field) + + diff --git a/scheme/demo.scm b/scheme/demo.scm new file mode 100644 index 0000000..012cece --- /dev/null +++ b/scheme/demo.scm @@ -0,0 +1,217 @@ +(define NULL (ascii->char 0)) + +(define demo + (lambda () + (let ((win (init-screen))) + (keypad win #t) + (noecho) + + (make&install-input-field win + 20 10 + 42 23 + " + +----------------------------------+ + | f1 : move left input-field | + | f2 : move right input-field | + | f3 : move up input-field | + | f4 : move down input-field | + | | + | f5 : make bigger in x direction | + | f6 : make smaler in x direction | + | f7 : make bigger in y direction | + | f8 : make smaler in y direction | + | | + | f9 : toggle x-scroll | + | f10 : toggle y-scroll | + | | + | f11 : clear | + | f12 : reset | + | | + | tab : toggle insert | + | | + | ESC : quit | + +----------------------------------+ + +0-0 0-1 0-2 0-3 0-4 0-5 +1-0 1-1 1-2 1-3 1-4 1-5 1-6 +2-0 2-1 2-2 2-3 2-4 2-5 2-6 2-7 +3-0 3-1 3-2 3-3 3-4 3-5 3-6 3-7 3-8 +4-0 4-1 4-2 4-3 4-4 4-5 4-6 4-7 4-8 4-9 +5-0 5-1 5-2 5-3 5-4 5-5 5-6 5-7 5-8 4-9 +6-0 6-1 6-2 6-3 6-4 6-5 6-6 6-7 6-8 +7-0 7-1 7-2 7-3 7-4 7-5 7-6 7-7 +8-0 8-1 8-2 8-3 8-4 8-5 8-6 +9-0 9-1 9-2 9-3 9-4 9-5\n" + (append + (list (cons 9 ;; tab + 'toggle-insert) + (cons key-ppage + 'move-backward) + (cons key-npage + 'move-forward)) + standard-behavior-pro) + #t #t #t) + + (wmove win 10 20) + (screen-refresh win) + + (letrec ((else-loop (lambda (asc) + (let ((infl (cursor-over-input-field? win))) + (cond ((= asc 27) + (wclear win) + (clear) + (echo) + (endwin)) + ((= asc key-f1) + (input-field-move infl + (- (input-field-x-location infl) + 1) + (input-field-y-location infl)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f2) + (input-field-move infl + (+ (input-field-x-location infl) + 1) + (input-field-y-location infl)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f3) + (input-field-move infl + (input-field-x-location infl) + (- (input-field-y-location infl) + 1)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f4) + (input-field-move infl + (input-field-x-location infl) + (+ (input-field-y-location infl) + 1)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f5) + (input-field-resize infl + (+ (input-field-x-size infl) + 1) + (input-field-y-size infl)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f6) + (input-field-resize infl + (- (input-field-x-size infl) + 1) + (input-field-y-size infl)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f7) + (input-field-resize infl + (input-field-x-size infl) + (+ (input-field-y-size infl) + 1)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f8) + (input-field-resize infl + (input-field-x-size infl) + (- (input-field-y-size infl) + 1)) + (screen-refresh win) + (loop (wgetch win))) + ((= asc key-f9) + (input-field-toggle-x-scroll infl) + (wrefresh win) + (loop (wgetch win))) + ((= asc key-f10) + (input-field-toggle-y-scroll infl) + (wrefresh win) + (loop (wgetch win))) + ((= asc key-f11) + (input-field-clear infl) + (wrefresh win) + (loop (wgetch win))) + ((= asc key-f12) + (input-field-reset infl) + (wrefresh win) + (loop (wgetch win))) + (else (loop (wgetch win))))))) + (loop (lambda (asc) + (cond ((cursor-over-input-field? win) + => (lambda (infl) + (call-with-values + (lambda () + (send-input-field infl asc)) + (lambda (was-known is-changed) + (if is-changed + (begin + (wrefresh win) + (loop (wgetch win))) + (if was-known + (loop (wgetch win)) + (else-loop asc))))))))))) + (loop (wgetch win)))))) + + +(define screen-refresh + (lambda (screen) + (let ((infl (cursor-over-input-field? screen)) + (x (getx screen)) + (y (gety screen))) + (wclear screen) + (input-field-refresh infl) + (wdraw-box screen + (- (input-field-x-location infl) 1) + (- (input-field-y-location infl) 1) + (+ (input-field-x-size infl) 2) + (+ (input-field-y-size infl) 2)) + (wmove screen y x) + (wrefresh screen)))) + +(define wdraw-box + (lambda (win x y dimx dimy) + (mvwaddstr win + y + x "+") + (mvwaddstr win + y + (+ dimx + (- x + 1)) "+") + (mvwaddstr win + (+ dimy + (- y + 1)) + x "+") + (mvwaddstr win + (+ dimy + (- y + 1)) + (+ dimx + (- x + 1)) "+") + (let loop-x ((dx (+ x 1))) + (if (= dx (+ x (- dimx 2))) + (begin + (mvwaddstr win y dx "-") + (mvwaddstr win (+ dimy + (- y + 1)) dx "-")) + (begin + (mvwaddstr win y dx "-") + (mvwaddstr win (+ dimy + (- y + 1)) dx "-") + (loop-x (+ dx 1))))) + (let loop-y ((dy (+ y 1))) + (if (= dy (+ y (- dimy 2))) + (begin + (mvwaddstr win dy x "|") + (mvwaddstr win dy (+ dimx + (- x + 1)) "|")) + (begin + (mvwaddstr win dy x "|") + (mvwaddstr win dy (+ dimx + (- x + 1)) "|") + (loop-y (+ dy 1))))))) diff --git a/scheme/input-fields.scm b/scheme/input-fields.scm new file mode 100644 index 0000000..82a4b38 --- /dev/null +++ b/scheme/input-fields.scm @@ -0,0 +1,1461 @@ +;; TODOO +;; sobald funktinalität getestet +;; und abgesegnet -> +;; mach's klein! mach's schnell!... +;;=============================================================================== +;; record input-field: + +(define-record-type input-field :input-field + (really-make-input-field default-text + edit-lines + window + behavior + insert-active + x-loc y-loc + x-dim y-dim + x-pos y-pos + x-edit-pos y-edit-pos + x-offset y-offset + x-scroll y-scroll) + input-field? + (default-text if-default-text) + (edit-lines if-edit-lines set-if-edit-lines!) + (window if-window set-if-window!) + (behavior if-behavior set-if-behavior!) + (insert-active if-insert-active set-if-insert-active!) + (x-loc if-x-loc set-if-x-loc!) + (y-loc if-y-loc set-if-y-loc!) + (x-dim if-x-dim set-if-x-dim!) + (y-dim if-y-dim set-if-y-dim!) + (x-pos if-x-pos set-if-x-pos!) + (y-pos if-y-pos set-if-y-pos!) + (x-edit-pos if-x-edit-pos set-if-x-edit-pos!) + (y-edit-pos if-y-edit-pos set-if-y-edit-pos!) + (x-offset if-x-offset set-if-x-offset!) + (y-offset if-y-offset set-if-y-offset!) + (x-scroll if-x-scroll set-if-x-scroll!) + (y-scroll if-y-scroll set-if-y-scroll!)) + +(define-record-discloser :input-field + (lambda (i-f) + (list 'input-field + (if-default-text i-f)))) + +;; record input-field END +;;=============================================================================== + +;;=============================================================================== +;; "basics" + +; ---------------------------------------------------------------------------- +;; "basics" - make-input-field + +(define make-input-field + (lambda (x-dim y-dim . args) + (let* ((args-len (length args)) + (default-text (if (> args-len 0) + (car args) + "")) + (behavior (if (> args-len 1) + (cadr args) + standard-behavior)) + (insert-active (if (> args-len 2) + (caddr args) + #t)) + (x-scroll (if (> args-len 3) + (cadddr args) + #f)) + (y-scroll (if (> args-len 4) + (caddddr args) + #f))) + (let ((i-f (really-make-input-field default-text + #f + #f + behavior + insert-active + #f #f + x-dim y-dim + 0 0 + 0 0 + 0 0 + x-scroll y-scroll))) + (set-if-edit-lines! i-f + (string->if-edit-lines i-f + default-text)) + i-f)))) + +;; "basics" - make-input-field END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; "basics" - remove / install-input-field & cursor-over-input-field? + +;; FIXIT: sollte jemand auf die idee kommen ein input-field in mehrere +;; fenster zu installieren, müsste man hier noch was tun :-( + +;; -------------------------------------------- +;; input-field-lookup-list +;; für die zentrale verwaltung der input-fields +;; -------------------------------------------- +(define input-fields-lookup-list '()) + +;; -------------------------------------------------- +;; install-input-field ordnet einem input-field ein +;; window zu und trägt das input-field in die +;; look-up-liste als weak-pointer ein +;; --------------------------------------------------- +(define install-input-field + (lambda (i-f window x y) + (set-if-window! i-f window) + (set-if-y-loc! i-f y) + (set-if-x-loc! i-f x) + (set! input-fields-lookup-list + (cons (make-weak-pointer i-f) + (util-filter (lambda (x) x) + input-fields-lookup-list))) + (refresh-all i-f) + (wrefresh window))) + +(define make&install-input-field + (lambda (win x-loc y-loc x-dim y-dim . args) + (install-input-field (apply make-input-field + x-dim y-dim + args) + win + x-loc y-loc))) + +(define remove-input-field + (lambda (i-f) + (set! input-fields-lookup-list + (let loop ((input-fields input-fields-lookup-list)) + (if (null? input-fields) + '() + (let ((first (car input-fields))) + (if (eq? i-f first) + (cdr input-fields) + (cons first + (loop (cdr input-fields)))))))))) + +;; -------------------------------------------------------- +;; cursor-over-input-field? schaut nach, ob ein input-field +;; in das übergebene window eingetragen ist und ob +;; sich der cursor über diesem befindet +;; -------------------------------------------------------- +(define cursor-over-input-field? + (lambda (window) + (let ((x (getx window)) + (y (gety window))) + (let loop ((i-f-lst input-fields-lookup-list)) + (if (null? i-f-lst) + #f + (let* ((i-f (weak-pointer-ref (car i-f-lst))) + (win (if i-f + (if-window i-f) + #f))) + (if (eq? window win) + (or (cursor-over-this-input-field? x y i-f) + (loop (cdr i-f-lst))) + (loop (cdr i-f-lst))))))))) + +(define cursor-over-this-input-field? + (lambda (cursor-x cursor-y i-f) + (let* ((upper-left-x (if-x-loc i-f)) + (upper-left-y (if-y-loc i-f)) + (lower-right-x (- (+ upper-left-x + (if-x-dim i-f)) + 1)) + (lower-right-y (- (+ upper-left-y + (if-y-dim i-f)) + 1))) + (if (and (>= cursor-y upper-left-y) + (<= cursor-y lower-right-y) + (>= cursor-x upper-left-x) + (<= cursor-x lower-right-x)) + i-f + #f)))) +;; "basics" - remove / install-input-field & cursor-over-input-field END +;; --------------------------------------------------------------------------- + +;; --------------------------------------------------------------------------- +;; "basics" - selectors + +;; TODOO - vielleicht gibt's sowas wie "export-as" + +(define input-field-default-text if-default-text) +(define input-field-x-location if-x-loc) +(define input-field-y-location if-y-loc) +(define input-field-x-size if-x-dim) +(define input-field-y-size if-y-dim) +(define input-field-column if-x-edit-pos) +(define input-field-line if-y-edit-pos) +(define input-field-x-scroll if-x-scroll) +(define input-field-y-scroll if-y-scroll) +(define input-field-insert if-insert-active) + +(define input-field-text + (lambda (i-f) + (list->string (cat (if-edit-lines i-f))))) + +;(define input-field-edit-pos +; (lambda (i-f) +; (values (if-x-edit-pos i-f) +; (if-y-edit-pos i-f)))) + +;; "basics" - selectors END +;; --------------------------------------------------------------------------- + +;; --------------------------------------------------------------------------- +;; "basics" - clear/reset + +(define input-field-clear + (lambda (i-f) + (set-if-x-offset! i-f 0) + (set-if-y-offset! i-f 0) + (set-if-x-pos! i-f 0) + (set-if-y-pos! i-f 0) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f 0) + (set-if-edit-lines! i-f '(())) + (refresh-all i-f))) + +(define input-field-reset + (lambda (i-f) + (set-if-x-offset! i-f 0) + (set-if-y-offset! i-f 0) + (set-if-x-pos! i-f 0) + (set-if-y-pos! i-f 0) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f 0) + (set-if-edit-lines! i-f + (string->if-edit-lines i-f + (if-default-text i-f))) + (refresh-all i-f))) + +;; "basics" - clear/reset END +;; --------------------------------------------------------------------------- + +;; "basics" END +;;=============================================================================== + + +;;=============================================================================== +;; draw/refresh functions + +(define paint-black + (lambda (i-f) + (let ((x-dim (if-x-dim i-f)) + (y-dim (if-y-dim i-f)) + (x-loc (if-x-loc i-f)) + (y-loc (if-y-loc i-f)) + (win (if-window i-f))) + (let loop ((dy 0) + (strings (map list->string + (fill-up '() + y-dim + (fill-up '() + x-dim + #\space))))) + (if (null? strings) + #t + (begin + (mvwaddstr win + (+ y-loc dy) x-loc + (car strings)) + (loop (+ dy 1) + (cdr strings)))))))) + + + +;;; TODOOOO (performance): +;;; funktionen geben zurück welcher +;;; refresh notwendig ist z.b.: +;;; 'position +;;; 'current-line +;;; 'from-current-line ... +;;; if-refresh ruft dann das richtige auf + +(define if-refresh + (lambda (i-f msg) + (if msg + (refresh-all i-f) + (values #t #f)))) + +(define refresh-position + (lambda (i-f) + (wmove (if-window i-f) + (+ (if-y-loc i-f) + (if-y-pos i-f)) + (+ (if-x-loc i-f) + (if-x-pos i-f))) + (values #t #t))) + +(define refresh-from-position + (lambda (i-f) + #f)) + +(define refresh-all + (lambda (i-f) + (let ((x-loc (if-x-loc i-f)) + (y-loc (if-y-loc i-f)) + (x-dim (if-x-dim i-f)) + (y-dim (if-y-dim i-f)) + (x-offset (if-x-offset i-f)) + (y-offset (if-y-offset i-f)) + (win (if-window i-f))) + (let* ((if-lines (map (lambda (if-line) + (util-filter (lambda (char) + (not (char=? char #\newline))) + if-line)) + (cat (map (lambda (edit-line) + (edit-line->if-lines i-f + edit-line)) + (if-edit-lines i-f))))) + (if-lines-cut (take (drop (map (lambda (if-line) + (take (drop if-line + x-offset) + x-dim)) + if-lines) + y-offset) + y-dim)) + (if-lines-filled (map (lambda (if-line) + (fill-up if-line + x-dim + #\space)) + (fill-up if-lines-cut + y-dim + '())))) + (let loop ((lines if-lines-filled) + (y-ofst 0)) + (if (null? lines) + (refresh-position i-f) + (begin + (mvwaddstr win + (+ y-loc y-ofst) + x-loc + (list->string (car lines))) + (loop (cdr lines) + (+ y-ofst 1))))))))) + +(define refresh-current-line + (lambda (i-f) + #f)) + +;; draw/refresh functions END +;;=============================================================================== + + +;;=============================================================================== +;; send-input-field + +(define send-input-field + (lambda (i-f msg . args) + (if (integer? msg) + (cond ((get-behavior i-f msg) => + (lambda (method) + (apply really-send-input-field i-f method args))) + (else (apply really-send-input-field i-f msg args))) + (values #f #f)))) + +(define really-send-input-field + (lambda (i-f msg . args) + (cond ((and (number? msg) + (or (and (> msg 31) + (< msg 127)) + (= msg 10) + (= msg 13))) + (if-refresh i-f (insert-char i-f + (if (= msg 13) + #\newline + (ascii->char msg))))) + ((eq? msg 'move-prev-line) + (if-refresh i-f (move-prev-line i-f))) + ((eq? msg 'move-next-line) + (if-refresh i-f (move-next-line i-f))) + ((eq? msg 'move-left) + (if-refresh i-f (move-left i-f))) + ((eq? msg 'move-right) + (if-refresh i-f (move-right i-f))) + ((eq? msg 'delete-right) + (if-refresh i-f (delete-right i-f))) + ((eq? msg 'move-forward) + (if-refresh i-f (move-forward i-f))) + ((eq? msg 'move-backward) + (if-refresh i-f (move-backward i-f))) + ((eq? msg 'delete-left) + (if-refresh i-f (delete-left i-f))) + ((eq? msg 'delete-all-right) + (if-refresh i-f (delete-all-right i-f))) + ((eq? msg 'delete-all-left) + (if-refresh i-f (delete-all-left i-f))) + ((eq? msg 'delete-line) + (if-refresh i-f (delete-line i-f))) + ((eq? msg 'goto-begin-of-line) + (if-refresh i-f (goto-begin-of-line i-f))) + ((eq? msg 'goto-end-of-line) + (if-refresh i-f (goto-end-of-line i-f))) + ((eq? msg 'goto-begin-of-first-line) + (if-refresh i-f (goto-begin-of-first-line i-f))) + ((eq? msg 'goto-begin-of-last-line) + (if-refresh i-f (goto-begin-of-last-line i-f))) + ((eq? msg 'goto-begin-of-word-forward) + (if-refresh i-f (goto-begin-of-word-forward i-f))) + ((eq? msg 'goto-begin-of-word-backward) + (if-refresh i-f (goto-begin-of-word-backward i-f))) + ((eq? msg 'goto-end-of-word-forward) + (if-refresh i-f (goto-begin-of-word-forward i-f))) + ((eq? msg 'goto-end-of-word-backward) + (if-refresh i-f (goto-begin-of-word-backward i-f))) +; ((eq? msg 'input-field-move-up) +; (if-refresh i-f (input-field-move-up i-f))) +; ((eq? msg 'input-field-move-down) +; (if-refresh i-f (input-field-move-down i-f))) +; ((eq? msg 'input-field-move-left) +; (if-refresh i-f (input-field-move-left i-f))) +; ((eq? msg 'input-field-move-right) +; (if-refresh i-f (input-field-move-right i-f))) + ((eq? msg 'refresh-all) + (refresh-all i-f)) + ((eq? msg 'toggle-insert) + (toggle-insert i-f)) + ((eq? msg 'restore) + (restore-input-field i-f)) + ((list? msg) + (for-each (lambda (msg-single) + (send-input-field i-f + msg-single)) + msg) + (values #t #t)) + (else (values #f #f))))) + +;; send-input-field END +;;=============================================================================== + +;;=============================================================================== +;; behavior lists + +(define standard-behavior + (list (cons key-up + 'move-prev-line) + (cons key-down + 'move-next-line) + (cons key-left + 'move-left) + (cons key-right + 'move-right) + (cons key-backspace + 'delete-left) + (cons key-dc + 'delete-right) + (cons key-home + 'goto-begin-of-line) + (cons key-end + 'goto-end-of-line))) + +(define standard-behavior-pro + (append standard-behavior + (list (cons 2 ;; C-b + 'move-left) + (cons 6 ;; C-f + 'move-right) + (cons 16 ;; C-p + 'move-prev-line) + (cons 14 ;; C-n + 'move-next-line) + (cons 1 ;; C-a + 'goto-begin-of-line) + (cons 5 ;; C-e + 'goto-end-of-line) + (cons 4 ;; C-d + 'delete-right) + (cons 11 ;; C-k + 'delete-all-right)))) + +;; behavior lists END +;;=============================================================================== +;;=============================================================================== +;; behavior methods + +(define get-behavior + (lambda (i-f msg) + (let loop ((behavior (if-behavior i-f))) + (if (null? behavior) + #f + (if (eq? msg (caar behavior)) + (cdar behavior) + (loop (cdr behavior))))))) + +;; ---------------------------------------------------------------------------- +;; move + +(define move-prev-line + (lambda (i-f) + (if (first-line? i-f) + #f + (begin + (set-if-y-edit-pos! i-f (- (if-y-edit-pos i-f) + 1)) + (sync-if-edit-pos i-f))))) + +(define move-next-line + (lambda (i-f) + (if (last-line? i-f) + #f + (begin + (set-if-y-edit-pos! i-f (+ (if-y-edit-pos i-f) + 1)) + (sync-if-edit-pos i-f))))) + +(define move-left + (lambda (i-f) + (if (begin-of-line? i-f) + #f + (begin + (set-if-x-edit-pos! i-f (- (if-x-edit-pos i-f) + 1)) + (sync-if-edit-pos i-f))))) + +(define move-right + (lambda (i-f) + (if (or (end-of-line? i-f) + (and (right-border? i-f) + (lower-border? i-f) + (not (if-y-scroll i-f)) + (not (if-x-scroll i-f)))) + #f + (begin + (set-if-x-edit-pos! i-f (+ (if-x-edit-pos i-f) + 1)) + (sync-if-edit-pos i-f))))) + +(define move-forward + (lambda (i-f) + (if (move-right i-f) + #t + (if (move-next-line i-f) + (goto-begin-of-line i-f) + #f)))) + +(define move-backward + (lambda (i-f) + (if (move-left i-f) + #t + (if (move-prev-line i-f) + (goto-end-of-line i-f) + #f)))) + +(define sync-if-edit-pos + (lambda (i-f) + (call-with-values + (lambda () + (edit-pos->if-pos i-f + (if-x-edit-pos i-f) + (if-y-edit-pos i-f))) + (lambda (x-pos y-pos) + (set-if-x-pos! i-f (- x-pos (if-x-offset i-f))) + (set-if-y-pos! i-f (- y-pos (if-y-offset i-f))))) + (legalize-position i-f) + (if (not (legal-offsets? i-f)) + (legalize-offsets i-f) + #t))) + +;; move END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; scroll + +(define scroll-up + (lambda (i-f) + (set-if-y-offset! i-f + (- (if-y-offset i-f) + 1)) + #t)) + +(define scroll-down + (lambda (i-f) + (set-if-y-offset! i-f + (+ (if-y-offset i-f) + 1)) + #t)) + +(define scroll-left + (lambda (i-f) + (set-if-x-offset! i-f + (- (if-x-offset i-f) + 1)) + #t)) + +(define scroll-right + (lambda (i-f) + (set-if-x-offset! i-f + (+ (if-x-offset i-f) + 1)) + #t)) +;; scroll END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; insert + +(define insert-char + (lambda (i-f char) + (let* ((y-edit-pos (if-y-edit-pos i-f)) + (edit-lines (if-edit-lines i-f)) + (current-line (list-ref edit-lines + y-edit-pos)) + (new-lines-tmp (string->edit-lines + (list->string + ((if (or (char=? char #\newline) + (if-insert-active i-f)) + insert + replace) + current-line + (if-x-edit-pos i-f) + char)))) + (new-lines (if (and (= (+ y-edit-pos 1) + (length edit-lines)) + (end-of-line? i-f) + (char=? char #\newline)) + (append new-lines-tmp '(())) + new-lines-tmp)) + (new-edit-lines (append (take edit-lines + y-edit-pos) + new-lines + (drop edit-lines + (+ y-edit-pos 1))))) + (if (or (if-y-scroll i-f) + (= (length (edit-lines->if-lines i-f new-lines)) + (length (edit-line->if-lines i-f current-line))) + (<= (length (edit-lines->if-lines i-f new-edit-lines)) + (if-y-dim i-f))) + (begin (set-if-edit-lines! i-f new-edit-lines) + (if (char=? char #\newline) + (begin (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f (+ (if-y-edit-pos i-f) + 1)) + (sync-if-edit-pos i-f)) + (move-right i-f)) + #t) + #f)))) + +;; insert END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; delete + +(define delete-right + (lambda (i-f) + (let* ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f)) + (edit-lines (if-edit-lines i-f)) + (current-line (list-ref edit-lines + y-edit-pos)) + (current-line-len (length current-line))) + (if (and (< x-edit-pos current-line-len) + (not (char=? (list-ref current-line + x-edit-pos) + #\newline))) + (let ((new-line (remove current-line + x-edit-pos))) + (set-if-edit-lines! i-f (replace edit-lines + y-edit-pos + new-line)) + #t) + #f)))) + +(define delete-left + (lambda (i-f) + (if (move-left i-f) + (delete-right i-f) + #f))) + +(define delete-all-left + (lambda (i-f) + (let* ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f)) + (edit-lines (if-edit-lines i-f)) + (current-line (list-ref edit-lines + y-edit-pos))) + (if (not (zero? x-edit-pos)) + (begin + (set-if-edit-lines! i-f (replace edit-lines + y-edit-pos + (drop current-line + x-edit-pos))) + (set-if-x-edit-pos! i-f 0) + (sync-if-edit-pos i-f) + #t) + #f)))) + +(define delete-all-right + (lambda (i-f) + (let* ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f)) + (edit-lines (if-edit-lines i-f)) + (current-line (list-ref edit-lines + y-edit-pos))) + (if (and (end-of-line? i-f) + (not (last-line? i-f))) + (begin + (set-if-edit-lines! i-f + (append (take edit-lines + y-edit-pos) + (list + (append + (reverse (cdr (reverse current-line))) + (list-ref edit-lines + (+ y-edit-pos 1)))) + (drop edit-lines + (+ y-edit-pos 2)))) + #t) + (begin + (set-if-edit-lines! i-f + (replace edit-lines + y-edit-pos + (let ((new-line (take current-line + x-edit-pos))) + (if (char=? (last current-line) + #\newline) + (append new-line + (list #\newline)) + new-line)))) + #t))))) + +(define delete-line + (lambda (i-f) + (let* ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f)) + (edit-lines (if-edit-lines i-f)) + (edit-lines-len (length edit-lines)) + (current-line (list-ref edit-lines + y-edit-pos))) + (if (= edit-lines-len 1) + (begin + (set-if-edit-lines! i-f '(())) + (set-if-x-edit-pos! i-f 0) + (sync-if-edit-pos i-f)) + (begin + (set-if-edit-lines! i-f (remove edit-lines + y-edit-pos)) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f (min y-edit-pos + (- edit-lines-len 2))) + (sync-if-edit-pos i-f)))))) + +;; delete END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; goto + +;; TODOO - fertig machen... (siehe #f) + +(define goto-begin-of-word-forward + (lambda (i-f) + (goto-next-forward i-f #\space #\newline) + (goto-next-not-forward i-f #\space #\newline) + #t)) + + +(define goto-end-of-word-forward + (lambda (i-f) + #f)) + + +(define goto-begin-of-word-backward + (lambda (i-f) + (if (and (goto-next-not-backward i-f #\space #\newline) + (goto-next-backward i-f #\space #\newline)) + (move-forward i-f)) + #t)) + +(define goto-end-of-word-backward + (lambda (i-f) + #f)) + +(define goto-begin-of-line + (lambda (i-f) + (set-if-x-edit-pos! i-f 0) + (sync-if-edit-pos i-f))) + +(define goto-end-of-line + (lambda (i-f) + (let ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f))) + (call-with-values + (lambda () + (let* ((current-line (list-ref (if-edit-lines i-f) + y-edit-pos))) + (if (null? current-line) + (set-if-x-edit-pos! i-f 0) + (let ((len (length current-line)) + (end-char (last current-line))) + (set-if-x-edit-pos! i-f (if (char=? end-char #\newline) + (- len 1) + len)))) + (edit-pos->if-pos i-f + (if-x-edit-pos i-f) + y-edit-pos))) + (lambda (x-pos y-pos) + (set-if-x-pos! i-f (- x-pos (if-x-offset i-f))) + (set-if-y-pos! i-f (- y-pos (if-y-offset i-f))) + (sync-if-edit-pos i-f)))))) + +(define goto-begin-of-first-line + (lambda (i-f) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f 0) + (sync-if-edit-pos i-f))) + +(define goto-end-of-first-line + (lambda (i-f) + #f)) + +(define goto-begin-of-last-line + (lambda (i-f) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f (- (length (if-edit-lines i-f)) + 1)) + (sync-if-edit-pos i-f))) + +(define goto-end-of-last-line + (lambda (i-f) + #f)) + +;; ------------------------------------------------------------------ +; wozu eigentlich? +;(define goto-end-of-if-line +; (lambda (i-f) +; #f)) + +;; ------------------------------------------------------------------ + +(define goto-next-forward + (lambda (i-f . chars) + (if (move-forward i-f) + (let loop () + (let ((sign (sign-under-cursor i-f))) + (if (and sign + (memq sign chars)) + #t + (if (move-forward i-f) + (loop) + #f)))) + #f))) + +(define goto-next-not-forward + (lambda (i-f . chars) + (if (move-forward i-f) + (let loop () + (let ((sign (sign-under-cursor i-f))) + (if (and sign + (not (memq sign chars))) + #t + (if (move-forward i-f) + (loop) + #f)))) + #f))) + +(define goto-next-backward + (lambda (i-f . chars) + (if (move-backward i-f) + (let loop () + (let ((sign (sign-under-cursor i-f))) + (if (and sign + (memq sign chars)) + #t + (if (move-backward i-f) + (loop) + #f)))) + #f))) + +(define goto-next-not-backward + (lambda (i-f . chars) + (if (move-backward i-f) + (let loop () + (let ((sign (sign-under-cursor i-f))) + (if (and sign + (not (memq sign chars))) + #t + (if (move-backward i-f) + (loop) + #f)))) + #f))) + +;; goto END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; others +(define toggle-insert + (lambda (i-f) + (set-if-insert-active! i-f + (not (if-insert-active i-f))) + (values #t #f))) +;; others END +;; ---------------------------------------------------------------------------- + +;; behavior methods END +;;=============================================================================== + +;;=============================================================================== +;; "mutate" functions and few others + +(define input-field-refresh + (lambda (i-f) + (really-send-input-field i-f 'refresh-all))) + +;(define input-field-move-up +; (lambda (i-f) +; (let ((y-loc (if-y-loc i-f))) +; (if (> y-loc 1) +; (begin +; (paint-black i-f) +; (set-if-y-loc! i-f (- y-loc +; 1)) +; #t) +; #f)))) + +;(define input-field-move-down +; (lambda (i-f) +; (let ((y-loc (if-y-loc i-f))) +; (if (< (+ y-loc (if-y-dim i-f)) +; (- (getmaxy (if-window i-f)) +; 1)) +; (begin +; (paint-black i-f) +; (set-if-y-loc! i-f (+ y-loc +; 1)) +; #t) +; #f)))) + +;(define input-field-move-left +; (lambda (i-f) +; (let ((x-loc (if-x-loc i-f))) +; (if (> x-loc 1) +; (begin +; (paint-black i-f) +; (set-if-x-loc! i-f (- x-loc +; 1)) +; #t) +; #f)))) + +;(define input-field-move-right +; (lambda (i-f) +; (let ((x-loc (if-x-loc i-f))) +; (if (< (+ x-loc (if-x-dim i-f)) +; (- (getmaxx (if-window i-f)) +; 1)) +; (begin +; (paint-black i-f) +; (set-if-x-loc! i-f (+ x-loc +; 1)) +; #t) +; #f)))) + +(define input-field-move + (lambda (i-f x y) + (let ((win (if-window i-f))) + (if (and (> x 1) + (> y 1) + (< (+ x (if-x-dim i-f)) + (getmaxx win)) + (< (+ y (if-y-dim i-f)) + (getmaxy win))) + (begin + (paint-black i-f) + (set-if-x-loc! i-f x) + (set-if-y-loc! i-f y) + (refresh-all i-f)) + #f)))) + +(define input-field-resize + (lambda (i-f x y) + (let ((win (if-window i-f))) + (if (and (> x 0) + (> y 0) + (< (+ x (if-x-loc i-f)) + (getmaxx win)) + (< (+ y (if-y-loc i-f)) + (getmaxy win))) + (begin + (paint-black i-f) + (set-if-x-offset! i-f 0) + (set-if-y-offset! i-f 0) + (set-if-x-pos! i-f 0) + (set-if-y-pos! i-f 0) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f 0) + (set-if-x-dim! i-f x) + (set-if-y-dim! i-f y) + (set-if-edit-lines! i-f + (string->if-edit-lines i-f + (input-field-text i-f))) + (refresh-all i-f)) + #f)))) + +(define input-field-toggle-x-scroll + (lambda (i-f) + (paint-black i-f) + (set-if-x-offset! i-f 0) + (set-if-y-offset! i-f 0) + (set-if-x-pos! i-f 0) + (set-if-y-pos! i-f 0) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f 0) + (set-if-x-scroll! i-f (not (if-x-scroll i-f))) + (set-if-edit-lines! i-f + (string->if-edit-lines i-f + (input-field-text i-f))) + (refresh-all i-f))) + +(define input-field-toggle-y-scroll + (lambda (i-f) + (paint-black i-f) + (set-if-x-offset! i-f 0) + (set-if-y-offset! i-f 0) + (set-if-x-pos! i-f 0) + (set-if-y-pos! i-f 0) + (set-if-x-edit-pos! i-f 0) + (set-if-y-edit-pos! i-f 0) + (set-if-y-scroll! i-f (not (if-y-scroll i-f))) + (set-if-edit-lines! i-f + (string->if-edit-lines i-f + (input-field-text i-f))) + (refresh-all i-f))) + +(define restore-input-field + (lambda (i-f) + (set-if-edit-lines! i-f + (string->if-edit-lines i-f + (input-field-text i-f))) + (sync-if-edit-pos i-f) + (refresh-all i-f))) + +;; mutate-functions END +;;=============================================================================== + + +;;=============================================================================== +;; helpfunctions (converter, predicates...) + + +(define string->edit-lines + (lambda (str) + (let loop ((chars (string->list str))) + (if (null? chars) + '() + (call-with-values + (lambda () + (split-after-first-newline chars)) + (lambda (line chars) + (cons line + (loop chars)))))))) + +(define string->edit-lines-with-null + (lambda (str) + (let* ((edit-lines (let loop ((chars (string->list str))) + (if (null? chars) + '() + (call-with-values + (lambda () + (split-after-first-newline chars)) + (lambda (line chars) + (cons line + (loop chars))))))) + (last-line (if (null? edit-lines) + #f + (last edit-lines)))) + (if (and last-line + (not (null? last-line)) + (char=? (last last-line) + #\newline)) + (append edit-lines '(())) + edit-lines)))) + +(define split-after-first-newline + (lambda (chars) + (let loop ((line '()) + (chars chars)) + (if (null? chars) + (values (reverse line) chars) + (let ((char (car chars)) + (rest (cdr chars))) + (if (char=? char #\newline) + (values (reverse (cons char line)) + rest) + (loop (cons char line) + rest))))))) + +(define edit-line->if-lines + (lambda (i-f edit-line) + (let ((x-dim (if-x-dim i-f)) + (x-scroll (if-x-scroll i-f))) + (if (or x-scroll + (null? edit-line)) + (list edit-line) + (let loop ((edit-line edit-line)) + (if (null? edit-line) + '() + (call-with-values + (lambda () + (split-if-line-from-edit-line x-dim edit-line)) + (lambda (if-line edit-line) + (cons if-line + (loop edit-line)))))))))) + +(define edit-lines->if-lines + (lambda (i-f edit-lines) + (cat (map (lambda (edit-line) + (edit-line->if-lines i-f edit-line)) + edit-lines)))) + +(define split-if-line-from-edit-line + (lambda (x-dim edit-line) + (let loop ((if-line '()) + (rest edit-line) + (space-left x-dim)) + (if (null? rest) + (values (reverse if-line) + rest) + (let ((char (car rest))) + (cond ((char=? char #\newline) + (values (reverse (cons char + if-line)) + (cdr rest))) + ((zero? space-left) + (values (reverse if-line) + rest)) + (else + (loop (cons char if-line) + (cdr rest) + (- space-left 1))))))))) + +(define if-lines->edit-lines + (lambda (if-lines) + (let loop ((rest if-lines)) + (if (null? rest) + '() + (call-with-values + (lambda () + (split-edit-line-from-if-lines rest)) + (lambda (edit-line rest) + (cons edit-line + (loop rest)))))))) + +(define split-edit-line-from-if-lines + (lambda (if-lines) + (let loop ((edit-line '()) + (rest if-lines)) + (if (null? rest) + (values (reverse edit-line) '()) + (let ((rev-line (reverse (car rest)))) + (if (null? rev-line) + (values '() (cdr rest)) + (if (char=? (car rev-line) + #\newline) + (values (reverse (append rev-line + edit-line)) + (cdr rest)) + (loop (append rev-line + edit-line) + (cdr rest))))))))) + +(define string->if-edit-lines + (lambda (i-f string) + (let* ((edit-lines (string->edit-lines-with-null string)) + (if-lines (edit-lines->if-lines i-f edit-lines)) + (if-lines-cut (if (if-y-scroll i-f) + if-lines + (take if-lines + (if-y-dim i-f))))) + (if-lines->edit-lines if-lines-cut)))) + +(define if->edit-pos + (lambda (i-f) + (let ((x-pos (+ (if-x-offset i-f) + (if-x-pos i-f))) + (y-pos (+ (if-y-offset i-f) + (if-y-pos i-f))) + (x-scroll (if-x-scroll i-f))) + (if x-scroll + (values x-pos y-pos) + (let loop ((edit-lines (if-edit-lines i-f)) + (y-edit-pos 0) + (y-pos y-pos)) + (if (null? edit-lines) + (let ((y-edit-pos (- y-edit-pos 1))) + (values (length (list-ref (if-edit-lines i-f) + y-edit-pos)) + y-edit-pos)) + (let* ((edit-line (car edit-lines)) + (num-if-lines (length + (edit-line->if-lines i-f edit-line)))) + (if (< y-pos num-if-lines) + (values (+ (* y-pos + (if-x-dim i-f)) + x-pos) + y-edit-pos) + (loop (cdr edit-lines) + (+ y-edit-pos 1) + (- y-pos num-if-lines)))))))))) + +(define edit-pos->if-pos + (lambda (i-f x-edit-pos y-edit-pos) + (if (if-x-scroll i-f) + (values x-edit-pos y-edit-pos) + (let loop ((edit-lines (if-edit-lines i-f)) + (y-edit-pos y-edit-pos) + (y-pos 0)) + (if (null? edit-lines) + 'error--edit-pos->if-pos + (if (zero? y-edit-pos) + (let ((x-dim (if-x-dim i-f))) + (values (modulo x-edit-pos + x-dim) + (+ y-pos + (quotient x-edit-pos + x-dim)))) + (loop (cdr edit-lines) + (- y-edit-pos 1) + (+ y-pos + (length + (edit-line->if-lines i-f + (car edit-lines))))))))))) + +;; ---------------------------------------------------------------------------- +;; legalize-position +(define legalize-position + (lambda (i-f) + (let* ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f)) + (current-line (list-ref (if-edit-lines i-f) + y-edit-pos)) + (current-line-len (length current-line))) + (if (or (> x-edit-pos current-line-len) + (and (> current-line-len 0) + (= x-edit-pos current-line-len) + (char=? (last current-line) + #\newline))) + (goto-end-of-line i-f))) + #t)) + +(define legal-offsets? + (lambda (i-f) + (let ((x (if-x-pos i-f)) + (y (if-y-pos i-f))) + (and (>= x 0) + (< x (if-x-dim i-f)) + (>= y 0) + (< y (if-y-dim i-f)))))) + + +(define legalize-offsets + (lambda (i-f) + (let ((x-pos (if-x-pos i-f)) + (x-offset (if-x-offset i-f)) + (x-dim (if-x-dim i-f)) + (y-pos (if-y-pos i-f)) + (y-offset (if-y-offset i-f)) + (y-dim (if-y-dim i-f))) + (if (< x-pos 0) + (begin + (set! x-offset (+ x-offset x-pos)) + (set! x-pos 0))) + (if (> (+ x-pos 1) + x-dim) + (let ((dx (- (+ x-pos 1) + x-dim))) + (set! x-offset (+ x-offset dx)) + (set! x-pos (- x-pos dx)))) + (if (< y-pos 0) + (begin + (set! y-offset (+ y-offset y-pos)) + (set! y-pos 0))) + (if (> (+ y-pos 1) + y-dim) + (let ((dy (- (+ y-pos 1) + y-dim))) + (set! y-offset (+ y-offset dy)) + (set! y-pos (- y-pos dy)))) + (set-if-x-pos! i-f x-pos) + (set-if-x-offset! i-f x-offset) + (set-if-y-pos! i-f y-pos) + (set-if-y-offset! i-f y-offset) + #t))) +;; legalize-position END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; predicates + +(define first-line? + (lambda (i-f) + (zero? (if-y-edit-pos i-f)))) + +(define last-line? + (lambda (i-f) + (= (+ (if-y-edit-pos i-f) + 1) + (length (if-edit-lines i-f))))) + +(define begin-of-line? + (lambda (i-f) + (zero? (if-x-edit-pos i-f)))) + +(define end-of-line? + (lambda (i-f) + (let* ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f)) + (edit-line (list-ref (if-edit-lines i-f) + y-edit-pos))) + (or (= x-edit-pos + (length edit-line)) + (char=? (list-ref edit-line + x-edit-pos) + #\newline))))) + +(define left-border? + (lambda (i-f) + (= (if-x-pos i-f) + 0))) + +(define right-border? + (lambda (i-f) + (= (if-x-pos i-f) + (- (if-x-dim i-f) 1)))) + +(define lower-border? + (lambda (i-f) + (= (if-y-pos i-f) + (- (if-y-dim i-f) 1)))) + +(define upper-border? + (lambda (i-f) + (= (if-y-pos i-f) + 0))) +;; predicates END +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; selectors +(define sign-at-xy + (lambda (i-f x y) + #f)) + +(define sign-under-cursor + (lambda (i-f) + (let* ((x-edit-pos (if-x-edit-pos i-f)) + (y-edit-pos (if-y-edit-pos i-f)) + (current-line (list-ref (if-edit-lines i-f) + y-edit-pos)) + (current-line-len (length current-line))) + (if (< x-edit-pos current-line-len) + (list-ref current-line x-edit-pos) + #f)))) + +(define sign-before-cursor + (lambda (i-f) + #f)) + +(define sign-behind-cursor + (lambda (i-f) + #f)) + +;; selectors END +;; ---------------------------------------------------------------------------- +;; helpfunctions END +;;=============================================================================== + +;;=============================================================================== +;; "primitives" + +(define caddddr + (lambda (x) + (car (cddddr x)))) + +(define last + (lambda (lst) + (if (null? lst) + 'error--last + (car (reverse lst))))) + +(define fill-up + (lambda (lst len elem) + (append lst + (let loop ((n (- len + (length lst)))) + (if (< n 0) + 'error--fill-up + (if (zero? n) + '() + (cons elem + (loop (- n 1))))))))) + +(define cat + (lambda (lst-lst) + (if (null? lst-lst) + '() + (append (car lst-lst) + (cat (cdr lst-lst)))))) + +(define split + (lambda (lst n) + (let loop ((fst '()) + (scnd lst) + (n n)) + (if (or (null? scnd) + (zero? n)) + (values (reverse fst) scnd) + (loop (cons (car scnd) + fst) + (cdr scnd) + (- n 1)))))) + +(define remove + (lambda (lst pos) + (append (take lst pos) + (drop lst (+ pos 1))))) + +(define insert + (lambda (lst n elem) + (if (zero? n) + (cons elem lst) + (cons (car lst) + (insert (cdr lst) + (- n 1) + elem))))) + +(define replace + (lambda (lst n elem) + (if (zero? n) + (cons elem + (if (null? lst) + lst + (cdr lst))) + (cons (car lst) + (replace (cdr lst) + (- n 1) + elem))))) + +(define take + (lambda (lst n) + (if (or (null? lst) + (zero? n)) + '() + (cons (car lst) + (take (cdr lst) + (- n 1)))))) + +(define drop + (lambda (lst n) + (if (or (null? lst) + (zero? n)) + lst + (drop (cdr lst) + (- n 1))))) + + +;; "primitives" END +;;===============================================================================