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