;; mysterx.ss (module mysterx mzscheme ; private mysterx modules (require (prefix mxprims: "private/mxmain.ss")) (require (prefix style: "private/style.ss")) (require "private/filter.ss") (require "private/properties.ss") (require "private/util.ss") ; mzlib (require (prefix mzlib: mzlib/list)) (require mzlib/string) (require mzlib/class) (require net/url) (require mzlib/etc) (require mzlib/thread) ; exports (provide mx-browser% mx-element% mx-document<%> mx-event<%> mx-version block-while-browsers com-invoke com-get-property com-set-property! com-methods com-get-properties com-set-properties com-events com-method-type com-get-property-type com-set-property-type com-event-type com-object-type com-add-ref com-ref-count com-is-a? com-help com-register-event-handler com-unregister-event-handler com-all-coclasses com-all-controls coclass->html progid->html cocreate-instance-from-coclass cci/coclass cocreate-instance-from-progid cci/progid com-get-active-object-from-coclass gao/coclass coclass progid set-coclass! set-coclass-from-progid! com-object-eq? com-omit make-css-percentage css-percentage? css-percentage-num make-css-length css-length? css-length-num css-length-units com-date->date date->com-date com-date? com-currency? com-currency->number number->com-currency com-scode? com-scode->number number->com-scode com-object? com-iunknown? %%initialize-dotnet-runtime) (define mx-version mxprims:mx-version) (define block-while-browsers mxprims:block-while-browsers) (define com-invoke mxprims:com-invoke) (define com-method-type mxprims:com-method-type) (define com-get-property-type mxprims:com-get-property-type) (define com-set-property-type mxprims:com-set-property-type) (define com-event-type mxprims:com-event-type) (define com-object-type mxprims:com-object-type) (define com-add-ref mxprims:com-add-ref) (define com-ref-count mxprims:com-ref-count) (define com-is-a? mxprims:com-is-a?) (define com-currency? mxprims:com-currency?) (define number->com-currency mxprims:number->com-currency) (define com-currency->number mxprims:com-currency->number) (define com-date? mxprims:com-date?) (define com-date->date mxprims:com-date->date) (define date->com-date mxprims:date->com-date) (define com-scode? mxprims:com-scode?) (define number->com-scode mxprims:number->com-scode) (define com-scode->number mxprims:com-scode->number) (define com-object? mxprims:com-object?) (define com-iunknown? mxprims:com-iunknown?) (define com-help mxprims:com-help) (define com-register-event-handler mxprims:com-register-event-handler) (define com-unregister-event-handler mxprims:com-unregister-event-handler) (define coclass->html mxprims:coclass->html) (define progid->html mxprims:progid->html) (define cocreate-instance-from-coclass mxprims:cocreate-instance-from-coclass) (define cci/coclass cocreate-instance-from-coclass) (define cocreate-instance-from-progid mxprims:cocreate-instance-from-progid) (define cci/progid cocreate-instance-from-progid) (define com-get-active-object-from-coclass mxprims:com-get-active-object-from-coclass) (define gao/coclass com-get-active-object-from-coclass) (define coclass mxprims:coclass) (define progid mxprims:progid) (define set-coclass! mxprims:set-coclass!) (define set-coclass-from-progid! mxprims:set-coclass-from-progid!) (define com-object-eq? mxprims:com-object-eq?) (define com-omit mxprims:com-omit) (define %%initialize-dotnet-runtime mxprims:%%initialize-dotnet-runtime) ;; sort results of "reflection" results (define (alphabetize lst) (mzlib:sort lst string-cisymbol s))))) (define set-symbol-as-string (lambda (sym vals f name) (unless (member sym vals) (error (format "~a: Expected value in '~a, got ~a" name vals sym))) (f elt (symbol->string sym)))) (define html-insertion-maker (lambda (f) (lambda (s) (dynamic-wind html-wait (lambda () (f elt s)) html-post)))) (define insert-object-maker (lambda (name->html) (opt-lambda (object width height [size 'pixels]) (dynamic-wind html-wait (lambda () (let ([old-objects (mxprims:document-objects doc)]) (mxprims:element-insert-html elt (name->html object width height size)) (let* ([new-objects (mxprims:document-objects doc)] [obj (car (mzlib:remove* old-objects new-objects com-object-eq?))]) (mxprims:com-register-object obj) obj))) html-post)))) (define append-object-maker (lambda (name->html) (opt-lambda (object width height [size 'pixels]) (dynamic-wind html-wait (lambda () (let* ([old-objects (mxprims:document-objects doc)]) (mxprims:element-append-html elt (name->html object width height size)) (let* ([new-objects (mxprims:document-objects doc)] [obj (car (mzlib:remove* old-objects new-objects com-object-eq?))]) (mxprims:com-register-object obj) obj))) html-post)))) (define insert-object-from-coclass-raw (insert-object-maker coclass->html)) (define append-object-from-coclass-raw (append-object-maker coclass->html)) (define insert-object-from-progid-raw (insert-object-maker progid->html)) (define append-object-from-progid-raw (append-object-maker progid->html)) (define insert-html (lambda (s) (dynamic-wind html-wait (lambda () (mxprims:element-insert-html elt s)) html-post))) (define get-html (lambda () (mxprims:element-get-html elt))) (define get-text (lambda () (mxprims:element-get-text elt))) (define insert-text (lambda (s) (dynamic-wind html-wait (lambda () (mxprims:element-insert-text elt s)) html-post))) (define append-text (lambda (s) (dynamic-wind html-wait (lambda () (mxprims:element-append-text elt s)) html-post))) (define append-html (lambda (s) (dynamic-wind html-wait (lambda () (mxprims:element-append-html elt s)) html-post))) (define replace-html (lambda (s) (dynamic-wind html-wait (lambda () (mxprims:element-replace-html elt s)) html-post))) (define insert-object-from-coclass (lambda args (apply insert-object-from-coclass-raw args))) (define append-object-from-coclass (lambda args (apply append-object-from-coclass-raw args))) (define insert-object-from-progid (lambda args (apply insert-object-from-progid-raw args))) (define append-object-from-progid (lambda args (apply append-object-from-progid-raw args))) (define focus (lambda () (mxprims:element-focus elt))) (define selection (lambda () (mxprims:element-selection elt))) (define set-selection! (lambda (val) (mxprims:element-set-selection! elt val))) (define attribute (lambda (s) (mxprims:element-attribute elt s))) (define set-attribute! (lambda (a v) (mxprims:element-set-attribute! elt a v))) (define click (lambda () (mxprims:element-click elt))) (define tag (lambda () (mxprims:element-tag elt))) (define font-family (lambda () (let ([s (mxprims:element-font-family elt)]) (if (empty-string? s) (empty-property-error "font-family") (style:string->font-families s))))) (define font-family-native (lambda () (mxprims:element-font-family elt))) (define set-font-family! (lambda (ff) (unless (and (pair? ff) (andmap string? ff)) (error "set-font-family!: Expected list of strings, got" ff)) (mxprims:element-set-font-family! elt (style:font-families->string ff)))) (define set-font-family-native! (lambda (s) (mxprims:element-set-font-family! elt s))) (define font-style (lambda () (get-string-as-symbol mxprims:element-font-style "font-style"))) (define font-style-native (lambda () (mxprims:element-font-style elt))) (define set-font-style! (lambda (sym) (set-symbol-as-string sym *font-styles* mxprims:element-set-font-style! "set-font-style!"))) (define set-font-style-native! (lambda (s) (mxprims:element-set-font-style! elt s))) (define font-variant (lambda () (get-string-as-symbol mxprims:element-font-variant "font-variant"))) (define font-variant-native (lambda () (mxprims:element-font-variant elt))) (define set-font-variant! (lambda (sym) (set-symbol-as-string sym *font-variants* mxprims:element-set-font-variant! "set-font-variant!"))) (define set-font-variant-native! (lambda (s) (mxprims:element-set-font-variant! elt s))) (define font-weight (lambda () (let ([s (mxprims:element-font-weight elt)]) (if (empty-string? s) (empty-property-error "font-weight") (let ((c (string-ref s 0))) (if (char-numeric? c) (string->number s) (string->symbol s))))))) (define font-weight-native (lambda () (mxprims:element-font-weight elt))) (define set-font-weight! (lambda (w) (unless (member w '(bold bolder lighter normal 100 200 300 400 500 600 700 800 900)) (error (string-append "Expected value in " "'(bold bolder lighter normal " "100 200 300 400 500 600 700 800 900)," "got ~a") w)) (let ((s (if (number? w) (number->string w) (symbol->string w)))) (mxprims:element-set-font-weight! elt s)))) (define set-font-weight-native! (lambda (s) (mxprims:element-set-font-weight! elt s))) (define font-native (lambda () (mxprims:element-font elt))) (define set-font-native! (lambda (s) (mxprims:element-set-font! elt s))) (define background-native (lambda () (mxprims:element-background elt))) (define set-background-native! (lambda (s) (mxprims:element-set-background! elt s))) (define background-attachment (lambda () (get-string-as-symbol mxprims:element-background-attachment "background-attachment"))) (define background-attachment-native (lambda () (mxprims:element-background-attachment elt))) (define set-background-attachment! (lambda (sym) (set-symbol-as-string sym *background-attachments* mxprims:element-set-background-attachment! "set-background-attachment!"))) (define set-background-attachment-native! (lambda (s) (mxprims:element-set-background-attachment! elt s))) (define background-image (lambda () (let ([s (mxprims:element-background-image elt)]) (cond [(empty-string? s) (empty-property-error "background-image")] [(string=? s "none") 'none] [(string-ci=? (substring s 0 3) "url") (list->string (mzlib:filter (lambda (c) (not (member c '(#\( #\))))) (string->list (substring s 3 (string-length s)))))] [else (error "Unknown background-image value: ~a" s)])))) (define background-image-native (lambda () (mxprims:element-background-image elt))) (define set-background-image! (lambda (image) (cond [(eq? image 'none) (mxprims:element-set-background-image! elt "none")] [(string? image) (mxprims:element-set-background-image! elt (string-append "url(" image ")"))] [else (error "Expected 'none or string, got: ~a" image)]))) (define set-background-image-native! (lambda (s) (mxprims:element-set-background-image! elt s))) (define background-repeat (lambda () (get-string-as-symbol mxprims:element-background-repeat "background-repeat"))) (define background-repeat-native (lambda () (mxprims:element-background-repeat elt))) (define set-background-repeat! (lambda (sym) (set-symbol-as-string sym *background-repeats* mxprims:element-set-background-repeat! "set-background-repeat!"))) (define set-background-repeat-native! (lambda (s) (mxprims:element-set-background-repeat! elt s))) (define background-position (lambda () (let ([s (mxprims:element-background-position elt)]) (if (empty-string? s) (empty-property-error "background-position") (style:string->background-position s))))) (define background-position-native (lambda () (mxprims:element-background-position elt))) (define set-background-position! (lambda (pos) (cond [(and (pair? pos) (= (length pos) 2)) (if (andmap symbol? pos) (let ([elt-1 (car pos)] [elt-2 (cadr pos)]) (if (or (and (horizontal? elt-1) (vertical? elt-2)) (and (vertical? elt-1) (horizontal? elt-2))) (mxprims:element-set-background-position! elt (string-append (symbol->string elt-1) " " (symbol->string elt-2))) (error (format (string-append "One symbol must be from " "'~a, other from " "'~a, got: ~a") *horizontals* *verticals* pos)))) (if (andmap style:percentage-or-length? pos) (mxprims:element-set-background-position! elt (string-append (style:percentage-or-length->string (car pos)) " " (style:percentage-or-length->string (cadr pos)))) (error (format (string-append "Two elements of list " " must be either a percentage or " " CSS length, got: ~a") pos))))] [(style:percentage-or-length? pos) (mxprims:element-set-background-position! elt (style:percentage-or-length->string pos))] [else (error (format (string-append "Expected any of " "1) a list of two symbols, one " "from '~a, the other from '~a, or " "2) a two element list, where each element is a " "percentage or CSS length, or " "3) a percentage, or " "4) a CSS length. Got: ~a") *horizontals* *verticals* pos))]))) (define set-background-position-native! (lambda (s) (mxprims:element-set-background-position! elt s))) (define text-decoration (lambda () (style:validated-string->symbols (mxprims:element-text-decoration elt) "text-decoration" style:parse-decoration))) (define text-decoration-native (lambda () (mxprims:element-text-decoration elt))) (define set-text-decoration! (lambda (decs) (unless (andmap decoration? decs) (error (format "Expected text decorations from ~a, got: ~a" *decorations* decs))) (mxprims:element-set-text-decoration! elt (symbols->string decs)))) (define set-text-decoration-native! (lambda (s) (mxprims:element-set-text-decoration! elt s))) (define text-transform (lambda () (get-string-as-symbol mxprims:element-text-transform "text-transform"))) (define text-transform-native (lambda () (mxprims:element-text-transform elt))) (define set-text-transform! (lambda (sym) (set-symbol-as-string sym *text-transforms* mxprims:element-set-text-transform! "set-text-transforms!"))) (define set-text-transform-native! (lambda (s) (mxprims:element-set-text-transform! elt s))) (define text-align (lambda () (get-string-as-symbol mxprims:element-text-align "text-align"))) (define text-align-native (lambda () (mxprims:element-text-align elt))) (define set-text-align! (lambda (sym) (set-symbol-as-string sym *text-aligns* mxprims:element-set-text-align! "set-text-align!"))) (define set-text-align-native! (lambda (s) (mxprims:element-set-text-align! elt s))) (define margin (lambda () (let ([s (mxprims:element-margin elt)]) (if (empty-string? s) (empty-property-error "margin") (style:string->margin s))))) (define margin-native (lambda () (mxprims:element-margin elt))) (define set-margin! (lambda (lst) (let ([len (length lst)]) (when (or (< len 1) (> len 4)) (error "Expected one to four margin values, got" lst))) (mxprims:element-set-margin! elt (style:margin->string lst)))) (define set-margin-native! (lambda (s) (mxprims:element-set-margin! elt s))) (define padding (lambda () (let ([s (mxprims:element-padding elt)]) (if (empty-string? s) (empty-property-error "padding") (style:string->padding s))))) (define padding-native (lambda () (mxprims:element-padding elt))) (define set-padding! (lambda (pads) (unless (and (pair? pads) (let ([len (length pads)]) (and (>= len 1) (<= len 4))) (andmap style:percentage-or-length? pads)) (error (string-append "set-padding: expected list of " "1 to 4 css-percentages or " "css-lengths, got") pads)) (mxprims:element-set-padding! elt (style:padding->string pads)))) (define set-padding-native! (lambda (s) (mxprims:element-set-padding! elt s))) (define border-raw (style:make-border-getter elt mxprims:element-border "border")) (define border (lambda args (apply border-raw args))) (define border-native (lambda (s) (mxprims:element-border elt s))) (define set-border! (lambda (cs) (style:set-border-with-fun elt cs mxprims:element-set-border!))) (define set-border-native! (lambda (s) (mxprims:element-set-border! elt s))) (define border-top-raw (style:make-border-getter elt mxprims:element-border-top "border-top")) (define border-top (lambda args (apply border-top-raw args))) (define border-top-native (lambda () (mxprims:element-border-top elt))) (define set-border-top! (lambda (cs) (style:set-border-with-fun elt cs mxprims:element-set-border-top!))) (define set-border-top-native! (lambda (s) (mxprims:element-set-border-top! elt s))) (define border-bottom-raw (style:make-border-getter elt mxprims:element-border-bottom "border-bottom")) (define border-bottom (lambda args (apply border-bottom-raw args))) (define border-bottom-native (lambda () (mxprims:element-border-bottom elt))) (define set-border-bottom! (lambda (cs) (style:set-border-with-fun elt cs mxprims:element-set-border-bottom!))) (define set-border-bottom-native! (lambda (s) (mxprims:element-set-border-bottom! elt s))) (define border-left-raw (style:make-border-getter elt mxprims:element-border-left "border-left")) (define border-left (lambda args (apply border-left-raw args))) (define border-left-native (lambda () (mxprims:element-border-left elt))) (define set-border-left! (lambda (cs) (style:set-border-with-fun elt cs mxprims:element-set-border-left!))) (define set-border-left-native! (lambda (s) (mxprims:element-set-border-left! elt s))) (define border-right-raw (style:make-border-getter elt mxprims:element-border-right "border-right")) (define border-right (lambda args (apply border-right-raw args))) (define border-right-native (lambda () (mxprims:element-border-right elt))) (define set-border-right! (lambda (cs) (style:set-border-with-fun elt cs mxprims:element-set-border-right!))) (define set-border-right-native! (lambda (s) (mxprims:element-set-border-right! elt s))) (define border-color-raw (style:make-color-getter elt mxprims:element-border-color "border-color")) (define border-color (lambda args (apply border-color-raw args))) (define border-color-native (lambda () (mxprims:element-border-color elt))) (define set-border-color-raw! (style:make-color-setter elt mxprims:element-set-border-color! "set-border-color!")) (define set-border-color! (lambda args (apply set-border-color-raw! args))) (define set-border-color-native! (lambda (s) (mxprims:element-set-border-color! elt s))) (define border-width-raw (style:make-border-width-getter elt mxprims:element-border-width "border-width")) (define border-width (lambda args (apply border-width-raw args))) (define border-width-native (lambda () (mxprims:element-border-width elt))) (define set-border-width! (lambda (s) (unless (style:border-width? s) (error (format "border-width: Expected element of ~a or CSS length, got: ~a" *border-widths* s))) (mxprims:element-set-border-width! elt (style:border-width->string s)))) (define set-border-width-native! (lambda (s) (mxprims:element-set-border-width! elt s))) (define border-style-raw (style:make-border-style-getter elt mxprims:element-border-style "border-style")) (define border-style (lambda args (apply border-style-raw args))) (define border-style-native (lambda () (mxprims:element-border-style elt))) (define set-border-style-raw! (style:make-border-style-setter elt mxprims:element-set-border-style! "set-border-style!")) (define set-border-style! (lambda args (apply set-border-style-raw! args))) (define set-border-style-native! (lambda (s) (mxprims:element-set-border-style! elt s))) (define border-top-style-raw (style:make-border-style-getter elt mxprims:element-border-top-style "border-top-style")) (define border-top-style (lambda args (apply border-top-style-raw args))) (define border-top-style-native (lambda () (mxprims:element-border-top-style elt))) (define set-border-top-style-raw! (style:make-border-style-setter elt mxprims:element-set-border-top-style! "set-border-top-style!")) (define set-border-top-style! (lambda args (apply set-border-top-style-raw! args))) (define set-border-top-style-native! (lambda (s) (mxprims:element-set-border-top-style! elt s))) (define border-bottom-style-raw (style:make-border-style-getter elt mxprims:element-border-bottom-style "border-bottom-style")) (define border-bottom-style (lambda args (apply border-bottom-style-raw args))) (define border-bottom-style-native (lambda () (mxprims:element-border-bottom-style elt))) (define set-border-bottom-style-raw! (style:make-border-style-setter elt mxprims:element-set-border-bottom-style! "set-border-bottom-style!")) (define set-border-bottom-style! (lambda args (apply set-border-bottom-style-raw! args))) (define set-border-bottom-style-native! (lambda (s) (mxprims:element-set-border-bottom-style! elt s))) (define border-left-style-raw (style:make-border-style-getter elt mxprims:element-border-left-style "border-left-style")) (define border-left-style (lambda args (apply border-left-style-raw args))) (define border-left-style-native (lambda () (mxprims:element-border-left-style elt))) (define set-border-left-style-raw! (style:make-border-style-setter elt mxprims:element-set-border-left-style! "set-border-left-style!")) (define set-border-left-style! (lambda args (apply set-border-left-style-raw! args))) (define set-border-left-style-native! (lambda (s) (mxprims:element-set-border-left-style! elt s))) (define border-right-style-raw (style:make-border-style-getter elt mxprims:element-border-right-style "border-right-style")) (define border-right-style (lambda args (apply border-right-style-raw args))) (define border-right-style-native (lambda () (mxprims:element-border-right-style elt))) (define set-border-right-style-raw! (style:make-border-style-setter elt mxprims:element-set-border-right-style! "set-border-right-style!")) (define set-border-right-style! (lambda args (apply set-border-right-style-raw! args))) (define set-border-right-style-native! (lambda (s) (mxprims:element-set-border-right-style! elt s))) (define border-top-color-raw (style:make-color-getter elt mxprims:element-border-top-color "border-top-color")) (define border-top-color (lambda args (apply border-top-color-raw args))) (define border-top-color-native! (lambda () (mxprims:element-border-top-color elt))) (define set-border-top-color-raw! (style:make-color-setter elt mxprims:element-set-border-top-color! "set-border-top-color!")) (define set-border-top-color! (lambda args (apply set-border-top-color-raw! args))) (define set-border-top-color-native! (lambda (s) (mxprims:element-set-border-top-color! elt s))) (define border-bottom-color-raw (style:make-color-getter elt mxprims:element-border-bottom-color "border-bottom-color")) (define border-bottom-color (lambda args (apply border-bottom-color-raw args))) (define border-bottom-color-native (lambda () (mxprims:element-border-bottom-color elt))) (define set-border-bottom-color-raw! (style:make-color-setter elt mxprims:element-set-border-bottom-color! "set-border-bottom-color!")) (define set-border-bottom-color! (lambda args (apply set-border-bottom-color-raw! args))) (define set-border-bottom-color-native! (lambda (s) (mxprims:element-set-border-bottom-color! elt s))) (define border-left-color-raw (style:make-color-getter elt mxprims:element-border-left-color "border-left-color")) (define border-left-color (lambda args (apply border-left-color-raw args))) (define border-left-color-native (lambda () (mxprims:element-border-left-color elt))) (define set-border-left-color-raw! (style:make-color-setter elt mxprims:element-set-border-left-color! "set-border-left-color!")) (define set-border-left-color! (lambda args (apply set-border-left-color-raw! args))) (define set-border-left-color-native! (lambda (s) (mxprims:element-set-border-left-color! elt s))) (define border-right-color-raw (style:make-color-getter elt mxprims:element-border-right-color "border-right-color")) (define border-right-color (lambda args (apply border-right-color-raw args))) (define border-right-color-native (lambda () (mxprims:element-border-right-color elt))) (define set-border-right-color-raw! (style:make-color-setter elt mxprims:element-set-border-right-color! "set-border-right-color!")) (define set-border-right-color! (lambda args (apply set-border-right-color-raw! args))) (define set-border-right-color-native! (lambda (s) (mxprims:element-set-border-right-color! elt s))) (define border-top-width-raw (style:make-border-width-getter elt mxprims:element-border-top-width "border-top-width")) (define border-top-width (lambda args (apply border-top-width-raw args))) (define border-top-width-native (lambda () (mxprims:element-border-top-width elt))) (define set-border-top-width-raw! (style:make-border-width-setter elt mxprims:element-set-border-top-width! "set-border-top-width!")) (define set-border-top-width! (lambda args (apply set-border-top-width-raw! args))) (define set-border-top-width-native! (lambda (s) (mxprims:element-set-border-top-width! elt s))) (define border-bottom-width-raw (style:make-border-width-getter elt mxprims:element-border-bottom-width "border-bottom-width")) (define border-bottom-width (lambda args (apply border-bottom-width-raw args))) (define border-bottom-width-native (lambda () (mxprims:element-border-bottom-width elt))) (define set-border-bottom-width-raw! (style:make-border-width-setter elt mxprims:element-set-border-bottom-width! "set-border-bottom-width!")) (define set-border-bottom-width! (lambda args (apply set-border-bottom-width-raw! args))) (define set-border-bottom-width-native! (lambda (s) (mxprims:element-set-border-bottom-width! elt s))) (define border-left-width-raw (style:make-border-width-getter elt mxprims:element-border-left-width "border-left-width")) (define border-left-width (lambda args (apply border-left-width-raw args))) (define border-left-width-native (lambda () (mxprims:element-border-left-width elt))) (define set-border-left-width-raw! (style:make-border-width-setter elt mxprims:element-set-border-left-width! "set-border-left-width!")) (define set-border-left-width! (lambda args (apply set-border-left-width-raw! args))) (define set-border-left-width-native! (lambda (s) (mxprims:element-set-border-left-width! elt s))) (define border-right-width-raw (style:make-border-width-getter elt mxprims:element-border-right-width "border-right-width")) (define border-right-width (lambda args (apply border-right-width-raw args))) (define border-right-width-native (lambda () (mxprims:element-border-right-width elt))) (define set-border-right-width-raw! (style:make-border-width-setter elt mxprims:element-set-border-right-width! "set-border-right-width!")) (define set-border-right-width! (lambda args (apply set-border-right-width-raw! args))) (define set-border-right-width-native! (lambda (s) (mxprims:element-set-border-right-width! elt s))) (define style-float-raw (style:make-element-getter elt mxprims:element-style-float "style-float" )) (define style-float (lambda args (apply style-float-raw args))) (define style-float-native (lambda () (mxprims:element-style-float elt))) (define set-style-float-raw! (style:make-element-setter elt style-float? *style-floats* mxprims:element-set-style-float!)) (define set-style-float! (lambda args (apply set-style-float-raw! args))) (define set-style-float-native! (lambda (s) (mxprims:element-set-style-float! elt s))) (define clear-raw (style:make-element-getter elt mxprims:element-clear "clear")) (define clear (lambda args (apply clear-raw args))) (define clear-native (lambda () (mxprims:element-clear elt))) (define set-clear-raw! (style:make-element-setter elt clear? *clears* mxprims:element-set-clear!)) (define set-clear! (lambda args (apply set-clear-raw! args))) (define set-clear-native! (lambda (s) (mxprims:element-set-clear! elt s))) (define display-raw (style:make-element-getter elt mxprims:element-display "display")) (define display (lambda args (apply display-raw args))) (define display-native (lambda () (mxprims:element-display elt))) (define set-display-raw! (style:make-element-setter elt display? *displays* mxprims:element-set-display!)) (define set-display! (lambda args (apply set-display-raw! args))) (define set-display-native! (lambda (s) (mxprims:element-set-display! elt s))) (define visibility-raw (style:make-element-getter elt mxprims:element-visibility "visibility")) (define visibility (lambda args (apply visibility-raw args))) (define visibility-native (lambda () (mxprims:element-visibility elt))) (define set-visibility-raw! (style:make-element-setter elt visibility? *visibilities* mxprims:element-set-visibility!)) (define set-visibility! (lambda args (apply set-visibility-raw! args))) (define set-visibility-native! (lambda (s) (mxprims:element-set-visibility! elt s))) (define list-style-type-raw (style:make-element-getter elt mxprims:element-list-style-type "list-style-type")) (define list-style-type (lambda args (apply list-style-type-raw args))) (define list-style-type-native (lambda () (mxprims:element-list-style-type elt))) (define set-list-style-type-native! (lambda (s) (mxprims:element-set-list-style-type! elt s))) (define list-style-position-raw (style:make-element-getter elt mxprims:element-list-style-position "list-style-position")) (define list-style-position (lambda args (apply list-style-position-raw args))) (define list-style-position-native (lambda () (mxprims:element-list-style-position elt))) (define set-list-style-position-native! (lambda (s) (mxprims:element-set-list-style-position! elt s))) (define list-style-image (lambda () (let ([s (mxprims:element-list-style-image elt)]) (when (empty-string? s) (empty-property-error "list-style-image")) (cond [(string-ci=? s "none") 'none] [(string-ci=? (substring s 0 4) "url(") (style:url->string s)] [else (error (format "list-style-image: Expected 'none or URL, got: ~a" s))])))) (define list-style-image-native (lambda () (mxprims:element-list-style-image elt))) (define set-list-style-image! (lambda (s) (let ([str (if (eq? s 'none) "none" (style:string->url s))]) (mxprims:element-set-list-style-image! elt str)))) (define set-list-style-image-native! (lambda (s) (mxprims:element-set-list-style-image! elt s))) (define list-style (lambda () (let* ([s (mxprims:element-list-style elt)] [elts (style:parse-string s)]) (map style:string->list-style-item elts)))) (define list-style-native (lambda () (mxprims:element-list-style elt))) (define set-list-style! (lambda (items) (mxprims:element-set-list-style! elt (fold-strings-with-spaces (map style:list-style-item->string items))))) (define set-list-style-native! (lambda (s) (mxprims:element-set-list-style! elt s))) (define position-raw (style:make-element-getter elt mxprims:element-position "position")) (define position (lambda args (apply position-raw args))) (define position-native (lambda () (mxprims:element-position elt))) (define overflow-raw (style:make-element-getter elt mxprims:element-overflow "overflow")) (define overflow (lambda args (apply overflow-raw args))) (define overflow-native (lambda () (mxprims:element-overflow elt))) (define set-overflow-raw! (style:make-element-setter elt overflow? *overflows* mxprims:element-set-overflow!)) (define set-overflow! (lambda args (apply set-overflow-raw! args))) (define set-overflow-native! (lambda (s) (mxprims:element-set-overflow! elt s))) (define pagebreak-before-raw (style:make-pagebreak-getter elt mxprims:element-pagebreak-before)) (define pagebreak-before (lambda args (apply pagebreak-before-raw args))) (define pagebreak-before-native (lambda () (mxprims:element-pagebreak-before elt))) (define set-pagebreak-before-raw! (style:make-pagebreak-setter elt mxprims:element-set-pagebreak-before! "set-pagebreak-before!")) (define set-pagebreak-before! (lambda args (apply set-pagebreak-before-raw! args))) (define set-pagebreak-before-native! (lambda (s) (mxprims:element-set-pagebreak-before! elt s))) (define pagebreak-after-raw (style:make-pagebreak-getter elt mxprims:element-pagebreak-after)) (define pagebreak-after (lambda args (apply pagebreak-after-raw args))) (define pagebreak-after-native (lambda () (mxprims:element-pagebreak-after elt))) (define set-pagebreak-after-raw! (style:make-pagebreak-setter elt mxprims:element-set-pagebreak-after! "set-pagebreak-after!")) (define set-pagebreak-after! (lambda args (apply set-pagebreak-after-raw! args))) (define css-text-native (lambda () (mxprims:element-css-text elt))) (define set-css-text-native! (lambda (s) (mxprims:element-set-css-text! elt s))) (define cursor-raw (style:make-element-getter elt mxprims:element-cursor "cursor")) (define cursor (lambda args (apply cursor-raw args))) (define cursor-native (lambda () (mxprims:element-cursor elt))) (define set-cursor-raw! (style:make-element-setter elt cursor? *cursors* mxprims:element-set-cursor!)) (define set-cursor! (lambda args (apply set-cursor-raw! args))) (define set-cursor-native! (lambda (s) (mxprims:element-set-cursor! elt s))) (define clip (lambda () (let ([s (mxprims:element-clip elt)]) (cond [(empty-string? s) (empty-property-error "clip")] [(string-ci=? s "auto") 'auto] [(style:clip-rect? s) (style:clip-rect->symbols s)] [else (error (format "clip: Expected clip string, got: ~a" s))])))) (define clip-native (lambda () (mxprims:element-clip elt))) (define set-clip! (lambda (s) (let ([str (cond [(eq? s 'auto) "auto"] [(and (pair? s) (= (length s) 4) (andmap (lambda (elt) (or (eq? elt 'auto) (css-length? elt))) s)) (string-append "rect(" (fold-strings-with-spaces (map (lambda (elt) (if (eq? elt 'auto) "auto" (style:css-length->string elt))) s)) ")")] [else (error (format (string-append "Expected 'auto or 4-element list of " "CSS lengths, with elements " "possibly replaced by 'auto. Got ~a") s))])]) (mxprims:element-set-clip! elt str)))) (define set-clip-native! (lambda (s) (mxprims:element-set-clip! elt s))) (define filter (lambda () (let ([s (mxprims:element-filter elt)]) (if (empty-string? s) (empty-property-error "filter") (string->filter s))))) (define filter-native (lambda () (mxprims:element-filter elt))) (define set-filter! (lambda (flt . options) (let ([s (filter->string flt options)]) (mxprims:element-set-filter! elt s)))) (define set-filter-native! (lambda (s) (mxprims:element-set-filter! elt s))) (define style-string (lambda () (mxprims:element-style-string elt))) ; the text decoration, blink attributes are boolean ; hence no conversion to/from strings (define text-decoration-none (lambda () (mxprims:element-text-decoration-none elt))) (define set-text-decoration-none! (lambda (s) (mxprims:element-set-text-decoration-none! elt s))) (define text-decoration-underline (lambda () (mxprims:element-text-decoration-underline elt))) (define set-text-decoration-underline! (lambda (s) (mxprims:element-set-text-decoration-underline! elt s))) (define text-decoration-overline (lambda () (mxprims:element-text-decoration-overline elt))) (define set-text-decoration-overline! (lambda (s) (mxprims:element-set-text-decoration-overline! elt s))) (define text-decoration-linethrough (lambda () (mxprims:element-text-decoration-linethrough elt))) (define set-text-decoration-linethrough! (lambda (s) (mxprims:element-set-text-decoration-linethrough! elt s))) (define text-decoration-blink (lambda () (mxprims:element-text-decoration-blink elt))) (define set-text-decoration-blink! (lambda (s) (mxprims:element-set-text-decoration-blink! elt s))) ; pixel attributes are all longs ; hence, no conversion to/from strings (define pixel-top (lambda () (mxprims:element-pixel-top elt))) (define set-pixel-top! (lambda (s) (mxprims:element-set-pixel-top! elt s))) (define pixel-left (lambda () (mxprims:element-pixel-left elt))) (define set-pixel-left! (lambda (s) (mxprims:element-set-pixel-left! elt s))) (define pixel-width (lambda () (mxprims:element-pixel-width elt))) (define set-pixel-width! (lambda (s) (mxprims:element-set-pixel-width! elt s))) (define pixel-height (lambda () (mxprims:element-pixel-height elt))) (define set-pixel-height! (lambda (s) (mxprims:element-set-pixel-height! elt s))) ; position attributes are all floats ; hence no conversion to/from strings (define pos-top (lambda () (mxprims:element-pos-top elt))) (define set-pos-top! (lambda (s) (mxprims:element-set-pos-top! elt s))) (define pos-left (lambda () (mxprims:element-pos-left elt))) (define set-pos-left! (lambda (s) (mxprims:element-set-pos-left! elt s))) (define pos-width (lambda () (mxprims:element-pos-width elt))) (define set-pos-width! (lambda (s) (mxprims:element-set-pos-width! elt s))) (define pos-height (lambda () (mxprims:element-pos-height elt))) (define set-pos-height! (lambda (s) (mxprims:element-set-pos-height! elt s))) (define font-size (lambda () (let ([s (mxprims:element-font-size elt)]) (if (empty-string? s) (empty-property-error "font-size") (style:string->font-size s))))) (define font-size-native (lambda () (mxprims:element-font-size elt))) (define set-font-size! (lambda (sz) (let ([s (cond [(font-size? sz) (symbol->string sz)] [(style:percentage-or-length? sz) (style:percentage-or-length->string sz)] [else (error (format (string-append "set-font-size!: Expected element of ~a, " "a CSS length, or CSS percentage. Got: ~a") *font-sizes* sz))])]) (mxprims:element-set-font-size! elt s)))) (define set-font-size-native! (lambda (s) (mxprims:element-set-font-size! elt s))) (define color-raw (style:make-color-getter elt mxprims:element-color "color")) (define color (lambda args (apply color-raw args))) (define color-native-raw (lambda () (mxprims:element-color elt))) (define color-native (lambda args (apply color-native-raw args))) (define set-color-raw! (style:make-color-setter elt mxprims:element-set-color! "set-color!")) (define set-color! (lambda args (apply set-color-raw! args))) (define set-color-native! (lambda (s) (mxprims:element-set-color! elt s))) (define background-color-raw (style:make-color-getter elt mxprims:element-background-color "background-color")) (define background-color (lambda args (apply background-color-raw args))) (define background-color-native (lambda () (mxprims:element-background-color elt))) (define set-background-color-raw! (style:make-color-setter elt mxprims:element-set-background-color! "set-background-color!")) (define set-background-color! (lambda args (apply set-background-color-raw! args))) (define set-background-color-native! (lambda (s) (mxprims:element-set-background-color! elt s))) (define background-position-x-raw (style:make-bg-pos-getter elt mxprims:element-background-position-x "background-position-x")) (define background-position-x (lambda args (apply background-position-x-raw args))) (define background-position-x-native (lambda () (mxprims:element-background-position-x elt))) (define set-background-position-x-raw! (style:make-bg-pos-setter elt mxprims:element-set-background-position-x! horizontal? *horizontals* "x")) (define set-background-position-x! (lambda args (apply set-background-position-x-raw! args))) (define set-background-position-x-native! (lambda (n) (mxprims:element-set-background-position-x! elt n))) (define background-position-y-raw (style:make-bg-pos-getter elt mxprims:element-background-position-y "background-position-y")) (define background-position-y (lambda args (apply background-position-y-raw args))) (define background-position-y-native (lambda () (mxprims:element-background-position-y elt))) (define set-background-position-y-raw! (style:make-bg-pos-setter elt mxprims:element-set-background-position-y! vertical? *verticals* "y")) (define set-background-position-y! (lambda args (apply set-background-position-y-raw! args))) (define set-background-position-y-native! (lambda (s) (mxprims:element-set-background-position-y! elt s))) (define letter-spacing-raw (style:make-normal-or-css-getter elt mxprims:element-letter-spacing "letter-spacing")) (define letter-spacing (lambda args (apply letter-spacing-raw args))) (define letter-spacing-native (lambda () (mxprims:element-letter-spacing elt))) (define set-letter-spacing-raw! (style:make-normal-or-css-setter elt mxprims:element-set-letter-spacing! "set-letter-spacing!")) (define set-letter-spacing! (lambda args (apply set-letter-spacing-raw! args))) (define set-letter-spacing-native! (lambda (s) (mxprims:element-set-letter-spacing! elt s))) (define vertical-align (lambda () (let ([s (mxprims:element-vertical-align elt)]) (when (empty-string? s) (empty-property-error "vertical-align")) (string->symbol s)))) (define vertical-align-native (lambda () (mxprims:element-vertical-align elt))) (define set-vertical-align! (lambda (sym) (unless (vertical-align? sym) (error (format (string-append "set-vertical-align!: " "Expected element of ~a, got ~a") *vertical-aligns* sym))) (mxprims:element-set-vertical-align! elt (symbol->string sym)))) (define set-vertical-align-native! (lambda (s) (mxprims:element-set-vertical-align! elt s))) (define text-indent-raw (style:make-css-getter elt mxprims:element-text-indent "text-indent")) (define text-indent (lambda args (apply text-indent-raw args))) (define text-indent-native (lambda () (mxprims:element-text-indent elt))) (define set-text-indent-raw! (style:make-css-setter elt mxprims:element-set-text-indent! "set-text-indent!")) (define set-text-indent! (lambda args (apply set-text-indent-raw! args))) (define set-text-indent-native! (lambda (s) (mxprims:element-set-text-indent! elt s))) (define line-height-raw (style:make-normal-or-css-getter elt mxprims:element-line-height "line-height")) (define line-height (lambda args (apply line-height-raw args))) (define line-height-native (lambda () (mxprims:element-line-height elt))) (define set-line-height-raw! (style:make-normal-or-css-setter elt mxprims:element-set-line-height! "set-line-height!")) (define set-line-height! (lambda args (apply set-line-height-raw! args))) (define set-line-height-native! (lambda (s) (mxprims:element-set-line-height! elt s))) (define margin-top-raw (style:make-auto-or-css-getter elt mxprims:element-margin-top "margin-top")) (define margin-top (lambda args (apply margin-top-raw args))) (define margin-top-native (lambda () (mxprims:element-margin-top elt))) (define set-margin-top-raw! (style:make-auto-or-css-setter elt mxprims:element-set-margin-top! "set-margin-top!")) (define set-margin-top! (lambda args (apply set-margin-top-raw! args))) (define set-margin-top-native! (lambda (s) (mxprims:element-set-margin-top! elt s))) (define margin-bottom-raw (style:make-auto-or-css-getter elt mxprims:element-margin-bottom "margin-bottom")) (define margin-bottom (lambda args (apply margin-bottom-raw args))) (define margin-bottom-native (lambda () (mxprims:element-margin-bottom elt))) (define set-margin-bottom-raw! (style:make-auto-or-css-setter elt mxprims:element-set-margin-bottom! "set-margin-bottom!")) (define set-margin-bottom! (lambda args (apply set-margin-bottom-raw! args))) (define set-margin-bottom-native! (lambda (s) (mxprims:element-set-margin-bottom! elt s))) (define margin-left-raw (style:make-auto-or-css-getter elt mxprims:element-margin-left "margin-left")) (define margin-left (lambda args (apply margin-left-raw args))) (define margin-left-native (lambda () (mxprims:element-margin-left elt))) (define set-margin-left-raw! (style:make-auto-or-css-setter elt mxprims:element-set-margin-left! "set-margin-left!")) (define set-margin-left! (lambda args (apply set-margin-left-raw! args))) (define set-margin-left-native! (lambda (s) (mxprims:element-set-margin-left! elt s))) (define margin-right-raw (style:make-auto-or-css-getter elt mxprims:element-margin-right "margin-right")) (define margin-right (lambda args (apply margin-right-raw args))) (define margin-right-native (lambda () (mxprims:element-margin-right elt))) (define set-margin-right-raw! (style:make-auto-or-css-setter elt mxprims:element-set-margin-right! "set-margin-right!")) (define set-margin-right! (lambda args (apply set-margin-right-raw! args))) (define set-margin-right-native! (lambda (s) (mxprims:element-set-margin-right! elt s))) (define padding-top-raw (style:make-css-getter elt mxprims:element-padding-top "padding-top")) (define padding-top (lambda args (apply padding-top-raw args))) (define padding-top-native (lambda () (mxprims:element-padding-top elt))) (define set-padding-top-raw! (style:make-css-setter elt mxprims:element-set-padding-top! "set-padding-top!")) (define set-padding-top! (lambda args (apply set-padding-top-raw! args))) (define set-padding-top-native! (lambda (s) (mxprims:element-set-padding-top! elt s))) (define padding-bottom-raw (style:make-css-getter elt mxprims:element-padding-bottom "padding-bottom")) (define padding-bottom (lambda args (apply padding-bottom-raw args))) (define padding-bottom-native (lambda () (mxprims:element-padding-bottom elt))) (define set-padding-bottom-raw! (style:make-css-setter elt mxprims:element-set-padding-bottom! "set-padding-bottom!")) (define set-padding-bottom! (lambda args (apply set-padding-bottom-raw! args))) (define set-padding-bottom-native! (lambda (s) (mxprims:element-set-padding-bottom! elt s))) (define padding-left-raw (style:make-css-getter elt mxprims:element-padding-left "padding-left")) (define padding-left (lambda args (apply padding-left-raw args))) (define padding-left-native (lambda () (mxprims:element-padding-left elt))) (define set-padding-left-raw! (style:make-css-setter elt mxprims:element-set-padding-left! "set-padding-left!")) (define set-padding-left! (lambda args (apply set-padding-left-raw! args))) (define set-padding-left-native! (lambda (s) (mxprims:element-set-padding-left! elt s))) (define padding-right-raw (style:make-css-getter elt mxprims:element-padding-right "padding-right")) (define padding-right (lambda args (apply padding-right-raw args))) (define padding-right-native (lambda () (mxprims:element-padding-right elt))) (define set-padding-right-raw! (style:make-css-setter elt mxprims:element-set-padding-right! "set-padding-right!")) (define set-padding-right! (lambda args (apply set-padding-right-raw! args))) (define set-padding-right-native! (lambda (s) (mxprims:element-set-padding-right! elt s))) (define width-raw (style:make-auto-or-css-getter elt mxprims:element-width "width")) (define width (lambda args (apply width-raw args))) (define width-native (lambda () (mxprims:element-width elt))) (define set-width-raw! (style:make-auto-or-css-setter elt mxprims:element-set-width! "set-width!")) (define set-width! (lambda args (apply set-width-raw! args))) (define set-width-native! (lambda (s) (mxprims:element-set-width! elt s))) (define height-raw (style:make-auto-or-css-getter elt mxprims:element-height "height")) (define height (lambda args (apply height-raw args))) (define height-native (lambda () (mxprims:element-height elt))) (define set-height-raw! (style:make-auto-or-css-setter elt mxprims:element-set-height! "set-height!")) (define set-height! (lambda args (apply set-height-raw! args))) (define set-height-native! (lambda (s) (mxprims:element-set-height! elt s))) (define top-raw (style:make-auto-or-css-getter elt mxprims:element-top "top")) (define top (lambda args (apply top-raw args))) (define top-native (lambda () (mxprims:element-top elt))) (define set-top-raw! (style:make-auto-or-css-setter elt mxprims:element-set-top! "set-top!")) (define set-top! (lambda args (apply set-top-raw! args))) (define set-top-native! (lambda (s) (mxprims:element-set-top! elt s))) (define left-raw (style:make-auto-or-css-getter elt mxprims:element-left "left")) (define left (lambda args (apply left-raw args))) (define left-native (lambda () (mxprims:element-left elt))) (define set-left-raw! (style:make-auto-or-css-setter elt mxprims:element-set-left! "set-left!")) (define set-left! (lambda args (apply set-left-raw! args))) (define set-left-native! (lambda (s) (mxprims:element-set-left! elt s))) (define z-index (lambda () (let ([s (mxprims:element-z-index elt)]) (when (empty-string? s) (empty-property-error "z-index")) (if (and (string? s) (string=? s "auto")) 'auto s)))) (define z-index-native (lambda () (mxprims:element-z-index elt))) (define set-z-index! (lambda (zi) (let ([s (cond [(eq? zi 'auto) "auto"] [(and (number? zi) (exact? zi)) zi] [else (error (string-append "set-z-index!: " "Expected 'auto or exact integer, " "got") zi)])]) (mxprims:element-set-z-index! elt s)))) (define set-z-index-native! (lambda (s) (mxprims:element-set-z-index! elt s))) (define set-list-style-position-raw! (style:make-element-setter elt list-style-position? *list-style-positions* mxprims:element-set-list-style-position!)) (define set-list-style-position! (lambda args (apply set-list-style-position-raw! args))) (define set-list-style-type-raw! (style:make-element-setter elt list-style-type? *list-style-types* mxprims:element-set-list-style-type!)) (define set-list-style-type! (lambda args (apply set-list-style-type-raw! args))) (super-make-object))) (define mx-event% (class object% (init dhtml-event) ; private fields (define event dhtml-event) (public keypress? keydown? keyup? mousedown? mousemove? mouseover? mouseout? mouseup? click? dblclick? error? tag id from-tag from-id to-tag to-id keycode shift-key ctrl-key alt-key x y) ; predicates (define keypress? (lambda () (mxprims:event-keypress? event))) (define keydown? (lambda () (mxprims:event-keydown? event))) (define keyup? (lambda () (mxprims:event-keyup? event))) (define mousedown? (lambda () (mxprims:event-mousedown? event))) (define mousemove? (lambda () (mxprims:event-mousemove? event))) (define mouseover? (lambda () (mxprims:event-mouseover? event))) (define mouseout? (lambda () (mxprims:event-mouseout? event))) (define mouseup? (lambda () (mxprims:event-mouseup? event))) (define click? (lambda () (mxprims:event-click? event))) (define dblclick? (lambda () (mxprims:event-dblclick? event))) (define error? (lambda () (mxprims:event-error? event))) ; attributes (define tag (lambda () (mxprims:event-tag event))) (define id (lambda () (mxprims:event-id event))) (define from-tag (lambda () (mxprims:event-from-tag event))) (define from-id (lambda () (mxprims:event-id event))) (define to-tag (lambda () (mxprims:event-to-tag event))) (define to-id (lambda () (mxprims:event-to-id event))) (define keycode (lambda () (mxprims:event-keycode event))) (define shift-key (lambda () (mxprims:event-shiftkey event))) (define ctrl-key (lambda () (mxprims:event-ctrlkey event))) (define alt-key (lambda () (mxprims:event-altkey event))) (define x (lambda () (mxprims:event-x event))) (define y (lambda () (mxprims:event-y event))) (super-make-object))) (define mx-event<%> (class->interface mx-event%)) (define mx-browser% (class object% (init (label "MysterX") (width 'default) (height 'default) (x 'default) (y 'default) (style-options null)) ; private fields (define browser (mxprims:make-browser label width height x y style-options)) (define thread-sem (make-semaphore 1)) (define thread-wait (lambda () (semaphore-wait thread-sem))) (define thread-post (lambda () (semaphore-post thread-sem))) (define navigate-sem (make-semaphore 0)) (define navigate-mutex (make-semaphore 1)) (define navigate-url #f) (define handler-sem (make-semaphore 1)) (define handler-wait (lambda () (semaphore-wait handler-sem))) (define handler-post (lambda () (semaphore-post handler-sem))) (define handler-table (make-hash-table)) (define handler-thread #f) (define make-navigator (lambda (navigate-fun name) (lambda url (let ([actual-url #f]) (semaphore-wait navigate-mutex) (if (apply navigate-fun (cons browser url)) (begin (semaphore-wait navigate-sem) (set! actual-url navigate-url)) (begin (semaphore-post navigate-mutex) (error name "Error navigating browser"))) (semaphore-post navigate-mutex) actual-url)))) (define block-until-event (lambda () (mxprims:block-until-event browser))) (define make-event-key (lambda (tag id) ; string x string -> symbol (let ([new-tag (string-copy tag)] [new-id (string-copy id)]) (string-uppercase! new-tag) (string-uppercase! new-id) (string->symbol (string-append new-tag "@" new-id))))) (public show navigate navigate/status go-back go-forward refresh iconize restore current-url current-document print-document register-event-handler unregister-event-handler handle-events stop-handling-events) (define show (lambda (b) (mxprims:browser-show browser b))) (define navigate/status (lambda (url) (let ([actual (navigate url)]) (if (and (>= (string-length actual) 7) (string=? (substring actual 0 7) "http://")) (let* ([p (get-impure-port (string->url actual))] [response (read-line p)] [raw-status (regexp-match "[0-9][0-9][0-9]" response)]) (close-input-port p) (list actual (if raw-status (string->number (car raw-status)) #f))) (list actual 'no-status))))) (define navigate-raw (make-navigator mxprims:navigate 'navigate)) (define navigate (lambda args (apply navigate-raw args))) (define go-back-raw (make-navigator mxprims:go-back 'go-back)) (define go-back (lambda args (apply go-back-raw args))) (define go-forward-raw (make-navigator mxprims:go-forward 'go-forward)) (define go-forward (lambda args (apply go-forward-raw args))) (define refresh (lambda () (mxprims:refresh browser))) (define iconize (lambda () (mxprims:iconize browser))) (define restore (lambda () (mxprims:restore browser))) (define current-url (lambda () (mxprims:current-url browser))) (define current-document (lambda () (make-object mx-document% (mxprims:current-document browser)))) (define print-document (lambda () (mxprims:print-document browser))) (define register-event-handler (lambda (elt fn) (dynamic-wind handler-wait (lambda () (let* ([tag (send elt tag)] [id (send elt attribute "id")]) (let ([key (make-event-key tag id)]) (hash-table-remove! handler-table key) (hash-table-put! handler-table key fn)))) handler-post))) (define unregister-event-handler (lambda (elt) (dynamic-wind handler-wait (lambda () (let* ([tag (send elt tag)] [id (send elt attribute "id")]) (let ([key (make-event-key tag id)]) (hash-table-remove! handler-table key)))) handler-post))) (define handle-events (lambda () (dynamic-wind thread-wait (lambda () ; no-op if existing handler-thread (unless handler-thread (dynamic-wind handler-wait (lambda () (let* ([handler-thunk (lambda () (let loop () (block-until-event) (let* ([prim-event (with-handlers ([void (lambda (e) (printf "~a~n" (exn-message e)) (loop))]) (mxprims:get-event browser))] [event (make-object mx-event% prim-event)] [tag (send event tag)] [id (send event id)] [key (make-event-key tag id)] [handler (hash-table-get handler-table key void)]) (unless (void? handler) (handler event)) (loop))))]) (set! handler-thread (thread handler-thunk)))) handler-post))) thread-post))) (define stop-handling-events (lambda () (dynamic-wind thread-wait (lambda () (when handler-thread (kill-thread handler-thread)) (set! handler-thread #f)) thread-post))) (super-make-object) (mxprims:register-navigate-handler browser (lambda (_ boxed-url) (set! navigate-url (current-url)) (semaphore-post navigate-sem))))) (define mx-document% (class object% (init the-doc) ; private fields (define doc the-doc) (define insert-object-maker (lambda (name->html) (opt-lambda (object width height [size 'pixels]) (dynamic-wind html-wait (lambda () (mxprims:document-insert-html doc (name->html object width height size)) (car (mxprims:document-objects doc))) html-post)))) (define append-object-maker (lambda (name->html) (opt-lambda (object width height [size 'pixels]) (dynamic-wind html-wait (lambda () (mxprims:document-append-html doc (name->html object width height size)) (car (mzlib:last-pair (mxprims:document-objects doc)))) html-post)))) (define html-insertion-maker (lambda (f) (lambda (s) (dynamic-wind html-wait (lambda () (f doc s)) html-post)))) (public title find-element find-element-by-id-or-name elements-with-tag objects insert-html append-html replace-html insert-object-from-coclass append-object-from-coclass insert-object-from-progid append-object-from-progid) (define title (lambda () (mxprims:document-title doc))) (define find-element (lambda (tag id . n) (make-object mx-element% doc (apply mxprims:document-find-element doc tag id n)))) (define find-element-by-id-or-name (lambda (id . n) (make-object mx-element% doc (apply mxprims:document-find-element-by-id-or-name doc id n)))) (define elements-with-tag (lambda (tag) (map (lambda (elt) (make-object mx-element% doc elt)) (mxprims:document-elements-with-tag doc tag)))) (define objects (lambda () (mxprims:document-objects doc))) (define insert-html-raw (html-insertion-maker mxprims:document-insert-html)) (define insert-html (lambda args (apply insert-html-raw args))) (define append-html-raw (html-insertion-maker mxprims:document-append-html)) (define append-html (lambda args (apply append-html-raw args))) (define replace-html-raw (html-insertion-maker mxprims:document-replace-html)) (define replace-html (lambda args (apply replace-html-raw args))) (define insert-object-from-coclass-raw (insert-object-maker coclass->html)) (define insert-object-from-coclass (lambda args (apply insert-object-from-coclass-raw args))) (define append-object-from-coclass-raw (append-object-maker coclass->html)) (define append-object-from-coclass (lambda args (apply append-object-from-coclass-raw args))) (define insert-object-from-progid-raw (insert-object-maker progid->html)) (define insert-object-from-progid (lambda args (apply insert-object-from-progid-raw args))) (define append-object-from-progid-raw (append-object-maker progid->html)) (define append-object-from-progid (lambda args (apply append-object-from-progid-raw args))) (super-make-object))) (define mx-document<%> (class->interface mx-document%)) (thread (lambda () (let loop () (mxprims:process-win-events) (sleep 0.01) (loop)))))