ns-win: set ApplePressAndHoldEnabled to NO as it is unsupported.
[bpt/emacs.git] / lisp / term / ns-win.el
CommitLineData
c0642f6d
GM
1;;; ns-win.el --- lisp side of interface with NeXT/Open/GNUstep/MacOS X window system
2
95df8112 3;; Copyright (C) 1993-1994, 2005-2011 Free Software Foundation, Inc.
c0642f6d 4
c5220417
GM
5;; Authors: Carl Edman
6;; Christian Limpach
7;; Scott Bender
8;; Christophe de Dinechin
9;; Adrian Robert
c0642f6d
GM
10;; Keywords: terminals
11
12;; This file is part of GNU Emacs.
13
14;; GNU Emacs is free software: you can redistribute it and/or modify
15;; it under the terms of the GNU General Public License as published by
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
edfda783
AR
26
27;;; Commentary:
28
a5a1b464
CY
29;; ns-win.el: this file is loaded from ../lisp/startup.el when it
30;; recognizes that Nextstep windows are to be used. Command line
31;; switches are parsed and those pertaining to Nextstep are processed
32;; and removed from the command line. The Nextstep display is opened
33;; and hooks are set for popping up the initial window.
edfda783
AR
34
35;; startup.el will then examine startup files, and eventually call the hooks
36;; which create the first window (s).
37
a5a1b464
CY
38;; A number of other Nextstep convenience functions are defined in
39;; this file, which works in close coordination with src/nsfns.m.
edfda783
AR
40
41;;; Code:
42
725513b7 43(or (featurep 'ns)
3dcdb6ea 44 (error "%s: Loading ns-win.el but not compiled for GNUstep/MacOS"
725513b7 45 (invocation-name)))
ebe68042 46
e925113b
GM
47(eval-when-compile (require 'cl)) ; lexical-let
48
1bcc4637 49;; Documentation-purposes only: actually loaded in loadup.el.
edfda783
AR
50(require 'frame)
51(require 'mouse)
52(require 'faces)
edfda783
AR
53(require 'menu-bar)
54(require 'fontset)
55
20bc68dd
GM
56(defgroup ns nil
57 "GNUstep/Mac OS X specific features."
58 :group 'environment)
59
edfda783
AR
60;;;; Command line argument handling.
61
d7d8c62a
GM
62(defvar x-invocation-args)
63(defvar ns-command-line-resources nil) ; FIXME unused?
d377ef4a 64
c0642f6d
GM
65;; nsterm.m.
66(defvar ns-input-file)
67
1bcc4637
GM
68(defun ns-handle-nxopen (switch &optional temp)
69 (setq unread-command-events (append unread-command-events
70 (if temp '(ns-open-temp-file)
71 '(ns-open-file)))
d7d8c62a 72 ns-input-file (append ns-input-file (list (pop x-invocation-args)))))
edfda783
AR
73
74(defun ns-handle-nxopentemp (switch)
1bcc4637 75 (ns-handle-nxopen switch t))
edfda783 76
edfda783 77(defun ns-ignore-1-arg (switch)
d7d8c62a 78 (setq x-invocation-args (cdr x-invocation-args)))
edfda783 79
489382c5 80(defun ns-parse-geometry (geom)
ba0c843d 81 "Parse a Nextstep-style geometry string GEOM.
edfda783
AR
82Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
83The properties returned may include `top', `left', `height', and `width'."
a5a1b464
CY
84 (when (string-match "\\([0-9]+\\)\\( \\([0-9]+\\)\\( \\([0-9]+\\)\
85\\( \\([0-9]+\\) ?\\)?\\)?\\)?"
86 geom)
87 (apply
88 'append
89 (list
90 (list (cons 'top (string-to-number (match-string 1 geom))))
91 (if (match-string 3 geom)
92 (list (cons 'left (string-to-number (match-string 3 geom)))))
93 (if (match-string 5 geom)
94 (list (cons 'height (string-to-number (match-string 5 geom)))))
95 (if (match-string 7 geom)
96 (list (cons 'width (string-to-number (match-string 7 geom)))))))))
edfda783
AR
97
98;;;; Keyboard mapping.
99
725513b7 100(define-obsolete-variable-alias 'ns-alternatives-map 'x-alternatives-map "24.1")
edfda783 101
a5a1b464 102;; Here are some Nextstep-like bindings for command key sequences.
4c785fa7 103(define-key global-map [?\s-,] 'customize)
edfda783
AR
104(define-key global-map [?\s-'] 'next-multiframe-window)
105(define-key global-map [?\s-`] 'other-frame)
79cb9c05 106(define-key global-map [?\s-~] 'ns-prev-frame)
edfda783
AR
107(define-key global-map [?\s--] 'center-line)
108(define-key global-map [?\s-:] 'ispell)
109(define-key global-map [?\s-\;] 'ispell-next)
110(define-key global-map [?\s-?] 'info)
111(define-key global-map [?\s-^] 'kill-some-buffers)
112(define-key global-map [?\s-&] 'kill-this-buffer)
113(define-key global-map [?\s-C] 'ns-popup-color-panel)
114(define-key global-map [?\s-D] 'dired)
115(define-key global-map [?\s-E] 'edit-abbrevs)
116(define-key global-map [?\s-L] 'shell-command)
117(define-key global-map [?\s-M] 'manual-entry)
118(define-key global-map [?\s-S] 'ns-write-file-using-panel)
119(define-key global-map [?\s-a] 'mark-whole-buffer)
120(define-key global-map [?\s-c] 'ns-copy-including-secondary)
121(define-key global-map [?\s-d] 'isearch-repeat-backward)
122(define-key global-map [?\s-e] 'isearch-yank-kill)
123(define-key global-map [?\s-f] 'isearch-forward)
124(define-key global-map [?\s-g] 'isearch-repeat-forward)
125(define-key global-map [?\s-h] 'ns-do-hide-emacs)
126(define-key global-map [?\s-H] 'ns-do-hide-others)
127(define-key global-map [?\s-j] 'exchange-point-and-mark)
128(define-key global-map [?\s-k] 'kill-this-buffer)
129(define-key global-map [?\s-l] 'goto-line)
130(define-key global-map [?\s-m] 'iconify-frame)
131(define-key global-map [?\s-n] 'make-frame)
132(define-key global-map [?\s-o] 'ns-open-file-using-panel)
133(define-key global-map [?\s-p] 'ns-print-buffer)
134(define-key global-map [?\s-q] 'save-buffers-kill-emacs)
135(define-key global-map [?\s-s] 'save-buffer)
136(define-key global-map [?\s-t] 'ns-popup-font-panel)
137(define-key global-map [?\s-u] 'revert-buffer)
138(define-key global-map [?\s-v] 'yank)
139(define-key global-map [?\s-w] 'delete-frame)
140(define-key global-map [?\s-x] 'kill-region)
141(define-key global-map [?\s-y] 'ns-paste-secondary)
142(define-key global-map [?\s-z] 'undo)
143(define-key global-map [?\s-|] 'shell-command-on-region)
144(define-key global-map [s-kp-bar] 'shell-command-on-region)
ebe68042 145;; (as in Terminal.app)
edfda783
AR
146(define-key global-map [s-right] 'ns-next-frame)
147(define-key global-map [s-left] 'ns-prev-frame)
148
149(define-key global-map [home] 'beginning-of-buffer)
150(define-key global-map [end] 'end-of-buffer)
151(define-key global-map [kp-home] 'beginning-of-buffer)
152(define-key global-map [kp-end] 'end-of-buffer)
153(define-key global-map [kp-prior] 'scroll-down)
154(define-key global-map [kp-next] 'scroll-up)
155
1bcc4637 156;; Allow shift-clicks to work similarly to under Nextstep.
55e8d9a5
AR
157(define-key global-map [S-mouse-1] 'mouse-save-then-kill)
158(global-unset-key [S-down-mouse-1])
159
a5a1b464 160;; Special Nextstep-generated events are converted to function keys. Here
fc3eda04
AR
161;; are the bindings for them. Note, these keys are actually declared in
162;; x-setup-function-keys in common-win.
c6c62e78 163(define-key global-map [ns-power-off] 'save-buffers-kill-emacs)
edfda783
AR
164(define-key global-map [ns-open-file] 'ns-find-file)
165(define-key global-map [ns-open-temp-file] [ns-open-file])
166(define-key global-map [ns-drag-file] 'ns-insert-file)
167(define-key global-map [ns-drag-color] 'ns-set-foreground-at-mouse)
168(define-key global-map [S-ns-drag-color] 'ns-set-background-at-mouse)
169(define-key global-map [ns-drag-text] 'ns-insert-text)
170(define-key global-map [ns-change-font] 'ns-respond-to-change-font)
171(define-key global-map [ns-open-file-line] 'ns-open-file-select-line)
edfda783 172(define-key global-map [ns-spi-service-call] 'ns-spi-service-call)
3e972d98 173(define-key global-map [ns-new-frame] 'make-frame)
33b35792 174(define-key global-map [ns-toggle-toolbar] 'ns-toggle-toolbar)
3e972d98 175(define-key global-map [ns-show-prefs] 'customize)
edfda783
AR
176
177
2f93961f
CY
178;; Set up a number of aliases and other layers to pretend we're using
179;; the Choi/Mitsuharu Carbon port.
180
181(defvaralias 'mac-allow-anti-aliasing 'ns-antialias-text)
182(defvaralias 'mac-command-modifier 'ns-command-modifier)
b7d1e144 183(defvaralias 'mac-right-command-modifier 'ns-right-command-modifier)
2f93961f 184(defvaralias 'mac-control-modifier 'ns-control-modifier)
b7d1e144 185(defvaralias 'mac-right-control-modifier 'ns-right-control-modifier)
2f93961f 186(defvaralias 'mac-option-modifier 'ns-option-modifier)
a2e35ef5 187(defvaralias 'mac-right-option-modifier 'ns-right-option-modifier)
2f93961f 188(defvaralias 'mac-function-modifier 'ns-function-modifier)
406aaa6f 189(declare-function ns-do-applescript "nsfns.m" (script))
583ff3c3
AR
190(defalias 'do-applescript 'ns-do-applescript)
191
edfda783 192;;;; Services
d377ef4a
GM
193(declare-function ns-perform-service "nsfns.m" (service send))
194
edfda783
AR
195(defun ns-define-service (path)
196 (let ((mapping [menu-bar services])
197 (service (mapconcat 'identity path "/"))
198 (name (intern
ebe68042
SM
199 (subst-char-in-string
200 ?\s ?-
201 (mapconcat 'identity (cons "ns-service" path) "-")))))
202 ;; This defines the function.
203 (defalias name
204 (lexical-let ((service service))
205 (lambda (arg)
206 (interactive "p")
207 (let* ((in-string
208 (cond ((stringp arg) arg)
209 (mark-active
210 (buffer-substring (region-beginning) (region-end)))))
211 (out-string (ns-perform-service service in-string)))
212 (cond
213 ((stringp arg) out-string)
214 ((and out-string (or (not in-string)
215 (not (string= in-string out-string))))
216 (if mark-active (delete-region (region-beginning) (region-end)))
217 (insert out-string)
218 (setq deactivate-mark nil)))))))
edfda783
AR
219 (cond
220 ((lookup-key global-map mapping)
221 (while (cdr path)
222 (setq mapping (vconcat mapping (list (intern (car path)))))
223 (if (not (keymapp (lookup-key global-map mapping)))
224 (define-key global-map mapping
225 (cons (car path) (make-sparse-keymap (car path)))))
226 (setq path (cdr path)))
227 (setq mapping (vconcat mapping (list (intern (car path)))))
228 (define-key global-map mapping (cons (car path) name))))
229 name))
230
c0642f6d
GM
231;; nsterm.m
232(defvar ns-input-spi-name)
233(defvar ns-input-spi-arg)
234
f2d9c15f
GM
235(declare-function dnd-open-file "dnd" (uri action))
236
edfda783 237(defun ns-spi-service-call ()
82a330df 238 "Respond to a service request."
edfda783
AR
239 (interactive)
240 (cond ((string-equal ns-input-spi-name "open-selection")
241 (switch-to-buffer (generate-new-buffer "*untitled*"))
242 (insert ns-input-spi-arg))
243 ((string-equal ns-input-spi-name "open-file")
244 (dnd-open-file ns-input-spi-arg nil))
245 ((string-equal ns-input-spi-name "mail-selection")
246 (compose-mail)
247 (rfc822-goto-eoh)
248 (forward-line 1)
249 (insert ns-input-spi-arg))
250 ((string-equal ns-input-spi-name "mail-to")
251 (compose-mail ns-input-spi-arg))
252 (t (error (concat "Service " ns-input-spi-name " not recognized")))))
253
254
43c660bc
SM
255;; Composed key sequence handling for Nextstep system input methods.
256;; (On Nextstep systems, input methods are provided for CJK
257;; characters, etc. which require multiple keystrokes, and during
258;; entry a partial ("working") result is typically shown in the
259;; editing window.)
edfda783
AR
260
261(defface ns-working-text-face
262 '((t :underline t))
263 "Face used to highlight working text during compose sequence insert."
264 :group 'ns)
265
266(defvar ns-working-overlay nil
43c660bc
SM
267 "Overlay used to highlight working text during compose sequence insert.
268When text is in th echo area, this just stores the length of the working text.")
edfda783 269
33b35792
AR
270(defvar ns-working-text) ; nsterm.m
271
272;; Test if in echo area, based on mac-win.el 2007/08/26 unicode-2.
273;; This will fail if called from a NONASCII_KEYSTROKE event on the global map.
edfda783
AR
274(defun ns-in-echo-area ()
275 "Whether, for purposes of inserting working composition text, the minibuffer
276is currently being used."
277 (or isearch-mode
278 (and cursor-in-echo-area (current-message))
279 ;; Overlay strings are not shown in some cases.
280 (get-char-property (point) 'invisible)
281 (and (not (bobp))
282 (or (and (get-char-property (point) 'display)
283 (eq (get-char-property (1- (point)) 'display)
284 (get-char-property (point) 'display)))
285 (and (get-char-property (point) 'composition)
286 (eq (get-char-property (1- (point)) 'composition)
287 (get-char-property (point) 'composition)))))))
288
9d8f6d31
AR
289;; The 'interactive' here stays for subinvocations, so the ns-in-echo-area
290;; always returns nil for some reason. If this WASN'T the case, we could
291;; map this to [ns-insert-working-text] and eliminate Fevals in nsterm.m.
33b35792 292;; These functions test whether in echo area and delegate accordingly.
9d8f6d31 293(defun ns-put-working-text ()
edfda783 294 (interactive)
9d8f6d31 295 (if (ns-in-echo-area) (ns-echo-working-text) (ns-insert-working-text)))
33b35792
AR
296(defun ns-unput-working-text ()
297 (interactive)
43c660bc 298 (ns-delete-working-text))
c0642f6d 299
9d8f6d31 300(defun ns-insert-working-text ()
2b4e72e1 301 "Insert contents of `ns-working-text' as UTF-8 string and mark with
43c660bc
SM
302`ns-working-overlay'. Any previously existing working text is cleared first.
303The overlay is assigned the face `ns-working-text-face'."
304 ;; FIXME: if buffer is read-only, don't try to insert anything
305 ;; and if text is bound to a command, execute that instead (Bug#1453)
edfda783 306 (interactive)
43c660bc 307 (ns-delete-working-text)
edfda783
AR
308 (let ((start (point)))
309 (insert ns-working-text)
310 (overlay-put (setq ns-working-overlay (make-overlay start (point)
311 (current-buffer) nil t))
43c660bc 312 'face 'ns-working-text-face)))
edfda783
AR
313
314(defun ns-echo-working-text ()
2b4e72e1 315 "Echo contents of `ns-working-text' in message display area.
43c660bc
SM
316See `ns-insert-working-text'."
317 (ns-delete-working-text)
edfda783
AR
318 (let* ((msg (current-message))
319 (msglen (length msg))
320 message-log-max)
43c660bc 321 (setq ns-working-overlay (length ns-working-text))
edfda783 322 (setq msg (concat msg ns-working-text))
43c660bc 323 (put-text-property msglen (+ msglen ns-working-overlay)
08324aaa 324 'face 'ns-working-text-face msg)
43c660bc 325 (message "%s" msg)))
edfda783
AR
326
327(defun ns-delete-working-text()
43c660bc 328 "Delete working text and clear `ns-working-overlay'."
edfda783 329 (interactive)
43c660bc
SM
330 (cond
331 ((and (overlayp ns-working-overlay)
332 ;; Still alive?
333 (overlay-buffer ns-working-overlay))
334 (with-current-buffer (overlay-buffer ns-working-overlay)
335 (delete-region (overlay-start ns-working-overlay)
336 (overlay-end ns-working-overlay))
337 (delete-overlay ns-working-overlay)))
338 ((integerp ns-working-overlay)
339 (let ((msg (current-message))
340 message-log-max)
341 (setq msg (substring msg 0 (- (length msg) ns-working-overlay)))
342 (message "%s" msg))))
343 (setq ns-working-overlay nil))
edfda783
AR
344
345
c0642f6d
GM
346(declare-function ns-convert-utf8-nfd-to-nfc "nsfns.m" (str))
347
edfda783
AR
348;;;; OS X file system Unicode UTF-8 NFD (decomposed form) support
349;; Lisp code based on utf-8m.el, by Seiji Zenitani, Eiji Honjoh, and
350;; Carsten Bormann.
e925113b
GM
351(when (eq system-type 'darwin)
352 (defun ns-utf8-nfd-post-read-conversion (length)
353 "Calls `ns-convert-utf8-nfd-to-nfc' to compose char sequences."
354 (save-excursion
355 (save-restriction
356 (narrow-to-region (point) (+ (point) length))
357 (let ((str (buffer-string)))
358 (delete-region (point-min) (point-max))
359 (insert (ns-convert-utf8-nfd-to-nfc str))
1bcc4637 360 (- (point-max) (point-min))))))
e925113b
GM
361
362 (define-coding-system 'utf-8-nfd
363 "UTF-8 NFD (decomposed) encoding."
364 :coding-type 'utf-8
365 :mnemonic ?U
366 :charset-list '(unicode)
367 :post-read-conversion 'ns-utf8-nfd-post-read-conversion)
368 (set-file-name-coding-system 'utf-8-nfd))
edfda783
AR
369
370;;;; Inter-app communications support.
371
c0642f6d
GM
372(defvar ns-input-text) ; nsterm.m
373
edfda783 374(defun ns-insert-text ()
2b4e72e1 375 "Insert contents of `ns-input-text' at point."
edfda783
AR
376 (interactive)
377 (insert ns-input-text)
378 (setq ns-input-text nil))
c0642f6d 379
edfda783 380(defun ns-insert-file ()
2b4e72e1
JB
381 "Insert contents of file `ns-input-file' like insert-file but with less
382prompting. If file is a directory perform a `find-file' on it."
edfda783 383 (interactive)
c6efd3dd 384 (let ((f (pop ns-input-file)))
edfda783
AR
385 (if (file-directory-p f)
386 (find-file f)
1bcc4637 387 (push-mark (+ (point) (cadr (insert-file-contents f)))))))
edfda783
AR
388
389(defvar ns-select-overlay nil
a5a1b464 390 "Overlay used to highlight areas in files requested by Nextstep apps.")
edfda783
AR
391(make-variable-buffer-local 'ns-select-overlay)
392
c0642f6d
GM
393(defvar ns-input-line) ; nsterm.m
394
edfda783 395(defun ns-open-file-select-line ()
b90cc058
CY
396 "Open a buffer containing the file `ns-input-file'.
397Lines are highlighted according to `ns-input-line'."
edfda783
AR
398 (interactive)
399 (ns-find-file)
400 (cond
401 ((and ns-input-line (buffer-modified-p))
402 (if ns-select-overlay
403 (setq ns-select-overlay (delete-overlay ns-select-overlay)))
404 (deactivate-mark)
5f68c1b7
GM
405 (goto-char (point-min))
406 (forward-line (1- (if (consp ns-input-line)
407 (min (car ns-input-line) (cdr ns-input-line))
408 ns-input-line))))
edfda783
AR
409 (ns-input-line
410 (if (not ns-select-overlay)
d93e053b
GM
411 (overlay-put (setq ns-select-overlay (make-overlay (point-min)
412 (point-min)))
edfda783
AR
413 'face 'highlight))
414 (let ((beg (save-excursion
d93e053b
GM
415 (goto-char (point-min))
416 (line-beginning-position
417 (if (consp ns-input-line)
418 (min (car ns-input-line) (cdr ns-input-line))
419 ns-input-line))))
edfda783 420 (end (save-excursion
d93e053b
GM
421 (goto-char (point-min))
422 (line-beginning-position
423 (1+ (if (consp ns-input-line)
424 (max (car ns-input-line) (cdr ns-input-line))
425 ns-input-line))))))
edfda783
AR
426 (move-overlay ns-select-overlay beg end)
427 (deactivate-mark)
428 (goto-char beg)))
429 (t
430 (if ns-select-overlay
431 (setq ns-select-overlay (delete-overlay ns-select-overlay))))))
432
433(defun ns-unselect-line ()
a5a1b464 434 "Removes any Nextstep highlight a buffer may contain."
edfda783
AR
435 (if ns-select-overlay
436 (setq ns-select-overlay (delete-overlay ns-select-overlay))))
437
438(add-hook 'first-change-hook 'ns-unselect-line)
439
edfda783 440;;;; Preferences handling.
c0642f6d 441(declare-function ns-get-resource "nsfns.m" (owner name))
edfda783
AR
442
443(defun get-lisp-resource (arg1 arg2)
444 (let ((res (ns-get-resource arg1 arg2)))
445 (cond
446 ((not res) 'unbound)
447 ((string-equal (upcase res) "YES") t)
448 ((string-equal (upcase res) "NO") nil)
449 (t (read res)))))
450
c0642f6d 451;; nsterm.m
c6c62e78 452
c0642f6d
GM
453(declare-function ns-read-file-name "nsfns.m"
454 (prompt &optional dir isLoad init))
455
edfda783
AR
456;;;; File handling.
457
458(defun ns-open-file-using-panel ()
459 "Pop up open-file panel, and load the result in a buffer."
460 (interactive)
ebe68042 461 ;; Prompt dir defaultName isLoad initial.
edfda783
AR
462 (setq ns-input-file (ns-read-file-name "Select File to Load" nil t nil))
463 (if ns-input-file
464 (and (setq ns-input-file (list ns-input-file)) (ns-find-file))))
465
466(defun ns-write-file-using-panel ()
467 "Pop up save-file panel, and save buffer in resulting name."
468 (interactive)
469 (let (ns-output-file)
ebe68042 470 ;; Prompt dir defaultName isLoad initial.
edfda783
AR
471 (setq ns-output-file (ns-read-file-name "Save As" nil nil nil))
472 (message ns-output-file)
473 (if ns-output-file (write-file ns-output-file))))
474
73f6360c
GM
475(defcustom ns-pop-up-frames 'fresh
476 "Non-nil means open files upon request from the Workspace in a new frame.
c0642f6d 477If t, always do so. Any other non-nil value means open a new frame
73f6360c
GM
478unless the current buffer is a scratch buffer."
479 :type '(choice (const :tag "Never" nil)
480 (const :tag "Always" t)
481 (other :tag "Except for scratch buffer" fresh))
482 :version "23.1"
483 :group 'ns)
c0642f6d
GM
484
485(declare-function ns-hide-emacs "nsfns.m" (on))
486
edfda783 487(defun ns-find-file ()
2b4e72e1 488 "Do a `find-file' with the `ns-input-file' as argument."
edfda783 489 (interactive)
14beddf4
CY
490 (let* ((f (file-truename
491 (expand-file-name (pop ns-input-file)
492 command-line-default-directory)))
c6efd3dd
GM
493 (file (find-file-noselect f))
494 (bufwin1 (get-buffer-window file 'visible))
495 (bufwin2 (get-buffer-window "*scratch*" 'visibile)))
edfda783
AR
496 (cond
497 (bufwin1
498 (select-frame (window-frame bufwin1))
499 (raise-frame (window-frame bufwin1))
500 (select-window bufwin1))
501 ((and (eq ns-pop-up-frames 'fresh) bufwin2)
502 (ns-hide-emacs 'activate)
503 (select-frame (window-frame bufwin2))
504 (raise-frame (window-frame bufwin2))
505 (select-window bufwin2)
506 (find-file f))
507 (ns-pop-up-frames
508 (ns-hide-emacs 'activate)
509 (let ((pop-up-frames t)) (pop-to-buffer file nil)))
510 (t
511 (ns-hide-emacs 'activate)
512 (find-file f)))))
513
edfda783
AR
514;;;; Frame-related functions.
515
a5a1b464 516;; Don't show the frame name; that's redundant with Nextstep.
edfda783
AR
517(setq-default mode-line-frame-identification '(" "))
518
e925113b
GM
519;; nsterm.m
520(defvar ns-alternate-modifier)
521(defvar ns-right-alternate-modifier)
b7d1e144
JD
522(defvar ns-right-command-modifier)
523(defvar ns-right-control-modifier)
e925113b 524
edfda783
AR
525;; You say tomAYto, I say tomAHto..
526(defvaralias 'ns-option-modifier 'ns-alternate-modifier)
a2e35ef5 527(defvaralias 'ns-right-option-modifier 'ns-right-alternate-modifier)
edfda783
AR
528
529(defun ns-do-hide-emacs ()
530 (interactive)
531 (ns-hide-emacs t))
532
c0642f6d
GM
533(declare-function ns-hide-others "nsfns.m" ())
534
edfda783
AR
535(defun ns-do-hide-others ()
536 (interactive)
537 (ns-hide-others))
538
c0642f6d
GM
539(declare-function ns-emacs-info-panel "nsfns.m" ())
540
edfda783
AR
541(defun ns-do-emacs-info-panel ()
542 (interactive)
543 (ns-emacs-info-panel))
544
545(defun ns-next-frame ()
546 "Switch to next visible frame."
547 (interactive)
548 (other-frame 1))
2b4e72e1 549
edfda783
AR
550(defun ns-prev-frame ()
551 "Switch to previous visible frame."
552 (interactive)
553 (other-frame -1))
554
ebe68042 555;; If no position specified, make new frame offset by 25 from current.
e5744c66 556(defvar parameters) ; dynamically bound in make-frame
edfda783 557(add-hook 'before-make-frame-hook
ebe68042
SM
558 (lambda ()
559 (let ((left (cdr (assq 'left (frame-parameters))))
560 (top (cdr (assq 'top (frame-parameters)))))
561 (if (consp left) (setq left (cadr left)))
562 (if (consp top) (setq top (cadr top)))
563 (cond
564 ((or (assq 'top parameters) (assq 'left parameters)))
565 ((or (not left) (not top)))
566 (t
567 (setq parameters (cons (cons 'left (+ left 25))
568 (cons (cons 'top (+ top 25))
569 parameters))))))))
570
571;; frame will be focused anyway, so select it
55e8d9a5 572;; (if this is not done, modeline is dimmed until first interaction)
edfda783
AR
573(add-hook 'after-make-frame-functions 'select-frame)
574
f2d9c15f
GM
575(defvar tool-bar-mode)
576(declare-function tool-bar-mode "tool-bar" (&optional arg))
577
edfda783
AR
578;; Based on a function by David Reitter <dreitter@inf.ed.ac.uk> ;
579;; see http://lists.gnu.org/archive/html/emacs-devel/2005-09/msg00681.html .
580(defun ns-toggle-toolbar (&optional frame)
581 "Switches the tool bar on and off in frame FRAME.
582 If FRAME is nil, the change applies to the selected frame."
583 (interactive)
ebe68042
SM
584 (modify-frame-parameters
585 frame (list (cons 'tool-bar-lines
edfda783
AR
586 (if (> (or (frame-parameter frame 'tool-bar-lines) 0) 0)
587 0 1)) ))
588 (if (not tool-bar-mode) (tool-bar-mode t)))
589
edfda783 590
edfda783
AR
591;;;; Dialog-related functions.
592
593;; Ask user for confirm before printing. Due to Kevin Rodgers.
594(defun ns-print-buffer ()
595 "Interactive front-end to `print-buffer': asks for user confirmation first."
596 (interactive)
32226619 597 (if (and (called-interactively-p 'interactive)
ebe68042
SM
598 (or (listp last-nonmenu-event)
599 (and (char-or-string-p (event-basic-type last-command-event))
600 (memq 'super (event-modifiers last-command-event)))))
601 (let ((last-nonmenu-event (if (listp last-nonmenu-event)
602 last-nonmenu-event
603 ;; Fake it:
604 `(mouse-1 POSITION 1))))
605 (if (y-or-n-p (format "Print buffer %s? " (buffer-name)))
606 (print-buffer)
edfda783
AR
607 (error "Cancelled")))
608 (print-buffer)))
609
edfda783
AR
610;;;; Font support.
611
edfda783
AR
612;; Needed for font listing functions under both backend and normal
613(setq scalable-fonts-allowed t)
614
615;; Set to use font panel instead
406aaa6f 616(declare-function ns-popup-font-panel "nsfns.m" (&optional frame))
28571246 617(defalias 'x-select-font 'ns-popup-font-panel "Pop up the font panel.
2b4e72e1 618This function has been overloaded in Nextstep.")
4c785fa7 619(defalias 'mouse-set-font 'ns-popup-font-panel "Pop up the font panel.
2b4e72e1 620This function has been overloaded in Nextstep.")
edfda783 621
c0642f6d
GM
622;; nsterm.m
623(defvar ns-input-font)
624(defvar ns-input-fontsize)
625
edfda783 626(defun ns-respond-to-change-font ()
2b4e72e1
JB
627 "Respond to changeFont: event, expecting `ns-input-font' and\n\
628`ns-input-fontsize' of new font."
edfda783
AR
629 (interactive)
630 (modify-frame-parameters (selected-frame)
631 (list (cons 'font ns-input-font)
632 (cons 'fontsize ns-input-fontsize)))
633 (set-frame-font ns-input-font))
634
635
636;; Default fontset for Mac OS X. This is mainly here to show how a fontset
637;; can be set up manually. Ordinarily, fontsets are auto-created whenever
2b4e72e1 638;; a font is chosen by
edfda783 639(defvar ns-standard-fontset-spec
ebe68042
SM
640 ;; Only some code supports this so far, so use uglier XLFD version
641 ;; "-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard,latin:Courier,han:Kai"
642 (mapconcat 'identity
643 '("-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard"
644 "latin:-*-Courier-*-*-*-*-10-*-*-*-*-*-iso10646-1"
645 "han:-*-Kai-*-*-*-*-10-*-*-*-*-*-iso10646-1"
646 "cyrillic:-*-Trebuchet$MS-*-*-*-*-10-*-*-*-*-*-iso10646-1")
647 ",")
648 "String of fontset spec of the standard fontset.
edfda783 649This defines a fontset consisting of the Courier and other fonts that
2b4e72e1
JB
650come with OS X.
651See the documentation of `create-fontset-from-fontset-spec' for the format.")
edfda783 652
ebe68042 653;; Conditional on new-fontset so bootstrapping works on non-GUI compiles.
725513b7
GM
654(when (fboundp 'new-fontset)
655 ;; Setup the default fontset.
656 (create-default-fontset)
657 ;; Create the standard fontset.
658 (condition-case err
659 (create-fontset-from-fontset-spec ns-standard-fontset-spec t)
660 (error (display-warning
661 'initialization
662 (format "Creation of the standard fontset failed: %s" err)
663 :error))))
edfda783 664
6125167c
GM
665(defvar ns-reg-to-script) ; nsfont.m
666
a3b4b363
AR
667;; This maps font registries (not exposed by NS APIs for font selection) to
668;; unicode scripts (which can be mapped to unicode character ranges which are).
669;; See ../international/fontset.el
670(setq ns-reg-to-script
671 '(("iso8859-1" . latin)
672 ("iso8859-2" . latin)
673 ("iso8859-3" . latin)
674 ("iso8859-4" . latin)
675 ("iso8859-5" . cyrillic)
676 ("microsoft-cp1251" . cyrillic)
677 ("koi8-r" . cyrillic)
678 ("iso8859-6" . arabic)
679 ("iso8859-7" . greek)
680 ("iso8859-8" . hebrew)
681 ("iso8859-9" . latin)
682 ("iso8859-10" . latin)
683 ("iso8859-11" . thai)
684 ("tis620" . thai)
685 ("iso8859-13" . latin)
686 ("iso8859-14" . latin)
687 ("iso8859-15" . latin)
688 ("iso8859-16" . latin)
689 ("viscii1.1-1" . latin)
690 ("jisx0201" . kana)
691 ("jisx0208" . han)
692 ("jisx0212" . han)
693 ("jisx0213" . han)
694 ("gb2312.1980" . han)
695 ("gb18030" . han)
696 ("gbk-0" . han)
697 ("big5" . han)
698 ("cns11643" . han)
699 ("sisheng_cwnn" . bopomofo)
700 ("ksc5601.1987" . hangul)
701 ("ethiopic-unicode" . ethiopic)
702 ("is13194-devanagari" . indian-is13194)
703 ("iso10646.indian-1" . devanagari)))
704
edfda783
AR
705
706;;;; Pasteboard support.
707
c0642f6d
GM
708(declare-function ns-get-cut-buffer-internal "nsselect.m" (buffer))
709
edfda783
AR
710(defun ns-get-pasteboard ()
711 "Returns the value of the pasteboard."
64cb6c78 712 (ns-get-cut-buffer-internal 'CLIPBOARD))
edfda783 713
c0642f6d
GM
714(declare-function ns-store-cut-buffer-internal "nsselect.m" (buffer string))
715
edfda783 716(defun ns-set-pasteboard (string)
a5a1b464 717 "Store STRING into the pasteboard of the Nextstep display server."
edfda783
AR
718 ;; Check the data type of STRING.
719 (if (not (stringp string)) (error "Nonstring given to pasteboard"))
64cb6c78 720 (ns-store-cut-buffer-internal 'CLIPBOARD string))
edfda783 721
ebe68042
SM
722;; We keep track of the last text selected here, so we can check the
723;; current selection against it, and avoid passing back our own text
6d7cc563 724;; from x-selection-value.
edfda783
AR
725(defvar ns-last-selected-text nil)
726
a5a1b464
CY
727;; Return the value of the current Nextstep selection. For
728;; compatibility with older Nextstep applications, this checks cut
729;; buffer 0 before retrieving the value of the primary selection.
6d7cc563 730(defun x-selection-value ()
edfda783 731 (let (text)
45240125 732 ;; Consult the selection. Treat empty strings as if they were unset.
edfda783
AR
733 (or text (setq text (ns-get-pasteboard)))
734 (if (string= text "") (setq text nil))
edfda783
AR
735 (cond
736 ((not text) nil)
737 ((eq text ns-last-selected-text) nil)
738 ((string= text ns-last-selected-text)
739 ;; Record the newer string, so subsequent calls can use the `eq' test.
740 (setq ns-last-selected-text text)
741 nil)
742 (t
743 (setq ns-last-selected-text text)))))
744
745(defun ns-copy-including-secondary ()
746 (interactive)
747 (call-interactively 'kill-ring-save)
748 (ns-store-cut-buffer-internal 'SECONDARY
749 (buffer-substring (point) (mark t))))
750(defun ns-paste-secondary ()
751 (interactive)
752 (insert (ns-get-cut-buffer-internal 'SECONDARY)))
753
edfda783 754
edfda783
AR
755;;;; Scrollbar handling.
756
757(global-set-key [vertical-scroll-bar down-mouse-1] 'ns-handle-scroll-bar-event)
758(global-unset-key [vertical-scroll-bar mouse-1])
759(global-unset-key [vertical-scroll-bar drag-mouse-1])
760
f2d9c15f
GM
761(declare-function scroll-bar-scale "scroll-bar" (num-denom whole))
762
edfda783 763(defun ns-scroll-bar-move (event)
55e8d9a5 764 "Scroll the frame according to a Nextstep scroller event."
edfda783
AR
765 (interactive "e")
766 (let* ((pos (event-end event))
767 (window (nth 0 pos))
768 (scale (nth 2 pos)))
937e6a56 769 (with-current-buffer (window-buffer window)
edfda783
AR
770 (cond
771 ((eq (car scale) (cdr scale))
772 (goto-char (point-max)))
773 ((= (car scale) 0)
774 (goto-char (point-min)))
775 (t
776 (goto-char (+ (point-min) 1
777 (scroll-bar-scale scale (- (point-max) (point-min)))))))
778 (beginning-of-line)
779 (set-window-start window (point))
780 (vertical-motion (/ (window-height window) 2) window))))
781
782(defun ns-handle-scroll-bar-event (event)
55e8d9a5 783 "Handle scroll bar EVENT to emulate Nextstep style scrolling."
edfda783
AR
784 (interactive "e")
785 (let* ((position (event-start event))
786 (bar-part (nth 4 position))
787 (window (nth 0 position))
788 (old-window (selected-window)))
789 (cond
790 ((eq bar-part 'ratio)
791 (ns-scroll-bar-move event))
792 ((eq bar-part 'handle)
793 (if (eq window (selected-window))
794 (track-mouse (ns-scroll-bar-move event))
ebe68042 795 ;; track-mouse faster for selected window, slower for unselected.
edfda783
AR
796 (ns-scroll-bar-move event)))
797 (t
798 (select-window window)
799 (cond
800 ((eq bar-part 'up)
801 (goto-char (window-start window))
802 (scroll-down 1))
803 ((eq bar-part 'above-handle)
804 (scroll-down))
805 ((eq bar-part 'below-handle)
806 (scroll-up))
807 ((eq bar-part 'down)
808 (goto-char (window-start window))
809 (scroll-up 1)))
810 (select-window old-window)))))
811
812
813;;;; Color support.
814
edfda783
AR
815;; Functions for color panel + drag
816(defun ns-face-at-pos (pos)
817 (let* ((frame (car pos))
818 (frame-pos (cons (cadr pos) (cddr pos)))
819 (window (window-at (car frame-pos) (cdr frame-pos) frame))
820 (window-pos (coordinates-in-window-p frame-pos window))
821 (buffer (window-buffer window))
822 (edges (window-edges window)))
823 (cond
824 ((not window-pos)
825 nil)
826 ((eq window-pos 'mode-line)
827 'modeline)
828 ((eq window-pos 'vertical-line)
829 'default)
830 ((consp window-pos)
937e6a56 831 (with-current-buffer buffer
edfda783
AR
832 (let ((p (car (compute-motion (window-start window)
833 (cons (nth 0 edges) (nth 1 edges))
834 (window-end window)
835 frame-pos
836 (- (window-width window) 1)
837 nil
838 window))))
839 (cond
840 ((eq p (window-point window))
841 'cursor)
842 ((and mark-active (< (region-beginning) p) (< p (region-end)))
843 'region)
844 (t
845 (let ((faces (get-char-property p 'face window)))
846 (if (consp faces) (car faces) faces)))))))
847 (t
848 nil))))
849
c0642f6d
GM
850(defvar ns-input-color) ; nsterm.m
851
edfda783 852(defun ns-set-foreground-at-mouse ()
2b4e72e1 853 "Set the foreground color at the mouse location to `ns-input-color'."
edfda783
AR
854 (interactive)
855 (let* ((pos (mouse-position))
856 (frame (car pos))
857 (face (ns-face-at-pos pos)))
858 (cond
859 ((eq face 'cursor)
c0642f6d 860 (modify-frame-parameters frame (list (cons 'cursor-color
edfda783
AR
861 ns-input-color))))
862 ((not face)
863 (modify-frame-parameters frame (list (cons 'foreground-color
864 ns-input-color))))
865 (t
866 (set-face-foreground face ns-input-color frame)))))
867
868(defun ns-set-background-at-mouse ()
2b4e72e1 869 "Set the background color at the mouse location to `ns-input-color'."
edfda783
AR
870 (interactive)
871 (let* ((pos (mouse-position))
872 (frame (car pos))
873 (face (ns-face-at-pos pos)))
874 (cond
875 ((eq face 'cursor)
876 (modify-frame-parameters frame (list (cons 'cursor-color
877 ns-input-color))))
878 ((not face)
879 (modify-frame-parameters frame (list (cons 'background-color
880 ns-input-color))))
881 (t
882 (set-face-background face ns-input-color frame)))))
883
a5a1b464 884;; Set some options to be as Nextstep-like as possible.
edfda783
AR
885(setq frame-title-format t
886 icon-title-format t)
887
edfda783
AR
888
889(defvar ns-initialized nil
a5a1b464 890 "Non-nil if Nextstep windowing has been initialized.")
edfda783 891
c0642f6d 892(declare-function ns-list-services "nsfns.m" ())
b51a3365 893(declare-function x-open-connection "nsfns.m"
f2d9c15f 894 (display &optional xrm-string must-succeed))
c0642f6d 895
a5a1b464
CY
896;; Do the actual Nextstep Windows setup here; the above code just
897;; defines functions and variables that we use now.
edfda783 898(defun ns-initialize-window-system ()
a5a1b464 899 "Initialize Emacs for Nextstep (Cocoa / GNUstep) windowing."
edfda783 900
ebe68042 901 ;; PENDING: not needed?
d7d8c62a 902 (setq command-line-args (x-handle-args command-line-args))
edfda783 903
9e50ff0c 904 (x-open-connection (system-name) nil t)
edfda783 905
ebe68042
SM
906 (dolist (service (ns-list-services))
907 (if (eq (car service) 'undefined)
908 (ns-define-service (cdr service))
909 (define-key global-map (vector (car service))
910 (ns-define-service (cdr service)))))
edfda783
AR
911
912 (if (and (eq (get-lisp-resource nil "NXAutoLaunch") t)
913 (eq (get-lisp-resource nil "HideOnAutoLaunch") t))
914 (add-hook 'after-init-hook 'ns-do-hide-emacs))
915
ebe68042 916 ;; FIXME: This will surely lead to "MODIFIED OUTSIDE CUSTOM" warnings.
edfda783 917 (menu-bar-mode (if (get-lisp-resource nil "Menus") 1 -1))
edfda783 918
cd93b359
DR
919 ;; OS X Lion introduces PressAndHold, which is unsupported by this port.
920 ;; See this thread for more details:
921 ;; http://lists.gnu.org/archive/html/emacs-devel/2011-06/msg00505.html
922 (ns-set-resource nil "ApplePressAndHoldEnabled" "NO")
923
edfda783
AR
924 (setq ns-initialized t))
925
d7d8c62a 926(add-to-list 'handle-args-function-alist '(ns . x-handle-args))
edfda783
AR
927(add-to-list 'frame-creation-function-alist '(ns . x-create-frame-with-faces))
928(add-to-list 'window-system-initialization-alist '(ns . ns-initialize-window-system))
929
930
931(provide 'ns-win)
932
933;;; ns-win.el ends here