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