Compare commits

...

140 Commits
v6.3 ... master

Author SHA1 Message Date
Robby Findler
d0376db70a Rackety 2016-08-19 09:28:10 -05:00
Stephen De Gabrielle
0e99b1f286 correct small typo in 'Animation in Canvases' (#40)
flushing to the screen can be starved if flushing is frequently suspend.
changed to
flushing to the screen can be starved if flushing is frequently suspended.
2016-08-19 07:37:35 -05:00
Robby Findler
ce1ded41f2 fix leak 2016-07-30 20:30:48 -05:00
Leif Andersen
68dcd1156d Updated docs to point to gui-interactive.rkt 2016-07-30 13:38:47 -04:00
Robby Findler
1df6383e3c fix ascii-art-enlarge-mode tests 2016-07-30 10:36:44 -05:00
Robby Findler
18404570dd improve support for editing the ascii art (unicode) #2d rectangles
specifically, add a mode that avoids breaking the edges of
the rectangle when you type and add a keystroke for adding
a new in the existing row
2016-07-30 04:55:01 -05:00
Robby Findler
fcd134eebe more search fixes 2016-07-26 19:15:48 -05:00
Leif Andersen
4053cb1e16 gui-doc now depends on xrepl doc. 2016-07-26 10:30:05 -04:00
Leif Andersen
ef78d330b6 Move docs for racket/gui/init and racket/gui/interactive
Previously they were part of the base repo.
2016-07-26 09:41:58 -04:00
Robby Findler
a8574ce5e6 missed a call to do-search 2016-07-26 01:11:49 -05:00
Leif Andersen
1801eac125 racket/gui/interactive should be using racket/base
Previously it was using racket/gui
2016-07-25 22:39:16 -04:00
Robby Findler
dbede3f33c get rid of (worse) implementation of find-string-embedded
that was hanging around from old times. Instead, just use the
text% find-string-embedded functionality directly
2016-07-24 04:02:42 -05:00
Robby Findler
6b16c0fd6b rackety & add test suite 2016-07-24 04:02:42 -05:00
Robby Findler
feaff67418 fix bug in searching (start from the correct editor) 2016-07-24 04:02:41 -05:00
Leif Andersen
e293d24da7 Apparently find-graphical-system-path finds the correct gracketrc file 2016-07-23 13:09:01 -04:00
Robby Findler
52300ff032 highlight search hits in embedded editors 2016-07-23 09:18:17 -05:00
Robby Findler
28ca7c6d14 improve the situation for search results in nested editors
This doesn't quite fix all the problems, as the outer editor doesn't get callbacks
when the position changes in the inner editors (and the inner ones aren't propogating
the callbacks currently) so the "n/m matches" display doesn't update properly in that
case. Also, it doesn't (yet) try to draw the search bubbles for embedded editors

Still, progress has been made; at least the bar is not red anymore when there are
hits only in embedded editors

closes PR 12786
2016-07-23 03:00:00 -05:00
Robby Findler
ed5f0ae09b clarify chaining precedence rules 2016-07-23 03:00:00 -05:00
Leif Andersen
cb81e3768d Woops, racket/gui/interactive should load .gracketrc.
(Cannot use (find-system-path 'init-file) because it will always
evaluate to .racketrc, even in gracket (where it should be
.gracketrc).)
2016-07-23 02:27:40 -04:00
Leif Andersen
0ae02837e5 Add interactive file to be used by Racket core. 2016-07-23 00:33:46 -04:00
Robby Findler
66bda1c9c8 fix marshalling bug in syntax-browser
closes #35
2016-07-22 03:25:04 -05:00
Robby Findler
d73fc00749 protect DrRacket against bugs in snipclass marshalling code
I believe this applies only when DrRacket already trusts
the handler, so this is just a debugging aid, not true protection

closes racket/drracket#49
2016-07-22 03:09:48 -05:00
Robby Findler
6941a07998 fix the "Show Active Keybindings" menu item
for the case where one keybinding's keys is a prefix of anothers (and the keymaps are chained)
2016-07-21 22:13:55 -05:00
Robby Findler
943582763e correct error checking for keymaps 2016-07-21 21:42:17 -05:00
Robby Findler
8272f99035 adjust tabifying behavior to mess with blank lines less
Be more like Emacs: when indenting only change the whitespace
on a blank line when indenting just a single line (e.g. when
hitting return or when hitting tab with a selection that
doesn't span multiple lines)

closes racket/drracket#65
2016-07-07 11:06:25 -05:00
Robby Findler
b10086ed13 add info the docs about between methods that create separator items 2016-07-07 11:06:25 -05:00
Robby Findler
0b2be755e4 do even less work before queueing the callback in hopes it is guaranteed to get queued
closes PR 15317
2016-06-30 10:14:10 -05:00
Robby Findler
af33c70558 dont use get-keyword-type as the parameter name 2016-06-28 10:12:26 -05:00
Robby Findler
09519347e2 use a hash for the preferences (instead of the real file) 2016-06-25 21:27:25 -05:00
Robby Findler
f629545c2d use pretty-write when printing in write mode 2016-06-25 09:41:52 -05:00
Robby Findler
c3322ca05d adjust indentation so that hyphens at the start of sexp causes subsequent
lines to not indent
2016-06-22 20:44:29 -05:00
Robby Findler
9f3635f399 adjust indentation so that a sequence of hyphens always moves to the start of the sexp 2016-06-22 20:41:17 -05:00
Dan Feltey
d9dbfb01fd Fix racket:text-mixin docs to include required editor:keymap<%> interface (#34) 2016-06-20 22:32:15 -05:00
Matthew Flatt
e01e970722 fix a problem in WXME decoding
Thanks to Robby for the test case and for narrowing down the problem.
2016-06-06 09:20:47 -06:00
Robby Findler
7c857706d7 added an optional argument to compute-racket-amount-to-indent 2016-06-05 08:41:10 -05:00
Robby Findler
48d2de53d5 ispell (not aspell) doesn't seem to deal correctly with non-ASCII words
so just don't try to spell check them unless we know we have aspell
2016-05-29 20:02:47 -05:00
Robby Findler
c3f4b5dedd generalize set-interactive-write-handler & use it in text:ports-mixin
to avoid duplicate code between the drracket support for printing and
for write/display; also add a special case for 2htdp/image images
because they can be trusted across the boundary between DrRacket's
implementation and the user's program (as there is no way to embed
arbitrary code into a 2htdp/image image)
2016-05-28 18:34:52 -05:00
Stephen De Gabrielle
7794ace98d Typo line 874 changed 'if' to 'of' 2016-05-27 15:40:07 -05:00
Matthew Flatt
399cfe9c5b add 'hide-hscroll and 'hide-vscroll for panel% 2016-05-18 15:30:33 -06:00
Matthew Flatt
3e6fcf18bb Cocoa: fix enable method of choice% 2016-05-18 14:33:16 -06:00
Robby Findler
10425033b8 fix marshalling of embedded editors 2016-05-15 16:02:01 -05:00
Asumu Takikawa
50fb0e9a93 Minor wording fix in highlight-range docs 2016-05-11 15:34:04 -04:00
Robby Findler
fc5c233cdd minor edit to undo docs 2016-04-20 13:11:18 -05:00
Robby Findler
0863437394 dont allow undoing of the color changes that IO uses to indicate which port is which
closes PR 15291
2016-04-20 12:37:09 -05:00
Matthew Flatt
f0d10e9cc8 OS X: disable reordering of tabs in the new tab-panel% widget
Fixes racket/drracket#52
2016-04-17 20:59:10 -06:00
Matthew Flatt
2fa9b94683 repair to work with ancient Gtk 2016-04-17 14:30:31 -06:00
Matthew Flatt
6de1e4310c fix disable of tab-panel% with 'no-border 2016-04-15 21:59:13 -06:00
Robby Findler
fdd52ef965 loosen passing predicate for number snip test 2016-04-15 18:11:29 -05:00
Robby Findler
ca2deebe47 fix ellipsis in test 2016-04-15 18:09:38 -05:00
Matthew Flatt
fc813b32ca cooperate with tethered-executable builds 2016-04-14 16:21:16 -06:00
Matthew Flatt
32f8bfd90e repairs to work with old Gtk 2016-04-14 06:06:34 -06:00
Robby Findler
eb8d060f84 fix short circuiting computation for line number drawing
closes #30

please include in the release
2016-04-11 18:06:43 -05:00
Matthew Flatt
9ef883a79f Cocoa, 64-bit, 10.10 and later: use MMTabBarView
On 10.11 in 64-bit mode, showing a frame with a PSMTabBarControl
instance somehow causes the event loop to become occupied on
mouse movements, so that moving the mouse in a `2htdp/universe`
program is slow when more than one tab is open in DrRacket. The
modern MMTabBarView widget doesn't have that problem. Also, the
MMTabBarView widget has a Yosemite look (to replace Aqua).
2016-04-07 13:12:30 -06:00
Matthew Flatt
30c8202656 fix focus for windows within a floating frame
Make the `focus` method shift focus to a floating frame. Also, shift
focus away from the floating frame when `focus` is used in an window
within the current main frame.
2016-03-28 17:25:22 -06:00
Matthew Flatt
9fdc917295 unbreak splash dialog
Bug fix is by Robby.
2016-03-27 17:38:54 -06:00
Robby Findler
c4b0dffcfa try to help the search window to have the right size
in the case that the font size has changed since it was last open

(this doesn't seem to be a problem with only one tab and
may actually be a bug in the way editor canvases with set-line-count
enabled handle font size changes, I'm not sure, but this seems
to fix a fairly annoying behavior I run into)
2016-03-27 17:40:22 -05:00
Robby Findler
3da682ebe1 add syntax-parameterize to tabbing rules 2016-03-27 16:16:19 -05:00
Robby Findler
0b8598e9d0 remove useless code 2016-03-27 16:15:38 -05:00
Robby Findler
9a9ecb72fb fix bug in keybinding table construction 2016-03-18 09:42:31 -05:00
Matthew Flatt
ac0442b990 framework preferences: add option for Control+Alt as AltGr 2016-03-17 17:01:36 -06:00
Matthew Flatt
282a22b8f0 add any-control+alt-is-altgr
Thanks to Bert De Ketelaere for helping to sort out this new
behavior.
2016-03-17 16:39:40 -06:00
Matthew Flatt
3ae70e6617 fix doc typos 2016-03-15 18:44:41 -06:00
Matthew Flatt
2c5b1480f4 fix mouse wheel for GTK+ 3
Closes PR 15271
2016-03-15 13:28:13 -06:00
Robby Findler
50655cea7e some more updates to follow TeX better for \var vs non-\var greek letters
Source: https://www.w3.org/TR/WD-math-970515/table04.html
Hat Tip: Max New
2016-03-10 21:54:30 -06:00
Robby Findler
1717521602 follow latex's \varepsilon vs \epsilon convention, as described here:
http://tex.stackexchange.com/questions/98013/varepsilon-vs-epsilon
2016-03-10 16:52:01 -06:00
Matthew Flatt
c4ef1829fc Gtk: adjust handling of composed input
Intended to fix #29
2016-03-10 13:10:37 -07:00
Robby Findler
cf2859049a add a preference to control the maximum reflow width 2016-03-08 09:29:48 -06:00
Robby Findler
28406b9a76 remove the restriction that new preferences can be registered only before a snapshot is grabbed
also improve the docs a little bit and some Rackety
2016-03-08 09:29:03 -06:00
Robby Findler
da7a258da8 bring down below 102 columns and fix a set! expression
to actually have an effect
2016-03-07 08:30:32 -06:00
Matthew Flatt
2ab1fb319a rearrange dc fields to avoid undefined-checking chaperone 2016-03-02 08:42:55 -07:00
Asumu Takikawa
6b9cd9fa9c Fix docs for get-search-hit-count to match code 2016-03-02 03:54:18 -05:00
Robby Findler
ab063326fe change indentation strategy for sequences whose head is a keyword
assume that these are part of some internal structure of something
that, in general looks like

  (#:x 1 #:y 2 #:z 3)

and so prefer to indent like this:

  (#:x 1
   #:y 2
   #:z 3)

instead of like this:

  (#:x 1
       #:y 2
       #:z 3)
2016-02-25 10:37:44 -06:00
Matthew Flatt
be30bf721d Cocoa: avoid backing-dc failure on zero-sized canvas
Closes https://github.com/racket/racket#1255
2016-02-22 05:05:35 -07:00
Robby Findler
c8c8ce64eb use the right font for sizing the line numbers invalidate region
closes #41
2016-02-19 09:03:39 -06:00
Robby Findler
d88ba8d2cd fix on-scroll-to callback method when an editor has multiple canvases
closes PR 15252
2016-02-17 08:58:09 -06:00
Robby Findler
8e81b5346a don't color parens when the colorer is stopped 2016-02-10 09:19:33 -06:00
Robby Findler
7d5144acba adjust switchable-button so that it can change its label 2016-02-09 18:16:36 -06:00
Robby Findler
e9e2940138 adjust indentation so that it treats only symbols as things with
special indentation

(this could only come about if the regexp specification in the prefernces
matched (the printed out) version of strings, so it wouldn't happen with
the default preferences)
2016-02-09 13:44:30 -06:00
Leif Andersen
9411eb44c4 Add with-* to the set of lambda like expressions. 2016-02-06 19:45:57 -05:00
Matthew Flatt
5736535b8a avoid spurious screen refresh on text-measure operations
The drawing layer now indicates whether drawing content was
changed as it releases a drawing handle.
2016-02-05 16:51:39 -07:00
Leif Andersen
f02fd8f338 Add link to weak reference. 2016-02-05 18:36:02 -05:00
Matthew Flatt
d28ab71058 fix -singleInstance for GTK+3
Closes PR 15240
2016-02-05 10:40:04 -07:00
Robby Findler
021f9a6a0a delay the creation of the information in the info text
this has the advantage of that the information is inserted when the
state of the text is set up so that font sizing works

it also means that if there is a syntax object with a syntax
object on its properties with another one like that etc etc etc
they will only be rendered when they are made visible which
theoretically could be a performance improvement for some people
2016-02-02 09:36:15 -06:00
Robby Findler
55e34bd6d4 make syntax snips inherit the style-list of the editors that contain them 2016-02-01 18:02:00 -06:00
Matthew Flatt
345a20c5e8 use NSOpenGLPFAAllowOfflineRenderers for GC bitmap
Try to tell Macs with two graphics cards that it's ok to
use the low-performance one for the GC bitmap (when
GL is used for that, which is OS X 10.11 and later).
2016-01-16 08:50:06 -07:00
Matthew Flatt
55d0d96dbe Gtk: fix handling of widget to extract text colors
With GTK+ 3 on Raspbian, at least, the old management of the
widget causes a crash.
2016-01-12 10:05:09 -07:00
Matthew Flatt
e206dab087 use #:runtime?-id for improved cross-build support 2016-01-09 09:47:28 -07:00
Matthew Flatt
4d5d08f07f fix back-end reference for cross-build 2016-01-08 16:45:16 -07:00
Matthew Flatt
6e7964b0b7 include icons needed by "gui-lib" in the package
The "plt-logo-48x48.png" file is a copy of "plt-48x48.png" from
"icons", but renamed to avoid conflicts.
2016-01-08 16:31:52 -07:00
Matthew Flatt
dbce2e2878 avoid an NSTableColumn warning 2016-01-08 07:58:53 -07:00
Matthew Flatt
0e344def40 Windows play-sound: remove extra delay after async 2016-01-05 07:31:01 -07:00
Matthew Flatt
8ae077c22a Windows play-sound: use the right custodian registration
Otherwise, a GC tends to terminate the sound.
2016-01-04 19:19:51 -07:00
Matthew Flatt
76c305852b Windows play-sound: avoid leaks and shutdown on custodian
Also, stop a synchronous sound on a break exception.
2016-01-04 18:10:23 -07:00
Matthew Flatt
edc56ee8de Windows: change play-sound to use MCI
Provided by Eli Barzilay.

This approach is better than a separate process, because creating
too many processes can overwhelm the OS. Also, MCI supports more
sound formats.
2016-01-04 17:41:53 -07:00
Lehi Toskin
89007ae039 Fix typo, clarify get-file filter 2016-01-01 12:37:37 -06:00
Matthew Flatt
41d4e9dd2d Cocoa: fix refresh and fullscreen problems
Add more agressive re-enabling of screen updates and explicit `update`
calls to avoid partially refreshed frames and never-updated titlebars
on El Capitan.

Also, use `close` instead of `orderOut` to hide a frame. That fixes
problems with closing windows that are in fullscreen mode.

Closes racket/drracket#33
2015-12-31 15:50:41 -07:00
Sam Tobin-Hochstadt
61c0b53716 Fix test for Unicode ellipsis. 2015-12-31 12:00:32 -05:00
Robby Findler
aeb2577715 make error message a little more informative 2015-12-29 21:25:28 -06:00
Matthew Flatt
196797b529 Windows: fix play-sound to return a boolean 2015-12-28 10:09:10 -06:00
Matthew Flatt
bf442a8c99 refine docs on play-sound 2015-12-28 09:42:23 -06:00
Matthew Flatt
ca24d94cdc Cocoa: avoid screen sync for GC-blit GL context
Affects 10.11 and up
2015-12-28 09:42:23 -06:00
Matthew Flatt
87c2317cbc Windows: change play-sound to run an external program
Running a sound through a separate process allows multiple
sounds to be played at once.
2015-12-28 08:24:34 -07:00
Robby Findler
fc61b26e04 fix snip test example setup 2015-12-27 08:26:03 -06:00
Matthew Flatt
87e17a89da Windows: fix get-current-mouse-state for HiDPI 2015-12-23 08:31:38 -07:00
Matthew Flatt
65fc1c4e8f put-file: clarify filter and extension handling on Windows 2015-12-22 10:58:52 -07:00
Matthew Flatt
d170a8ff31 editor<%>: request incremental GC on key & mouse events 2015-12-19 12:45:25 -07:00
Matthew Flatt
446df9e047 put on-to-scroll callbacks in a refresh sequence
Avoid flickering for the "#lang" line and documentation
wedge in DrRacket, for example.
2015-12-19 07:54:30 -07:00
Matthew Flatt
1944cd8dbd regsiter-collecting-blit: support background bitmap in El Capitan
The GC blit implementation used on Mc OS X 10.11 assumed that
the no-GC bitmap is blank. Make it use the given no-GC bitmap.

Also, repair the left-to-right flipping(!) of the GC bitmap,
and repair a backing-scale mismatch that could leave a thin
border around a GC blit.
2015-12-18 16:05:48 -07:00
Robby Findler
7c43e6d876 fix contract-related errors in framework/splash 2015-12-18 11:21:04 -06:00
Robby Findler
3af5db35be fix bugs in support and docs for the snip flag HANDLES-BETWEEN-EVENTS
(the previous commit was pushed too soon; it is completely broken. Apologies)
2015-12-17 22:24:59 -06:00
Robby Findler
759d89443f add support and docs for the snip flag HANDLES-BETWEEN-EVENTS 2015-12-17 16:18:46 -06:00
Robby Findler
23f22a8bcf extend the example snip with wxme support
and add some tests for the example
2015-12-17 10:33:36 -06:00
Robby Findler
6fd5459211 fix add-splash-icon contract 2015-12-15 17:41:09 -06:00
Robby Findler
debd229668 guard call 2015-12-15 14:20:12 -06:00
Robby Findler
46eb5ae3aa add contracts and fix some (theoretical) threading bugs 2015-12-15 14:20:12 -06:00
Jay McCarthy
c1cddc538c Casting flag-x-error-handler in this case too. Necessary for getting GL working on my Linux/Nvidia box to test pict3d 2015-12-14 08:55:36 -05:00
Robby Findler
6e97d0bc9d correct docs 2015-12-14 06:58:49 -06:00
Sam Tobin-Hochstadt
83a7c7b8f1 Remove this-expression-source-directory. 2015-12-11 10:42:54 -05:00
Matthew Flatt
c4793a218f Windows: avoid refresh on no-op canvas show-scrollbars 2015-12-03 05:36:42 -07:00
Matthew Flatt
d3f212b98c fix copy-on-scroll for non-integer scroll offset 2015-12-02 20:50:21 -07:00
Robby Findler
be9cd36922 added editor:font-size-message% 2015-11-27 10:41:57 -06:00
Robby Findler
fe77bb34d4 more on scroll-by-copy
make it per-editor customizable, add callbacks, and use
them to make the special first line mixin work properly
when it is enabled
2015-11-26 13:11:47 -06:00
Matthew Flatt
79128627d2 avoid scrolling too far for scroll-via-copy
But scroll-via-copy is still not enabled.
2015-11-25 16:14:54 -07:00
Matthew Flatt
4358d22a0a disable scroll via copy
Sometimes doesn't work right, as illustrated by PR 15186
2015-11-25 08:46:37 -07:00
Matthew Flatt
bdac2da540 enable scoll via copy 2015-11-25 05:07:44 -07:00
Matthew Flatt
33395ae1cf Cocoa: canvas DC copy improvement 2015-11-24 15:01:25 -07:00
Matthew Flatt
3873064c80 Cocoa: avoid over-eager refresh on OS X 10.11
A relatively late correction to refresh handling for El Capitan
(commit 9bf18505d5) causes a canvas to be refreshed too often
in some cases. Delay the refresh to restore the old timing
without the old bug.
2015-11-23 20:45:25 -07:00
Matthew Flatt
facc07e123 Cocoa: make copy method work for canvas DC
Also correct problems with disabled scrolling via `copy`.
2015-11-23 12:13:48 -07:00
Matthew Flatt
b29a7ae399 Gtk+ 3: open library in "global" mode to support the printer dialog
Opening a shared object in global mode risks conflicts with
other shared objects, but opening only one library that way
will hopefully not create conflicts.
2015-11-19 12:03:18 -07:00
Robby Findler
c0bbc70194 fix newline insertion position calculation
closes #21
2015-11-14 09:53:26 -06:00
Vincent St-Amour
73fb3dbe39 Add test for pasteboard bug. 2015-11-11 16:54:28 -06:00
Thomas Hilliker
acab3f14e1 added length parameter to call of snip insert 2015-11-11 16:54:05 -06:00
Matthew Flatt
9bf18505d5 fix refresh on El Capitan
When restoring autodisplay, need to check whether a display was
lost since display was suspended.
2015-11-07 06:45:34 -07:00
Leif Andersen
16bf6cf55d Swap get-end-position and get-start-position 2015-10-30 19:17:47 -05:00
Matthew Flatt
746956a6ae skip clean-up of bitmap that isn't there
Backing-bitmap allocation might fail for a too-large window?
2015-10-29 07:43:45 -04:00
Robby Findler
35a288da6a allow meta-q for re-indent under unix 2015-10-25 21:14:26 -05:00
Matthew Flatt
172b7d5a56 implement GL screen sync for Windows canvases 2015-10-18 18:15:03 -06:00
Matthew Flatt
5a1d5557c4 implement GL screen sync for X11 canvases 2015-10-18 18:08:05 -06:00
Matthew Flatt
4daafb2357 implement GL screen sync for Cocoa canvases 2015-10-18 17:49:32 -06:00
Vincent St-Amour
8bfd1bb25e Add missing history annotations.
Please merge to 6.3.
2015-10-12 14:16:16 -05:00
120 changed files with 3565 additions and 1549 deletions

View File

@ -13,8 +13,10 @@
"syntax-color-lib"
"wxme-lib"
"gui-lib"
"pict-lib"
"racket-doc"
"string-constants-doc"))
"string-constants-doc"
"xrepl-doc"))
(define deps '("base"))
(define update-implies '("gui-lib"))

View File

@ -6,35 +6,53 @@
@defmodule[mrlib/interactive-value-port]
@defproc[(set-interactive-display-handler [port output-port?]) void?]{
@defproc[(set-interactive-display-handler
[port output-port?]
[#:snip-handler snip-handler
(or/c #f (-> (is-a?/c snip%) output-port? any))
#f])
void?]{
Sets @racket[port]'s display handler (via
@racket[port-display-handler]) so that when it encounters these
values:
Sets @racket[port]'s display handler (via
@racket[port-display-handler]) so that when it encounters
these values:
@itemize[@item{syntax objects}
@item{snips}]
@itemize[
@item{exact, real, non-integral numbers}
it uses @racket[write-special] to send snips to the port
and uses @racketmodname[mrlib/syntax-browser] to turn
syntax object into snips and then uses
@racket[write-special] with the result to send it to the
port. Otherwise, it behaves like the default handler.
@item{syntax objects}
If @racket[snip-handler] is not @racket[#f], then
@racket[set-interactive-display-handler] passes any snips
to it (not those it creates by
@racketmodname[mrlib/syntax-browser]) instead of calling
@racket[write-special].
]
it uses @racket[write-special] to send snips to the port,
instead of those values. Otherwise, it behaves like the
default handler.
To show values embedded in lists and other compound object, it uses
@racket[pretty-print].}
To show values embedded in lists and other compound object,
it uses @racket[pretty-display].
}
@defproc[(set-interactive-write-handler [port output-port?]) void?]{
@defproc[(set-interactive-write-handler
[port output-port?]
[#:snip-handler snip-handler
(or/c #f (-> (is-a?/c snip%) output-port? any))
#f])
void?]{
Like @racket[set-interactive-display-handler], but sets the
@racket[port-write-handler].}
@racket[port-write-handler] and uses @racket[pretty-write].}
@defproc[(set-interactive-print-handler [port output-port?]) void?]{
@defproc[(set-interactive-print-handler
[port output-port?]
[#:snip-handler snip-handler
(or/c #f (-> (is-a?/c snip%) output-port? any))
#f])
void?]{
Like @racket[set-interactive-display-handler], but sets the
@racket[port-print-handler].}
@racket[port-print-handler] and uses @racket[pretty-print].}

View File

@ -454,4 +454,26 @@
}
}
@defclass[editor:font-size-message% canvas% ()]{
@defconstructor[([message (or/c string? (listof string?))]
[stretchable-height any/c #f])]{
The @racket[message] field controls the initial contents. If there
is a list of strings, then each string is put on a separate line.
If there is just a single string, it is split on newlines and then
treated as if it were a list.
The @racket[stretchable-height] has the opposite default from the
@racket[canvas%] superclass.
}
@defmethod[(set-message [message (or/c string? (listof string?))]) void?]{
Changes the message.
If @racket[message] is a list of strings, then each
string is put on a separate line. If there is just a
single string, it is split on newlines and then treated as
if it were a list argument.
}
}
@(include-previously-extracted "main-extracts.rkt" #rx"^editor:")

View File

@ -19,9 +19,12 @@
@defmethod*[(((get-map-function-table/ht (ht hash?)) hash?))]{
This is a helper function for @method[keymap:aug-keymap<%>
get-map-function-table] that returns the same result, except it accepts a
get-map-function-table] that returns a similar result, except it accepts a
hash-table that it inserts the bindings into. It does not replace any
bindings already in @racket[ht].
bindings already in @racket[ht]. The result is different from
@method[keymap:aug-keymap<%> get-map-function-table] only in that
@racket[keymap:aug-keymap<%> get-map-function-table] will remove keybindings
that are also have a prefix (since those keybindings are not active).
}
}
@defmixin[keymap:aug-keymap-mixin (keymap%) (keymap:aug-keymap<%>)]{

View File

@ -42,6 +42,8 @@ listeners when the contents of the cell is changed.
@defmethod[(remove-all-listeners) void?]{
Removes all previously registered callbacks.
}
@history[#:added "1.18"]{}
}
@defproc[(notify:notify-box/pref
@ -67,6 +69,8 @@ reflected in the notify-box.
(send nb set 'deer)
(animal)
]
@history[#:added "1.18"]{}
}
@defform[(notify:define-notify name value-expr)
@ -97,6 +101,8 @@ Useful for aggregating many notify-boxes together into one
(send food set 'honey))
(send c get-animal)
]
@history[#:added "1.18"]{}
}
@defproc[(notify:menu-option/notify-box
@ -108,6 +114,8 @@ Useful for aggregating many notify-boxes together into one
Creates a @racket[checkable-menu-item%] tied to @racket[notify-box]. The menu item is
checked whenever @racket[(send notify-box get)] is true. Clicking the
menu item toggles the value of @racket[notify-box] and invokes its listeners.
@history[#:added "1.18"]{}
}
@defproc[(notify:check-box/notify-box
@ -121,6 +129,8 @@ Creates a @racket[check-box%] tied to @racket[notify-box]. The
check-box is checked whenever @racket[(send notify-box get)] is
true. Clicking the check box toggles the value of @racket[notify-box]
and invokes its listeners.
@history[#:added "1.18"]{}
}
@defproc[(notify:choice/notify-box
@ -138,6 +148,8 @@ its listeners.
If the value of @racket[notify-box] is not in @racket[choices], either
initially or upon an update, an error is raised.
@history[#:added "1.18"]{}
}
@defproc[(notify:menu-group/notify-box
@ -151,6 +163,8 @@ Returns a list of @racket[checkable-menu-item%] controls tied to
@racket[(send notify-box get)]. Clicking a menu item updates
@racket[notify-box] to its label and invokes @racket[notify-box]'s
listeners.
@history[#:added "1.18"]{}
}

View File

@ -84,12 +84,22 @@
}
@defmethod[#:mode public-final
(compute-racket-amount-to-indent [pos exact-nonnegative-integer?])
(compute-racket-amount-to-indent
[pos exact-nonnegative-integer?]
[get-head-sexp-type
(-> string? (or/c #f 'lambda 'define 'begin 'for/fold 'other))
(λ (x) #f)])
exact-nonnegative-integer?]{
Computes the amount of space to indent the line containing @racket[pos],
using the default s-expression indentation strategy.
@history[#:added "1.9"]
The function @racket[get-head-sexp-type] is consulted for each symbol/keyword
that follows an open parenthesis. If it returns @racket[#f], then the
user's preferences (from the @onscreen{Indenting} panel of the @onscreen{Editing}
panel in the preferences dialog) are used.
@history[#:added "1.9"
#:changed "1.26" @list{Added the @racket[get-head-sexp-type] argument.}]
}
@defmethod[#:mode augment
@ -248,7 +258,7 @@
}
}
@defmixin[racket:text-mixin
(text:basic<%> mode:host-text<%> color:text<%> text:autocomplete<%>)
(text:basic<%> mode:host-text<%> color:text<%> text:autocomplete<%> editor:keymap<%>)
(racket:text<%>)]{
This mixin adds functionality for editing Racket files.

View File

@ -74,7 +74,7 @@ that number to control the gauge along the bottom of the splash screen.
if there is more initialization work to be done where you do not want to count loaded files.
}
@defproc[(add-splash-icon [bmp (is-a?/c bitmap%)] [x exact-nonnegative-integer?] [y exact-nonnegative-integer?])
@defproc[(add-splash-icon [bmp (is-a?/c bitmap%)] [x real?] [y real?])
void?]{
Adds an icon to the splash screen. (DrRacket uses this function to show the tools as they are loaded.)
}

View File

@ -20,7 +20,7 @@
This function highlights a region of text in the buffer.
The range between @racket[start] and @racket[end] will be highlighted with
the color in color, if the style is @racket['rectangle] (the default). If
the given @racket[color], if the style is @racket['rectangle] (the default). If
the style is @racket['ellipse], then an ellipse is drawn around the range
in the editor, using the color. If the style is @racket['hollow-ellipse],
then the outline of an ellipse is drawn around the range in the editor,
@ -268,6 +268,39 @@
preference changes.
}
@definterface[text:ascii-art-enlarge-boxes<%> ()]{
@defmethod[(set-ascii-art-enlarge [e? any/c]) void?]{
Enables or disables the ascii art box enlarging mode based on @racket[e?]'s true value.
}
@defmethod[(get-ascii-art-enlarge) boolean?]{
Returns @racket[#t] if ascii art box enlarging mode is enabled and @racket[#f] otherwise.
}
}
@defmixin[text:ascii-art-enlarge-boxes-mixin (text%) (text:ascii-art-enlarge-boxes<%>)]{
@defmethod[#:mode override (on-local-char [event (is-a?/c key-event%)]) void?]{
When the @method[key-event% get-key-code] method of @racket[event] returns either
@racket['numpad-enter] or @racket[#\return] and
@method[text:ascii-art-enlarge-boxes<%> get-ascii-art-enlarge] returns
@racket[#t], this method handles
the return key by adding an additional line in the containing unicode ascii art
box and moving the insertion point to the first character on the new line that
is in the containing cell.
It does not call the @racket[super] method (in that case).
}
@defmethod[#:mode override (on-default-char [event (is-a?/c key-event%)]) void?]{
When the @method[key-event% get-key-code] method of @racket[event] returns either
a character or symbol that corresponds to the insertion of a single character
@method[text:ascii-art-enlarge-boxes<%> get-ascii-art-enlarge] returns
@racket[#t], this method first makes room in the box and then calls the
@racket[super] method. If the @method[text% get-overwrite-mode] returns
@racket[#f], then it always opens up a column in the box. If @method[text% get-overwrite-mode]
returns @racket[#t], then it opens up a column only when the character to
be inserted would overwrite one of the walls.
}
}
@definterface[text:first-line<%> (text%)]{
Objects implementing this interface, when @method[text:first-line<%>
@ -539,8 +572,9 @@
@racket['framework:anchored-search] preference is on.
}
@defmethod[(get-search-hit-count) number?]{
Returns the number of hits for the search in the buffer, based on the count
@defmethod[(get-search-hit-count) (values number? number?)]{
Returns the number of hits for the search in the buffer before the
insertion point and the total number of hits. Both are based on the count
found last time that a search completed.
}

View File

@ -58,7 +58,9 @@ On Windows and Unix, @racket[filters] determines a set of filters from
@racket[filters] list contains two strings: a description of the filter
as seen by the user, and a filter pattern matched against file names.
Pattern strings can be a simple ``glob'' pattern, or a number of glob
patterns separated by a @litchar[";"] character.
patterns separated by a @litchar[";"] character. These patterns are not
regular expressions and can only be used with a @litchar["*"] wildcard
character. For example, @racket["*.jp*g;*.png"].
On Unix, a @racket["*.*"] pattern is implicitly replaced with @racket["*"].
On Mac OS X, suffix names are extracted from all globs that match a
fixed suffix (e.g., two suffixes of @racket["foo"] and @racket["bar"]
@ -84,7 +86,7 @@ See also @racket[path-dialog%] for a richer interface.
(or/c (listof path?) #f)]{
Like
@racket[get-file], except that the user can select multiple files, and the
result is either a list of file paths of @racket[#f].
result is either a list of file paths or @racket[#f].
}
@ -118,11 +120,11 @@ If @racket[directory] is not @racket[#f], it is used as the starting
prefix.
On Windows, if @racket[extension] is not @racket[#f], the returned path
will get a default extension if the user does not supply one. If
@racket[extension] is the empty string, then the extension is derived
will get a default extension if the user does not supply one. The extension is derived
from the user's @racket[filters] choice if the corresponding pattern is
of the form @racket[(string-append "*." extension)]; if the pattern is
@racket["*.*"], then no default extension is added. Finally, if
of the form @racket[(string-append "*." _an-extension)], and the first such
pattern is used if the choice has multiple patterns. If the user's choice has the pattern
@racket["*.*"] and @racket[extension] is the empty string, then no default extension is added. Finally, if
@racket[extension] is any string other than the empty string,
@racket[extension] is used as the default extension when the user's
@racket[filters] choice has the pattern @racket["*.*"]. Meanwhile, the

View File

@ -183,6 +183,17 @@ Returns a line count installed with @method[editor-canvas%
}
@defmethod[(get-scroll-via-copy) boolean?]{
Returns @racket[#t] if scrolling triggers a copy of
the editor content (and then a refresh of the newly exposed
content). Returns @racket[#f] when scrolling triggers a
refresh of the entire editor canvas. Defaults to
@racket[#f].
See also @method[editor<%> on-scroll-to]
and @method[editor<%> after-scroll-to].
}
@defmethod*[([(horizontal-inset)
(integer-in 1 10000)]
[(horizontal-inset [step (integer-in 1 10000)])
@ -324,7 +335,7 @@ Enables or disables bottom-base scrolling, or gets the current enable
}
@defmethod[(set-editor [edit (or/c (or/c (is-a?/c text%) (is-a?/c pasteboard%)) #f)]
[redraw? any/c #t])
void?]{
@ -360,6 +371,10 @@ If the line count is set to @racket[#f], then the canvas's graphical
}
@defmethod[(set-scroll-via-copy [scroll-via-copy? any/c]) void?]{
Changes the scrolling mode refresh. See also @method[editor-canvas% get-scroll-via-copy].
}
@defmethod*[([(vertical-inset)
(integer-in 1 10000)]
[(vertical-inset [step (integer-in 1 10000)])

View File

@ -164,6 +164,20 @@ Does nothing.
}
}
@defmethod[(after-scroll-to) void?]{
@methspec{
Called when the editor has just scrolled, but the entire display
may not have been refreshed. (If the editor scrolls but the entire window
is redrawn, this method may not be called.)
See also @method[editor-canvas% get-scroll-via-copy].
}
@methimpl{Does nothing.}
}
@defmethod*[([(auto-wrap)
boolean?]
[(auto-wrap [auto-wrap? any/c])
@ -857,7 +871,7 @@ If @racket[bottom-right?] is not @racket[#f], the values in the
@racket[x] and @racket[y] boxes are for the snip's bottom right
corner instead of its top-left corner.
Obtaining the @techlink{location} if the bottom-right corner may
Obtaining the @techlink{location} of the bottom-right corner may
trigger delayed size calculations (including snips other than
the one whose @techlink{location} was requested).
@ -1656,6 +1670,17 @@ Does nothing.
}}
@defmethod[(on-scroll-to) void?]{
@methspec{
Called when the editor is about to scroll, but the entire display is
may not be refreshed. (If the editor scrolls but the entire window
is redrawn, this method may not be called.)
See also @method[editor-canvas% get-scroll-via-copy].
}
@methimpl{Does nothing.}
}
@defmethod[#:mode pubment
(on-snip-modified [snip (is-a?/c snip%)]
@ -2446,7 +2471,8 @@ See @xmethod[style-list% notify-on-change] for more information.
void?]{
Undoes the last editor change, if undos have been enabled by calling
@method[editor<%> set-max-undo-history] with a non-zero integer.
@method[editor<%> set-max-undo-history] with a non-zero integer or
@racket['forever].
If the editor is currently performing an undo or redo, the method call
is ignored.
@ -2462,7 +2488,7 @@ The system may perform an undo without calling this method in response
to other method calls. Use methods such as
@method[editor<%> on-change] to monitor editor content changes.
See also @method[editor<%> add-undo] .
See also @method[editor<%> add-undo].
}

View File

@ -124,6 +124,24 @@ If no argument is provided, the result is @racket[#t] if Option is
currently treated specially, @racket[#f] otherwise.
}
@defproc*[([(any-control+alt-is-altgr [on? any/c])
void?]
[(any-control+alt-is-altgr)
boolean?])]{
Enables or disables the treatment of any Control plus Alt as
equivalent to AltGr (Windows), as opposed to treating only a
left-hand Control plus a right-hand Alt (for keyboard configurations
that have both) as AltGr.
If @racket[on?] is provided as @racket[#f], key events are reported
normally. This setting affects all windows and eventspaces.
If no argument is provided, the result is @racket[#t] if Control plus Alt is
currently treated as AltGr, @racket[#f] otherwise.
@history[#:added "1.24"]}
@defproc[(queue-callback [callback (-> any)]
[high-priority? any/c #t])
void?]{

View File

@ -52,6 +52,7 @@ Both parts of the toolbox rely extensively on the
@include-section["prefs.scrbl"]
@include-section["dynamic.scrbl"]
@include-section["startup.scrbl"]
@include-section["init.scrbl"]
@include-section["libs.scrbl"]
@;------------------------------------------------------------------------

View File

@ -0,0 +1,30 @@
#lang scribble/doc
@(require "common.rkt"
(for-label racket/gui/dynamic racket/pretty racket/gui/base setup/dirs))
@title{Init Libraries}
@defmodule*/no-declare[(racket/gui/init)]{The
@racketmodname[racket/gui/init] library is the default start-up
library for GRacket. It re-exports the @racketmodname[racket/init] and
@racketmodname[racket/gui/base] libraries, and it sets
@racket[current-load] to use @racket[text-editor-load-handler].}
@defmodule*/no-declare[(racket/gui/interactive)]{
Similar to @racketmodname[racket/interactive], but for
GRacket. This library can be changed by modifying
@racket['gui-interactive-file] in the
@filepath{config.rktd} file in @racket[(find-config-dir)].
Additionally, if the file @filepath{gui-interactive.rkt}
exists in @racket[(find-system-path 'addon-dir)], it is run
rather than the installation wide graphical interactive
module.
This library runs the
@racket[(find-graphical-system-path 'init-file)] file in
the users home directory if it exists, rather than their
@racket[(find-system-path 'init-file)]. Unlike
@racketmodname[racket/interactive], this library does not
start @racketmodname[xrepl].
@history[#:added "1.27"]}

View File

@ -74,9 +74,11 @@ On Mac OS X, if a Control-key press is combined with a mouse button
boolean?]{
Returns @racket[#t] if a Control plus Meta event should be treated as
an AltGr event on Windows: the Control key was the left one and the
Alt key was the right one (typed that way on a keyboard with a right
Alt key, or produced by a single AltGr key).
an AltGr event on Windows. By default, AltGr treatment applies if the
Control key was the left one and the Alt key (as Meta) was the right one---typed
that way on a keyboard with a right Alt key, or produced by a single
AltGr key. See also @racket[any-control+alt-is-altgr], which controls
whether other Control plus Alt combinations are treated as AltGr.
@history[#:added "1.2"]}
@ -357,11 +359,11 @@ On Mac OS X, if a control-key press is combined with a mouse button
}
@defmethod[(control+meta-is-altgr [down? any/c])
@defmethod[(set-control+meta-is-altgr [down? any/c])
void?]{
Sets whether a Control plus Meta combination on Windows should be
treated as an AltGr combinations. See @racket[get-control+meta-is-altgr].
treated as an AltGr combinations. See @method[key-event% get-control+meta-is-altgr].
@history[#:added "1.2"]}

View File

@ -101,9 +101,13 @@ If @racket[try-chain?] is not @racket[#f], keymaps chained to this one
void?]{
Chains @racket[next] off @this-obj[] The @racket[next] keymap will be
used to handle events which are not handled by @this-obj[]. If
@racket[prefix?] is a true value, then @racket[next] will take
precedence over other keymaps already chained to @this-obj[].
used to handle events which are not handled by @this-obj[].
If @racket[prefix?] is a true value, then @racket[next] will take
precedence over other keymaps already chained to @this-obj[] in the
case that both keymaps map the same key sequence.
When one chained keymap maps a key that is a prefix of another, then the
shorter key sequence is always used, regardless of @racket[prefix?].
Multiple keymaps can be chained off one keymap using @method[keymap%
chain-to-keymap]. When keymaps are chained off a main keymap, events
@ -187,7 +191,7 @@ The modifier identifiers are:
@item{@litchar{l:} --- All platforms: Caps Lock}
@item{@litchar{g:} --- Windows: Control plus Alt as AltGr;
see @xmethod[key-event% control+meta-is-altgr]}
see @xmethod[key-event% get-control+meta-is-altgr]}
@item{@litchar{?:} --- All platforms: allow match to character produced by opposite
use of Shift, AltGr/Option, and/or Caps Lock, when available; see

View File

@ -19,5 +19,5 @@ either case:
@item{@filepath{libgtk-3.0[.0]} (GTK+ 3) or @filepath{libgtk-x11-2.0[.0]} (GTK+ 2)}
@item{@filepath{libgio-2.0[.0]} --- optional, for detecting interface scaling}
@item{@filepath{libGL[.1]} --- optional, for OpenGL support}
@item{@filepath{libunique-1.0[.0]} --- optional, for single-instance support}
@item{@filepath{libunique-1.0[.0]} --- optional, for single-instance support (GTK+ 2)}
]

View File

@ -322,26 +322,31 @@ Plays a sound file. If @racket[async?] is false, the function does not
The result is @racket[#t] if the sound plays successfully, @racket[#f]
otherwise.
On Windows, only @filepath{.wav} files are supported.
On Windows, MCI is used to play sounds, so file formats such as
@filepath{.wav} and @filepath{.mp3} should be supported.
On Unix, the function invokes an external sound-playing program;
looking for a few known programs (@exec{aplay}, @exec{play},
@exec{esdplay}, @exec{sndfile-play}, @exec{audioplay}). In addition, a
On Mac OS X, Quicktime is used to play sounds; most sound
formats (@filepath{.wav}, @filepath{.aiff}, @filepath{.mp3}) are supported in recent versions of
Quicktime. To play @filepath{.wav} files, Quicktime 3.0 (compatible
with OS 7.5 and up) is required.
On Unix, the function invokes an external sound-playing program---looking
by default for a few known programs (@exec{aplay}, @exec{play},
@exec{esdplay}, @exec{sndfile-play}, @exec{audioplay}). A
play command can be defined through the @ResourceFirst{playcmd}
preference (see @|mrprefsdiscuss|). The preference can hold a
program name, or a format string containing a single @litchar{~a}
where the filename should be substituted---and used as a shell
command. (Don't use @litchar{~s}, since the string that is used
with the format string will be properly quoted and wrapped in double
quotes.) A plain command name is usually better since execution is
quotes.) A plain command name is usually better, since execution is
faster. The command's output is discarded, unless it returns an
error code---in this case the last part of the error output is
error code, in which case the last part of the error output is
shown.
On Mac OS X, Quicktime is used to play sounds; most sound
formats (.wav, .aiff, .mp3) are supported in recent versions of
Quicktime. In order to play .wav files, Quicktime 3.0 (compatible
with OS 7.5 and up) is required.}
@history[#:changed "1.22" @elem{On Windows, added support for multiple
sounds at once and file format such as
@filepath{.mp3}.}]}
@defproc[(position-integer? [v any/c]) boolean?]{

View File

@ -24,8 +24,8 @@ A @racket[panel%] object has a degenerate placement strategy for
@defconstructor[([parent (or/c (is-a?/c frame%) (is-a?/c dialog%)
(is-a?/c panel%) (is-a?/c pane%))]
[style (listof (or/c 'border 'deleted
'hscroll 'auto-hscroll
'vscroll 'auto-vscroll)) null]
'hscroll 'auto-hscroll 'hide-hscroll
'vscroll 'auto-vscroll 'hide-vscroll)) null]
[enabled any/c #t]
[vert-margin spacing-integer? 0]
[horiz-margin spacing-integer? 0]
@ -47,14 +47,17 @@ If the @racket['hscroll] or @racket['vscroll] style is specified, then
the panel includes a scrollbar in the corresponding direction, and
the panel's own size in the corresponding direction is not
constrained by the size of its children subareas. The @racket['auto-hscroll]
and @racket['auto-vscroll] styles are like @racket['hscroll] or
@racket['vscroll], but they cause the corresponding scrollbar to
and @racket['auto-vscroll] styles imply @racket['hscroll] and
@racket['vscroll], respectively, but they cause the corresponding scrollbar to
disappear when no scrolling is needed in the corresponding direction;
the @racket['auto-vscroll] and @racket['auto-hscroll] modes assume that
children subareas are placed using the default algorithm for a @racket[panel%],
@racket[vertical-panel%], or @racket[horizontal-panel%].
@racket[vertical-panel%], or @racket[horizontal-panel%]. The @racket['hide-hscroll]
and @racket['hide-vscroll] styles imply @racket['auto-hscroll] and
@racket['auto-vscroll], respectively, but the corresponding scroll bar is never
made visible (while still allowing the panel content to exceed its own size).
@WindowKWs[@racket[enabled]] @SubareaKWs[] @AreaContKWs[] @AreaKWs[]
}}
@history[#:changed "1.25" @elem{Added @racket['hide-vscroll] and @racket['hide-hscroll].}]}}

View File

@ -312,6 +312,12 @@ following symbols:
not have the keyboard focus (see also
@method[snip% on-goodbye-event])}
@item{@indexed-racket['handles-between-events] --- this snip handles
mouse events that are between items in the snip
(instead of defaulting to treating mouse clicks as
setting the position or other event handling that happens
at the @racket[text%] or @racket[pasteboard%] level)}
@item{@indexed-racket['width-depends-on-x] --- this snip's display
width depends on the snip's x-@techlink{location} within the
editor; e.g.: tab}

View File

@ -0,0 +1,65 @@
#lang racket/base
(require racket/class
racket/snip
racket/format)
(provide circle-snip%
(rename-out [circle-snip-class snip-class]))
(define circle-snip%
(class snip%
(inherit set-snipclass
get-flags set-flags
get-admin)
(init-field [size 20.0])
(super-new)
(set-snipclass circle-snip-class)
(send (get-the-snip-class-list) add circle-snip-class)
(set-flags (cons 'handles-events (get-flags)))
(define/override (get-extent dc x y
[w #f]
[h #f]
[descent #f]
[space #f]
[lspace #f]
[rspace #f])
(define (maybe-set-box! b v) (when b (set-box! b v)))
(maybe-set-box! w (+ 2.0 size))
(maybe-set-box! h (+ 2.0 size))
(maybe-set-box! descent 1.0)
(maybe-set-box! space 1.0)
(maybe-set-box! lspace 1.0)
(maybe-set-box! rspace 1.0))
(define/override (draw dc x y left top right bottom dx dy draw-caret)
(send dc draw-ellipse (+ x 1.0) (+ y 1.0) size size))
(define/override (copy)
(new circle-snip% [size size]))
(define/override (write f)
(send f put size))
(define/override (on-event dc x y editorx editory e)
(when (send e button-down?)
(set! size (+ 1.0 size))
(define admin (get-admin))
(when admin
(send admin resized this #t))))))
(define circle-snip-class%
(class snip-class%
(inherit set-classname)
(super-new)
(set-classname (~s '((lib "main.rkt" "circle-snip")
(lib "wxme-circle-snip.rkt" "circle-snip"))))
(define/override (read f)
(define size-b (box 0.0))
(send f get size-b)
(new circle-snip% [size (unbox size-b)]))))
(define circle-snip-class (new circle-snip-class%))

View File

@ -1,5 +1,8 @@
#lang scribble/doc
@(require scribble/bnf "common.rkt")
@(require scribble/bnf
racket/runtime-path
(for-label wxme)
"common.rkt")
@title[#:tag "snip-example"]{Implementing New Snips}
@ -96,71 +99,25 @@ circle. Clicking on the snip causes the circle to grow. To enable
copying an instance of the snip from one program/eventspace to
another, the module should be @filepath{main.rkt} a
@filepath{circle-snip} directory that is installed as a
@filepath{circle-snip} package.
@filepath{circle-snip} package. The snip also has a @racketmodname[wxme]
reader implementation following it that must be installed as
the file @filepath{wxme-circle-snip.rkt} in the @filepath{circle-snip}
directory.
@codeblock{
#lang racket/base
(require racket/class
racket/snip
racket/format)
@(begin
(define-runtime-path snip-example.rkt "snip-example.rkt")
(define-runtime-path wxme-circle-snip.rkt "wxme-circle-snip.rkt")
(define (put-code filename)
(apply
typeset-code
#:context #'here
(call-with-input-file filename
(λ (port)
(for/list ([l (in-lines port)])
(format "~a\n" l))))))
(put-code snip-example.rkt))
(provide circle-snip%
(rename-out [circle-snip-class snip-class]))
This is the @filepath{wxme-circle-snip.rkt} file:
(define circle-snip%
(class snip%
(inherit set-snipclass
get-flags set-flags
get-admin)
(init-field [size 20.0])
@(put-code wxme-circle-snip.rkt))
(super-new)
(set-snipclass circle-snip-class)
(send (get-the-snip-class-list) add circle-snip-class)
(set-flags (cons 'handles-events (get-flags)))
(define/override (get-extent dc x y
[w #f]
[h #f]
[descent #f]
[space #f]
[lspace #f]
[rspace #f])
(define (maybe-set-box! b v) (when b (set-box! b v)))
(maybe-set-box! w (+ 2.0 size))
(maybe-set-box! h (+ 2.0 size))
(maybe-set-box! descent 1.0)
(maybe-set-box! space 1.0)
(maybe-set-box! lspace 1.0)
(maybe-set-box! rspace 1.0))
(define/override (draw dc x y left top right bottom dx dy draw-caret)
(send dc draw-ellipse (+ x 1.0) (+ y 1.0) size size))
(define/override (copy)
(new circle-snip% [size size]))
(define/override (write f)
(send f put size))
(define/override (on-event dc x y editorx editory e)
(when (send e button-down?)
(set! size (+ 1.0 size))
(define admin (get-admin))
(when admin
(send admin resized this #t))))))
(define circle-snip-class%
(class snip-class%
(inherit set-classname)
(super-new)
(set-classname (~s '(lib "main.rkt" "circle-snip")))
(define/override (read f)
(define size-b (box 0.0))
(send f get size-b)
(new circle-snip% [size (unbox size-b)]))))
(define circle-snip-class (new circle-snip-class%))
}

View File

@ -0,0 +1,97 @@
#lang racket/base
(require wxme ;; this is dynamically required
racket/gui/base
racket/file
racket/runtime-path
racket/port)
(define collection-name "circle-snip")
(define snip-example-name "main.rkt")
(define-runtime-path snip-example.rkt "snip-example.rkt")
(define-runtime-path wxme-circle-snip.rkt "wxme-circle-snip.rkt")
(define new-lib-coll-dir
(make-temporary-file "scribblings-gui-test-snip-example-~a"
'directory))
(dynamic-wind
void
(λ ()
(make-directory (build-path new-lib-coll-dir collection-name))
(copy-file snip-example.rkt
(build-path new-lib-coll-dir collection-name snip-example-name))
(copy-file wxme-circle-snip.rkt
(build-path new-lib-coll-dir collection-name "wxme-circle-snip.rkt"))
(define orig-namespace (current-namespace))
(parameterize ([current-library-collection-paths
(cons new-lib-coll-dir
(current-library-collection-paths))])
(define save-filename (build-path new-lib-coll-dir collection-name "circle.rkt"))
(define circle-snip-pos #f)
(define (get-circle-snip-pos) circle-snip-pos)
(define (set-circle-snip-pos p) (set! circle-snip-pos p))
(parameterize ([current-namespace (make-base-namespace)])
(namespace-attach-module orig-namespace 'mred/mred)
(define circle-snip% (dynamic-require `(lib ,snip-example-name ,collection-name)
'circle-snip%))
(eval '(require racket/gui/base racket/class racket/format))
(eval
`(let ()
(define circle-snip% ,circle-snip%)
(define t (new text%))
(send t insert "#lang racket/base\n")
(send t insert "(define s ")
(,set-circle-snip-pos (send t last-position))
(send t insert (new circle-snip%))
(send t insert ")\n")
(send t insert (~s `(provide s)))
(send t save-file ,save-filename)
(send t set-filename #f)
(define t2 (new text%))
(send t2 set-filename ,save-filename)
(send t2 load-file)
(define circle-snip-copy (send t find-snip (,get-circle-snip-pos) 'after))
(unless (is-a? circle-snip-copy circle-snip%)
(error 'test-snip-example.rtk "didnt find circle snip.1, found ~s"
circle-snip-copy))
(define gui-loaded (dynamic-require ,save-filename 's))
(unless (is-a? gui-loaded circle-snip%)
(error 'test-snip-example.rkt "didnt find circle snip.2, found ~s"
gui-loaded)))))
(parameterize ([current-namespace (make-base-namespace)])
(namespace-attach-module orig-namespace 'mred/mred)
(define loaded (format "~s" (dynamic-require save-filename 's)))
(unless (regexp-match #rx"struct:object:circle-snip%" loaded)
(error 'test-snip-example.rkt "didn't find circle snip.3, found ~s" loaded)))
(define wxme-text-content
(parameterize ([current-namespace (make-base-namespace)])
(eval '(require racket/base wxme))
(eval
`(call-with-input-file ,save-filename
(λ (port)
(apply
string
(for/list ([s (in-input-port-chars (wxme-port->text-port port))])
s)))))))
(unless (regexp-match #rx"[(]circle [0-9.]+[)]" wxme-text-content)
(error 'test-snip-example.rkt "didn't find circle snip.4 ~s" wxme-text-content))
(define wxme-content-as-pos
(parameterize ([current-namespace (make-base-namespace)])
(eval '(require racket/base wxme))
(eval
`(call-with-input-file ,save-filename
(λ (port)
(port-count-lines! port)
(for/or ([s (in-port read-char-or-special
(wxme-port->port port))])
(and (syntax? s)
(list (syntax-position s)))))))))
(unless (equal? (list (+ circle-snip-pos 1)) wxme-content-as-pos)
(error 'test-snip-example.rkt "didn't find circle snip.5 ~s vs ~s"
wxme-content-as-pos
circle-snip-pos))))
(λ ()
(delete-directory/files new-lib-coll-dir)))

View File

@ -850,13 +850,13 @@ Returns the ending @techlink{position} of the current selection. See
@defmethod[(get-extend-start-position) exact-nonnegative-integer?]{
Returns the beginning of the ``extend'' region if the selection
is currently being extended via, e.g., shift and a cursor movement key;
otherwise returns the same value as @method[text% get-end-position].
otherwise returns the same value as @method[text% get-start-position].
}
@defmethod[(get-extend-end-position) exact-nonnegative-integer?]{
Returns the beginning of the ``extend'' region if the selection
is currently being extended via, e.g., shift and a cursor movement key;
otherwise returns the same value as @method[text% get-start-position].
otherwise returns the same value as @method[text% get-end-position].
}
@defmethod[(get-file-format)

View File

@ -998,7 +998,7 @@ animation frame with @method[canvas<%> suspend-flush] and
are not flushed to the screen. Use @method[canvas<%> flush] to ensure
that canvas content is flushed when it is ready if a @method[canvas<%>
suspend-flush] will soon follow, because the process of flushing to
the screen can be starved if flushing is frequently suspend. The
the screen can be starved if flushing is frequently suspended. The
method @xmethod[canvas% refresh-now] conveniently encapsulates this
sequence.

View File

@ -65,7 +65,9 @@ If @racket[enable?] is true, the window is enabled, otherwise it is
@index['("keyboard focus" "setting")]{Moves} the keyboard focus to the
window, relative to its top-level window, if the window ever accepts
the keyboard focus. If the focus is in the window's top-level
window, then the focus is immediately moved to this
window or if the window's top-level window is visible and floating
(i.e., created with the @racket['float] style), then the focus is
immediately moved to this
window. Otherwise, the focus is not immediately moved, but when the
window's top-level window gets the keyboard focus, the focus is
delegated to this window.

View File

@ -0,0 +1,34 @@
#lang racket/base
(require racket/class
racket/format
wxme
pict)
(provide reader)
(define circle-reader%
(class* object% (snip-reader<%>)
(define/public (read-header version stream) (void))
(define/public (read-snip text-only? version stream)
(define size (send stream read-inexact "circle-snip"))
(cond
[text-only?
(string->bytes/utf-8 (~s `(circle ,size)))]
[else
(new circle-readable [size size])]))
(super-new)))
(define circle-readable
(class* object% (readable<%>)
(init-field size)
(define/public (read-special source line column position)
;; construct a syntax object holding a 3d value that
;; is a circle from the pict library with an appropriate
;; source location
(datum->syntax #f
(circle size)
(vector source line column position 1)
#f))
(super-new)))
(define reader (new circle-reader%))

View File

@ -107,7 +107,8 @@ contains only alpha-numeric ASCII characters, @litchar{.},
@defproc[(string->lib-path [str string?] [gui? any/c])
(cons/c 'lib (listof string?))]{
(or/c (cons/c 'lib (listof string?))
#f)]{
Returns a quoted module path for @racket[str] for either
@racket[editor<%>] mode when @racket[gui?] is true, or

View File

@ -183,6 +183,14 @@
(v)
@{Recognizes the result of @racket[text:make-snip-special].})
(proc-doc/names
text:send-snip-to-port
(-> (is-a?/c snip%) output-port? void?)
(snip port)
@{Sends @racket[snip] to @racket[port] by using @racket[text:make-snip-special],
handling a few special cases for performance and backwards compatibility
reasons.})
(proc-doc/names
number-snip:make-repeating-decimal-snip
(real? boolean? . -> . (is-a?/c snip%))

View File

@ -58,8 +58,7 @@ the state transitions / contracts are:
(define (pref-un/marshall-set? pref) (hash-has-key? marshall-unmarshall pref))
(define (preferences:default-set? pref) (hash-has-key? defaults pref))
(define (pref-can-init? pref)
(and (not snapshot-grabbed?)
(not (hash-has-key? preferences pref))))
(not (hash-has-key? preferences pref)))
;; type un/marshall = (make-un/marshall (any -> prinable) (printable -> any))
(define-struct un/marshall (marshall unmarshall))
@ -343,9 +342,7 @@ the state transitions / contracts are:
value))))
(define-struct preferences:snapshot (x))
(define snapshot-grabbed? #f)
(define (preferences:get-prefs-snapshot)
(set! snapshot-grabbed? #t)
(make-preferences:snapshot
(hash-map defaults
(λ (k v) (cons k (copy-pref-value k (preferences:get k)))))))
@ -374,12 +371,12 @@ the state transitions / contracts are:
(symbol value)
@{Sets the preference
@racket[symbol] to @racket[value]. It should be called when the
users requests a change to a preference.
user requests a change to a preference.
@racket[preferences:set] immediately writes the preference value to disk.
It raises an exception matching
@racket[exn:unknown-preference?]
if the preference's default has not been set.
if the preference's default has not been set
See also @racket[preferences:set-default].})
@ -389,7 +386,9 @@ the state transitions / contracts are:
(pref)
@{Returns a procedure that when applied to zero arguments retrieves the
current value of the preference named @racket[pref] and when
applied to one argument updates the preference named @racket[pref].})
applied to one argument updates the preference named @racket[pref].
@history[#:added "1.18"]{}})
(proc-doc/names
preferences:add-callback
@ -404,7 +403,9 @@ the state transitions / contracts are:
invoked, removes the callback from this preference.
If @racket[weak?] is true, the preferences system will only hold on to
the callback weakly.
the callback
@tech[#:key "weak references"
#:doc '(lib "scribblings/reference/reference.scrbl")]{weakly}.
The callbacks will be called in the order in which they were added.
@ -415,7 +416,8 @@ the state transitions / contracts are:
This function raises an exception matching
@racket[exn:unknown-preference?]
if the preference has not been set.})
if the preference default has not been set via
@racket[preferences:set-default].})
(proc-doc/names
preferences:set-default
(->* (symbol? any/c (any/c . -> . any))
@ -433,6 +435,8 @@ the state transitions / contracts are:
This sets the default value of the preference @racket[symbol] to
@racket[value]. If the user has chosen a different setting,
(reflected via a call to @racket[preferences:set], possibly
in a different run of your program),
the user's setting will take precedence over the default value.
The @racket[test] argument is used as a safeguard. That function is
@ -446,7 +450,11 @@ the state transitions / contracts are:
expected to be a list of symbols that correspond to old versions
of the preferences. It defaults to @racket['()]. If @racket[rewrite-aliases]
is present, it is used to adjust the old values of the preferences
when they are present in the saved file.})
when they are present in the saved file.
@history[#:changed "1.23" @list{Allow @racket[preferences:set-default]
to be called even after a snapshot has been grabbed.}]
})
(proc-doc/names
preferences:default-set?
@ -562,7 +570,9 @@ the state transitions / contracts are:
preferences:restore-prefs-snapshot
(-> preferences:snapshot? void?)
(snapshot)
@{Restores the preferences saved in @racket[snapshot].
@{Restores the preferences saved in @racket[snapshot], updating
all of the preferences values to the ones they had at the time
that @racket[preferences:get-prefs-snapshot] was called.
See also @racket[preferences:get-prefs-snapshot].})
@ -570,7 +580,7 @@ the state transitions / contracts are:
preferences:get-prefs-snapshot
(-> preferences:snapshot?)
()
@{Caches all of the current values of the preferences and returns them.
@{Caches all of the current values of the known preferences and returns them.
For any preference that has marshalling and unmarshalling set
(see @racket[preferences:set-un/marshall]), the preference value is
copied by passing it through the marshalling and unmarshalling process.

View File

@ -95,6 +95,7 @@
(define aspell-proc #f)
(define already-attempted-aspell? #f)
(define current-dict #f)
(define is-actually-aspell? #f)
(define (fire-up-aspell)
(unless already-attempted-aspell?
@ -105,6 +106,8 @@
(define line (with-handlers ((exn:fail? exn-message))
(read-line (list-ref aspell-proc 0))))
(asp-log (format "framework: started speller: ~a" line))
(when (regexp-match? #rx"[Aa]spell" line)
(set! is-actually-aspell? #t))
(when (and (string? line)
(regexp-match #rx"[Aa]spell" line))
@ -129,7 +132,12 @@
(close-output-port (list-ref aspell-proc 1))
(close-input-port (list-ref aspell-proc 3))
(proc 'kill)
(set! aspell-proc #f))
(set! aspell-proc #f)
(set! is-actually-aspell? #f))
(define (is-ascii? l)
(for/and ([s (in-string l)])
(<= (char->integer s) 127)))
(let loop ()
(sync
@ -147,7 +155,9 @@
(sync (channel-put-evt resp-chan resp)
nack-evt))
(cond
[aspell-proc
[(and aspell-proc
(or is-actually-aspell?
(is-ascii? line)))
(define stdout (list-ref aspell-proc 0))
(define stdin (list-ref aspell-proc 1))

View File

@ -769,7 +769,8 @@ added get-regions
(clear-old-locations)
(set! clear-old-locations void)
(when (and (preferences:get 'framework:highlight-parens)
(not just-clear?))
(not just-clear?)
(not stopped?))
(let* ((here (get-start-position)))
(when (= here (get-end-position))
(let ([ls (find-ls here)])

View File

@ -8,7 +8,9 @@
"interfaces.rkt"
mzlib/etc
mred/mred-sig
racket/path)
racket/path
racket/contract
racket/format)
(import mred^
[prefix autosave: framework:autosave^]
@ -745,3 +747,81 @@
#f))))
'framework:update-lock-icon))
(super-new)))
(define font-size-message%
(class canvas%
(init message
[stretchable-height #f])
(init-field [text-alignment 'center])
(define msgs
(cond
[(string? message) (regexp-split #rx"\n" message)]
[((listof string?) message) message]
[else
(raise-argument-error 'editor:font-size-message%
(~s '(or/c string? (listof string?)))
message)]))
(unless (member text-alignment '(left center right))
(raise-argument-error 'editor:font-size-message%
(~s '(or/c 'left 'center 'right))
text-alignment))
(inherit refresh get-dc get-client-size popup-menu)
(define/public (set-message message)
(set! msgs
(cond
[(string? message) (regexp-split #rx"\n" message)]
[((listof string?) message) message]
[else
(raise-argument-error 'editor:font-size-message%::set-label
(~s '(or/c string? (listof string?)))
message)]))
(refresh))
(define/override (on-paint)
(define dc (get-dc))
(define-values (cw ch) (get-client-size))
(define-values (tot-th tot-tw)
(for/fold ([tot-th 0] [tot-tw 0])
([msg (in-list msgs)])
(define-values (tw th td ta) (send dc get-text-extent msg))
(values (+ tot-th th) (max tot-tw tw))))
(for/fold ([y (- (/ ch 2) (/ tot-th 2))]) ([msg (in-list msgs)])
(define-values (tw th td ta) (send dc get-text-extent msg))
(define x
(case text-alignment
[(center) (- (/ cw 2) (/ tw 2))]
[(left) 2]
[(right) (- cw 2)]))
(send dc draw-text msg x y)
(+ y th)))
(super-new [style '(transparent)][stretchable-height stretchable-height])
;; need object to hold onto this function, so this is
;; intentionally a private field, not a method
(define (font-size-changed-callback _ new-prefs)
(define new-size (font-size-pref->current-font-size new-prefs))
(set-the-height/dc-font new-size)
(refresh))
(preferences:add-callback
'framework:standard-style-list:font-size
font-size-changed-callback
#t)
(define/private (set-the-height/dc-font font-size)
(define dc (get-dc))
(send dc set-font
(send the-font-list find-or-create-font
font-size
(send normal-control-font get-family)
(send normal-control-font get-style)
(send normal-control-font get-weight)
(send normal-control-font get-underlined)
(send normal-control-font get-smoothing)))
(define tot-th
(for/sum ([msg (in-list msgs)])
(define-values (tw th td ta) (send dc get-text-extent msg))
th))
(min-height (inexact->exact (ceiling tot-th))))
(inherit min-height)
(set-the-height/dc-font
(get-current-preferred-font-size))))

View File

@ -1118,6 +1118,29 @@
[define anchor-last-state? #f]
[define overwrite-last-state? #f]
(define/private (update-ascii-art-enlarge-msg)
(define ascii-art-enlarge-mode?
(let ([e (get-info-editor)])
(and (is-a? e text:ascii-art-enlarge-boxes<%>)
(send e get-ascii-art-enlarge))))
(unless (eq? (and (member ascii-art-enlarge-mode-msg (send uncommon-parent get-children)) #t)
ascii-art-enlarge-mode?)
(if ascii-art-enlarge-mode?
(add-uncommon-child ascii-art-enlarge-mode-msg)
(remove-uncommon-child ascii-art-enlarge-mode-msg))))
;; this callback is kind of a hack. we know that when the set-ascii-art-enlarge
;; method of text:ascii-art-enlarge<%> is called that it changes the preferences
;; value so we will get called back here; it would be better if we could just
;; have the callback happen directly by overriding that method, but that causes
;; backwards incompatibility problems.
(define callback (λ (p v)
(queue-callback
(λ () (update-ascii-art-enlarge-msg))
#f)))
(preferences:add-callback 'framework:ascii-art-enlarge callback #t)
(field (macro-recording? #f))
(define/private (update-macro-recording-icon)
@ -1193,6 +1216,7 @@
(define/override (update-info)
(super update-info)
(update-macro-recording-icon)
(update-ascii-art-enlarge-msg)
(overwrite-status-changed)
(anchor-status-changed)
(editor-position-changed)
@ -1233,6 +1257,11 @@
(send (get-info-panel) change-children
(λ (l) (cons uncommon-parent (remq uncommon-parent l))))
(define ascii-art-enlarge-mode-msg (new message%
[parent uncommon-parent]
[label "╠╬╣"]
[auto-resize #t]))
(define anchor-message
(new message%
[font small-control-font]
@ -1254,6 +1283,7 @@
(define/private (add-uncommon-child c)
(define (child->num c)
(cond
[(eq? c ascii-art-enlarge-mode-msg) -1]
[(eq? c anchor-message) 0]
[(eq? c overwrite-message) 1]
[(eq? c macro-recording-message) 2]))
@ -2053,10 +2083,13 @@
(let* ([string (get-text)]
[top-searching-edit (get-searching-text)])
(when top-searching-edit
(let ([searching-edit (let ([focus-snip (send top-searching-edit get-focus-snip)])
(if (and focus-snip (is-a? focus-snip editor-snip%))
(send focus-snip get-editor)
top-searching-edit))]
(let ([searching-edit
(let loop ([txt top-searching-edit])
(define focus-snip (send txt get-focus-snip))
(cond
[(and focus-snip (is-a? focus-snip editor-snip%))
(loop (send focus-snip get-editor))]
[else txt]))]
[not-found
(λ (found-edit skip-beep?)
@ -2382,11 +2415,12 @@
(define/public-final (search-string-changed) (search-parameters-changed))
(define/private (search-parameters-changed)
(let ([str (send find-edit get-text)])
(send text-to-search set-searching-state
(if (equal? str "") #f str)
case-sensitive-search?
replace-visible?
#t)))
(when text-to-search
(send text-to-search set-searching-state
(if (equal? str "") #f str)
case-sensitive-search?
replace-visible?
#t))))
(define/public (search-hidden?) hidden?)
@ -2418,6 +2452,10 @@
(when focus?
(send find-edit set-position 0 (send find-edit last-position))
(send (send find-edit get-canvas) focus))
(let ([c (send find-edit get-canvas)])
(when (and c (send c get-line-count))
;; try to update the canvas so that the font size is correctly accounted for
(send c set-editor (send c get-editor))))
(send find-edit end-edit-sequence)))
(define/public (unhide-search-and-toggle-focus #:new-search-string-from-selection? [new-search-string-from-selection? #f])

View File

@ -180,7 +180,12 @@
`(@defmethod[(,(between->name x) [menu (is-a?/c menu-item%)]) void?]{
This method is called between the addition of the
@tt[,(format "~a" (between-before x))] and the @tt[,(format "~a" (between-after x))] menu-item.
Override it to add additional menu items at that point. })]
Override it to add additional menu items at that point.
@unquote[(if (equal? (between-procedure x) 'separator)
`@list{Defaults to creating a @racket[separator-menu-item%].}
"")]
})]
[(an-item? x)
`(@defmethod[(,(an-item->get-item-name x)) (or/c false/c (is-a?/c menu-item%))]{
This method returns the @racket[menu-item%] object corresponding

View File

@ -173,10 +173,23 @@
;; install-recent-items : (is-a?/c menu%) -> void?
(define (install-recent-items menu)
;; sometimes, we get here via an on-demand callback
;; and we run out of time during the callback and
;; things go awry with the menu. So, to hack around
;; that problem, lets try to do it twice; once here
;; when we notice that things are wrong, and then once
;; in a later event callback, when we know we won't run
;; afoul of any time limits.
(do-install-recent-items menu)
(queue-callback (λ () (do-install-recent-items menu)) #f)
(void))
(define (do-install-recent-items menu)
(define recently-opened-files
(preferences:get
'framework:recently-opened-files/pos))
(define (update-menu-with-new-stuff)
(unless (menu-items-still-same? recently-opened-files menu)
(for ([item (send menu get-items)]) (send item delete))
(for ([recent-list-item recently-opened-files])
@ -188,20 +201,7 @@
(new menu-item%
[parent menu]
[label (string-constant show-recent-items-window-menu-item)]
[callback (λ (x y) (show-recent-items-window))]))
(unless (menu-items-still-same? recently-opened-files menu)
;; sometimes, we get here via an on-demand callback
;; and we run out of time during the callback and
;; things go awry with the menu. So, to hack around
;; that problem, lets try to do it twice; once here
;; when we notice that things are wrong, and then once
;; later, when we know we won't run afoul of any time
;; limits.
(queue-callback (λ () (update-menu-with-new-stuff)) #f)
(update-menu-with-new-stuff))
(void))
[callback (λ (x y) (show-recent-items-window))])))
(define (recent-list-item->menu-label recent-list-item)
(let ([filename (car recent-list-item)])

View File

@ -9,7 +9,8 @@
frame:basic<%>
frame:standard-menus<%>
frame:info<%>
frame:text-info<%>)
frame:text-info<%>
text:ascii-art-enlarge-boxes<%>)
(define editor:basic<%>
(interface (editor<%>)
@ -32,6 +33,12 @@
(interface (editor:basic<%>)
get-keymaps))
(define text:ascii-art-enlarge-boxes<%>
(interface ()
set-ascii-art-enlarge
get-ascii-art-enlarge))
(define text:basic<%>
(interface (editor:basic<%> (class->interface text%))
highlight-range

View File

@ -6,6 +6,7 @@
"interfaces.rkt"
"../preferences.rkt"
"gen-standard-menus.rkt"
"unicode-ascii-art.rkt"
(only-in srfi/13 string-prefix? string-prefix-length)
2d/dir-chars
racket/list)
@ -708,6 +709,17 @@
(define start (send txt get-start-position))
(when (= start (send txt get-end-position))
(widen-unicode-ascii-art-box txt start)))]
[heighten-unicode-ascii-art-box
(λ (txt evt)
(define start (send txt get-start-position))
(when (= start (send txt get-end-position))
(heighten-unicode-ascii-art-box txt start)))]
[toggle-unicode-ascii-art-enlarge-mode
(λ (txt evt)
(when (is-a? txt text:ascii-art-enlarge-boxes<%>)
(send txt set-ascii-art-enlarge (not (send txt get-ascii-art-enlarge)))))]
[center-in-unicode-ascii-art-box
(λ (txt evt)
@ -740,6 +752,8 @@
(add "normalize-unicode-ascii-art-box" normalize-unicode-ascii-art-box)
(add "widen-unicode-ascii-art-box" widen-unicode-ascii-art-box)
(add "heighten-unicode-ascii-art-box" heighten-unicode-ascii-art-box)
(add "toggle-unicode-ascii-art-enlarge-mode" toggle-unicode-ascii-art-enlarge-mode)
(add "center-in-unicode-ascii-art-box" center-in-unicode-ascii-art-box)
(add "shift-focus" (shift-focus values))
(add "shift-focus-backwards" (shift-focus reverse))
@ -836,7 +850,9 @@
(map "c:x;r;a" "normalize-unicode-ascii-art-box")
(map "c:x;r;w" "widen-unicode-ascii-art-box")
(map "c:x;r;v" "highten-unicode-ascii-art-box")
(map "c:x;r;c" "center-in-unicode-ascii-art-box")
(map "c:x;r;o" "toggle-unicode-ascii-art-enlarge-mode")
(map "~m:c:\\" "TeX compress")
(map "~c:m:\\" "TeX compress")
@ -1027,166 +1043,6 @@
(f click-pos eol start-pos click-pos)
(f click-pos eol click-pos end-pos))))
(define (widen-unicode-ascii-art-box t orig-pos)
(define start-pos (scan-for-start-pos t orig-pos))
(when start-pos
(send t begin-edit-sequence)
(define-values (start-x start-y) (pos->xy t orig-pos))
(define min-y #f)
(define max-y #f)
(trace-unicode-ascii-art-box
t start-pos #f
(λ (pos x y i-up? i-dn? i-lt? i-rt?)
(when (= x start-x)
(unless min-y
(set! min-y y)
(set! max-y y))
(set! min-y (min y min-y))
(set! max-y (max y max-y)))))
(define to-adjust 0)
(for ([y (in-range max-y (- min-y 1) -1)])
(define-values (pos char) (xy->pos t start-x y))
(when (< pos start-pos)
(set! to-adjust (+ to-adjust 1)))
(send t insert
(cond
[(member char lt-chars) #\═]
[else #\space])
pos pos))
(send t set-position (+ orig-pos to-adjust 1) (+ orig-pos to-adjust 1))
(send t end-edit-sequence)))
(define (normalize-unicode-ascii-art-box t pos)
(define start-pos (scan-for-start-pos t pos))
(when start-pos
(send t begin-edit-sequence)
(trace-unicode-ascii-art-box
t start-pos #f
(λ (pos x y i-up? i-dn? i-lt? i-rt?)
(cond
[(and i-up? i-dn? i-lt? i-rt?) (set-c t pos "")]
[(and i-dn? i-lt? i-rt?) (set-c t pos "")]
[(and i-up? i-lt? i-rt?) (set-c t pos "")]
[(and i-up? i-dn? i-rt?) (set-c t pos "")]
[(and i-up? i-dn? i-lt?) (set-c t pos "")]
[(and i-up? i-lt?) (set-c t pos "")]
[(and i-up? i-rt?) (set-c t pos "")]
[(and i-dn? i-lt?) (set-c t pos "")]
[(and i-dn? i-rt?) (set-c t pos "")]
[(or i-up? i-dn?) (set-c t pos "")]
[else (set-c t pos "")])))
(send t end-edit-sequence)))
(define (center-in-unicode-ascii-art-box txt insertion-pos)
(define (find-something start-pos inc char-p?)
(define-values (x y) (pos->xy txt start-pos))
(let loop ([pos start-pos])
(cond
[(char-p? (send txt get-character pos))
pos]
[else
(define new-pos (inc pos))
(cond
[(<= 0 new-pos (send txt last-position))
(define-values (x2 y2) (pos->xy txt new-pos))
(cond
[(= y2 y)
(loop new-pos)]
[else #f])]
[else #f])])))
(define (adjust-space before-space after-space pos)
(cond
[(< before-space after-space)
(send txt insert (make-string (- after-space before-space) #\space) pos pos)]
[(> before-space after-space)
(send txt delete pos (+ pos (- before-space after-space)))]))
(define left-bar (find-something insertion-pos sub1 (λ (x) (equal? x #\║))))
(define right-bar (find-something insertion-pos add1 (λ (x) (equal? x #\║))))
(when (and left-bar right-bar (< left-bar right-bar))
(define left-space-edge (find-something (+ left-bar 1) add1 (λ (x) (not (char-whitespace? x)))))
(define right-space-edge (find-something (- right-bar 1) sub1 (λ (x) (not (char-whitespace? x)))))
(when (and left-space-edge right-space-edge)
(define before-left-space-count (- left-space-edge left-bar 1))
(define before-right-space-count (- right-bar right-space-edge 1))
(define tot-space (+ before-left-space-count before-right-space-count))
(define after-left-space-count (floor (/ tot-space 2)))
(define after-right-space-count (ceiling (/ tot-space 2)))
(send txt begin-edit-sequence)
(adjust-space before-right-space-count after-right-space-count (+ right-space-edge 1))
(adjust-space before-left-space-count after-left-space-count (+ left-bar 1))
(send txt end-edit-sequence))))
(define (trace-unicode-ascii-art-box t start-pos only-double-barred-chars? f)
(define visited (make-hash))
(let loop ([pos start-pos])
(unless (hash-ref visited pos #f)
(hash-set! visited pos #t)
(define-values (x y) (pos->xy t pos))
(define c (send t get-character pos))
(define-values (up upc) (xy->pos t x (- y 1)))
(define-values (dn dnc) (xy->pos t x (+ y 1)))
(define-values (lt ltc) (xy->pos t (- x 1) y))
(define-values (rt rtc) (xy->pos t (+ x 1) y))
(define (interesting-dir? dir-c dir-chars)
(or (and (not only-double-barred-chars?)
(member dir-c adjustable-chars)
(member c dir-chars))
(and (member dir-c double-barred-chars)
(member c double-barred-chars))))
(define i-up? (interesting-dir? upc up-chars))
(define i-dn? (interesting-dir? dnc dn-chars))
(define i-lt? (interesting-dir? ltc lt-chars))
(define i-rt? (interesting-dir? rtc rt-chars))
(f pos x y i-up? i-dn? i-lt? i-rt?)
(when i-up? (loop up))
(when i-dn? (loop dn))
(when i-lt? (loop lt))
(when i-rt? (loop rt)))))
(define (scan-for-start-pos t pos)
(define-values (x y) (pos->xy t pos))
(findf
(λ (p) (adj? t p))
(for*/list ([xadj '(0 -1)]
[yadj '(0 -1 1)])
(define-values (d dc) (xy->pos t (+ x xadj) (+ y yadj)))
d)))
(define (adj? t pos)
(and pos
(member (send t get-character pos)
adjustable-chars)))
(define (set-c t pos s)
(unless (equal? (string-ref s 0) (send t get-character pos))
(send t delete pos (+ pos 1))
(send t insert s pos pos)))
(define (pos->xy text pos)
(define para (send text position-paragraph pos))
(define start (send text paragraph-start-position para))
(values (- pos start) para))
(define (xy->pos text x y)
(cond
[(and (<= 0 x) (<= 0 y (send text last-paragraph)))
(define para-start (send text paragraph-start-position y))
(define para-end (send text paragraph-end-position y))
(define pos (+ para-start x))
(define res-pos
(and (< pos para-end)
;; the newline at the end of the
;; line is not on the line, so use this guard
pos))
(if res-pos
(values res-pos (send text get-character res-pos))
(values #f #f))]
[else (values #f #f)]))
(define/contract (run-some-keystrokes before key-evts)
(-> (list/c string? exact-nonnegative-integer? exact-nonnegative-integer?)
(listof (is-a?/c key-event%))
@ -1204,182 +1060,7 @@
(send t get-end-position)))
(module+ test
(require rackunit
racket/gui/base)
(define sa string-append)
(define (first-value-xy->pos a b c)
(define-values (d e) (xy->pos a b c))
d)
(let ([t (new text%)])
(send t insert (sa "abc\n"
"d\n"
"ghi\n"))
(check-equal? (first-value-xy->pos t 0 0) 0)
(check-equal? (first-value-xy->pos t 1 0) 1)
(check-equal? (first-value-xy->pos t 0 1) 4)
(check-equal? (first-value-xy->pos t 3 0) #f)
(check-equal? (first-value-xy->pos t 0 3) #f)
(check-equal? (first-value-xy->pos t 1 1) #f)
(check-equal? (first-value-xy->pos t 2 1) #f)
(check-equal? (first-value-xy->pos t 0 2) 6)
(check-equal? (first-value-xy->pos t 1 2) 7)
(check-equal? (first-value-xy->pos t 2 -1) #f)
(check-equal? (first-value-xy->pos t -1 0) #f)
(check-equal? (first-value-xy->pos t 2 2) 8)
(check-equal? (first-value-xy->pos t 2 3) #f))
(let ([t (new text%)])
(send t insert (sa "abc\n"
"d\n"
"ghi"))
(check-equal? (first-value-xy->pos t 2 2) 8)
(check-equal? (first-value-xy->pos t 2 3) #f))
(let ([t (new text%)])
(send t insert (string-append "+-+\n"
"| |\n"
"+-+\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═╗\n"
"║ ║\n"
"╚═╝\n")))
(let ([t (new text%)])
(send t insert (string-append "+=+\n"
"| |\n"
"+=+\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═╗\n"
"║ ║\n"
"╚═╝\n")))
(let ([t (new text%)])
(send t insert (string-append "+-+-+\n"
"| | |\n"
"+-+-+\n"
"| | |\n"
"+-+-+\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═══╗\n"
"║ - ║\n"
"╚═══╝\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═══╗\n"
"║ - ║\n"
"╚═══╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n"))
(send t set-position 1 1)
(widen-unicode-ascii-art-box t 1)
(check-equal? (send t get-start-position) 2)
(check-equal? (send t get-text)
(string-append
"╔══╦═╗\n"
"║ ║ ║\n"
"╠══╬═╣\n"
"║ ║ ║\n"
"╚══╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n"))
(send t set-position 8 8)
(widen-unicode-ascii-art-box t 8)
(check-equal? (send t get-start-position) 10)
(check-equal? (send t get-text)
(string-append
"╔══╦═╗\n"
"║ ║ ║\n"
"╠══╬═╣\n"
"║ ║ ║\n"
"╚══╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"))
(send t set-position 8 8)
(widen-unicode-ascii-art-box t 8)
(check-equal? (send t get-text)
(string-append
"╔══╦═╗\n"
"║ ║ ║\n"
"╠══╬═╣\n"
"║ ║ ║\n")))
(let ([t (new text%)])
(send t insert "║ x ║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║ x ║\n"))
(let ([t (new text%)])
(send t insert "║x ║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║ x ║\n"))
(let ([t (new text%)])
(send t insert "║ x║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║ x ║\n"))
(let ([t (new text%)])
(send t insert "║abcde║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║abcde║\n"))
(let ([t (new text%)])
(send t insert "║║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║║\n"))
(let ([t (new text%)])
(send t insert "║abcde \n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║abcde \n"))
(let ([t (new text%)])
(send t insert " abcde║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
" abcde║\n"))
(require rackunit)
(check-equal? (run-some-keystrokes '("abc" 0 0)
(list (new key-event% [key-code 'escape])
(new key-event% [key-code #\c])))

View File

@ -148,7 +148,38 @@
(hash-set! function-table (string->symbol keyname) fname))
(define/public (get-map-function-table)
(get-map-function-table/ht (make-hasheq)))
(define table-possibly-with-prefixes (get-map-function-table/ht (make-hasheq)))
(define trie (make-hash))
(define (add-to-trie loks name)
(let loop ([trie trie]
[loks loks])
(cond
[(null? (cdr loks))
(hash-set! trie (car loks) name)]
[else
(define sub (hash-ref trie (car loks)
(λ ()
(define h (make-hash))
(hash-set! trie (car loks) h)
h)))
(loop sub (cdr loks))])))
(for ([(canonicalized-symbol keyname) (in-hash table-possibly-with-prefixes)])
(define keys (regexp-split #rx";" (symbol->string canonicalized-symbol)))
(add-to-trie keys keyname))
(define table-without-prefixes (make-hash))
(let loop ([trie trie]
[prefix '()])
(cond
[(string? trie)
(define keystring (string->symbol (join-strings ";" (reverse prefix))))
(hash-set! table-without-prefixes keystring trie)]
[else (for ([(key sub-trie) (in-hash trie)])
(loop sub-trie (cons key prefix)))]))
table-without-prefixes)
(define/public (get-map-function-table/ht table)
(for ([(keyname fname) (in-hash function-table)])
@ -194,7 +225,7 @@
(define/private (all-but-last l)
(cond
[(null? l) l]
[(null? (cdr l)) l]
[(null? (cdr l)) '()]
[else (cons (car l) (all-but-last (cdr l)))]))
(super-new)))

View File

@ -25,6 +25,8 @@
(application-preferences-handler (λ () (preferences:show-dialog)))
(preferences:set-default 'framework:ascii-art-enlarge #f boolean?)
(preferences:set-default 'framework:color-scheme 'classic symbol?)
(preferences:set-default 'framework:column-guide-width
@ -198,7 +200,7 @@
"match-let" "match-let*" "match-letrec"
"letrec"
"letrec-syntaxes" "letrec-syntaxes+values" "letrec-values"
"parameterize" "parameterize*"
"parameterize" "parameterize*" "syntax-parameterize"
"with-syntax" "with-handlers")))
(set-square-bracket-nonum-pref 'framework:square-bracket:for/fold for/folds)
@ -214,6 +216,10 @@
(preferences:add-callback 'framework:special-meta-key (λ (p v) (map-command-as-meta-key v)))
(map-command-as-meta-key (preferences:get 'framework:special-meta-key))
(preferences:set-default 'framework:any-control+alt-is-altgr #f boolean?)
(preferences:add-callback 'framework:any-control+alt-is-altgr (λ (p v) (any-control+alt-is-altgr v)))
(any-control+alt-is-altgr (preferences:get 'framework:any-control+alt-is-altgr))
(preferences:set-default 'framework:fraction-snip-style
'mixed (λ (x) (memq x '(mixed improper decimal))))
@ -441,7 +447,7 @@
unit/sig unit/lang
with-handlers
interface
parameterize parameterize*
parameterize parameterize* syntax-parameterize
call-with-input-file call-with-input-file* with-input-from-file
with-input-from-port call-with-output-file
with-output-to-file with-output-to-port
@ -451,7 +457,7 @@
type-case))
(preferences:set-default
'framework:tabify
(list defaults-ht #rx"^begin" #rx"^def" #rx"^for\\*?(/|$)" #f)
(list defaults-ht #rx"^begin" #rx"^def" #rx"^(for\\*?(/|$)|with-)" #f)
(list/c (hash/c symbol? (or/c 'for/fold 'define 'begin 'lambda) #:flat? #t)
(or/c #f regexp?) (or/c #f regexp?) (or/c #f regexp?) (or/c #f regexp?)))

View File

@ -51,33 +51,34 @@ the state transitions / contracts are:
(define (get-preference/gui sym [def (λ () (error 'get-preference/gui "unknown pref ~s" sym))])
(define (try)
(get-preference sym
def
#:timeout-lock-there
(λ (filename)
(define what-to-do
(cond
[get-pref-retry-result
get-pref-retry-result]
[else
(define-values (res dont-ask-again?)
(message+check-box/custom
(string-constant error-reading-preferences)
(format (string-constant error-reading-preferences-explanation)
sym)
(string-constant dont-ask-again-until-drracket-restarted) ;; check label
(string-constant try-again)
(string-constant give-up-and-use-the-default)
#f
#f
'(caution default=1)
1)) ;; cannot return #f here or get-pref-retry-result may get set wrong
(when dont-ask-again?
(set! get-pref-retry-result res))
res]))
(case what-to-do
[(1) (try)]
[(2) (def)]))))
(get-preference
sym
def
#:timeout-lock-there
(λ (filename)
(define what-to-do
(cond
[get-pref-retry-result
get-pref-retry-result]
[else
(define-values (res dont-ask-again?)
(message+check-box/custom
(string-constant error-reading-preferences)
(format (string-constant error-reading-preferences-explanation)
sym)
(string-constant dont-ask-again-until-drracket-restarted) ;; check label
(string-constant try-again)
(string-constant give-up-and-use-the-default)
#f
#f
'(caution default=1)
1)) ;; cannot return #f here or get-pref-retry-result may get set wrong
(when dont-ask-again?
(set! get-pref-retry-result res))
res]))
(case what-to-do
[(1) (try)]
[(2) (def)]))))
(try))
@ -127,7 +128,9 @@ the state transitions / contracts are:
#f
#f ;;parent
'(default=2 caution))]
[else (error 'preferences.rkt "preferences-lock-file-mode returned unknown mode ~s\n" the-mode)]))
[else (error 'preferences.rkt
"preferences-lock-file-mode returned unknown mode ~s\n"
the-mode)]))
(case mb-ans
[(2 #f) (record-actual-failure)]
[(1)
@ -457,7 +460,8 @@ the state transitions / contracts are:
(list (string-constant editor-prefs-panel-label)
(string-constant editor-general-prefs-panel-label))
(λ (editor-panel)
(add-check editor-panel 'framework:delete-forward? (string-constant map-delete-to-backspace)
(add-check editor-panel 'framework:delete-forward?
(string-constant map-delete-to-backspace)
not not)
(add-check editor-panel
'framework:auto-set-wrap?
@ -474,6 +478,11 @@ the state transitions / contracts are:
'framework:special-meta-key
(string-constant command-as-meta)))
(when (memq (system-type) '(windows))
(add-check editor-panel
'framework:any-control+alt-is-altgr
(string-constant any-control+alt-is-altgr)))
(add-check editor-panel
'framework:coloring-active
(string-constant online-coloring-active))
@ -498,93 +507,94 @@ the state transitions / contracts are:
'framework:line-spacing-add-gap?
(string-constant add-spacing-between-lines))
(let ([hp (new horizontal-panel% [parent editor-panel] [stretchable-height #f])]
[init-pref (preferences:get 'framework:column-guide-width)])
(define on-cb
(new check-box%
[parent hp]
[label (string-constant maximum-char-width-guide-pref-check-box)]
[value (car init-pref)]
[callback
(λ (x y)
(update-pref)
(update-tf-bkg)
(send tf enable (send on-cb get-value)))]))
(define tf
(new text-field%
[label #f]
[parent hp]
[init-value (format "~a" (cadr init-pref))]
[callback
(λ (x y)
(update-pref)
(update-tf-bkg))]))
(define (update-tf-bkg)
(send tf set-field-background
(send the-color-database find-color
(cond
[(not (send on-cb get-value)) "gray"]
[(good-val? (string->number (send tf get-value)))
"white"]
[else
"yellow"]))))
(define (good-val? n)
(and (exact-integer? n)
(>= n 2)))
(define (update-pref)
(define current (preferences:get 'framework:column-guide-width))
(define candidate-num (string->number (send tf get-value)))
(preferences:set 'framework:column-guide-width
(list (send on-cb get-value)
(if (good-val? candidate-num)
candidate-num
(cadr current)))))
(update-tf-bkg))
(add-number editor-panel
'framework:column-guide-width
(string-constant maximum-char-width-guide-pref-check-box)
(λ (n) (and (exact-integer? n) (>= n 2))))
(editor-panel-procs editor-panel))))])
(add-editor-checkbox-panel)))
(define (add-general-checkbox-panel)
(letrec ([add-general-checkbox-panel
(λ ()
(set! add-general-checkbox-panel void)
(add-checkbox-panel
(list (string-constant general-prefs-panel-label))
(λ (editor-panel)
(make-recent-items-slider editor-panel)
(add-check editor-panel
'framework:autosaving-on?
(string-constant auto-save-files))
(add-check editor-panel 'framework:backup-files? (string-constant backup-files))
(add-check editor-panel 'framework:show-status-line (string-constant show-status-line))
;; does this not belong here?
;; (add-check editor-panel 'drracket:show-line-numbers (string-constant show-line-numbers)
(add-check editor-panel 'framework:col-offsets (string-constant count-columns-from-one))
(add-check editor-panel
'framework:display-line-numbers
(string-constant display-line-numbers))
(define print-rb (new radio-box%
[label (string-constant printing-mode)]
[parent editor-panel]
[choices (list (string-constant print-using-platform-specific-mode)
(string-constant print-to-ps)
(string-constant print-to-pdf))]
[callback
(λ (rb evt)
(preferences:set 'framework:print-output-mode
(case (send print-rb get-selection)
[(0) 'standard]
[(1) 'postscript]
[(2) 'pdf])))]))
(define (update-print-rb what)
(send print-rb set-selection (case what
[(standard) 0]
[(postscript) 1]
[(pdf) 2])))
(update-print-rb (preferences:get 'framework:print-output-mode))
(preferences:add-callback 'framework:print-output-mode (λ (p v) (update-print-rb v)))
(general-panel-procs editor-panel))))])
(add-general-checkbox-panel)))
(define (add-number editor-panel pref-name label good-val?)
(define hp (new horizontal-panel% [parent editor-panel] [stretchable-height #f]))
(define init-pref (preferences:get pref-name))
(define on-cb
(new check-box%
[parent hp]
[label label]
[value (car init-pref)]
[callback
(λ (x y)
(update-pref)
(update-tf-bkg)
(send tf enable (send on-cb get-value)))]))
(define tf
(new text-field%
[label #f]
[parent hp]
[init-value (format "~a" (cadr init-pref))]
[callback
(λ (x y)
(update-pref)
(update-tf-bkg))]))
(define (update-tf-bkg)
(send tf set-field-background
(send the-color-database find-color
(cond
[(not (send on-cb get-value)) "gray"]
[(good-val? (string->number (send tf get-value)))
"white"]
[else
"yellow"]))))
(define (update-pref)
(define current (preferences:get pref-name))
(define candidate-num (string->number (send tf get-value)))
(preferences:set pref-name
(list (send on-cb get-value)
(if (good-val? candidate-num)
candidate-num
(cadr current)))))
(update-tf-bkg))
(define (add-general-checkbox-panel) (add-general-checkbox-panel/real))
(define (add-general-checkbox-panel/real)
(set! add-general-checkbox-panel/real void)
(add-checkbox-panel
(list (string-constant general-prefs-panel-label))
(λ (editor-panel)
(make-recent-items-slider editor-panel)
(add-check editor-panel
'framework:autosaving-on?
(string-constant auto-save-files))
(add-check editor-panel 'framework:backup-files? (string-constant backup-files))
(add-check editor-panel 'framework:show-status-line (string-constant show-status-line))
;; does this not belong here?
;; (add-check editor-panel 'drracket:show-line-numbers (string-constant show-line-numbers)
(add-check editor-panel 'framework:col-offsets (string-constant count-columns-from-one))
(add-check editor-panel
'framework:display-line-numbers
(string-constant display-line-numbers))
(define print-rb (new radio-box%
[label (string-constant printing-mode)]
[parent editor-panel]
[choices (list (string-constant print-using-platform-specific-mode)
(string-constant print-to-ps)
(string-constant print-to-pdf))]
[callback
(λ (rb evt)
(preferences:set 'framework:print-output-mode
(case (send print-rb get-selection)
[(0) 'standard]
[(1) 'postscript]
[(2) 'pdf])))]))
(define (update-print-rb what)
(send print-rb set-selection (case what
[(standard) 0]
[(postscript) 1]
[(pdf) 2])))
(update-print-rb (preferences:get 'framework:print-output-mode))
(preferences:add-callback 'framework:print-output-mode (λ (p v) (update-print-rb v)))
(general-panel-procs editor-panel))))
(define (add-warnings-checkbox-panel)
(letrec ([add-warnings-checkbox-panel
@ -639,7 +649,8 @@ the state transitions / contracts are:
(cond
[(string? default) string?]
[(number? default) number?]
[else (error 'internal-error.set-default "unrecognized default: ~a\n" default)])))))])
[else (error 'internal-error.set-default
"unrecognized default: ~a\n" default)])))))])
(for-each (set-default build-font-entry font-default-string string?)
font-families)

View File

@ -504,12 +504,6 @@
[else
(+ i 1)])))
(public tabify-all insert-return calc-last-para
box-comment-out-selection comment-out-selection uncomment-selection
flash-forward-sexp
flash-backward-sexp backward-sexp find-up-sexp up-sexp find-down-sexp down-sexp
remove-parens-forward)
(define/public (get-limit pos) 0)
(define/public (balance-parens key-event [smart-skip #f])
@ -564,11 +558,15 @@
tab-char?))
(define/pubment (compute-amount-to-indent pos)
(inner (compute-racket-amount-to-indent pos) compute-amount-to-indent pos))
(define/public-final (compute-racket-amount-to-indent pos)
(define/public-final (compute-racket-amount-to-indent pos [_get-head-sexp-type (λ (x) #f)])
(cond
[(is-stopped?) #f]
[else
(define tabify-prefs (preferences:get 'framework:tabify))
(define get-head-sexp-type
(let ([tabify-prefs (preferences:get 'framework:tabify)])
(λ (text)
(or (_get-head-sexp-type text)
(get-head-sexp-type-from-prefs text tabify-prefs)))))
(define last-pos (last-position))
(define para (position-paragraph pos))
(define is-tabbable?
@ -625,8 +623,11 @@
(define id-end (get-forward-sexp contains))
(and (and id-end (> id-end contains))
(let ([text (get-text contains id-end)])
(or (get-keyword-type text tabify-prefs)
'other))))
(cond
[(member (classify-position contains) '(keyword symbol))
(get-head-sexp-type text)]
[else
'other]))))
(define (procedure-indent)
(case (get-proc)
[(begin define) 1]
@ -690,16 +691,24 @@
;; So far, the S-exp containing "pos" was all on
;; one line (possibly not counting the opening paren),
;; so indent to follow the first S-exp's end
;; unless there are just two sexps and the second is an ellipsis.
;; in that case, we just ignore the ellipsis
;; unless
;; - there are just two sexps earlier and the second is an ellipsis.
;; in that case, we just ignore the ellipsis or
;; - the sexp we are indenting is a bunch of hypens;
;; in that case, we match the opening paren
(define id-end (get-forward-sexp contains))
(define name-length
(if id-end
(- id-end contains)
0))
(cond
[(or (first-sexp-is-keyword? contains)
(sexp-is-all-hyphens? contains))
(visual-offset contains)]
[(second-sexp-is-ellipsis? contains)
(visual-offset contains)]
[(sexp-is-all-hyphens? pos)
(visual-offset contains)]
[(not (find-up-sexp pos))
(visual-offset contains)]
[else
@ -718,6 +727,21 @@
(loop next-to-last next-to-last-para)
(visual-offset last))))]))
amt-to-indent]))
;; returns #t if `pos` is in a symbol (or keyword) that consists entirely
;; of hyphens and has at least three hyphens; returns #f otherwise
(define/private (sexp-is-all-hyphens? pos)
(define fst-end (get-forward-sexp pos))
(and fst-end
(let ([fst-start (get-backward-sexp fst-end)])
(and fst-start
(memq (classify-position fst-start) '(symbol keyword))
(>= (- fst-end fst-start) 3)
(let loop ([i fst-start])
(cond
[(< i fst-end)
(and (equal? #\- (get-character i)) (loop (+ i 1)))]
[else #t]))))))
;; returns #t if `contains' is at a position on a line with an sexp, an ellipsis and nothing else.
;; otherwise, returns #f
@ -734,12 +758,20 @@
(and (or (not thrd-start)
(not (= (position-paragraph thrd-start)
(position-paragraph snd-start)))))))))))))
(define/private (first-sexp-is-keyword? contains)
(let ([fst-end (get-forward-sexp contains)])
(and fst-end
(let ([fst-start (get-backward-sexp fst-end)])
(and fst-start
(equal? (classify-position fst-start) 'hash-colon-keyword))))))
(define/public (tabify-selection [start-pos (get-start-position)]
[end-pos (get-end-position)])
(unless (is-stopped?)
(define first-para (position-paragraph start-pos))
(define end-para (position-paragraph end-pos))
(define tabifying-multiple-paras? (not (= first-para end-para)))
(with-handlers ([exn:break?
(λ (x) #t)])
(dynamic-wind
@ -750,7 +782,14 @@
(λ ()
(let loop ([para first-para])
(when (<= para end-para)
(tabify (paragraph-start-position para))
(define start (paragraph-start-position para))
(define end (paragraph-end-position para))
(define skip-this-line?
(and tabifying-multiple-paras?
(for/and ([i (in-range start (+ end 1))])
(char-whitespace? (get-character i)))))
(unless skip-this-line?
(tabify start))
(parameterize-break #t (void))
(loop (add1 para))))
(when (and (>= (position-paragraph start-pos) end-para)
@ -768,8 +807,8 @@
(when (< first-para end-para)
(end-busy-cursor)))))))
(define (tabify-all) (tabify-selection 0 (last-position)))
(define (insert-return)
(define/public (tabify-all) (tabify-selection 0 (last-position)))
(define/public (insert-return)
(begin-edit-sequence #t #f)
(define end-of-whitespace (get-start-position))
(define start-cutoff
@ -793,7 +832,7 @@
new-pos))))
(end-edit-sequence))
(define (calc-last-para last-pos)
(define/public (calc-last-para last-pos)
(let ([last-para (position-paragraph last-pos #t)])
(if (and (> last-pos 0)
(> last-para 0))
@ -804,55 +843,53 @@
last-para)))
last-para)))
(define comment-out-selection
(lambda ([start-pos (get-start-position)]
[end-pos (get-end-position)])
(begin-edit-sequence)
(let ([first-pos-is-first-para-pos?
(= (paragraph-start-position (position-paragraph start-pos))
start-pos)])
(let* ([first-para (position-paragraph start-pos)]
[last-para (calc-last-para end-pos)])
(let para-loop ([curr-para first-para])
(when (<= curr-para last-para)
(let ([first-on-para (paragraph-start-position curr-para)])
(insert #\; first-on-para)
(para-loop (add1 curr-para))))))
(when first-pos-is-first-para-pos?
(set-position
(paragraph-start-position (position-paragraph (get-start-position)))
(get-end-position))))
(end-edit-sequence)
#t))
(define/public (comment-out-selection [start-pos (get-start-position)]
[end-pos (get-end-position)])
(begin-edit-sequence)
(let ([first-pos-is-first-para-pos?
(= (paragraph-start-position (position-paragraph start-pos))
start-pos)])
(let* ([first-para (position-paragraph start-pos)]
[last-para (calc-last-para end-pos)])
(let para-loop ([curr-para first-para])
(when (<= curr-para last-para)
(let ([first-on-para (paragraph-start-position curr-para)])
(insert #\; first-on-para)
(para-loop (add1 curr-para))))))
(when first-pos-is-first-para-pos?
(set-position
(paragraph-start-position (position-paragraph (get-start-position)))
(get-end-position))))
(end-edit-sequence)
#t)
(define box-comment-out-selection
(lambda ([_start-pos 'start]
[_end-pos 'end])
(let ([start-pos (if (eq? _start-pos 'start)
(get-start-position)
_start-pos)]
[end-pos (if (eq? _end-pos 'end)
(get-end-position)
_end-pos)])
(begin-edit-sequence)
(split-snip start-pos)
(split-snip end-pos)
(let* ([cb (instantiate comment-box:snip% ())]
[text (send cb get-editor)])
(let loop ([snip (find-snip start-pos 'after-or-none)])
(cond
[(not snip) (void)]
[((get-snip-position snip) . >= . end-pos) (void)]
[else
(send text insert (send snip copy)
(send text last-position)
(send text last-position))
(loop (send snip next))]))
(delete start-pos end-pos)
(insert cb start-pos)
(set-position start-pos start-pos))
(end-edit-sequence)
#t)))
(define/public (box-comment-out-selection [_start-pos 'start]
[_end-pos 'end])
(let ([start-pos (if (eq? _start-pos 'start)
(get-start-position)
_start-pos)]
[end-pos (if (eq? _end-pos 'end)
(get-end-position)
_end-pos)])
(begin-edit-sequence)
(split-snip start-pos)
(split-snip end-pos)
(let* ([cb (instantiate comment-box:snip% ())]
[text (send cb get-editor)])
(let loop ([snip (find-snip start-pos 'after-or-none)])
(cond
[(not snip) (void)]
[((get-snip-position snip) . >= . end-pos) (void)]
[else
(send text insert (send snip copy)
(send text last-position)
(send text last-position))
(loop (send snip next))]))
(delete start-pos end-pos)
(insert cb start-pos)
(set-position start-pos start-pos))
(end-edit-sequence)
#t))
;; uncomment-box/selection : -> void
;; uncomments a comment box, if the focus is inside one.
@ -872,44 +909,43 @@
(end-edit-sequence)
#t)
(define uncomment-selection
(lambda ([start-pos (get-start-position)]
[end-pos (get-end-position)])
(let ([snip-before (find-snip start-pos 'before-or-none)]
[snip-after (find-snip start-pos 'after-or-none)])
(define/public (uncomment-selection [start-pos (get-start-position)]
[end-pos (get-end-position)])
(let ([snip-before (find-snip start-pos 'before-or-none)]
[snip-after (find-snip start-pos 'after-or-none)])
(begin-edit-sequence)
(cond
[(and (= start-pos end-pos)
snip-before
(is-a? snip-before comment-box:snip%))
(extract-contents start-pos snip-before)]
[(and (= start-pos end-pos)
snip-after
(is-a? snip-after comment-box:snip%))
(extract-contents start-pos snip-after)]
[(and (= (+ start-pos 1) end-pos)
snip-after
(is-a? snip-after comment-box:snip%))
(extract-contents start-pos snip-after)]
[else
(let* ([last-pos (last-position)]
[first-para (position-paragraph start-pos)]
[last-para (calc-last-para end-pos)])
(let para-loop ([curr-para first-para])
(when (<= curr-para last-para)
(let ([first-on-para
(skip-whitespace (paragraph-start-position curr-para)
'forward
#f)])
(split-snip first-on-para)
(when (and (< first-on-para last-pos)
(char=? #\; (get-character first-on-para))
(is-a? (find-snip first-on-para 'after-or-none) string-snip%))
(delete first-on-para (+ first-on-para 1)))
(para-loop (add1 curr-para))))))])
(end-edit-sequence))
#t))
(begin-edit-sequence)
(cond
[(and (= start-pos end-pos)
snip-before
(is-a? snip-before comment-box:snip%))
(extract-contents start-pos snip-before)]
[(and (= start-pos end-pos)
snip-after
(is-a? snip-after comment-box:snip%))
(extract-contents start-pos snip-after)]
[(and (= (+ start-pos 1) end-pos)
snip-after
(is-a? snip-after comment-box:snip%))
(extract-contents start-pos snip-after)]
[else
(let* ([last-pos (last-position)]
[first-para (position-paragraph start-pos)]
[last-para (calc-last-para end-pos)])
(let para-loop ([curr-para first-para])
(when (<= curr-para last-para)
(let ([first-on-para
(skip-whitespace (paragraph-start-position curr-para)
'forward
#f)])
(split-snip first-on-para)
(when (and (< first-on-para last-pos)
(char=? #\; (get-character first-on-para))
(is-a? (find-snip first-on-para 'after-or-none) string-snip%))
(delete first-on-para (+ first-on-para 1)))
(para-loop (add1 curr-para))))))])
(end-edit-sequence))
#t)
;; extract-contents : number (is-a?/c comment-box:snip%) -> void
;; copies the contents of the comment-box-snip out of the snip
@ -987,13 +1023,12 @@
(set-position end-pos)
(bell))
#t))
[define flash-forward-sexp
(λ (start-pos)
(let ([end-pos (get-forward-sexp start-pos)])
(if end-pos
(flash-on end-pos (add1 end-pos))
(bell))
#t))]
(define/public (flash-forward-sexp start-pos)
(let ([end-pos (get-forward-sexp start-pos)])
(if end-pos
(flash-on end-pos (add1 end-pos))
(bell))
#t))
(define/public (get-backward-sexp start-pos)
(let* ([limit (get-limit start-pos)]
[end-pos (backward-match start-pos limit)]
@ -1012,89 +1047,82 @@
end-pos)))
;; can't go backward at all:
#f)))
[define flash-backward-sexp
(λ (start-pos)
(let ([end-pos (get-backward-sexp start-pos)])
(if end-pos
(flash-on end-pos (add1 end-pos))
(bell))
#t))]
[define backward-sexp
(λ (start-pos)
(let ([end-pos (get-backward-sexp start-pos)])
(if end-pos
(set-position end-pos)
(bell))
#t))]
[define find-up-sexp
(λ (start-pos)
(let* ([limit-pos (get-limit start-pos)]
[exp-pos
(backward-containing-sexp start-pos limit-pos)])
(define/public (flash-backward-sexp start-pos)
(let ([end-pos (get-backward-sexp start-pos)])
(if end-pos
(flash-on end-pos (add1 end-pos))
(bell))
#t))
(define/public (backward-sexp start-pos)
(let ([end-pos (get-backward-sexp start-pos)])
(if end-pos
(set-position end-pos)
(bell))
#t))
(define/public (find-up-sexp start-pos)
(let* ([limit-pos (get-limit start-pos)]
[exp-pos
(backward-containing-sexp start-pos limit-pos)])
(if (and exp-pos (> exp-pos limit-pos))
(let* ([in-start-pos (skip-whitespace exp-pos 'backward #t)]
[paren-pos
(λ (paren-pair)
(find-string
(car paren-pair)
'backward
in-start-pos
limit-pos))])
(let ([poss (let loop ([parens (racket-paren:get-paren-pairs)])
(cond
[(null? parens) null]
[else
(let ([pos (paren-pos (car parens))])
(if pos
(cons pos (loop (cdr parens)))
(loop (cdr parens))))]))])
(if (null? poss) ;; all finds failed
#f
(- (apply max poss) 1)))) ;; subtract one to move outside the paren
#f)))]
[define up-sexp
(λ (start-pos)
(let ([exp-pos (find-up-sexp start-pos)])
(if exp-pos
(set-position exp-pos)
(bell))
#t))]
[define find-down-sexp
(λ (start-pos)
(let loop ([pos start-pos])
(let ([next-pos (get-forward-sexp pos)])
(if (and next-pos (> next-pos pos))
(let ([back-pos
(backward-containing-sexp (sub1 next-pos) pos)])
(if (and back-pos
(> back-pos pos))
back-pos
(loop next-pos)))
#f))))]
[define down-sexp
(λ (start-pos)
(let ([pos (find-down-sexp start-pos)])
(if pos
(set-position pos)
(bell))
#t))]
[define remove-parens-forward
(λ (start-pos)
(let* ([pos (skip-whitespace start-pos 'forward #f)]
[first-char (get-character pos)]
[paren? (or (char=? first-char #\()
(char=? first-char #\[)
(char=? first-char #\{))]
[closer (and paren?
(get-forward-sexp pos))])
(if (and paren? closer)
(begin (begin-edit-sequence #t #f)
(delete pos (add1 pos))
(delete (- closer 2) (- closer 1))
(end-edit-sequence))
(bell))
#t))]
(if (and exp-pos (> exp-pos limit-pos))
(let* ([in-start-pos (skip-whitespace exp-pos 'backward #t)]
[paren-pos
(λ (paren-pair)
(find-string
(car paren-pair)
'backward
in-start-pos
limit-pos))])
(let ([poss (let loop ([parens (racket-paren:get-paren-pairs)])
(cond
[(null? parens) null]
[else
(let ([pos (paren-pos (car parens))])
(if pos
(cons pos (loop (cdr parens)))
(loop (cdr parens))))]))])
(if (null? poss) ;; all finds failed
#f
(- (apply max poss) 1)))) ;; subtract one to move outside the paren
#f)))
(define/public (up-sexp start-pos)
(let ([exp-pos (find-up-sexp start-pos)])
(if exp-pos
(set-position exp-pos)
(bell))
#t))
(define/public (find-down-sexp start-pos)
(let loop ([pos start-pos])
(let ([next-pos (get-forward-sexp pos)])
(if (and next-pos (> next-pos pos))
(let ([back-pos
(backward-containing-sexp (sub1 next-pos) pos)])
(if (and back-pos
(> back-pos pos))
back-pos
(loop next-pos)))
#f))))
(define/public (down-sexp start-pos)
(let ([pos (find-down-sexp start-pos)])
(if pos
(set-position pos)
(bell))
#t))
(define/public (remove-parens-forward start-pos)
(let* ([pos (skip-whitespace start-pos 'forward #f)]
[first-char (get-character pos)]
[paren? (or (char=? first-char #\()
(char=? first-char #\[)
(char=? first-char #\{))]
[closer (and paren?
(get-forward-sexp pos))])
(if (and paren? closer)
(begin (begin-edit-sequence #t #f)
(delete pos (add1 pos))
(delete (- closer 2) (- closer 1))
(end-edit-sequence))
(bell))
#t))
(define/private (select-text f forward?)
(define start-pos (get-start-position))
@ -1111,11 +1139,11 @@
(extend-position new-pos)
(bell))
#t)
(public select-forward-sexp select-backward-sexp select-up-sexp select-down-sexp)
[define select-forward-sexp (λ () (select-text (λ (x) (get-forward-sexp x)) #t))]
[define select-backward-sexp (λ () (select-text (λ (x) (get-backward-sexp x)) #f))]
[define select-up-sexp (λ () (select-text (λ (x) (find-up-sexp x)) #f))]
[define select-down-sexp (λ () (select-text (λ (x) (find-down-sexp x)) #t))]
(define/public (select-forward-sexp) (select-text (λ (x) (get-forward-sexp x)) #t))
(define/public (select-backward-sexp) (select-text (λ (x) (get-backward-sexp x)) #f))
(define/public (select-up-sexp) (select-text (λ (x) (find-up-sexp x)) #f))
(define/public (select-down-sexp) (select-text (λ (x) (find-down-sexp x)) #t))
(define/public (introduce-let-ans pos)
(dynamic-wind
@ -1261,10 +1289,9 @@
(for-each (λ (s) (insert s start-1)) snips-2/rev)
(set-position end-2)
(end-edit-sequence)))))))))))
[define tab-size 8]
(public get-tab-size set-tab-size)
[define get-tab-size (λ () tab-size)]
[define set-tab-size (λ (s) (set! tab-size s))]
(define tab-size 8)
(define/public (get-tab-size) tab-size)
(define/public (set-tab-size s) (set! tab-size s))
(define/override (get-start-of-line pos)
(define para (position-paragraph pos))
@ -1332,7 +1359,7 @@
(cond
[(and (eq? type 'symbol)
(string? lexeme)
(get-keyword-type lexeme tabify-pref))
(get-head-sexp-type-from-prefs lexeme tabify-pref))
(values lexeme 'keyword paren start end backup-delta new-mode)]
[else
(values lexeme type paren start end backup-delta new-mode)]))
@ -1351,9 +1378,9 @@
(|[| |]|)
(|{| |}|))))))
;; get-keyword-type : string (list ht regexp regexp regexp)
;; -> (or/c #f 'lambda 'define 'begin 'for/fold)
(define (get-keyword-type text pref)
;; get-head-sexp-type-from-prefs : string (list ht regexp regexp regexp)
;; -> (or/c #f 'lambda 'define 'begin 'for/fold)
(define (get-head-sexp-type-from-prefs text pref)
(define ht (car pref))
(define beg-reg (list-ref pref 1))
(define def-reg (list-ref pref 2))

View File

@ -1,99 +1,116 @@
#lang scheme/base
#lang racket/base
(require racket/contract/base
racket/class
scheme/gui/base)
racket/gui/base)
(provide/contract
[find-string-embedded
(->* ((is-a?/c text%)
string?)
((symbols 'forward 'backward)
(or/c (symbols 'start) number?)
(or/c (symbols 'eof) number?)
boolean?
boolean?
boolean?)
(values (is-a?/c editor<%>)
(or/c false/c number?)))])
(provide
(contract-out
[find-string-embedded
(->* ((is-a?/c text%)
string?)
((or/c 'forward 'backward)
(or/c 'start number?)
(or/c 'eof number?)
boolean?
boolean?
boolean?)
(values (is-a?/c editor<%>)
(or/c #f number?)))]))
(define find-string-embedded
(lambda (edit
str
[direction 'forward]
[start 'start]
[end 'eof]
[get-start #t]
[case-sensitive? #t]
[pop-out? #f])
(let/ec k
(let* ([start (if (eq? start 'start)
(send edit get-start-position)
start)]
[end (if (eq? 'eof end)
(if (eq? direction 'forward)
(send edit last-position)
0)
end)]
[flat (send edit find-string str direction
start end get-start
case-sensitive?)]
[pop-out
(λ ()
(let ([admin (send edit get-admin)])
(if (is-a? admin editor-snip-editor-admin<%>)
(let* ([snip (send admin get-snip)]
[edit-above (send (send snip get-admin) get-editor)]
[pos (send edit-above get-snip-position snip)]
[pop-out-pos (if (eq? direction 'forward) (add1 pos) pos)])
(find-string-embedded
edit-above
str
direction
pop-out-pos
(if (eq? direction 'forward) 'eof 0)
get-start
case-sensitive?
pop-out?))
(values edit #f))))])
(let loop ([current-snip (send edit find-snip start
(if (eq? direction 'forward)
'after-or-none
'before-or-none))])
(let ([next-loop
(λ ()
(if (eq? direction 'forward)
(loop (send current-snip next))
(loop (send current-snip previous))))])
(cond
[(or (not current-snip)
(and flat
(let* ([start (send edit get-snip-position current-snip)]
[end (+ start (send current-snip get-count))])
(if (eq? direction 'forward)
(and (<= start flat)
(< flat end))
(and (< start flat)
(<= flat end))))))
(if (and (not flat) pop-out?)
(pop-out)
(values edit flat))]
[(is-a? current-snip editor-snip%)
(let-values ([(embedded embedded-pos)
(let ([media (send current-snip get-editor)])
(if (and media
(is-a? media text%))
(begin
(find-string-embedded
media
str
direction
(if (eq? 'forward direction)
0
(send media last-position))
'eof
get-start case-sensitive?))
(values #f #f)))])
(if (not embedded-pos)
(next-loop)
(values embedded embedded-pos)))]
[else (next-loop)])))))))
(define (find-string-embedded a-text
str
[direction 'forward]
[start 'start]
[end 'eof]
[get-start #t]
[case-sensitive? #t]
[pop-out? #f])
(let/ec k
(let loop ([a-text a-text]
[start start]
[end end])
(define found (send a-text find-string-embedded str direction start end get-start case-sensitive?))
(define (done)
(cond
[(not found)
(k a-text found)]
[else
(let loop ([a-text a-text]
[found found])
(cond
[(number? found)
(k a-text found)]
[else (loop (car found) (cdr found))]))]))
(when found (done))
(unless pop-out? (done))
(define a-text-admin (send a-text get-admin))
(unless (is-a? a-text-admin editor-snip-editor-admin<%>) (done))
(define editor-snip (send a-text-admin get-snip))
(define editor-snip-admin (send editor-snip get-admin))
(unless editor-snip-admin (done))
(define enclosing-text (send editor-snip-admin get-editor))
(unless (is-a? enclosing-text text%) (done))
(loop enclosing-text
(+ (send enclosing-text get-snip-position editor-snip)
(send editor-snip get-count))
'eof))))
(module+ test
(require rackunit)
(define abcX (new text%))
(send abcX insert "abcX")
(define abc/abcX/abcQ (new text%))
(send abc/abcX/abcQ insert "abc")
(send abc/abcX/abcQ insert (new editor-snip% [editor abcX]))
(send abc/abcX/abcQ insert "abcQ")
(define abc//abc/abcX/abcQ//abcZ (new text%))
(send abc//abc/abcX/abcQ//abcZ insert "abc")
(send abc//abc/abcX/abcQ//abcZ insert (new editor-snip% [editor abc/abcX/abcQ]))
(send abc//abc/abcX/abcQ//abcZ insert "abcZ")
(let ()
(define-values (ta pos) (find-string-embedded abcX "b" 'forward 0))
(check-equal? ta abcX)
(check-equal? pos 1))
(let ()
(define-values (ta pos) (find-string-embedded abcX "c" 'forward 0))
(check-equal? ta abcX)
(check-equal? pos 2))
(let ()
(define-values (ta pos) (find-string-embedded abcX "d" 'forward 2))
(check-equal? pos #f))
(let ()
(define-values (ta pos) (find-string-embedded abc/abcX/abcQ "b" 'forward 0))
(check-equal? ta ta)
(check-equal? pos 1))
(let ()
(define-values (ta pos) (find-string-embedded abc/abcX/abcQ "b" 'forward 2))
(check-equal? ta abcX)
(check-equal? pos 1))
(let ()
(define-values (ta pos) (find-string-embedded abc//abc/abcX/abcQ//abcZ "X" 'forward 0))
(check-equal? ta abcX)
(check-equal? pos 3))
(let ()
(define-values (ta pos) (find-string-embedded abcX "Q" 'forward 0 'eof #t #t #t))
(check-equal? ta abc/abcX/abcQ)
(check-equal? pos 7))
(let ()
(define-values (ta pos) (find-string-embedded abcX "Z" 'forward 0 'eof #t #t #t))
(check-equal? ta abc//abc/abcX/abcQ//abcZ)
(check-equal? pos 7))
(let ()
(define-values (ta pos) (find-string-embedded abcX "c" 'forward 4 'eof #t #t #t))
(check-equal? ta abc/abcX/abcQ)
(check-equal? pos 6)))

View File

@ -154,7 +154,8 @@
autowrap-mixin
info-mixin
file-mixin
backup-autosave-mixin))
backup-autosave-mixin
font-size-message%))
(define-signature editor^ extends editor-class^
(get-standard-style-list
set-standard-style-list-pref-callbacks
@ -181,6 +182,7 @@
(define-signature text-class^
(basic<%>
line-spacing<%>
ascii-art-enlarge-boxes<%>
first-line<%>
line-numbers<%>
foreground-color<%>
@ -224,6 +226,7 @@
basic-mixin
line-spacing-mixin
ascii-art-enlarge-boxes-mixin
first-line-mixin
line-numbers-mixin
foreground-color-mixin
@ -258,7 +261,8 @@
range-color
make-snip-special
snip-special?))
snip-special?
send-snip-to-port))
(define-signature canvas-class^
(basic<%>

View File

@ -12,9 +12,11 @@
"autocomplete.rkt"
mred/mred-sig
mrlib/interactive-value-port
(prefix-in image-core: mrlib/image-core)
racket/list
"logging-timer.rkt"
"coroutine.rkt"
"unicode-ascii-art.rkt"
data/queue
racket/unit)
@ -748,6 +750,38 @@
(super on-event event)]
[else
(super on-event event)]))]))
(define to-invalidate #f)
(define/override (on-scroll-to)
(super on-scroll-to)
(set! to-invalidate (get-region-to-draw)))
(define/override (after-scroll-to)
(super after-scroll-to)
(define (maybe-invalidate)
(when to-invalidate
(invalidate-bitmap-cache
(list-ref to-invalidate 0)
(list-ref to-invalidate 1)
(list-ref to-invalidate 2)
(list-ref to-invalidate 3))
(set! to-invalidate #f)))
(maybe-invalidate)
(set! to-invalidate (get-region-to-draw))
(maybe-invalidate))
(define/private (get-region-to-draw)
(cond
[(show-first-line?)
(define admin (get-admin))
(cond
[admin
(send admin get-view bx by bw #f #f)
(define first-line (get-text 0 (paragraph-end-position 0)))
(define-values (tw th _1 _2) (send (get-dc) get-text-extent first-line (get-font)))
(list (unbox bx) (unbox by) (unbox bw) (+ th extra-fade-space))]
[else #f])]
[else #f]))
(define extra-fade-space 11)
(define/override (on-paint before? dc left top right bottom dx dy draw-caret)
(unless before?
@ -755,7 +789,8 @@
(define admin (get-admin))
(when admin
(send admin get-view bx by bw #f #f)
(unless (= (unbox by) 0)
(define y-coord (unbox by))
(unless (= y-coord 0)
(define draw-first-line-number?
(and (is-a? this line-numbers<%>)
(send this showing-line-numbers?)))
@ -772,10 +807,10 @@
(send dc set-smoothing 'aligned)
(send dc set-text-mode 'transparent)
(define-values (tw th _1 _2) (send dc get-text-extent first-line))
(define line-height (+ (unbox by) dy th 1))
(define line-height (+ y-coord dy th 1))
(define line-left (+ (unbox bx) dx))
(define line-right (+ (unbox bx) dx (unbox bw)))
(if w-o-b?
(send dc set-pen "white" 1 'solid)
(send dc set-pen "black" 1 'solid))
@ -784,7 +819,7 @@
(when (eq? (send dc get-smoothing) 'aligned)
(define start (if w-o-b? 6/10 3/10))
(define end 0)
(define steps 10)
(define steps (- extra-fade-space 1))
(send dc set-pen
(if w-o-b? dark-wob-first-line-color dark-first-line-color)
1
@ -803,20 +838,20 @@
(send dc set-alpha 1)
(send dc set-pen "gray" 1 'transparent)
(send dc set-brush (if w-o-b? "black" "white") 'solid)
(send dc draw-rectangle (+ (unbox bx) dx) (+ (unbox by) dy) (unbox bw) th)
(send dc draw-rectangle (+ (unbox bx) dx) (+ y-coord dy) (unbox bw) th)
(send dc set-text-foreground
(send the-color-database find-color
(if w-o-b? "white" "black")))
(define x-start
(cond
[draw-first-line-number?
(send this do-draw-single-line dc dx dy 0 (unbox by) #f #f)
(send this do-draw-single-line dc dx dy 0 y-coord #f #f)
(send dc set-pen (if w-o-b? "white" "black") 1 'solid)
(send this draw-separator dc (unbox by) (+ (unbox by) line-height) dx dy)
(send this draw-separator dc y-coord (+ y-coord line-height) dx dy)
(define-values (padding-left _1 _2 _3) (get-padding))
padding-left]
[else 0]))
(send dc draw-text first-line (+ x-start (+ (unbox bx) dx)) (+ (unbox by) dy))
(send dc draw-text first-line (+ x-start (+ (unbox bx) dx)) (+ y-coord dy))
(send dc set-text-foreground old-text-foreground)
(send dc set-text-mode old-text-mode)
@ -836,6 +871,89 @@
(super-new)))
(define ascii-art-enlarge-boxes<%> text:ascii-art-enlarge-boxes<%>)
(define ascii-art-enlarge-boxes-mixin
(mixin ((class->interface text%)) (ascii-art-enlarge-boxes<%>)
(inherit get-overwrite-mode set-overwrite-mode
get-start-position get-end-position set-position last-position
get-character
begin-edit-sequence end-edit-sequence
position-paragraph paragraph-start-position)
(define ascii-art-enlarge? (preferences:get 'framework:ascii-art-enlarge))
(define/public (get-ascii-art-enlarge) ascii-art-enlarge?)
(define/public (set-ascii-art-enlarge _e?)
(define e? (and _e? #t))
(preferences:set 'framework:ascii-art-enlarge e?)
(set! ascii-art-enlarge? e?))
(define/override (on-default-char c)
(define kc (send c get-key-code))
(define overwrite? (get-overwrite-mode))
(cond
[(not ascii-art-enlarge?) (super on-default-char c)]
[(or (and (char? kc)
(not (member kc '(#\return #\tab #\backspace #\rubout))))
(member (send c get-key-code)
going-to-insert-something))
(begin-edit-sequence)
(define pos (get-start-position))
(define widen? (and (= pos (get-end-position))
(or (not overwrite?)
(insertion-point-at-double-barred-char?))))
(when widen?
(define para (position-paragraph pos))
(define delta-from-start (- pos (paragraph-start-position para)))
(widen-unicode-ascii-art-box this pos)
(define new-pos (+ (paragraph-start-position para) delta-from-start))
(set-position new-pos new-pos))
(unless overwrite? (set-overwrite-mode #t))
(super on-default-char c)
(unless overwrite? (set-overwrite-mode #f))
(end-edit-sequence)]
[else
(super on-default-char c)]))
(define/override (on-local-char c)
(define kc (send c get-key-code))
(define overwrite? (get-overwrite-mode))
(cond
[(not ascii-art-enlarge?) (super on-local-char c)]
[(member kc '(numpad-enter #\return))
(define pos (get-start-position))
(cond
[(= pos (get-end-position))
(heighten-unicode-ascii-art-box this pos)
(define pos-para (position-paragraph pos))
(define pos-para-start (paragraph-start-position pos-para))
(define next-para-start (paragraph-start-position (+ pos-para 1)))
(define just-below-pos (+ next-para-start (- pos pos-para-start)))
(define new-pos
(let loop ([pos just-below-pos])
(cond
[(<= pos next-para-start)
pos]
[(equal? (get-character (- pos 1)) #\║)
pos]
[else (loop (- pos 1))])))
(set-position new-pos new-pos)]
[else
(super on-local-char c)])]
[else
(super on-local-char c)]))
(define/private (insertion-point-at-double-barred-char?)
(define sp (get-start-position))
(and (< sp (last-position))
(equal? (get-character sp) #\║)))
(super-new)))
(define going-to-insert-something
'(multiply
add subtract decimal divide
numpad0 numpad1 numpad2 numpad3 numpad4 numpad5 numpad6 numpad7 numpad8 numpad9))
(define foreground-color<%>
(interface (basic<%> editor:standard-style-list<%>)
@ -1104,7 +1222,7 @@
get-start-position get-end-position
unhighlight-ranges/key unhighlight-range highlight-range
run-after-edit-sequence begin-edit-sequence end-edit-sequence
find-string get-admin position-line
find-string find-string-embedded get-admin position-line
in-edit-sequence? get-pos/text-dc-location
get-canvas get-top-level-window)
@ -1145,7 +1263,7 @@
(car to-replace-highlight)))
;; NEW METHOD: used for test suites
(define/public (search-updates-pending?)
(define/public (search-updates-pending?)
(or update-replace-bubble-callback-running?
search-position-callback-running?
search-coroutine))
@ -1234,16 +1352,16 @@
(when to-replace-highlight
(unhighlight-replace))]
[else
(define next (do-search (get-start-position) 'eof))
(define next (do-search (get-start-position)))
(begin-edit-sequence #t #f)
(cond
[next
[(number? next)
(unless (and to-replace-highlight
(= (car to-replace-highlight) next)
(= (cdr to-replace-highlight)
(+ next (string-length searching-str))))
(string-length searching-str)))
(replace-highlight->normal-hit)
(define pr (cons next (+ next (string-length searching-str))))
(define pr (cons next (string-length searching-str)))
(unhighlight-hit pr)
(highlight-replace pr))]
[else
@ -1260,16 +1378,27 @@
(queue-callback
(λ ()
(when searching-str
(define count 0)
(define start-pos (get-start-position))
(hash-for-each
search-bubble-table
(λ (k v)
(when (<= (car k) start-pos)
(set! count (+ count 1)))))
(define start-pos (get-focus-editor-start-position))
(define count
(for/sum ([(k v) (in-hash search-bubble-table)])
(define n (if (search-result-compare <= (car k) start-pos) 1 0))
n))
(update-before-caret-search-hit-count count))
(set! search-position-callback-running? #f))
#f)))
(define/private (get-focus-editor-start-position)
(let loop ([txt this])
(define focus (send txt get-focus-snip))
(define embedded
(and focus
(is-a? focus editor-snip%)
(is-a? (send focus get-editor) text%)
(send focus get-editor)))
(cond
[embedded
(cons embedded (loop embedded))]
[else (send txt get-start-position)])))
(define/private (update-before-caret-search-hit-count c)
(unless (equal? before-caret-search-hit-count c)
@ -1296,7 +1425,7 @@
(clear-yellow)
(set! clear-yellow void)
(when (and searching-str (= (string-length searching-str) (- end start)))
(when (do-search start end)
(when (find-string searching-str 'forward start end #t case-sensitive?)
(set! clear-yellow (highlight-range
start end
(if (preferences:get 'framework:white-on-black?)
@ -1315,7 +1444,7 @@
(list (list to-replace-highlight 'dark-search-color))
(list))
(hash-map search-bubble-table
(λ (x true)
(λ (x _true)
(list x (if replace-mode? 'light-search-color 'normal-search-color)))))
string<?
#:key (λ (x) (format "~s" (car x)))))
@ -1380,31 +1509,40 @@
[searching-str
(define new-search-bubbles '())
(define new-replace-bubble #f)
(define first-hit (do-search 0 'eof))
(define first-hit (do-search 0))
(define-values (this-search-hit-count this-before-caret-search-hit-count)
(cond
[first-hit
(define sp (get-start-position))
(define sp (get-focus-editor-start-position))
(let loop ([bubble-start first-hit]
[search-hit-count 0]
[before-caret-search-hit-count 1])
[before-caret-search-hit-count (if (search-result-compare < first-hit sp) 1 0)])
(maybe-pause)
(define bubble-end (+ bubble-start (string-length searching-str)))
(define bubble (cons bubble-start bubble-end))
(define bubble-end (search-result+ bubble-start (string-length searching-str)))
(define bubble (cons bubble-start (string-length searching-str)))
(define this-bubble
(cond
[(and replace-mode?
(not new-replace-bubble)
(<= sp bubble-start))
(search-result-compare <= sp bubble-start))
(set! new-replace-bubble bubble)
'the-replace-bubble]
[else
bubble]))
(set! new-search-bubbles (cons this-bubble new-search-bubbles))
(define next (do-search bubble-end 'eof))
(define next (do-search bubble-end))
(when (> (let loop ([x bubble-start])
(cond
[(number? x) 1]
[else (+ 1 (loop (cdr x)))]))
3)
(car))
(define next-before-caret-search-hit-count
(if (and next (< next sp))
(if (and next (search-result-compare < next sp))
(+ 1 before-caret-search-hit-count)
before-caret-search-hit-count))
(cond
@ -1454,15 +1592,82 @@
(send w search-hits-changed)]
[(is-a? w area<%>)
(loop (send w get-parent))]))))))
(define/private (search-result+ search-result num)
(let loop ([search-result search-result])
(cond
[(number? search-result) (+ search-result num)]
[(cons? search-result)
(cons (car search-result)
(loop (cdr search-result)))])))
(define/private (search-result-compare lt l r)
(let loop ([txt this]
[l l]
[r r])
(define (get-the-position x)
;; the zeros shouldn't happen because the editors should still
;; be in the main text object while we are doing stuff with them
(define admin (send x get-admin))
(cond
[(is-a? admin editor-snip-editor-admin<%>)
(or (send txt get-snip-position (send admin get-snip)) 0)]
[else
0]))
(cond
[(and (number? l) (number? r)) (lt l r)]
[(or (number? l) (number? r))
(define ln (if (number? l) l (get-the-position (car l))))
(define rn (if (number? r) r (get-the-position (car r))))
(lt ln rn)]
[else
(cond
[(equal? (car l) (car r))
(loop (car l) (cdr l) (cdr r))]
[else
(lt (get-the-position (car l))
(get-the-position (car r)))])])))
(define all-txt-with-regions-to-clear (make-hasheq))
(define/private (clear-all-regions)
(when to-replace-highlight
(unhighlight-replace))
(unhighlight-ranges/key 'plt:framework:search-bubbles)
(for ([(txt _) (in-hash all-txt-with-regions-to-clear)])
(send txt unhighlight-ranges/key 'plt:framework:search-bubbles))
(set! all-txt-with-regions-to-clear (make-hasheq))
(set! search-bubble-table (make-hash)))
(define/private (do-search start end)
(find-string searching-str 'forward start end #t case-sensitive?))
(define/private (do-search start)
(define context (list this))
(define position
(let loop ([start start])
(cond
[(number? start) start]
[else
(set! context (cons (car start) context))
(loop (cdr start))])))
(let loop ([position position]
[context context])
(define found-at-this-level
(send (car context) find-string-embedded searching-str 'forward position 'eof #t case-sensitive?))
(cond
[found-at-this-level
(let loop ([context context])
(cond
[(null? (cdr context)) found-at-this-level]
[else (cons (car context)
(loop (cdr context)))]))]
[(null? (cdr context)) #f]
[else
(define admin (send (car context) get-admin))
(cond
[(is-a? admin editor-snip-editor-admin<%>)
(define snip (send admin get-snip))
(loop (+ (send (second context) get-snip-position snip)
(send snip get-count))
(cdr context))]
[else
(error 'framework/private/text.rkt::searching "admin went wrong ~s" admin)])])))
;; INVARIANT: when a search bubble is highlighted,
;; the search-bubble-table has it mapped to #t
@ -1472,40 +1677,61 @@
;; this method may be called with bogus inputs (ie a pair that has no highlight)
;; but only when there is a pending "erase all highlights and recompute everything" callback
(define/private (unhighlight-hit pair)
(hash-remove! search-bubble-table pair)
(unhighlight-range (car pair) (cdr pair)
(if replace-mode? light-search-color normal-search-color)
#f
'hollow-ellipse))
(define/private (highlight-hit pair)
(hash-set! search-bubble-table pair #t)
(highlight-range (car pair) (cdr pair)
(if replace-mode? light-search-color normal-search-color)
#f
'low
'hollow-ellipse
#:key 'plt:framework:search-bubbles
#:adjust-on-insert/delete? #t))
(define/private (unhighlight-hit bubble)
(hash-remove! search-bubble-table bubble)
(define-values (txt start end) (get-highlighting-text-and-range bubble))
(when txt
(send txt unhighlight-range
start end
(if replace-mode? light-search-color normal-search-color)
#f
'hollow-ellipse)))
(define/private (highlight-hit bubble)
(hash-set! search-bubble-table bubble #t)
(define-values (txt start end) (get-highlighting-text-and-range bubble))
(when txt
(hash-set! all-txt-with-regions-to-clear txt #t)
(send txt highlight-range
start end
(if replace-mode? light-search-color normal-search-color)
#f
'low
'hollow-ellipse
#:key 'plt:framework:search-bubbles
#:adjust-on-insert/delete? #t)))
;; INVARIANT: the "next to replace" highlight is always
;; saved in 'to-replace-highlight'
(define/private (unhighlight-replace)
(unhighlight-range (car to-replace-highlight)
(cdr to-replace-highlight)
dark-search-color
#f
'hollow-ellipse)
(define-values (txt start end) (get-highlighting-text-and-range to-replace-highlight))
(when txt
(send txt unhighlight-range
start end
dark-search-color
#f
'hollow-ellipse))
(set! to-replace-highlight #f))
(define/private (highlight-replace new-to-replace)
(set! to-replace-highlight new-to-replace)
(highlight-range (car to-replace-highlight)
(cdr to-replace-highlight)
dark-search-color
#f
'high
'hollow-ellipse))
(define-values (txt start end) (get-highlighting-text-and-range new-to-replace))
(when txt
(send txt highlight-range
start end
dark-search-color
#f
'high
'hollow-ellipse)))
(define/private (get-highlighting-text-and-range bubble)
(let loop ([txt this]
[txt/pr (car bubble)])
(cond
[(number? txt/pr)
(if (is-a? txt text:basic<%>)
(values txt txt/pr (+ txt/pr (cdr bubble)))
(values #f #f #f))]
[else (loop (car txt/pr) (cdr txt/pr))])))
(define/private (unhighlight-anchor)
(unhighlight-range anchor-pos anchor-pos "red" #f 'dot)
@ -2237,22 +2463,29 @@
[the-snipclass
(define base (new editor-stream-out-bytes-base%))
(define stream (make-object editor-stream-out% base))
(write-editor-global-header stream)
(send snip write stream)
(write-editor-global-footer stream)
(snip-special snip
(send the-snipclass get-classname)
(send base get-bytes))]
[else
(snip-special snip #f #f)]))
;; -> (or/c (is-a?/c snip%) exn:fail?)
(define (snip-special->snip snip-special)
(define the-name (snip-special-name snip-special))
(define snipclass (and the-name (send (get-the-snip-class-list) find the-name)))
(cond
[snipclass
(define base (make-object editor-stream-in-bytes-base%
(snip-special-bytes snip-special)))
(define es (make-object editor-stream-in% base))
(or (send snipclass read es)
(snip-special-snip snip-special))]
(with-handlers ([exn:fail? values])
(define base (make-object editor-stream-in-bytes-base%
(snip-special-bytes snip-special)))
(define es (make-object editor-stream-in% base))
(read-editor-global-header es)
(define the-snip (send snipclass read es))
(read-editor-global-footer es)
(or the-snip
(snip-special-snip snip-special)))]
[else
(snip-special-snip snip-special)]))
@ -2606,7 +2839,7 @@
(define/private (do-insertion txts showing-input?)
(define locked? (is-locked?))
(define sf? (get-styles-fixed))
(begin-edit-sequence)
(begin-edit-sequence #f)
(lock #f)
(set-styles-fixed #f)
(set! allow-edits? #t)
@ -2615,12 +2848,26 @@
[(null? txts) (void)]
[else
(define fst (car txts))
(define str/snp
(define-values (str/snp style)
(cond
[(snip-special? (car fst))
(snip-special->snip (car fst))]
[else (car fst)]))
(define style (cdr fst))
(define the-snip
(snip-special->snip (car fst)))
(if (exn:fail? the-snip)
(values (apply
string-append
"error while rendering snip "
(format "~s" (snip-special-name (car fst)))
":\n"
(exn-message the-snip)
" context:\n"
(for/list ([x (in-list (continuation-mark-set->context
(exn-continuation-marks
the-snip)))])
(format " ~s\n" x)))
(add-standard error-style-name))
(values the-snip (cdr fst)))]
[else (values (car fst) (cdr fst))]))
(define inserted-count
(if (is-a? str/snp snip%)
@ -2828,8 +3075,8 @@
;; don't want to set the port-print-handler here;
;; instead drracket sets the global-port-print-handler
;; to catch fractions and the like
(set-interactive-write-handler port)
(set-interactive-display-handler port))])
(set-interactive-write-handler port #:snip-handler send-snip-to-port)
(set-interactive-display-handler port #:snip-handler send-snip-to-port))])
(install-handlers out-port)
(install-handlers err-port)
(install-handlers value-port))))
@ -2968,6 +3215,30 @@
(define in-port (make-in-port-with-a-name (get-port-name)))
(define in-box-port (make-in-box-port-with-a-name (get-port-name)))))
(define (send-snip-to-port value port)
(cond
[(image-core:image? value)
;; do this computation here so that any failures
;; during drawing happen under the user's custodian
(image-core:compute-image-cache value)
;; once that is done, we trust the value not to run
;; any code that the user wrote, so just send it over
(write-special value port)]
[else
(define str (format "~s" value))
(cond
;; special case these snips as they don't work properly
;; without this and we aren't ready to break them yet
;; and image-core:image? should be safe-- there is no user
;; code in those images to fail
[(or (regexp-match? #rx"plot-snip%" str)
(regexp-match? #rx"pict3d%" str))
(write-special (send value copy) port)]
[else
(write-special (make-snip-special (send value copy)) port)])])
(void))
(define input-box<%>
(interface ((class->interface text%))
))
@ -4309,7 +4580,7 @@ designates the character that triggers autocompletion
(inner (void) after-edit-sequence))
(define/private (draw-numbers dc left top right bottom dx dy start-line end-line)
(unless (left . > . (line-x-coordinate dc dx))
(unless ((+ left dx) . > . (line-x-coordinate dc dx))
(define last-paragraph #f)
(define insertion-para
(let ([sp (get-start-position)])
@ -4400,12 +4671,12 @@ designates the character that triggers autocompletion
(define/private (text-width dc stuff)
(define-values (font-width font-height baseline space)
(send dc get-text-extent stuff))
(send dc get-text-extent stuff (get-style-font)))
font-width)
(define/private (text-height dc stuff)
(define-values (font-width height baseline space)
(send dc get-text-extent stuff))
(send dc get-text-extent stuff (get-style-font)))
height)
(define old-clipping #f)
@ -4570,7 +4841,7 @@ designates the character that triggers autocompletion
#t)
(super-new)))
(define basic% (basic-mixin (editor:basic-mixin text%)))
(define line-spacing% (line-spacing-mixin basic%))
(define hide-caret/selection% (hide-caret/selection-mixin line-spacing%))

View File

@ -0,0 +1,450 @@
#lang racket/base
(require racket/gui/base
racket/class
racket/contract
2d/dir-chars)
(provide normalize-unicode-ascii-art-box
widen-unicode-ascii-art-box
heighten-unicode-ascii-art-box
center-in-unicode-ascii-art-box)
(define (widen-unicode-ascii-art-box t orig-pos)
(widen/highten-unicode-ascii-art-box t orig-pos #t))
(define (heighten-unicode-ascii-art-box t orig-pos)
(widen/highten-unicode-ascii-art-box t orig-pos #f))
(define (widen/highten-unicode-ascii-art-box t orig-pos widen?)
(define start-pos (scan-for-start-pos t orig-pos))
(when start-pos
(send t begin-edit-sequence)
(define-values (start-x start-y) (pos->xy t orig-pos))
(define start-major (if widen? start-x start-y))
(define min-minor #f)
(define max-minor #f)
(trace-unicode-ascii-art-box
t start-pos #f
(λ (pos x y i-up? i-dn? i-lt? i-rt?)
(define minor (if widen? y x))
(define major (if widen? x y))
(when (= major start-major)
(unless min-minor
(set! min-minor minor)
(set! max-minor minor))
(set! min-minor (min minor min-minor))
(set! max-minor (max minor max-minor)))))
(cond
[widen?
(define to-adjust 0)
(for ([minor (in-range max-minor (- min-minor 1) -1)])
(define-values (pos char) (xy->pos t start-major minor))
(when (< pos start-pos)
(set! to-adjust (+ to-adjust 1)))
(send t insert
(cond
[(member char lt-chars) #\═]
[else #\space])
pos pos))
(send t set-position (+ orig-pos to-adjust 1) (+ orig-pos to-adjust 1))]
[else
(define-values (min-pos _1) (xy->pos t min-minor start-major))
(define-values (max-pos _2) (xy->pos t max-minor start-major))
(define para (send t position-paragraph max-pos))
(define para-start (send t paragraph-start-position para))
(define para-end (send t paragraph-end-position para))
(send t insert "\n" para-end para-end)
(for ([to-copy-pos (in-range para-start (+ max-pos 1))])
(define to-insert-pos (+ para-end 1 (- to-copy-pos para-start)))
(define char
(cond
[(< to-copy-pos min-pos) " "]
[else
(define above-char (send t get-character to-copy-pos))
(if (and (member above-char dn-chars)
(member above-char double-barred-chars))
""
" ")]))
(send t insert char to-insert-pos to-insert-pos))
(void)])
(send t end-edit-sequence)))
(define (normalize-unicode-ascii-art-box t pos)
(define start-pos (scan-for-start-pos t pos))
(when start-pos
(send t begin-edit-sequence)
(trace-unicode-ascii-art-box
t start-pos #f
(λ (pos x y i-up? i-dn? i-lt? i-rt?)
(cond
[(and i-up? i-dn? i-lt? i-rt?) (set-c t pos "")]
[(and i-dn? i-lt? i-rt?) (set-c t pos "")]
[(and i-up? i-lt? i-rt?) (set-c t pos "")]
[(and i-up? i-dn? i-rt?) (set-c t pos "")]
[(and i-up? i-dn? i-lt?) (set-c t pos "")]
[(and i-up? i-lt?) (set-c t pos "")]
[(and i-up? i-rt?) (set-c t pos "")]
[(and i-dn? i-lt?) (set-c t pos "")]
[(and i-dn? i-rt?) (set-c t pos "")]
[(or i-up? i-dn?) (set-c t pos "")]
[else (set-c t pos "")])))
(send t end-edit-sequence)))
(define (center-in-unicode-ascii-art-box txt insertion-pos)
(define (find-something start-pos inc char-p?)
(define-values (x y) (pos->xy txt start-pos))
(let loop ([pos start-pos])
(cond
[(char-p? (send txt get-character pos))
pos]
[else
(define new-pos (inc pos))
(cond
[(<= 0 new-pos (send txt last-position))
(define-values (x2 y2) (pos->xy txt new-pos))
(cond
[(= y2 y)
(loop new-pos)]
[else #f])]
[else #f])])))
(define (adjust-space before-space after-space pos)
(cond
[(< before-space after-space)
(send txt insert (make-string (- after-space before-space) #\space) pos pos)]
[(> before-space after-space)
(send txt delete pos (+ pos (- before-space after-space)))]))
(define left-bar (find-something insertion-pos sub1 (λ (x) (equal? x #\║))))
(define right-bar (find-something insertion-pos add1 (λ (x) (equal? x #\║))))
(when (and left-bar right-bar (< left-bar right-bar))
(define left-space-edge (find-something (+ left-bar 1) add1 (λ (x) (not (char-whitespace? x)))))
(define right-space-edge (find-something (- right-bar 1) sub1 (λ (x) (not (char-whitespace? x)))))
(when (and left-space-edge right-space-edge)
(define before-left-space-count (- left-space-edge left-bar 1))
(define before-right-space-count (- right-bar right-space-edge 1))
(define tot-space (+ before-left-space-count before-right-space-count))
(define after-left-space-count (floor (/ tot-space 2)))
(define after-right-space-count (ceiling (/ tot-space 2)))
(send txt begin-edit-sequence)
(adjust-space before-right-space-count after-right-space-count (+ right-space-edge 1))
(adjust-space before-left-space-count after-left-space-count (+ left-bar 1))
(send txt end-edit-sequence))))
(define (trace-unicode-ascii-art-box t start-pos only-double-barred-chars? f)
(define visited (make-hash))
(let loop ([pos start-pos])
(unless (hash-ref visited pos #f)
(hash-set! visited pos #t)
(define-values (x y) (pos->xy t pos))
(define c (send t get-character pos))
(define-values (up upc) (xy->pos t x (- y 1)))
(define-values (dn dnc) (xy->pos t x (+ y 1)))
(define-values (lt ltc) (xy->pos t (- x 1) y))
(define-values (rt rtc) (xy->pos t (+ x 1) y))
(define (interesting-dir? dir-c dir-chars)
(or (and (not only-double-barred-chars?)
(member dir-c adjustable-chars)
(member c dir-chars))
(and (member dir-c double-barred-chars)
(member c double-barred-chars))))
(define i-up? (interesting-dir? upc up-chars))
(define i-dn? (interesting-dir? dnc dn-chars))
(define i-lt? (interesting-dir? ltc lt-chars))
(define i-rt? (interesting-dir? rtc rt-chars))
(f pos x y i-up? i-dn? i-lt? i-rt?)
(when i-up? (loop up))
(when i-dn? (loop dn))
(when i-lt? (loop lt))
(when i-rt? (loop rt)))))
(define (scan-for-start-pos t pos)
(define-values (x y) (pos->xy t pos))
(findf
(λ (p) (adj? t p))
(for*/list ([xadj '(0 -1)]
[yadj '(0 -1 1)])
(define-values (d dc) (xy->pos t (+ x xadj) (+ y yadj)))
d)))
(define (adj? t pos)
(and pos
(member (send t get-character pos)
adjustable-chars)))
(define (set-c t pos s)
(unless (equal? (string-ref s 0) (send t get-character pos))
(send t delete pos (+ pos 1))
(send t insert s pos pos)))
(define (pos->xy text pos)
(define para (send text position-paragraph pos))
(define start (send text paragraph-start-position para))
(values (- pos start) para))
(define (xy->pos text x y)
(cond
[(and (<= 0 x) (<= 0 y (send text last-paragraph)))
(define para-start (send text paragraph-start-position y))
(define para-end (send text paragraph-end-position y))
(define pos (+ para-start x))
(define res-pos
(and (< pos para-end)
;; the newline at the end of the
;; line is not on the line, so use this guard
pos))
(if res-pos
(values res-pos (send text get-character res-pos))
(values #f #f))]
[else (values #f #f)]))
(module+ test
(require rackunit
racket/gui/base)
(define sa string-append)
(define (first-value-xy->pos a b c)
(define-values (d e) (xy->pos a b c))
d)
(let ([t (new text%)])
(send t insert (sa "abc\n"
"d\n"
"ghi\n"))
(check-equal? (first-value-xy->pos t 0 0) 0)
(check-equal? (first-value-xy->pos t 1 0) 1)
(check-equal? (first-value-xy->pos t 0 1) 4)
(check-equal? (first-value-xy->pos t 3 0) #f)
(check-equal? (first-value-xy->pos t 0 3) #f)
(check-equal? (first-value-xy->pos t 1 1) #f)
(check-equal? (first-value-xy->pos t 2 1) #f)
(check-equal? (first-value-xy->pos t 0 2) 6)
(check-equal? (first-value-xy->pos t 1 2) 7)
(check-equal? (first-value-xy->pos t 2 -1) #f)
(check-equal? (first-value-xy->pos t -1 0) #f)
(check-equal? (first-value-xy->pos t 2 2) 8)
(check-equal? (first-value-xy->pos t 2 3) #f))
(let ([t (new text%)])
(send t insert (sa "abc\n"
"d\n"
"ghi"))
(check-equal? (first-value-xy->pos t 2 2) 8)
(check-equal? (first-value-xy->pos t 2 3) #f))
(let ([t (new text%)])
(send t insert (string-append "+-+\n"
"| |\n"
"+-+\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═╗\n"
"║ ║\n"
"╚═╝\n")))
(let ([t (new text%)])
(send t insert (string-append "+=+\n"
"| |\n"
"+=+\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═╗\n"
"║ ║\n"
"╚═╝\n")))
(let ([t (new text%)])
(send t insert (string-append "+-+-+\n"
"| | |\n"
"+-+-+\n"
"| | |\n"
"+-+-+\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═══╗\n"
"║ - ║\n"
"╚═══╝\n"))
(normalize-unicode-ascii-art-box t 0)
(check-equal? (send t get-text)
(string-append
"╔═══╗\n"
"║ - ║\n"
"╚═══╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n"))
(send t set-position 1 1)
(widen-unicode-ascii-art-box t 1)
(check-equal? (send t get-start-position) 2)
(check-equal? (send t get-text)
(string-append
"╔══╦═╗\n"
"║ ║ ║\n"
"╠══╬═╣\n"
"║ ║ ║\n"
"╚══╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n"))
(send t set-position 8 8)
(widen-unicode-ascii-art-box t 8)
(check-equal? (send t get-start-position) 10)
(check-equal? (send t get-text)
(string-append
"╔══╦═╗\n"
"║ ║ ║\n"
"╠══╬═╣\n"
"║ ║ ║\n"
"╚══╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"))
(send t set-position 8 8)
(widen-unicode-ascii-art-box t 8)
(check-equal? (send t get-text)
(string-append
"╔══╦═╗\n"
"║ ║ ║\n"
"╠══╬═╣\n"
"║ ║ ║\n")))
(let ([t (new text%)])
(send t insert (string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n"))
(send t set-position 8 8)
(heighten-unicode-ascii-art-box t 8)
(check-equal? (send t get-start-position) 8)
(check-equal? (send t get-text)
(string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"1 ╔═╦═╗\n"
"2 ║ ║ ║\n"
"3 ╠═╬═╣\n"
"4 ║ ║ ║\n"
"5 ╚═╩═╝\n"))
(send t set-position 11 11)
(heighten-unicode-ascii-art-box t 11)
(check-equal? (send t get-text)
(string-append
"1 ╔═╦═╗\n"
"2 ║ ║ ║\n"
" ║ ║ ║\n"
"3 ╠═╬═╣\n"
"4 ║ ║ ║\n"
"5 ╚═╩═╝\n")))
(let ([t (new text%)])
(send t insert (string-append
"1 ╔═╦═╗\n"
"2 ║ ║ ║\n"
"3 ╠═╬═╣\n"
"4 ║ ║ ║\n"
"5 ╚═╩═╝\n"))
(send t set-position 19 19)
(heighten-unicode-ascii-art-box t 19)
(check-equal? (send t get-text)
(string-append
"1 ╔═╦═╗\n"
"2 ║ ║ ║\n"
"3 ╠═╬═╣\n"
" ║ ║ ║\n"
"4 ║ ║ ║\n"
"5 ╚═╩═╝\n")))
(let ([t (new text%)])
(send t insert "║ x ║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║ x ║\n"))
(let ([t (new text%)])
(send t insert "║x ║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║ x ║\n"))
(let ([t (new text%)])
(send t insert "║ x║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║ x ║\n"))
(let ([t (new text%)])
(send t insert "║abcde║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║abcde║\n"))
(let ([t (new text%)])
(send t insert "║║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║║\n"))
(let ([t (new text%)])
(send t insert "║abcde \n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
"║abcde \n"))
(let ([t (new text%)])
(send t insert " abcde║\n")
(center-in-unicode-ascii-art-box t 1)
(check-equal? (send t get-text)
" abcde║\n")))
#;
(module+ main
(require framework)
(define f (new frame% [label ""] [width 500] [height 500]))
(define t (new (ascii-art-enlarge-boxes-mixin racket:text%)))
(send t set-overwrite-mode #t)
(define ec (new editor-canvas% [parent f] [editor t]))
(send t insert
(string-append
"╔═╦═╗\n"
"║ ║ ║\n"
"║ ║ ║\n"
"╠═╬═╣\n"
"║ ║ ║\n"
"╚═╩═╝\n"))
(send t set-position 14 14)
(send f show #t))

View File

@ -3,26 +3,59 @@
(require racket/class
racket/file
racket/gui/base
racket/contract
(for-syntax racket/base))
(provide get-splash-bitmap
set-splash-bitmap
get-splash-canvas
get-splash-eventspace
get-splash-paint-callback
set-splash-paint-callback
start-splash
shutdown-splash
close-splash
add-splash-icon
set-splash-progress-bar?!
set-splash-char-observer
set-splash-event-callback
get-splash-event-callback
set-refresh-splash-on-gauge-change?!
get-splash-width
get-splash-height
refresh-splash)
(provide
(contract-out
[get-splash-bitmap (-> (or/c #f (is-a?/c bitmap%)))]
[set-splash-bitmap (-> (is-a?/c bitmap%) void?)]
[get-splash-canvas (-> (is-a?/c canvas%))]
[get-splash-eventspace (-> eventspace?)]
[get-splash-paint-callback (-> procedure?)]
[set-splash-paint-callback (-> (or/c (-> (is-a?/c dc<%>)
exact-nonnegative-integer?
exact-nonnegative-integer?
exact-nonnegative-integer?
exact-nonnegative-integer?
any)
(-> (is-a?/c dc<%>)
any))
void?)]
[start-splash
(->* ((or/c path-string?
(is-a?/c bitmap%)
(vector/c (or/c (-> (is-a?/c dc<%>) void?)
(-> (is-a?/c dc<%>)
exact-nonnegative-integer?
exact-nonnegative-integer?
exact-nonnegative-integer?
exact-nonnegative-integer?
any))
exact-nonnegative-integer?
exact-nonnegative-integer?))
string?
exact-nonnegative-integer?)
(#:allow-funny?
boolean?
#:frame-icon
(or/c #f
(is-a?/c bitmap%)
(cons/c (is-a?/c bitmap%)
(is-a?/c bitmap%))))
void?)]
[shutdown-splash (-> void?)]
[close-splash (-> void?)]
[add-splash-icon (-> (is-a?/c bitmap%) real? real? void?)]
[set-splash-progress-bar?! (-> boolean? void?)]
[set-splash-char-observer (-> procedure? void?)]
[set-splash-event-callback (-> procedure? void?)]
[get-splash-event-callback (-> procedure?)]
[set-refresh-splash-on-gauge-change?! (-> procedure? void?)]
[get-splash-width (-> exact-nonnegative-integer?)]
[get-splash-height (-> exact-nonnegative-integer?)]
[refresh-splash (-> void?)]))
(define splash-bitmap #f)
(define splash-cache-bitmap #f)
@ -62,26 +95,29 @@
e ...)))
(printf "finishing ~a\n" line))))]))
(define (get-splash-bitmap) splash-bitmap)
(define (get-splash-bitmap) (on-splash-eventspace/ret splash-bitmap))
(define (set-splash-bitmap bm)
(set! splash-bitmap bm)
(on-splash-eventspace (send splash-canvas on-paint)))
(on-splash-eventspace
(set! splash-bitmap bm)
(send splash-canvas on-paint)))
(define (get-splash-canvas) splash-canvas)
(define (get-splash-eventspace) splash-eventspace)
(define (get-splash-paint-callback) splash-paint-callback)
(define (set-splash-paint-callback sp)
(set! splash-paint-callback sp)
(refresh-splash))
(define (get-splash-paint-callback) (on-splash-eventspace/ret splash-paint-callback))
(define (set-splash-paint-callback sp)
(on-splash-eventspace
(set! splash-paint-callback sp)
(refresh-splash)))
(define (get-splash-width) (on-splash-eventspace/ret (send splash-canvas get-width)))
(define (get-splash-height) (on-splash-eventspace/ret (send splash-canvas get-height)))
(define (set-splash-event-callback cb) (set! splash-event-callback cb))
(define (get-splash-event-callback cb) splash-event-callback)
(define (set-splash-event-callback cb) (on-splash-eventspace (set! splash-event-callback cb)))
(define (get-splash-event-callback) (on-splash-eventspace/ret splash-event-callback))
(define (refresh-splash-on-gauge-change? start range) #f)
(define (set-refresh-splash-on-gauge-change?! f) (set! refresh-splash-on-gauge-change? f))
(define (set-refresh-splash-on-gauge-change?! f)
(on-splash-eventspace (set! refresh-splash-on-gauge-change? f)))
(define (refresh-splash)
@ -118,7 +154,9 @@
[else
(parameterize ([current-eventspace splash-eventspace])
(queue-callback
recompute-bitmap/refresh))]))
recompute-bitmap/refresh))])
(void))
(define (set-splash-progress-bar?! b?)
(on-splash-eventspace/ret
@ -143,8 +181,9 @@
(define-struct icon (bm x y))
(define icons null)
(define (add-splash-icon bm x y)
(set! icons (cons (make-icon bm x y) icons))
(refresh-splash))
(on-splash-eventspace
(set! icons (cons (make-icon bm x y) icons))
(refresh-splash)))
(define (start-splash splash-draw-spec _splash-title width-default
#:allow-funny? [allow-funny? #f]
@ -170,12 +209,10 @@
(send splash-tlw set-icon frame-icon (send frame-icon get-loaded-mask) 'both)))
(cond
[(or (path? splash-draw-spec)
(string? splash-draw-spec)
[(or (path-string? splash-draw-spec)
(is-a? splash-draw-spec bitmap%))
(cond
[(or (path? splash-draw-spec)
(string? splash-draw-spec))
[(path-string? splash-draw-spec)
(unless (file-exists? splash-draw-spec)
(eprintf "WARNING: bitmap path ~s not found\n" splash-draw-spec)
(no-splash))
@ -201,12 +238,7 @@
(send splash-canvas min-height (vector-ref splash-draw-spec 2))
(set! splash-cache-bitmap (make-screen-bitmap
(vector-ref splash-draw-spec 1)
(vector-ref splash-draw-spec 2)))]
[(not splash-draw-spec)
(no-splash)]
[else
(eprintf "WARNING: unknown splash spec: ~s" splash-draw-spec)
(no-splash)])
(vector-ref splash-draw-spec 2)))])
(send splash-tlw reflow-container)
@ -260,23 +292,20 @@
(refresh-splash)))))
(old-load f expected))
(let-values ([(make-compilation-manager-load/use-compiled-handler
manager-trace-handler)
(if (or (getenv "PLTDRCM")
(getenv "PLTDRDEBUG"))
(parameterize ([current-namespace (make-base-namespace)])
(values
(dynamic-require 'compiler/cm 'make-compilation-manager-load/use-compiled-handler)
(dynamic-require 'compiler/cm 'manager-trace-handler)))
(values #f #f))])
(let ([make-compilation-manager-load/use-compiled-handler
(if (or (getenv "PLTDRCM")
(getenv "PLTDRDEBUG"))
(parameterize ([current-namespace (make-base-namespace)])
(dynamic-require 'compiler/cm
'make-compilation-manager-load/use-compiled-handler))
#f)])
(current-load
(let ([old-load (current-load)])
(λ (f expected)
(splash-load-handler old-load f expected))))
(when (and make-compilation-manager-load/use-compiled-handler
manager-trace-handler)
(when make-compilation-manager-load/use-compiled-handler
(printf "PLTDRCM/PLTDRDEBUG: reinstalling CM load handler after setting splash load handler\n")
(current-load/use-compiled (make-compilation-manager-load/use-compiled-handler))))

View File

@ -644,16 +644,24 @@
(error menu-tag "active frame does not have menu bar"))
(send menu-bar on-demand)
(let* ([items (send menu-bar get-items)])
(let loop ([items items]
(let loop ([all-items-this-level items]
[items items]
[this-name (car item-names)]
[wanted-names (cdr item-names)])
(cond
[(null? items)
(error 'menu-select "didn't find a menu: ~e, entire list: ~e" this-name item-names)]
(error 'menu-select
"didn't find a menu: ~e, desired list: ~e, all items at this level ~e"
this-name
item-names
(map (λ (x) (and (is-a? x labelled-menu-item<%>)
(send x get-plain-label)))
all-items-this-level))]
[else (let ([i (car items)])
(cond
[(not (is-a? i labelled-menu-item<%>))
(loop (cdr items)
(loop all-items-this-level
(cdr items)
this-name
wanted-names)]
[(string=? this-name (send i get-plain-label))
@ -664,12 +672,14 @@
[(and (not (null? wanted-names))
(is-a? i menu-item-container<%>))
(loop (send i get-items)
(send i get-items)
(car wanted-names)
(cdr wanted-names))]
[else
(error menu-tag "no menu matching ~e" item-names)])]
[else
(loop (cdr items)
(loop all-items-this-level
(cdr items)
this-name
wanted-names)]))]))))])))

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -4,15 +4,15 @@
(define deps '("srfi-lite-lib"
"data-lib"
["base" #:version "6.2.900.17"]
["base" #:version "6.5.0.2"]
"syntax-color-lib"
["draw-lib" #:version "1.9"]
"snip-lib"
["draw-lib" #:version "1.13"]
["snip-lib" #:version "1.2"]
"wxme-lib"
"pict-lib"
"scheme-lib"
"scribble-lib"
"string-constants-lib"
["string-constants-lib" #:version "1.9"]
"option-contract-lib"
"2d-lib"
"compatibility-lib"
@ -30,4 +30,4 @@
(define pkg-authors '(mflatt robby))
(define version "1.18")
(define version "1.28")

View File

@ -1,7 +1,7 @@
#lang info
(define version '(400))
(define post-install-collection "installer.rkt")
(define install-collection "installer.rkt")
(define copy-man-pages '("mred.1"))
(define release-note-files

View File

@ -3,44 +3,71 @@
compiler/embed
racket/file
racket/path
setup/dirs
setup/cross-system)
(provide post-installer)
(provide installer)
;; Platforms that get a `MrEd' executable:
(define mred-exe-systems '(unix))
(define (post-installer path coll user?)
(define (installer path coll user? no-main?)
(unless no-main?
(do-installer path coll user? #f)
(when (and (not user?)
(find-config-tethered-console-bin-dir))
(do-installer path coll #f #t)))
(when (find-addon-tethered-console-bin-dir)
(do-installer path coll #t #t)))
(define (do-installer path coll user? tethered?)
(define variants (available-mred-variants))
(when (memq (cross-system-type) mred-exe-systems)
(for ([v variants] #:when (memq v '(3m cgc)))
(parameterize ([current-launcher-variant v])
(create-embedding-executable
(prep-dir (mred-program-launcher-path "MrEd" #:user? user?))
#:cmdline '("-I" "scheme/gui/init")
(prep-dir (mred-program-launcher-path "MrEd" #:user? user? #:tethered? tethered?))
#:cmdline (append
(if tethered? (if user? (addon-flags) (config-flags)) null)
'("-I" "scheme/gui/init"))
#:variant v
#:launcher? #t
#:gracket? #t
#:aux `((relative? . ,(not user?)))))))
;; add a mred-text executable that uses the -z flag (preferring a script)
(define tether-mode (and tethered? (if user? 'addon 'config)))
(for ([vs '((script-3m 3m) (script-cgc cgc))])
(let ([v (findf (lambda (v) (memq v variants)) vs)])
(when v
(parameterize ([current-launcher-variant v])
(make-gracket-launcher
#:tether-mode tether-mode
'("-I" "scheme/gui/init" "-z")
(prep-dir (mred-program-launcher-path "mred-text" #:user? user?))
`([relative? . ,(not user?)] [subsystem . console] [single-instance? . #f]))))))
(prep-dir (mred-program-launcher-path "mred-text" #:user? user? #:tethered? tethered?))
`([relative? . ,(not (or user? tethered?))]
[subsystem . console]
[single-instance? . #f]))))))
;; add bin/mred script under OS X
(when (eq? 'macosx (cross-system-type))
(for ([v variants] #:when (memq v '(script-3m script-cgc)))
(parameterize ([current-launcher-variant v])
(make-gracket-launcher
'()
(prep-dir (mred-program-launcher-path "MrEd" #:user? user?))
'([exe-name . "GRacket"] [relative? . ,(not user?)] [exe-is-gracket . #t]))))))
#:tether-mode tether-mode
null
(prep-dir (mred-program-launcher-path "MrEd" #:user? user? #:tethered? tethered?))
`([exe-name . "GRacket"]
[relative? . ,(not (or user? tethered?))]
[exe-is-gracket . #t]))))))
(define (prep-dir p)
(define dir (path-only p))
(make-directory* dir)
p)
(define (addon-flags)
(append
(config-flags)
(list "-A" (path->string (find-system-path 'addon-dir)))))
(define (config-flags)
(list "-C" (path->string (find-config-dir))))

View File

@ -4,6 +4,7 @@ add-color<%>
add-editor-keymap-functions
add-pasteboard-keymap-functions
add-text-keymap-functions
any-control+alt-is-altgr
append-editor-font-menu-items
append-editor-operation-menu-items
application-about-handler

View File

@ -320,6 +320,8 @@
(define scroll-to-last? #f)
(define scroll-bottom? #f)
(define/public (call-as-primary-owner f) (send wx call-as-primary-owner f))
(define/public (set-scroll-via-copy s) (send wx set-scroll-via-copy s))
(define/public (get-scroll-via-copy) (send wx get-scroll-via-copy))
(define allow-scroll-to-last
(entry-point
(case-lambda

View File

@ -143,6 +143,7 @@
scroll-event%
special-control-key
special-option-key
any-control+alt-is-altgr
map-command-as-meta-key
label->plain-label
write-editor-global-footer

View File

@ -182,14 +182,29 @@
panel))]
[as-canvas? (lambda () (or (memq 'vscroll style)
(memq 'auto-vscroll style)
(memq 'hide-vscroll style)
(memq 'hscroll style)
(memq 'auto-hscroll style)))])
(memq 'auto-hscroll style)
(memq 'hide-hscroll style)))])
(check-container-parent cwho parent)
(check-style cwho #f (append '(border deleted)
(if can-canvas?
'(hscroll vscroll auto-hscroll auto-vscroll)
'(hscroll vscroll
auto-hscroll auto-vscroll
hide-hscroll hide-vscroll)
null))
style)
(define (add-scrolls style)
(append
(if (memq 'hide-vscroll style)
'(auto-vscroll)
null)
(if (memq 'hide-hscroll style)
'(auto-hscroll)
null)
style))
(as-entry
(lambda ()
(super-instantiate
@ -208,7 +223,7 @@
wx-canvas-panel%
wx-panel%)])
this this (mred->wx-container parent)
(cons 'transparent style)
(cons 'transparent (add-scrolls style))
(get-initial-label)))
wx)
(lambda () wx)

View File

@ -99,7 +99,13 @@
(define-objc-class RacketGCGLView NSOpenGLView
#:mixins (KeyMouseResponder)
[wxb])
[wxb]
(-a #:async-apply (box (void))
_void (drawRect: [_NSRect r])
(when wxb
(let ([wx (->wx wxb)])
(when wx
(send wx draw-gc-background))))))
(define-objc-class RacketGCWindow NSWindow
#:mixins (RacketEventspaceMethods)
@ -202,12 +208,13 @@
(define NSOpenGLPFASampleBuffers 55)
(define NSOpenGLPFASamples 56)
(define NSOpenGLPFAMultisample 59)
(define NSOpenGLPFAAllowOfflineRenderers 96)
(define NSOpenGLPFAOpenGLProfile 99)
(define NSOpenGLProfileVersionLegacy #x1000)
(define NSOpenGLProfileVersion3_2Core #x3200)
(define (gl-config->pixel-format conf)
(define (gl-config->pixel-format conf allow-offline?)
(let ([conf (or conf (new gl-config%))])
(tell (tell NSOpenGLPixelFormat alloc)
initWithAttributes: #:type (_list i _int)
@ -218,6 +225,9 @@
NSOpenGLProfileVersionLegacy
NSOpenGLProfileVersion3_2Core))
null)
(if allow-offline?
(list NSOpenGLPFAAllowOfflineRenderers)
null)
(if (send conf get-double-buffered) (list NSOpenGLPFADoubleBuffer) null)
(if (send conf get-stereo) (list NSOpenGLPFAStereo) null)
(list
@ -383,7 +393,9 @@
(define/override (get-cocoa-content) content-cocoa)
(define is-gl? (and (not is-combo?) (memq 'gl style)))
(define want-sync-gl? (and is-gl? gl-config (send gl-config get-sync-swap)))
(define/public (can-gl?) is-gl?)
(define/public (sync-gl?) want-sync-gl?)
(define dc #f)
(define blits null)
@ -419,7 +431,7 @@
initWithFrame: #:type _NSRect r)
(let* ([share-context (and gl-config (send gl-config get-share-context))]
[context-handle (and share-context (send share-context get-handle))]
[pf (gl-config->pixel-format gl-config)]
[pf (gl-config->pixel-format gl-config #f)]
[new-context (and
context-handle
(tell (tell NSOpenGLContext alloc)
@ -918,9 +930,9 @@
(define/private (suspend-all-reg-blits)
(let ([cocoa-win (get-cocoa-window)])
(for ([r (in-list reg-blits)])
(tellv cocoa-win removeChildWindow: (car r))
(release (car r))
(scheme_remove_gc_callback (cdr r))))
(tellv cocoa-win removeChildWindow: (vector-ref r 0))
(release (vector-ref r 0))
(scheme_remove_gc_callback (vector-ref r 1))))
(set! reg-blits null))
(define/public (resume-all-reg-blits)
@ -928,10 +940,10 @@
(when (pair? blits)
(set! reg-blits
(for/list ([b (in-list blits)])
(let-values ([(x y w h s img) (apply values b)])
(register-one-blit x y w h s img)))))))
(let-values ([(x y w h s img us unimg) (apply values b)])
(register-one-blit x y w h s img us unimg)))))))
(define/private (register-one-blit x y w h s img)
(define/private (register-one-blit x y w h s img us unimg)
(let ([xb (box x)]
[yb (box y)])
(client-to-screen xb yb #f)
@ -947,7 +959,7 @@
backing: #:type _int NSBackingStoreBuffered
defer: #:type _BOOL NO))]
[glv (and gc-via-gl?
(let ([pf (gl-config->pixel-format #f)])
(let ([pf (gl-config->pixel-format #f #t)])
(begin0
(tell (tell RacketGCGLView alloc)
initWithFrame: #:type _NSRect (make-NSRect (make-NSPoint 0 0)
@ -958,10 +970,14 @@
(tell (tell NSImageView alloc) init))])
(cond
[gc-via-gl?
(tellv (tell glv openGLContext) setValues:
#:type (_ptr i _long) 0
forParameter: #:type _int NSOpenGLCPSwapInterval)
(tellv win setAcceptsMouseMovedEvents: #:type _BOOL #t)
(set-ivar! win wxb (->wxb this))
(set-ivar! glv wxb (->wxb this))
(tellv glv setWantsBestResolutionOpenGLSurface: #:type _uint 1)
(unless (= s 1)
(tellv glv setWantsBestResolutionOpenGLSurface: #:type _uint 1))
(tellv (tell win contentView) addSubview: glv)]
[else
(tellv win setAlphaValue: #:type _CGFloat 0.0)
@ -974,36 +990,56 @@
(when gc-via-gl?
(tellv win orderWindow: #:type _int NSWindowAbove
relativeTo: #:type _NSInteger (tell #:type _NSInteger cocoa-win windowNumber)))
(define uninstall-desc
(if gc-via-gl?
(if (and unimg
;; all white?
(not (for/and ([i (in-range 0 (bytes-length unimg) 4)])
(or (= (bytes-ref unimg i) 0)
(and (= (bytes-ref unimg (+ 1 i)) 255)
(= (bytes-ref unimg (+ 2 i)) 255)
(= (bytes-ref unimg (+ 3 i)) 255))))))
(make-gl-install win glv w h unimg us)
(make-gl-uninstall win glv w h))
(make-gc-action-desc win (selector setAlphaValue:) 0.0)))
(let ([r (scheme_add_gc_callback
(if gc-via-gl?
(make-gl-install win glv w h img s)
(make-gc-action-desc win (selector setAlphaValue:) 1.0))
(if gc-via-gl?
(make-gl-uninstall win glv w h)
(make-gc-action-desc win (selector setAlphaValue:) 0.0)))])
uninstall-desc)])
(when gc-via-gl?
(tellv glv release))
(cons win r)))))))
(vector win r uninstall-desc)))))))
(define/public (register-collecting-blit x y w h on off on-x on-y off-x off-y)
(let ([on (fix-bitmap-size on w h on-x on-y)]
[s (send on get-backing-scale)])
[off (and gc-via-gl?
(fix-bitmap-size off w h on-x on-y))]
[s (send on get-backing-scale)]
[us (send off get-backing-scale)])
(define (bm->img on s)
(let* ([xw (inexact->exact (ceiling (* s w)))]
[xh (inexact->exact (ceiling (* s h)))]
[rgba (make-bytes (* xw xh 4))])
(send on get-argb-pixels 0 0 xw xh rgba #:unscaled? #t)
rgba))
(let ([img (if gc-via-gl?
(let* ([xw (inexact->exact (ceiling (* s w)))]
[xh (inexact->exact (ceiling (* s h)))]
[rgba (make-bytes (* xw xh 4))])
(send on get-argb-pixels 0 0 xw xh rgba #:unscaled? #t)
rgba)
(bitmap->image on))])
(bm->img on s)
(bitmap->image on))]
[unimg (and gc-via-gl? (bm->img off us))])
(atomically
(set! blits (cons (list x y w h s img) blits))
(set! blits (cons (list x y w h s img us unimg) blits))
(when (is-shown-to-root?)
(set! reg-blits (cons (register-one-blit x y w h s img) reg-blits)))))))
(set! reg-blits (cons (register-one-blit x y w h s img us unimg) reg-blits)))))))
(define/public (unregister-collecting-blits)
(atomically
(suspend-all-reg-blits)
(set! blits null))))))
(set! blits null)))
(define/public (draw-gc-background)
(for ([rb (in-list reg-blits)])
(do-gl-action (vector-ref rb 2)))))))
(define canvas-panel%
(class (panel-mixin canvas%)

View File

@ -29,6 +29,7 @@
(define-appserv CGContextAddRect (_fun _CGContextRef _NSRect -> _void))
(define-appserv CGContextAddLines (_fun _CGContextRef (v : (_vector i _NSPoint)) (_long = (vector-length v)) -> _void))
(define-appserv CGContextStrokePath (_fun _CGContextRef -> _void))
(define-appserv CGContextClipToRect (_fun _CGContextRef _NSRect -> _void))
(define-appserv CGContextClipToRects (_fun _CGContextRef (_vector i _NSRect) _size -> _void))
(define-appserv CGContextSetAlpha (_fun _CGContextRef _CGFloat -> _void))

View File

@ -21,7 +21,8 @@
do-backing-flush)
display-bitmap-resolution
make-screen-bitmap
make-window-bitmap)
make-window-bitmap
NSOpenGLCPSwapInterval)
(import-class NSOpenGLContext NSScreen NSGraphicsContext NSWindow)
@ -31,43 +32,42 @@
(class backing-dc%
(init [(cnvs canvas)]
transparent?)
(define canvas cnvs)
(inherit end-delay)
(define canvas cnvs)
(define gl #f)
(define trans? transparent?)
(inherit end-delay internal-get-bitmap internal-copy)
(super-new [transparent? transparent?])
(define gl #f)
(define/override (get-gl-context)
(and (send canvas can-gl?)
(let ([gl-ctx (tell (send canvas get-cocoa-content) openGLContext)])
(or gl
(let ([g (new (class gl-context%
(define/override (get-handle) gl-ctx)
(define/override (do-call-as-current t)
(dynamic-wind
(lambda () (tellv gl-ctx makeCurrentContext))
t
(lambda () (tellv NSOpenGLContext clearCurrentContext))))
(define/override (do-swap-buffers)
(tellv gl-ctx flushBuffer))
(super-new)))])
;; Disable screen sync for GL flushBuffer; otherwise,
(let ([g (new dc-gl-context% [gl-ctx gl-ctx])])
;; By default, disable screen sync for GL flushBuffer; otherwise,
;; flushBuffer can take around 10 msec depending on the timing
;; of event polling, and that can be bad for examples like gears.
;; Maybe whether to sync with the screen should be a configuration
;; option, but I can't tell the difference on my screen.
(tellv gl-ctx setValues:
#:type (_ptr i _long) 0
forParameter: #:type _int NSOpenGLCPSwapInterval)
(unless (send canvas sync-gl?)
(tellv gl-ctx setValues:
#:type (_ptr i _long) 0
forParameter: #:type _int NSOpenGLCPSwapInterval))
(set! gl g)
g)))))
;; Use a quartz bitmap so that text looks good:
(define trans? transparent?)
(define/override (make-backing-bitmap w h)
(make-window-bitmap w h (send canvas get-cocoa-window)
trans?
(send canvas is-flipped?)))
(def/override (copy [real? x] [real? y] [nonnegative-real? w] [nonnegative-real? h]
[real? x2] [real? y2])
(internal-copy x y w h x2 y2
(lambda (cr x y w h x2 y2)
(define bm (internal-get-bitmap))
(and bm
(send bm do-self-copy cr x y w h x2 y2)))))
(define/override (can-combine-text? sz) #t)
@ -94,6 +94,20 @@
(define/override (cancel-delay req)
(send canvas cancel-canvas-flush-delay req))))
(define dc-gl-context%
(class gl-context%
(init [(gtx gl-ctx)])
(define gl-ctx gtx)
(define/override (get-handle) gl-ctx)
(define/override (do-call-as-current t)
(dynamic-wind
(lambda () (tellv gl-ctx makeCurrentContext))
t
(lambda () (tellv NSOpenGLContext clearCurrentContext))))
(define/override (do-swap-buffers)
(tellv gl-ctx flushBuffer))
(super-new)))
(define-local-member-name get-layer)
(define (do-backing-flush canvas dc ctx dx dy)
@ -145,9 +159,11 @@
(display-bitmap-resolution 0 void)))
(define (make-window-bitmap w h win [trans? #t] [flipped? #f])
(if win
(make-object layer-bitmap% w h win trans? flipped?)
(make-screen-bitmap w h)))
(let ([w (max 1 w)]
[h (max 1 h)])
(if win
(make-object layer-bitmap% w h win trans? flipped?)
(make-screen-bitmap w h))))
(define layer-bitmap%
(class quartz-bitmap%
@ -157,20 +173,23 @@
(define layer (make-layer win w h))
(define layer-w w)
(define layer-h h)
(define/public (get-layer) layer)
(define is-trans? trans?)
(define s-bm #f)
(let ([bs (inexact->exact
(display-bitmap-resolution 0 (lambda () 1)))])
(super-make-object w h trans? bs
(let ([cg (CGLayerGetContext layer)])
(unless flipped?
(CGContextTranslateCTM cg 0 h)
(CGContextScaleCTM cg 1 -1))
(unless (= bs 1)
(CGContextScaleCTM cg (/ 1 bs) (/ 1 bs)))
cg)))
(define bs (inexact->exact
(display-bitmap-resolution 0 (lambda () 1))))
(super-make-object w h trans? bs
(let ([cg (CGLayerGetContext layer)])
(unless flipped?
(CGContextTranslateCTM cg 0 h)
(CGContextScaleCTM cg 1 -1))
(unless (= bs 1)
(CGContextScaleCTM cg (/ 1 bs) (/ 1 bs)))
cg))
(define/public (get-layer) layer)
(define/override (draw-bitmap-to cr sx sy dx dy w h alpha clipping-region)
;; Called when the destination rectangle is inside the clipping region
@ -204,13 +223,7 @@
(cairo_matrix_t-y0 m)))
(cairo_surface_flush s)
(define cg (cairo_quartz_surface_get_cg_context s))
(begin
;; A Cairo flush doesn't reset the clipping region. The
;; implementation of clipping is that there's a saved
;; GState that we can use to get back to the original
;; clipping region, so restore (and save again) that state:
(CGContextRestoreGState cg)
(CGContextSaveGState cg))
(reset-cairo-clipping cg)
(CGContextSaveGState cg)
(CGContextConcatCTM cg trans)
(let ([n (cairo_rectangle_list_t-num_rectangles rs)])
@ -237,7 +250,37 @@
#t)]
[else #f]))
(define s-bm #f)
(define/override (do-self-copy cr x y w h x2 y2)
(define bs (get-backing-scale))
(define s (cairo_get_target cr))
(cairo_surface_flush s)
(define cg (cairo_quartz_surface_get_cg_context s))
(define orig-size (CGLayerGetSize layer))
(atomically
(reset-cairo-clipping cg)
(CGContextSaveGState cg)
(CGContextScaleCTM cg bs (- bs))
(define sz (CGLayerGetSize layer))
(define lh (NSSize-height sz))
(CGContextTranslateCTM cg 0 (- lh))
(CGContextClipToRect cg (make-NSRect
(make-NSPoint x2 (- lh (+ y2 h)))
(make-NSSize w h)))
(CGContextDrawLayerAtPoint cg
(make-NSPoint (- x2 x) (- y y2))
layer)
(CGContextRestoreGState cg)
(cairo_surface_mark_dirty s))
#t)
(define/private (reset-cairo-clipping cg)
;; A Cairo flush doesn't reset the clipping region. The
;; implementation of clipping is that there's a saved
;; GState that we can use to get back to the original
;; clipping region, so restore (and save again) that state:
(CGContextRestoreGState cg)
(CGContextSaveGState cg))
(define/override (get-cairo-surface)
;; Convert to a platform bitmap, which Cairo understands
(let ([t-bm (or s-bm

View File

@ -90,9 +90,9 @@
(when wxb
(let ([wx (->wx wxb)])
(when wx
(send wx clean-up)
(queue-window-event wx (lambda ()
(send wx queue-on-size)
(send wx clean-up)))
(send wx queue-on-size)))
;; Live resize:
(constrained-reply (send wx get-eventspace)
(lambda ()
@ -316,7 +316,10 @@
(define/public (clean-up)
;; When a window is resized, then any drawing that is in flight
;; might draw outside the canvas boundaries. Just refresh everything.
(tellv cocoa display))
(call-with-refreshable
(lambda ()
(unless (version-10.11-or-later?)
(tellv cocoa display)))))
(when label
(tellv cocoa setTitle: #:type _NSString label))
@ -352,16 +355,22 @@
(not (send p get-sheet)))))
(let ([p (get-parent)])
(send p set-sheet this)
(tellv (tell NSApplication sharedApplication)
beginSheet: cocoa
modalForWindow: (send p get-cocoa)
modalDelegate: #f
didEndSelector: #:type _SEL #f
contextInfo: #f))
(call-with-refreshable
(lambda ()
(tellv (tell NSApplication sharedApplication)
beginSheet: cocoa
modalForWindow: (send p get-cocoa)
modalDelegate: #f
didEndSelector: #:type _SEL #f
contextInfo: #f))))
(if float?
(tellv cocoa orderFront: #f)
(call-with-refreshable
(lambda ()
(tellv cocoa orderFront: #f)))
(begin
(tellv cocoa makeKeyAndOrderFront: #f)
(call-with-refreshable
(lambda ()
(tellv cocoa makeKeyAndOrderFront: #f)))
(when unshown-fullscreen?
(set! unshown-fullscreen? #f)
(tellv cocoa toggleFullScreen: #f)))))
@ -377,11 +386,8 @@
(tellv cocoa deminiaturize: #f)
(define fs? (fullscreened?))
(set! unshown-fullscreen? fs?)
(tellv cocoa orderOut: #f)
(when fs?
;; Need to select another window to get rid of
;; the window's screen:
(tellv (get-app-front-window) orderFront: #f)))
(tellv cocoa setReleasedWhenClosed: #:type _BOOL #f)
(tellv cocoa close))
(force-window-focus)))
(register-frame-shown this on?)
(let ([num (tell #:type _NSInteger cocoa windowNumber)])
@ -398,12 +404,7 @@
(when (eventspace-shutdown? es)
(error (string->symbol
(format "show method in ~a" (if is-a-dialog? 'dialog% 'frame%)))
"the eventspace hash been shutdown"))
(when (version-10.11-or-later?)
;; Ensure that the basic window background is drawn before
;; we potentially suspend redrawing. Otherwise, the window
;; can start black and end up with a too-dark titlebar.
(tellv cocoa display))
"the eventspace has been shutdown"))
(when saved-child
(if (eq? (current-thread) (eventspace-handler-thread es))
(do-paint-children)
@ -416,20 +417,53 @@
(direct-show on?)))
(define flush-disabled 0)
(define flush-disable-disabled 0)
(define/public (disable-flush-window)
(when (zero? flush-disabled)
(when (version-10.11-or-later?)
(tellv cocoa setAutodisplay: #:type _BOOL #f))
(tellv cocoa disableFlushWindow))
(when (zero? flush-disable-disabled)
(when (version-10.11-or-later?)
(tellv cocoa setAutodisplay: #:type _BOOL #f))
(tellv cocoa disableFlushWindow)))
(set! flush-disabled (add1 flush-disabled)))
(define/public (enable-flush-window)
(set! flush-disabled (sub1 flush-disabled))
(when (zero? flush-disabled)
(tellv cocoa enableFlushWindow)
(when (zero? flush-disable-disabled)
(tellv cocoa enableFlushWindow))
(when (version-10.11-or-later?)
(tellv cocoa setAutodisplay: #:type _BOOL #t))))
(when (zero? flush-disable-disabled)
(tellv cocoa setAutodisplay: #:type _BOOL #t))
(queue-window-refresh-event
this
(lambda ()
(tellv cocoa displayIfNeeded))))))
(define/private (call-with-refreshable thunk)
(cond
[(not (version-10.11-or-later?))
(thunk)]
[(zero? flush-disabled)
;; In case a display got lost earlier:
(tellv cocoa display)
(thunk)]
[else
(atomically
(dynamic-wind
(lambda ()
(when (zero? flush-disable-disabled)
(tellv cocoa setAutodisplay: #:type _BOOL #t)
(tellv cocoa enableFlushWindow))
(tellv cocoa display)
(set! flush-disable-disabled (add1 flush-disable-disabled)))
thunk
(lambda ()
(set! flush-disable-disabled (sub1 flush-disable-disabled))
(when (zero? flush-disable-disabled)
(unless (zero? flush-disabled)
(tellv cocoa setAutodisplay: #:type _BOOL #f)
(tellv cocoa disableFlushWindow))))))]))
(define/public (force-window-focus)
(let ([next (get-app-front-window)])
@ -575,25 +609,27 @@
(unless (and (equal? x -1) (equal? y -1))
(internal-move x y))
(let ([f (tell #:type _NSRect cocoa frame)])
(tellv cocoa setFrame:
#:type _NSRect (make-NSRect
(make-NSPoint (if (and is-a-dialog?
(let ([p (get-parent)])
(and p
(eq? this (send p get-sheet)))))
;; need to re-center sheet:
(let* ([p (get-parent)]
[px (send p get-x)]
[pw (send p get-width)])
(+ px (/ (- pw w) 2)))
;; keep current x position:
(NSPoint-x (NSRect-origin f)))
;; keep current y position:
(- (NSPoint-y (NSRect-origin f))
(- h
(NSSize-height (NSRect-size f)))))
(make-NSSize w h))
display: #:type _BOOL #t)))
(call-with-refreshable
(lambda ()
(tellv cocoa setFrame:
#:type _NSRect (make-NSRect
(make-NSPoint (if (and is-a-dialog?
(let ([p (get-parent)])
(and p
(eq? this (send p get-sheet)))))
;; need to re-center sheet:
(let* ([p (get-parent)]
[px (send p get-x)]
[pw (send p get-width)])
(+ px (/ (- pw w) 2)))
;; keep current x position:
(NSPoint-x (NSRect-origin f)))
;; keep current y position:
(- (NSPoint-y (NSRect-origin f))
(- h
(NSSize-height (NSRect-size f)))))
(make-NSSize w h))
display: #:type _BOOL #t)))))
(define/override (internal-move x y)
(let ([x (if (not x) (get-x) x)]
[y (if (not y) (get-y) y)])

View File

@ -10,7 +10,8 @@
scheme_remove_gc_callback
make-gc-action-desc
make-gl-install
make-gl-uninstall))
make-gl-uninstall
do-gl-action))
;; ----------------------------------------
;; 10.10 and earlier: change window opacity
@ -74,6 +75,9 @@
(define-gl glClearColor (_fun _GLclampf _GLclampf _GLclampf _GLclampf -> _void))
(define-gl glClear (_fun _GLbitfield -> _void))
(define-gl glCallList (_fun _GLint -> _void))
(define-gl glFlush (_fun -> _void))
(define-gl glClear-pointer _fpointer
#:c-id glClear)
(define-gl glCallList-pointer _fpointer
@ -112,12 +116,14 @@
(define size (* w h 4))
(define size-4 (- size 4))
(define rgba (make-bytes size))
(for ([i (in-range 0 size 4)])
(define j (- size-4 i))
(bytes-set! rgba (+ i 3) (bytes-ref argb j))
(bytes-set! rgba i (bytes-ref argb (+ j 1)))
(bytes-set! rgba (+ i 1) (bytes-ref argb (+ j 2)))
(bytes-set! rgba (+ i 2) (bytes-ref argb (+ j 3))))
(for ([x (in-range w)])
(for ([y (in-range h)])
(define i (* (+ x (* w y)) 4))
(define j (* (+ x (* w (- h y 1))) 4))
(bytes-set! rgba (+ i 3) (bytes-ref argb j))
(bytes-set! rgba i (bytes-ref argb (+ j 1)))
(bytes-set! rgba (+ i 1) (bytes-ref argb (+ j 2)))
(bytes-set! rgba (+ i 2) (bytes-ref argb (+ j 3)))))
(define tex (glGenTexture))
@ -172,6 +178,8 @@
(tellv old-gl makeCurrentContext)
(tellv NSOpenGLContext clearCurrentContext))
;; The shape of this vector is parsed back out by
;; `do-gl-action`, below:
(vector
(vector 'ptr_ptr->save
msg-send-proc
@ -237,3 +245,18 @@
(vector 'save!_ptr->void
msg-send-proc
(selector makeCurrentContext))))
(define (do-gl-action vec)
(when (= 8 (vector-length vec))
(define gl (vector-ref (vector-ref vec 1) 2))
(define list-id (vector-ref (vector-ref vec 3) 2))
(define old-ctx (tell NSOpenGLContext currentContext))
(tellv gl makeCurrentContext)
(glClear GL_COLOR_BUFFER_BIT)
(glCallList list-id)
(glFlush)
(tellv gl flushBuffer)
(tellv NSOpenGLContext clearCurrentContext)
(when old-ctx
(tellv old-ctx makeCurrentContext))))

View File

@ -282,7 +282,7 @@
(define/public (append-column title)
(atomically
(let ([col (as-objc-allocation
(tell (tell NSTableColumn alloc) initWithIdentifier: content-cocoa))])
(tell (tell NSTableColumn alloc) initWithIdentifier: #:type _NSString title))])
(tellv content-cocoa addTableColumn: col)
(tellv (tell col headerCell) setStringValue: #:type _NSString title)
(set! column-cocoas (append column-cocoas (list col)))

View File

@ -85,6 +85,7 @@
get-color-from-user
special-option-key
special-control-key
any-control+alt-is-altgr
get-highlight-background-color
get-highlight-text-color
make-screen-bitmap

View File

@ -65,6 +65,7 @@
play-sound
file-creator-and-type
file-selector
any-control+alt-is-altgr
key-symbol-to-menu-key
needs-grow-box-spacer?
get-current-mouse-state

View File

@ -19,15 +19,33 @@
(define-runtime-path psm-tab-bar-dir
'(so "PSMTabBarControl.framework"))
(define-runtime-path mm-tab-bar-dir
;; This directory will not exist for platforms other than x86_64:
'(so "MMTabBarView.framework"))
;; Load PSMTabBarControl:
(void (ffi-lib (build-path psm-tab-bar-dir "PSMTabBarControl")))
(define use-mm?
(and (version-10.10-or-later?)
64-bit?
(directory-exists? mm-tab-bar-dir)))
;; Load MMTabBarView or PSMTabBarControl:
(if use-mm?
(void (ffi-lib (build-path mm-tab-bar-dir "MMTabBarView")))
(void (ffi-lib (build-path psm-tab-bar-dir "PSMTabBarControl"))))
(define NSNoTabsNoBorder 6)
(define NSDefaultControlTint 0)
(define NSClearControlTint 7)
(import-class NSView NSTabView NSTabViewItem PSMTabBarControl)
(import-class NSView NSTabView NSTabViewItem)
(define TabBarControl
(if use-mm?
(let ()
(import-class MMTabBarView)
MMTabBarView)
(let ()
(import-class PSMTabBarControl)
PSMTabBarControl)))
(import-protocol NSTabViewDelegate)
(define NSOrderedAscending -1)
@ -49,8 +67,26 @@
(when (and wx (send wx callbacks-enabled?))
(queue-window*-event wxb (lambda (wx) (send wx do-callback)))))))
(define-objc-class RacketPSMTabBarControl PSMTabBarControl
#:mixins (FocusResponder KeyMouseResponder CursorDisplayer)
;; The MMTabBarView widget doesn't support disabling, so we have to
;; implement it. Also, we need to override a method to disable (for now)
;; reordering tabs.
(define-objc-mixin (EnableMixin Superclass)
[wxb]
(-a _id (hitTest: [_NSPoint pt])
(let ([wx (->wx wxb)])
(if (and wx
(not (send wx is-enabled-to-root?)))
#f
(super-tell hitTest: #:type _NSPoint pt))))
(-a _BOOL (shouldStartDraggingAttachedTabBarButton: b withMouseDownEvent: evt)
#f))
;; A no-op mixin instead of `EnableMixin` for PSMTabBarControl:
(define-objc-mixin (EmptyMixin Superclass)
[wxb])
(define-objc-class RacketPSMTabBarControl TabBarControl
#:mixins (FocusResponder KeyMouseResponder CursorDisplayer (if use-mm? EnableMixin EmptyMixin))
[wxb]
(-a _void (tabView: [_id cocoa] didSelectTabViewItem: [_id item-cocoa])
(super-tell #:type _void tabView: cocoa didSelectTabViewItem: item-cocoa)
@ -83,8 +119,10 @@
(tellv tabv-cocoa setDelegate: i)
(tellv tabv-cocoa setTabViewType: #:type _int NSNoTabsNoBorder)
(tellv i setTabView: tabv-cocoa)
(tellv i setStyleNamed: #:type _NSString "Aqua")
;;(tellv i setSizeCellsToFit: #:type _BOOL #t)
(tellv i setStyleNamed: #:type _NSString (if use-mm? "Yosemite" "Aqua"))
;; (tellv i setSizeCellsToFit: #:type _BOOL #t)
(when use-mm?
(tellv i setResizeTabsToFitTotalWidth: #:type _BOOL #t))
(tellv i setDisableTabClose: #:type _BOOL #t)
i)))
@ -204,7 +242,8 @@
(tellv tabv-cocoa setControlTint: #:type _int
(if on? NSDefaultControlTint NSClearControlTint))
(when control-cocoa
(tellv control-cocoa setEnabled: #:type _BOOL on?))))
(unless use-mm?
(tellv control-cocoa setEnabled: #:type _BOOL on?)))))
(define/override (can-accept-focus?)
(and (not control-cocoa)

View File

@ -21,8 +21,6 @@
(define _OSStatus _sint32)
(define 64-bit? (= (ctype-sizeof _long) 8))
(define _CGFloat (make-ctype (if 64-bit? _double _float)
(lambda (v) (if (and (number? v)
(exact? v))

View File

@ -21,6 +21,7 @@
clean-menu-label
->wxb
->wx
64-bit?
old-cocoa?
version-10.6-or-later?
version-10.7-or-later?
@ -74,6 +75,8 @@
(and wxb
(weak-box-value wxb)))
(define 64-bit? (= (ctype-sizeof _long) 8))
(define-appkit NSAppKitVersionNumber _double)
(define old-cocoa?

View File

@ -621,11 +621,13 @@
(define enabled? #t)
(define/public (is-enabled-to-root?)
(and (is-window-enabled?) (is-parent-enabled-to-root?)))
(and (is-window-enabled?/raw) (is-parent-enabled-to-root?)))
(define/public (is-parent-enabled-to-root?)
(send parent is-enabled-to-root?))
(define/public (is-window-enabled?)
(define/public (is-window-enabled?/raw)
enabled?)
(define/public (is-window-enabled?)
(is-window-enabled?/raw))
(define/public (enable on?)
(atomically
(set! enabled? on?)
@ -761,7 +763,16 @@
(is-enabled-to-root?))
(let ([w (tell cocoa window)])
(when w
(tellv w makeFirstResponder: (get-cocoa-focus))))))
(tellv w makeFirstResponder: (get-cocoa-focus))
;; Within a floating frame or when potentially taking
;; focus from a floating frame, also make the frame the
;; key window:
(let ([top (get-wx-window)])
(when (and (or (send top floating?)
(tell #:type _BOOL w isMainWindow))
(tell #:type _bool w isVisible))
(tellv w makeKeyAndOrderFront: #f)))))))
(define/public (on-set-focus) (void))
(define/public (on-kill-focus) (void))

View File

@ -43,6 +43,13 @@
(class (record-dc-mixin (dc-mixin bitmap-dc-backend%))
(init transparent?)
(define retained-cr #f)
(define retained-counter 0)
(define needs-flush? #f)
(define nada? #t)
(define flush-suspends 0)
(define req #f)
(inherit internal-get-bitmap
internal-set-bitmap
reset-cr
@ -67,11 +74,6 @@
(define/public (queue-backing-flush)
(void))
(define retained-cr #f)
(define retained-counter 0)
(define needs-flush? #f)
(define nada? #t)
;; called with a procedure that is applied to a bitmap;
;; returns #f if there's nothing to flush
(define/public (on-backing-flush proc)
@ -96,8 +98,9 @@
(set! retained-cr #f)
(internal-set-bitmap #f #t)
(super release-cr retained-cr)
(proc bm)
(release-backing-bitmap bm)))))
(when bm
(proc bm)
(release-backing-bitmap bm))))))
(define/public (start-backing-retained)
(as-entry
@ -133,6 +136,9 @@
(when (zero? flush-suspends)
(queue-backing-flush)))
(define/override (release-unchanged-cr cr)
(void))
(define/override (erase)
(super erase)
(when (= (get-clear-operator)
@ -143,9 +149,6 @@
(super erase)
(set! nada? #t))
(define flush-suspends 0)
(define req #f)
(define/public (request-delay) (void))
(define/public (cancel-delay req) (void))

View File

@ -3,6 +3,7 @@
racket/draw/private/color)
(provide special-control-key
special-option-key
any-control+alt-is-altgr
file-creator-and-type
get-panel-background
fill-private-color)
@ -19,6 +20,12 @@
[() special-option-key?]
[(on?) (set! special-option-key? (and on? #t))]))
(define any-control+alt-is-altgr? #f)
(define any-control+alt-is-altgr
(case-lambda
[() any-control+alt-is-altgr?]
[(on?) (set! any-control+alt-is-altgr? (and on? #t))]))
(define file-creator-and-type
(case-lambda
[(path cr ty) (void)]

View File

@ -469,7 +469,8 @@
GDK_POINTER_MOTION_MASK
GDK_FOCUS_CHANGE_MASK
GDK_ENTER_NOTIFY_MASK
GDK_LEAVE_NOTIFY_MASK))
GDK_LEAVE_NOTIFY_MASK
GDK_SCROLL_MASK))
(unless (or (memq 'no-focus style)
(is-panel?))
(gtk_widget_set_can_focus client-gtk #t))

View File

@ -131,9 +131,9 @@
(GdkEventWindowState-new_window_state evt))))
#f))
(define-runtime-path plt-16x16-file '(lib "icons/plt-16x16.png"))
(define-runtime-path plt-32x32-file '(lib "icons/plt-32x32.png"))
(define-runtime-path plt-48x48-file '(lib "icons/plt-48x48.png"))
(define-runtime-path plt-16x16-file '(lib "icons/plt-icon-16x16.png"))
(define-runtime-path plt-32x32-file '(lib "icons/plt-icon-32x32.png"))
(define-runtime-path plt-48x48-file '(lib "icons/plt-icon-48x48.png"))
(define icon-pixbufs+glist
(delay

View File

@ -144,6 +144,9 @@
(define-gtk gtk_widget_get_display (_fun _GtkWidget -> _GdkDisplay))
(define-gtk gtk_widget_get_screen (_fun _GtkWidget -> _GdkScreen))
(define-glx glXSwapIntervalEXT (_fun _Display _XID _int -> _void)
#:fail (lambda () void))
;; ===================================================================================================
;; GLX versions and extensions queries
@ -247,9 +250,10 @@
(dynamic-wind
(λ ()
(set! old-handler
(XSetErrorHandler (cast flag-x-error-handler
(_fun #:atomic? #t _Display _XErrorEvent -> _int)
_fpointer))))
(XSetErrorHandler
(cast flag-x-error-handler
(_fun #:atomic? #t _Display _XErrorEvent -> _int)
_fpointer))))
(λ ()
(set! create-context-error? #f)
(glXCreateNewContext xdisplay cfg GLX_RGBA_TYPE share-gl #t))
@ -290,7 +294,11 @@
(define gl
(dynamic-wind
(λ ()
(set! old-handler (XSetErrorHandler flag-x-error-handler)))
(set! old-handler
(XSetErrorHandler
(cast flag-x-error-handler
(_fun #:atomic? #t _Display _XErrorEvent -> _int)
_fpointer))))
(λ ()
(set! create-context-error? #f)
(glXCreateContextAttribsARB xdisplay cfg share-gl #t context-attribs))
@ -419,6 +427,9 @@
;; The above will return a direct rendering context when it can
;; If it doesn't, the context will be version 1.4 or lower, unless GLX is implemented with
;; proprietary extensions (NVIDIA's drivers sometimes do this)
(when (and widget (send conf get-sync-swap))
(glXSwapIntervalEXT xdisplay (gdk_x11_drawable_get_xid drawable) 1))
;; Now wrap the GLX context in a gl-context%
(cond

View File

@ -9,7 +9,11 @@
(provide (protect-out (all-defined-out)))
(define-runtime-lib gio-lib
[(unix) (ffi-lib "libgio-2.0" '("0" ""))]
[(unix) (ffi-lib "libgio-2.0" '("0" "")
;; For old glib, libgio isn't separate;
;; try to find bindings in already-loaded
;; libraries:
#:fail (lambda () #f))]
[(macosx)
(ffi-lib "libgio-2.0.0.dylib")]
[(windows)

View File

@ -8,7 +8,9 @@
(define (get-gdk3-lib)
(ffi-lib "libgdk-3" '("0" "") #:fail (lambda () #f)))
(define (get-gtk3-lib)
(ffi-lib "libgtk-3" '("0" "") #:fail (lambda () #f)))
;; Open in "global" mode so that gtk_print_operation_run()
;; can find the printer dialog using _g_module_symbol():
(ffi-lib "libgtk-3" '("0" "") #:global? #t #:fail (lambda () #f)))
(define gtk3?
(and (not (getenv "PLT_GTK2"))

View File

@ -139,8 +139,6 @@
(gtk_fixed_move (get-container-gtk) child-gtk (->screen x) (->screen y))
(gtk_widget_set_size_request child-gtk (->screen w) (->screen h)))))
(define-gdk gdk_window_has_native (_fun _GdkWindow -> _gboolean))
(define panel%
(class (panel-container-mixin (panel-mixin window%))
(init parent

View File

@ -86,6 +86,7 @@
get-color-from-user
special-option-key
special-control-key
any-control+alt-is-altgr
get-highlight-background-color
get-highlight-text-color
make-screen-bitmap

View File

@ -56,6 +56,7 @@
file-creator-and-type
special-control-key
special-option-key
any-control+alt-is-altgr
get-panel-background
fill-private-color
get-color-from-user

View File

@ -67,6 +67,7 @@
(define-gtk gtk_widget_get_style (_fun _GtkWidget -> _GtkStyle-pointer))
(define-gtk gtk_rc_get_style (_fun _GtkWidget -> _GtkStyle-pointer))
(define-gtk gtk_text_view_new (_fun -> _GtkWidget))
(define-gtk gtk_widget_destroy (_fun _GtkWidget -> _void))
(define the-text-style
(let ([w (gtk_text_view_new)])
@ -74,8 +75,7 @@
(g_object_ref style)
(begin0
style
(g_object_ref_sink w)
(g_object_unref w)))))
(gtk_widget_destroy w)))))
(define (extract-color-values c)
(define (s v) (arithmetic-shift v -8))

View File

@ -10,6 +10,9 @@
(provide
(protect-out do-single-instance))
;; ----------------------------------------
;; Old-style -singleInstance support lith libunqiue
(define unique-lib-name "libunique-1.0")
(define unique-lib
@ -56,14 +59,94 @@
(exn-message exn))))])
(let* ([p (open-input-bytes d)]
[vec (read p)])
(for-each
queue-file-event
(map (lambda (s) (if (bytes? s)
(bytes->path s)
(string->path s)))
(vector->list vec))))))
(handle-argv vec))))
UNIQUE_RESPONSE_OK))
(define (send-command-line app)
(let ([msg (unique_message_data_new)]
[b (let ([o (open-output-bytes)])
(write (for/vector ([p (in-vector (current-command-line-arguments))])
(define cp (path->complete-path p))
(define s (path->string cp))
(if (equal? cp (string->path s))
s
;; can't represent as string; use bytes
(path->bytes cp)))
o)
(get-output-bytes o))])
(unique_message_data_set msg b (bytes-length b))
(unique_app_send_message app 42 msg)))
(define (do-single-instance/libunique)
(let ([app (unique_app_new (build-app-name) #f)])
(when app
(unique_app_add_command app "startup" 42)
(when (unique_app_is_running app)
(when (= (send-command-line app)
UNIQUE_RESPONSE_OK)
(exit 0)))
(void (connect-message-received app)))))
;; ----------------------------------------
;; New-style -singleInstance support with Gtk
(define _GtkApplication _GtkWidget) ; (_cpointer/null 'GtkApplication)
(define _GApplicationCommandLine (_cpointer 'GApplicationCommandLine))
(define-gtk gtk_application_new (_fun _string _int -> _GtkApplication)
#:fail (lambda () #f))
(define-gdk g_application_get_is_remote (_fun _GtkApplication -> _gboolean)
#:make-fail make-not-available)
(define-gdk g_application_run (_fun _GtkApplication _int (_vector i _string) -> _gboolean)
#:make-fail make-not-available)
(define-gdk g_application_command_line_get_arguments
(_fun _GApplicationCommandLine (n : (_ptr o _int)) -> (p : _pointer) -> (values p n))
#:make-fail make-not-available)
(define-gdk g_strfreev (_fun _pointer -> _void)
#:make-fail make-not-available)
(define-signal-handler connect-activate "activate"
(_fun _GtkApplication -> _void)
(lambda (app)
(void)))
(define-signal-handler connect-command-line "command-line"
(_fun _GtkApplication _GApplicationCommandLine -> _void)
(lambda (app cmdline)
(define-values (args n) (g_application_command_line_get_arguments cmdline))
(define argv (cast args _pointer (_vector o _string n)))
(g_strfreev args)
(handle-argv argv)))
(define APPLICATION_HANDLES_COMMAND_LINE 8)
(define (do-single-instance/gtk)
(define app (gtk_application_new (build-app-name) APPLICATION_HANDLES_COMMAND_LINE))
(when app
(define args (for/vector ([i (current-command-line-arguments)])
(path->string (path->complete-path i))))
(g_application_run app (vector-length args) args)
(when (g_application_get_is_remote app)
(exit 0))
(connect-activate app)
(connect-command-line app)))
;; ----------------------------------------
(define (do-single-instance)
(if gtk_application_new
(do-single-instance/gtk)
(do-single-instance/libunique)))
(define (handle-argv vec)
(for-each
queue-file-event
(map (lambda (s) (if (bytes? s)
(bytes->path s)
(string->path s)))
(vector->list vec))))
(define-mz gethostname (_fun _pointer _long -> _int)
#:fail (lambda () #f))
@ -87,28 +170,3 @@
(define (encode s)
(regexp-replace* #rx"=|\r\n" (base64-encode (string->bytes/utf-8 s)) ""))
(define (send-command-line app)
(let ([msg (unique_message_data_new)]
[b (let ([o (open-output-bytes)])
(write (for/vector ([p (in-vector (current-command-line-arguments))])
(define cp (path->complete-path p))
(define s (path->string cp))
(if (equal? cp (string->path s))
s
;; can't represent as string; use bytes
(path->bytes cp)))
o)
(get-output-bytes o))])
(unique_message_data_set msg b (bytes-length b))
(unique_app_send_message app 42 msg)))
(define (do-single-instance)
(let ([app (unique_app_new (build-app-name) #f)])
(when app
(unique_app_add_command app "startup" 42)
(when (unique_app_is_running app)
(when (= (send-command-line app)
UNIQUE_RESPONSE_OK)
(exit 0)))
(void (connect-message-received app)))))

View File

@ -269,28 +269,30 @@
(or
(map-key-code kv)
(integer->char (gdk_keyval_to_unicode kv))))]
[key-code (if scroll?
(let ([dir (GdkEventScroll-direction event)])
[key-code (cond
[scroll?
(let ([dir (GdkEventScroll-direction event)])
(cond
[(= dir GDK_SCROLL_UP) 'wheel-up]
[(= dir GDK_SCROLL_DOWN) 'wheel-down]
[(= dir GDK_SCROLL_LEFT) 'wheel-left]
[(= dir GDK_SCROLL_RIGHT) 'wheel-right]
[(= dir GDK_SCROLL_SMOOTH)
(define-values (dx dy) (gdk_event_get_scroll_deltas event))
(cond
[(= dir GDK_SCROLL_UP) 'wheel-up]
[(= dir GDK_SCROLL_DOWN) 'wheel-down]
[(= dir GDK_SCROLL_LEFT) 'wheel-left]
[(= dir GDK_SCROLL_RIGHT) 'wheel-right]
[(= dir GDK_SCROLL_SMOOTH)
(define-values (dx dy) (gdk_event_get_scroll_deltas event))
(cond
[(positive? dy) 'wheel-down]
[(negative? dy) 'wheel-up]
[(positive? dx) 'wheel-right]
[(negative? dx) 'wheel-left]
[else #f])]
[else #f]))
(keyval->code (GdkEventKey-keyval event)))]
[(positive? dy) 'wheel-down]
[(negative? dy) 'wheel-up]
[(positive? dx) 'wheel-right]
[(negative? dx) 'wheel-left]
[else #f])]
[else #f]))]
[(and (string? im-str)
(= 1 (string-length im-str)))
(string-ref im-str 0)]
[else
(keyval->code (GdkEventKey-keyval event))])]
[k (new key-event%
[key-code (if (and (string? im-str)
(= 1 (string-length im-str)))
(string-ref im-str 0)
key-code)]
[key-code key-code]
[shift-down (bit? modifiers GDK_SHIFT_MASK)]
[control-down (bit? modifiers GDK_CONTROL_MASK)]
[meta-down (bit? modifiers GDK_MOD1_MASK)]
@ -704,7 +706,15 @@
(send parent in-floating?))
(define/public (set-focus)
(gtk_widget_grab_focus (get-client-gtk)))
(define gtk (get-client-gtk))
(gtk_widget_grab_focus gtk)
;; Force focus to or away from a floating window:
(cond
[(and (in-floating?)
(is-shown-to-root?))
(gdk_keyboard_grab (widget-window gtk) #t 0)]
[else
(gdk_keyboard_ungrab 0)]))
(define cursor-handle #f)
(define/public (set-cursor v)

View File

@ -1,13 +1,16 @@
#lang racket/base
(require racket/runtime-path
(for-syntax racket/base))
setup/cross-system
(for-syntax racket/base
setup/cross-system))
(provide
(protect-out (all-defined-out)))
(define-runtime-module-path-index platform-lib
#:runtime?-id runtime?
(let ([gtk-lib
'(lib "mred/private/wx/gtk/platform.rkt")])
(case (system-type)
(case (if runtime? (system-type) (cross-system-type))
[(windows) (if (getenv "PLT_WIN_GTK")
gtk-lib
'(lib "mred/private/wx/win32/platform.rkt"))]
@ -72,6 +75,7 @@
get-color-from-user
special-option-key
special-control-key
any-control+alt-is-altgr
get-highlight-background-color
get-highlight-text-color
make-screen-bitmap

View File

@ -401,15 +401,19 @@
(define h-scroll-visible? hscroll?)
(define v-scroll-visible? vscroll?)
(define/public (show-scrollbars h? v?)
(when hscroll?
(atomically
(set! h-scroll-visible? (and h? #t))
(ShowScrollBar canvas-hwnd SB_HORZ h?)))
(when vscroll?
(atomically
(set! v-scroll-visible? (and v? #t))
(ShowScrollBar canvas-hwnd SB_VERT v?)))
(reset-dc))
(unless (and (equal? h-scroll-visible?
(and h? hscroll? #t))
(equal? v-scroll-visible?
(and v? vscroll? #t)))
(when hscroll?
(atomically
(set! h-scroll-visible? (and h? #t))
(ShowScrollBar canvas-hwnd SB_HORZ h?)))
(when vscroll?
(atomically
(set! v-scroll-visible? (and v? #t))
(ShowScrollBar canvas-hwnd SB_VERT v?)))
(reset-dc)))
(define/override (do-set-scrollbars h-step v-step
h-len v-len

View File

@ -428,9 +428,18 @@
(set! focus-window-path #f)))
(define/override (set-top-focus win win-path child-hwnd)
(set! focus-window-path (cons this win-path))
(when (ptr-equal? hwnd (GetActiveWindow))
(define active-hwnd (GetActiveWindow))
(when (or (ptr-equal? hwnd active-hwnd)
(and (or float-without-caption?
(let ([wx (any-hwnd->wx active-hwnd)])
(and wx
(send wx is-floating?))))
(is-shown?)))
(void (SetFocus child-hwnd))))
(define/public (is-floating?)
float-without-caption?)
(define/private (set-frame-focus)
(let ([p focus-window-path])
(when (pair? p)

View File

@ -74,6 +74,9 @@
(define looked-for-createcontextattribs? #f)
(define wglCreateContextAttribsARB #f)
(define looked-for-wglswapinternalext? #f)
(define wglSwapIntervalEXT #f)
;; ----------------------------------------
(define gl-context%
@ -176,7 +179,21 @@
(wglCreateContextAttribsARB hdc context-handle (vector 0))
(wglCreateContext hdc))])
(and hglrc
(new gl-context% [hglrc hglrc] [hdc hdc]))))))))
(begin
(when (send config get-sync-swap)
(call-with-context
hdc
hglrc
(lambda ()
(unless looked-for-wglswapinternalext?
(set! wglSwapIntervalEXT
(let ([f (wglGetProcAddress "wglSwapIntervalEXT")])
(and f
(function-ptr f (_wfun _int -> _void)))))
(set! looked-for-wglswapinternalext? #t))
(when wglSwapIntervalEXT
(wglSwapIntervalEXT 1)))))
(new gl-context% [hglrc hglrc] [hdc hdc])))))))))
(define (with-dummy-context config thunk)
;; To create a gl context, we need a separate window

View File

@ -10,25 +10,47 @@
(protect-out maybe-make-key-event
generates-key-event?
reset-key-mapping
key-symbol-to-menu-key))
key-symbol-to-menu-key
any-control+alt-is-altgr))
(define-user32 GetKeyState (_wfun _int -> _SHORT))
(define-user32 MapVirtualKeyW (_wfun _UINT _UINT -> _UINT))
(define-user32 VkKeyScanW (_wfun _WCHAR -> _SHORT))
(define-user32 ToUnicode (_wfun _UINT _UINT _pointer _pointer _int _UINT -> _int))
(define-user32 GetKeyboardState (_wfun _pointer -> _BOOL))
(define control+alt-always-as-altgr? #f)
(define any-control+alt-is-altgr
(case-lambda
[() control+alt-always-as-altgr?]
[(on?) (set! control+alt-always-as-altgr? (and on? #t))]))
;; Back-door result from `key-mapped?` via `maybe-make-key-event`:
(define no-translate? #f)
;; Called to determine whether a WM_KEYDOWN event should
;; be passed to TranslateEvent() to get a WM_CHAR event.
;; If the WM_KEYDOWN event itself will translate to a
;; visible key event, then don't use TranslateEvent().
(define (generates-key-event? msg)
(let ([message (MSG-message msg)])
(and (or (eq? message WM_KEYDOWN)
(eq? message WM_SYSKEYDOWN)
(eq? message WM_KEYUP)
(eq? message WM_SYSKEYUP))
(maybe-make-key-event #t
(MSG-wParam msg)
(MSG-lParam msg)
#f
(or (= message WM_KEYUP)
(= message WM_SYSKEYUP))
(MSG-hwnd msg)))))
(or (maybe-make-key-event #t
(MSG-wParam msg)
(MSG-lParam msg)
#f
(or (= message WM_KEYUP)
(= message WM_SYSKEYUP))
(MSG-hwnd msg))
;; If ToUnicode() was used for checking, claim that
;; an event will be generated so that TranslateEvent()
;; is not used.
(begin0
no-translate?
(set! no-translate? #f))))))
(define (THE_SCAN_CODE lParam)
(bitwise-and (arithmetic-shift lParam -16) #x1FF))
@ -53,7 +75,8 @@
(VkKeyScanW (char->integer i)))))
other-key-codes)))
(define (reset-key-mapping)
(set! other-key-codes #f))
(set! other-key-codes #f)
(set! mapped-keys (make-hash)))
(define (other-orig j)
(char->integer (string-ref find_shift_alts j)))
@ -184,9 +207,14 @@
;; wParam is a virtual key code
(let ([id (hash-ref win32->symbol wParam #f)]
[override-mapping? (and control-down?
;; not AltGR:
(not (and lcontrol-down?
ralt-down?)))]
;; not AltGR or no mapping:
(or (not alt-down?)
(not (or control+alt-always-as-altgr?
(and lcontrol-down?
ralt-down?)))
(not (key-mapped? wParam
(THE_SCAN_CODE lParam)
just-check?))))]
[try-generate-release
(lambda ()
(let ([sc (THE_SCAN_CODE lParam)])
@ -264,8 +292,9 @@
[caps-down caps-down?]
[control+meta-is-altgr (and control-down?
alt-down?
(not rcontrol-down?)
(not lalt-down?))])]
(or control+alt-always-as-altgr?
(and (not rcontrol-down?)
(not lalt-down?))))])]
[as-key (lambda (v)
(if (integer? v) (integer->char v) v))])
(when is-up?
@ -341,3 +370,29 @@
(subtract . Subtract)
(numpad-enter . |Numpad Enter|)
(numpad6 . |Numpad 6|)))
;; The `key-mapped?` function is used to predict whether an
;; AltGr combination will produce a key; if not, a key
;; event can be synthesized (like control combinations)
(define keys-state (make-bytes 256))
(define unicode-result (make-bytes 20))
(define mapped-keys (make-hash))
(define (key-mapped? vk sc just-check?)
(define key (vector vk sc))
(hash-ref mapped-keys
key
(lambda ()
(cond
[just-check?
;; In checking mode, we can use ToUnicode():
(GetKeyboardState keys-state)
(define n (ToUnicode vk sc keys-state unicode-result 10 0))
(when (= n -1)
;; For a dead char, ToUnicode() seems to have the effect
;; of TranslateEvent(), so avoid the latter.
(set! no-translate? #t))
(define mapped? (not (zero? n)))
;; Record what we learned for use by non-checking mode:
(hash-set! mapped-keys key mapped?)
mapped?]
[else #f]))))

View File

@ -23,6 +23,7 @@
"slider.rkt"
"tab-panel.rkt"
"window.rkt"
"key.rkt"
"procs.rkt")
(provide (protect-out platform-values))
@ -86,6 +87,7 @@
get-color-from-user
special-option-key
special-control-key
any-control+alt-is-altgr
get-highlight-background-color
get-highlight-text-color
make-screen-bitmap

View File

@ -12,7 +12,8 @@
"dc.rkt"
"printer-dc.rkt"
(except-in "../common/default-procs.rkt"
get-panel-background)
get-panel-background
any-control+alt-is-altgr)
"filedialog.rkt"
"colordialog.rkt"
"sound.rkt"
@ -136,7 +137,7 @@
(list sym)
null))
(define swapped? (not (zero? (GetSystemMetrics SM_SWAPBUTTON))))
(values (make-object point% (POINT-x p) (POINT-y p))
(values (make-object point% (->normal (POINT-x p)) (->normal (POINT-y p)))
(append
(maybe (if swapped? VK_RBUTTON VK_LBUTTON) 'left)
(maybe (if swapped? VK_LBUTTON VK_RBUTTON) 'right)

View File

@ -1,7 +1,9 @@
#lang racket/base
(require ffi/unsafe
ffi/winapi
ffi/unsafe/custodian
ffi/unsafe/atomic
racket/class
"../../lock.rkt"
"utils.rkt"
"types.rkt"
"const.rkt")
@ -9,28 +11,67 @@
(provide
(protect-out play-sound))
(define-winmm PlaySoundW (_wfun _string/utf-16 _pointer _DWORD -> _BOOL))
(define BUFFER-SIZE 512)
(define BUFFER-BYTES-SIZE (* 2 BUFFER-SIZE))
(define SND_SYNC #x0000)
(define SND_ASYNC #x0001)
(define SND_NOSTOP #x0010)
(define-winmm mciGetErrorStringW
(_fun _int
[buf : _pointer = (malloc BUFFER-BYTES-SIZE)]
[_int = BUFFER-SIZE]
-> [ret : _bool]
-> (and ret (cast buf _pointer _string/utf-16))))
(define previous-done-sema #f)
(define-winmm mciSendStringW
(_fun _string/utf-16 [_pointer = #f] [_int = 0] [_pointer = #f]
-> [ret : _int]
-> (if (zero? ret)
(void)
(error 'mciSendStringW "~a" (mciGetErrorStringW ret)))))
(define (play-sound path async?)
(let ([path (simplify-path path #f)]
[done (make-semaphore)])
(and (let ([p (path->string
(cleanse-path (path->complete-path path)))])
(atomically
(when previous-done-sema (semaphore-post previous-done-sema))
(set! previous-done-sema done)
(PlaySoundW p #f SND_ASYNC)))
(or async?
;; Implement synchronous playing by polling, where
;; PlaySound with no sound file and SND_NOSTOP polls.
(let loop ()
(sleep 0.1)
(or (semaphore-try-wait? done)
(PlaySoundW #f #f (bitwise-ior SND_ASYNC SND_NOSTOP))
(loop)))))))
(define (mci-send fmt . args)
(mciSendStringW (apply format fmt args)))
(define-winmm mciSendStringW*
(_fun _string/utf-16
[buf : _pointer = (malloc BUFFER-BYTES-SIZE)]
[_int = BUFFER-SIZE]
[_pointer = #f]
-> [ret : _int]
-> (if (zero? ret)
(cast buf _pointer _string/utf-16)
(error 'mciSendStringW* "~a" (mciGetErrorStringW ret))))
#:c-id mciSendStringW)
(define (mci-send* fmt . args)
(mciSendStringW* (apply format fmt args)))
(define (play-sound file async?)
;; Generated ID is unique enough, because we only
;; instantiate this library in one place:
(define id (gensym 'play))
(define cust (make-custodian))
(call-as-atomic
(lambda ()
(mci-send "open \"~a\" alias ~a" (simplify-path file) id)
(register-custodian-shutdown
id
(lambda (id)
(mci-send "close ~a" id))
cust)))
(define (done msec)
(when msec (sleep (/ msec 1000)))
(custodian-shutdown-all cust))
(dynamic-wind
void
(lambda ()
(mci-send "set ~a time format milliseconds" id)
(define len (let ([s (mci-send* "status ~a length" id)])
(string->number s)))
(unless len (error 'play "mci did not return a numeric length"))
(mci-send "play ~a" id)
(if async? (thread (lambda () (done len))) (done len)))
(lambda ()
(unless async?
(done #f))))
;; Report success, since otherwise we throw an error:
#t)

View File

@ -170,6 +170,10 @@
begin-refresh-sequence
end-refresh-sequence)
(define scroll-via-copy? #f)
(define/public (set-scroll-via-copy v) (set! scroll-via-copy? (and v #t)))
(define/public (get-scroll-via-copy) scroll-via-copy?)
(define blink-timer #f)
(define noloop? #f)
@ -306,14 +310,14 @@
(maybe-reset-size))))))
(define/private (maybe-reset-size)
(begin-refresh-sequence)
(let-boxes ([w 0]
[h 0])
(get-size w h)
(unless (and (= w lastwidth)
(= h lastheight))
(reset-size)))
(end-refresh-sequence))
(begin-refresh-sequence)
(reset-size)
(end-refresh-sequence))))
(define/private (reset-size)
(reset-visual #f)
@ -460,6 +464,7 @@
(case (and (positive? wheel-amt)
code)
[(wheel-up wheel-down)
(collect-garbage 'incremental)
(when (and allow-y-scroll?
(not fake-y-scroll?))
(let-boxes ([x 0]
@ -474,6 +479,7 @@
0)])
(do-scroll x y #t x old-y))))]
[(wheel-left wheel-right)
(collect-garbage 'incremental)
(when (and allow-x-scroll?
(not fake-x-scroll?))
(let-boxes ([x 0]
@ -628,12 +634,14 @@
(when clear?
(let ([bg (get-canvas-background)])
(when bg
(let ([adc (get-dc)])
(let* ([dx (box 0)]
[dy (box 0)]
[adc (get-dc-and-offset dx dy)])
(let ([b (send adc get-brush)]
[p (send adc get-pen)])
(send adc set-brush bg 'solid)
(send adc set-pen bg 1 'transparent)
(send adc draw-rectangle localx localy fw fh)
(send adc draw-rectangle (- localx (unbox dx)) (- localy (unbox dy)) fw fh)
(send adc set-brush b)
(send adc set-pen p))))))
(let ([x (box 0)]
@ -940,11 +948,13 @@
retval)))))))
(define/private (do-scroll x y refresh? old-x old-y)
(define ed (get-editor))
(let ([savenoloop? noloop?])
(set! noloop? #t)
(maybe-reset-size)
(define on-scroll-to-called? #f)
(define change?
(or
;; Set x
@ -954,6 +964,14 @@
(and (not (= x old-x))
(begin
(when (not fake-x-scroll?)
(when scroll-via-copy?
(set! on-scroll-to-called? #t)
(begin-refresh-sequence)
(when scroll-via-copy?
(when ed
(call-as-primary-owner
(λ ()
(send ed on-scroll-to))))))
(set-scroll-pos 'horizontal x))
#t))))
;; Set y
@ -963,49 +981,77 @@
(and (not (= y old-y))
(begin
(when (not fake-y-scroll?)
(unless on-scroll-to-called?
(when scroll-via-copy?
(set! on-scroll-to-called? #t)
(begin-refresh-sequence)
(when ed
(call-as-primary-owner
(λ ()
(send ed on-scroll-to))))))
(set-scroll-pos 'vertical y))
#t))))))
(set! noloop? savenoloop?)
(when (and change? refresh?)
(if (and #f ;; special scrolling disabled: not faster with Cocoa, broken for Windows
(if (and scroll-via-copy?
(not need-refresh?)
(not lazy-refresh?)
(get-canvas-background)
(= x old-x)) ; could handle horizontal scrolling in the future
(let-boxes ([fx 0]
[old-fy 0]
[new-fy 0])
(begin
(convert-scroll-to-location x y fx new-fy)
(convert-scroll-to-location old-x old-y #f old-fy))
[old-fy* 0]
[new-fy* 0])
(let ([x (min x scroll-width)]
[y (min y scroll-height)])
(convert-scroll-to-location x y fx new-fy*)
(convert-scroll-to-location old-x old-y #f old-fy*))
(define new-fy (floor new-fy*))
(define old-fy (floor old-fy*))
(let-boxes ([vx 0][vy 0][vw 0][vh 0])
(get-view vx vy vw vh) ; editor coords
(cond
[(and (new-fy . < . old-fy)
(old-fy . < . (+ new-fy vh)))
(old-fy . < . (+ new-fy vh))
(integer? (send (get-dc) get-backing-scale)))
(let ([dc (get-dc)])
(unless on-scroll-to-called?
(begin-refresh-sequence))
(send dc copy
xmargin ymargin
vw (- (+ new-fy vh) old-fy)
xmargin (+ ymargin (- old-fy new-fy)))
(redraw xmargin ymargin
(redraw vx vy
vw (- old-fy new-fy)
#t))]
#t)
(unless on-scroll-to-called?
(end-refresh-sequence)))]
[(and (old-fy . < . new-fy)
(new-fy . < . (+ old-fy vh)))
(new-fy . < . (+ old-fy vh))
(integer? (send (get-dc) get-backing-scale)))
(let ([dc (get-dc)])
(unless on-scroll-to-called?
(begin-refresh-sequence))
(send dc copy
xmargin (+ ymargin (- new-fy old-fy))
vw (- (+ old-fy vh) new-fy)
xmargin ymargin)
(let ([d (- (+ old-fy vh) new-fy)])
(redraw xmargin (+ ymargin d)
(redraw vx (+ vy d)
vw (- vh d)
#t)))]
#t))
(unless on-scroll-to-called?
(end-refresh-sequence)))]
[else (repaint)])))
(repaint)))))
(repaint)))
(when on-scroll-to-called?
(when ed
(call-as-primary-owner
(λ ()
(send ed after-scroll-to))))
(end-refresh-sequence))))
(define/override (set-scrollbars x y x2 y2 x3 y3 x4 y4 ?) (void))

View File

@ -226,6 +226,11 @@
;; ----------------------------------------
(define/public (on-scroll-to) (void))
(define/public (after-scroll-to) (void))
;; ----------------------------------------
(def/public (set-admin [(make-or-false editor-admin%) administrator])
(setting-admin administrator)

View File

@ -284,7 +284,7 @@
(if (caps . < . 0) "~l:" "")
(if (altgr . > . 0) "g:" "")
(if (altgr . < . 0) "~g:" "")
(or (hash-ref rev-keylist code)
(or (hash-ref rev-keylist code #f)
(format "~c" code)))])
(error (method-name 'keymap% 'map-function)
"~s is already mapped as a ~aprefix key"

View File

@ -249,6 +249,11 @@
(def/override (on-event [mouse-event% event])
(when s-admin
(when (and (not (send event moving?))
(not (send event entering?))
(not (send event leaving?)))
;; Request incremental mode to improve interactivity:
(collect-garbage 'incremental))
(let-values ([(dc x y scrollx scrolly)
;; first, find clicked-on snip:
(let ([x (send event get-x)]
@ -404,6 +409,8 @@
(def/override (on-char [key-event% event])
(when s-admin
;; Request incremental mode to improve interactivity:
(collect-garbage 'incremental)
(let-boxes ([scrollx 0.0]
[scrolly 0.0]
[dc #f])
@ -1860,7 +1867,7 @@
(let ([snip (new string-snip%)])
(set-snip-style! snip (or (get-default-style)
(send s-style-list basic-style)))
(send snip insert str)
(send snip insert str (string-length str))
(insert-paste-snip snip #f)))
(def/override (kill [exact-integer? [time 0]])

View File

@ -381,6 +381,15 @@
(unless recur? (inc-item-count))
(let ([s (with-handlers ([exn:fail:read? (lambda (x) #f)])
(read si))])
(when (and recur? s)
;; It's ok to have extra whitespace when reading a byte
;; string in a sequence
(let loop ()
(define c (peek-byte si))
(unless (eof-object? c)
(when (char-whitespace? (integer->char c))
(read-byte si)
(loop)))))
(if (or (not s)
(not (eof-object? (read-byte si))))
(fail)

View File

@ -452,7 +452,9 @@
(when (and (not (send event moving?))
(not (send event entering?))
(not (send event leaving?)))
(end-streaks '(except-key-sequence cursor delayed)))
(end-streaks '(except-key-sequence cursor delayed))
;; Request incremental mode to improve interactivity:
(collect-garbage 'incremental))
(let-values ([(dc x y scrollx scrolly)
;; first, find clicked-on snip:
(let ([x (send event get-x)]
@ -464,17 +466,16 @@
;; FIXME: old code returned if !dc
(values dc (+ x scrollx) (+ y scrolly) scrollx scrolly)))])
(let ([snip
(let-boxes ([onit? #f]
[how-close 0.0]
(let-boxes ([how-close 0.0]
[now 0])
(set-box! now (find-position x y #f onit? how-close))
;; FIXME: the following refinement of `onit?' seems pointless
(let ([onit? (and onit?
(not (zero? how-close))
((abs how-close) . > . between-threshold))])
(if onit?
;; we're in the snip's horizontal region...
(let ([snip (do-find-snip now 'after)])
(set-box! now (find-position x y #f #f how-close))
(let* ([snip (do-find-snip now 'after)]
[onit? (or (and (not (zero? how-close))
((abs how-close) . > . between-threshold))
(has-flag? (snip->flags snip)
HANDLES-BETWEEN-EVENTS))])
(if onit?
;; we're in the snip's horizontal region...
;; ... but maybe the mouse is above or below it.
(let-boxes ([top 0.0]
[bottom 0.0]
@ -484,8 +485,8 @@
(get-snip-location snip dummy bottom #t))
(if (or (top . > . y) (y . > . bottom))
#f
snip)))
#f)))])
snip))
#f)))])
(when (send event button-down?)
(set-caret-owner snip))
(when (and prev-mouse-snip
@ -601,7 +602,9 @@
(not (eq? 'control code))
(not (eq? 'menu code))
(not (equal? code #\nul)))
(hide-cursor))
(hide-cursor)
;; Request incremental mode to improve interactivity:
(collect-garbage 'incremental))
(on-local-char event)))))
(def/override (on-default-char [key-event% event])

View File

@ -97,13 +97,17 @@
(define ignore-redraw-request? #f)
(define hide-scroll-x? (and (memq 'hide-hscroll style) #t))
(define hide-scroll-y? (and (memq 'hide-vscroll style) #t))
(define auto-scroll-x? (and (memq 'auto-hscroll style) #t))
(define auto-scroll-y? (and (memq 'auto-vscroll style) #t))
(define can-scroll-x? (or auto-scroll-x?
hide-scroll-x?
(and (memq 'hscroll style) #t)))
(define can-scroll-y? (or auto-scroll-y?
hide-scroll-y?
(and (memq 'vscroll style) #t)))
(define scroll-x? can-scroll-x?)
@ -450,13 +454,15 @@
;; loop for fix-point on x and y scroll
(let loop ([w w] [h h] [iters 0])
(let ([want-scroll-x?
(if auto-scroll-x?
((car ms) . > . w)
scroll-x?)]
(and (not hide-scroll-x?)
(if auto-scroll-x?
((car ms) . > . w)
scroll-x?))]
[want-scroll-y?
(if auto-scroll-y?
((cadr ms) . > . h)
scroll-y?)])
(and (not hide-scroll-y?)
(if auto-scroll-y?
((cadr ms) . > . h)
scroll-y?))])
(if (and (eq? scroll-x? want-scroll-x?)
(eq? scroll-y? want-scroll-y?))
(values (if can-scroll-x?

View File

@ -30,6 +30,7 @@ has been moved out).
"private/image-core-snipclass.rkt"
"private/regmk.rkt"
racket/snip
(prefix-in : racket/base)
(prefix-in cis: "cache-image-snip.rkt"))
@ -454,9 +455,11 @@ has been moved out).
(set-box/f! lspace 0)
(set-box/f! rspace 0)))
(define/override (write f)
(let ([bytes (string->bytes/utf-8 (format "~s" (list shape bb pinhole)))])
(send f put (bytes-length bytes) bytes)))
(define/override (write f)
(define bp (open-output-bytes))
(:write (list shape bb pinhole) bp)
(define bytes (get-output-bytes bp))
(send f put (bytes-length bytes) bytes))
(super-new)

View File

@ -1,7 +1,8 @@
(module interactive-value-port mzscheme
(require mzlib/pretty
mred
mzlib/class
#lang racket/base
(require racket/pretty
racket/gui/base
racket/class
"syntax-browser.rkt")
(provide set-interactive-display-handler
set-interactive-write-handler
@ -10,7 +11,7 @@
(define op (current-output-port))
(define (oprintf . x) (apply fprintf op x))
(define (set-interactive-display-handler port)
(define (set-interactive-display-handler port #:snip-handler [snip-handler #f])
(let ([original-port-display-handler (port-display-handler port)])
(port-display-handler
port
@ -18,19 +19,19 @@
(cond
[(string? val) (original-port-display-handler val port)]
[else
(do-printing pretty-display val port)])))))
(do-printing pretty-display val port snip-handler)])))))
(define (set-interactive-write-handler port)
(define (set-interactive-write-handler port #:snip-handler [snip-handler #f])
(port-write-handler
port
(λ (val port)
(do-printing pretty-print val port))))
(do-printing pretty-write val port snip-handler))))
(define (set-interactive-print-handler port)
(define (set-interactive-print-handler port #:snip-handler [snip-handler #f])
(port-print-handler
port
(λ (val port)
(do-printing pretty-print val port))))
(do-printing pretty-print val port snip-handler))))
(define (use-number-snip? x)
(and #f
@ -41,7 +42,7 @@
(define default-pretty-print-current-style-table (pretty-print-current-style-table))
(define (do-printing pretty value port)
(define (do-printing pretty value port snip-handler)
(parameterize (;; these handlers aren't used, but are set to override the user's settings
[pretty-print-print-line (λ (line-number op old-line dest-columns)
(when (and (not (equal? line-number 0))
@ -70,22 +71,19 @@
(cond
[(not (port-writes-special? port)) #f]
[(is-a? value snip%) 1]
;[(use-number-snip? value) 1]
[(syntax? value) 1]
[else #f]))]
[pretty-print-print-hook
(λ (value display? port)
(cond
[(is-a? value snip%)
(write-special value port)
1]
#;
[(use-number-snip? value)
(write-special
(number-snip:make-repeating-decimal-snip value #f)
port)
(cond
[snip-handler
(snip-handler value port)]
[else
(write-special value port)])
1]
[(syntax? value)
(write-special (render-syntax/snip value))]
[else (void)]))])
(pretty value port))))
(pretty value port)))

Some files were not shown because too many files have changed in this diff Show More