1 ;;; mac-win.el --- parse switches controlling interface with Mac window system
3 ;; Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005
4 ;; Free Software Foundation, Inc.
6 ;; Author: Andrew Choi <akochoi@mac.com>
9 ;; This file is part of GNU Emacs.
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
28 ;; Mac-win.el: this file is loaded from ../lisp/startup.el when it recognizes
29 ;; that Mac windows are to be used. Command line switches are parsed and those
30 ;; pertaining to Mac are processed and removed from the command line. The
31 ;; Mac display is opened and hooks are set for popping up the initial window.
33 ;; startup.el will then examine startup files, and eventually call the hooks
34 ;; which create the first window(s).
38 ;; These are the standard X switches from the Xt Initialize.c file of
41 ;; Command line Resource Manager string
44 ;; +synchronous *synchronous
45 ;; -background *background
48 ;; -bordercolor *borderColor
49 ;; -borderwidth .borderWidth
55 ;; -foreground *foreground
56 ;; -geometry .geometry
61 ;; -reverse *reverseVideo
63 ;; -selectionTimeout .selectionTimeout
64 ;; -synchronous *synchronous
67 ;; An alist of X options and the function which handles them. See
70 (if (not (eq window-system 'mac))
71 (error "%s: Loading mac-win.el but not compiled for Mac" (invocation-name)))
82 (defvar x-invocation-args)
84 (defvar x-command-line-resources nil)
86 ;; Handler for switches of the form "-switch value" or "-switch".
87 (defun x-handle-switch (switch)
88 (let ((aelt (assoc switch command-line-x-option-alist)))
90 (let ((param (nth 3 aelt))
93 (setq default-frame-alist
94 (cons (cons param value)
96 (setq default-frame-alist
98 (car x-invocation-args))
100 x-invocation-args (cdr x-invocation-args)))))))
102 ;; Handler for switches of the form "-switch n"
103 (defun x-handle-numeric-switch (switch)
104 (let ((aelt (assoc switch command-line-x-option-alist)))
106 (let ((param (nth 3 aelt)))
107 (setq default-frame-alist
109 (string-to-int (car x-invocation-args)))
112 (cdr x-invocation-args))))))
114 ;; Handle options that apply to initial frame only
115 (defun x-handle-initial-switch (switch)
116 (let ((aelt (assoc switch command-line-x-option-alist)))
118 (let ((param (nth 3 aelt))
119 (value (nth 4 aelt)))
121 (setq initial-frame-alist
122 (cons (cons param value)
123 initial-frame-alist))
124 (setq initial-frame-alist
126 (car x-invocation-args))
128 x-invocation-args (cdr x-invocation-args)))))))
130 ;; Make -iconic apply only to the initial frame!
131 (defun x-handle-iconic (switch)
132 (setq initial-frame-alist
133 (cons '(visibility . icon) initial-frame-alist)))
135 ;; Handle the -xrm option.
136 (defun x-handle-xrm-switch (switch)
137 (unless (consp x-invocation-args)
138 (error "%s: missing argument to `%s' option" (invocation-name) switch))
139 (setq x-command-line-resources
140 (if (null x-command-line-resources)
141 (car x-invocation-args)
142 (concat x-command-line-resources "\n" (car x-invocation-args))))
143 (setq x-invocation-args (cdr x-invocation-args)))
145 ;; Handle the geometry option
146 (defun x-handle-geometry (switch)
147 (let* ((geo (x-parse-geometry (car x-invocation-args)))
148 (left (assq 'left geo))
149 (top (assq 'top geo))
150 (height (assq 'height geo))
151 (width (assq 'width geo)))
152 (if (or height width)
153 (setq default-frame-alist
154 (append default-frame-alist
156 (if height (list height))
157 (if width (list width)))
159 (append initial-frame-alist
161 (if height (list height))
162 (if width (list width)))))
164 (setq initial-frame-alist
165 (append initial-frame-alist
166 '((user-position . t))
167 (if left (list left))
168 (if top (list top)))))
169 (setq x-invocation-args (cdr x-invocation-args))))
171 ;; Handle the -name option. Set the variable x-resource-name
172 ;; to the option's operand; set the name of
173 ;; the initial frame, too.
174 (defun x-handle-name-switch (switch)
175 (or (consp x-invocation-args)
176 (error "%s: missing argument to `%s' option" (invocation-name) switch))
177 (setq x-resource-name (car x-invocation-args)
178 x-invocation-args (cdr x-invocation-args))
179 (setq initial-frame-alist (cons (cons 'name x-resource-name)
180 initial-frame-alist)))
182 (defvar x-display-name nil
183 "The display name specifying server and frame.")
185 (defun x-handle-display (switch)
186 (setq x-display-name (car x-invocation-args)
187 x-invocation-args (cdr x-invocation-args)))
189 (defun x-handle-args (args)
190 "Process the X-related command line options in ARGS.
191 This is done before the user's startup file is loaded. They are copied to
192 `x-invocation-args', from which the X-related things are extracted, first
193 the switch (e.g., \"-fg\") in the following code, and possible values
194 \(e.g., \"black\") in the option handler code (e.g., x-handle-switch).
195 This function returns ARGS minus the arguments that have been processed."
196 ;; We use ARGS to accumulate the args that we don't handle here, to return.
197 (setq x-invocation-args args
199 (while (and x-invocation-args
200 (not (equal (car x-invocation-args) "--")))
201 (let* ((this-switch (car x-invocation-args))
202 (orig-this-switch this-switch)
203 completion argval aelt handler)
204 (setq x-invocation-args (cdr x-invocation-args))
205 ;; Check for long options with attached arguments
206 ;; and separate out the attached option argument into argval.
207 (if (string-match "^--[^=]*=" this-switch)
208 (setq argval (substring this-switch (match-end 0))
209 this-switch (substring this-switch 0 (1- (match-end 0)))))
210 ;; Complete names of long options.
211 (if (string-match "^--" this-switch)
213 (setq completion (try-completion this-switch command-line-x-option-alist))
214 (if (eq completion t)
215 ;; Exact match for long option.
217 (if (stringp completion)
218 (let ((elt (assoc completion command-line-x-option-alist)))
219 ;; Check for abbreviated long option.
221 (error "Option `%s' is ambiguous" this-switch))
222 (setq this-switch completion))))))
223 (setq aelt (assoc this-switch command-line-x-option-alist))
224 (if aelt (setq handler (nth 2 aelt)))
227 (let ((x-invocation-args
228 (cons argval x-invocation-args)))
229 (funcall handler this-switch))
230 (funcall handler this-switch))
231 (setq args (cons orig-this-switch args)))))
232 (nconc (nreverse args) x-invocation-args))
236 ;; Standard Mac cursor shapes
239 (defconst mac-pointer-arrow 0)
240 (defconst mac-pointer-copy-arrow 1)
241 (defconst mac-pointer-alias-arrow 2)
242 (defconst mac-pointer-contextual-menu-arrow 3)
243 (defconst mac-pointer-I-beam 4)
244 (defconst mac-pointer-cross 5)
245 (defconst mac-pointer-plus 6)
246 (defconst mac-pointer-watch 7)
247 (defconst mac-pointer-closed-hand 8)
248 (defconst mac-pointer-open-hand 9)
249 (defconst mac-pointer-pointing-hand 10)
250 (defconst mac-pointer-counting-up-hand 11)
251 (defconst mac-pointer-counting-down-hand 12)
252 (defconst mac-pointer-counting-up-and-down-hand 13)
253 (defconst mac-pointer-spinning 14)
254 (defconst mac-pointer-resize-left 15)
255 (defconst mac-pointer-resize-right 16)
256 (defconst mac-pointer-resize-left-right 17)
257 ;; Mac OS X 10.2 and later
258 (defconst mac-pointer-not-allowed 18)
259 ;; Mac OS X 10.3 and later
260 (defconst mac-pointer-resize-up 19)
261 (defconst mac-pointer-resize-down 20)
262 (defconst mac-pointer-resize-up-down 21)
263 (defconst mac-pointer-poof 22)
266 ;; Standard X cursor shapes that have Mac counterparts
269 (defconst x-pointer-left-ptr mac-pointer-arrow)
270 (defconst x-pointer-xterm mac-pointer-I-beam)
271 (defconst x-pointer-crosshair mac-pointer-cross)
272 (defconst x-pointer-plus mac-pointer-plus)
273 (defconst x-pointer-watch mac-pointer-watch)
274 (defconst x-pointer-hand2 mac-pointer-pointing-hand)
275 (defconst x-pointer-left-side mac-pointer-resize-left)
276 (defconst x-pointer-right-side mac-pointer-resize-right)
277 (defconst x-pointer-sb-h-double-arrow mac-pointer-resize-left-right)
278 (defconst x-pointer-top-side mac-pointer-resize-up)
279 (defconst x-pointer-bottom-side mac-pointer-resize-down)
280 (defconst x-pointer-sb-v-double-arrow mac-pointer-resize-up-down)
287 (defvar x-colors '("LightGreen"
886 "LightGoldenrodYellow"
887 "light goldenrod yellow"
904 "medium spring green"
1039 "The list of X colors from the `rgb.txt' file.
1040 XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp")
1042 (defun xw-defined-colors (&optional frame)
1043 "Internal function called by `defined-colors', which see."
1044 (or frame (setq frame (selected-frame)))
1045 (let ((all-colors x-colors)
1047 (defined-colors nil))
1049 (setq this-color (car all-colors)
1050 all-colors (cdr all-colors))
1051 (and (color-supported-p this-color frame t)
1052 (setq defined-colors (cons this-color defined-colors))))
1057 (substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame
1060 ;; Map certain keypad keys into ASCII characters
1061 ;; that people usually expect.
1062 (define-key function-key-map [backspace] [?\d])
1063 (define-key function-key-map [delete] [?\d])
1064 (define-key function-key-map [tab] [?\t])
1065 (define-key function-key-map [linefeed] [?\n])
1066 (define-key function-key-map [clear] [?\C-l])
1067 (define-key function-key-map [return] [?\C-m])
1068 (define-key function-key-map [escape] [?\e])
1069 (define-key function-key-map [M-backspace] [?\M-\d])
1070 (define-key function-key-map [M-delete] [?\M-\d])
1071 (define-key function-key-map [M-tab] [?\M-\t])
1072 (define-key function-key-map [M-linefeed] [?\M-\n])
1073 (define-key function-key-map [M-clear] [?\M-\C-l])
1074 (define-key function-key-map [M-return] [?\M-\C-m])
1075 (define-key function-key-map [M-escape] [?\M-\e])
1077 ;; These tell read-char how to convert
1078 ;; these special chars to ASCII.
1079 (put 'backspace 'ascii-character ?\d)
1080 (put 'delete 'ascii-character ?\d)
1081 (put 'tab 'ascii-character ?\t)
1082 (put 'linefeed 'ascii-character ?\n)
1083 (put 'clear 'ascii-character ?\C-l)
1084 (put 'return 'ascii-character ?\C-m)
1085 (put 'escape 'ascii-character ?\e)
1090 ;; Define constant values to be set to mac-keyboard-text-encoding
1091 (defconst kTextEncodingMacRoman 0)
1092 (defconst kTextEncodingISOLatin1 513 "0x201")
1093 (defconst kTextEncodingISOLatin2 514 "0x202")
1096 ;;;; Selections and cut buffers
1098 ;; Setup to use the Mac clipboard. The functions mac-cut-function and
1099 ;; mac-paste-function are defined in mac.c.
1100 (set-selection-coding-system 'compound-text-mac)
1102 (setq interprogram-cut-function
1105 (encode-coding-string str selection-coding-system t) push)))
1107 (setq interprogram-paste-function
1109 (let ((clipboard (mac-paste-function)))
1111 (decode-coding-string clipboard selection-coding-system t)))))
1114 ;;; Do the actual Windows setup here; the above code just defines
1115 ;;; functions and variables that we use now.
1117 (setq command-line-args (x-handle-args command-line-args))
1119 ;;; Make sure we have a valid resource name.
1120 (or (stringp x-resource-name)
1122 (setq x-resource-name (invocation-name))
1124 ;; Change any . or * characters in x-resource-name to hyphens,
1125 ;; so as not to choke when we use it in X resource queries.
1126 (while (setq i (string-match "[.*]" x-resource-name))
1127 (aset x-resource-name i ?-))))
1129 (if (x-display-list)
1130 ;; On Mac OS 8/9, Most coding systems used in code conversion for
1131 ;; font names are not ready at the time when the terminal frame is
1132 ;; created. So we reconstruct font name table for the initial
1134 (mac-clear-font-name-table)
1135 (x-open-connection "Mac"
1136 x-command-line-resources
1137 ;; Exit Emacs with fatal error if this fails.
1140 (setq frame-creation-function 'x-create-frame-with-faces);; Setup the default fontset.
1141 (setup-default-fontset)
1143 ;; Carbon uses different fonts than commonly found on X, so
1144 ;; we define our own standard fontset here.
1145 (defvar mac-standard-fontset-spec
1146 "-apple-Monaco-normal-r-*-*-12-*-*-*-*-*-fontset-mac"
1147 "String of fontset spec of the standard fontset.
1148 This defines a fontset consisting of the Monaco variations for
1149 European languages which are distributed with Mac OS X.
1151 See the documentation of `create-fontset-from-fontset-spec for the format.")
1153 ;; Create a fontset that uses mac-roman font. With this fontset,
1154 ;; characters decoded from mac-roman encoding (ascii, latin-iso8859-1,
1155 ;; and mule-unicode-xxxx-yyyy) are displayed by a mac-roman font.
1156 (create-fontset-from-fontset-spec mac-standard-fontset-spec t)
1158 ;; Create fontset specified in X resources "Fontset-N" (N is 0, 1, ...).
1159 (create-fontset-from-x-resource)
1161 ;; Try to create a fontset from a font specification which comes
1162 ;; from initial-frame-alist, default-frame-alist, or X resource.
1163 ;; A font specification in command line argument (i.e. -fn XXXX)
1164 ;; should be already in default-frame-alist as a `font'
1165 ;; parameter. However, any font specifications in site-start
1166 ;; library, user's init file (.emacs), and default.el are not
1167 ;; yet handled here.
1169 (let ((font (or (cdr (assq 'font initial-frame-alist))
1170 (cdr (assq 'font default-frame-alist))
1171 (x-get-resource "font" "Font")))
1172 xlfd-fields resolved-name)
1174 (not (query-fontset font))
1175 (setq resolved-name (x-resolve-font-name font))
1176 (setq xlfd-fields (x-decompose-font-name font)))
1177 (if (string= "fontset" (aref xlfd-fields xlfd-regexp-registry-subnum))
1178 (new-fontset font (x-complement-fontset-spec xlfd-fields nil))
1179 ;; Create a fontset from FONT. The fontset name is
1180 ;; generated from FONT.
1181 (create-fontset-from-ascii-font font resolved-name "startup"))))
1183 ;; Apply a geometry resource to the initial frame. Put it at the end
1184 ;; of the alist, so that anything specified on the command line takes
1186 (let* ((res-geometry (x-get-resource "geometry" "Geometry"))
1190 (setq parsed (x-parse-geometry res-geometry))
1191 ;; If the resource specifies a position,
1192 ;; call the position and size "user-specified".
1193 (if (or (assq 'top parsed) (assq 'left parsed))
1194 (setq parsed (cons '(user-position . t)
1195 (cons '(user-size . t) parsed))))
1196 ;; All geometry parms apply to the initial frame.
1197 (setq initial-frame-alist (append initial-frame-alist parsed))
1198 ;; The size parms apply to all frames.
1199 (if (assq 'height parsed)
1200 (setq default-frame-alist
1201 (cons (cons 'height (cdr (assq 'height parsed)))
1202 default-frame-alist)))
1203 (if (assq 'width parsed)
1204 (setq default-frame-alist
1205 (cons (cons 'width (cdr (assq 'width parsed)))
1206 default-frame-alist))))))
1208 ;; Check the reverseVideo resource.
1209 (let ((case-fold-search t))
1210 (let ((rv (x-get-resource "reverseVideo" "ReverseVideo")))
1212 (string-match "^\\(true\\|yes\\|on\\)$" rv))
1213 (setq default-frame-alist
1214 (cons '(reverse . t) default-frame-alist)))))
1216 (defun x-win-suspend-error ()
1217 (error "Suspending an Emacs running under Mac makes no sense"))
1218 (add-hook 'suspend-hook 'x-win-suspend-error)
1220 ;; Don't show the frame name; that's redundant.
1221 (setq-default mode-line-frame-identification " ")
1223 ;; Turn on support for mouse wheels.
1224 (mouse-wheel-mode 1)
1226 (defun mac-drag-n-drop (event)
1227 "Edit the files listed in the drag-n-drop EVENT.
1228 Switch to a buffer editing the last file dropped."
1230 ;; Make sure the drop target has positive co-ords
1231 ;; before setting the selected frame - otherwise it
1232 ;; won't work. <skx@tardis.ed.ac.uk>
1233 (let* ((window (posn-window (event-start event)))
1234 (coords (posn-x-y (event-start event)))
1237 (if (and (> x 0) (> y 0))
1238 (set-frame-selected-window nil window))
1239 (mapcar (lambda (file-name)
1240 (if (listp file-name)
1241 (let ((line (car file-name))
1242 (start (car (cdr file-name)))
1243 (end (car (cdr (cdr file-name)))))
1246 (if (and (> start 0) (> end 0))
1247 (progn (set-mark start)
1249 (x-dnd-handle-one-url window 'private
1250 (concat "file:" file-name))))
1251 (car (cdr (cdr event)))))
1254 (global-set-key [drag-n-drop] 'mac-drag-n-drop)
1256 ;; By checking whether the variable mac-ready-for-drag-n-drop has been
1257 ;; defined, the event loop in macterm.c can be informed that it can
1258 ;; now receive Finder drag and drop events. Files dropped onto the
1259 ;; Emacs application icon can only be processed when the initial frame
1260 ;; has been created: this is where the files should be opened.
1261 (add-hook 'after-init-hook
1263 (defvar mac-ready-for-drag-n-drop t)))
1268 ;; (defun mac-handle-scroll-bar-event (event) (interactive "e") (princ event))
1270 ;;(global-set-key [vertical-scroll-bar mouse-1] 'mac-handle-scroll-bar-event)
1273 [vertical-scroll-bar down-mouse-1]
1274 'mac-handle-scroll-bar-event)
1276 (global-unset-key [vertical-scroll-bar drag-mouse-1])
1277 (global-unset-key [vertical-scroll-bar mouse-1])
1279 (defun mac-handle-scroll-bar-event (event)
1280 "Handle scroll bar EVENT to emulate Mac Toolbox style scrolling."
1282 (let* ((position (event-start event))
1283 (window (nth 0 position))
1284 (bar-part (nth 4 position)))
1285 (select-window window)
1288 (goto-char (window-start window))
1289 (mac-scroll-down-line))
1290 ((eq bar-part 'above-handle)
1292 ((eq bar-part 'handle)
1293 (scroll-bar-drag event))
1294 ((eq bar-part 'below-handle)
1296 ((eq bar-part 'down)
1297 (goto-char (window-start window))
1298 (mac-scroll-up-line)))))
1300 (defun mac-scroll-ignore-events ()
1301 ;; Ignore confusing non-mouse events
1302 (while (not (memq (car-safe (read-event))
1303 '(mouse-1 double-mouse-1 triple-mouse-1))) nil))
1305 (defun mac-scroll-down ()
1307 (mac-scroll-ignore-events)
1310 (defun mac-scroll-down-line ()
1312 (mac-scroll-ignore-events)
1315 (defun mac-scroll-up ()
1317 (mac-scroll-ignore-events)
1320 (defun mac-scroll-up-line ()
1322 (mac-scroll-ignore-events)
1328 (unless (eq system-type 'darwin)
1329 ;; This variable specifies the Unix program to call (as a process) to
1330 ;; determine the amount of free space on a file system (defaults to
1331 ;; df). If it is not set to nil, ls-lisp will not work correctly
1332 ;; unless an external application df is implemented on the Mac.
1333 (setq directory-free-space-program nil)
1335 ;; Set this so that Emacs calls subprocesses with "sh" as shell to
1336 ;; expand filenames Note no subprocess for the shell is actually
1337 ;; started (see run_mac_command in sysdep.c).
1338 (setq shell-file-name "sh")
1340 ;; To display filenames in Chinese or Japanese, replace mac-roman with
1342 (setq file-name-coding-system 'mac-roman))
1344 ;; X Window emulation in macterm.c is not complete enough to start a
1345 ;; frame without a minibuffer properly. Call this to tell ediff
1346 ;; library to use a single frame.
1347 ; (ediff-toggle-multiframe)
1349 ;; If Emacs is started from the Finder, change the default directory
1350 ;; to the user's home directory.
1351 (if (string= default-directory "/")
1354 ;; Darwin 6- pty breakage is now controlled from the C code so that
1355 ;; it applies to all builds on darwin. See s/darwin.h PTY_ITERATION.
1356 ;; (setq process-connection-type t)
1358 ;; Assume that fonts are always scalable on the Mac. This sometimes
1359 ;; results in characters with jagged edges. However, without it,
1360 ;; fonts with both truetype and bitmap representations but no italic
1361 ;; or bold bitmap versions will not display these variants correctly.
1362 (setq scalable-fonts-allowed t)
1364 ;; (prefer-coding-system 'mac-roman)
1366 ;; arch-tag: 71dfcd14-cde8-4d66-b05c-85ec94fb23a6
1367 ;;; mac-win.el ends here