]> code.delx.au - gnu-emacs/blob - lisp/term/ns-win.el
* term/ns-win.el (ns-insert-working-text, ns-delete-working-text):
[gnu-emacs] / lisp / term / ns-win.el
1 ;;; ns-win.el --- lisp side of interface with NeXT/Open/GNUstep/MacOS X window system
2
3 ;; Copyright (C) 1993, 1994, 2005, 2006, 2007, 2008, 2009
4 ;; Free Software Foundation, Inc.
5
6 ;; Authors: Carl Edman
7 ;; Christian Limpach
8 ;; Scott Bender
9 ;; Christophe de Dinechin
10 ;; Adrian Robert
11 ;; Keywords: terminals
12
13 ;; This file is part of GNU Emacs.
14
15 ;; GNU Emacs is free software: you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation, either version 3 of the License, or
18 ;; (at your option) any later version.
19
20 ;; GNU Emacs is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
27
28 ;;; Commentary:
29
30 ;; ns-win.el: this file is loaded from ../lisp/startup.el when it
31 ;; recognizes that Nextstep windows are to be used. Command line
32 ;; switches are parsed and those pertaining to Nextstep are processed
33 ;; and removed from the command line. The Nextstep display is opened
34 ;; and hooks are set for popping up the initial window.
35
36 ;; startup.el will then examine startup files, and eventually call the hooks
37 ;; which create the first window (s).
38
39 ;; A number of other Nextstep convenience functions are defined in
40 ;; this file, which works in close coordination with src/nsfns.m.
41
42 ;;; Code:
43
44
45 (if (not (featurep 'ns))
46 (error "%s: Loading ns-win.el but not compiled for GNUstep/MacOS"
47 (invocation-name)))
48
49 (eval-when-compile (require 'cl))
50
51 ;; Documentation-purposes only: actually loaded in loadup.el
52 (require 'frame)
53 (require 'mouse)
54 (require 'faces)
55 (require 'easymenu)
56 (require 'menu-bar)
57 (require 'fontset)
58
59 ;; Not needed?
60 ;;(require 'ispell)
61
62 ;; nsterm.m
63 (defvar ns-version-string)
64 (defvar ns-expand-space)
65 (defvar ns-alternate-modifier)
66
67 ;;;; Command line argument handling.
68
69 (defvar ns-invocation-args nil)
70 (defvar ns-command-line-resources nil)
71
72 ;; Handler for switches of the form "-switch value" or "-switch".
73 (defun ns-handle-switch (switch &optional numeric)
74 (let ((aelt (assoc switch command-line-ns-option-alist)))
75 (if aelt
76 (setq default-frame-alist
77 (cons (cons (nth 3 aelt)
78 (if numeric
79 (string-to-number (pop ns-invocation-args))
80 (or (nth 4 aelt) (pop ns-invocation-args))))
81 default-frame-alist)))))
82
83 ;; Handler for switches of the form "-switch n"
84 (defun ns-handle-numeric-switch (switch)
85 (ns-handle-switch switch t))
86
87 ;; Make -iconic apply only to the initial frame!
88 (defun ns-handle-iconic (switch)
89 (setq initial-frame-alist
90 (cons '(visibility . icon) initial-frame-alist)))
91
92 ;; Handle the -name option, set the name of the initial frame.
93 (defun ns-handle-name-switch (switch)
94 (or (consp ns-invocation-args)
95 (error "%s: missing argument to `%s' option" (invocation-name) switch))
96 (setq initial-frame-alist (cons (cons 'name (pop ns-invocation-args))
97 initial-frame-alist)))
98
99 ;; Set (but not used?) in frame.el.
100 (defvar x-display-name nil
101 "The name of the Nextstep display on which Emacs was started.")
102
103 ;; nsterm.m.
104 (defvar ns-input-file)
105
106 (defun ns-handle-nxopen (switch)
107 (setq unread-command-events (append unread-command-events '(ns-open-file))
108 ns-input-file (append ns-input-file (list (pop ns-invocation-args)))))
109
110 (defun ns-handle-nxopentemp (switch)
111 (setq unread-command-events (append unread-command-events
112 '(ns-open-temp-file))
113 ns-input-file (append ns-input-file (list (pop ns-invocation-args)))))
114
115 (defun ns-ignore-1-arg (switch)
116 (setq ns-invocation-args (cdr ns-invocation-args)))
117 (defun ns-ignore-2-arg (switch)
118 (setq ns-invocation-args (cddr ns-invocation-args)))
119
120 (defun ns-handle-args (args)
121 "Process Nextstep-related command line options.
122 This is run before the user's startup file is loaded.
123 The options in ARGS are copied to `ns-invocation-args'.
124 The Nextstep-related settings are then applied using the handlers
125 defined in `command-line-ns-option-alist'.
126 The return value is ARGS minus the number of arguments processed."
127 ;; We use ARGS to accumulate the args that we don't handle here, to return.
128 (setq ns-invocation-args args
129 args nil)
130 (while ns-invocation-args
131 (let* ((this-switch (pop ns-invocation-args))
132 (orig-this-switch this-switch)
133 completion argval aelt handler)
134 ;; Check for long options with attached arguments
135 ;; and separate out the attached option argument into argval.
136 (if (string-match "^--[^=]*=" this-switch)
137 (setq argval (substring this-switch (match-end 0))
138 this-switch (substring this-switch 0 (1- (match-end 0)))))
139 ;; Complete names of long options.
140 (if (string-match "^--" this-switch)
141 (progn
142 (setq completion (try-completion this-switch
143 command-line-ns-option-alist))
144 (if (eq completion t)
145 ;; Exact match for long option.
146 nil
147 (if (stringp completion)
148 (let ((elt (assoc completion command-line-ns-option-alist)))
149 ;; Check for abbreviated long option.
150 (or elt
151 (error "Option `%s' is ambiguous" this-switch))
152 (setq this-switch completion))))))
153 (setq aelt (assoc this-switch command-line-ns-option-alist))
154 (if aelt (setq handler (nth 2 aelt)))
155 (if handler
156 (if argval
157 (let ((ns-invocation-args
158 (cons argval ns-invocation-args)))
159 (funcall handler this-switch))
160 (funcall handler this-switch))
161 (setq args (cons orig-this-switch args)))))
162 (nreverse args))
163
164 (defun ns-parse-geometry (geom)
165 "Parse a Nextstep-style geometry string GEOM.
166 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
167 The properties returned may include `top', `left', `height', and `width'."
168 (when (string-match "\\([0-9]+\\)\\( \\([0-9]+\\)\\( \\([0-9]+\\)\
169 \\( \\([0-9]+\\) ?\\)?\\)?\\)?"
170 geom)
171 (apply
172 'append
173 (list
174 (list (cons 'top (string-to-number (match-string 1 geom))))
175 (if (match-string 3 geom)
176 (list (cons 'left (string-to-number (match-string 3 geom)))))
177 (if (match-string 5 geom)
178 (list (cons 'height (string-to-number (match-string 5 geom)))))
179 (if (match-string 7 geom)
180 (list (cons 'width (string-to-number (match-string 7 geom)))))))))
181
182 ;;;; Keyboard mapping.
183
184 ;; These tell read-char how to convert these special chars to ASCII.
185 ;;TODO: all terms have these, and at least the return mapping is necessary
186 ;; for tramp to recognize the enter key.
187 ;; Perhaps they should be moved into common code somewhere
188 ;; (when a window system is active).
189 ;; Remove if no problems for some time after 2008-08-06.
190 (put 'backspace 'ascii-character 127)
191 (put 'delete 'ascii-character 127)
192 (put 'tab 'ascii-character ?\t)
193 (put 'S-tab 'ascii-character (logior 16 ?\t))
194 (put 'linefeed 'ascii-character ?\n)
195 (put 'clear 'ascii-character 12)
196 (put 'return 'ascii-character 13)
197 (put 'escape 'ascii-character ?\e)
198
199
200 (defvar ns-alternatives-map
201 (let ((map (make-sparse-keymap)))
202 ;; Map certain keypad keys into ASCII characters
203 ;; that people usually expect.
204 (define-key map [backspace] [?\d])
205 (define-key map [delete] [?\d])
206 (define-key map [tab] [?\t])
207 (define-key map [S-tab] [25])
208 (define-key map [linefeed] [?\n])
209 (define-key map [clear] [?\C-l])
210 (define-key map [return] [?\C-m])
211 (define-key map [escape] [?\e])
212 (define-key map [M-backspace] [?\M-\d])
213 (define-key map [M-delete] [?\M-\d])
214 (define-key map [M-tab] [?\M-\t])
215 (define-key map [M-linefeed] [?\M-\n])
216 (define-key map [M-clear] [?\M-\C-l])
217 (define-key map [M-return] [?\M-\C-m])
218 (define-key map [M-escape] [?\M-\e])
219 map)
220 "Keymap of alternative meanings for some keys under NS.")
221
222 ;; Here are some Nextstep-like bindings for command key sequences.
223 (define-key global-map [?\s-,] 'ns-popup-prefs-panel)
224 (define-key global-map [?\s-'] 'next-multiframe-window)
225 (define-key global-map [?\s-`] 'other-frame)
226 (define-key global-map [?\s--] 'center-line)
227 (define-key global-map [?\s-:] 'ispell)
228 (define-key global-map [?\s-\;] 'ispell-next)
229 (define-key global-map [?\s-?] 'info)
230 (define-key global-map [?\s-^] 'kill-some-buffers)
231 (define-key global-map [?\s-&] 'kill-this-buffer)
232 (define-key global-map [?\s-C] 'ns-popup-color-panel)
233 (define-key global-map [?\s-D] 'dired)
234 (define-key global-map [?\s-E] 'edit-abbrevs)
235 (define-key global-map [?\s-L] 'shell-command)
236 (define-key global-map [?\s-M] 'manual-entry)
237 (define-key global-map [?\s-S] 'ns-write-file-using-panel)
238 (define-key global-map [?\s-a] 'mark-whole-buffer)
239 (define-key global-map [?\s-c] 'ns-copy-including-secondary)
240 (define-key global-map [?\s-d] 'isearch-repeat-backward)
241 (define-key global-map [?\s-e] 'isearch-yank-kill)
242 (define-key global-map [?\s-f] 'isearch-forward)
243 (define-key global-map [?\s-g] 'isearch-repeat-forward)
244 (define-key global-map [?\s-h] 'ns-do-hide-emacs)
245 (define-key global-map [?\s-H] 'ns-do-hide-others)
246 (define-key global-map [?\s-j] 'exchange-point-and-mark)
247 (define-key global-map [?\s-k] 'kill-this-buffer)
248 (define-key global-map [?\s-l] 'goto-line)
249 (define-key global-map [?\s-m] 'iconify-frame)
250 (define-key global-map [?\s-n] 'make-frame)
251 (define-key global-map [?\s-o] 'ns-open-file-using-panel)
252 (define-key global-map [?\s-p] 'ns-print-buffer)
253 (define-key global-map [?\s-q] 'save-buffers-kill-emacs)
254 (define-key global-map [?\s-s] 'save-buffer)
255 (define-key global-map [?\s-t] 'ns-popup-font-panel)
256 (define-key global-map [?\s-u] 'revert-buffer)
257 (define-key global-map [?\s-v] 'yank)
258 (define-key global-map [?\s-w] 'delete-frame)
259 (define-key global-map [?\s-x] 'kill-region)
260 (define-key global-map [?\s-y] 'ns-paste-secondary)
261 (define-key global-map [?\s-z] 'undo)
262 (define-key global-map [?\s-|] 'shell-command-on-region)
263 (define-key global-map [s-kp-bar] 'shell-command-on-region)
264 ;; (as in Terminal.app)
265 (define-key global-map [s-right] 'ns-next-frame)
266 (define-key global-map [s-left] 'ns-prev-frame)
267
268 (define-key global-map [home] 'beginning-of-buffer)
269 (define-key global-map [end] 'end-of-buffer)
270 (define-key global-map [kp-home] 'beginning-of-buffer)
271 (define-key global-map [kp-end] 'end-of-buffer)
272 (define-key global-map [kp-prior] 'scroll-down)
273 (define-key global-map [kp-next] 'scroll-up)
274
275 ;;; Allow shift-clicks to work similarly to under Nextstep
276 (define-key global-map [S-mouse-1] 'mouse-save-then-kill)
277 (global-unset-key [S-down-mouse-1])
278
279
280 ;; Special Nextstep-generated events are converted to function keys. Here
281 ;; are the bindings for them.
282 (define-key global-map [ns-power-off]
283 (lambda () (interactive) (save-buffers-kill-emacs t)))
284 (define-key global-map [ns-open-file] 'ns-find-file)
285 (define-key global-map [ns-open-temp-file] [ns-open-file])
286 (define-key global-map [ns-drag-file] 'ns-insert-file)
287 (define-key global-map [ns-drag-color] 'ns-set-foreground-at-mouse)
288 (define-key global-map [S-ns-drag-color] 'ns-set-background-at-mouse)
289 (define-key global-map [ns-drag-text] 'ns-insert-text)
290 (define-key global-map [ns-change-font] 'ns-respond-to-change-font)
291 (define-key global-map [ns-open-file-line] 'ns-open-file-select-line)
292 (define-key global-map [ns-spi-service-call] 'ns-spi-service-call)
293 (define-key global-map [ns-new-frame] 'make-frame)
294 (define-key global-map [ns-toggle-toolbar] 'ns-toggle-toolbar)
295 (define-key global-map [ns-info-prefs] 'ns-show-preferences-help)
296
297
298 ;; Functions to set environment variables by running a subshell.
299 ;;; Idea based on Nextstep 4.2 distribution, this version of code
300 ;;; based on mac-read-environment-vars-from-shell () by David Reitter.
301 ;;; Mostly used only under ns-extended-platform-support-mode.
302
303 (defun ns-make-command-string (cmdlist)
304 (mapconcat 'identity cmdlist " ; "))
305
306 ;;;###autoload
307 (defun ns-grabenv (&optional shell-path startup)
308 "Set the Emacs environment using the output of a shell command.
309 This runs a shell subprocess, and interpret its output as a
310 series of environment variables to insert into the emacs
311 environment.
312 SHELL-PATH gives the path to the shell; if nil, this defaults to
313 the current setting of `shell-file-name'.
314 STARTUP is a list of commands for the shell to execute; if nil,
315 this defaults to \"printenv\"."
316 (interactive)
317 (with-temp-buffer
318 (let ((shell-file-name (if shell-path shell-path shell-file-name))
319 (cmd (ns-make-command-string (if startup startup '("printenv")))))
320 (shell-command cmd t)
321 (while (search-forward-regexp "^\\([A-Za-z_0-9]+\\)=\\(.*\\)$" nil t)
322 (setenv (match-string 1)
323 (if (equal (match-string 1) "PATH")
324 (concat (getenv "PATH") ":" (match-string 2))
325 (match-string 2)))))))
326
327 ;; Set up a number of aliases and other layers to pretend we're using
328 ;; the Choi/Mitsuharu Carbon port.
329
330 (defvaralias 'mac-allow-anti-aliasing 'ns-antialias-text)
331 (defvaralias 'mac-command-modifier 'ns-command-modifier)
332 (defvaralias 'mac-control-modifier 'ns-control-modifier)
333 (defvaralias 'mac-option-modifier 'ns-option-modifier)
334 (defvaralias 'mac-function-modifier 'ns-function-modifier)
335 (declare-function ns-do-applescript "nsfns.m" (script))
336 (defalias 'do-applescript 'ns-do-applescript)
337
338
339 (defvar menu-bar-ns-file-menu) ; below
340
341 ;; Toggle some additional Nextstep-like features that may interfere
342 ;; with users' expectations coming from emacs on other platforms.
343 (define-minor-mode ns-extended-platform-support-mode
344 "Toggle Nextstep extended platform support features.
345 When this mode is active (no modeline indicator):
346 - File menu is altered slightly in keeping with conventions.
347 - Screen position is preserved in scrolling.
348 - Transient mark mode is activated"
349 :init-value nil
350 :global t
351 :group 'ns
352 (if ns-extended-platform-support-mode
353 (progn
354 (defun ns-show-manual () "Show Emacs.app section in the Emacs manual"
355 (interactive)
356 (info "(emacs) Mac OS / GNUstep"))
357 (setq where-is-preferred-modifier 'super)
358 (setq scroll-preserve-screen-position t)
359 (transient-mark-mode 1)
360
361 ;; Change file menu to simplify and add a couple of
362 ;; Nextstep-specific items
363 (easy-menu-remove-item global-map '("menu-bar") 'file)
364 (easy-menu-add-item global-map '(menu-bar)
365 (cons "File" menu-bar-ns-file-menu) 'edit)
366 (define-key menu-bar-help-menu [ns-manual]
367 '(menu-item "Read the Emacs.app Manual Chapter" ns-show-manual)))
368 (progn
369 ;; Undo everything above.
370 (fmakunbound 'ns-show-manual)
371 (setq where-is-preferred-modifier 'nil)
372 (setq scroll-preserve-screen-position nil)
373 (transient-mark-mode 0)
374 (easy-menu-remove-item global-map '("menu-bar") 'file)
375 (easy-menu-add-item global-map '(menu-bar)
376 (cons "File" menu-bar-file-menu) 'edit)
377 (easy-menu-remove-item global-map '("menu-bar" "help-menu") 'ns-manual)
378 )))
379
380
381 (defun x-setup-function-keys (frame)
382 "Set up function Keys for Nextstep for frame FRAME."
383 (unless (terminal-parameter frame 'x-setup-function-keys)
384 (with-selected-frame frame
385 (setq interprogram-cut-function 'x-select-text
386 interprogram-paste-function 'x-cut-buffer-or-selection-value)
387 (let ((map (copy-keymap ns-alternatives-map)))
388 (set-keymap-parent map (keymap-parent local-function-key-map))
389 (set-keymap-parent local-function-key-map map))
390 (setq system-key-alist
391 (list
392 (cons (logior (lsh 0 16) 1) 'ns-power-off)
393 (cons (logior (lsh 0 16) 2) 'ns-open-file)
394 (cons (logior (lsh 0 16) 3) 'ns-open-temp-file)
395 (cons (logior (lsh 0 16) 4) 'ns-drag-file)
396 (cons (logior (lsh 0 16) 5) 'ns-drag-color)
397 (cons (logior (lsh 0 16) 6) 'ns-drag-text)
398 (cons (logior (lsh 0 16) 7) 'ns-change-font)
399 (cons (logior (lsh 0 16) 8) 'ns-open-file-line)
400 ; (cons (logior (lsh 0 16) 9) 'ns-insert-working-text)
401 ; (cons (logior (lsh 0 16) 10) 'ns-delete-working-text)
402 (cons (logior (lsh 0 16) 11) 'ns-spi-service-call)
403 (cons (logior (lsh 0 16) 12) 'ns-new-frame)
404 (cons (logior (lsh 0 16) 13) 'ns-toggle-toolbar)
405 (cons (logior (lsh 0 16) 14) 'ns-info-prefs)
406 (cons (logior (lsh 1 16) 32) 'f1)
407 (cons (logior (lsh 1 16) 33) 'f2)
408 (cons (logior (lsh 1 16) 34) 'f3)
409 (cons (logior (lsh 1 16) 35) 'f4)
410 (cons (logior (lsh 1 16) 36) 'f5)
411 (cons (logior (lsh 1 16) 37) 'f6)
412 (cons (logior (lsh 1 16) 38) 'f7)
413 (cons (logior (lsh 1 16) 39) 'f8)
414 (cons (logior (lsh 1 16) 40) 'f9)
415 (cons (logior (lsh 1 16) 41) 'f10)
416 (cons (logior (lsh 1 16) 42) 'f11)
417 (cons (logior (lsh 1 16) 43) 'f12)
418 (cons (logior (lsh 1 16) 44) 'kp-insert)
419 (cons (logior (lsh 1 16) 45) 'kp-delete)
420 (cons (logior (lsh 1 16) 46) 'kp-home)
421 (cons (logior (lsh 1 16) 47) 'kp-end)
422 (cons (logior (lsh 1 16) 48) 'kp-prior)
423 (cons (logior (lsh 1 16) 49) 'kp-next)
424 (cons (logior (lsh 1 16) 50) 'print-screen)
425 (cons (logior (lsh 1 16) 51) 'scroll-lock)
426 (cons (logior (lsh 1 16) 52) 'pause)
427 (cons (logior (lsh 1 16) 53) 'system)
428 (cons (logior (lsh 1 16) 54) 'break)
429 (cons (logior (lsh 1 16) 56) 'please-tell-carl-what-this-key-is-called-56)
430 (cons (logior (lsh 1 16) 61) 'please-tell-carl-what-this-key-is-called-61)
431 (cons (logior (lsh 1 16) 62) 'please-tell-carl-what-this-key-is-called-62)
432 (cons (logior (lsh 1 16) 63) 'please-tell-carl-what-this-key-is-called-63)
433 (cons (logior (lsh 1 16) 64) 'please-tell-carl-what-this-key-is-called-64)
434 (cons (logior (lsh 1 16) 69) 'please-tell-carl-what-this-key-is-called-69)
435 (cons (logior (lsh 1 16) 70) 'please-tell-carl-what-this-key-is-called-70)
436 (cons (logior (lsh 1 16) 71) 'please-tell-carl-what-this-key-is-called-71)
437 (cons (logior (lsh 1 16) 72) 'please-tell-carl-what-this-key-is-called-72)
438 (cons (logior (lsh 1 16) 73) 'please-tell-carl-what-this-key-is-called-73)
439 (cons (logior (lsh 2 16) 3) 'kp-enter)
440 (cons (logior (lsh 2 16) 9) 'kp-tab)
441 (cons (logior (lsh 2 16) 28) 'kp-quit)
442 (cons (logior (lsh 2 16) 35) 'kp-hash)
443 (cons (logior (lsh 2 16) 42) 'kp-multiply)
444 (cons (logior (lsh 2 16) 43) 'kp-add)
445 (cons (logior (lsh 2 16) 44) 'kp-separator)
446 (cons (logior (lsh 2 16) 45) 'kp-subtract)
447 (cons (logior (lsh 2 16) 46) 'kp-decimal)
448 (cons (logior (lsh 2 16) 47) 'kp-divide)
449 (cons (logior (lsh 2 16) 48) 'kp-0)
450 (cons (logior (lsh 2 16) 49) 'kp-1)
451 (cons (logior (lsh 2 16) 50) 'kp-2)
452 (cons (logior (lsh 2 16) 51) 'kp-3)
453 (cons (logior (lsh 2 16) 52) 'kp-4)
454 (cons (logior (lsh 2 16) 53) 'kp-5)
455 (cons (logior (lsh 2 16) 54) 'kp-6)
456 (cons (logior (lsh 2 16) 55) 'kp-7)
457 (cons (logior (lsh 2 16) 56) 'kp-8)
458 (cons (logior (lsh 2 16) 57) 'kp-9)
459 (cons (logior (lsh 2 16) 60) 'kp-less)
460 (cons (logior (lsh 2 16) 61) 'kp-equal)
461 (cons (logior (lsh 2 16) 62) 'kp-more)
462 (cons (logior (lsh 2 16) 64) 'kp-at)
463 (cons (logior (lsh 2 16) 92) 'kp-backslash)
464 (cons (logior (lsh 2 16) 96) 'kp-backtick)
465 (cons (logior (lsh 2 16) 124) 'kp-bar)
466 (cons (logior (lsh 2 16) 126) 'kp-tilde)
467 (cons (logior (lsh 2 16) 157) 'kp-mu)
468 (cons (logior (lsh 2 16) 165) 'kp-yen)
469 (cons (logior (lsh 2 16) 167) 'kp-paragraph)
470 (cons (logior (lsh 2 16) 172) 'left)
471 (cons (logior (lsh 2 16) 173) 'up)
472 (cons (logior (lsh 2 16) 174) 'right)
473 (cons (logior (lsh 2 16) 175) 'down)
474 (cons (logior (lsh 2 16) 176) 'kp-ring)
475 (cons (logior (lsh 2 16) 201) 'kp-square)
476 (cons (logior (lsh 2 16) 204) 'kp-cube)
477 (cons (logior (lsh 3 16) 8) 'backspace)
478 (cons (logior (lsh 3 16) 9) 'tab)
479 (cons (logior (lsh 3 16) 10) 'linefeed)
480 (cons (logior (lsh 3 16) 11) 'clear)
481 (cons (logior (lsh 3 16) 13) 'return)
482 (cons (logior (lsh 3 16) 18) 'pause)
483 (cons (logior (lsh 3 16) 25) 'S-tab)
484 (cons (logior (lsh 3 16) 27) 'escape)
485 (cons (logior (lsh 3 16) 127) 'delete)
486 )))
487 (set-terminal-parameter frame 'x-setup-function-keys t)))
488
489
490
491 ;; Must come after keybindings.
492
493 (fmakunbound 'clipboard-yank)
494 (fmakunbound 'clipboard-kill-ring-save)
495 (fmakunbound 'clipboard-kill-region)
496 (fmakunbound 'menu-bar-enable-clipboard)
497
498 ;; Add a couple of menus and rearrange some others; easiest just to redo toplvl
499 ;; Note keymap defns must be given last-to-first
500 (define-key global-map [menu-bar] (make-sparse-keymap "menu-bar"))
501
502 (setq menu-bar-final-items
503 (cond ((eq system-type 'darwin)
504 '(buffer windows services help-menu))
505 ;; Otherwise, GNUstep.
506 (t
507 '(buffer windows services hide-app quit))))
508
509 ;; Add standard top-level items to GNUstep menu.
510 (unless (eq system-type 'darwin)
511 (define-key global-map [menu-bar quit] '("Quit" . save-buffers-kill-emacs))
512 (define-key global-map [menu-bar hide-app] '("Hide" . ns-do-hide-emacs)))
513
514 (define-key global-map [menu-bar services]
515 (cons "Services" (make-sparse-keymap "Services")))
516 (define-key global-map [menu-bar windows] (make-sparse-keymap "Windows"))
517 (define-key global-map [menu-bar buffer]
518 (cons "Buffers" global-buffers-menu-map))
519 ;; (cons "Buffers" (make-sparse-keymap "Buffers")))
520 (define-key global-map [menu-bar tools] (cons "Tools" menu-bar-tools-menu))
521 (define-key global-map [menu-bar options] (cons "Options" menu-bar-options-menu))
522 (define-key global-map [menu-bar edit] (cons "Edit" menu-bar-edit-menu))
523 (define-key global-map [menu-bar file] (cons "File" menu-bar-file-menu))
524
525 ;; If running under GNUstep, rename "Help" to "Info"
526 (cond ((eq system-type 'darwin)
527 (define-key global-map [menu-bar help-menu]
528 (cons "Help" menu-bar-help-menu)))
529 (t
530 (let ((contents (reverse (cdr menu-bar-help-menu))))
531 (setq menu-bar-help-menu
532 (append (list 'keymap) (cdr contents) (list "Info"))))
533 (define-key global-map [menu-bar help-menu]
534 (cons "Info" menu-bar-help-menu))))
535
536 (if (not (eq system-type 'darwin))
537 ;; in OS X it's in the app menu already
538 (define-key menu-bar-help-menu [info-panel]
539 '("About Emacs..." . ns-do-emacs-info-panel)))
540
541
542 ;;;; File menu, replaces standard under ns-extended-platform-support
543 (defvar menu-bar-ns-file-menu (make-sparse-keymap "File"))
544 (define-key menu-bar-ns-file-menu [one-window]
545 '("Remove Splits" . delete-other-windows))
546 (define-key menu-bar-ns-file-menu [split-window]
547 '("Split Window" . split-window-vertically))
548
549 (define-key menu-bar-ns-file-menu [separator-print] '("--"))
550
551 (defvar ns-ps-print-menu-map (make-sparse-keymap "Postscript Print"))
552 (define-key ns-ps-print-menu-map [ps-print-region]
553 '("Region (B+W)" . ps-print-region))
554 (define-key ns-ps-print-menu-map [ps-print-buffer]
555 '("Buffer (B+W)" . ps-print-buffer))
556 (define-key ns-ps-print-menu-map [ps-print-region-faces]
557 '("Region" . ps-print-region-with-faces))
558 (define-key ns-ps-print-menu-map [ps-print-buffer-faces]
559 '("Buffer" . ps-print-buffer-with-faces))
560 (define-key menu-bar-ns-file-menu [postscript-print]
561 (cons "Postscript Print" ns-ps-print-menu-map))
562
563 (define-key menu-bar-ns-file-menu [print-region]
564 '("Print Region" . print-region))
565 (define-key menu-bar-ns-file-menu [print-buffer]
566 '("Print Buffer" . ns-print-buffer))
567
568 (define-key menu-bar-ns-file-menu [separator-save] '("--"))
569
570 (define-key menu-bar-ns-file-menu [recover-session]
571 '("Recover Crashed Session" . recover-session))
572 (define-key menu-bar-ns-file-menu [revert-buffer]
573 '("Revert Buffer" . revert-buffer))
574 (define-key menu-bar-ns-file-menu [write-file]
575 '("Save Buffer As..." . ns-write-file-using-panel))
576 (define-key menu-bar-ns-file-menu [save-buffer] '("Save Buffer" . save-buffer))
577
578 (define-key menu-bar-ns-file-menu [kill-buffer]
579 '("Kill Current Buffer" . kill-this-buffer))
580 (define-key menu-bar-ns-file-menu [delete-this-frame]
581 '("Close Frame" . delete-frame))
582
583 (define-key menu-bar-ns-file-menu [separator-open] '("--"))
584
585 (define-key menu-bar-ns-file-menu [insert-file]
586 '("Insert File..." . insert-file))
587 (define-key menu-bar-ns-file-menu [dired]
588 '("Open Directory..." . ns-open-file-using-panel))
589 (define-key menu-bar-ns-file-menu [open-file]
590 '("Open File..." . ns-open-file-using-panel))
591 (define-key menu-bar-ns-file-menu [make-frame]
592 '("New Frame" . make-frame))
593
594
595 ;;;; Edit menu: Modify slightly
596
597 ;; Substitute a Copy function that works better under X (for GNUstep).
598 (easy-menu-remove-item global-map '("menu-bar" "edit") 'copy)
599 (define-key-after menu-bar-edit-menu [copy]
600 '(menu-item "Copy" ns-copy-including-secondary
601 :enable mark-active
602 :help "Copy text in region between mark and current position")
603 'cut)
604
605 ;; Change to same precondition as select-and-paste, as we don't have
606 ;; `x-selection-exists-p'.
607 (easy-menu-remove-item global-map '("menu-bar" "edit") 'paste)
608 (define-key-after menu-bar-edit-menu [paste]
609 '(menu-item "Paste" yank
610 :enable (and (cdr yank-menu) (not buffer-read-only))
611 :help "Paste (yank) text most recently cut/copied")
612 'copy)
613
614 ;; Change text to be more consistent with surrounding menu items `paste', etc.
615 (easy-menu-remove-item global-map '("menu-bar" "edit") 'paste-from-menu)
616 (define-key-after menu-bar-edit-menu [select-paste]
617 '(menu-item "Select and Paste" yank-menu
618 :enable (and (cdr yank-menu) (not buffer-read-only))
619 :help "Choose a string from the kill ring and paste it")
620 'paste)
621
622 ;; Separate undo from cut/paste section, add spell for platform consistency.
623 (define-key-after menu-bar-edit-menu [separator-undo] '("--") 'undo)
624 (define-key-after menu-bar-edit-menu [spell] '("Spell" . ispell-menu-map) 'fill)
625
626 (defun menu-bar-update-frames ()
627 ;; If user discards the Windows item, play along.
628 (when (lookup-key (current-global-map) [menu-bar windows])
629 (let ((frames (frame-list))
630 (frames-menu (make-sparse-keymap "Select Frame")))
631 (setcdr frames-menu
632 (nconc
633 (mapcar (lambda (frame)
634 (list*
635 (frame-parameter frame 'window-id)
636 (frame-parameter frame 'name)
637 `(lambda ()
638 (interactive) (menu-bar-select-frame ,frame))))
639 frames)
640 (cdr frames-menu)))
641 (define-key frames-menu [separator-frames] '("--"))
642 (define-key frames-menu [popup-color-panel]
643 '("Colors..." . ns-popup-color-panel))
644 (define-key frames-menu [popup-font-panel]
645 '("Font Panel..." . ns-popup-font-panel))
646 (define-key frames-menu [separator-arrange] '("--"))
647 (define-key frames-menu [arrange-all-frames]
648 '("Arrange All Frames" . ns-arrange-all-frames))
649 (define-key frames-menu [arrange-visible-frames]
650 '("Arrange Visible Frames" . ns-arrange-visible-frames))
651 ;; Don't use delete-frame as event name
652 ;; because that is a special event.
653 (define-key (current-global-map) [menu-bar windows]
654 (cons "Windows" frames-menu)))))
655
656 (defun force-menu-bar-update-buffers ()
657 ;; This is a hack to get around fact that we already checked
658 ;; frame-or-buffer-changed-p and reset it, so menu-bar-update-buffers
659 ;; does not pick up any change.
660 (menu-bar-update-buffers t))
661
662 (add-hook 'menu-bar-update-fab-hook 'menu-bar-update-frames)
663 (add-hook 'menu-bar-update-fab-hook 'force-menu-bar-update-buffers)
664
665 (defun menu-bar-update-frames-and-buffers ()
666 (if (frame-or-buffer-changed-p)
667 (run-hooks 'menu-bar-update-fab-hook)))
668
669 (setq menu-bar-update-hook
670 (delq 'menu-bar-update-buffers menu-bar-update-hook))
671 (add-hook 'menu-bar-update-hook 'menu-bar-update-frames-and-buffers)
672
673 (menu-bar-update-frames-and-buffers)
674
675
676 ;; ns-arrange functions contributed
677 ;; by Eberhard Mandler <mandler@dbag.ulm.DaimlerBenz.COM>
678 (defun ns-arrange-all-frames ()
679 "Arranges all frames according to topline"
680 (interactive)
681 (ns-arrange-frames t))
682
683 (defun ns-arrange-visible-frames ()
684 "Arranges all visible frames according to topline"
685 (interactive)
686 (ns-arrange-frames nil))
687
688 (defun ns-arrange-frames (vis)
689 (let ((frame (next-frame))
690 (end-frame (selected-frame))
691 (inc-x 20) ;relative position of frames
692 (inc-y 22)
693 (x-pos 100) ;start position
694 (y-pos 40)
695 (done nil))
696 (while (not done) ;cycle through all frames
697 (if (not (or vis (eq (frame-visible-p frame) t)))
698 (setq x-pos x-pos); do nothing; true case
699 (set-frame-position frame x-pos y-pos)
700 (setq x-pos (+ x-pos inc-x))
701 (setq y-pos (+ y-pos inc-y))
702 (raise-frame frame))
703 (select-frame frame)
704 (setq frame (next-frame))
705 (setq done (equal frame end-frame)))
706 (set-frame-position end-frame x-pos y-pos)
707 (raise-frame frame)
708 (select-frame frame)))
709
710
711 ;;;; Services
712 (declare-function ns-perform-service "nsfns.m" (service send))
713
714 (defun ns-define-service (path)
715 (let ((mapping [menu-bar services])
716 (service (mapconcat 'identity path "/"))
717 (name (intern
718 (subst-char-in-string
719 ?\s ?-
720 (mapconcat 'identity (cons "ns-service" path) "-")))))
721 ;; This defines the function.
722 (defalias name
723 (lexical-let ((service service))
724 (lambda (arg)
725 (interactive "p")
726 (let* ((in-string
727 (cond ((stringp arg) arg)
728 (mark-active
729 (buffer-substring (region-beginning) (region-end)))))
730 (out-string (ns-perform-service service in-string)))
731 (cond
732 ((stringp arg) out-string)
733 ((and out-string (or (not in-string)
734 (not (string= in-string out-string))))
735 (if mark-active (delete-region (region-beginning) (region-end)))
736 (insert out-string)
737 (setq deactivate-mark nil)))))))
738 (cond
739 ((lookup-key global-map mapping)
740 (while (cdr path)
741 (setq mapping (vconcat mapping (list (intern (car path)))))
742 (if (not (keymapp (lookup-key global-map mapping)))
743 (define-key global-map mapping
744 (cons (car path) (make-sparse-keymap (car path)))))
745 (setq path (cdr path)))
746 (setq mapping (vconcat mapping (list (intern (car path)))))
747 (define-key global-map mapping (cons (car path) name))))
748 name))
749
750 ;; nsterm.m
751 (defvar ns-input-spi-name)
752 (defvar ns-input-spi-arg)
753
754 (declare-function dnd-open-file "dnd" (uri action))
755
756 (defun ns-spi-service-call ()
757 "Respond to a service request."
758 (interactive)
759 (cond ((string-equal ns-input-spi-name "open-selection")
760 (switch-to-buffer (generate-new-buffer "*untitled*"))
761 (insert ns-input-spi-arg))
762 ((string-equal ns-input-spi-name "open-file")
763 (dnd-open-file ns-input-spi-arg nil))
764 ((string-equal ns-input-spi-name "mail-selection")
765 (compose-mail)
766 (rfc822-goto-eoh)
767 (forward-line 1)
768 (insert ns-input-spi-arg))
769 ((string-equal ns-input-spi-name "mail-to")
770 (compose-mail ns-input-spi-arg))
771 (t (error (concat "Service " ns-input-spi-name " not recognized")))))
772
773
774 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
775
776
777
778 ;;;; Composed key sequence handling for Nextstep system input methods.
779 ;;;; (On Nextstep systems, input methods are provided for CJK
780 ;;;; characters, etc. which require multiple keystrokes, and during
781 ;;;; entry a partial ("working") result is typically shown in the
782 ;;;; editing window.)
783
784 (defface ns-working-text-face
785 '((t :underline t))
786 "Face used to highlight working text during compose sequence insert."
787 :group 'ns)
788
789 (defvar ns-working-overlay nil
790 "Overlay used to highlight working text during compose sequence insert.")
791 (make-variable-buffer-local 'ns-working-overlay)
792 (defvar ns-working-overlay-len 0
793 "Length of working text during compose sequence insert.")
794 (make-variable-buffer-local 'ns-working-overlay-len)
795
796 (defvar ns-working-text) ; nsterm.m
797
798 ;; Test if in echo area, based on mac-win.el 2007/08/26 unicode-2.
799 ;; This will fail if called from a NONASCII_KEYSTROKE event on the global map.
800 (defun ns-in-echo-area ()
801 "Whether, for purposes of inserting working composition text, the minibuffer
802 is currently being used."
803 (or isearch-mode
804 (and cursor-in-echo-area (current-message))
805 ;; Overlay strings are not shown in some cases.
806 (get-char-property (point) 'invisible)
807 (and (not (bobp))
808 (or (and (get-char-property (point) 'display)
809 (eq (get-char-property (1- (point)) 'display)
810 (get-char-property (point) 'display)))
811 (and (get-char-property (point) 'composition)
812 (eq (get-char-property (1- (point)) 'composition)
813 (get-char-property (point) 'composition)))))))
814
815 ;; The 'interactive' here stays for subinvocations, so the ns-in-echo-area
816 ;; always returns nil for some reason. If this WASN'T the case, we could
817 ;; map this to [ns-insert-working-text] and eliminate Fevals in nsterm.m.
818 ;; These functions test whether in echo area and delegate accordingly.
819 (defun ns-put-working-text ()
820 (interactive)
821 (if (ns-in-echo-area) (ns-echo-working-text) (ns-insert-working-text)))
822 (defun ns-unput-working-text ()
823 (interactive)
824 (if (ns-in-echo-area) (ns-unecho-working-text) (ns-delete-working-text)))
825
826 (defun ns-insert-working-text ()
827 "Insert contents of ns-working-text as UTF8 string and mark with
828 ns-working-overlay. Any previously existing working text is cleared first.
829 The overlay is assigned the face ns-working-text-face."
830 ;; FIXME: if buffer is read-only, don't try to insert anything
831 ;; and if text is bound to a command, execute that instead (Bug#1453)
832 (interactive)
833 (if ns-working-overlay (ns-delete-working-text))
834 (let ((start (point)))
835 (insert ns-working-text)
836 (overlay-put (setq ns-working-overlay (make-overlay start (point)
837 (current-buffer) nil t))
838 'face 'ns-working-text-face)
839 (setq ns-working-overlay-len (+ ns-working-overlay-len (- (point) start)))))
840
841 (defun ns-echo-working-text ()
842 "Echo contents of ns-working-text in message display area.
843 See ns-insert-working-text."
844 (if ns-working-overlay (ns-unecho-working-text))
845 (let* ((msg (current-message))
846 (msglen (length msg))
847 message-log-max)
848 (setq ns-working-overlay-len (length ns-working-text))
849 (setq msg (concat msg ns-working-text))
850 (put-text-property msglen (+ msglen ns-working-overlay-len)
851 'face 'ns-working-text-face msg)
852 (message "%s" msg)
853 (setq ns-working-overlay t)))
854
855 (defun ns-delete-working-text()
856 "Delete working text and clear ns-working-overlay."
857 (interactive)
858 (delete-backward-char ns-working-overlay-len)
859 (setq ns-working-overlay-len 0)
860 (delete-overlay ns-working-overlay))
861
862 (defun ns-unecho-working-text()
863 "Delete working text from echo area and clear ns-working-overlay."
864 (let ((msg (current-message))
865 message-log-max)
866 (setq msg (substring msg 0 (- (length msg) ns-working-overlay-len)))
867 (message "%s" msg)
868 (setq ns-working-overlay-len 0)
869 (setq ns-working-overlay nil)))
870
871
872 (declare-function ns-convert-utf8-nfd-to-nfc "nsfns.m" (str))
873
874 ;;;; OS X file system Unicode UTF-8 NFD (decomposed form) support
875 ;; Lisp code based on utf-8m.el, by Seiji Zenitani, Eiji Honjoh, and
876 ;; Carsten Bormann.
877 (if (eq system-type 'darwin)
878 (progn
879
880 (defun ns-utf8-nfd-post-read-conversion (length)
881 "Calls ns-convert-utf8-nfd-to-nfc to compose char sequences."
882 (save-excursion
883 (save-restriction
884 (narrow-to-region (point) (+ (point) length))
885 (let ((str (buffer-string)))
886 (delete-region (point-min) (point-max))
887 (insert (ns-convert-utf8-nfd-to-nfc str))
888 (- (point-max) (point-min))
889 ))))
890
891 (define-coding-system 'utf-8-nfd
892 "UTF-8 NFD (decomposed) encoding."
893 :coding-type 'utf-8
894 :mnemonic ?U
895 :charset-list '(unicode)
896 :post-read-conversion 'ns-utf8-nfd-post-read-conversion)
897 (set-file-name-coding-system 'utf-8-nfd)))
898
899 ;; PENDING: disable composition-based display for Indic scripts as it
900 ;; is not working well under Nextstep for some reason
901 (set-char-table-range composition-function-table
902 '(#x0900 . #x0DFF) nil)
903
904
905 ;;;; Inter-app communications support.
906
907 (defvar ns-input-text) ; nsterm.m
908
909 (defun ns-insert-text ()
910 "Insert contents of ns-input-text at point."
911 (interactive)
912 (insert ns-input-text)
913 (setq ns-input-text nil))
914
915 (defun ns-insert-file ()
916 "Insert contents of file ns-input-file like insert-file but with less
917 prompting. If file is a directory perform a find-file on it."
918 (interactive)
919 (let ((f))
920 (setq f (car ns-input-file))
921 (setq ns-input-file (cdr ns-input-file))
922 (if (file-directory-p f)
923 (find-file f)
924 (push-mark (+ (point) (car (cdr (insert-file-contents f))))))))
925
926 (defvar ns-select-overlay nil
927 "Overlay used to highlight areas in files requested by Nextstep apps.")
928 (make-variable-buffer-local 'ns-select-overlay)
929
930 (defvar ns-input-line) ; nsterm.m
931
932 (defun ns-open-file-select-line ()
933 "Open a buffer containing the file `ns-input-file'.
934 Lines are highlighted according to `ns-input-line'."
935 (interactive)
936 (ns-find-file)
937 (cond
938 ((and ns-input-line (buffer-modified-p))
939 (if ns-select-overlay
940 (setq ns-select-overlay (delete-overlay ns-select-overlay)))
941 (deactivate-mark)
942 (goto-line (if (consp ns-input-line)
943 (min (car ns-input-line) (cdr ns-input-line))
944 ns-input-line)))
945 (ns-input-line
946 (if (not ns-select-overlay)
947 (overlay-put (setq ns-select-overlay (make-overlay (point-min) (point-min)))
948 'face 'highlight))
949 (let ((beg (save-excursion
950 (goto-line (if (consp ns-input-line)
951 (min (car ns-input-line) (cdr ns-input-line))
952 ns-input-line))
953 (point)))
954 (end (save-excursion
955 (goto-line (+ 1 (if (consp ns-input-line)
956 (max (car ns-input-line) (cdr ns-input-line))
957 ns-input-line)))
958 (point))))
959 (move-overlay ns-select-overlay beg end)
960 (deactivate-mark)
961 (goto-char beg)))
962 (t
963 (if ns-select-overlay
964 (setq ns-select-overlay (delete-overlay ns-select-overlay))))))
965
966 (defun ns-unselect-line ()
967 "Removes any Nextstep highlight a buffer may contain."
968 (if ns-select-overlay
969 (setq ns-select-overlay (delete-overlay ns-select-overlay))))
970
971 (add-hook 'first-change-hook 'ns-unselect-line)
972
973
974
975 ;;;; Preferences handling.
976 (declare-function ns-get-resource "nsfns.m" (owner name))
977
978 (defun get-lisp-resource (arg1 arg2)
979 (let ((res (ns-get-resource arg1 arg2)))
980 (cond
981 ((not res) 'unbound)
982 ((string-equal (upcase res) "YES") t)
983 ((string-equal (upcase res) "NO") nil)
984 (t (read res)))))
985
986 ;; nsterm.m
987 (defvar ns-command-modifier)
988 (defvar ns-control-modifier)
989 (defvar ns-function-modifier)
990 (defvar ns-antialias-text)
991 (defvar ns-use-qd-smoothing)
992 (defvar ns-use-system-highlight-color)
993
994 (declare-function ns-set-resource "nsfns.m" (owner name value))
995 (declare-function ns-font-name "nsfns.m" (name))
996 (declare-function ns-read-file-name "nsfns.m"
997 (prompt &optional dir isLoad init))
998
999 (defun ns-save-preferences ()
1000 "Set all the defaults."
1001 (interactive)
1002 ;; Global preferences
1003 (ns-set-resource nil "AlternateModifier" (symbol-name ns-alternate-modifier))
1004 (ns-set-resource nil "CommandModifier" (symbol-name ns-command-modifier))
1005 (ns-set-resource nil "ControlModifier" (symbol-name ns-control-modifier))
1006 (ns-set-resource nil "FunctionModifier" (symbol-name ns-function-modifier))
1007 (ns-set-resource nil "ExpandSpace"
1008 (if ns-expand-space
1009 (number-to-string ns-expand-space)
1010 "NO"))
1011 (ns-set-resource nil "GSFontAntiAlias" (if ns-antialias-text "YES" "NO"))
1012 (ns-set-resource nil "UseQuickdrawSmoothing"
1013 (if ns-use-qd-smoothing "YES" "NO"))
1014 (ns-set-resource nil "UseSystemHighlightColor"
1015 (if ns-use-system-highlight-color "YES" "NO"))
1016 ;; Default frame parameters
1017 (let ((p (frame-parameters))
1018 v)
1019 (if (setq v (assq 'font p))
1020 (ns-set-resource nil "Font" (ns-font-name (cdr v))))
1021 (if (setq v (assq 'fontsize p))
1022 (ns-set-resource nil "FontSize" (number-to-string (cdr v))))
1023 (if (setq v (assq 'foreground-color p))
1024 (ns-set-resource nil "Foreground" (cdr v)))
1025 (if (setq v (assq 'background-color p))
1026 (ns-set-resource nil "Background" (cdr v)))
1027 (if (setq v (assq 'cursor-color p))
1028 (ns-set-resource nil "CursorColor" (cdr v)))
1029 (if (setq v (assq 'cursor-type p))
1030 (ns-set-resource nil "CursorType" (if (symbolp (cdr v))
1031 (symbol-name (cdr v))
1032 (cdr v))))
1033 (if (setq v (assq 'underline p))
1034 (ns-set-resource nil "Underline"
1035 (case (cdr v)
1036 ((t) "YES")
1037 ((nil) "NO")
1038 (t (cdr v)))))
1039 (if (setq v (assq 'internal-border-width p))
1040 (ns-set-resource nil "InternalBorderWidth"
1041 (number-to-string (cdr v))))
1042 (if (setq v (assq 'vertical-scroll-bars p))
1043 (ns-set-resource nil "VerticalScrollBars"
1044 (case (cdr v)
1045 ((t) "YES")
1046 ((nil) "NO")
1047 ((left) "left")
1048 ((right) "right")
1049 (t nil))))
1050 (if (setq v (assq 'height p))
1051 (ns-set-resource nil "Height" (number-to-string (cdr v))))
1052 (if (setq v (assq 'width p))
1053 (ns-set-resource nil "Width" (number-to-string (cdr v))))
1054 (if (setq v (assq 'top p))
1055 (ns-set-resource nil "Top" (number-to-string (cdr v))))
1056 (if (setq v (assq 'left p))
1057 (ns-set-resource nil "Left" (number-to-string (cdr v))))
1058 ;; These not fully supported
1059 (if (setq v (assq 'auto-raise p))
1060 (ns-set-resource nil "AutoRaise" (if (cdr v) "YES" "NO")))
1061 (if (setq v (assq 'auto-lower p))
1062 (ns-set-resource nil "AutoLower" (if (cdr v) "YES" "NO")))
1063 (if (setq v (assq 'menu-bar-lines p))
1064 (ns-set-resource nil "Menus" (if (cdr v) "YES" "NO")))
1065 )
1066 (let ((fl (face-list)))
1067 (while (consp fl)
1068 (or (eq 'default (car fl))
1069 ;; dont save Default* since it causes all created faces to
1070 ;; inherit its values. The properties of the default face
1071 ;; have already been saved from the frame-parameters anyway.
1072 (let* ((name (symbol-name (car fl)))
1073 (font (face-font (car fl)))
1074 ;; (fontsize (face-fontsize (car fl)))
1075 (foreground (face-foreground (car fl)))
1076 (background (face-background (car fl)))
1077 (underline (face-underline-p (car fl)))
1078 (italic (face-italic-p (car fl)))
1079 (bold (face-bold-p (car fl)))
1080 (stipple (face-stipple (car fl))))
1081 ;; (ns-set-resource nil (concat name ".attributeFont")
1082 ;; (if font font nil))
1083 ;; (ns-set-resource nil (concat name ".attributeFontSize")
1084 ;; (if fontsize (number-to-string fontsize) nil))
1085 (ns-set-resource nil (concat name ".attributeForeground")
1086 (if foreground foreground nil))
1087 (ns-set-resource nil (concat name ".attributeBackground")
1088 (if background background nil))
1089 (ns-set-resource nil (concat name ".attributeUnderline")
1090 (if underline "YES" nil))
1091 (ns-set-resource nil (concat name ".attributeItalic")
1092 (if italic "YES" nil))
1093 (ns-set-resource nil (concat name ".attributeBold")
1094 (if bold "YES" nil))
1095 (and stipple
1096 (or (stringp stipple)
1097 (setq stipple (prin1-to-string stipple))))
1098 (ns-set-resource nil (concat name ".attributeStipple")
1099 (if stipple stipple nil))))
1100 (setq fl (cdr fl)))))
1101
1102 (declare-function menu-bar-options-save-orig "ns-win" () t)
1103
1104 ;; call ns-save-preferences when menu-bar-options-save is called
1105 (fset 'menu-bar-options-save-orig (symbol-function 'menu-bar-options-save))
1106 (defun ns-save-options ()
1107 (interactive)
1108 (menu-bar-options-save-orig)
1109 (ns-save-preferences))
1110 (fset 'menu-bar-options-save (symbol-function 'ns-save-options))
1111
1112
1113 ;;;; File handling.
1114
1115 (defun ns-open-file-using-panel ()
1116 "Pop up open-file panel, and load the result in a buffer."
1117 (interactive)
1118 ;; Prompt dir defaultName isLoad initial.
1119 (setq ns-input-file (ns-read-file-name "Select File to Load" nil t nil))
1120 (if ns-input-file
1121 (and (setq ns-input-file (list ns-input-file)) (ns-find-file))))
1122
1123 (defun ns-write-file-using-panel ()
1124 "Pop up save-file panel, and save buffer in resulting name."
1125 (interactive)
1126 (let (ns-output-file)
1127 ;; Prompt dir defaultName isLoad initial.
1128 (setq ns-output-file (ns-read-file-name "Save As" nil nil nil))
1129 (message ns-output-file)
1130 (if ns-output-file (write-file ns-output-file))))
1131
1132 (defvar ns-pop-up-frames 'fresh
1133 "*Non-nil means open files upon request from the Workspace in a new frame.
1134 If t, always do so. Any other non-nil value means open a new frame
1135 unless the current buffer is a scratch buffer.")
1136
1137 (declare-function ns-hide-emacs "nsfns.m" (on))
1138
1139 (defun ns-find-file ()
1140 "Do a find-file with the ns-input-file as argument."
1141 (interactive)
1142 (let ((f) (file) (bufwin1) (bufwin2))
1143 (setq f (file-truename (car ns-input-file)))
1144 (setq ns-input-file (cdr ns-input-file))
1145 (setq file (find-file-noselect f))
1146 (setq bufwin1 (get-buffer-window file 'visible))
1147 (setq bufwin2 (get-buffer-window "*scratch*" 'visibile))
1148 (cond
1149 (bufwin1
1150 (select-frame (window-frame bufwin1))
1151 (raise-frame (window-frame bufwin1))
1152 (select-window bufwin1))
1153 ((and (eq ns-pop-up-frames 'fresh) bufwin2)
1154 (ns-hide-emacs 'activate)
1155 (select-frame (window-frame bufwin2))
1156 (raise-frame (window-frame bufwin2))
1157 (select-window bufwin2)
1158 (find-file f))
1159 (ns-pop-up-frames
1160 (ns-hide-emacs 'activate)
1161 (let ((pop-up-frames t)) (pop-to-buffer file nil)))
1162 (t
1163 (ns-hide-emacs 'activate)
1164 (find-file f)))))
1165
1166
1167
1168 ;;;; Frame-related functions.
1169
1170 ;; Don't show the frame name; that's redundant with Nextstep.
1171 (setq-default mode-line-frame-identification '(" "))
1172
1173 ;; You say tomAYto, I say tomAHto..
1174 (defvaralias 'ns-option-modifier 'ns-alternate-modifier)
1175
1176 (defun ns-do-hide-emacs ()
1177 (interactive)
1178 (ns-hide-emacs t))
1179
1180 (declare-function ns-hide-others "nsfns.m" ())
1181
1182 (defun ns-do-hide-others ()
1183 (interactive)
1184 (ns-hide-others))
1185
1186 (declare-function ns-emacs-info-panel "nsfns.m" ())
1187
1188 (defun ns-do-emacs-info-panel ()
1189 (interactive)
1190 (ns-emacs-info-panel))
1191
1192 (defun ns-next-frame ()
1193 "Switch to next visible frame."
1194 (interactive)
1195 (other-frame 1))
1196 (defun ns-prev-frame ()
1197 "Switch to previous visible frame."
1198 (interactive)
1199 (other-frame -1))
1200
1201 ;; If no position specified, make new frame offset by 25 from current.
1202 (defvar parameters) ; dynamically bound in make-frame
1203 (add-hook 'before-make-frame-hook
1204 (lambda ()
1205 (let ((left (cdr (assq 'left (frame-parameters))))
1206 (top (cdr (assq 'top (frame-parameters)))))
1207 (if (consp left) (setq left (cadr left)))
1208 (if (consp top) (setq top (cadr top)))
1209 (cond
1210 ((or (assq 'top parameters) (assq 'left parameters)))
1211 ((or (not left) (not top)))
1212 (t
1213 (setq parameters (cons (cons 'left (+ left 25))
1214 (cons (cons 'top (+ top 25))
1215 parameters))))))))
1216
1217 ;; frame will be focused anyway, so select it
1218 ;; (if this is not done, modeline is dimmed until first interaction)
1219 (add-hook 'after-make-frame-functions 'select-frame)
1220
1221 (defvar tool-bar-mode)
1222 (declare-function tool-bar-mode "tool-bar" (&optional arg))
1223
1224 ;; Based on a function by David Reitter <dreitter@inf.ed.ac.uk> ;
1225 ;; see http://lists.gnu.org/archive/html/emacs-devel/2005-09/msg00681.html .
1226 (defun ns-toggle-toolbar (&optional frame)
1227 "Switches the tool bar on and off in frame FRAME.
1228 If FRAME is nil, the change applies to the selected frame."
1229 (interactive)
1230 (modify-frame-parameters
1231 frame (list (cons 'tool-bar-lines
1232 (if (> (or (frame-parameter frame 'tool-bar-lines) 0) 0)
1233 0 1)) ))
1234 (if (not tool-bar-mode) (tool-bar-mode t)))
1235
1236
1237
1238 ;;;; Dialog-related functions.
1239
1240
1241 (defun ns-show-preferences-help ()
1242 "Show NS Preferences panel section in the Emacs manual"
1243 (interactive)
1244 (info "(emacs)Mac / GNUstep Customization"))
1245
1246 ;; Ask user for confirm before printing. Due to Kevin Rodgers.
1247 (defun ns-print-buffer ()
1248 "Interactive front-end to `print-buffer': asks for user confirmation first."
1249 (interactive)
1250 (if (and (interactive-p)
1251 (or (listp last-nonmenu-event)
1252 (and (char-or-string-p (event-basic-type last-command-event))
1253 (memq 'super (event-modifiers last-command-event)))))
1254 (let ((last-nonmenu-event (if (listp last-nonmenu-event)
1255 last-nonmenu-event
1256 ;; Fake it:
1257 `(mouse-1 POSITION 1))))
1258 (if (y-or-n-p (format "Print buffer %s? " (buffer-name)))
1259 (print-buffer)
1260 (error "Cancelled")))
1261 (print-buffer)))
1262
1263
1264 ;;;; Font support.
1265
1266 ;; Needed for font listing functions under both backend and normal
1267 (setq scalable-fonts-allowed t)
1268
1269 ;; Set to use font panel instead
1270 (declare-function ns-popup-font-panel "nsfns.m" (&optional frame))
1271 (defalias 'generate-fontset-menu 'ns-popup-font-panel)
1272 (defalias 'mouse-set-font 'ns-popup-font-panel)
1273
1274 ;; nsterm.m
1275 (defvar ns-input-font)
1276 (defvar ns-input-fontsize)
1277
1278 (defun ns-respond-to-change-font ()
1279 "Respond to changeFont: event, expecting ns-input-font and\n\
1280 ns-input-fontsize of new font."
1281 (interactive)
1282 (modify-frame-parameters (selected-frame)
1283 (list (cons 'font ns-input-font)
1284 (cons 'fontsize ns-input-fontsize)))
1285 (set-frame-font ns-input-font))
1286
1287
1288 ;; Default fontset for Mac OS X. This is mainly here to show how a fontset
1289 ;; can be set up manually. Ordinarily, fontsets are auto-created whenever
1290 ;; a font is chosen by
1291 (defvar ns-standard-fontset-spec
1292 ;; Only some code supports this so far, so use uglier XLFD version
1293 ;; "-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard,latin:Courier,han:Kai"
1294 (mapconcat 'identity
1295 '("-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard"
1296 "latin:-*-Courier-*-*-*-*-10-*-*-*-*-*-iso10646-1"
1297 "han:-*-Kai-*-*-*-*-10-*-*-*-*-*-iso10646-1"
1298 "cyrillic:-*-Trebuchet$MS-*-*-*-*-10-*-*-*-*-*-iso10646-1")
1299 ",")
1300 "String of fontset spec of the standard fontset.
1301 This defines a fontset consisting of the Courier and other fonts that
1302 come with OS X\".
1303 See the documentation of `create-fontset-from-fontset-spec for the format.")
1304
1305 ;; Conditional on new-fontset so bootstrapping works on non-GUI compiles.
1306 (if (fboundp 'new-fontset)
1307 (progn
1308 ;; Setup the default fontset.
1309 (setup-default-fontset)
1310 ;; Create the standard fontset.
1311 (create-fontset-from-fontset-spec ns-standard-fontset-spec t)))
1312
1313 ;;(push (cons 'font "-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard")
1314 ;; default-frame-alist)
1315
1316 ;; Add some additional scripts to var we use for fontset generation.
1317 (setq script-representative-chars
1318 (cons '(kana #xff8a)
1319 (cons '(symbol #x2295 #x2287 #x25a1)
1320 script-representative-chars)))
1321
1322
1323 ;;;; Pasteboard support.
1324
1325 (declare-function ns-get-cut-buffer-internal "nsselect.m" (buffer))
1326
1327 (defun ns-get-pasteboard ()
1328 "Returns the value of the pasteboard."
1329 (ns-get-cut-buffer-internal 'PRIMARY))
1330
1331 (declare-function ns-store-cut-buffer-internal "nsselect.m" (buffer string))
1332
1333 (defun ns-set-pasteboard (string)
1334 "Store STRING into the pasteboard of the Nextstep display server."
1335 ;; Check the data type of STRING.
1336 (if (not (stringp string)) (error "Nonstring given to pasteboard"))
1337 (ns-store-cut-buffer-internal 'PRIMARY string))
1338
1339 ;; We keep track of the last text selected here, so we can check the
1340 ;; current selection against it, and avoid passing back our own text
1341 ;; from x-cut-buffer-or-selection-value.
1342 (defvar ns-last-selected-text nil)
1343
1344 (defun x-select-text (text &optional push)
1345 "Put TEXT, a string, on the pasteboard."
1346 ;; Don't send the pasteboard too much text.
1347 ;; It becomes slow, and if really big it causes errors.
1348 (ns-set-pasteboard text)
1349 (setq ns-last-selected-text text))
1350
1351 ;; Return the value of the current Nextstep selection. For
1352 ;; compatibility with older Nextstep applications, this checks cut
1353 ;; buffer 0 before retrieving the value of the primary selection.
1354 (defun x-cut-buffer-or-selection-value ()
1355 (let (text)
1356
1357 ;; Consult the selection, then the cut buffer. Treat empty strings
1358 ;; as if they were unset.
1359 (or text (setq text (ns-get-pasteboard)))
1360 (if (string= text "") (setq text nil))
1361
1362 (cond
1363 ((not text) nil)
1364 ((eq text ns-last-selected-text) nil)
1365 ((string= text ns-last-selected-text)
1366 ;; Record the newer string, so subsequent calls can use the `eq' test.
1367 (setq ns-last-selected-text text)
1368 nil)
1369 (t
1370 (setq ns-last-selected-text text)))))
1371
1372 (defun ns-copy-including-secondary ()
1373 (interactive)
1374 (call-interactively 'kill-ring-save)
1375 (ns-store-cut-buffer-internal 'SECONDARY
1376 (buffer-substring (point) (mark t))))
1377 (defun ns-paste-secondary ()
1378 (interactive)
1379 (insert (ns-get-cut-buffer-internal 'SECONDARY)))
1380
1381 ;; PENDING: not sure what to do here.. for now interprog- are set in
1382 ;; init-fn-keys, and unsure whether these x- settings have an effect.
1383 ;;(setq interprogram-cut-function 'x-select-text
1384 ;; interprogram-paste-function 'x-cut-buffer-or-selection-value)
1385 ;; These only needed if above not working.
1386
1387 (set-face-background 'region "ns_selection_color")
1388
1389
1390
1391 ;;;; Scrollbar handling.
1392
1393 (global-set-key [vertical-scroll-bar down-mouse-1] 'ns-handle-scroll-bar-event)
1394 (global-unset-key [vertical-scroll-bar mouse-1])
1395 (global-unset-key [vertical-scroll-bar drag-mouse-1])
1396
1397 (declare-function scroll-bar-scale "scroll-bar" (num-denom whole))
1398
1399 (defun ns-scroll-bar-move (event)
1400 "Scroll the frame according to a Nextstep scroller event."
1401 (interactive "e")
1402 (let* ((pos (event-end event))
1403 (window (nth 0 pos))
1404 (scale (nth 2 pos)))
1405 (save-excursion
1406 (set-buffer (window-buffer window))
1407 (cond
1408 ((eq (car scale) (cdr scale))
1409 (goto-char (point-max)))
1410 ((= (car scale) 0)
1411 (goto-char (point-min)))
1412 (t
1413 (goto-char (+ (point-min) 1
1414 (scroll-bar-scale scale (- (point-max) (point-min)))))))
1415 (beginning-of-line)
1416 (set-window-start window (point))
1417 (vertical-motion (/ (window-height window) 2) window))))
1418
1419 (defun ns-handle-scroll-bar-event (event)
1420 "Handle scroll bar EVENT to emulate Nextstep style scrolling."
1421 (interactive "e")
1422 (let* ((position (event-start event))
1423 (bar-part (nth 4 position))
1424 (window (nth 0 position))
1425 (old-window (selected-window)))
1426 (cond
1427 ((eq bar-part 'ratio)
1428 (ns-scroll-bar-move event))
1429 ((eq bar-part 'handle)
1430 (if (eq window (selected-window))
1431 (track-mouse (ns-scroll-bar-move event))
1432 ;; track-mouse faster for selected window, slower for unselected.
1433 (ns-scroll-bar-move event)))
1434 (t
1435 (select-window window)
1436 (cond
1437 ((eq bar-part 'up)
1438 (goto-char (window-start window))
1439 (scroll-down 1))
1440 ((eq bar-part 'above-handle)
1441 (scroll-down))
1442 ((eq bar-part 'below-handle)
1443 (scroll-up))
1444 ((eq bar-part 'down)
1445 (goto-char (window-start window))
1446 (scroll-up 1)))
1447 (select-window old-window)))))
1448
1449
1450 ;;;; Color support.
1451
1452 (declare-function ns-list-colors "nsfns.m" (&optional frame))
1453
1454 (defvar x-colors (ns-list-colors)
1455 "The list of colors defined in non-PANTONE color files.")
1456
1457 (defun xw-defined-colors (&optional frame)
1458 "Return a list of colors supported for a particular frame.
1459 The argument FRAME specifies which frame to try.
1460 The value may be different for frames on different Nextstep displays."
1461 (or frame (setq frame (selected-frame)))
1462 (let ((all-colors x-colors)
1463 (this-color nil)
1464 (defined-colors nil))
1465 (while all-colors
1466 (setq this-color (car all-colors)
1467 all-colors (cdr all-colors))
1468 ;; (and (face-color-supported-p frame this-color t)
1469 (setq defined-colors (cons this-color defined-colors))) ;;)
1470 defined-colors))
1471
1472 (declare-function ns-set-alpha "nsfns.m" (color alpha))
1473
1474 ;; Convenience and work-around for fact that set color fns now require named.
1475 (defun ns-set-background-alpha (alpha)
1476 "Sets alpha (opacity) of background.
1477 Set from 0.0 (fully transparent) to 1.0 (fully opaque; default).
1478 Note, tranparency works better on Tiger (10.4) and higher."
1479 (interactive "nSet background alpha to: ")
1480 (let ((bgcolor (cdr (assq 'background-color (frame-parameters)))))
1481 (set-frame-parameter (selected-frame)
1482 'background-color (ns-set-alpha bgcolor alpha))))
1483
1484 ;; Functions for color panel + drag
1485 (defun ns-face-at-pos (pos)
1486 (let* ((frame (car pos))
1487 (frame-pos (cons (cadr pos) (cddr pos)))
1488 (window (window-at (car frame-pos) (cdr frame-pos) frame))
1489 (window-pos (coordinates-in-window-p frame-pos window))
1490 (buffer (window-buffer window))
1491 (edges (window-edges window)))
1492 (cond
1493 ((not window-pos)
1494 nil)
1495 ((eq window-pos 'mode-line)
1496 'modeline)
1497 ((eq window-pos 'vertical-line)
1498 'default)
1499 ((consp window-pos)
1500 (save-excursion
1501 (set-buffer buffer)
1502 (let ((p (car (compute-motion (window-start window)
1503 (cons (nth 0 edges) (nth 1 edges))
1504 (window-end window)
1505 frame-pos
1506 (- (window-width window) 1)
1507 nil
1508 window))))
1509 (cond
1510 ((eq p (window-point window))
1511 'cursor)
1512 ((and mark-active (< (region-beginning) p) (< p (region-end)))
1513 'region)
1514 (t
1515 (let ((faces (get-char-property p 'face window)))
1516 (if (consp faces) (car faces) faces)))))))
1517 (t
1518 nil))))
1519
1520 (defvar ns-input-color) ; nsterm.m
1521
1522 (defun ns-set-foreground-at-mouse ()
1523 "Set the foreground color at the mouse location to ns-input-color."
1524 (interactive)
1525 (let* ((pos (mouse-position))
1526 (frame (car pos))
1527 (face (ns-face-at-pos pos)))
1528 (cond
1529 ((eq face 'cursor)
1530 (modify-frame-parameters frame (list (cons 'cursor-color
1531 ns-input-color))))
1532 ((not face)
1533 (modify-frame-parameters frame (list (cons 'foreground-color
1534 ns-input-color))))
1535 (t
1536 (set-face-foreground face ns-input-color frame)))))
1537
1538 (defun ns-set-background-at-mouse ()
1539 "Set the background color at the mouse location to ns-input-color."
1540 (interactive)
1541 (let* ((pos (mouse-position))
1542 (frame (car pos))
1543 (face (ns-face-at-pos pos)))
1544 (cond
1545 ((eq face 'cursor)
1546 (modify-frame-parameters frame (list (cons 'cursor-color
1547 ns-input-color))))
1548 ((not face)
1549 (modify-frame-parameters frame (list (cons 'background-color
1550 ns-input-color))))
1551 (t
1552 (set-face-background face ns-input-color frame)))))
1553
1554 ;; Set some options to be as Nextstep-like as possible.
1555 (setq frame-title-format t
1556 icon-title-format t)
1557
1558
1559 (defvar ns-initialized nil
1560 "Non-nil if Nextstep windowing has been initialized.")
1561
1562 (declare-function ns-list-services "nsfns.m" ())
1563 (declare-function x-open-connection "nsfns.m"
1564 (display &optional xrm-string must-succeed))
1565
1566 ;; Do the actual Nextstep Windows setup here; the above code just
1567 ;; defines functions and variables that we use now.
1568 (defun ns-initialize-window-system ()
1569 "Initialize Emacs for Nextstep (Cocoa / GNUstep) windowing."
1570
1571 ;; PENDING: not needed?
1572 (setq command-line-args (ns-handle-args command-line-args))
1573
1574 (x-open-connection (system-name) nil t)
1575
1576 (dolist (service (ns-list-services))
1577 (if (eq (car service) 'undefined)
1578 (ns-define-service (cdr service))
1579 (define-key global-map (vector (car service))
1580 (ns-define-service (cdr service)))))
1581
1582 (if (and (eq (get-lisp-resource nil "NXAutoLaunch") t)
1583 (eq (get-lisp-resource nil "HideOnAutoLaunch") t))
1584 (add-hook 'after-init-hook 'ns-do-hide-emacs))
1585
1586 ;; FIXME: This will surely lead to "MODIFIED OUTSIDE CUSTOM" warnings.
1587 (menu-bar-mode (if (get-lisp-resource nil "Menus") 1 -1))
1588 (mouse-wheel-mode 1)
1589
1590 (setq ns-initialized t))
1591
1592 (add-to-list 'handle-args-function-alist '(ns . ns-handle-args))
1593 (add-to-list 'frame-creation-function-alist '(ns . x-create-frame-with-faces))
1594 (add-to-list 'window-system-initialization-alist '(ns . ns-initialize-window-system))
1595
1596
1597 (provide 'ns-win)
1598
1599 ;; arch-tag: eb138a45-4e2e-4d68-b1c9-a39665731644
1600 ;;; ns-win.el ends here