changeset 71175:ed68e074ebb4

(mac-ts-active-input-overlay): Add defvar. (mac-ae-number, mac-ae-frame, mac-ae-script-language) (mac-bytes-to-text-range, mac-ae-text-range-array) (mac-ts-update-active-input-buf, mac-split-string-by-property-change) (mac-replace-untranslated-utf-8-chars, mac-ts-update-active-input-area) (mac-ts-unicode-for-key-event): New functions. (mac-handle-toolbar-switch-mode): Use mac-ae-frame. (mac-handle-font-selection): Use mac-ae-number. (mac-ts-active-input-buf, mac-ts-update-active-input-area-seqno): New variables. (mac-ts-caret-position, mac-ts-raw-text, mac-ts-selected-raw-text) (mac-ts-converted-text, mac-ts-selected-converted-text) (mac-ts-block-fill-text, mac-ts-outline-text) (mac-ts-selected-text, mac-ts-no-hilite): New faces. (mac-ts-hilite-style-faces): New constant. (mac-apple-event-map): Bind text input events. (mac-dispatch-apple-event): Use command-execute instead of call-interactively. (global-map): Don't bind mac-apple-event. (special-event-map): Bind mac-apple-event.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Sat, 03 Jun 2006 02:31:51 +0000
parents aedf192fdf04
children 18dfea3e3203
files lisp/term/mac-win.el
diffstat 1 files changed, 327 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/term/mac-win.el	Fri Jun 02 21:35:39 2006 +0000
+++ b/lisp/term/mac-win.el	Sat Jun 03 02:31:51 2006 +0000
@@ -84,6 +84,7 @@
 (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)
@@ -1570,6 +1571,15 @@
 		(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")))
+	(string-to-number str)
+      nil)))
+
 (defun mac-bytes-to-integer (bytes &optional from to)
   (or from (setq from 0))
   (or to (setq to (length bytes)))
@@ -1610,6 +1620,65 @@
     (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))
+
 (defun mac-ae-open-documents (event)
   "Open the documents specified by the Apple event EVENT."
   (interactive "e")
@@ -1637,10 +1706,6 @@
 	      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-get-url (event)
   "Open the URL specified by the Apple event EVENT.
 Currently the `mailto' scheme is supported."
@@ -1685,14 +1750,7 @@
     (if (and modifiers (not (string= modifiers "\000\000\000\000")))
 	;; Globally toggle tool-bar-mode if some modifier key is pressed.
 	(tool-bar-mode)
-      (let ((window-id
-	     (mac-coerce-ae-data "long" (cdr (mac-ae-parameter ae)) "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)))
+      (let ((frame (mac-ae-frame ae)))
 	(set-frame-parameter frame 'tool-bar-lines
 			     (if (= (frame-parameter frame 'tool-bar-lines) 0)
 				 1 0))))))
@@ -1722,13 +1780,12 @@
   "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")))
+	 (fm-font-size (mac-ae-number ae "fmsz"))
 	 (atsu-font-id (cdr (mac-ae-parameter ae "auid")))
 	 (attribute-values (gethash atsu-font-id mac-atsu-font-table)))
     (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
@@ -1745,6 +1802,258 @@
 
 ) ;; (fboundp 'mac-set-font-panel-visibility)
 
+;;; 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 only when the active input area is displayed in the
+echo area."
+  :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 "$,3u=(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-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))
+	 (text (or (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))
+	 (fix-len (mac-bytes-to-integer
+		   (cdr (mac-ae-parameter ae "tsfx" "long"))))
+	 ;; 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) 'display)
+	       (get-char-property (point) 'invisible)
+	       (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 (mac-utxt-to-string 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 use-echo-area
+		       (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 message-log-max)
+	    (if (and (current-message)
+		     ;; Don't get confused by previously displayed
+		     ;; `active-input-string'.
+		     (null (get-text-property 0 'mac-ts-active-input-string
+					      (current-message))))
+		(setq msg (propertize (current-message) 'display
+				      (concat (current-message)
+					      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))
+      ;; Unread confirmed characters and insert them in a keyboard
+      ;; macro being defined.
+      (apply 'isearch-unread
+	     (append (mac-replace-untranslated-utf-8-chars
+		      (mac-utxt-to-string 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)))
+    ;; Unread characters and insert them in a keyboard macro being
+    ;; defined.
+    (apply 'isearch-unread
+	   (append (mac-replace-untranslated-utf-8-chars
+		    (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-service-open-file ()
   "Open the file specified by the selection value for Services."
@@ -1811,17 +2120,17 @@
     ;; returns it.
     (setcar (cdr event) (list (selected-window) (point) '(0 . 0) 0))
     (if (null (mac-ae-parameter ae 'emacs-suspension-id))
-	(call-interactively binding)
+	(command-execute binding nil (vector event) t)
       (condition-case err
 	  (progn
-	    (call-interactively binding)
+	    (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