;;; mac-win.el --- parse switches controlling interface with Mac window system -*-coding: iso-2022-7bit;-*-
-;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
-;; 2005, 2006 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
+;; 2005, 2006, 2007 Free Software Foundation, Inc.
;; Author: Andrew Choi <akochoi@mac.com>
;; Keywords: terminals
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; An alist of X options and the function which handles them. See
;; ../startup.el.
-(if (not (eq window-system 'mac))
- (error "%s: Loading mac-win.el but not compiled for Mac" (invocation-name)))
+;; (if (not (eq window-system 'mac))
+;; (error "%s: Loading mac-win.el but not compiled for Mac" (invocation-name)))
(require 'frame)
(require 'mouse)
(eval-when-compile (require 'url))
(defvar mac-charset-info-alist)
-(defvar mac-services-selection)
+(defvar mac-service-selection)
(defvar mac-system-script-code)
(defvar mac-apple-event-map)
-(defvar mac-atsu-font-table)
(defvar mac-font-panel-mode)
+(defvar mac-ts-active-input-overlay)
(defvar x-invocation-args)
(defvar x-command-line-resources nil)
(substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame
global-map)
+(defun x-setup-function-keys (frame)
+ "Setup Function Keys for mac."
;; Map certain keypad keys into ASCII characters
;; that people usually expect.
(define-key local-function-key-map [backspace] [?\d])
(define-key local-function-key-map [M-clear] [?\M-\C-l])
(define-key local-function-key-map [M-return] [?\M-\C-m])
(define-key local-function-key-map [M-escape] [?\M-\e])
+)
;; These tell read-char how to convert
;; these special chars to ASCII.
\f
;;;; Conversion between common flavors and Lisp string.
+(defconst mac-text-encoding-ascii #x600
+ "ASCII text encoding.")
+
(defconst mac-text-encoding-mac-japanese-basic-variant #x20001
"MacJapanese text encoding without Apple double-byte extensions.")
(if (string-match "[\xa0\xfd-\xff]" str)
(setq str nil)
;; ASCII-only?
- (unless (string-match "\\`[[:ascii:]]*\\'" str)
+ (unless (mac-code-convert-string data nil mac-text-encoding-ascii)
(subst-char-in-string ?\x5c ?\\e(J\\e(B str t)
(subst-char-in-string ?\x80 ?\\ str t)))))
(or str
(find-coding-systems-string string)))
(setq coding-system
(coding-system-change-eol-conversion coding-system 'mac))
- (when (and (eq system-type 'darwin)
- (eq coding-system 'japanese-shift-jis-mac))
- (setq encoding mac-text-encoding-mac-japanese-basic-variant)
- (setq string (subst-char-in-string ?\\ ?\x80 string))
- (subst-char-in-string ?\\e(J\\e(B ?\x5c string t))
- (setq data (mac-code-convert-string
- (encode-coding-string string coding-system)
- (or encoding coding-system) nil)))
+ (let ((str string))
+ (when (and (eq system-type 'darwin)
+ (eq coding-system 'japanese-shift-jis-mac))
+ (setq encoding mac-text-encoding-mac-japanese-basic-variant)
+ (setq str (subst-char-in-string ?\\ ?\x80 str))
+ (subst-char-in-string ?\\e(J\\e(B ?\x5c str t)
+ ;; ASCII-only?
+ (if (string-match "\\`[\x00-\x7f]*\\'" str)
+ (setq str nil)))
+ (and str
+ (setq data (mac-code-convert-string
+ (encode-coding-string str coding-system)
+ (or encoding coding-system) nil)))))
(or data (encode-coding-string string (if (eq (byteorder) ?B)
'utf-16be-mac
'utf-16le-mac)))))
;;; Event IDs
;; kCoreEventClass
-(put 'open-application 'mac-apple-event-id "oapp") ; kAEOpenApplication
-(put 'reopen-application 'mac-apple-event-id "rapp") ; kAEReopenApplication
-(put 'open-documents 'mac-apple-event-id "odoc") ; kAEOpenDocuments
-(put 'print-documents 'mac-apple-event-id "pdoc") ; kAEPrintDocuments
-(put 'open-contents 'mac-apple-event-id "ocon") ; kAEOpenContents
-(put 'quit-application 'mac-apple-event-id "quit") ; kAEQuitApplication
-(put 'application-died 'mac-apple-event-id "obit") ; kAEApplicationDied
-(put 'show-preferences 'mac-apple-event-id "pref") ; kAEShowPreferences
-(put 'autosave-now 'mac-apple-event-id "asav") ; kAEAutosaveNow
+(put 'open-application 'mac-apple-event-id "oapp") ; kAEOpenApplication
+(put 'reopen-application 'mac-apple-event-id "rapp") ; kAEReopenApplication
+(put 'open-documents 'mac-apple-event-id "odoc") ; kAEOpenDocuments
+(put 'print-documents 'mac-apple-event-id "pdoc") ; kAEPrintDocuments
+(put 'open-contents 'mac-apple-event-id "ocon") ; kAEOpenContents
+(put 'quit-application 'mac-apple-event-id "quit") ; kAEQuitApplication
+(put 'application-died 'mac-apple-event-id "obit") ; kAEApplicationDied
+(put 'show-preferences 'mac-apple-event-id "pref") ; kAEShowPreferences
+(put 'autosave-now 'mac-apple-event-id "asav") ; kAEAutosaveNow
;; kAEInternetEventClass
-(put 'get-url 'mac-apple-event-id "GURL") ; kAEGetURL
-;; Converted HICommand events
-(put 'about 'mac-apple-event-id "abou") ; kHICommandAbout
+(put 'get-url 'mac-apple-event-id "GURL") ; kAEGetURL
+;; Converted HI command events
+(put 'about 'mac-apple-event-id "abou") ; kHICommandAbout
+(put 'show-hide-font-panel 'mac-apple-event-id "shfp") ; kHICommandShowHideFontPanel
(defmacro mac-event-spec (event)
`(nth 1 ,event))
(mac-coerce-ae-data (car type-data) (cdr type-data) type))
(cdr desc)))))))
+(defun mac-ae-number (ae keyword)
+ (let ((type-data (mac-ae-parameter ae keyword))
+ str)
+ (if (and type-data
+ (setq str (mac-coerce-ae-data (car type-data)
+ (cdr type-data) "TEXT")))
+ (let ((num (string-to-number str)))
+ ;; Mac OS Classic may return "0e+0" as the coerced value for
+ ;; the type "magn" and the data "\000\000\000\000".
+ (if (= num 0.0) 0 num))
+ nil)))
+
(defun mac-bytes-to-integer (bytes &optional from to)
(or from (setq from 0))
(or to (setq to (length bytes)))
(ash (lsh result extended-sign-len) (- extended-sign-len))
result)))
-(defun mac-bytes-to-digits (bytes &optional from to)
- (or from (setq from 0))
- (or to (setq to (length bytes)))
- (let ((len (- to from))
- (val 0.0))
- (dotimes (i len)
- (setq val (+ (* val 256.0)
- (aref bytes (+ from (if (eq (byteorder) ?B) i
- (- len i 1)))))))
- (format "%.0f" val)))
-
(defun mac-ae-selection-range (ae)
;; #pragma options align=mac68k
;; typedef struct SelectionRange {
(and utf8-text
(decode-coding-string utf8-text 'utf-8))))
+(defun mac-ae-text (ae)
+ (or (cdr (mac-ae-parameter ae nil "TEXT"))
+ (error "No text in Apple event.")))
+
+(defun mac-ae-frame (ae &optional keyword type)
+ (let ((bytes (cdr (mac-ae-parameter ae keyword type))))
+ (if (or (null bytes) (/= (length bytes) 4))
+ (error "No window reference in Apple event.")
+ (let ((window-id (mac-coerce-ae-data "long" bytes "TEXT"))
+ (rest (frame-list))
+ frame)
+ (while (and (null frame) rest)
+ (if (string= (frame-parameter (car rest) 'window-id) window-id)
+ (setq frame (car rest)))
+ (setq rest (cdr rest)))
+ frame))))
+
+(defun mac-ae-script-language (ae keyword)
+;; struct WritingCode {
+;; ScriptCode theScriptCode;
+;; LangCode theLangCode;
+;; };
+ (let ((bytes (cdr (mac-ae-parameter ae keyword "intl"))))
+ (and bytes
+ (cons (mac-bytes-to-integer bytes 0 2)
+ (mac-bytes-to-integer bytes 2 4)))))
+
+(defun mac-bytes-to-text-range (bytes &optional from to)
+;; struct TextRange {
+;; long fStart;
+;; long fEnd;
+;; short fHiliteStyle;
+;; };
+ (or from (setq from 0))
+ (or to (setq to (length bytes)))
+ (and (= (- to from) (+ 4 4 2))
+ (list (mac-bytes-to-integer bytes from (+ from 4))
+ (mac-bytes-to-integer bytes (+ from 4) (+ from 8))
+ (mac-bytes-to-integer bytes (+ from 8) to))))
+
+(defun mac-ae-text-range-array (ae keyword)
+;; struct TextRangeArray {
+;; short fNumOfRanges;
+;; TextRange fRange[1];
+;; };
+ (let* ((bytes (cdr (mac-ae-parameter ae keyword "tray")))
+ (len (length bytes))
+ nranges result)
+ (when (and bytes (>= len 2)
+ (progn
+ (setq nranges (mac-bytes-to-integer bytes 0 2))
+ (= len (+ 2 (* nranges 10)))))
+ (setq result (make-vector nranges nil))
+ (dotimes (i nranges)
+ (aset result i
+ (mac-bytes-to-text-range bytes (+ (* i 10) 2)
+ (+ (* i 10) 12)))))
+ result))
+
+(defconst mac-keyboard-modifier-mask-alist
+ (mapcar
+ (lambda (modifier-bit)
+ (cons (car modifier-bit) (lsh 1 (cdr modifier-bit))))
+ '((command . 8) ; cmdKeyBit
+ (shift . 9) ; shiftKeyBit
+ (option . 11) ; optionKeyBit
+ (control . 12) ; controlKeyBit
+ (function . 17))) ; kEventKeyModifierFnBit
+ "Alist of Mac keyboard modifier symbols vs masks.")
+
+(defun mac-ae-keyboard-modifiers (ae)
+ (let ((modifiers-value (mac-ae-number ae "kmod"))
+ modifiers)
+ (if modifiers-value
+ (dolist (modifier-mask mac-keyboard-modifier-mask-alist)
+ (if (/= (logand modifiers-value (cdr modifier-mask)) 0)
+ (setq modifiers (cons (car modifier-mask) modifiers)))))
+ modifiers))
+
(defun mac-ae-open-documents (event)
"Open the documents specified by the Apple event EVENT."
(interactive "e")
(let ((ae (mac-event-ae event)))
(dolist (file-name (mac-ae-list ae nil 'undecoded-file-name))
(if file-name
- (dnd-open-local-file (concat "file:" file-name) nil)))
+ (dnd-open-local-file
+ (concat "file://"
+ (mapconcat 'url-hexify-string
+ (split-string file-name "/") "/")) nil)))
(let ((selection-range (mac-ae-selection-range ae))
(search-text (mac-ae-text-for-search ae)))
(cond (selection-range
nil t)))))
(select-frame-set-input-focus (selected-frame)))
-(defun mac-ae-text (ae)
- (or (cdr (mac-ae-parameter ae nil "TEXT"))
- (error "No text in Apple event.")))
+(defun mac-ae-quit-application (event)
+ "Quit the application Emacs with the Apple event EVENT."
+ (interactive "e")
+ (let ((ae (mac-event-ae event)))
+ (unwind-protect
+ (save-buffers-kill-emacs)
+ ;; Reaches here if the user has canceled the quit.
+ (mac-resume-apple-event ae -128)))) ; userCanceledErr
(defun mac-ae-get-url (event)
"Open the URL specified by the Apple event EVENT.
(let* ((ae (mac-event-ae event))
(parsed-url (url-generic-parse-url (mac-ae-text ae))))
(if (string= (url-type parsed-url) "mailto")
- (url-mailto parsed-url)
- (error "Unsupported URL scheme: %s" (url-type parsed-url)))))
+ (progn
+ (url-mailto parsed-url)
+ (select-frame-set-input-focus (selected-frame)))
+ (mac-resume-apple-event ae t))))
(setq mac-apple-event-map (make-sparse-keymap))
'mac-ae-open-documents)
(define-key mac-apple-event-map [core-event show-preferences] 'customize)
(define-key mac-apple-event-map [core-event quit-application]
- 'save-buffers-kill-emacs)
+ 'mac-ae-quit-application)
(define-key mac-apple-event-map [internet-event get-url] 'mac-ae-get-url)
-(define-key mac-apple-event-map [hicommand about] 'display-splash-screen)
+(define-key mac-apple-event-map [hi-command about] 'display-splash-screen)
;;; Converted Carbon Events
(defun mac-handle-toolbar-switch-mode (event)
frame where the tool-bar toggle button was pressed. With some
modifiers, it changes global tool-bar visibility setting."
(interactive "e")
- (let* ((ae (mac-event-ae event))
- (modifiers (cdr (mac-ae-parameter ae "kmod"))))
- (if (and modifiers (not (string= modifiers "\000\000\000\000")))
+ (let ((ae (mac-event-ae event)))
+ (if (mac-ae-keyboard-modifiers ae)
;; Globally toggle tool-bar-mode if some modifier key is pressed.
(tool-bar-mode)
- (let ((window-id (mac-bytes-to-digits (cdr (mac-ae-parameter ae))))
- (rest (frame-list))
- frame)
- (while (and (null frame) rest)
- (if (string= (frame-parameter (car rest) 'window-id) window-id)
- (setq frame (car rest)))
- (setq rest (cdr rest)))
+ (let ((frame (mac-ae-frame ae)))
(set-frame-parameter frame 'tool-bar-lines
(if (= (frame-parameter frame 'tool-bar-lines) 0)
1 0))))))
'mac-handle-toolbar-switch-mode)
;;; Font panel
-(when (fboundp 'mac-set-font-panel-visibility)
+(when (fboundp 'mac-set-font-panel-visible-p)
(define-minor-mode mac-font-panel-mode
"Toggle use of the font panel.
-With numeric ARG, display the panel bar if and only if ARG is positive."
+With numeric ARG, display the font panel if and only if ARG is positive."
:init-value nil
:global t
:group 'mac
- (mac-set-font-panel-visibility mac-font-panel-mode))
+ (mac-set-font-panel-visible-p mac-font-panel-mode))
(defun mac-handle-font-panel-closed (event)
"Update internal status in response to font panel closed EVENT."
"Change default face attributes according to font selection EVENT."
(interactive "e")
(let* ((ae (mac-event-ae event))
- (fm-font-size (cdr (mac-ae-parameter ae "fmsz")))
- (atsu-font-id (cdr (mac-ae-parameter ae "auid")))
- (attribute-values (gethash atsu-font-id mac-atsu-font-table)))
+ (fm-font-size (mac-ae-number ae "fmsz"))
+ (atsu-font-id (mac-ae-number ae "auid"))
+ (attribute-values (and atsu-font-id
+ (mac-atsu-font-face-attributes atsu-font-id))))
(if fm-font-size
(setq attribute-values
- `(:height ,(* 10 (mac-bytes-to-integer fm-font-size))
- ,@attribute-values)))
+ `(:height ,(* 10 fm-font-size) ,@attribute-values)))
(apply 'set-face-attribute 'default (selected-frame) attribute-values)))
;; kEventClassFont/kEventFontPanelClosed
'mac-handle-font-panel-closed)
;; kEventClassFont/kEventFontSelection
(define-key mac-apple-event-map [font selection] 'mac-handle-font-selection)
+(define-key mac-apple-event-map [hi-command show-hide-font-panel]
+ 'mac-font-panel-mode)
(define-key-after menu-bar-showhide-menu [mac-font-panel-mode]
(menu-bar-make-mm-toggle mac-font-panel-mode
"Show the font panel as a floating dialog")
'showhide-speedbar)
-) ;; (fboundp 'mac-set-font-panel-visibility)
+) ;; (fboundp 'mac-set-font-panel-visible-p)
+
+;;; Text Services
+(defvar mac-ts-active-input-buf ""
+ "Byte sequence of the current Mac TSM active input area.")
+(defvar mac-ts-update-active-input-area-seqno 0
+ "Number of processed update-active-input-area events.")
+(setq mac-ts-active-input-overlay (make-overlay 0 0))
+
+(defface mac-ts-caret-position
+ '((t :inverse-video t))
+ "Face for caret position in Mac TSM active input area.
+This is used when the active input area is displayed either in
+the echo area or in a buffer where the cursor is not displayed."
+ :group 'mac)
+
+(defface mac-ts-raw-text
+ '((t :underline t))
+ "Face for raw text in Mac TSM active input area."
+ :group 'mac)
+
+(defface mac-ts-selected-raw-text
+ '((t :underline t))
+ "Face for selected raw text in Mac TSM active input area."
+ :group 'mac)
+
+(defface mac-ts-converted-text
+ '((((background dark)) :underline "gray20")
+ (t :underline "gray80"))
+ "Face for converted text in Mac TSM active input area."
+ :group 'mac)
+
+(defface mac-ts-selected-converted-text
+ '((t :underline t))
+ "Face for selected converted text in Mac TSM active input area."
+ :group 'mac)
+
+(defface mac-ts-block-fill-text
+ '((t :underline t))
+ "Face for block fill text in Mac TSM active input area."
+ :group 'mac)
+
+(defface mac-ts-outline-text
+ '((t :underline t))
+ "Face for outline text in Mac TSM active input area."
+ :group 'mac)
+
+(defface mac-ts-selected-text
+ '((t :underline t))
+ "Face for selected text in Mac TSM active input area."
+ :group 'mac)
+
+(defface mac-ts-no-hilite
+ '((t :inherit default))
+ "Face for no hilite in Mac TSM active input area."
+ :group 'mac)
+
+(defconst mac-ts-hilite-style-faces
+ '((2 . mac-ts-raw-text) ; kTSMHiliteRawText
+ (3 . mac-ts-selected-raw-text) ; kTSMHiliteSelectedRawText
+ (4 . mac-ts-converted-text) ; kTSMHiliteConvertedText
+ (5 . mac-ts-selected-converted-text) ; kTSMHiliteSelectedConvertedText
+ (6 . mac-ts-block-fill-text) ; kTSMHiliteBlockFillText
+ (7 . mac-ts-outline-text) ; kTSMHiliteOutlineText
+ (8 . mac-ts-selected-text) ; kTSMHiliteSelectedText
+ (9 . mac-ts-no-hilite)) ; kTSMHiliteNoHilite
+ "Alist of Mac TSM hilite style vs Emacs face.")
+
+(defun mac-ts-update-active-input-buf (text fix-len hilite-rng update-rng)
+ (let ((buf-len (length mac-ts-active-input-buf))
+ confirmed)
+ (if (or (null update-rng)
+ (/= (% (length update-rng) 2) 0))
+ ;; The parameter is missing (or in a bad format). The
+ ;; existing inline input session is completely replaced with
+ ;; the new text.
+ (setq mac-ts-active-input-buf text)
+ ;; Otherwise, the current subtext specified by the (2*j)-th
+ ;; range is replaced with the new subtext specified by the
+ ;; (2*j+1)-th range.
+ (let ((tail buf-len)
+ (i (length update-rng))
+ segments rng)
+ (while (> i 0)
+ (setq i (- i 2))
+ (setq rng (aref update-rng i))
+ (if (and (<= 0 (cadr rng)) (< (cadr rng) tail)
+ (<= tail buf-len))
+ (setq segments
+ (cons (substring mac-ts-active-input-buf (cadr rng) tail)
+ segments)))
+ (setq tail (car rng))
+ (setq rng (aref update-rng (1+ i)))
+ (if (and (<= 0 (car rng)) (< (car rng) (cadr rng))
+ (<= (cadr rng) (length text)))
+ (setq segments
+ (cons (substring text (car rng) (cadr rng))
+ segments))))
+ (if (and (< 0 tail) (<= tail buf-len))
+ (setq segments
+ (cons (substring mac-ts-active-input-buf 0 tail)
+ segments)))
+ (setq mac-ts-active-input-buf (apply 'concat segments))))
+ (setq buf-len (length mac-ts-active-input-buf))
+ ;; Confirm (a part of) inline input session.
+ (cond ((< fix-len 0)
+ ;; Entire inline session is being confirmed.
+ (setq confirmed mac-ts-active-input-buf)
+ (setq mac-ts-active-input-buf ""))
+ ((= fix-len 0)
+ ;; None of the text is being confirmed (yet).
+ (setq confirmed ""))
+ (t
+ (if (> fix-len buf-len)
+ (setq fix-len buf-len))
+ (setq confirmed (substring mac-ts-active-input-buf 0 fix-len))
+ (setq mac-ts-active-input-buf
+ (substring mac-ts-active-input-buf fix-len))))
+ (setq buf-len (length mac-ts-active-input-buf))
+ ;; Update highlighting and the caret position in the new inline
+ ;; input session.
+ (remove-text-properties 0 buf-len '(cursor nil) mac-ts-active-input-buf)
+ (mapc (lambda (rng)
+ (cond ((and (= (nth 2 rng) 1) ; kTSMHiliteCaretPosition
+ (<= 0 (car rng)) (< (car rng) buf-len))
+ (put-text-property (car rng) buf-len
+ 'cursor t mac-ts-active-input-buf))
+ ((and (<= 0 (car rng)) (< (car rng) (cadr rng))
+ (<= (cadr rng) buf-len))
+ (put-text-property (car rng) (cadr rng) 'face
+ (cdr (assq (nth 2 rng)
+ mac-ts-hilite-style-faces))
+ mac-ts-active-input-buf))))
+ hilite-rng)
+ confirmed))
+
+(defun mac-split-string-by-property-change (string)
+ (let ((tail (length string))
+ head result)
+ (unless (= tail 0)
+ (while (setq head (previous-property-change tail string)
+ result (cons (substring string (or head 0) tail) result)
+ tail head)))
+ result))
+
+(defun mac-replace-untranslated-utf-8-chars (string &optional to-string)
+ (or to-string (setq to-string "\e$,3u=\e(B"))
+ (mapconcat
+ (lambda (str)
+ (if (get-text-property 0 'untranslated-utf-8 str) to-string str))
+ (mac-split-string-by-property-change string)
+ ""))
+
+(defun mac-keyboard-translate-char (ch)
+ (if (and (char-valid-p ch)
+ (or (char-table-p keyboard-translate-table)
+ (and (or (stringp keyboard-translate-table)
+ (vectorp keyboard-translate-table))
+ (> (length keyboard-translate-table) ch))))
+ (or (aref keyboard-translate-table ch) ch)
+ ch))
+
+(defun mac-unread-string (string)
+ ;; Unread characters and insert them in a keyboard macro being
+ ;; defined.
+ (apply 'isearch-unread
+ (mapcar 'mac-keyboard-translate-char
+ (mac-replace-untranslated-utf-8-chars string))))
+
+(defun mac-ts-update-active-input-area (event)
+ "Update Mac TSM active input area according to EVENT.
+The confirmed text is converted to Emacs input events and pushed
+into `unread-command-events'. The unconfirmed text is displayed
+either in the current buffer or in the echo area."
+ (interactive "e")
+ (let* ((ae (mac-event-ae event))
+ (type-text (mac-ae-parameter ae "tstx"))
+ (text (or (cdr type-text) ""))
+ (decode-fun (if (equal (car type-text) "TEXT")
+ 'mac-TEXT-to-string 'mac-utxt-to-string))
+ (script-language (mac-ae-script-language ae "tssl"))
+ (coding (or (cdr (assq (car script-language)
+ mac-script-code-coding-systems))
+ 'mac-roman))
+ (fix-len (mac-ae-number ae "tsfx"))
+ ;; Optional parameters
+ (hilite-rng (mac-ae-text-range-array ae "tshi"))
+ (update-rng (mac-ae-text-range-array ae "tsup"))
+ ;;(pin-rng (mac-bytes-to-text-range (cdr (mac-ae-parameter ae "tspn" "txrn"))))
+ ;;(clause-offsets (cdr (mac-ae-parameter ae "tscl" "ofay")))
+ (seqno (mac-ae-number ae "tsSn"))
+ confirmed)
+ (unless (= seqno mac-ts-update-active-input-area-seqno)
+ ;; Reset internal states if sequence number is out of sync.
+ (setq mac-ts-active-input-buf ""))
+ (setq confirmed
+ (mac-ts-update-active-input-buf text fix-len hilite-rng update-rng))
+ (let ((use-echo-area
+ (or isearch-mode
+ (and cursor-in-echo-area (current-message))
+ ;; Overlay strings are not shown in some cases.
+ (get-char-property (point) 'invisible)
+ (and (not (bobp))
+ (or (and (get-char-property (point) 'display)
+ (eq (get-char-property (1- (point)) 'display)
+ (get-char-property (point) 'display)))
+ (and (get-char-property (point) 'composition)
+ (eq (get-char-property (1- (point)) 'composition)
+ (get-char-property (point) 'composition)))))))
+ active-input-string caret-seen)
+ ;; Decode the active input area text with inheriting faces and
+ ;; the caret position.
+ (setq active-input-string
+ (mapconcat
+ (lambda (str)
+ (let ((decoded (funcall decode-fun str coding)))
+ (put-text-property 0 (length decoded) 'face
+ (get-text-property 0 'face str) decoded)
+ (when (and (not caret-seen)
+ (get-text-property 0 'cursor str))
+ (setq caret-seen t)
+ (if (or use-echo-area (null cursor-type))
+ (put-text-property 0 1 'face 'mac-ts-caret-position
+ decoded)
+ (put-text-property 0 1 'cursor t decoded)))
+ decoded))
+ (mac-split-string-by-property-change mac-ts-active-input-buf)
+ ""))
+ (put-text-property 0 (length active-input-string)
+ 'mac-ts-active-input-string t active-input-string)
+ (if use-echo-area
+ (let ((msg (current-message))
+ message-log-max)
+ (if (and msg
+ ;; Don't get confused by previously displayed
+ ;; `active-input-string'.
+ (null (get-text-property 0 'mac-ts-active-input-string
+ msg)))
+ (setq msg (propertize msg 'display
+ (concat msg active-input-string)))
+ (setq msg active-input-string))
+ (message "%s" msg)
+ (overlay-put mac-ts-active-input-overlay 'before-string nil))
+ (move-overlay mac-ts-active-input-overlay
+ (point) (point) (current-buffer))
+ (overlay-put mac-ts-active-input-overlay 'before-string
+ active-input-string))
+ (mac-unread-string (funcall decode-fun confirmed coding)))
+ ;; The event is successfully processed. Sync the sequence number.
+ (setq mac-ts-update-active-input-area-seqno (1+ seqno))))
+
+(defun mac-ts-unicode-for-key-event (event)
+ "Convert Unicode key EVENT to Emacs key events and unread them."
+ (interactive "e")
+ (let* ((ae (mac-event-ae event))
+ (text (cdr (mac-ae-parameter ae "tstx" "utxt")))
+ (script-language (mac-ae-script-language ae "tssl"))
+ (coding (or (cdr (assq (car script-language)
+ mac-script-code-coding-systems))
+ 'mac-roman)))
+ (if text
+ (mac-unread-string (mac-utxt-to-string text coding)))))
+
+;; kEventClassTextInput/kEventTextInputUpdateActiveInputArea
+(define-key mac-apple-event-map [text-input update-active-input-area]
+ 'mac-ts-update-active-input-area)
+;; kEventClassTextInput/kEventTextInputUnicodeForKeyEvent
+(define-key mac-apple-event-map [text-input unicode-for-key-event]
+ 'mac-ts-unicode-for-key-event)
;;; Services
-(defun mac-services-open-file ()
+(defun mac-service-open-file ()
"Open the file specified by the selection value for Services."
(interactive)
- (find-file-existing (x-selection-value mac-services-selection)))
+ (find-file-existing (x-selection-value mac-service-selection)))
-(defun mac-services-open-selection ()
+(defun mac-service-open-selection ()
"Create a new buffer containing the selection value for Services."
(interactive)
(switch-to-buffer (generate-new-buffer "*untitled*"))
- (insert (x-selection-value mac-services-selection))
+ (insert (x-selection-value mac-service-selection))
(sit-for 0)
(save-buffer) ; It pops up the save dialog.
)
-(defun mac-services-mail-selection ()
+(defun mac-service-mail-selection ()
"Prepare a mail buffer containing the selection value for Services."
(interactive)
(compose-mail)
(rfc822-goto-eoh)
(forward-line 1)
- (insert (x-selection-value mac-services-selection) "\n"))
+ (insert (x-selection-value mac-service-selection) "\n"))
-(defun mac-services-mail-to ()
+(defun mac-service-mail-to ()
"Prepare a mail buffer to be sent to the selection value for Services."
(interactive)
- (compose-mail (x-selection-value mac-services-selection)))
+ (compose-mail (x-selection-value mac-service-selection)))
-(defun mac-services-insert-text ()
+(defun mac-service-insert-text ()
"Insert the selection value for Services."
(interactive)
- (let ((text (x-selection-value mac-services-selection)))
+ (let ((text (x-selection-value mac-service-selection)))
(if (not buffer-read-only)
(insert text)
(kill-new text)
(substitute-command-keys
"The text from the Services menu can be accessed with \\[yank]")))))
-(define-key mac-apple-event-map [services paste] 'mac-services-insert-text)
-(define-key mac-apple-event-map [services perform open-file]
- 'mac-services-open-file)
-(define-key mac-apple-event-map [services perform open-selection]
- 'mac-services-open-selection)
-(define-key mac-apple-event-map [services perform mail-selection]
- 'mac-services-mail-selection)
-(define-key mac-apple-event-map [services perform mail-to]
- 'mac-services-mail-to)
+;; kEventClassService/kEventServicePaste
+(define-key mac-apple-event-map [service paste] 'mac-service-insert-text)
+;; kEventClassService/kEventServicePerform
+(define-key mac-apple-event-map [service perform open-file]
+ 'mac-service-open-file)
+(define-key mac-apple-event-map [service perform open-selection]
+ 'mac-service-open-selection)
+(define-key mac-apple-event-map [service perform mail-selection]
+ 'mac-service-mail-selection)
+(define-key mac-apple-event-map [service perform mail-to]
+ 'mac-service-mail-to)
(defun mac-dispatch-apple-event (event)
"Dispatch EVENT according to the keymap `mac-apple-event-map'."
(interactive "e")
(let* ((binding (lookup-key mac-apple-event-map (mac-event-spec event)))
- (service-message
- (and (keymapp binding)
- (cdr (mac-ae-parameter (mac-event-ae event) "svmg")))))
+ (ae (mac-event-ae event))
+ (service-message (and (keymapp binding)
+ (cdr (mac-ae-parameter ae "svmg")))))
(when service-message
(setq service-message
(intern (decode-coding-string service-message 'utf-8)))
;; Replace (cadr event) with a dummy position so that event-start
;; returns it.
(setcar (cdr event) (list (selected-window) (point) '(0 . 0) 0))
- (call-interactively binding)))
+ (if (null (mac-ae-parameter ae 'emacs-suspension-id))
+ (command-execute binding nil (vector event) t)
+ (condition-case err
+ (progn
+ (command-execute binding nil (vector event) t)
+ (mac-resume-apple-event ae))
+ (error
+ (mac-ae-set-reply-parameter ae "errs"
+ (cons "TEXT" (error-message-string err)))
+ (mac-resume-apple-event ae -10000)))))) ; errAEEventFailed
-(global-set-key [mac-apple-event] 'mac-dispatch-apple-event)
+(define-key special-event-map [mac-apple-event] 'mac-dispatch-apple-event)
;; Processing of Apple events are deferred at the startup time. For
;; example, files dropped onto the Emacs application icon can only be
;; the files should be opened.
(add-hook 'after-init-hook 'mac-process-deferred-apple-events)
+(run-with-idle-timer 5 t 'mac-cleanup-expired-apple-events)
+
\f
;;;; Drag and drop
("TIFF" . mac-dnd-insert-TIFF))
"Which function to call to handle a drop of that type.
The function takes three arguments, WINDOW, ACTION and DATA.
-WINDOW is where the drop occured, ACTION is always `private' on
+WINDOW is where the drop occurred, ACTION is always `private' on
Mac. DATA is the drop data. Unlike the x-dnd counterpart, the
return value of the function is not significant.
(defun mac-dnd-insert-TIFF (window action data)
(dnd-insert-text window action (mac-TIFF-to-string data)))
-(defun mac-dnd-drop-data (event frame window data type)
+(defun mac-dnd-drop-data (event frame window data type &optional action)
+ (or action (setq action 'private))
(let* ((type-info (assoc type mac-dnd-types-alist))
(handler (cdr type-info))
- (action 'private)
(w (posn-window (event-start event))))
(when handler
- (if (and (windowp w) (window-live-p w)
+ (if (and (window-live-p w)
(not (window-minibuffer-p w))
(not (window-dedicated-p w)))
;; If dropping in an ordinary window which we could use,
;; let dnd-open-file-other-window specify what to do.
(progn
- (goto-char (posn-point (event-start event)))
+ (when (not mouse-yank-at-point)
+ (goto-char (posn-point (event-start event))))
(funcall handler window action data))
;; If we can't display the file here,
;; make a new window for it.
(defun mac-dnd-handle-drag-n-drop-event (event)
"Receive drag and drop events."
(interactive "e")
- (let ((window (posn-window (event-start event))))
+ (let ((window (posn-window (event-start event)))
+ (ae (mac-event-ae event))
+ action)
(when (windowp window) (select-window window))
- (dolist (item (mac-ae-list (mac-event-ae event)))
+ (if (memq 'option (mac-ae-keyboard-modifiers ae))
+ (setq action 'copy))
+ (dolist (item (mac-ae-list ae))
(if (not (equal (car item) "null"))
(mac-dnd-drop-data event (selected-frame) window
- (cdr item) (car item)))))
- (select-frame-set-input-focus (selected-frame)))
+ (cdr item) (car item) action)))))
\f
-;;; Do the actual Windows setup here; the above code just defines
-;;; functions and variables that we use now.
-
-(setq command-line-args (x-handle-args command-line-args))
-
-;;; Make sure we have a valid resource name.
-(or (stringp x-resource-name)
- (let (i)
- (setq x-resource-name (invocation-name))
-
- ;; Change any . or * characters in x-resource-name to hyphens,
- ;; so as not to choke when we use it in X resource queries.
- (while (setq i (string-match "[.*]" x-resource-name))
- (aset x-resource-name i ?-))))
-
-(if (x-display-list)
- ;; On Mac OS 8/9, Most coding systems used in code conversion for
- ;; font names are not ready at the time when the terminal frame is
- ;; created. So we reconstruct font name table for the initial
- ;; frame.
- (mac-clear-font-name-table)
- (x-open-connection "Mac"
- x-command-line-resources
- ;; Exit Emacs with fatal error if this fails.
- t))
-
-(setq frame-creation-function 'x-create-frame-with-faces)
-
(defvar mac-font-encoder-list
'(("mac-roman" mac-roman-encoder
ccl-encode-mac-roman-font "%s")
(fontset-add-mac-fonts fontset t)
fontset))
+(defun x-win-suspend-error ()
+ (error "Suspending an Emacs running under Mac makes no sense"))
+
+(defalias 'x-cut-buffer-or-selection-value 'x-get-selection-value)
+
+(defvar mac-initialized nil
+ "Non-nil if the w32 window system has been initialized.")
+
+(defun mac-initialize-window-system ()
+ "Initialize Emacs for Mac GUI frames."
+
+;;; Do the actual Windows setup here; the above code just defines
+;;; functions and variables that we use now.
+
+(setq command-line-args (x-handle-args command-line-args))
+
+;;; Make sure we have a valid resource name.
+(or (stringp x-resource-name)
+ (let (i)
+ (setq x-resource-name (invocation-name))
+
+ ;; Change any . or * characters in x-resource-name to hyphens,
+ ;; so as not to choke when we use it in X resource queries.
+ (while (setq i (string-match "[.*]" x-resource-name))
+ (aset x-resource-name i ?-))))
+
+(if (x-display-list)
+ ;; On Mac OS 8/9, Most coding systems used in code conversion for
+ ;; font names are not ready at the time when the terminal frame is
+ ;; created. So we reconstruct font name table for the initial
+ ;; frame.
+ (mac-clear-font-name-table)
+ (x-open-connection "Mac"
+ x-command-line-resources
+ ;; Exit Emacs with fatal error if this fails.
+ t))
+
+(add-hook 'suspend-hook 'x-win-suspend-error)
+
+;;; Arrange for the kill and yank functions to set and check the clipboard.
+(setq interprogram-cut-function 'x-select-text)
+(setq interprogram-paste-function 'x-get-selection-value)
+
+
+
+
+;;; Turn off window-splitting optimization; Mac is usually fast enough
+;;; that this is only annoying.
+(setq split-window-keep-point t)
+
+;; Don't show the frame name; that's redundant.
+(setq-default mode-line-frame-identification " ")
+
+;; Turn on support for mouse wheels.
+(mouse-wheel-mode 1)
+
+
+;; Enable CLIPBOARD copy/paste through menu bar commands.
+(menu-bar-enable-clipboard)
+
+
+;; Initiate drag and drop
+
+(define-key special-event-map [drag-n-drop] 'mac-dnd-handle-drag-n-drop-event)
+
+\f
+;;;; Non-toolkit Scroll bars
+
+(unless x-toolkit-scroll-bars
+
+;; for debugging
+;; (defun mac-handle-scroll-bar-event (event) (interactive "e") (princ event))
+
+;;(global-set-key [vertical-scroll-bar mouse-1] 'mac-handle-scroll-bar-event)
+
+(global-set-key
+ [vertical-scroll-bar down-mouse-1]
+ 'mac-handle-scroll-bar-event)
+
+(global-unset-key [vertical-scroll-bar drag-mouse-1])
+(global-unset-key [vertical-scroll-bar mouse-1])
+
;; Adjust Courier font specifications in x-fixed-font-alist.
(let ((courier-fonts (assoc "Courier" x-fixed-font-alist)))
(if courier-fonts
;; Setup the default fontset.
(setup-default-fontset)
-(cond ((x-list-fonts "*-iso10646-1")
+(cond ((x-list-fonts "*-iso10646-1" nil nil 1)
;; Use ATSUI (if available) for the following charsets.
(dolist
(charset '(latin-iso8859-1
vietnamese-viscii-lower vietnamese-viscii-upper
lao ethiopic tibetan))
(set-fontset-font nil charset '(nil . "iso10646-1"))))
- ((null (x-list-fonts "*-iso8859-1"))
+ ((null (x-list-fonts "*-iso8859-1" nil nil 1))
;; Add Mac-encoding fonts unless ETL fonts are installed.
(fontset-add-mac-fonts "fontset-default")))
(cons '(user-size . t) parsed))))
;; All geometry parms apply to the initial frame.
(setq initial-frame-alist (append initial-frame-alist parsed))
- ;; The size parms apply to all frames.
- (if (assq 'height parsed)
+ ;; The size parms apply to all frames. Don't set it if there are
+ ;; sizes there already (from command line).
+ (if (and (assq 'height parsed)
+ (not (assq 'height default-frame-alist)))
(setq default-frame-alist
(cons (cons 'height (cdr (assq 'height parsed)))
default-frame-alist)))
- (if (assq 'width parsed)
+ (if (and (assq 'width parsed)
+ (not (assq 'width default-frame-alist)))
(setq default-frame-alist
(cons (cons 'width (cdr (assq 'width parsed)))
default-frame-alist))))))
(setq default-frame-alist
(cons '(reverse . t) default-frame-alist)))))
-(defun x-win-suspend-error ()
- (error "Suspending an Emacs running under Mac makes no sense"))
-(add-hook 'suspend-hook 'x-win-suspend-error)
-
-;;; Arrange for the kill and yank functions to set and check the clipboard.
-(setq interprogram-cut-function 'x-select-text)
-(setq interprogram-paste-function 'x-get-selection-value)
-
-(defalias 'x-cut-buffer-or-selection-value 'x-get-selection-value)
-
-;;; Turn off window-splitting optimization; Mac is usually fast enough
-;;; that this is only annoying.
-(setq split-window-keep-point t)
-
-;; Don't show the frame name; that's redundant.
-(setq-default mode-line-frame-identification " ")
-
-;; Turn on support for mouse wheels.
-(mouse-wheel-mode 1)
-
-
-;; Enable CLIPBOARD copy/paste through menu bar commands.
-(menu-bar-enable-clipboard)
-
-;; Initiate drag and drop
-
-(global-set-key [drag-n-drop] 'mac-dnd-handle-drag-n-drop-event)
-(global-set-key [M-drag-n-drop] 'mac-dnd-handle-drag-n-drop-event)
-
-\f
-;;;; Non-toolkit Scroll bars
-
-(unless x-toolkit-scroll-bars
-
-;; for debugging
-;; (defun mac-handle-scroll-bar-event (event) (interactive "e") (princ event))
-
-;;(global-set-key [vertical-scroll-bar mouse-1] 'mac-handle-scroll-bar-event)
-
-(global-set-key
- [vertical-scroll-bar down-mouse-1]
- 'mac-handle-scroll-bar-event)
-
-(global-unset-key [vertical-scroll-bar drag-mouse-1])
-(global-unset-key [vertical-scroll-bar mouse-1])
+(setq mac-initialized t)))
(defun mac-handle-scroll-bar-event (event)
"Handle scroll bar EVENT to emulate Mac Toolbox style scrolling."
(mac-scroll-ignore-events)
(scroll-up 1)))
-)
\f
;;;; Others
;; or bold bitmap versions will not display these variants correctly.
(setq scalable-fonts-allowed t)
+(add-to-list 'handle-args-function-alist '(mac . x-handle-args))
+(add-to-list 'frame-creation-function-alist '(mac . x-create-frame-with-faces))
+(add-to-list 'window-system-initialization-alist '(mac . mac-initialize-window-system))
+
+(provide 'mac-win)
+
;; arch-tag: 71dfcd14-cde8-4d66-b05c-85ec94fb23a6
;;; mac-win.el ends here