guile-pstk

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 9c7e54371502090b6135dd988ff14a92c7024ded
Author: KikyTokamuro <kiky.tokamuro@yandex.ru>
Date:   Wed,  1 Dec 2021 19:50:33 +0300

Added PS/TK with modern GNU Guile changes

Diffstat:
Apstk.scm | 855+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 855 insertions(+), 0 deletions(-)

diff --git a/pstk.scm b/pstk.scm @@ -0,0 +1,855 @@ +; PS/Tk -- A Portable Scheme Interface to the Tk GUI Toolkit +; Copyright (C) 2021 Daniil Archangelsky aka Kiky Tokamuro +; Copyright (C) 2008 Kenneth A Dickey +; Copyright (C) 2006-2008 Nils M Holm +; Copyright (C) 2004 Wolf-Dieter Busch +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; PS/Tk is based on Chicken/Tk by Wolf-Dieter Busch (2004): +; http://wolf-dieter-busch.de/html/Software/Tools/ChickenTk.htm +; which is in turn based on Scheme_wish by Sven Hartrumpf (1997, 1998): +; http://pi7.fernuni-hagen.de/hartrumpf/scheme_wish.scm +; +; These are the changes that I (Nils) made to turn Chicken/Tk into PS/Tk: +; +; - Removed all Chicken-isms except for PROCESS. +; - All PS/Tk function names begin with TK/ or TK-: +; EVAL-WISH --> TK-EVAL-WISH +; GET-TK-VAR --> TK-GET-VAR +; SET-TK-VAR! --> TK-SET-VAR! +; START-TK --> TK-START +; END-TK --> TK-END +; EVENT-LOOP --> TK-EVENT-LOOP +; - Added TK-DISPATCH-EVENT. +; - Added TK-WAIT-FOR-WINDOW because TK/WAIT returned too early. +; - Removed some unused functions and variables. +; - Replaced keyword lists with property lists. +; - Removed ScrolledText compound widget. +; - Removed :WIDGET-NAME option. +; - Added a PLT Scheme version of RUN-PROGRAM. +; +; Contributions (in order of appearance): +; - Jens Axel Soegaard: PLT Scheme/Windows RUN-PROGRAM. +; - Taylor R Campbell: Scheme48 RUN-PROGRAM, portable GENSYM, and some R5RS +; portability fixes. +; - Jeffrey T. Read: Gambit hacks (RUN-PROGRAM, keyword hack). +; - Marc Feeley: Various versions of RUN-PROGRAM (Bigloo, Gauche, Guile, +; Kawa, Scsh, Stklos), SRFI-88 keyword auto-detection, some bug fixes. +; - David St-Hilaire: suggested catching unspecific value in form->string. +; - Ken Dickey: added Ikarus Scheme +; - Ken Dickey: added Larceny Scheme +; Thank you! +; +; Change Log: +; 2021-12-01 Deleted all non Guile sections. +; Changed "set-batch-mode?!" to "ensure-batch-mode!". +; Deleted the "bottom" function call. +; 2008-06-22 Added Larceny Scheme support. +; 2008-02-29 Added R6RS (Ikarus Scheme) support, added TTK/STYLE. +; 2007-06-27 Renamed source file to pstk.scm. +; 2007-06-27 Re-factored some large procedures, applied some cosmetics. +; 2007-06-26 FORM->STRING catches unspecific values now, so event handlers +; no longer have to return specific values. +; 2007-06-26 Re-imported the following ports from the processio/v1 snowball: +; Bigloo, Gauche, Guile, Kawa, Scsh, Stklos. +; 2007-06-26 Added auto-detection of SRFI-88 keywords. +; 2007-03-03 Removed callback mutex, because it blocked some redraw +; operations. Use TK-WITH-LOCK to protect critical sections. +; 2007-02-03 Added Tile support: TTK-MAP-WIDGETS, TTK/AVAILABLE-THEMES, +; TTK/SET-THEME. +; 2007-01-20 Added (Petite) Chez Scheme port. +; 2007-01-06 Fix: TK-WAIT-FOR-WINDOW requires nested callbacks. +; 2007-01-05 Added code to patch through fatal TCL messages. +; 2007-01-05 Protected call-backs by a mutex, so accidental double +; clicks, etc cannot mess up program state. +; 2006-12-21 Made FORM->STRING accept '(). +; 2006-12-18 Installing WM_DELETE_WINDOW handler in TK-START now, so it does +; not get reset in TK-EVENT-LOOP. +; 2006-12-18 Made TK-START and TK-END return () instead of #<unspecific> +; (which crashes FORM->STRING). +; 2006-12-12 Fixed some wrong Tcl quotation (introduced by myself). +; 2006-12-09 Added TK/BELL procedure. +; 2006-12-08 Replaced ATOM->STRING by FORM->STRING. +; 2006-12-06 Added TK-WAIT-UNTIL-VISIBLE. +; 2006-12-03 Made more variables local to outer LETREC. +; 2006-12-03 Added Gambit port and keywords hack. +; 2006-12-02 Added Scheme 48 port, portable GENSYM, R5RS fixes. +; 2006-12-02 Added PLT/Windows port. + +(use-modules (srfi srfi-88)) + +(define *wish-program* "tclsh") +(define *wish-debug-input* #f) +(define *wish-debug-output* #f) + +(define *use-keywords?* + (or (not (symbol? 'text:)) + (not (symbol? ':text)) + (string=? "text" (symbol->string 'text:)) + (string=? "text" (symbol->string ':text)))) + +(define tk #f) +(define tk-dispatch-event #f) +(define tk-end #f) +(define tk-eval #f) +(define tk-event-loop #f) +(define tk-get-var #f) +(define tk-id->widget #f) +(define tk-set-var! #f) +(define tk-start #f) +(define tk-var #f) +(define tk-wait-for-window #f) +(define tk-wait-until-visible #f) +(define tk-with-lock #f) +(define tk/after #f) +(define tk/appname #f) +(define tk/bell #f) +(define tk/bgerror #f) +(define tk/bind #f) +(define tk/bindtags #f) +(define tk/caret #f) +(define tk/choose-color #f) +(define tk/choose-directory #f) +(define tk/clipboard #f) +(define tk/destroy #f) +(define tk/dialog #f) +(define tk/event #f) +(define tk/focus #f) +(define tk/focus-follows-mouse #f) +(define tk/focus-next #f) +(define tk/focus-prev #f) +(define tk/get-open-file #f) +(define tk/get-save-file #f) +(define tk/grab #f) +(define tk/grid #f) +(define tk/image #f) +(define tk/lower #f) +(define tk/message-box #f) +(define tk/option #f) +(define tk/pack #f) +(define tk/place #f) +(define tk/popup #f) +(define tk/raise #f) +(define tk/scaling #f) +(define tk/selection #f) +(define tk/update #f) +(define tk/useinputmethods #f) +(define tk/wait #f) +(define tk/windowingsystem #f) +(define tk/winfo #f) +(define tk/wm #f) +(define ttk-map-widgets #f) +(define ttk/available-themes #f) +(define ttk/set-theme #f) +(define ttk/style #f) + +(letrec + ((nl (string #\newline)) + (wish-input #f) + (wish-output #f) + (tk-is-running #f) + (tk-ids+widgets '()) + (tk-widgets '()) + (commands-invoked-by-tk '()) + (inverse-commands-invoked-by-tk '()) + (in-callback #f) + (callback-mutex #t) + (ttk-widget-map '()) + (tk-init-string + (apply string-append + (apply append + (map (lambda (s) + (list s (string #\newline))) + '("package require Tk" + "if {[package version tile] != \"\"} {" + " package require tile" + "}" + "" + "namespace eval AutoName {" + " variable c 0" + " proc autoName {{result \\#\\#}} {" + " variable c" + " append result [incr c]" + " }" + " namespace export *" + "}" + "" + "namespace import AutoName::*" + "" + "proc callToScm {callKey args} {" + " global scmVar" + " set resultKey [autoName]" + " puts \"(call $callKey \\\"$resultKey\\\" $args)\"" + " flush stdout" + " vwait scmVar($resultKey)" + " set result $scmVar($resultKey)" + " unset scmVar($resultKey)" + " set result" + "}" + "" + "proc tclListToScmList {l} {" + " switch [llength $l] {" + " 0 {" + " return ()" + " }" + " 1 {" + " if {[string range $l 0 0] eq \"\\#\"} {" + " return $l" + " }" + " if {[regexp {^[0-9]+$} $l]} {" + " return $l" + " }" + " if {[regexp {^[.[:alpha:]][^ ,\\\"\\'\\[\\]\\\\;]*$} $l]} {" + " return $l" + " }" + " set result \\\"" + " append result\\" + " [string map [list \\\" \\\\\\\" \\\\ \\\\\\\\] $l]" + " append result \\\"" + "" + " }" + " default {" + " set result {}" + " foreach el $l {" + " append result \" \" [tclListToScmList $el]" + " }" + " set result [string range $result 1 end]" + " return \"($result)\"" + " }" + " }" + "}" + "" + "proc evalCmdFromScm {cmd {properly 0}} {" + " if {[catch {" + " set result [uplevel \\#0 $cmd]" + " } err]} {" + " puts \"(error \\\"[string map [list \\\\ \\\\\\\\ \\\" \\\\\\\"] $err]\\\")\"" + " } elseif $properly {" + " puts \"(return [tclListToScmList $result])\"" + " } else {" + " puts \"(return \\\"[string map [list \\\\ \\\\\\\\ \\\" \\\\\\\"] $result]\\\")\"" + " }" + " flush stdout" + "}"))))) + + (report-error + (lambda (x) + (newline) + (display x) + (newline))) + + (run-program + (lambda (program) + (letrec + ((open-i/o-process + (lambda (prog . args) + (let ((c2p (pipe)) + (p2c (pipe))) + (setvbuf (cdr c2p) _IONBF) + (setvbuf (cdr p2c) _IONBF) + (let ((pid (primitive-fork))) + (cond ((= pid 0) + (ensure-batch-mode!) + (let ((input-fdes (fileno (car p2c))) + (output-fdes (fileno (cdr c2p)))) + (port-for-each + (lambda (pt-entry) + (false-if-exception + (let ((pt-fileno (fileno pt-entry))) + (if (not (or (= pt-fileno input-fdes) + (= pt-fileno output-fdes))) + (close-fdes pt-fileno)))))) + (cond ((not (= input-fdes 0)) + (if (= output-fdes 0) + (set! output-fdes (dup->fdes 0))) + (dup2 input-fdes 0))) + (if (not (= output-fdes 1)) + (dup2 output-fdes 1)) + (apply execlp prog prog args))) + (else + (close-port (cdr c2p)) + (close-port (car p2c)) + (cons (car c2p) + (cdr p2c))))))))) + (let* ((in/out + (open-i/o-process "/bin/sh" "-c" + (string-append "exec " program))) + (in (car in/out)) + (out (cdr in/out))) + (list in out))))) + + (flush-output-port force-output) + + (flush-wish + (lambda () + (flush-output-port wish-input))) + + (option? + (lambda (x) + (or (and *use-keywords?* + (keyword? x)) + (and (symbol? x) + (let* ((s (symbol->string x)) + (n (string-length s))) + (char=? #\: (string-ref s (- n 1)))))))) + + (make-option-string + (lambda (x) + (if (and *use-keywords?* + (keyword? x)) + (string-append " -" (keyword->string x)) + (let ((s (symbol->string x))) + (string-append " -" + (substring s 0 (- (string-length s) 1))))))) + + (improper-list->string + (lambda (a first) + (cond ((pair? a) + (cons (string-append (if first "" " ") + (form->string (car a))) + (improper-list->string (cdr a) #f))) + ((null? a) '()) + (else (list (string-append " . " (form->string a))))))) + + (form->string + (lambda (x) + (cond ((eq? #t x) "#t") + ((eq? #f x) "#f") + ((number? x) (number->string x)) + ((symbol? x) (symbol->string x)) + ((string? x) x) + ((null? x) "()") + ((pair? x) + (string-append "(" + (apply string-append + (improper-list->string x #t)) + ")")) + ((eof-object? x) "#<eof>") + (else "#<other>")))) + + (string-translate + (lambda (s map) + (letrec + ((s-prepend (lambda (s1 s2) + (cond ((null? s1) s2) + (else (s-prepend (cdr s1) (cons (car s1) s2)))))) + (s-xlate (lambda (s r) + (cond ((null? s) (reverse r)) + (else (let ((n (assv (car s) map))) + (cond (n (s-xlate (cdr s) + (s-prepend (string->list (cdr n)) r))) + (else (s-xlate (cdr s) + (cons (car s) r)))))))))) + (list->string + (s-xlate (string->list s) '()))))) + + (string-trim-left + (lambda (str) + (cond ((string=? str "") "") + ((string=? (substring str 0 1) " ") + (string-trim-left (substring str 1 + (string-length str)))) + (else str)))) + + (get-property + (lambda (key args . thunk) + (cond ((null? args) + (cond ((null? thunk) #f) + (else ((car thunk))))) + ((eq? key (car args)) + (cond ((pair? (cdr args)) (cadr args)) + (else (report-error (list 'get-property key args))))) + ((or (not (pair? (cdr args))) + (not (pair? (cddr args)))) + (report-error (list 'get-property key args))) + (else (apply get-property key (cddr args) thunk))))) + + (tcl-true? + (let ((false-values + `(0 "0" 'false "false" ,(string->symbol "0")))) + (lambda (obj) (not (memv obj false-values))))) + + (widget? + (lambda (x) + (and (memq x tk-widgets) #t))) + + (call-by-key + (lambda (key resultvar . args) + (cond ((and in-callback (pair? callback-mutex)) #f) + (else (set! in-callback (cons #t in-callback)) + (let* ((cmd (get-property key commands-invoked-by-tk)) + (result (apply cmd args)) + (str (string-trim-left + (scheme-arglist->tk-argstring + (list result))))) + (set-var! resultvar str) + (set! in-callback (cdr in-callback)) + result))))) + + (gen-symbol + (let ((counter 0)) + (lambda () + (let ((sym (string-append "g" (number->string counter)))) + (set! counter (+ counter 1)) + (string->symbol sym))))) + + (widget-name + (lambda (x) + (let ((name (form->string x))) + (cond ((member name ttk-widget-map) + (string-append "ttk::" name)) + (else name))))) + + (make-widget-by-id + (lambda (type id . options) + (let + ((result + (lambda (command . args) + (case command + ((get-id) id) + ((create-widget) + (let* ((widget-type (widget-name (car args))) + (id-prefix (if (string=? id ".") "" id)) + (id-suffix (form->string (gen-symbol))) + (new-id (string-append id-prefix "." id-suffix)) + (options (cdr args))) + (eval-wish + (string-append + widget-type + " " + new-id + (scheme-arglist->tk-argstring options))) + (apply make-widget-by-id + (append (list widget-type new-id) + options)))) + ((configure) + (cond ((null? args) + (eval-wish + (string-append id " " (form->string command)))) + ((null? (cdr args)) + (eval-wish + (string-append + id + " " + (form->string command) + (scheme-arglist->tk-argstring args)))) + (else + (eval-wish + (string-append + id + " " + (form->string command) + (scheme-arglist->tk-argstring args))) + (do ((args args (cddr args))) + ((null? args) '()) + (let ((key (car args)) (val (cadr args))) + (cond ((null? options) + (set! options (list key val))) + ((not (memq key options)) + (set! options + (cons key (cons val options)))) + (else (set-car! (cdr (memq key options)) + val)))))))) + ((cget) + (let ((key (car args))) + (get-property + key + options + (lambda () + (eval-wish + (string-append + id + " cget" + (scheme-arglist->tk-argstring args))))))) + ((call exec) + (eval-wish + (string-trim-left + (scheme-arglist->tk-argstring args)))) + (else + (eval-wish + (string-append + id + " " + (form->string command) + (scheme-arglist->tk-argstring args)))))))) + (set! tk-widgets (cons result tk-widgets)) + (set! tk-ids+widgets + (cons (string->symbol id) + (cons result tk-ids+widgets))) + result))) + + (scheme-arg->tk-arg + (lambda (x) + (cond ((eq? x #f) " 0") + ((eq? x #t) " 1") + ((eq? x '()) " {}") + ((option? x) (make-option-string x)) + ((widget? x) (string-append " " (x 'get-id))) + ((and (pair? x) (procedure? (car x))) + (let* ((lambda-term (car x)) + (rest (cdr x)) + (l (memq lambda-term + inverse-commands-invoked-by-tk)) + (keystr (if l (form->string (cadr l)) + (symbol->string (gen-symbol))))) + (if (not l) + (let ((key (string->symbol keystr))) + (set! inverse-commands-invoked-by-tk + (cons lambda-term + (cons key + inverse-commands-invoked-by-tk))) + (set! commands-invoked-by-tk + (cons key + (cons lambda-term + commands-invoked-by-tk))))) + (string-append " {callToScm " + keystr + (scheme-arglist->tk-argstring rest) + "}"))) + ((procedure? x) + (scheme-arglist->tk-argstring `((,x)))) + ((list? x) + (cond ((eq? (car x) '+) + (let ((result (string-trim-left + (scheme-arglist->tk-argstring + (cdr x))))) + (cond ((string=? result "") " +") + ((string=? "{" (substring result 0 1)) + (string-append + " {+ " + (substring result 1 + (string-length result)))) + (else (string-append " +" result))))) + ((and (= (length x) 3) + (equal? (car x) (string->symbol "@")) + (number? (cadr x)) + (number? (caddr x))) + (string-append + "@" + (number->string (cadr x)) + "," + (number->string (caddr x)))) + (else + (string-append + " {" + (string-trim-left + (scheme-arglist->tk-argstring x)) + "}")))) + ((pair? x) + (string-append + " " + (form->string (car x)) + "." + (form->string (cdr x)))) + ((string? x) + (if (string->number x) + (string-append " " x) + (string-append + " \"" + (string-translate x + '((#\\ . "\\\\") (#\" . "\\\"") + (#\[ . "\\u005b") (#\] . "\\]") + (#\$ . "\\u0024") + (#\{ . "\\{") (#\} . "\\}"))) + "\""))) + (else (string-append " " (form->string x)))))) + + (scheme-arglist->tk-argstring + (lambda (args) + (apply string-append + (map scheme-arg->tk-arg + args)))) + + (make-wish-func + (lambda (tkname) + (let ((name (form->string tkname))) + (lambda args + (eval-wish + (string-append + name + (scheme-arglist->tk-argstring args))))))) + + (read-wish + (lambda () + (let ((term (read wish-output))) + (cond (*wish-debug-output* + (display "wish->scheme: ") + (write term) + (newline))) + term))) + + (wish + (lambda arguments + (for-each + (lambda (argument) + (cond (*wish-debug-input* + (display "scheme->wish: ") + (display argument) + (newline))) + (display argument wish-input) + (newline wish-input) + (flush-wish)) + arguments))) + + (start-wish + (lambda () + (let ((result (run-program *wish-program*))) + (set! wish-input (cadr result)) + (set! wish-output (car result))))) + + (read-line + (lambda (in) + (letrec + ((collect-chars + (lambda (c s) + (cond ((or (eof-object? c) (char=? c #\newline)) + (apply string (reverse s))) + (else (collect-chars (read-char in) (cons c s)))))) + (first-char + (read-char in))) + (cond ((eof-object? first-char) first-char) + (else (collect-chars first-char '())))))) + + (eval-wish + (lambda (cmd) + (wish (string-append + "evalCmdFromScm \"" + (string-translate cmd + '((#\\ . "\\\\") (#\" . "\\\""))) + "\"")) + (let again ((result (read-wish))) + (cond ((not (pair? result)) + (report-error (string-append + "An error occurred inside Tcl/Tk" nl + " --> " (form->string result) + " " (read-line wish-output)))) + ((eq? (car result) 'return) + (cadr result)) + ((eq? (car result) 'call) + (apply call-by-key (cdr result)) + (again (read-wish))) + ((eq? (car result) 'error) + (report-error (string-append + "An error occurred inside Tcl/Tk" nl + " " cmd nl + " --> " (cadr result)))) + (else (report-error result)))))) + + (id->widget + (lambda (id) + (get-property + (string->symbol (form->string id)) + tk-ids+widgets + (lambda () + (if (tcl-true? (tk/winfo 'exists id)) + (make-widget-by-id + (tk/winfo 'class id) + (form->string id)) + #f))))) + + (var + (lambda (varname) + (set-var! varname "") + (string-append + "::scmVar(" + (form->string varname) + ")"))) + + (get-var + (lambda (varname) + (eval-wish + (string-append + "set ::scmVar(" + (form->string varname) + ")")))) + + (set-var! + (lambda (varname value) + (eval-wish + (string-append + "set ::scmVar(" + (form->string varname) + ") {" + (form->string value) + "}")))) + + (start + (lambda () + (start-wish) + (wish tk-init-string) + (set! tk-ids+widgets '()) + (set! tk-widgets '()) + (set! in-callback #f) + (set! tk (make-widget-by-id 'toplevel "." 'class: 'Wish)) + (set! commands-invoked-by-tk '()) + (set! inverse-commands-invoked-by-tk '()) + (tk/wm 'protocol tk 'WM_DELETE_WINDOW end-tk))) + + (end-tk + (lambda () + (set! tk-is-running #f) + (wish "after 200 exit"))) + + (dispatch-event + (lambda () + (let ((tk-statement (read-wish))) + (if (and (list? tk-statement) + (eq? (car tk-statement) 'call)) + (apply call-by-key (cdr tk-statement)))))) + + (loop + (lambda () + (cond ((not tk-is-running) + (if wish-output + (tk/wm 'protocol tk 'WM_DELETE_WINDOW '()))) + (else (dispatch-event) + (loop))))) + + (event-loop + (lambda () + (set! tk-is-running #t) + (loop))) + + (map-ttk-widgets + (lambda (x) + (cond ((eq? x 'all) + (set! ttk-widget-map '("button" "checkbutton" "radiobutton" + "menubutton" "label" "entry" "frame" + "labelframe" "scrollbar" "notebook" + "progressbar" "combobox" "separator" + "scale" "sizegrip" "treeview"))) + ((eq? x 'none) + (set! ttk-widget-map '())) + ((pair? x) (set! ttk-widget-map + (map form->string x))) + (else (report-error + (string-append + "Argument to TTK-MAP-WIDGETS must be " + "ALL, NONE or a list of widget types.")))))) + + (string-split + (lambda (c s) + (letrec + ((split (lambda (i k tmp res) + (cond ((= i k) + (if (null? tmp) res (cons tmp res))) + ((char=? (string-ref s i) c) + (split (+ i 1) k "" (cons tmp res))) + (else (split (+ i 1) k + (string-append tmp + (string (string-ref s i))) + res)))))) + (reverse (split 0 (string-length s) "" '()))))) + + (ttk-available-themes + (lambda () + (string-split #\space (eval-wish "ttk::style theme names")))) + + (do-wait-for-window + (lambda (w) + (dispatch-event) + (cond ((equal? (tk/winfo 'exists w) "0") '()) + (else (do-wait-for-window w))))) + + (wait-for-window + (lambda (w) + (let ((outer-allow callback-mutex)) + (set! callback-mutex #t) + (do-wait-for-window w) + (set! callback-mutex outer-allow)))) + + (wait-until-visible + (lambda (w) + (tk/wait 'visibility w))) + + (lock! + (lambda () + (set! callback-mutex + (cons callback-mutex #t)))) + + (unlock! + (lambda () + (if (pair? callback-mutex) + (set! callback-mutex + (cdr callback-mutex))))) + + (with-lock + (lambda (thunk) + (lock!) + (thunk) + (unlock!)))) + + (set! tk-eval eval-wish) + (set! tk-id->widget id->widget) + (set! tk-var var) + (set! tk-get-var get-var) + (set! tk-set-var! set-var!) + (set! tk-start start) + (set! tk-end end-tk) + (set! tk-dispatch-event dispatch-event) + (set! tk-event-loop event-loop) + (set! tk-wait-for-window wait-for-window) + (set! tk-wait-until-visible wait-until-visible) + (set! tk-with-lock with-lock) + (set! tk/after (make-wish-func 'after)) + (set! tk/bell (make-wish-func 'bell)) + (set! tk/update (make-wish-func 'update)) + (set! tk/clipboard (make-wish-func 'clipboard)) + (set! tk/bgerror (make-wish-func 'bgerror)) + (set! tk/bind (make-wish-func 'bind)) + (set! tk/bindtags (make-wish-func 'bindtags)) + (set! tk/destroy (make-wish-func 'destroy)) + (set! tk/event (make-wish-func 'event)) + (set! tk/focus (make-wish-func 'focus)) + (set! tk/grab (make-wish-func 'grab)) + (set! tk/grid (make-wish-func 'grid)) + (set! tk/image (make-wish-func 'image)) + (set! tk/lower (make-wish-func 'lower)) + (set! tk/option (make-wish-func 'option)) + (set! tk/pack (make-wish-func 'pack)) + (set! tk/place (make-wish-func 'place)) + (set! tk/raise (make-wish-func 'raise)) + (set! tk/selection (make-wish-func 'selection)) + (set! tk/winfo (make-wish-func 'winfo)) + (set! tk/wm (make-wish-func 'wm)) + (set! tk/choose-color (make-wish-func "tk_chooseColor")) + (set! tk/choose-directory (make-wish-func "tk_chooseDirectory")) + (set! tk/dialog (make-wish-func "tk_dialog")) + (set! tk/get-open-file (make-wish-func "tk_getOpenFile")) + (set! tk/get-save-file (make-wish-func "tk_getSaveFile")) + (set! tk/message-box (make-wish-func "tk_messageBox")) + (set! tk/focus-follows-mouse (make-wish-func "tk_focusFollowsMouse")) + (set! tk/focus-next (make-wish-func "tk_focusNext")) + (set! tk/focus-prev (make-wish-func "tk_focusPrev")) + (set! tk/popup (make-wish-func "tk_popup")) + (set! tk/wait (lambda args (make-wish-func 'tkwait))) + (set! tk/appname (make-wish-func "tk appname")) + (set! tk/caret (make-wish-func "tk caret")) + (set! tk/scaling (make-wish-func "tk scaling")) + (set! tk/useinputmethods (make-wish-func "tk useinputmethods")) + (set! tk/windowingsystem (make-wish-func "tk windowingsystem")) + (set! ttk/available-themes ttk-available-themes) + (set! ttk/set-theme (make-wish-func "ttk::style theme use")) + (set! ttk/style (make-wish-func "ttk::style")) + (set! ttk-map-widgets map-ttk-widgets))