/racket-5.0.2-bin-x86_64-linux-f7/collects/framework/private/keymap.rkt

http://github.com/smorin/f4f.arc · Racket · 1452 lines · 1259 code · 143 blank · 50 comment · 181 complexity · d246e0ae9e7507a5012425c1854b9df3 MD5 · raw file

  1. #lang scheme/unit
  2. (require string-constants
  3. mzlib/class
  4. mzlib/list
  5. mred/mred-sig
  6. mzlib/match
  7. "../preferences.ss"
  8. mrlib/tex-table
  9. "sig.ss")
  10. (import mred^
  11. [prefix finder: framework:finder^]
  12. [prefix handler: framework:handler^]
  13. [prefix frame: framework:frame^]
  14. [prefix editor: framework:editor^])
  15. (export (rename framework:keymap^
  16. [-get-file get-file]))
  17. (init-depend mred^)
  18. (define user-keybindings-files (make-hash))
  19. (define (add-user-keybindings-file spec)
  20. (hash-ref
  21. user-keybindings-files
  22. spec
  23. (λ ()
  24. (let* ([path (spec->path spec)]
  25. [sexp (and (file-exists? path)
  26. (parameterize ([read-accept-reader #t])
  27. (call-with-input-file path read)))])
  28. (match sexp
  29. [`(module ,name ,lang
  30. ,@(x ...))
  31. (cond
  32. [(valid-keybindings-lang? lang)
  33. (let ([km (dynamic-require spec '#%keymap)])
  34. (hash-set! user-keybindings-files spec km)
  35. (send user-keymap chain-to-keymap km #t))]
  36. [else
  37. (error 'add-user-keybindings-file
  38. (string-constant user-defined-keybinding-malformed-file/found-lang)
  39. (path->string path)
  40. lang)])]
  41. [else (error 'add-user-keybindings-file
  42. (string-constant user-defined-keybinding-malformed-file)
  43. (path->string path))])))))
  44. (define (valid-keybindings-lang? x)
  45. (member x
  46. (list `(lib "keybinding-lang.ss" "framework")
  47. `(lib "framework/keybinding-lang.ss")
  48. `framework/keybinding-lang)))
  49. (define (spec->path p)
  50. (cond
  51. [(path? p) p]
  52. [else
  53. (let* ([mod-name ((current-module-name-resolver) p #f #f)]
  54. [str (symbol->string mod-name)]
  55. [pth (substring str 1 (string-length str))])
  56. (let-values ([(base name _) (split-path pth)])
  57. (let ([filenames
  58. (sort
  59. (filter (λ (x) (substring? (path->string name) x))
  60. (map path->string (directory-list base)))
  61. (λ (x y) (> (string-length x) (string-length y))))])
  62. (when (null? filenames)
  63. (error 'spec->path "could not convert ~s, found no filenames for ~s" p mod-name))
  64. (build-path base (car filenames)))))]))
  65. (define (substring? s1 s2)
  66. (and (<= (string-length s1)
  67. (string-length s2))
  68. (string=? s1 (substring s2 0 (string-length s1)))))
  69. (define (remove-user-keybindings-file spec)
  70. (let/ec k
  71. (let ([km (hash-ref user-keybindings-files spec (λ () (k (void))))])
  72. (send global remove-chained-keymap km)
  73. (hash-remove! user-keybindings-files spec))))
  74. (define (remove-chained-keymap ed keymap-to-remove)
  75. (let ([ed-keymap (send ed get-keymap)])
  76. (when (eq? keymap-to-remove ed-keymap)
  77. (error 'keymap:remove-keymap "cannot remove initial keymap from editor"))
  78. (let p-loop ([parent-keymap ed-keymap])
  79. (unless (is-a? parent-keymap aug-keymap<%>)
  80. (error 'keymap:remove-keymap
  81. "found a keymap that is not a keymap:aug-keymap<%> ~e"
  82. parent-keymap))
  83. (let c-loop ([child-keymaps (send parent-keymap get-chained-keymaps)])
  84. (cond
  85. [(null? child-keymaps)
  86. (void)]
  87. [else
  88. (let ([child-keymap (car child-keymaps)])
  89. (cond
  90. [(eq? child-keymap keymap-to-remove)
  91. (send parent-keymap remove-chained-keymap child-keymap)
  92. (c-loop (cdr child-keymaps))]
  93. [else
  94. (p-loop child-keymap)
  95. (c-loop (cdr child-keymaps))]))])))))
  96. (define (set-chained-keymaps parent-keymap children-keymaps)
  97. (for-each (λ (orig-sub) (send parent-keymap remove-chained-keymap))
  98. (send parent-keymap get-chained-keymaps))
  99. (for-each (λ (new-sub) (send parent-keymap chain-to-keymap new-sub #f))
  100. children-keymaps))
  101. (define aug-keymap<%> (interface ((class->interface keymap%))
  102. get-chained-keymaps
  103. get-map-function-table
  104. get-map-function-table/ht))
  105. (define aug-keymap-mixin
  106. (mixin ((class->interface keymap%)) (aug-keymap<%>)
  107. (define chained-keymaps null)
  108. (define/public (get-chained-keymaps) chained-keymaps)
  109. (define/override (chain-to-keymap keymap prefix?)
  110. (super chain-to-keymap keymap prefix?)
  111. (set! chained-keymaps
  112. (if prefix?
  113. (cons keymap chained-keymaps)
  114. (append chained-keymaps (list keymap)))))
  115. (define/override (remove-chained-keymap keymap)
  116. (super remove-chained-keymap keymap)
  117. (set! chained-keymaps (remq keymap chained-keymaps)))
  118. (define function-table (make-hasheq))
  119. (define/public (get-function-table) function-table)
  120. (define/override (map-function keyname fname)
  121. (super map-function (canonicalize-keybinding-string keyname) fname)
  122. (hash-set! function-table (string->symbol keyname) fname))
  123. (define/public (get-map-function-table)
  124. (get-map-function-table/ht (make-hasheq)))
  125. (define/public (get-map-function-table/ht table)
  126. (hash-for-each
  127. function-table
  128. (λ (keyname fname)
  129. (unless (hash-ref table keyname (λ () #f))
  130. (let ([cs (canonicalize-keybinding-string (format "~a" keyname))])
  131. (when (on-this-platform? cs)
  132. (hash-set! table keyname fname))))))
  133. (for-each
  134. (λ (chained-keymap)
  135. (when (is-a? chained-keymap aug-keymap<%>)
  136. (send chained-keymap get-map-function-table/ht table)))
  137. chained-keymaps)
  138. table)
  139. (define/private (on-this-platform? cs)
  140. (let* ([splits (map (λ (x) (all-but-last (split-out #\: x))) (split-out #\; (string->list cs)))]
  141. [has-key? (λ (k) (ormap (λ (x) (member (list k) x)) splits))])
  142. (cond
  143. [(eq? (system-type) 'windows)
  144. (cond
  145. [(or (regexp-match #rx"a:c" cs)
  146. (regexp-match #rx"c:m" cs))
  147. #f]
  148. [(or (has-key? #\a) (has-key? #\d))
  149. #f]
  150. [else #t])]
  151. [(eq? (system-type) 'macosx)
  152. (cond
  153. [(has-key? #\m)
  154. #f]
  155. [else #t])]
  156. [(eq? (system-type) 'unix)
  157. (cond
  158. [(or (has-key? #\a) (has-key? #\d))
  159. #f]
  160. [else #t])]
  161. [else
  162. ;; just in case new platforms come along ....
  163. #t])))
  164. (define/private (all-but-last l)
  165. (cond
  166. [(null? l) l]
  167. [(null? (cdr l)) l]
  168. [else (cons (car l) (all-but-last (cdr l)))]))
  169. (super-new)))
  170. (define aug-keymap% (aug-keymap-mixin keymap%))
  171. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  172. ;;;;;;; ;;;;;;;;
  173. ;;;;;;; canonicalize-keybinding-string ;;;;;;;;
  174. ;;;;;;; ;;;;;;;;
  175. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  176. ;; canonicalize-keybinding-string : string -> string
  177. ;; The result can be used with string=? to determine
  178. ;; if two key bindings refer to the same key.
  179. ;; Assumes a well-formed keystring.
  180. (define (canonicalize-keybinding-string str)
  181. (let* ([chars (map char-downcase (string->list str))]
  182. [separated-keys
  183. (map
  184. canonicalize-single-keybinding-string
  185. (split-out #\; chars))])
  186. (join-strings ";" separated-keys)))
  187. ;; join-strings : string (listof string) -> string
  188. ;; concatenates strs with sep between each of them
  189. (define (join-strings sep strs)
  190. (if (null? strs)
  191. ""
  192. (apply
  193. string-append
  194. (cons
  195. (car strs)
  196. (let loop ([sepd-strs (cdr strs)])
  197. (cond
  198. [(null? sepd-strs) null]
  199. [else (list*
  200. sep
  201. (car sepd-strs)
  202. (loop (cdr sepd-strs)))]))))))
  203. ;; canonicalize-single-keybinding-string : (listof char) -> string
  204. (define (canonicalize-single-keybinding-string chars)
  205. (let* ([neg? (char=? (car chars) #\:)]
  206. [mods/key (split-out #\: (if neg? (cdr chars) chars))]
  207. [mods
  208. (let loop ([mods mods/key])
  209. (cond
  210. [(null? mods) null]
  211. [(null? (cdr mods)) null]
  212. [else (cons (car mods) (loop (cdr mods)))]))]
  213. [key (apply string (car (last-pair mods/key)))]
  214. [canon-key
  215. (cond
  216. [(string=? key "enter") "return"]
  217. [(string=? key "del") "delete"]
  218. [(string=? key "ins") "insert"]
  219. [else key])]
  220. [shift (if neg? #f 'd/c)]
  221. [control (if neg? #f 'd/c)]
  222. [alt (if neg? #f 'd/c)]
  223. [meta (if neg? #f 'd/c)]
  224. [command (if neg? #f 'd/c)]
  225. [do-key
  226. (λ (char val)
  227. (cond
  228. [(eq? val #t) (string char)]
  229. [(eq? val #f) (string #\~ char)]
  230. [(eq? val 'd/c) #f]))])
  231. (for-each (λ (mod)
  232. (let ([val (not (char=? (car mod) #\~))])
  233. (case (if (char=? (car mod) #\~)
  234. (cadr mod)
  235. (car mod))
  236. [(#\s) (set! shift val)]
  237. [(#\c) (set! control val)]
  238. [(#\a) (set! alt val)]
  239. [(#\d) (set! command val)]
  240. [(#\m) (set! meta val)])))
  241. mods)
  242. (join-strings ":"
  243. (filter
  244. values
  245. (list
  246. (do-key #\a alt)
  247. (do-key #\c control)
  248. (do-key #\d command)
  249. (do-key #\m meta)
  250. (do-key #\s shift)
  251. canon-key)))))
  252. ;; split-out : char (listof char) -> (listof (listof char))
  253. ;; splits a list of characters at its first argument
  254. ;; if the last character is the same as the first character,
  255. ;; it is not split into an empty list, but returned.
  256. (define (split-out split-char chars)
  257. (let loop ([chars chars]
  258. [this-split null]
  259. [all-split null])
  260. (cond
  261. [(null? chars)
  262. (reverse (cons (reverse this-split) all-split))]
  263. [else (let ([char (car chars)])
  264. (cond
  265. [(char=? split-char char)
  266. (if (null? (cdr chars))
  267. (loop null
  268. (cons char this-split)
  269. all-split)
  270. (loop (cdr chars)
  271. null
  272. (cons (reverse this-split) all-split)))]
  273. [else
  274. (loop (cdr chars)
  275. (cons char this-split)
  276. all-split)]))])))
  277. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  278. ;;;;;;; ;;;;;;;;
  279. ;;;;;;; end canonicalize-keybinding-string ;;;;;;;;
  280. ;;;;;;; ;;;;;;;;
  281. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  282. (define (make-meta-prefix-list key)
  283. (list (string-append "m:" key)
  284. (string-append "ESC;" key)))
  285. (define send-map-function-meta
  286. (λ (keymap key func)
  287. (for-each (λ (key) (send keymap map-function key func))
  288. (make-meta-prefix-list key))))
  289. (define add-to-right-button-menu (make-parameter void))
  290. (define add-to-right-button-menu/before (make-parameter void))
  291. (define setup-global
  292. ; Define some useful keyboard functions
  293. (let* ([ring-bell
  294. (λ (edit event)
  295. (bell))]
  296. [mouse-popup-menu
  297. (λ (edit event)
  298. (when (send event button-down?)
  299. (let ([a (send edit get-admin)])
  300. (when a
  301. (let ([m (make-object popup-menu%)])
  302. ((add-to-right-button-menu/before) m edit event)
  303. (append-editor-operation-menu-items m)
  304. (for-each
  305. (λ (i)
  306. (when (is-a? i selectable-menu-item<%>)
  307. (send i set-shortcut #f)))
  308. (send m get-items))
  309. ((add-to-right-button-menu) m edit event)
  310. (let-values ([(x y) (send edit
  311. dc-location-to-editor-location
  312. (send event get-x)
  313. (send event get-y))])
  314. (send a popup-menu m (+ x 1) (+ y 1))))))))]
  315. [toggle-anchor
  316. (λ (edit event)
  317. (send edit set-anchor
  318. (not (send edit get-anchor))))]
  319. [center-view-on-line
  320. (λ (edit event)
  321. (let ([new-mid-line (send edit position-line
  322. (send edit get-start-position))]
  323. [bt (box 0)]
  324. [bb (box 0)])
  325. (send edit get-visible-line-range bt bb #f)
  326. (let* ([half (sub1 (quotient (- (unbox bb) (unbox bt)) 2))]
  327. [last-pos (send edit position-line (send edit last-position))]
  328. [top-pos (send edit line-start-position
  329. (max (min (- new-mid-line half) last-pos) 0))]
  330. [bottom-pos (send edit line-start-position
  331. (max 0
  332. (min (+ new-mid-line half)
  333. last-pos)))])
  334. (send edit scroll-to-position
  335. top-pos
  336. #f
  337. bottom-pos)))
  338. #t)]
  339. [make-insert-brace-pair
  340. (λ (open-brace close-brace)
  341. (λ (edit event)
  342. (send edit begin-edit-sequence)
  343. (let ([selection-start (send edit get-start-position)])
  344. (send edit set-position (send edit get-end-position))
  345. (send edit insert close-brace)
  346. (send edit set-position selection-start)
  347. (send edit insert open-brace))
  348. (send edit end-edit-sequence)))]
  349. [insert-lambda-template
  350. (λ (edit event)
  351. (send edit begin-edit-sequence)
  352. (let ([selection-start (send edit get-start-position)])
  353. (send edit set-position (send edit get-end-position))
  354. (send edit insert ")")
  355. (send edit set-position selection-start)
  356. (send edit insert ") ")
  357. (send edit set-position selection-start)
  358. (send edit insert "(λ ("))
  359. (send edit end-edit-sequence))]
  360. [collapse-variable-space
  361. ;; As per emacs: collapse tabs & spaces around the point,
  362. ;; perhaps leaving a single space.
  363. ;; drscheme bonus: if at end-of-line, collapse into the next line.
  364. (λ (leave-one? edit event)
  365. (letrec ([last-pos (send edit last-position)]
  366. [sel-start (send edit get-start-position)]
  367. [sel-end (send edit get-end-position)]
  368. [collapsible? (λ (c) (and (char-whitespace? c)
  369. (not (char=? #\newline c))))]
  370. [find-noncollapsible
  371. ; Return index of next non-collapsible char,
  372. ; starting at pos in direction dir.
  373. ; NB returns -1 or last-pos, if examining
  374. ; initial/final whitespace
  375. ; (or, when initial pos is outside of [0,last-pos).)
  376. (λ (pos dir)
  377. (let loop ([pos pos])
  378. (cond [(< pos 0) -1]
  379. [(>= pos last-pos) last-pos]
  380. [(collapsible? (send edit get-character pos))
  381. (loop (+ pos dir))]
  382. [else pos])))])
  383. (when (= sel-start sel-end) ; Only when no selection:
  384. (let* ([start (add1 (find-noncollapsible (sub1 sel-start) -1))]
  385. [end-heeding-eol (find-noncollapsible sel-start +1)]
  386. ; This is the end of the range, were we to always heed newlines.
  387. ; Special case: if we're sitting at EOL,
  388. ; and we're not affecting much else,
  389. ; then delete that EOL and collapse spaces
  390. ; at the start of next line, too:
  391. [end (if (and (<= (- end-heeding-eol start)
  392. (if leave-one? 1 0))
  393. (char=? #\newline (send edit get-character end-heeding-eol))
  394. ; If you wish to avoid deleting an newline at EOF, do so here.
  395. )
  396. (find-noncollapsible (add1 end-heeding-eol) +1)
  397. end-heeding-eol)]
  398. [making-no-difference?
  399. ; Don't introduce edits into undo-chain, if no effect.
  400. (if leave-one?
  401. (and (= (- end start) 1)
  402. (char=? #\space (send edit get-character start)))
  403. (= (- end start) 0))])
  404. (unless making-no-difference?
  405. (send edit begin-edit-sequence)
  406. (send edit set-position end) ; Even after delete, caret will be at "end".
  407. (send edit delete start end)
  408. (when leave-one? (send edit insert #\space start))
  409. (send edit end-edit-sequence))))))]
  410. [collapse-space
  411. (λ (edit event)
  412. (collapse-variable-space #t edit event))]
  413. [remove-space
  414. (λ (edit event)
  415. (collapse-variable-space #f edit event))]
  416. [collapse-newline
  417. (λ (edit event)
  418. (letrec ([find-nonwhite
  419. (λ (pos d offset)
  420. (let/ec escape
  421. (let ([max (if (> offset 0)
  422. (send edit last-position)
  423. 0)])
  424. (let loop ([pos pos])
  425. (if (= pos max)
  426. (escape pos)
  427. (let ([c (send edit get-character (+ pos offset))])
  428. (cond
  429. [(char=? #\newline c)
  430. (loop (+ pos d))
  431. (escape pos)]
  432. [(char-whitespace? c)
  433. (loop (+ pos d))]
  434. [else pos])))))))])
  435. (let ([sel-start (send edit get-start-position)]
  436. [sel-end (send edit get-end-position)])
  437. (when (= sel-start sel-end)
  438. (let* ([pos-line (send edit position-line sel-start #f)]
  439. [pos-line-start (send edit line-start-position pos-line)]
  440. [pos-line-end (send edit line-end-position pos-line)]
  441. [whiteline?
  442. (let loop ([pos pos-line-start])
  443. (if (>= pos pos-line-end)
  444. #t
  445. (and (char-whitespace? (send edit get-character pos))
  446. (loop (add1 pos)))))]
  447. [start (find-nonwhite pos-line-start -1 -1)]
  448. [end (find-nonwhite pos-line-end 1 0)]
  449. [start-line
  450. (send edit position-line start #f)]
  451. [start-line-start
  452. (send edit line-start-position start-line)]
  453. [end-line
  454. (send edit position-line end #f)]
  455. [end-line-start
  456. (send edit line-start-position (add1 end-line))])
  457. (cond
  458. [(and whiteline?
  459. (= start-line pos-line)
  460. (= end-line pos-line))
  461. ; Special case: just delete this line
  462. (send edit delete pos-line-start (add1 pos-line-end))]
  463. [(and whiteline? (< start-line pos-line))
  464. ; Can delete before & after
  465. (send* edit
  466. (begin-edit-sequence)
  467. (delete (add1 pos-line-end) end-line-start)
  468. (delete start-line-start pos-line-start)
  469. (end-edit-sequence))]
  470. [else
  471. ; Only delete after
  472. (send edit delete (add1 pos-line-end)
  473. end-line-start)]))))))]
  474. [open-line
  475. (λ (edit event)
  476. (let ([sel-start (send edit get-start-position)]
  477. [sel-end (send edit get-end-position)])
  478. (when (= sel-start sel-end)
  479. (send* edit
  480. (insert #\newline)
  481. (set-position sel-start)))))]
  482. [transpose-chars
  483. (λ (edit event)
  484. (let ([sel-start (send edit get-start-position)]
  485. [sel-end (send edit get-end-position)])
  486. (when (and (= sel-start sel-end)
  487. (not (= sel-start 0)))
  488. (let ([sel-start
  489. (if (= sel-start
  490. (send edit line-end-position
  491. (send edit position-line sel-start)))
  492. (sub1 sel-start)
  493. sel-start)])
  494. (let ([s (send edit get-text
  495. sel-start (add1 sel-start))])
  496. (send* edit
  497. (begin-edit-sequence)
  498. (delete sel-start (add1 sel-start))
  499. (insert s (- sel-start 1))
  500. (set-position (add1 sel-start))
  501. (end-edit-sequence)))))))]
  502. [transpose-words
  503. (λ (edit event)
  504. (let ([sel-start (send edit get-start-position)]
  505. [sel-end (send edit get-end-position)])
  506. (when (= sel-start sel-end)
  507. (let ([word-1-start (box sel-start)])
  508. (send edit find-wordbreak word-1-start #f 'caret)
  509. (let ([word-1-end (box (unbox word-1-start))])
  510. (send edit find-wordbreak #f word-1-end 'caret)
  511. (let ([word-2-end (box (unbox word-1-end))])
  512. (send edit find-wordbreak #f word-2-end 'caret)
  513. (let ([word-2-start (box (unbox word-2-end))])
  514. (send edit find-wordbreak word-2-start #f 'caret)
  515. (let ([text-1 (send edit get-text
  516. (unbox word-1-start)
  517. (unbox word-1-end))]
  518. [text-2 (send edit get-text
  519. (unbox word-2-start)
  520. (unbox word-2-end))])
  521. (send* edit
  522. (begin-edit-sequence)
  523. (insert text-1
  524. (unbox word-2-start)
  525. (unbox word-2-end))
  526. (insert text-2
  527. (unbox word-1-start)
  528. (unbox word-1-end))
  529. (set-position (unbox word-2-end))
  530. (end-edit-sequence))))))))))]
  531. [capitalize-it
  532. (λ (edit char-case1 char-case2)
  533. (let ([sel-start (send edit get-start-position)]
  534. [sel-end (send edit get-end-position)]
  535. [real-end (send edit last-position)])
  536. (when (= sel-start sel-end)
  537. (let ([word-end (let ([b (box sel-start)])
  538. (send edit find-wordbreak #f b 'caret)
  539. (min real-end (unbox b)))])
  540. (send edit begin-edit-sequence)
  541. (let loop ([pos sel-start]
  542. [char-case char-case1])
  543. (when (< pos word-end)
  544. (let ([c (send edit get-character pos)])
  545. (cond
  546. [(char-alphabetic? c)
  547. (send edit insert
  548. (list->string
  549. (list (char-case c)))
  550. pos (add1 pos))
  551. (loop (add1 pos) char-case2)]
  552. [else
  553. (loop (add1 pos) char-case)]))))
  554. (send* edit
  555. (end-edit-sequence)
  556. (set-position word-end))))))]
  557. [capitalize-word
  558. (λ (edit event)
  559. (capitalize-it edit char-upcase char-downcase))]
  560. [upcase-word
  561. (λ (edit event)
  562. (capitalize-it edit char-upcase char-upcase))]
  563. [downcase-word
  564. (λ (edit event)
  565. (capitalize-it edit char-downcase char-downcase))]
  566. [kill-word
  567. (λ (edit event)
  568. (let ([sel-start (send edit get-start-position)]
  569. [sel-end (send edit get-end-position)])
  570. (let ([end-box (box sel-end)])
  571. (send edit find-wordbreak #f end-box 'caret)
  572. (send edit kill 0 sel-start (unbox end-box)))))]
  573. [backward-kill-word
  574. (λ (edit event)
  575. (let ([sel-start (send edit get-start-position)]
  576. [sel-end (send edit get-end-position)])
  577. (let ([start-box (box sel-start)])
  578. (send edit find-wordbreak start-box #f 'caret)
  579. (send edit kill 0 (unbox start-box) sel-end))))]
  580. [region-click
  581. (λ (edit event f)
  582. (when (and (send event button-down?)
  583. (is-a? edit text%))
  584. (let ([x-box (box (send event get-x))]
  585. [y-box (box (send event get-y))]
  586. [eol-box (box #f)])
  587. (send edit global-to-local x-box y-box)
  588. (let ([click-pos (send edit find-position
  589. (unbox x-box)
  590. (unbox y-box)
  591. eol-box)]
  592. [start-pos (send edit get-start-position)]
  593. [end-pos (send edit get-end-position)])
  594. (let ([eol (unbox eol-box)])
  595. (if (< start-pos click-pos)
  596. (f click-pos eol start-pos click-pos)
  597. (f click-pos eol click-pos end-pos)))))))]
  598. [copy-click-region
  599. (λ (edit event)
  600. (region-click edit event
  601. (λ (click eol start end)
  602. (send edit flash-on start end)
  603. (send edit copy #f 0 start end))))]
  604. [cut-click-region
  605. (λ (edit event)
  606. (region-click edit event
  607. (λ (click eol start end)
  608. (send edit cut #f 0 start end))))]
  609. [paste-click-region
  610. (λ (edit event)
  611. (region-click edit event
  612. (λ (click eol start end)
  613. (send edit set-position click)
  614. (send edit paste-x-selection 0 click))))]
  615. [mouse-copy-clipboard
  616. (λ (edit event)
  617. (send edit copy #f (send event get-time-stamp)))]
  618. [mouse-paste-clipboard
  619. (λ (edit event)
  620. (send edit paste (send event get-time-stamp)))]
  621. [mouse-cut-clipboard
  622. (λ (edit event)
  623. (send edit cut #f (send event get-time-stamp)))]
  624. [select-click-word
  625. (λ (edit event)
  626. (region-click edit event
  627. (λ (click eol start end)
  628. (let ([start-box (box click)]
  629. [end-box (box click)])
  630. (send edit find-wordbreak
  631. start-box
  632. end-box
  633. 'selection)
  634. (send edit set-position
  635. (unbox start-box)
  636. (unbox end-box))))))]
  637. [select-click-line
  638. (λ (edit event)
  639. (region-click edit event
  640. (λ (click eol start end)
  641. (let* ([line (send edit position-line
  642. click eol)]
  643. [start (send edit line-start-position
  644. line #f)]
  645. [end (send edit line-end-position
  646. line #f)])
  647. (send edit set-position start end)))))]
  648. [goto-line
  649. (λ (edit event)
  650. (let ([num-str
  651. (call/text-keymap-initializer
  652. (λ ()
  653. (get-text-from-user
  654. (string-constant goto-line)
  655. (string-constant goto-line))))])
  656. (when (string? num-str)
  657. (let* ([possible-num (string->number num-str)]
  658. [line-num (and possible-num (inexact->exact possible-num))])
  659. (cond
  660. [(and (number? line-num)
  661. (integer? line-num)
  662. (<= 1 line-num (+ (send edit last-paragraph) 1)))
  663. (let ([pos (send edit paragraph-start-position
  664. (sub1 line-num))])
  665. (send edit set-position pos))]
  666. [else
  667. (message-box
  668. (string-constant goto-line)
  669. (format
  670. (string-constant goto-line-invalid-number)
  671. num-str
  672. (+ (send edit last-line) 1)))]))))
  673. #t)]
  674. [repeater
  675. (λ (n edit)
  676. (let* ([km (send edit get-keymap)]
  677. [done
  678. (λ ()
  679. (send km set-break-sequence-callback void)
  680. (send km remove-grab-key-function))])
  681. (send km set-grab-key-function
  682. (λ (name local-km edit event)
  683. (if name
  684. (begin
  685. (done)
  686. (dynamic-wind
  687. (λ ()
  688. (send edit begin-edit-sequence))
  689. (λ ()
  690. (let loop ([n n])
  691. (unless (zero? n)
  692. (send local-km call-function name edit event)
  693. (loop (sub1 n)))))
  694. (λ ()
  695. (send edit end-edit-sequence))))
  696. (let ([k (send event get-key-code)])
  697. (if (and (char? k) (char<=? #\0 k #\9))
  698. (set! n (+ (* n 10) (- (char->integer k)
  699. (char->integer #\0))))
  700. (begin
  701. (done)
  702. (dynamic-wind
  703. (λ ()
  704. (send edit begin-edit-sequence))
  705. (λ ()
  706. (let loop ([n n])
  707. (unless (zero? n)
  708. (send edit on-char event)
  709. (loop (sub1 n)))))
  710. (λ ()
  711. (send edit end-edit-sequence)))))))
  712. #t))
  713. (send km set-break-sequence-callback done)
  714. #t))]
  715. [make-make-repeater
  716. (λ (n)
  717. (λ (edit event)
  718. (repeater n edit)))]
  719. [current-macro '()]
  720. [building-macro #f] [build-macro-km #f] [build-protect? #f]
  721. [show/hide-keyboard-macro-icon
  722. (λ (edit on?)
  723. (when (is-a? edit editor:basic<%>)
  724. (let ([frame (send edit get-top-level-window)])
  725. (when (is-a? frame frame:text-info<%>)
  726. (send frame set-macro-recording on?)
  727. (send frame update-shown)))))]
  728. [do-macro
  729. (λ (edit event)
  730. ; If c:x;e during record, copy the old macro
  731. (when building-macro
  732. (set! building-macro (append (reverse current-macro)
  733. (cdr building-macro))))
  734. (let ([bm building-macro]
  735. [km (send edit get-keymap)])
  736. (dynamic-wind
  737. (λ ()
  738. (set! building-macro #f)
  739. (send edit begin-edit-sequence))
  740. (λ ()
  741. (let/ec escape
  742. (for-each
  743. (λ (f)
  744. (let ([name (car f)]
  745. [event (cdr f)])
  746. (if name
  747. (unless (send km call-function name edit event #t)
  748. (escape #t))
  749. (send edit on-char event))))
  750. current-macro)))
  751. (λ ()
  752. (send edit end-edit-sequence)
  753. (set! building-macro bm))))
  754. #t)]
  755. [start-macro
  756. (λ (edit event)
  757. (if building-macro
  758. (send build-macro-km break-sequence)
  759. (letrec ([km (send edit get-keymap)]
  760. [done
  761. (λ ()
  762. (if build-protect?
  763. (send km set-break-sequence-callback done)
  764. (begin
  765. (set! building-macro #f)
  766. (show/hide-keyboard-macro-icon edit #f)
  767. (send km set-break-sequence-callback void)
  768. (send km remove-grab-key-function))))])
  769. (set! building-macro '())
  770. (show/hide-keyboard-macro-icon edit #t)
  771. (set! build-macro-km km)
  772. (send km set-grab-key-function
  773. (λ (name local-km edit event)
  774. (dynamic-wind
  775. (λ ()
  776. (set! build-protect? #t))
  777. (λ ()
  778. (if name
  779. (send local-km call-function name edit event)
  780. (send edit on-default-char event)))
  781. (λ ()
  782. (set! build-protect? #f)))
  783. (when building-macro
  784. (set! building-macro
  785. (cons (cons name event)
  786. building-macro)))
  787. #t))
  788. (send km set-break-sequence-callback done)))
  789. #t)]
  790. [end-macro
  791. (λ (edit event)
  792. (when building-macro
  793. (set! current-macro (reverse building-macro))
  794. (set! build-protect? #f)
  795. (send build-macro-km break-sequence))
  796. #t)]
  797. [delete-key
  798. (λ (edit event)
  799. (let ([kmap (send edit get-keymap)])
  800. (send kmap call-function
  801. (if (preferences:get 'framework:delete-forward?)
  802. "delete-next-character"
  803. "delete-previous-character")
  804. edit event #t)))]
  805. [toggle-overwrite
  806. (λ (edit event)
  807. (when (preferences:get 'framework:overwrite-mode-keybindings)
  808. (send edit set-overwrite-mode
  809. (not (send edit get-overwrite-mode)))))]
  810. [down-into-embedded-editor
  811. (λ (text event)
  812. (let ([start (send text get-start-position)]
  813. [end (send text get-end-position)])
  814. (when (= start end)
  815. (let* ([bx (box 0)]
  816. [after-snip (send text find-snip start 'after-or-none bx)])
  817. (cond
  818. [(and (= (unbox bx) start)
  819. after-snip
  820. (is-a? after-snip editor-snip%))
  821. (let ([embedded-editor (send after-snip get-editor)])
  822. (when (is-a? embedded-editor text%)
  823. (send embedded-editor set-position 0))
  824. (send embedded-editor set-caret-owner #f 'global))]
  825. [else
  826. (let ([before-snip (send text find-snip start 'before-or-none bx)])
  827. (when (and (= (+ (unbox bx) 1) start)
  828. before-snip
  829. (is-a? before-snip editor-snip%))
  830. (let ([embedded-editor (send before-snip get-editor)])
  831. (when (is-a? embedded-editor text%)
  832. (send embedded-editor set-position
  833. (send embedded-editor last-position)))
  834. (send embedded-editor set-caret-owner #f 'global))))]))))
  835. #t)]
  836. [forward-to-next-embedded-editor
  837. (λ (text event)
  838. (let ([start-pos (send text get-start-position)]
  839. [end-pos (send text get-end-position)])
  840. (when (= start-pos end-pos)
  841. (let loop ([snip (send text find-snip start-pos 'after-or-none)])
  842. (cond
  843. [(not snip) (void)]
  844. [(is-a? snip editor-snip%)
  845. (send text set-position (send text get-snip-position snip))]
  846. [else (loop (send snip next))]))))
  847. #t)]
  848. [back-to-prev-embedded-editor
  849. (λ (text event)
  850. (let ([start-pos (send text get-start-position)]
  851. [end-pos (send text get-end-position)])
  852. (when (= start-pos end-pos)
  853. (let loop ([snip (send text find-snip start-pos 'before-or-none)])
  854. (cond
  855. [(not snip) (void)]
  856. [(is-a? snip editor-snip%)
  857. (send text set-position (+ (send text get-snip-position snip) 1))]
  858. [else (loop (send snip previous))]))))
  859. #t)]
  860. [up-out-of-embedded-editor
  861. (λ (text event)
  862. (let ([start (send text get-start-position)]
  863. [end (send text get-end-position)])
  864. (when (= start end)
  865. (let ([editor-admin (send text get-admin)])
  866. (when (is-a? editor-admin editor-snip-editor-admin<%>)
  867. (let* ([snip (send editor-admin get-snip)]
  868. [snip-admin (send snip get-admin)])
  869. (when snip-admin
  870. (let ([editor (send snip-admin get-editor)])
  871. (when (is-a? editor text%)
  872. (let ([new-pos (send editor get-snip-position snip)])
  873. (send editor set-position new-pos new-pos))
  874. (send editor set-caret-owner #f 'display)))))))))
  875. #t)]
  876. [make-read-only
  877. (λ (text event)
  878. (send text lock #t)
  879. #t)]
  880. [newline
  881. (λ (text event)
  882. (send text insert "\n")
  883. #t)]
  884. [shift-focus
  885. (λ (adjust)
  886. (λ (text event)
  887. (when (is-a? text editor:basic<%>)
  888. (let ([frame (send text get-top-level-window)])
  889. (let ([found-one? #f])
  890. (let/ec k
  891. (let ([go
  892. (λ ()
  893. (let loop ([obj frame])
  894. (cond
  895. [(and found-one?
  896. (is-a? obj editor-canvas%)
  897. (is-a? (send obj get-editor) editor:keymap<%>))
  898. (send obj focus)
  899. (k (void))]
  900. [(and (is-a? obj window<%>) (send obj has-focus?))
  901. (set! found-one? #t)]
  902. [(is-a? obj area-container<%>)
  903. (for-each loop (adjust (send obj get-children)))])))])
  904. (go)
  905. ;;; when we get here, we either didn't find the focus anywhere,
  906. ;;; or the last editor-canvas had the focus. either way,
  907. ;;; the next thing should get the focus
  908. (set! found-one? #t)
  909. (go))))))))]
  910. [TeX-compress
  911. (let* ([biggest (apply max (map (λ (x) (string-length (car x))) tex-shortcut-table))])
  912. (λ (text event)
  913. (let ([pos (send text get-start-position)])
  914. (when (= pos (send text get-end-position))
  915. (let ([slash (send text find-string "\\" 'backward pos (max 0 (- pos biggest 1)))])
  916. (when slash
  917. (let ([to-replace (assoc (send text get-text slash pos) tex-shortcut-table)])
  918. (when to-replace
  919. (send text begin-edit-sequence)
  920. (send text delete (- slash 1) pos)
  921. (send text insert (cadr to-replace))
  922. (send text end-edit-sequence)))))))))]
  923. [greek-letters "αβγδεζηθι κλμνξοπρςστυφχψω"]
  924. [Greek-letters "ΑΒΓΔΕΖΗΘΙ ΚΛΜΝΞΟΠΡ ΣΤΥΦΧΨΩ"]) ;; don't have a capital ς, just comes out as \u03A2 (or junk)
  925. (λ (kmap)
  926. (let* ([map (λ (key func)
  927. (send kmap map-function key func))]
  928. [map-meta (λ (key func)
  929. (send-map-function-meta kmap key func))]
  930. [add (λ (name func)
  931. (send kmap add-function name func))]
  932. [add-m (λ (name func)
  933. (send kmap add-function name func))])
  934. ; Map names to keyboard functions
  935. (for-each
  936. (λ (c)
  937. (unless (equal? c #\space)
  938. (add (format "insert ~a" c)
  939. (λ (txt evt) (send txt insert c)))))
  940. (string->list (string-append greek-letters Greek-letters)))
  941. (add "shift-focus" (shift-focus values))
  942. (add "shift-focus-backwards" (shift-focus reverse))
  943. (add "TeX compress" TeX-compress)
  944. (add "newline" newline)
  945. (add "down-into-embedded-editor" down-into-embedded-editor)
  946. (add "up-out-of-embedded-editor" up-out-of-embedded-editor)
  947. (add "forward-to-next-embedded-editor" forward-to-next-embedded-editor)
  948. (add "back-to-prev-embedded-editor" back-to-prev-embedded-editor)
  949. (add "toggle-overwrite (when enabled in prefs)" toggle-overwrite)
  950. (add "exit" (λ (edit event)
  951. (let ([frame (send edit get-frame)])
  952. (if (and frame
  953. (is-a? frame frame:standard-menus<%>))
  954. (send frame file-menu:quit)
  955. (bell)))))
  956. (add "ring-bell" ring-bell)
  957. (add "insert-()-pair" (make-insert-brace-pair "(" ")"))
  958. (add "insert-[]-pair" (make-insert-brace-pair "[" "]"))
  959. (add "insert-{}-pair" (make-insert-brace-pair "{" "}"))
  960. (add "insert-\"\"-pair" (make-insert-brace-pair "\"" "\""))
  961. (add "insert-||-pair" (make-insert-brace-pair "|" "|"))
  962. (add "insert-lambda-template" insert-lambda-template)
  963. (add "toggle-anchor" toggle-anchor)
  964. (add "center-view-on-line" center-view-on-line)
  965. (add "collapse-space" collapse-space)
  966. (add "remove-space" remove-space)
  967. (add "collapse-newline" collapse-newline)
  968. (add "open-line" open-line)
  969. (add "transpose-chars" transpose-chars)
  970. (add "transpose-words" transpose-words)
  971. (add "capitalize-word" capitalize-word)
  972. (add "upcase-word" upcase-word)
  973. (add "downcase-word" downcase-word)
  974. (add "kill-word" kill-word)
  975. (add "backward-kill-word" backward-kill-word)
  976. (let loop ([n 9])
  977. (unless (negative? n)
  978. (let ([s (number->string n)])
  979. (add (string-append "command-repeat-" s)
  980. (make-make-repeater n))
  981. (loop (sub1 n)))))
  982. (add "keyboard-macro-run-saved" do-macro)
  983. (add "keyboard-macro-start-record" start-macro)
  984. (add "keyboard-macro-end-record" end-macro)
  985. (add-m "copy-clipboard" mouse-copy-clipboard)
  986. (add-m "cut-clipboard" mouse-cut-clipboard)
  987. (add-m "paste-clipboard" mouse-paste-clipboard)
  988. (add-m "copy-click-region" copy-click-region)
  989. (add-m "cut-click-region" cut-click-region)
  990. (add-m "paste-click-region" paste-click-region)
  991. (add-m "select-click-word" select-click-word)
  992. (add-m "select-click-line" select-click-line)
  993. (add "goto-line" goto-line)
  994. (add "delete-key" delete-key)
  995. (add "mouse-popup-menu" mouse-popup-menu)
  996. (add "make-read-only" make-read-only)
  997. ; Map keys to functions
  998. (let ([setup-mappings
  999. (λ (greek-chars shift?)
  1000. (let loop ([i 0])
  1001. (when (< i (string-length greek-chars))
  1002. (let ([greek-char (string-ref greek-chars i)])
  1003. (unless (equal? greek-char #\space)
  1004. (let ([roman-char
  1005. (integer->char
  1006. (+ (char->integer #\a) i))])
  1007. (map (format "a:g;~a~a"
  1008. (if shift? "s:" "")
  1009. roman-char)
  1010. (format "insert ~a" greek-char))
  1011. (map (format "m:x;c:g;~a~a"
  1012. (if shift? "s:" "")
  1013. roman-char)
  1014. (format "insert ~a" greek-char))
  1015. (map (format "c:x;c:g;~a~a"
  1016. (if shift? "s:" "")
  1017. roman-char)
  1018. (format "insert ~a" greek-char)))))
  1019. (loop (+ i 1)))))])
  1020. (setup-mappings greek-letters #f)
  1021. (setup-mappings Greek-letters #t))
  1022. (map "~m:c:\\" "TeX compress")
  1023. (map "~c:m:\\" "TeX compress")
  1024. (map "c:j" "newline")
  1025. (map-meta "c:down" "down-into-embedded-editor")
  1026. (map "a:c:down" "down-into-embedded-editor")
  1027. (map-meta "c:up" "up-out-of-embedded-editor")
  1028. (map "a:c:up" "up-out-of-embedded-editor")
  1029. (map-meta "c:right" "forward-to-next-embedded-editor")
  1030. (map "a:c:right" "forward-to-next-embedded-editor")
  1031. (map-meta "c:left" "back-to-prev-embedded-editor")
  1032. (map "a:c:left" "back-to-prev-embedded-editor")
  1033. (map "c:c;c:g" "ring-bell")
  1034. (map-meta "(" "insert-()-pair")
  1035. (map-meta "[" "insert-[]-pair")
  1036. (map-meta "{" "insert-{}-pair")
  1037. (map-meta "\"" "insert-\"\"-pair")
  1038. (map-meta "|" "insert-||-pair")
  1039. (map-meta "s:l" "insert-lambda-template")
  1040. (map "c:p" "previous-line")
  1041. (map "up" "previous-line")
  1042. (map "s:c:p" "select-up")
  1043. (map "s:up" "select-up")
  1044. (map "c:n" "next-line")
  1045. (map "down" "next-line")
  1046. (map "s:c:n" "select-down")
  1047. (map "s:down" "select-down")
  1048. (map "c:e" "end-of-line")
  1049. (map "d:right" "end-of-line")
  1050. (map "end" "end-of-line")
  1051. (map "s:end" "select-to-end-of-line")
  1052. (map "s:c:e" "select-to-end-of-line")
  1053. (map "s:d:right" "select-to-end-of-line")
  1054. (map "c:a" "beginning-of-line")
  1055. (map "d:left" "beginning-of-line")
  1056. (map "home" "beginning-of-line")
  1057. (map "s:home" "select-to-beginning-of-line")
  1058. (map "s:c:a" "select-to-beginning-of-line")
  1059. (map "s:d:left" "select-to-beginning-of-line")
  1060. (map "c:f" "forward-character")
  1061. (map "right" "forward-character")
  1062. (map "s:c:f" "forward-select")
  1063. (map "s:right" "forward-select")
  1064. (map "c:b" "backward-character")
  1065. (map "left" "backward-character")
  1066. (map "s:c:b" "backward-select")
  1067. (map "s:left" "backward-select")
  1068. (map-meta "f" "forward-word")
  1069. (map "c:right" "forward-word")
  1070. (map-meta "s:f" "forward-select-word")
  1071. (map "c:s:right" "forward-select-word")
  1072. (map-meta "b" "backward-word")
  1073. (map "c:left" "backward-word")
  1074. (map-meta "s:b" "backward-select-word")
  1075. (map "c:s:left" "backward-select-word")
  1076. (map-meta "<" "beginning-of-file")
  1077. (map "d:up" "beginning-of-file")
  1078. (map "c:home" "beginning-of-file")
  1079. (map "s:c:home" "select-to-beginning-of-file")
  1080. (map "s:d:up" "select-to-beginning-of-file")
  1081. (map-meta ">" "end-of-file")
  1082. (map "d:down" "end-of-file")
  1083. (map "c:end" "end-of-file")
  1084. (map "s:c:end" "select-to-end-of-file")
  1085. (map "s:d:down" "select-to-end-of-file")
  1086. (map "c:v" "next-page")
  1087. (map "pagedown" "next-page")
  1088. (map "c:down" "next-page")
  1089. (map "s:c:v" "select-page-down")
  1090. (map "s:pagedown" "select-page-down")
  1091. (map "s:c:down" "select-page-down")
  1092. (map-meta "v" "previous-page")
  1093. (map "pageup" "previous-page")
  1094. (map "c:up" "previous-page")
  1095. (map-meta "s:v" "select-page-up")
  1096. (map "s:pageup" "select-page-up")
  1097. (map "s:c:up" "select-page-up")
  1098. (map "c:h" "delete-previous-character")
  1099. (map "c:d" "delete-next-character")
  1100. (map "del" "delete-key")
  1101. (map-meta "d" "kill-word")
  1102. (map-meta "del" "backward-kill-word")
  1103. (map-meta "c" "capitalize-word")
  1104. (map-meta "u" "upcase-word")
  1105. (map-meta "l" "downcase-word")
  1106. (map "c:l" "center-view-on-line")
  1107. (map "c:k" "delete-to-end-of-line")
  1108. (map "c:y" "paste-clipboard")
  1109. (map-meta "y" "paste-next")
  1110. (map "a:v" "paste-clipboard")
  1111. (map "d:v" "paste-clipboard")
  1112. (map "c:_" "undo")
  1113. (map "c:/" "undo")
  1114. (map (format "~a" (integer->char 31)) "undo") ; for Windows - strange
  1115. (map "c:+" "redo")
  1116. (map "a:z" "undo")
  1117. (map "d:z" "undo")
  1118. (map "c:x;u" "undo")
  1119. (map "c:w" "cut-clipboard")
  1120. (map "a:x" "cut-clipboard")
  1121. (map "d:x" "cut-clipboard")
  1122. (map-meta "w" "copy-clipboard")
  1123. (map "a:c" "copy-clipboard")
  1124. (map "d:c" "copy-clipboard")
  1125. (map "s:delete" "cut-clipboard")
  1126. (map "c:insert" "copy-clipboard")
  1127. (map "s:insert" "paste-clipboard")
  1128. (map-meta "space" "collapse-space")
  1129. (when (eq? (system-type) 'macosx)
  1130. (map "a:space" "collapse-space"))
  1131. ;(map-meta "\\" "remove-space") ; Conflicts with european keyboards.
  1132. (map "c:x;c:o" "collapse-newline")
  1133. (map "c:o" "open-line")
  1134. (map "c:t" "transpose-chars")
  1135. (map-meta "t" "transpose-words")
  1136. (map "c:space" "toggle-anchor")
  1137. (map "insert" "toggle-overwrite (when enabled in prefs)")
  1138. (map-meta "o" "toggle-overwrite (when enabled in prefs)")
  1139. (map-meta "g" "goto-line")
  1140. (map "c:u" "command-repeat-0")
  1141. (let loop ([n 9])
  1142. (unless (negative? n)
  1143. (let ([s (number->string n)])
  1144. (map-meta s (string-append "command-repeat-" s))
  1145. (loop (sub1 n)))))
  1146. (map "c:x;e" "keyboard-macro-run-saved")
  1147. (map "c:x;(" "keyboard-macro-start-record")
  1148. (map "c:x;)" "keyboard-macro-end-record")
  1149. (map "leftbuttontriple" "select-click-line")
  1150. (map "leftbuttondouble" "select-click-word")
  1151. ;; the "roller ball" mice map clicking the ball to button 2.
  1152. (unless (eq? (system-type) 'windows)
  1153. (map "middlebutton" "paste-click-region"))
  1154. (map ":rightbuttonseq" "mouse-popup-menu")
  1155. (map "c:c;c:r" "make-read-only")
  1156. (map "c:x;o" "shift-focus")
  1157. (map "c:x;p" "shift-focus-backwards")
  1158. (map "c:f6" "shift-focus")
  1159. (map "a:tab" "shift-focus")
  1160. (map "a:s:tab" "shift-focus-backwards")
  1161. ))))
  1162. (define setup-search
  1163. (let* ([send-frame
  1164. (λ (invoke-method)
  1165. (λ (edit event)
  1166. (let ([frame
  1167. (cond
  1168. [(is-a? edit editor<%>)
  1169. (let ([canvas (send edit get-active-canvas)])
  1170. (and canvas
  1171. (send canvas get-top-level-window)))]
  1172. [(is-a? edit area<%>)
  1173. (send edit get-top-level-window)]
  1174. [else #f])])
  1175. (if frame
  1176. (invoke-method frame)
  1177. (bell)))
  1178. #t))])
  1179. (λ (kmap)
  1180. (let* ([map (λ (key func)
  1181. (send kmap map-function key func))]
  1182. [map-meta (λ (key func)
  1183. (send-map-function-meta kmap key func))]
  1184. [add (λ (name func)
  1185. (send kmap add-function name func))]
  1186. [add-m (λ (name func)
  1187. (send kmap add-function name func))])
  1188. (add "search forward"
  1189. (send-frame (λ (f) (send f search 'forward))))
  1190. (add "search backward"
  1191. (send-frame (λ (f) (send f search 'backward))))
  1192. (add "replace & search forward"
  1193. (send-frame (λ (f) (send f replace&search 'forward))))
  1194. (add "replace & search backward"
  1195. (send-frame (λ (f) (send f replace&search 'backward))))
  1196. (add "unhide search and toggle focus"
  1197. (send-frame (λ (f) (send f unhide-search-and-toggle-focus))))
  1198. (add "hide-search"
  1199. (send-frame (λ (f) (send f hide-search))))
  1200. (map "c:g" "hide-search")
  1201. (map "f3" "unhide search and toggle focus")
  1202. (map "c:s" "search forward")
  1203. (map "c:r" "search backward")
  1204. (case (system-type)
  1205. [(unix)
  1206. (map-meta "%" "search forward")])))))
  1207. (define setup-file
  1208. (let* ([get-outer-editor ;; : text% -> text%
  1209. ;; returns the outermost editor, if this editor is nested in an editor snip.
  1210. (λ (edit)
  1211. (let loop ([edit edit])
  1212. (let ([admin (send edit get-admin)])
  1213. (cond
  1214. [(is-a? admin editor-snip-editor-admin<%>)
  1215. (loop (send (send (send admin get-snip) get-admin) get-editor))]
  1216. [else edit]))))]
  1217. [save-file-as
  1218. (λ (this-edit event)
  1219. (let ([edit (get-outer-editor this-edit)])
  1220. (parameterize ([finder:dialog-parent-parameter
  1221. (and (is-a? edit editor:basic<%>)
  1222. (send edit get-top-level-window))])
  1223. (let ([file (finder:put-file)])
  1224. (when file
  1225. (send edit save-file/gui-error file)))))
  1226. #t)]
  1227. [save-file
  1228. (λ (this-edit event)
  1229. (let ([edit (get-outer-editor this-edit)])
  1230. (if (send edit get-filename)
  1231. (send edit save-file/gui-error)
  1232. (save-file-as edit event)))
  1233. #t)]
  1234. [load-file
  1235. (λ (edit event)
  1236. (let ([fn (send edit get-filename)])
  1237. (handler:open-file
  1238. (and fn
  1239. (let-values ([(base name dir) (split-path fn)])
  1240. base))))
  1241. #t)])
  1242. (λ (kmap)
  1243. (let* ([map (λ (key func)
  1244. (send kmap map-function key func))]
  1245. [map-meta (λ (key func)
  1246. (send-map-function-meta kmap key func))]
  1247. [add (λ (name func)
  1248. (send kmap add-function name func))]
  1249. [add-m (λ (name func)
  1250. (send kmap add-function name func))])
  1251. (add "save-file" save-file)
  1252. (add "save-file-as" save-file-as)
  1253. (add "load-file" load-file)
  1254. (map "c:x;c:s" "save-file")
  1255. (map "d:s" "save-file")
  1256. (map "c:x;c:w" "save-file-as")
  1257. (map "c:x;c:f" "load-file")))))
  1258. (define (setup-editor kmap)
  1259. (let ([add/map
  1260. (λ (func op key)
  1261. (send kmap add-function
  1262. func
  1263. (λ (editor evt)
  1264. (send editor do-edit-operation op)))
  1265. (send kmap map-function
  1266. (string-append
  1267. (case (system-type)
  1268. [(macosx macos) "d:"]
  1269. [(windows unix) "c:"]
  1270. [else (error 'keymap.ss "unknown platform: ~s" (system-type))])
  1271. key)
  1272. func))])
  1273. (add/map "editor-undo" 'undo "z")
  1274. (unless (eq? (system-type) 'macosx)
  1275. (add/map "editor-redo" 'redo "y"))
  1276. (add/map "editor-cut" 'cut "x")
  1277. (add/map "editor-copy" 'copy "c")
  1278. (add/map "editor-paste" 'paste "v")
  1279. (add/map "editor-select-all" 'select-all "a")))
  1280. (define (generic-setup keymap)
  1281. (add-editor-keymap-functions keymap)
  1282. (add-pasteboard-keymap-functions keymap)
  1283. (add-text-keymap-functions keymap))
  1284. (define user-keymap (make-object aug-keymap%))
  1285. (define (get-user) user-keymap)
  1286. (define global (make-object aug-keymap%))
  1287. (define global-main (make-object aug-keymap%))
  1288. (send global chain-to-keymap global-main #f)
  1289. (setup-global global-main)
  1290. (generic-setup global-main)
  1291. (define (get-global) global)
  1292. (define file (make-object aug-keymap%))
  1293. (setup-file file)
  1294. (generic-setup file)
  1295. (define (-get-file) file)
  1296. (define search (make-object aug-keymap%))
  1297. (generic-setup search)
  1298. (setup-search search)
  1299. (define (get-search) search)
  1300. (define editor (make-object aug-keymap%))
  1301. (setup-editor editor)
  1302. (define (get-editor) editor)
  1303. (define (call/text-keymap-initializer thunk)
  1304. (let ([ctki (current-text-keymap-initializer)])
  1305. (parameterize ([current-text-keymap-initializer
  1306. (λ (keymap)
  1307. (send keymap chain-to-keymap global #t)
  1308. (ctki keymap))])
  1309. (thunk))))