Skip to content

Instantly share code, notes, and snippets.

@rzl24ozi
Last active August 29, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rzl24ozi/68c29ac4fe64f1aa8887 to your computer and use it in GitHub Desktop.
Save rzl24ozi/68c29ac4fe64f1aa8887 to your computer and use it in GitHub Desktop.
add w32-ime support to emacs with Windows GUI and various modifications
--- ./configure.ac.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./configure.ac 2015-04-11 07:27:30.430112300 +0900
@@ -263,6 +263,12 @@
OPTION_DEFAULT_OFF([ns],[use NeXTstep (Cocoa or GNUstep) windowing system])
OPTION_DEFAULT_OFF([w32], [use native MS Windows GUI in a Cygwin build])
+OPTION_DEFAULT_ON([w32-ime], [don't compile with W32-IME support])
+OPTION_DEFAULT_ON([reconversion], [don't compile with RECONVERSION support])
+OPTION_DEFAULT_ON([documentfeed], [don't compile with DOCUMENTFEED support])
+
+OPTION_DEFAULT_ON([cmigemo], [don't compile with CMIGEMO support])
+
OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console])
OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
OPTION_DEFAULT_ON([gconf],[don't compile with GConf support])
@@ -2236,7 +2242,7 @@
### Use -lrsvg-2 if available, unless `--with-rsvg=no' is specified.
HAVE_RSVG=no
-if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${opsys}" = "mingw32"; then
+if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" = "yes"; then
if test "${with_rsvg}" != "no"; then
RSVG_REQUIRED=2.11.0
RSVG_MODULE="librsvg-2.0 >= $RSVG_REQUIRED"
@@ -5006,6 +5012,50 @@
acl_summary=no
fi
+USE_W32_IME=no
+if test "${HAVE_W32}" = "yes"; then
+ if test "${with_w32_ime}" != "no"; then
+ USE_W32_IME=yes
+ AC_DEFINE(USE_W32_IME, 1, [Define to support W32-IME.])
+
+ RECONVERSION=no
+ if test "${with_reconversion}" != "no"; then
+ AC_CACHE_CHECK([whether RECONVERTSTRING is declared],
+ emacs_cv_have_reconvertstring,
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <windows.h>
+#include <imm.h>]], [[RECONVERTSTRING]])],
+ emacs_cv_have_reconvertstring=yes, emacs_cv_have_reconvertstring=no)])
+ if test "$emacs_cv_have_reconvertstring" = "yes"; then
+ RECONVERSION=yes
+ AC_DEFINE(RECONVERSION, 1, [Define to support RECONVERSION.])
+ AC_DEFINE(HAVE_RECONVERTSTRING, 1, [Define to 1 if you have RECONVERTSTRING.])
+
+ DOCUMENTFEED=no
+ if test "${with_documentfeed}" != "no"; then
+ AC_CHECK_DECL(IMR_DOCUMENTFEED, HAVE_IMR_DOCUMENTFEED=yes,
+ HAVE_IMR_DOCUMENTFEED=no,[[
+#include <windows.h>
+#include <imm.h>]])
+ if test "$ac_cv_have_decl_IMR_DOCUMENTFEED" = "yes"; then
+ DOCUMENTFEED=yes
+ AC_DEFINE(DOCUMENTFEED, 1, [Define to support DOCUMENTFEED.])
+ AC_DEFINE(HAVE_IMR_DOCUMENTFEED, 1, [Define to 1 if you have IMR_DOCUMENTFEED.])
+ fi
+ fi
+ fi
+ fi
+ fi
+fi
+
+HAVE_CMIGEMO=no
+if test "${with_cmigemo}" != "no"; then
+ AC_CHECK_HEADER(migemo.h, HAVE_CMIGEMO=yes)
+ if test "${HAVE_CMIGEMO}" = "yes"; then
+ AC_DEFINE(HAVE_CMIGEMO, 1, [Define to 1 if you have the "migemo.h" header file.])
+ fi
+fi
+
echo "
Configured for \`${canonical}'.
@@ -5056,6 +5106,20 @@
echo " Does Emacs directly use zlib? ${HAVE_ZLIB}"
echo " Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}"
+
+if test "${HAVE_W32}" = "yes"; then
+ echo \
+ " Does Emacs support W32-IME? ${USE_W32_IME}"
+ if test "${USE_W32_IME}" = "yes"; then
+ echo \
+ " Does Emacs support RECONVERSION? ${RECONVERSION}"
+ if test "${RECONVERSION}" = "yes"; then
+ echo \
+ " Does Emacs support DOCUMENTFEED? ${DOCUMENTFEED}"
+ fi
+ fi
+fi
+echo " Does Emacs use a cmigemo library? ${HAVE_CMIGEMO}"
echo
if test -n "${EMACSDATA}"; then
--- ./lib-src/make-docfile.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./lib-src/make-docfile.c 2015-04-11 07:27:30.436116800 +0900
@@ -50,6 +50,7 @@
#endif /* WINDOWSNT */
#ifdef DOS_NT
+#include <mbstring.h>
/* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this
is really just insurance.
@@ -209,10 +210,18 @@
{
char *tmp;
+#ifdef DOS_NT
+ for (tmp = filename; *tmp; tmp = _mbsinc (tmp))
+#else
for (tmp = filename; *tmp; tmp++)
+#endif
{
if (IS_DIRECTORY_SEP (*tmp))
+#ifdef DOS_NT
+ filename = _mbsinc (tmp);
+#else
filename = tmp + 1;
+#endif
}
putc (037, outfile);
--- ./lib-src/ntlib.c.orig 2015-02-02 02:27:17.000000000 +0900
+++ ./lib-src/ntlib.c 2015-04-11 07:27:30.445112900 +0900
@@ -370,7 +370,7 @@
}
else
{
- if (IS_DIRECTORY_SEP (name[len-1]))
+ if (IS_DIRECTORY_SEP (*_mbsdec(name, name + len)))
name[len - 1] = 0;
fh = FindFirstFile (name, &wfd);
--- ./lib-src/ntlib.h.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./lib-src/ntlib.h 2015-04-11 07:27:30.453111600 +0900
@@ -90,6 +90,7 @@
#define locking _locking
#define logb _logb
#define _longjmp longjmp
+#undef lseek
#define lseek _lseek
#define popen _popen
#define pclose _pclose
--- ./lisp/cedet/cedet-cscope.el.orig 2015-02-02 02:27:17.000000000 +0900
+++ ./lisp/cedet/cedet-cscope.el 2015-04-11 07:27:30.477113600 +0900
@@ -77,7 +77,7 @@
"Create a CScope database at the current directory.
FLAGS are additional flags to pass to cscope beyond the
options -cR."
- (cedet-cscope-call (append (list "-cR") flags)))
+ (cedet-cscope-call (append (list "-bcR") flags)))
(defun cedet-cscope-call (flags)
"Call CScope with the list of FLAGS."
@@ -151,7 +151,7 @@
nil)
(with-current-buffer b
(goto-char (point-min))
- (re-search-forward "cscope: version \\([0-9.]+\\)" nil t)
+ (re-search-forward "cscope\\(?:\\.exe\\)?: version \\([0-9.]+\\)" nil t)
(setq rev (match-string 1))
(if (inversion-check-version rev nil cedet-cscope-min-version)
(if noerror
--- ./lisp/image.el.orig 2015-02-02 02:27:17.000000000 +0900
+++ ./lisp/image.el 2015-04-11 07:27:30.481113200 +0900
@@ -126,6 +126,15 @@
:type '(repeat (choice directory variable))
:initialize 'custom-initialize-delay)
+;;;###autoload
+(defcustom image-fit-option-alist nil
+ "Alist of (IMAGE-TYPE . FIT-OPTION) pairs used by image loader to specify image size.
+the FIT-OPTION is one of 'never, 'frame, 'width-or-height, 'width or 'height.
+Note: All image loaders are not supporting this `fit' capability.
+"
+ :type 'sexp
+ :initialize 'custom-initialize-default
+ :group 'image)
(defun image-load-path-for-library (library image &optional path no-error)
"Return a suitable search path for images used by LIBRARY.
--- /dev/null 2015-04-11 07:27:55.000000000 +0900
+++ ./lisp/international/w32-ime.el 2015-04-11 07:27:30.485113300 +0900
@@ -0,0 +1,201 @@
+;;;;; w32-ime.el ---- Meadow features for NTEmacs.
+;;
+;; Author H.Miyashita
+;;
+;;;;;
+
+(defgroup W32-IME nil
+ "w32-ime"
+ :group 'emacs)
+
+(defvar w32-last-selection nil
+ "It is stored the last data from Emacs.")
+
+;----------
+
+(defvar w32-ime-on-hook nil
+ "Functions to eval when IME is turned on at least.
+Even if IME state is not changed, these functiona are maybe called.")
+(defvar w32-ime-off-hook nil
+ "Functions to eval when IME is turned off at least.
+Even if IME state is not changed, these functiona are maybe called.")
+(defvar w32-ime-buffer-switch-p t
+ "If this variable is nil, IME control when buffer is switched is disabled.")
+(defvar w32-ime-show-mode-line t
+ "When t, mode line indicates IME state.")
+(defvar w32-ime-mode-line-state-indicator "[O]"
+ "This is shown at the mode line. It is regarded as state of ime.")
+(make-variable-buffer-local 'w32-ime-mode-line-state-indicator)
+(put 'w32-ime-mode-line-state-indicator 'permanent-local t)
+(defvar w32-ime-mode-line-state-indicator-list '("-" "[|]" "[O]")
+ "List of IME state indicator string.")
+(defvar w32-ime-mode-line-format-original nil
+ "Original mode line format.")
+
+;;
+;; Section: IME
+;;
+
+;; ;; This is temporal solution. In the future, we will prepare
+;; ;; dynamic configuration.
+;; (defvar w32-ime-coding-system-language-environment-alist
+;; '(("Japanese" . japanese-shift-jis)
+;; ("Chinese-GB" . chinese-iso-8bit)
+;; ("Chinese-BIG5" . chinese-big5)
+;; ("Korean" . korean-iso-8bit)))
+
+;;
+;; IME state indicator
+;;
+(global-set-key [kanji] 'ignore)
+(global-set-key [compend] 'ignore)
+
+(defun wrap-function-to-control-ime
+ (function interactive-p interactive-arg &optional suffix)
+ "Wrap FUNCTION, and IME control is enabled when FUNCTION is called.
+An original function is saved to FUNCTION-SUFFIX when suffix is string.
+If SUFFIX is nil, \"-original\" is added. "
+ (let ((original-function
+ (intern (concat (symbol-name function)
+ (if suffix suffix "-original")))))
+ (cond
+ ((not (fboundp original-function))
+ (fset original-function
+ (symbol-function function))
+ (fset function
+ (list
+ 'lambda '(&rest arguments)
+ (when interactive-p
+ (list 'interactive interactive-arg))
+ `(cond
+ ((and (ime-get-mode)
+ (equal current-input-method "W32-IME"))
+ (ime-force-off)
+ (unwind-protect
+ (apply ',original-function arguments)
+ (when (and (not (ime-get-mode))
+ (equal current-input-method "W32-IME"))
+ (ime-force-on))))
+ (t
+ (apply ',original-function arguments)))))))))
+
+(defvar w32-ime-toroku-region-yomigana nil
+ "* if this variable is string, toroku-region regard this value as yomigana.")
+
+(defun w32-ime-toroku-region (begin end)
+ (interactive "r")
+ (let ((string (buffer-substring begin end))
+ (w32-ime-buffer-switch-p nil)
+ (reading w32-ime-toroku-region-yomigana))
+ (unless (stringp reading)
+ (w32-set-ime-mode 'hiragana)
+ (setq reading
+ (read-multilingual-string
+ (format "Input reading of \"%s\": " string) nil "W32-IME")))
+ (w32-ime-register-word-dialog reading string)))
+
+;; for IME management system.
+
+(defun w32-ime-sync-state (window)
+ (when w32-ime-buffer-switch-p
+ (with-current-buffer (window-buffer window)
+ (let* ((frame (window-frame window))
+ (ime-state (ime-get-mode)))
+ (cond
+ ((and (not ime-state)
+ (equal current-input-method "W32-IME"))
+ (ime-force-on nil)
+ (run-hooks 'w32-ime-on-hook))
+ ((and ime-state
+ (not (equal current-input-method "W32-IME")))
+;;; (when (= (w32-ime-undetermined-string-length) 0)
+ (ime-force-off nil)
+ (run-hooks 'w32-ime-off-hook)))))))
+
+(defun w32-ime-set-selected-window-buffer-hook (oldbuf newwin newbuf)
+ (w32-ime-sync-state newwin))
+
+(defun w32-ime-select-window-hook (old new)
+ (w32-ime-sync-state new))
+
+(defun w32-ime-mode-line-update ()
+ (cond
+ (w32-ime-show-mode-line
+ (unless (window-minibuffer-p (selected-window))
+ (setq w32-ime-mode-line-state-indicator
+ (nth (if (ime-get-mode) 1 2)
+ w32-ime-mode-line-state-indicator-list))))
+ (t
+ (setq w32-ime-mode-line-state-indicator
+ (nth 0 w32-ime-mode-line-state-indicator-list))))
+ (force-mode-line-update))
+
+(defun w32-ime-init-mode-line-display ()
+ (unless (member 'w32-ime-mode-line-state-indicator mode-line-format)
+ (setq w32-ime-mode-line-format-original
+ (default-value 'mode-line-format))
+ (if (and (stringp (car mode-line-format))
+ (string= (car mode-line-format) "-"))
+ (setq-default mode-line-format
+ (cons ""
+ (cons 'w32-ime-mode-line-state-indicator
+ (cdr mode-line-format))))
+ (setq-default mode-line-format
+ (cons ""
+ (cons 'w32-ime-mode-line-state-indicator
+ mode-line-format))))
+ (force-mode-line-update t)))
+
+(defun w32-ime-initialize ()
+ (when (and (or (eq system-type 'windows-nt) (eq system-type 'cygwin))
+ (eq window-system 'w32)
+ (featurep 'w32-ime))
+ (w32-ime-init-mode-line-display)
+ (w32-ime-mode-line-update)
+ (add-hook 'select-window-functions
+ 'w32-ime-select-window-hook)
+ (add-hook 'set-selected-window-buffer-functions
+ 'w32-ime-set-selected-window-buffer-hook)
+ (define-key global-map [kanji] 'toggle-input-method)))
+;; (set-keyboard-coding-system 'utf-8)))
+
+(defun w32-ime-uninitialize ()
+ (when (and (or (eq system-type 'windows-nt) (eq system-type 'cygwin))
+ (eq window-system 'w32)
+ (featurep 'w32-ime))
+ (setq-default mode-line-format
+ w32-ime-mode-line-format-original)
+ (force-mode-line-update t)
+ (remove-hook 'select-window-functions
+ 'w32-ime-select-window-hook)
+ (remove-hook 'set-selected-window-buffer-functions
+ 'w32-ime-set-selected-window-buffer-hook)
+ (define-key global-map [kanji] 'ignore)))
+
+(defun w32-ime-exit-from-minibuffer ()
+ (deactivate-input-method)
+ (when (<= (minibuffer-depth) 1)
+ (remove-hook 'minibuffer-exit-hook 'w32-ime-exit-from-minibuffer)))
+
+(defun w32-ime-state-switch (&optional arg)
+ (if arg
+ (progn
+ (setq deactivate-current-input-method-function
+ 'w32-ime-state-switch)
+ (run-hooks 'input-method-activate-hook)
+ (run-hooks 'w32-ime-on-hook)
+ (setq describe-current-input-method-function nil)
+ (when (eq (selected-window) (minibuffer-window))
+ (add-hook 'minibuffer-exit-hook 'w32-ime-exit-from-minibuffer))
+ (ime-force-on))
+ (setq current-input-method nil)
+ (run-hooks 'input-method-deactivate-hook)
+ (run-hooks 'w32-ime-off-hook)
+ (setq describe-current-input-method-function nil)
+ (ime-force-off))
+ (w32-ime-mode-line-update))
+
+(register-input-method "W32-IME" "Japanese" 'w32-ime-state-switch ""
+ "W32 System IME")
+
+(provide 'w32-ime)
--- ./lisp/language/japan-util.el.orig 2015-02-02 02:27:17.000000000 +0900
+++ ./lisp/language/japan-util.el 2015-04-11 07:27:30.491115400 +0900
@@ -31,9 +31,11 @@
(defun setup-japanese-environment-internal ()
;; By default, we use 'japanese-iso-8bit for file names. But, the
;; following prefer-coding-system will override it.
- (if (memq system-type '(windows-nt ms-dos cygwin))
+ (if (memq system-type '(windows-nt ms-dos))
(prefer-coding-system 'japanese-shift-jis)
- (prefer-coding-system 'japanese-iso-8bit))
+ (if (eq system-type 'cygwin)
+ (prefer-coding-system 'utf-8)
+ (prefer-coding-system 'japanese-iso-8bit)))
(use-cjk-char-width-table 'ja_JP))
(defconst japanese-kana-table
--- ./lisp/loadup.el.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./lisp/loadup.el 2015-04-11 07:27:30.494115700 +0900
@@ -250,6 +250,7 @@
(load "term/w32-win")
(load "disp-table")
(load "w32-common-fns")
+ (load "international/w32-ime")
(when (eq system-type 'windows-nt)
(load "w32-fns")
(load "ls-lisp")
--- ./lisp/startup.el.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./lisp/startup.el 2015-04-11 07:27:30.499116000 +0900
@@ -595,6 +595,7 @@
(put 'user-full-name 'standard-value
(list (default-value 'user-full-name)))
;; If the PWD environment variable isn't accurate, delete it.
+ (set-language-environment "japanese")
(let ((pwd (getenv "PWD")))
(and (stringp pwd)
;; Use FOO/., so that if FOO is a symlink, file-attributes
@@ -1630,7 +1631,7 @@
(defun fancy-splash-head ()
"Insert the head part of the splash screen into the current buffer."
(let* ((image-file (fancy-splash-image-file))
- (img (create-image image-file))
+ (img (create-image image-file nil nil :fit 'never))
(image-width (and img (car (image-size img))))
(window-width (window-width)))
(when img
--- ./nt/inc/sys/socket.h.orig 2015-02-02 02:27:17.000000000 +0900
+++ ./nt/inc/sys/socket.h 2015-04-11 07:27:30.502115800 +0900
@@ -99,7 +99,11 @@
#define recvfrom sys_recvfrom
#define sendto sys_sendto
+#ifdef __MINGW64__
+SOCKET sys_socket(int af, int type, int protocol);
+#else
int sys_socket(int af, int type, int protocol);
+#endif
int sys_bind (int s, const struct sockaddr *addr, int namelen);
int sys_connect (int s, const struct sockaddr *addr, int namelen);
u_short sys_htons (u_short hostshort);
--- /dev/null 2015-04-11 07:27:56.000000000 +0900
+++ ./sample/lisp/site-init.el 2015-04-11 07:27:30.510115100 +0900
@@ -0,0 +1,19 @@
+;;
+;; image options
+;;
+(setq image-library-alist
+ '((xpm "libxpm.dll" "xpm4.dll" "libXpm-nox4.dll")
+ (png "libpng14-14.dll" "libpng14.dll" "libpng15.dll")
+ (jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll"
+ "libjpeg-8.dll" "jpegdll.dll")
+ (tiff "libtiff3.dll" "libtiff.dll" "libtiff-3.dll")
+ (gif "giflib4.dll" "libungif4.dll" "libungif.dll")
+ (svg "librsvg-2-2.dll" "librsvg2.dll")
+ (gdk-pixbuf "libgdk_pixbuf-2.0-0.dll" "gdk_pixbuf-2-vs9.dll")
+ (glib "libglib-2.0-0.dll" "glib-2-vs9.dll" )
+ (gobject "libgobject-2.0-0.dll" "gobject-2-vs9.dll")))
+
+(setq image-fit-option-alist
+ '((jpeg . frame)
+ (svg . width-or-height)))
+
--- /dev/null 2015-04-11 07:27:57.000000000 +0900
+++ ./sample/lisp/site-start.el 2015-04-11 07:27:30.515116900 +0900
@@ -0,0 +1,10 @@
+;;
+;; create init.el for japanese user
+;;
+(when (and (not noninteractive)
+ (eq (window-system) 'w32)
+ (= (w32-get-default-locale-id) 1041)) ; japanese?
+ (add-hook 'after-init-hook
+ #'(lambda ()
+ (unless (file-exists-p user-init-file)
+ (load-library "ezsetup")))))
\ No newline at end of file
--- /dev/null 2015-04-11 07:27:57.000000000 +0900
+++ ./site-lisp/cmigemo.el 2015-04-11 07:27:30.524115400 +0900
@@ -0,0 +1,811 @@
+;;; migemo.el --- Japanese incremental search through dynamic pattern expansion
+
+;; $Id: migemo.el.in,v 1.9 2012/06/24 04:09:59 kaworu Exp $
+;; Copyright (C) Satoru Takabayashi
+
+;; Author: Satoru Takabayashi <satoru-t@is.aist-nara.ac.jp>
+;; URL: https://github.com/emacs-jp/migemo
+;; Version: 1.9
+;; Keywords:
+
+;; This file 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)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+(defgroup migemo nil
+ "migemo - Japanese incremental search trough dynamic pattern expansion."
+ :group 'matching)
+
+(defcustom migemo-cmigemo-library "cmigemo.dll"
+ "*Name or full path of the cmigemo dynamic library."
+ :group 'migemo
+ :type 'string)
+
+(defcustom migemo-command "ruby"
+ "*Name or full path of the executable for running migemo."
+ :group 'migemo
+ :type '(choice (const :tag "Ruby Migemo" "ruby")
+ (const :tag "CMIGEMO" "cmigemo")
+ (string :tag "Other")))
+
+;; -t emacs for specifying the type of regular expression.
+;; "-i" "\a" for searching a word over multi-lines.
+(defcustom migemo-options '("-S" "migemo" "-t" "emacs" "-i" "\a")
+ "*Options for migemo command."
+ :group 'migemo
+ :type '(repeat string))
+
+(defcustom migemo-white-space-regexp "[ ¡¡\t\r\n]*"
+ "*Regexp representing white spaces."
+ :group 'migemo
+ :type 'string)
+
+;; for C/Migemo
+;; (setq migemo-command "cmigemo")
+;; (setq migemo-options '("-q" "--emacs" "-i" "\g"))
+;; (setq migemo-dictionary "somewhere/migemo/euc-jp/migemo-dict")
+;; (setq migemo-user-dictionary nil)
+;; (setq migemo-regex-dictionary nil))
+
+(defcustom migemo-directory
+ (if (eq system-type 'windows-nt)
+ (concat data-directory "migemo")
+ "/usr/local/share/migemo")
+ "*Directory where migemo files are placed"
+ :group 'migemo
+ :type 'directory)
+
+(defcustom migemo-isearch-enable-p t
+ "*Enable the migemo feature on isearch or not."
+ :group 'migemo
+ :type 'boolean)
+
+(defcustom migemo-dictionary
+ (expand-file-name (concat "utf-8" "/migemo-dict") migemo-directory)
+ "*Migemo dictionary file."
+ :group 'migemo
+ :type '(file :must-match t))
+
+(defcustom migemo-user-dictionary nil
+ "*Migemo user dictionary file."
+ :group 'migemo
+ :type '(choice (file :must-match t)
+ (const :tag "Do not use" nil)))
+
+(defcustom migemo-regex-dictionary nil
+ "*Migemo regex dictionary file."
+ :group 'migemo
+ :type '(choice (file :must-match t)
+ (const :tag "Do not use" nil)))
+
+(defcustom migemo-pre-conv-function nil
+ "*Function of migemo pre-conversion."
+ :group 'migemo
+ :type '(choice (const :tag "Do not use" nil)
+ function))
+
+(defcustom migemo-after-conv-function nil
+ "*Function of migemo after-conversion."
+ :group 'migemo
+ :type '(choice (const :tag "Do not use" nil)
+ function))
+
+(defcustom migemo-coding-system
+ (with-no-warnings
+ (if (>= emacs-major-version 20)
+ (if (featurep 'mule)
+ (if (string-match "XEmacs" emacs-version)
+ (cond
+ ((memq 'euc-japan-unix (coding-system-list)) 'euc-japan-unix)
+ ((memq 'euc-jp-unix (coding-system-list)) 'euc-jp-unix))
+ 'euc-japan-unix))
+ (and (boundp 'MULE) *euc-japan*unix)))
+ "*Default coding system for migemo.el"
+ :group 'migemo
+ :type 'coding-system)
+
+(defcustom migemo-use-pattern-alist nil
+ "*Use pattern cache."
+ :group 'migemo
+ :type 'boolean)
+
+(defcustom migemo-use-frequent-pattern-alist nil
+ "*Use frequent patttern cache."
+ :group 'migemo
+ :type 'boolean)
+
+(defcustom migemo-pattern-alist-length 512
+ "*Maximal length of migemo-pattern-alist."
+ :group 'migemo
+ :type 'integer)
+
+(defcustom migemo-pattern-alist-file "~/.migemo-pattern"
+ "*Path of migemo alist file. If nil, don't save and restore the file."
+ :group 'migemo
+ :type 'file)
+
+(defcustom migemo-frequent-pattern-alist-file "~/.migemo-frequent"
+ "*Path of migemo frequent alist file. If nil, don't save and restore the file."
+ :group 'migemo
+ :type 'file)
+
+(defcustom migemo-accept-process-output-timeout-msec 5
+ "*Timeout of migemo process communication."
+ :group 'migemo
+ :type 'integer)
+
+(defcustom migemo-isearch-min-length 1
+ "*Minimum length of word to start isearch."
+ :group 'migemo
+ :type 'integer)
+
+(defconst migemo-mw32-input-method (and (featurep 'meadow) "MW32-IME")
+ "Support \"MW32-IME\" for Meadow.")
+
+;; internal variables
+(defvar migemo-process nil)
+(defvar migemo-buffer nil)
+(defvar migemo-current-input-method nil)
+(defvar migemo-search-pattern nil)
+(defvar migemo-pattern-alist nil)
+(defvar migemo-frequent-pattern-alist nil)
+(defconst migemo-emacs21p (and (> emacs-major-version 20) (not (featurep 'xemacs))))
+(defvar migemo-search-pattern-alist nil)
+(defvar migemo-do-isearch nil)
+(defvar cmigemo-initialized nil)
+
+(defconst coding-system-for-japanese
+ (let ((cs (cdr (assoc 'coding-system
+ (assoc "Japanese" language-info-alist)))))
+ (append
+ (mapcar
+ #'(lambda (c)
+ (intern-soft (concat (symbol-name c) "-unix"))) cs)
+ (mapcar
+ #'(lambda (c)
+ (intern-soft (concat (symbol-name c) "-dos"))) cs)
+ (mapcar
+ #'(lambda (c)
+ (intern-soft (concat (symbol-name c) "-mac"))) cs))))
+
+;; For warnings of byte-compile. Following functions are defined in XEmacs
+(declare-function set-process-input-coding-system "code-process")
+(declare-function set-process-output-coding-system "code-process")
+
+(defsubst migemo-search-pattern-get (string)
+ (let ((pattern (cdr (assoc string migemo-search-pattern-alist))))
+ (unless pattern
+ (setq pattern (migemo-get-pattern string))
+ (setq migemo-search-pattern-alist
+ (cons (cons string pattern)
+ migemo-search-pattern-alist)))
+ pattern))
+
+(defun migemo-toggle-isearch-enable ()
+ (interactive)
+ (setq migemo-isearch-enable-p (not migemo-isearch-enable-p))
+ (message (if migemo-isearch-enable-p
+ "t"
+ "nil")))
+
+(defun migemo-start-process (name buffer program args)
+ (let ((proc (apply 'start-process name buffer program args)))
+ (if (fboundp 'set-process-coding-system)
+ (set-process-coding-system proc
+ migemo-coding-system
+ migemo-coding-system)
+ (set-process-input-coding-system proc migemo-coding-system)
+ (set-process-output-coding-system proc migemo-coding-system))
+ proc))
+
+(defun migemo-init ()
+ (when (and migemo-use-frequent-pattern-alist
+ migemo-frequent-pattern-alist-file
+ (null migemo-frequent-pattern-alist))
+ (setq migemo-frequent-pattern-alist
+ (migemo-pattern-alist-load migemo-frequent-pattern-alist-file)))
+ (when (and migemo-use-pattern-alist
+ migemo-pattern-alist-file
+ (null migemo-pattern-alist))
+ (setq migemo-pattern-alist
+ (migemo-pattern-alist-load migemo-pattern-alist-file)))
+ ;; C/Migemo begin
+ (if (fboundp 'cmigemo-open)
+ (when (not cmigemo-initialized)
+ (setq cmigemo-initialized
+ (cmigemo-open migemo-dictionary))
+ (if (consp migemo-user-dictionary)
+ (dolist (d migemo-user-dictionary)
+ (cmigemo-load d))
+ (cmigemo-load migemo-user-dictionary)))
+ ;; !!!WARNING!!! the following block has original indent
+ (or (and migemo-process
+ (eq (process-status migemo-process) 'run))
+ (let ((options
+ (delq nil
+ (append migemo-options
+ (when (and migemo-user-dictionary
+ (file-exists-p migemo-user-dictionary))
+ (list "-u" migemo-user-dictionary))
+ (when (and migemo-regex-dictionary
+ (file-exists-p migemo-regex-dictionary))
+ (list "-r" migemo-regex-dictionary))
+ (list "-d" migemo-dictionary)))))
+ (setq migemo-buffer (get-buffer-create " *migemo*"))
+ (setq migemo-process (migemo-start-process
+ "migemo" migemo-buffer migemo-command options))
+ (set-process-query-on-exit-flag migemo-process nil)
+ t))))
+ ;; C/Migemo end
+
+(defun migemo-replace-in-string (string from to)
+ (with-temp-buffer
+ (insert string)
+ (goto-char (point-min))
+ (let ((migemo-do-isearch nil))
+ (while (search-forward from nil t)
+ (replace-match to nil t)))
+ (buffer-substring (point-min) (point-max))))
+
+(defun migemo-get-pattern (word)
+ (cond
+ ((< (length word) migemo-isearch-min-length)
+ "")
+ (t
+ (let (deactivate-mark pattern freq alst)
+ (set-text-properties 0 (length word) nil word)
+ (migemo-init)
+ (when (and migemo-pre-conv-function
+ (functionp migemo-pre-conv-function))
+ (setq word (funcall migemo-pre-conv-function word)))
+ (setq pattern
+ (cond
+ ((setq freq (and migemo-use-frequent-pattern-alist
+ (assoc word migemo-frequent-pattern-alist)))
+ (cdr freq))
+ ((setq alst (and migemo-use-pattern-alist
+ (assoc word migemo-pattern-alist)))
+ (setq migemo-pattern-alist (cons alst (delq alst migemo-pattern-alist)))
+ (cdr alst))
+ (t
+ ;; C/Migemo begin
+ (if (fboundp 'cmigemo-open)
+ (setq pattern (cmigemo-query word))
+ ;; !!!WARNING!!! the following block has original indent
+ (with-current-buffer (process-buffer migemo-process)
+ (delete-region (point-min) (point-max))
+ (process-send-string migemo-process (concat word "\n"))
+ (while (not (and (> (point-max) 1)
+ (eq (char-after (1- (point-max))) ?\n)))
+ (accept-process-output migemo-process
+ 0 migemo-accept-process-output-timeout-msec))
+ (setq pattern (buffer-substring (point-min) (1- (point-max))))))
+ ;; C/Migemo end
+ (when (and (memq system-type '(windows-nt OS/2 emx))
+ (> (length pattern) 1)
+ (eq ?\r (aref pattern (1- (length pattern)))))
+ (setq pattern (substring pattern 0 -1)))
+ (when migemo-use-pattern-alist
+ (setq migemo-pattern-alist
+ (cons (cons word pattern) migemo-pattern-alist))
+ (when (and migemo-pattern-alist-length
+ (> (length migemo-pattern-alist)
+ (* migemo-pattern-alist-length 2)))
+ (setcdr (nthcdr (1- (* migemo-pattern-alist-length 2))
+ migemo-pattern-alist) nil)))
+ pattern)))
+ (if (and migemo-after-conv-function
+ (functionp migemo-after-conv-function))
+ (funcall migemo-after-conv-function word pattern)
+ (migemo-replace-in-string pattern "\a" migemo-white-space-regexp))))))
+
+(defun migemo-pattern-alist-load (file)
+ "Load migemo alist file."
+ (setq file (expand-file-name file))
+ (when (file-readable-p file)
+ (with-temp-buffer
+ (let ((coding-system-for-read migemo-coding-system)
+ (buffer-file-coding-system migemo-coding-system)))
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (condition-case err
+ (read (current-buffer))
+ (error
+ (message "Error while reading %s; %s"
+ (file-name-nondirectory file)
+ (error-message-string err))
+ nil)))))
+
+(defun migemo-pattern-alist-save (&optional clear)
+ "Save migemo alist file."
+ (interactive)
+ (when (and migemo-use-pattern-alist
+ migemo-pattern-alist-file
+ (or migemo-pattern-alist clear))
+ (let ((file (expand-file-name migemo-pattern-alist-file)))
+ (when (file-writable-p file)
+ (when clear
+ (setq migemo-pattern-alist nil))
+ (when (and migemo-pattern-alist-length
+ (> (length migemo-pattern-alist) migemo-pattern-alist-length))
+ (setcdr (nthcdr (1- migemo-pattern-alist-length)
+ migemo-pattern-alist) nil))
+ (with-temp-buffer
+ (let ((coding-system-for-write migemo-coding-system)
+ (buffer-file-coding-system migemo-coding-system))
+ (if (fboundp 'pp)
+ (pp migemo-pattern-alist (current-buffer))
+ (prin1 migemo-pattern-alist (current-buffer)))
+ (write-region (point-min) (point-max) file nil 'nomsg)))
+ (setq migemo-pattern-alist nil)))))
+
+(defun migemo-kill ()
+ "Kill migemo process"
+ (interactive)
+ ;; C/Migemo begin
+ (if (fboundp 'cmigemo-open)
+ (when cmigemo-initialized
+ (cmigemo-close))
+ ;; !!!WARNING!!! the following block has original indent
+ (when (and migemo-process (eq (process-status migemo-process) 'run))
+ (kill-process migemo-process)
+ (setq migemo-process nil)
+ (when (get-buffer migemo-buffer)
+ (kill-buffer migemo-buffer)))))
+ ;; C/Migemo end
+
+(defun migemo-pattern-alist-clear ()
+ "Clear migemo alist data & file."
+ (interactive)
+ (migemo-kill)
+ (migemo-pattern-alist-save 'clear)
+ (migemo-init))
+
+(defun migemo-frequent-pattern-make (fcfile)
+ "Create frequent pattern from `frequent-chars'."
+ (interactive "ffrequent-chars: ")
+ (migemo-pattern-alist-save 'clear)
+ (when migemo-frequent-pattern-alist-file
+ (migemo-kill)
+ (migemo-init)
+ (let ((file (expand-file-name migemo-frequent-pattern-alist-file))
+ (migemo-use-pattern-alist nil)
+ (migemo-use-frequent-pattern-alist nil)
+ (migemo-after-conv-function (lambda (_x y) y))
+ word)
+ (setq migemo-frequent-pattern-alist nil)
+ (with-temp-buffer
+ (let ((coding-system-for-write migemo-coding-system)
+ (buffer-file-coding-system migemo-coding-system)))
+ (insert-file-contents fcfile)
+ (goto-char (point-min))
+ (message "Make frequently pattern...")
+ (while (not (eobp))
+ (when (looking-at "^[a-z]+$")
+ (setq word (match-string 0))
+ (message "Make frequently pattern...%s" word)
+ (setq migemo-frequent-pattern-alist
+ (cons (cons word (migemo-get-pattern word))
+ migemo-frequent-pattern-alist)))
+ (forward-line 1))
+ (when (file-writable-p file)
+ (setq migemo-frequent-pattern-alist
+ (nreverse migemo-frequent-pattern-alist))
+ (erase-buffer)
+ (if (fboundp 'pp)
+ (pp migemo-frequent-pattern-alist (current-buffer))
+ (prin1 migemo-frequent-pattern-alist (current-buffer)))
+ (write-region (point-min) (point-max) file nil 'nomsg)))
+ (migemo-kill)
+ (migemo-init)
+ (message "Make frequently pattern...done"))))
+
+(defun migemo-expand-pattern () "\
+Expand the Romaji sequences on the left side of the cursor
+into the migemo's regexp pattern."
+ (interactive)
+ (let ((pos (point)))
+ (goto-char (- pos 1))
+ (if (re-search-backward "[^-a-zA-Z]" (line-beginning-position) t)
+ (forward-char 1)
+ (beginning-of-line))
+ (let* ((str (buffer-substring-no-properties (point) pos))
+ (jrpat (migemo-get-pattern str)))
+ (delete-region (point) pos)
+ (insert jrpat))))
+
+(defun migemo-forward (word &optional bound noerror count)
+ (interactive "sSearch: \nP\nP")
+ (if (delq 'ascii (find-charset-string word))
+ (setq migemo-search-pattern word)
+ (setq migemo-search-pattern (migemo-search-pattern-get word)))
+ (search-forward-regexp migemo-search-pattern bound noerror count))
+
+(defun migemo-backward (word &optional bound noerror count)
+ (interactive "sSearch backward: \nP\nP")
+ (if (delq 'ascii (find-charset-string word))
+ (setq migemo-search-pattern word)
+ (setq migemo-search-pattern (migemo-search-pattern-get word)))
+ (if (null migemo-do-isearch)
+ (search-backward-regexp migemo-search-pattern bound noerror count)
+ (or (and (not (eq this-command 'isearch-repeat-backward))
+ (not (get-char-property (point) 'invisible (current-buffer)))
+ (or (and (looking-at migemo-search-pattern)
+ (match-beginning 0))
+ (and (not (eq (point) (point-min)))
+ (progn (forward-char -1)
+ (and (looking-at migemo-search-pattern)
+ (match-beginning 0))))))
+ (search-backward-regexp migemo-search-pattern bound noerror count))))
+
+;; experimental
+;; (define-key global-map "\M-;" 'migemo-dabbrev-expand)
+(defcustom migemo-dabbrev-display-message nil
+ "*Display dabbrev message to minibuffer."
+ :group 'migemo
+ :type 'boolean)
+
+(defcustom migemo-dabbrev-ol-face 'highlight
+ "*Face of migemo-dabbrev overlay."
+ :group 'migemo
+ :type 'face)
+
+(defvar migemo-dabbrev-pattern nil)
+(defvar migemo-dabbrev-start-point nil)
+(defvar migemo-dabbrev-search-point nil)
+(defvar migemo-dabbrev-pre-patterns nil)
+(defvar migemo-dabbrev-ol nil)
+(defun migemo-dabbrev-expand-done ()
+ (remove-hook 'pre-command-hook 'migemo-dabbrev-expand-done)
+ (unless (eq last-command this-command)
+ (setq migemo-search-pattern-alist nil)
+ (setq migemo-dabbrev-pre-patterns nil))
+ (when migemo-dabbrev-ol
+ (delete-overlay migemo-dabbrev-ol)))
+
+(defun migemo-dabbrev-expand ()
+ (interactive)
+ (let ((end-pos (point))
+ matched-start matched-string)
+ (if (eq last-command this-command)
+ (goto-char migemo-dabbrev-search-point)
+ (goto-char (- end-pos 1))
+ (if (re-search-backward "[^a-z-]" (line-beginning-position) t)
+ (forward-char 1)
+ (beginning-of-line))
+ (setq migemo-search-pattern-alist nil)
+ (setq migemo-dabbrev-start-point (point))
+ (setq migemo-dabbrev-search-point (point))
+ (setq migemo-dabbrev-pattern
+ (buffer-substring-no-properties (point) end-pos))
+ (setq migemo-dabbrev-pre-patterns nil))
+ (if (catch 'found
+ (while (if (> migemo-dabbrev-search-point migemo-dabbrev-start-point)
+ (and (migemo-forward migemo-dabbrev-pattern (point-max) t)
+ (setq migemo-dabbrev-search-point (match-end 0)))
+ (if (migemo-backward migemo-dabbrev-pattern (point-min) t)
+ (setq migemo-dabbrev-search-point (match-beginning 0))
+ (goto-char migemo-dabbrev-start-point)
+ (forward-word 1)
+ (message (format "Trun back for `%s'" migemo-dabbrev-pattern))
+ (and (migemo-forward migemo-dabbrev-pattern (point-max) t)
+ (setq migemo-dabbrev-search-point (match-end 0)))))
+ (setq matched-start (match-beginning 0))
+ (unless (re-search-forward ".\\>" (line-end-position) t)
+ (end-of-line))
+ (setq matched-string (buffer-substring-no-properties matched-start (point)))
+ (unless (member matched-string migemo-dabbrev-pre-patterns)
+ (let ((matched-end (point))
+ (str (copy-sequence matched-string))
+ lstart lend)
+ (if (and (pos-visible-in-window-p matched-start)
+ (pos-visible-in-window-p matched-end))
+ (progn
+ (if migemo-dabbrev-ol
+ (move-overlay migemo-dabbrev-ol matched-start (point))
+ (setq migemo-dabbrev-ol (make-overlay matched-start (point))))
+ (overlay-put migemo-dabbrev-ol 'evaporate t)
+ (overlay-put migemo-dabbrev-ol 'face migemo-dabbrev-ol-face))
+ (when migemo-dabbrev-ol
+ (delete-overlay migemo-dabbrev-ol))
+ (when migemo-dabbrev-display-message
+ (save-excursion
+ (save-restriction
+ (goto-char matched-start)
+ (setq lstart (progn (beginning-of-line) (point)))
+ (setq lend (progn (end-of-line) (point)))
+ (if migemo-emacs21p
+ (put-text-property 0 (length str)
+ 'face migemo-dabbrev-ol-face str)
+ (setq str (concat "¡Ú" str "¡Û")))
+ (message "(%d): %s%s%s"
+ (count-lines (point-min) matched-start)
+ (buffer-substring-no-properties lstart matched-start)
+ str
+ (buffer-substring-no-properties matched-end lend)))))))
+ (throw 'found t))
+ (goto-char migemo-dabbrev-search-point)))
+ (progn
+ (setq migemo-dabbrev-pre-patterns
+ (cons matched-string migemo-dabbrev-pre-patterns))
+ (delete-region migemo-dabbrev-start-point end-pos)
+ (forward-char 1)
+ (goto-char migemo-dabbrev-start-point)
+ (insert matched-string))
+ (goto-char end-pos)
+ (message (format "No dynamic expansion for `%s' found"
+ migemo-dabbrev-pattern)))
+ (add-hook 'pre-command-hook 'migemo-dabbrev-expand-done)))
+
+;; Use migemo-{forward,backward} instead of search-{forward,backward}.
+(defadvice isearch-search (around migemo-search-ad activate)
+ "adviced by migemo."
+ (when migemo-isearch-enable-p
+ (setq migemo-do-isearch t))
+ (unwind-protect
+ ad-do-it
+ (setq migemo-do-isearch nil)))
+
+(defadvice isearch-search-and-update (around migemo-search-ad activate)
+ "adviced by migemo."
+ (let ((isearch-adjusted isearch-adjusted))
+ (when (and migemo-isearch-enable-p
+ (not isearch-forward) (not isearch-regexp) (not isearch-word))
+ ;; don't use 'looking-at'
+ (setq isearch-adjusted t))
+ ad-do-it))
+
+(defadvice search-forward (around migemo-search-ad activate)
+ "adviced by migemo."
+ (if migemo-do-isearch
+ (setq ad-return-value
+ (migemo-forward (ad-get-arg 0) (ad-get-arg 1) (ad-get-arg 2) (ad-get-arg 3)))
+ ad-do-it))
+
+(defadvice search-backward (around migemo-search-ad activate)
+ "adviced by migemo."
+ (if migemo-do-isearch
+ (setq ad-return-value
+ (migemo-backward (ad-get-arg 0) (ad-get-arg 1) (ad-get-arg 2) (ad-get-arg 3)))
+ ad-do-it))
+
+(when (and (boundp 'isearch-regexp-lax-whitespace)
+ (fboundp 're-search-forward-lax-whitespace)
+ (fboundp 'search-forward-lax-whitespace))
+ (setq isearch-search-fun-function 'isearch-search-fun-migemo)
+
+ (defun isearch-search-fun-migemo ()
+ "Return default functions to use for the search with migemo."
+ (cond
+ (isearch-word
+ (lambda (string &optional bound noerror count)
+ ;; Use lax versions to not fail at the end of the word while
+ ;; the user adds and removes characters in the search string
+ ;; (or when using nonincremental word isearch)
+ (let* ((state-string-func (if (fboundp 'isearch--state-string)
+ 'isearch--state-string
+ 'isearch-string-state))
+ (lax (not (or isearch-nonincremental
+ (eq (length isearch-string)
+ (length (funcall state-string-func (car isearch-cmds))))))))
+ (funcall
+ (if isearch-forward #'re-search-forward #'re-search-backward)
+ (if (functionp isearch-word)
+ (funcall isearch-word string lax)
+ (word-search-regexp string lax))
+ bound noerror count))))
+ ((and isearch-regexp isearch-regexp-lax-whitespace
+ search-whitespace-regexp)
+ (if isearch-forward
+ 're-search-forward-lax-whitespace
+ 're-search-backward-lax-whitespace))
+ (isearch-regexp
+ (if isearch-forward 're-search-forward 're-search-backward))
+ ((and (if (boundp 'isearch-lax-whitespace) isearch-lax-whitespace t)
+ search-whitespace-regexp migemo-do-isearch)
+ (if isearch-forward 'migemo-forward 'migemo-backward))
+ ((and (if (boundp 'isearch-lax-whitespace) isearch-lax-whitespace t)
+ search-whitespace-regexp)
+ (if isearch-forward 'search-forward-lax-whitespace
+ 'search-backward-lax-whitespace))
+ (migemo-do-isearch
+ (if isearch-forward 'migemo-forward 'migemo-backward))
+ (t
+ (if isearch-forward 'search-forward 'search-backward))))
+ )
+
+(defun japanese-p (coding-system-list)
+ (cond ((atom coding-system-list) nil)
+ ((member (car coding-system-list)
+ coding-system-for-japanese)
+ t)
+ (t (japanese-p (cdr coding-system-list)))))
+
+;; Turn off input-method automatically when C-s or C-r are typed.
+(defadvice isearch-mode (before migemo-search-ad activate)
+ "adviced by migemo."
+ (unless (local-variable-p 'migemo-isearch-enable-p)
+ (set (make-local-variable 'migemo-isearch-enable-p)
+ (japanese-p (detect-coding-with-language-environment
+ (point-min) (point-max) "japanese"))))
+ (setq migemo-search-pattern nil)
+ (setq migemo-search-pattern-alist nil))
+
+(defadvice isearch-done (after migemo-search-ad activate)
+ "adviced by migemo."
+ (setq migemo-search-pattern nil)
+ (setq migemo-search-pattern-alist nil))
+
+(defcustom migemo-message-prefix-face 'highlight
+ "*Face of minibuffer prefix"
+ :group 'migemo
+ :type 'face)
+
+(defadvice isearch-message-prefix (after migemo-status activate)
+ "adviced by migemo."
+ (let ((ret ad-return-value)
+ (str "[MIGEMO]"))
+ (when migemo-emacs21p
+ (put-text-property 0 (length str) 'face migemo-message-prefix-face str))
+ (when (and migemo-isearch-enable-p
+ (not (or isearch-regexp isearch-word)))
+ (setq ad-return-value (concat str " " ret)))))
+
+;;;; for isearch-lazy-highlight (Emacs 21)
+;; Avoid byte compile warningsfor other emacsen
+(defvar isearch-lazy-highlight-wrapped)
+(defvar isearch-lazy-highlight-start)
+(defvar isearch-lazy-highlight-end)
+
+(defun migemo-isearch-lazy-highlight-search ()
+ "Search ahead for the next or previous match, for lazy highlighting.
+Attempt to do the search exactly the way the pending isearch would.
+This function used with Megemo feature."
+ (let ((case-fold-search isearch-case-fold-search)
+ (choices (cond (isearch-word
+ '(word-search-forward word-search-backward))
+ (isearch-regexp
+ '(re-search-forward re-search-backward))
+ (migemo-isearch-enable-p
+ '(re-search-forward re-search-backward t))
+ (t
+ '(search-forward search-backward))))
+ (pattern isearch-string))
+ (when (nth 2 choices)
+ (setq pattern (migemo-search-pattern-get isearch-string)))
+ (funcall (if isearch-forward
+ (nth 0 choices) (nth 1 choices))
+ pattern
+ (if isearch-forward
+ (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-start
+ (window-end))
+ (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-end
+ (window-start)))
+ t)))
+
+(when (fboundp 'isearch-lazy-highlight-search)
+ (defalias 'isearch-lazy-highlight-search 'migemo-isearch-lazy-highlight-search))
+
+;;;; for isearch-highlightify-region (XEmacs 21)
+(when (fboundp 'isearch-highlightify-region)
+ (defadvice isearch-highlightify-region (around migemo-highlightify-region
+ activate)
+ "adviced by migemo."
+ (if migemo-isearch-enable-p
+ (let ((isearch-string (migemo-search-pattern-get isearch-string))
+ (isearch-regexp t))
+ ad-do-it)
+ ad-do-it)))
+
+;; supports C-w C-d for GNU emacs only [migemo:00171]
+(when (and (not (featurep 'xemacs))
+ (fboundp 'isearch-yank-line))
+ (add-hook 'isearch-mode-hook
+ (lambda ()
+ (define-key isearch-mode-map "\C-d" 'migemo-isearch-yank-char)
+ (define-key isearch-mode-map "\C-w" 'migemo-isearch-yank-word)
+ (define-key isearch-mode-map "\C-y" 'migemo-isearch-yank-line)
+ (define-key isearch-mode-map "\M-m" 'migemo-isearch-toggle-migemo)))
+
+ (defun migemo-isearch-toggle-migemo ()
+ "Toggle migemo mode in isearch."
+ (interactive)
+ (unless (or isearch-regexp isearch-word)
+ (discard-input)
+ (setq migemo-isearch-enable-p (not migemo-isearch-enable-p)))
+ (when (fboundp 'isearch-lazy-highlight-new-loop)
+ (let ((isearch-lazy-highlight-last-string nil))
+ (condition-case nil
+ (isearch-lazy-highlight-new-loop)
+ (error
+ (isearch-lazy-highlight-new-loop nil nil)))))
+ (isearch-message))
+
+ (defun migemo-isearch-yank-char ()
+ "Pull next character from buffer into search string with migemo."
+ (interactive)
+ (when (and migemo-isearch-enable-p
+ (not isearch-regexp) isearch-other-end)
+ (setq isearch-string (buffer-substring-no-properties
+ isearch-other-end (point)))
+ (setq isearch-message isearch-string))
+ (let ((search-upper-case (unless migemo-isearch-enable-p
+ search-upper-case)))
+ (isearch-yank-string
+ (save-excursion
+ (and (not isearch-forward) isearch-other-end
+ (goto-char isearch-other-end))
+ (buffer-substring-no-properties (point)
+ (progn (forward-char 1) (point)))))))
+
+ (defun migemo-isearch-yank-word ()
+ "Pull next character from buffer into search string with migemo."
+ (interactive)
+ (when (and migemo-isearch-enable-p
+ (not isearch-regexp) isearch-other-end)
+ (setq isearch-string (buffer-substring-no-properties
+ isearch-other-end (point)))
+ (setq isearch-message isearch-string))
+ (let ((search-upper-case (unless migemo-isearch-enable-p
+ search-upper-case)))
+ (isearch-yank-string
+ (save-excursion
+ (and (not isearch-forward) isearch-other-end
+ (goto-char isearch-other-end))
+ (buffer-substring-no-properties (point)
+ (progn (forward-word 1) (point)))))))
+
+ (defun migemo-isearch-yank-line ()
+ "Pull next character from buffer into search string with migemo."
+ (interactive)
+ (when (and migemo-isearch-enable-p
+ (not isearch-regexp) isearch-other-end)
+ (setq isearch-string (buffer-substring-no-properties
+ isearch-other-end (point)))
+ (setq isearch-message isearch-string))
+ (let ((search-upper-case (unless migemo-isearch-enable-p
+ search-upper-case)))
+ (isearch-yank-string
+ (save-excursion
+ (and (not isearch-forward) isearch-other-end
+ (goto-char isearch-other-end))
+ (buffer-substring-no-properties (point)
+ (line-end-position))))))
+)
+
+(if (and (not (fboundp 'cmigemo-open))
+ (fboundp 'load-dynamic-library))
+ (load-dynamic-library migemo-cmigemo-library))
+
+(add-hook 'kill-emacs-hook 'migemo-pattern-alist-save)
+
+(provide 'cmigemo)
+
+;; sample
+;; 0123 abcd ABCD ¤Ò¤é¤¬¤Ê ¥«¥¿¥«¥Ê ´Á»ú !"[#\$]%^&_':`(;)<*=+>,?-@./{|}~
+
+;; Local Variables:
+;; coding: euc-japan-unix
+;; lexical-binding: t
+;; indent-tabs-mode: nil
+;; End:
+
+;;; migemo.el ends here
--- /dev/null 2015-04-11 07:27:57.000000000 +0900
+++ ./site-lisp/cp5022x.el 2015-04-11 07:27:30.531116300 +0900
@@ -0,0 +1,156 @@
+;;; cp5022x.el --- cp50220, cp50221, cp50222 coding system
+
+;; Copyright (C) 2008 ARISAWA Akihiro
+
+;; Author: ARISAWA Akihiro <ari@mbf.ocn.ne.jp>
+;; Keywords: languages, cp50220, cp50221, cp50222, cp51932, cp932
+
+;; This file 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 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This program requires Mule-6.0 or later.
+
+;;; Code:
+
+;; http://unicode.org/reports/tr30/datafiles/WidthFolding.txt
+(define-translation-table
+ 'cp50220-jisx0201-katakana-to-zenkaku
+ '(;; Half-width to generic width (singletons)
+ (#xFF61 . #x3002) ;; 。 → 。 HALFWIDTH IDEOGRAPHIC FULL STOP → IDEOGRAPHIC FULL STOP
+ (#xFF62 . #x300C) ;; 「 → 「 HALFWIDTH LEFT CORNER BRACKET → LEFT CORNER BRACKET
+ (#xFF63 . #x300D) ;; 」 → 」 HALFWIDTH RIGHT CORNER BRACKET → RIGHT CORNER BRACKET
+ (#xFF64 . #x3001) ;; 、 → 、 HALFWIDTH IDEOGRAPHIC COMMA → IDEOGRAPHIC COMMA
+ ;; Half-witdh to generic Katakana (singletons)
+ (#xFF65 . #x30FB) ;; ・ → ・ HALFWIDTH KATAKANA MIDDLE DOT → KATAKANA MIDDLE DOT
+ (#xFF66 . #x30F2) ;; ヲ → ヲ HALFWIDTH KATAKANA LETTER WO → KATAKANA LETTER WO
+ (#xFF67 . #x30A1) ;; ァ → ァ HALFWIDTH KATAKANA LETTER SMALL A → KATAKANA LETTER SMALL A
+ (#xFF68 . #x30A3) ;; ィ → ィ HALFWIDTH KATAKANA LETTER SMALL I → KATAKANA LETTER SMALL I
+ (#xFF69 . #x30A5) ;; ゥ → ゥ HALFWIDTH KATAKANA LETTER SMALL U → KATAKANA LETTER SMALL U
+ (#xFF6A . #x30A7) ;; ェ → ェ HALFWIDTH KATAKANA LETTER SMALL E → KATAKANA LETTER SMALL E
+ (#xFF6B . #x30A9) ;; ォ → ォ HALFWIDTH KATAKANA LETTER SMALL O → KATAKANA LETTER SMALL O
+ (#xFF6C . #x30E3) ;; ャ → ャ HALFWIDTH KATAKANA LETTER SMALL YA → KATAKANA LETTER SMALL YA
+ (#xFF6D . #x30E5) ;; ュ → ュ HALFWIDTH KATAKANA LETTER SMALL YU → KATAKANA LETTER SMALL YU
+ (#xFF6E . #x30E7) ;; ョ → ョ HALFWIDTH KATAKANA LETTER SMALL YO → KATAKANA LETTER SMALL YO
+ (#xFF6F . #x30C3) ;; ッ → ッ HALFWIDTH KATAKANA LETTER SMALL TU → KATAKANA LETTER SMALL TU
+ (#xFF70 . #x30FC) ;; ー → ー HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK → KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ (#xFF71 . #x30A2) ;; ア → ア HALFWIDTH KATAKANA LETTER A → KATAKANA LETTER A
+ (#xFF72 . #x30A4) ;; イ → イ HALFWIDTH KATAKANA LETTER I → KATAKANA LETTER I
+ (#xFF73 . #x30A6) ;; ウ → ウ HALFWIDTH KATAKANA LETTER U → KATAKANA LETTER U
+ (#xFF74 . #x30A8) ;; エ → エ HALFWIDTH KATAKANA LETTER E → KATAKANA LETTER E
+ (#xFF75 . #x30AA) ;; オ → オ HALFWIDTH KATAKANA LETTER O → KATAKANA LETTER O
+ (#xFF76 . #x30AB) ;; カ → カ HALFWIDTH KATAKANA LETTER KA → KATAKANA LETTER KA
+ (#xFF77 . #x30AD) ;; キ → キ HALFWIDTH KATAKANA LETTER KI → KATAKANA LETTER KI
+ (#xFF78 . #x30AF) ;; ク → ク HALFWIDTH KATAKANA LETTER KU → KATAKANA LETTER KU
+ (#xFF79 . #x30B1) ;; ケ → ケ HALFWIDTH KATAKANA LETTER KE → KATAKANA LETTER KE
+ (#xFF7A . #x30B3) ;; コ → コ HALFWIDTH KATAKANA LETTER KO → KATAKANA LETTER KO
+ (#xFF7B . #x30B5) ;; サ → サ HALFWIDTH KATAKANA LETTER SA → KATAKANA LETTER SA
+ (#xFF7C . #x30B7) ;; シ → シ HALFWIDTH KATAKANA LETTER SI → KATAKANA LETTER SI
+ (#xFF7D . #x30B9) ;; ス → ス HALFWIDTH KATAKANA LETTER SU → KATAKANA LETTER SU
+ (#xFF7E . #x30BB) ;; セ → セ HALFWIDTH KATAKANA LETTER SE → KATAKANA LETTER SE
+ (#xFF7F . #x30BD) ;; ソ → ソ HALFWIDTH KATAKANA LETTER SO → KATAKANA LETTER SO
+ (#xFF80 . #x30BF) ;; タ → タ HALFWIDTH KATAKANA LETTER TA → KATAKANA LETTER TA
+ (#xFF81 . #x30C1) ;; チ → チ HALFWIDTH KATAKANA LETTER TI → KATAKANA LETTER TI
+ (#xFF82 . #x30C4) ;; ツ → ツ HALFWIDTH KATAKANA LETTER TU → KATAKANA LETTER TU
+ (#xFF83 . #x30C6) ;; テ → テ HALFWIDTH KATAKANA LETTER TE → KATAKANA LETTER TE
+ (#xFF84 . #x30C8) ;; ト → ト HALFWIDTH KATAKANA LETTER TO → KATAKANA LETTER TO
+ (#xFF85 . #x30CA) ;; ナ → ナ HALFWIDTH KATAKANA LETTER NA → KATAKANA LETTER NA
+ (#xFF86 . #x30CB) ;; ニ → ニ HALFWIDTH KATAKANA LETTER NI → KATAKANA LETTER NI
+ (#xFF87 . #x30CC) ;; ヌ → ヌ HALFWIDTH KATAKANA LETTER NU → KATAKANA LETTER NU
+ (#xFF88 . #x30CD) ;; ネ → ネ HALFWIDTH KATAKANA LETTER NE → KATAKANA LETTER NE
+ (#xFF89 . #x30CE) ;; ノ → ノ HALFWIDTH KATAKANA LETTER NO → KATAKANA LETTER NO
+ (#xFF8A . #x30CF) ;; ハ → ハ HALFWIDTH KATAKANA LETTER HA → KATAKANA LETTER HA
+ (#xFF8B . #x30D2) ;; ヒ → ヒ HALFWIDTH KATAKANA LETTER HI → KATAKANA LETTER HI
+ (#xFF8C . #x30D5) ;; フ → フ HALFWIDTH KATAKANA LETTER HU → KATAKANA LETTER HU
+ (#xFF8D . #x30D8) ;; ヘ → ヘ HALFWIDTH KATAKANA LETTER HE → KATAKANA LETTER HE
+ (#xFF8E . #x30DB) ;; ホ → ホ HALFWIDTH KATAKANA LETTER HO → KATAKANA LETTER HO
+ (#xFF8F . #x30DE) ;; マ → マ HALFWIDTH KATAKANA LETTER MA → KATAKANA LETTER MA
+ (#xFF90 . #x30DF) ;; ミ → ミ HALFWIDTH KATAKANA LETTER MI → KATAKANA LETTER MI
+ (#xFF91 . #x30E0) ;; ム → ム HALFWIDTH KATAKANA LETTER MU → KATAKANA LETTER MU
+ (#xFF92 . #x30E1) ;; メ → メ HALFWIDTH KATAKANA LETTER ME → KATAKANA LETTER ME
+ (#xFF93 . #x30E2) ;; モ → モ HALFWIDTH KATAKANA LETTER MO → KATAKANA LETTER MO
+ (#xFF94 . #x30E4) ;; ヤ → ヤ HALFWIDTH KATAKANA LETTER YA → KATAKANA LETTER YA
+ (#xFF95 . #x30E6) ;; ユ → ユ HALFWIDTH KATAKANA LETTER YU → KATAKANA LETTER YU
+ (#xFF96 . #x30E8) ;; ヨ → ヨ HALFWIDTH KATAKANA LETTER YO → KATAKANA LETTER YO
+ (#xFF97 . #x30E9) ;; ラ → ラ HALFWIDTH KATAKANA LETTER RA → KATAKANA LETTER RA
+ (#xFF98 . #x30EA) ;; リ → リ HALFWIDTH KATAKANA LETTER RI → KATAKANA LETTER RI
+ (#xFF99 . #x30EB) ;; ル → ル HALFWIDTH KATAKANA LETTER RU → KATAKANA LETTER RU
+ (#xFF9A . #x30EC) ;; レ → レ HALFWIDTH KATAKANA LETTER RE → KATAKANA LETTER RE
+ (#xFF9B . #x30ED) ;; ロ → ロ HALFWIDTH KATAKANA LETTER RO → KATAKANA LETTER RO
+ (#xFF9C . #x30EF) ;; ワ → ワ HALFWIDTH KATAKANA LETTER WA → KATAKANA LETTER WA
+ (#xFF9D . #x30F3) ;; ン → ン HALFWIDTH KATAKANA LETTER N → KATAKANA LETTER N
+; (#xFF9E . #x3099) ;; ゙ → ゙ HALFWIDTH KATAKANA VOICED SOUND MARK → COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+; (#xFF9F . #x309A) ;; ゚ → ゚ HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK → COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+ (#xFF9E . #x309B) ;; ゙ → ゛ HALFWIDTH KATAKANA VOICED SOUND MARK → KATAKANA-HIRAGANA VOICED SOUND MARK
+ (#xFF9F . #x309C) ;; ゚ → ゜ HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK → KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+ ))
+
+(define-coding-system 'cp50220
+ "CP50220 (Microsoft iso-2022-jp for mail)"
+ :coding-type 'iso-2022
+ :mnemonic ?J
+ :designation [(ascii japanese-jisx0208-1978 japanese-jisx0208
+ latin-jisx0201 katakana-jisx0201)
+ nil nil nil]
+ :flags '(short ascii-at-eol ascii-at-cntl 7-bit designation)
+ :charset-list '(ascii japanese-jisx0208
+ japanese-jisx0208-1978 latin-jisx0201
+ katakana-jisx0201)
+ :decode-translation-table '(cp51932-decode japanese-ucs-jis-to-cp932-map)
+ :encode-translation-table '(cp50220-jisx0201-katakana-to-zenkaku
+ cp51932-encode japanese-ucs-cp932-to-jis-map))
+
+(define-coding-system 'cp50221
+ "CP50221 (Microsoft iso-2022-jp)"
+ :coding-type 'iso-2022
+ :mnemonic ?J
+ :designation [(ascii japanese-jisx0208-1978 japanese-jisx0208
+ latin-jisx0201 katakana-jisx0201)
+ nil nil nil]
+ :flags '(short ascii-at-eol ascii-at-cntl 7-bit designation)
+ :charset-list '(ascii japanese-jisx0208
+ japanese-jisx0208-1978 latin-jisx0201
+ katakana-jisx0201)
+ :decode-translation-table '(cp51932-decode japanese-ucs-jis-to-cp932-map)
+ :encode-translation-table '(cp51932-encode japanese-ucs-cp932-to-jis-map))
+
+(define-coding-system 'cp50222
+ "CP50222 (Microsoft iso-2022-jp)"
+ :coding-type 'iso-2022
+ :mnemonic ?J
+ :designation [(ascii japanese-jisx0208-1978 japanese-jisx0208
+ latin-jisx0201)
+ katakana-jisx0201 nil nil]
+ :flags '(short ascii-at-eol ascii-at-cntl 7-bit designation)
+ :charset-list '(ascii japanese-jisx0208
+ japanese-jisx0208-1978 latin-jisx0201
+ katakana-jisx0201)
+ :decode-translation-table '(cp51932-decode japanese-ucs-jis-to-cp932-map)
+ :encode-translation-table '(cp51932-encode japanese-ucs-cp932-to-jis-map))
+
+(define-coding-system 'cp51932
+ "CP51932 (Microsoft euc-jp)"
+ :coding-type 'iso-2022
+ :mnemonic ?E
+ :designation [ascii japanese-jisx0208 katakana-jisx0201 nil]
+ :flags '(short ascii-at-eol ascii-at-cntl single-shift)
+ :charset-list '(ascii latin-jisx0201 japanese-jisx0208
+ katakana-jisx0201)
+ :decode-translation-table '(cp51932-decode japanese-ucs-jis-to-cp932-map)
+ :encode-translation-table '(cp51932-encode japanese-ucs-cp932-to-jis-map))
+
+(provide 'cp5022x)
+;;; cp5022x.el ends here
--- /dev/null 2015-04-11 07:27:58.000000000 +0900
+++ ./site-lisp/ezsetup.el 2015-04-11 07:27:30.542118200 +0900
@@ -0,0 +1,104 @@
+;;
+;;
+;;
+(when (and (= (w32-get-default-locale-id) 1041) ; japanese?
+ (not (file-exists-p user-init-file)))
+ (require 'cus-edit)
+ (let ((user-init-file
+ (expand-file-name "init.el" user-emacs-directory))
+ (cust-vars
+ `((default-frame-alist .
+ ,(cons
+ '(font . "fontset-std:std")
+ (cons '(ime-cursor-color . "SkyBlue")
+ default-frame-alist)))
+ (current-language-environment . "Japanese"))))
+
+ (mapc #'(lambda (l)
+ (let ((symbol (car l))
+ (value (cdr l)))
+ (put symbol 'saved-value
+ (list (custom-quote value)))))
+ cust-vars)
+
+ (with-temp-buffer
+ (if (member "Migu 1M" (font-family-list))
+ (insert ";;
+;; フォント
+;;
+(dolist (spec '((10 . \"small\")
+ (12 . \"std\")
+ (14 . \"large\")))
+
+ (let* ((ff \"Migu 1M\")
+ (sz (car spec))
+ (fs (create-fontset-from-ascii-font
+ (format \"-*-%s-normal-*-*-*-%g-*\" ff sz) nil ff)))
+
+ (dolist (sn '(katakana-jisx0201
+ japanese-jisx0208
+ japanese-jisx0212))
+ (set-fontset-font fs sn (cons ff \"iso10646-1\"))
+ (add-to-list 'fontset-alias-alist
+ (cons fs (format \"fontset-std:%s\" (cdr spec)))))))"))
+
+ (insert ";;
+;; 日本語コード
+;;
+(load-library \"ja-coding\")
+;;
+;; モードラインにIMEの状態を表示
+;;
+(setq-default w32-ime-mode-line-state-indicator \"[--]\")
+(setq w32-ime-mode-line-state-indicator-list '(\"[--]\" \"[あ]\" \"[--]\"))
+
+;;
+;; imeサポート セットアップ
+;;
+(w32-ime-initialize)
+(require 'smart-ime)
+
+;;
+;; MIGEMO
+;;
+(unless (boundp 'isearch-mode-map)
+ (load-library \"isearch\"))
+
+(dolist (key (where-is-internal
+ 'toggle-input-method global-map nil nil
+ (command-remapping 'toggle-input-method)))
+ (when (= (length key) 1)
+ (define-key isearch-mode-map
+ key 'migemo-isearch-toggle-migemo)))
+
+(require 'cmigemo)
+
+;;
+(custom-set-variables)
+
+;; カーソル色
+;; custom-variableの値を使うのでこの位置に記述する
+(add-hook 'w32-ime-on-hook
+ `(lambda () (set-cursor-color ,(frame-parameter nil 'ime-cursor-color))))
+(add-hook 'w32-ime-off-hook
+ `(lambda () (set-cursor-color ,(frame-parameter nil 'cursor-color))))")
+ (set-buffer-file-coding-system 'utf-8)
+ (custom-save-variables)
+ (write-file (expand-file-name "init.el" user-emacs-directory)))
+ (load-file user-init-file)
+
+ (save-window-excursion
+ (with-temp-buffer
+ (pop-to-buffer (current-buffer))
+ (insert "設定ファイル ~/.emacs.d/init.elを作成しました。
+以下のカスタム変数を設定しました。これらの変数は
+M-x customize-variable<ENTER>
+の後に変数名を入力し、変更することができます。\n")
+ (mapc #'(lambda (l)
+ (insert
+ (format "%s: %s\n" (car l) (symbol-value (car l)))))
+ cust-vars)
+ (insert "何かキーを押してください。")
+ (read-char "? ")))))
+
+
--- /dev/null 2015-04-11 07:27:58.000000000 +0900
+++ ./site-lisp/ja-coding.el 2015-04-11 07:27:30.547117100 +0900
@@ -0,0 +1,81 @@
+;; http://nijino.homelinux.net/emacs/emacs23-ja.html
+(cond
+ ((not (string< mule-version "6.0"))
+
+ (coding-system-put 'euc-jp :encode-translation-table
+ (get 'japanese-ucs-cp932-to-jis-map 'translation-table))
+ (coding-system-put 'iso-2022-jp :encode-translation-table
+ (get 'japanese-ucs-cp932-to-jis-map 'translation-table))
+ (coding-system-put 'cp932 :encode-translation-table
+ (get 'japanese-ucs-jis-to-cp932-map 'translation-table))
+ ;; charset と coding-system の優先度設定
+ (set-charset-priority 'ascii 'japanese-jisx0208 'latin-jisx0201
+ 'katakana-jisx0201 'iso-8859-1 'cp1252 'unicode)
+ (set-coding-system-priority 'utf-8 'cp932 'euc-jp 'iso-2022-jp)
+
+ ;; East Asian Ambiguous
+ (let ((width 2))
+ (while (char-table-parent char-width-table)
+ (setq char-width-table (char-table-parent char-width-table)))
+ (let ((table (make-char-table nil)))
+ (dolist (range
+ '(#x00A1 #x00A4 (#x00A7 . #x00A8) #x00AA (#x00AD . #x00AE)
+ (#x00B0 . #x00B4) (#x00B6 . #x00BA) (#x00BC . #x00BF)
+ #x00C6 #x00D0 (#x00D7 . #x00D8) (#x00DE . #x00E1) #x00E6
+ (#x00E8 . #x00EA) (#x00EC . #x00ED) #x00F0
+ (#x00F2 . #x00F3) (#x00F7 . #x00FA) #x00FC #x00FE
+ #x0101 #x0111 #x0113 #x011B (#x0126 . #x0127) #x012B
+ (#x0131 . #x0133) #x0138 (#x013F . #x0142) #x0144
+ (#x0148 . #x014B) #x014D (#x0152 . #x0153)
+ (#x0166 . #x0167) #x016B #x01CE #x01D0 #x01D2 #x01D4
+ #x01D6 #x01D8 #x01DA #x01DC #x0251 #x0261 #x02C4 #x02C7
+ (#x02C9 . #x02CB) #x02CD #x02D0 (#x02D8 . #x02DB) #x02DD
+ #x02DF (#x0300 . #x036F) (#x0391 . #x03A9)
+ (#x03B1 . #x03C1) (#x03C3 . #x03C9) #x0401
+ (#x0410 . #x044F) #x0451 #x2010 (#x2013 . #x2016)
+ (#x2018 . #x2019) (#x201C . #x201D) (#x2020 . #x2022)
+ (#x2024 . #x2027) #x2030 (#x2032 . #x2033) #x2035 #x203B
+ #x203E #x2074 #x207F (#x2081 . #x2084) #x20AC #x2103
+ #x2105 #x2109 #x2113 #x2116 (#x2121 . #x2122) #x2126
+ #x212B (#x2153 . #x2154) (#x215B . #x215E)
+ (#x2160 . #x216B) (#x2170 . #x2179) (#x2190 . #x2199)
+ (#x21B8 . #x21B9) #x21D2 #x21D4 #x21E7 #x2200
+ (#x2202 . #x2203) (#x2207 . #x2208) #x220B #x220F #x2211
+ #x2215 #x221A (#x221D . #x2220) #x2223 #x2225
+ (#x2227 . #x222C) #x222E (#x2234 . #x2237)
+ (#x223C . #x223D) #x2248 #x224C #x2252 (#x2260 . #x2261)
+ (#x2264 . #x2267) (#x226A . #x226B) (#x226E . #x226F)
+ (#x2282 . #x2283) (#x2286 . #x2287) #x2295 #x2299 #x22A5
+ #x22BF #x2312 (#x2460 . #x24E9) (#x24EB . #x254B)
+ (#x2550 . #x2573) (#x2580 . #x258F) (#x2592 . #x2595)
+ (#x25A0 . #x25A1) (#x25A3 . #x25A9) (#x25B2 . #x25B3)
+ (#x25B6 . #x25B7) (#x25BC . #x25BD) (#x25C0 . #x25C1)
+ (#x25C6 . #x25C8) #x25CB (#x25CE . #x25D1)
+ (#x25E2 . #x25E5) #x25EF (#x2605 . #x2606) #x2609
+ (#x260E . #x260F) (#x2614 . #x2615) #x261C #x261E #x2640
+ #x2642 (#x2660 . #x2661) (#x2663 . #x2665)
+ (#x2667 . #x266A) (#x266C . #x266D) #x266F #x273D
+ (#x2776 . #x277F) (#xE000 . #xF8FF) (#xFE00 . #xFE0F)
+ #xFFFD
+ ))
+ (set-char-table-range table range width))
+ (optimize-char-table table)
+ (set-char-table-parent table char-width-table)
+ (setq char-width-table table)))
+
+ ;; 機種依存文字
+ (require 'cp5022x)))
+
+;; emacs-w3m
+(eval-after-load "w3m"
+ '(when (coding-system-p 'cp51932)
+ (add-to-list 'w3m-compatible-encoding-alist '(euc-jp . cp51932))))
+;; Gnus
+(eval-after-load "mm-util"
+ '(when (coding-system-p 'cp50220)
+ (add-to-list 'mm-charset-override-alist '(iso-2022-jp . cp50220))))
+;; SEMI (cf. http://d.hatena.ne.jp/kiwanami/20091103/1257243524)
+(eval-after-load "mcs-20"
+ '(when (coding-system-p 'cp50220)
+ (add-to-list 'mime-charset-coding-system-alist
+ '(iso-2022-jp . cp50220))))
\ No newline at end of file
--- /dev/null 2015-04-11 07:27:58.000000000 +0900
+++ ./site-lisp/smart-ime.el 2015-04-11 07:27:30.553117700 +0900
@@ -0,0 +1,173 @@
+;;; smart-ime.el - smart Input Method
+;;
+;; Copyright (C) 2011 HIROSHI OOTA
+
+;; Author: HIROSHI OOTA
+;; Keywords: convenience
+
+;; This program 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 3, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; smart-im frees you from the frustration about IM.
+;; It disables an IM automatically according to a situation.
+
+;;; Install:
+;; Put this file into load-path'ed directory, and byte compile it if
+;; desired. And put the following expression into your ~/.emacs.
+;;
+;; (require 'smart-ime)
+
+;; Todo:
+
+;;; Code:
+
+;; variable
+(defvar sime-saved-input-method nil)
+(make-variable-buffer-local 'sime-saved-input-method)
+(set-default 'sime-saved-input-method nil)
+
+(defun sime-activate-input-method ()
+ (setq sime-saved-input-method (list current-input-method))
+ (inactivate-input-method))
+(defun sime-inactivate-input-method ()
+ (when sime-saved-input-method
+ (activate-input-method (car sime-saved-input-method))
+ (setq sime-saved-input-method nil)))
+
+;;
+;; minibuffer
+(add-hook 'minibuffer-setup-hook 'sime-activate-input-method)
+(add-hook 'minibuffer-exit-hook 'sime-inactivate-input-method)
+;;
+;; incremental search
+(add-hook 'isearch-mode-hook 'sime-activate-input-method)
+(add-hook 'isearch-mode-end-hook 'sime-inactivate-input-method)
+
+;;
+;; query-replace, query-replace-regexp, query-replace-regexp-eval ...
+(defadvice perform-replace
+ (around sime-ad-perform-replace compile activate)
+ (let ((im current-input-method))
+ (if (or (not im)
+ (not (ad-get-arg 2)))
+ ad-do-it
+ (inactivate-input-method)
+ ad-do-it
+ (activate-input-method im))))
+
+;;
+;; read-passwd
+(defadvice read-passwd
+ (around sime-ad-read-passwd compile activate)
+ (let ((sime-ad-toggle-ime-mapped-key-list nil)
+ (im current-input-method))
+ (dolist (k (where-is-internal
+ 'toggle-input-method overriding-local-map nil nil
+ (command-remapping 'toggle-input-method)))
+ (when (integerp (aref k 0))
+ (setq sime-ad-toggle-ime-mapped-key-list
+ (cons (aref k 0) sime-ad-toggle-ime-mapped-key-list))))
+
+ (ad-enable-advice 'read-key 'around 'sime-ad-read-key)
+ (ad-activate 'read-key)
+ (inactivate-input-method)
+ ad-do-it
+ (activate-input-method im)
+ (ad-disable-advice 'read-key 'around 'sime-ad-read-key)
+ (ad-activate 'read-key)))
+
+(defadvice read-key
+ (around sime-ad-read-key compile)
+ (let ((flag t)
+ (msg (current-message)))
+ (while flag
+ ad-do-it
+ (if (not (memq ad-return-value
+ sime-ad-toggle-ime-mapped-key-list))
+ (setq flag nil)
+ (toggle-input-method)
+ (message msg)))))
+
+;;
+;; universal-argument
+(defun sime-universal-toggle-input-method (arg)
+ (interactive "P")
+ (if (consp arg)
+ (universal-argument-other-key arg)
+ (toggle-input-method)
+ (setq prefix-arg arg
+ universal-argument-num-events
+ (length (this-command-keys)))))
+
+; patch universal-argument-map after init
+(add-hook
+ 'after-init-hook
+ #'(lambda ()
+ (require 'simple)
+ (dolist (key (where-is-internal
+ 'toggle-input-method global-map nil nil
+ (command-remapping 'toggle-input-method)))
+ (when (= (length key) 1)
+ (define-key
+ universal-argument-map
+ key 'sime-universal-toggle-input-method)))))
+
+(defadvice universal-argument
+ (after sime-ad-universal-argument compile activate)
+ (setq sime-saved-input-method
+ (or sime-saved-input-method
+ (list current-input-method)))
+ (inactivate-input-method))
+
+(defadvice restore-overriding-map
+ (after sime-ad-restore-overriding-map compile activate)
+ (when sime-saved-input-method
+ (activate-input-method (car sime-saved-input-method))
+ (setq sime-saved-input-method nil)))
+
+;; a keyboard which has no KANJI-KEY
+;; entering/leaving KANJI-mode key-sequence is <kanji><M-kanji>
+;; then we should pass prefix-arg to next command.
+(global-set-key
+ [M-kanji]
+ #'(lambda (arg)
+ (interactive "P")
+ (setq prefix-arg arg)))
+
+;;
+;; others
+(defmacro wrap-function-to-control-input-method (fcn)
+ `(defadvice ,fcn (around
+ ,(make-symbol (concat "sime-ad-" (symbol-name fcn)))
+ compile activate)
+ (let ((im current-input-method))
+ (inactivate-input-method)
+ ad-do-it
+ (activate-input-method im))))
+
+(wrap-function-to-control-input-method map-y-or-n-p)
+(wrap-function-to-control-input-method y-or-n-p)
+(wrap-function-to-control-input-method read-key-sequence)
+
+;; disable W32-IME control during processing the timer handler
+(defadvice timer-event-handler
+ (around sime-ad-timer-event-handler compile activate)
+ (let ((w32-ime-buffer-switch-p nil))
+ ad-do-it))
+
+(provide 'smart-ime)
+;; -*- mode: Emacs-Lisp; coding: euc-jp-unix -*-
--- ./src/alloc.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/alloc.c 2015-04-11 07:27:30.561118400 +0900
@@ -30,6 +30,13 @@
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
+#ifdef WINDOWSNT
+#if (defined(_MSC_VER) && _MSC_VER >= 1600) || defined(__MINGW32__)
+#include <stdint.h>
+#else
+#include <crtdefs.h>
+#endif
+#endif
#include "lisp.h"
#include "process.h"
@@ -336,6 +343,9 @@
/* Base address of stack. Set in main. */
+#ifdef USE_W32_CALL_LISP_THREAD
+TLS
+#endif
Lisp_Object *stack_base;
/* Root of the tree describing allocated Lisp memory. */
@@ -655,9 +665,31 @@
# define MALLOC_BLOCK_INPUT malloc_block_input ()
# define MALLOC_UNBLOCK_INPUT malloc_unblock_input ()
#else
+#ifdef USE_W32_CALL_LISP_THREAD
+CRITICAL_SECTION alloc_critical_section;
+# define MALLOC_BLOCK_INPUT \
+ do \
+ { \
+ if (dwMainThreadId == GetCurrentThreadId ()) \
+ block_input (); \
+ w32_apc_mutex_acquire(); \
+ EnterCriticalSection(&alloc_critical_section); \
+ } \
+ while (0)
+# define MALLOC_UNBLOCK_INPUT \
+ do \
+ { \
+ LeaveCriticalSection(&alloc_critical_section); \
+ w32_apc_mutex_release(); \
+ if (dwMainThreadId == GetCurrentThreadId ()) \
+ unblock_input (); \
+ } \
+ while (0)
+#else
# define MALLOC_BLOCK_INPUT ((void) 0)
# define MALLOC_UNBLOCK_INPUT ((void) 0)
#endif
+#endif
#define MALLOC_PROBE(size) \
do { \
@@ -3757,6 +3789,10 @@
/* This used to call error, but if we've run out of memory, we could
get infinite recursion trying to build the string. */
xsignal (Qnil, Vmemory_signal_data);
+#ifdef EMACSDEBUG
+ if (noninteractive)
+ abort();
+#endif
}
/* If we released our reserve (due to running out of memory),
@@ -5320,6 +5356,34 @@
return obj;
}
+#ifdef USE_W32_CALL_LISP_THREAD
+static VOID CALLBACK mark_stack_stub(ULONG_PTR ev)
+{
+ mark_stack ();
+ SetEvent((HANDLE)ev);
+}
+
+static void w32_mark_stack()
+{
+ static HANDLE ev;
+ static int inilialized = 0;
+
+ if (hWindowsThread == NULL)
+ return;
+
+ if (!inilialized) {
+ if ((ev = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
+ abort();
+ inilialized = 1;
+ }
+ ResetEvent(ev);
+
+ if (QueueUserAPC(mark_stack_stub, hWindowsThread, (ULONG_PTR)ev) == 0)
+ abort ();
+
+ WaitForSingleObject(ev, INFINITE);
+}
+#endif
/***********************************************************************
@@ -5582,6 +5646,10 @@
message1_nolog ("Garbage collecting...");
block_input ();
+#ifdef USE_W32_CALL_LISP_THREAD
+ w32_apc_mutex_acquire();
+ EnterCriticalSection(&alloc_critical_section);
+#endif
shrink_regexp_cache ();
@@ -5607,6 +5675,9 @@
#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
|| GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
mark_stack ();
+#ifdef USE_W32_CALL_LISP_THREAD
+ w32_mark_stack();
+#endif
#else
{
register struct gcpro *tail;
@@ -5663,6 +5734,10 @@
gc_in_progress = 0;
+#ifdef USE_W32_CALL_LISP_THREAD
+ w32_apc_mutex_release();
+ LeaveCriticalSection(&alloc_critical_section);
+#endif
unblock_input ();
consing_since_gc = 0;
--- ./src/callproc.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/callproc.c 2015-04-11 07:27:30.567120000 +0900
@@ -30,6 +30,9 @@
#include "lisp.h"
+#ifdef DOS_NT
+#include <mbstring.h>
+#endif
#ifdef WINDOWSNT
#define NOMINMAX
#include <sys/socket.h> /* for fcntl */
@@ -1236,6 +1239,10 @@
at least check. */
if (chdir (temp) < 0)
_exit (EXIT_CANCELED);
+
+ /* Strip trailing slashes for PWD, but leave "/" and "//" alone. */
+ while (i > 2 && IS_DIRECTORY_SEP (temp[i - 1]))
+ temp[--i] = 0;
#else /* DOS_NT */
/* Get past the drive letter, so that d:/ is left alone. */
if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2]))
@@ -1243,11 +1250,11 @@
temp += 2;
i -= 2;
}
-#endif /* DOS_NT */
/* Strip trailing slashes for PWD, but leave "/" and "//" alone. */
- while (i > 2 && IS_DIRECTORY_SEP (temp[i - 1]))
+ while (i > 2 && IS_DIRECTORY_SEP (*_mbsdec(temp, temp + i)))
temp[--i] = 0;
+#endif /* DOS_NT */
}
/* Set `env' to a vector of the strings in the environment. */
--- /dev/null 2015-04-11 07:27:59.000000000 +0900
+++ ./src/cmigemo.c 2015-04-11 07:27:30.576125800 +0900
@@ -0,0 +1,460 @@
+#ifdef NULL
+#undef NULL
+#endif
+#include <config.h>
+#ifdef HAVE_CMIGEMO
+#include <setjmp.h>
+
+#include "lisp.h"
+#include "charset.h"
+#include "coding.h"
+
+#ifdef WINDOWSNT
+#include <windows.h>
+#define MIGEMO_DLL "migemo.dll"
+#else
+#ifdef CYGWIN
+#define MIGEMO_DLL "cygmigemo1.dll"
+#else
+#define MIGEMO_DLL "libmigemo.so"
+#endif
+#include <stdio.h>
+#include <dlfcn.h>
+#endif
+
+#include "migemo.h"
+
+/* from cmigemo charset.h */
+enum {
+ CHARSET_NONE = 0,
+ CHARSET_CP932 = 1,
+ CHARSET_EUCJP = 2,
+ CHARSET_UTF8 = 3,
+};
+typedef int (*charset_proc_int2char)(unsigned int, unsigned char*);
+#define CHARSET_PROC_INT2CHAR charset_proc_int2char
+
+/* from cmigemo charset.c */
+#define BUFLEN_DETECT 4096
+static int cp932_int2char(unsigned int in, unsigned char* out)
+{
+ if (in >= 0x100)
+ {
+ if (out)
+ {
+ out[0] = (unsigned char)((in >> 8) & 0xFF);
+ out[1] = (unsigned char)(in & 0xFF);
+ }
+ return 2;
+ }
+ else
+ return 0;
+}
+static int eucjp_int2char(unsigned int in, unsigned char* out)
+{
+ /* CP932と内容は同じだが将来JISX0213に対応させるために分離しておく */
+ if (in >= 0x100)
+ {
+ if (out)
+ {
+ out[0] = (unsigned char)((in >> 8) & 0xFF);
+ out[1] = (unsigned char)(in & 0xFF);
+ }
+ return 2;
+ }
+ else
+ return 0;
+}
+static int utf8_int2char(unsigned int in, unsigned char* out)
+{
+ if (in < 0x80)
+ return 0;
+ if (in < 0x800)
+ {
+ if (out)
+ {
+ out[0] = 0xc0 + (in >> 6);
+ out[1] = 0x80 + ((in >> 0) & 0x3f);
+ }
+ return 2;
+ }
+ if (in < 0x10000)
+ {
+ if (out)
+ {
+ out[0] = 0xe0 + (in >> 12);
+ out[1] = 0x80 + ((in >> 6) & 0x3f);
+ out[2] = 0x80 + ((in >> 0) & 0x3f);
+ }
+ return 3;
+ }
+ if (in < 0x200000)
+ {
+ if (out)
+ {
+ out[0] = 0xf0 + (in >> 18);
+ out[1] = 0x80 + ((in >> 12) & 0x3f);
+ out[2] = 0x80 + ((in >> 6) & 0x3f);
+ out[3] = 0x80 + ((in >> 0) & 0x3f);
+ }
+ return 4;
+ }
+ if (in < 0x4000000)
+ {
+ if (out)
+ {
+ out[0] = 0xf8 + (in >> 24);
+ out[1] = 0x80 + ((in >> 18) & 0x3f);
+ out[2] = 0x80 + ((in >> 12) & 0x3f);
+ out[3] = 0x80 + ((in >> 6) & 0x3f);
+ out[4] = 0x80 + ((in >> 0) & 0x3f);
+ }
+ return 5;
+ }
+ else
+ {
+ if (out)
+ {
+ out[0] = 0xf8 + (in >> 30);
+ out[1] = 0x80 + ((in >> 24) & 0x3f);
+ out[2] = 0x80 + ((in >> 18) & 0x3f);
+ out[3] = 0x80 + ((in >> 12) & 0x3f);
+ out[4] = 0x80 + ((in >> 6) & 0x3f);
+ out[5] = 0x80 + ((in >> 0) & 0x3f);
+ }
+ return 6;
+ }
+}
+static int
+charset_detect_buf(const unsigned char* buf, int len)
+{
+ int sjis = 0, smode = 0;
+ int euc = 0, emode = 0, eflag = 0;
+ int utf8 = 0, umode = 0, ufailed = 0;
+ int i;
+ for (i = 0; i < len; ++i)
+ {
+ unsigned char c = buf[i];
+ // SJISであるかのチェック
+ if (smode)
+ {
+ if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc))
+ ++sjis;
+ smode = 0;
+ }
+ else if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xf0))
+ smode = 1;
+ // EUCであるかのチェック
+ eflag = 0xa1 <= c && c <= 0xfe;
+ if (emode)
+ {
+ if (eflag)
+ ++euc;
+ emode = 0;
+ }
+ else if (eflag)
+ emode = 1;
+ // UTF8であるかのチェック
+ if (!ufailed)
+ {
+ if (umode < 1)
+ {
+ if ((c & 0x80) != 0)
+ {
+ if ((c & 0xe0) == 0xc0)
+ umode = 1;
+ else if ((c & 0xf0) == 0xe0)
+ umode = 2;
+ else if ((c & 0xf8) == 0xf0)
+ umode = 3;
+ else if ((c & 0xfc) == 0xf8)
+ umode = 4;
+ else if ((c & 0xfe) == 0xfc)
+ umode = 5;
+ else
+ {
+ ufailed = 1;
+ --utf8;
+ }
+ }
+ }
+ else
+ {
+ if ((c & 0xc0) == 0x80)
+ {
+ ++utf8;
+ --umode;
+ }
+ else
+ {
+ --utf8;
+ umode = 0;
+ ufailed = 1;
+ }
+ }
+ if (utf8 < 0)
+ utf8 = 0;
+ }
+ }
+ // 最終的に一番得点の高いエンコードを返す
+ if (euc > sjis && euc > utf8)
+ return CHARSET_EUCJP;
+ else if (!ufailed && utf8 > euc && utf8 > sjis)
+ return CHARSET_UTF8;
+ else if (sjis > euc && sjis > utf8)
+ return CHARSET_CP932;
+ else
+ return CHARSET_NONE;
+}
+static int
+charset_detect_file(const char* path)
+{
+ int charset = CHARSET_NONE;
+ FILE* fp;
+ if ((fp = fopen(path, "rt")) != NULL)
+ {
+ unsigned char buf[BUFLEN_DETECT];
+ size_t len = fread(buf, sizeof(buf[0]), sizeof(buf), fp);
+ fclose(fp);
+ if (len > 0 && len <= INT_MAX)
+ charset = charset_detect_buf(buf, (int)len);
+ }
+ return charset;
+}
+/**/
+
+migemo* (*migemo_open_)(const char*);
+void (*migemo_close_)(migemo*);
+unsigned char* (*migemo_query_)(migemo*, unsigned char*);
+void (*migemo_release_)(migemo*, unsigned char*);
+
+int (*migemo_set_operator_)(migemo*, int, unsigned char*);
+int (*migemo_is_enable_)(migemo*);
+int (*migemo_load_)(migemo*, int, char *);
+void (*migemo_setproc_char2int_)(migemo*, MIGEMO_PROC_CHAR2INT);
+void (*migemo_setproc_int2char_)(migemo*, MIGEMO_PROC_INT2CHAR);
+
+static migemo *pmigemo = NULL;
+#ifdef WINDOWSNT
+static HMODULE hMigemo = NULL;
+#else
+static void *hMigemo = NULL;
+#endif
+
+static int int2char(unsigned int in, unsigned char* out,
+ CHARSET_PROC_INT2CHAR proc)
+{
+ switch (in) {
+ case '.': case '*': case '+': case '?':
+ case '[': case ']': case '^': case '$':
+ case '\\':
+ if (!out)
+ return 0;
+ out[0] = '\\';
+ out[1] = in;
+ return 2;
+ default:
+ break;
+ }
+ return (*proc)(in, out);
+}
+
+static int eucjp(unsigned int in, unsigned char* out)
+{
+ return int2char(in, out, eucjp_int2char);
+}
+
+static int cp932(unsigned int in, unsigned char* out)
+{
+ return int2char(in, out, cp932_int2char);
+}
+
+static int utf8(unsigned int in, unsigned char* out)
+{
+ return int2char(in, out, utf8_int2char);
+}
+
+static int charset;
+
+static MIGEMO_PROC_INT2CHAR getproc(int charset)
+{
+
+ switch (charset) {
+ case CHARSET_CP932:
+ return cp932;
+ break;
+ case CHARSET_EUCJP:
+ return eucjp;
+ break;
+ case CHARSET_UTF8:
+ return utf8;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+DEFUN ("cmigemo-open", Fcmigemo_open, Scmigemo_open, 1, 1, 0,
+ doc: /* open cmigemo with DICTIONARY.*/ )
+ (Lisp_Object dictionary)
+{
+ static int coding_system_initialized = 0;
+ MIGEMO_PROC_INT2CHAR int2char;
+
+ if (pmigemo)
+ error ("cmigemo already opened");
+
+ CHECK_STRING(dictionary);
+
+#ifdef WINDOWSNT
+ hMigemo = LoadLibrary(MIGEMO_DLL);
+#else
+ hMigemo = dlopen(MIGEMO_DLL, RTLD_NOW);
+#endif
+ if (hMigemo == NULL)
+ error (MIGEMO_DLL ": can't load");
+
+#ifdef WINDOWSNT
+#define GETPROC(n, t) do { \
+ migemo_ ## n ## _ = (t) GetProcAddress(hMigemo, "migemo_" # n); \
+} while(0)
+#else
+#define GETPROC(n, t) do { \
+ migemo_ ## n ## _ = (t) dlsym(hMigemo, "migemo_" # n); \
+} while(0)
+#endif
+
+ GETPROC(open, migemo* (*)(const char*));
+ GETPROC(close, void (*)(migemo*));
+ GETPROC(query, unsigned char* (*)(migemo*, unsigned char*));
+ GETPROC(release, void (*)(migemo*, unsigned char*));
+ GETPROC(set_operator, int (*)(migemo*, int, unsigned char*));
+ GETPROC(is_enable, int (*)(migemo*));
+ GETPROC(load, int (*)(migemo*, int, char *));
+ GETPROC(setproc_char2int, void (*)(migemo*, MIGEMO_PROC_CHAR2INT));
+ GETPROC(setproc_int2char, void (*)(migemo*, MIGEMO_PROC_INT2CHAR));
+
+ if (!(pmigemo = migemo_open_(SDATA(dictionary))) ||
+ !migemo_is_enable_(pmigemo)) {
+ pmigemo = NULL;
+ error("could not open cmigemo");
+ }
+ migemo_set_operator_(pmigemo, MIGEMO_OPINDEX_OR, "\\|");
+ migemo_set_operator_(pmigemo, MIGEMO_OPINDEX_NEST_IN, "\\(");
+ migemo_set_operator_(pmigemo, MIGEMO_OPINDEX_NEST_OUT, "\\)");
+ migemo_set_operator_(pmigemo, MIGEMO_OPINDEX_NEWLINE, "\\s-*");
+
+ charset = charset_detect_file(SDATA(dictionary));
+
+ if ((int2char = getproc(charset)) != NULL)
+ migemo_setproc_int2char_(pmigemo, int2char);
+
+ return Qt;
+}
+
+DEFUN ("cmigemo-close", Fcmigemo_close, Scmigemo_close, 0, 0, 0,
+ doc: /*close cmigemo.*/)
+ (void)
+{
+ if (!pmigemo)
+ error ("cmigemo was not opened");
+ migemo_close_(pmigemo);
+ pmigemo = NULL;
+#ifdef WINDOWSNT
+ FreeLibrary(hMigemo);
+#else
+ dlclose(hMigemo);
+#endif
+ hMigemo = NULL;
+ return Qt;
+}
+
+DEFUN ("cmigemo-query", Fcmigemo_query, Scmigemo_query, 1, 1, 0,
+ doc: /*query cmigemo about WORD.*/)
+ (Lisp_Object word)
+{
+ char *ans;
+ Lisp_Object temp;
+ struct gcpro gcpro1;
+
+ if (!pmigemo)
+ error ("cmigemo was not opened");
+
+ CHECK_STRING(word);
+
+ GCPRO1(temp);
+ temp = word;
+
+ if (STRING_MULTIBYTE (temp))
+ switch (charset) {
+ default:
+ case CHARSET_CP932:
+ temp = code_convert_string_norecord(temp, intern("sjis"), 1);
+ break;
+ case CHARSET_EUCJP:
+ temp = code_convert_string_norecord(temp, intern("euc-japan"), 1);
+ break;
+ case CHARSET_UTF8:
+ break;
+ }
+
+ ans = migemo_query_(pmigemo, SDATA(temp));
+
+ if (!ans)
+ temp = Qnil;
+ else
+ switch (charset) {
+ default:
+ case CHARSET_CP932:
+ temp = code_convert_string_norecord(temp = build_string(ans),
+ intern("sjis"), 0);
+ break;
+ case CHARSET_EUCJP:
+ temp = code_convert_string_norecord(temp = build_string(ans),
+ intern("euc-japan"), 0);
+ break;
+ case CHARSET_UTF8:
+ temp = build_string(ans);
+ break;
+ }
+ UNGCPRO;
+ migemo_release_(pmigemo, ans);
+ return temp;
+}
+
+DEFUN ("cmigemo-load", Fcmigemo_load, Scmigemo_load, 1, 1, 0,
+ doc: /*load a sub DICTIONARY.*/)
+ (Lisp_Object dictionary)
+{
+ MIGEMO_PROC_INT2CHAR int2char;
+
+ if (!pmigemo)
+ error ("cmigemo was not opened");
+
+ CHECK_STRING(dictionary);
+
+ if (migemo_load_(pmigemo, MIGEMO_DICTID_MIGEMO,
+ SDATA(dictionary)) == MIGEMO_DICTID_INVALID)
+ error("migemo_load invalid dict %s", dictionary);
+
+ /*
+ * Migemo_load resets int2char proc,
+ * then we set it again.
+ */
+
+ int2char = getproc(charset);
+ migemo_setproc_int2char_(pmigemo, int2char);
+
+ return Qt;
+}
+
+void
+syms_of_cmigemo ()
+{
+ defsubr(&Scmigemo_open);
+ defsubr(&Scmigemo_close);
+ defsubr(&Scmigemo_query);
+ defsubr(&Scmigemo_load);
+}
+#endif /* HAVE_CMIGEMO */
--- ./src/doprnt.c.orig 2015-02-02 02:27:17.000000000 +0900
+++ ./src/doprnt.c 2015-04-11 07:27:30.582120600 +0900
@@ -155,9 +155,9 @@
if (format_end == 0)
format_end = format + strlen (format);
- fmtcpy = (format_end - format < sizeof (fixed_buffer) - 1
+ fmtcpy = (format_end - format + 1 + 1 < sizeof (fixed_buffer)
? fixed_buffer
- : SAFE_ALLOCA (format_end - format + 1));
+ : SAFE_ALLOCA (format_end - format + 1 + 1));
bufsize--;
--- ./src/emacs.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/emacs.c 2015-04-11 07:27:30.589121000 +0900
@@ -208,6 +208,10 @@
static void sort_args (int argc, char **argv);
static void syms_of_emacs (void);
+#ifdef HAVE_CMIGEMO
+extern void syms_of_cmigemo (void);
+#endif
+
/* C89 needs each string be at most 509 characters, so the usage
strings below are split to not overflow this limit. */
static char const *const usage_message[] =
@@ -768,6 +772,13 @@
atexit (close_output_streams);
+#ifdef USE_W32_CALL_LISP_THREAD
+ {
+ extern CRITICAL_SECTION alloc_critical_section;
+ InitializeCriticalSection(&alloc_critical_section);
+ }
+#endif
+
sort_args (argc, argv);
argc = 0;
while (argv[argc]) argc++;
@@ -1523,6 +1534,10 @@
syms_of_profiler ();
+#ifdef HAVE_CMIGEMO
+ syms_of_cmigemo ();
+#endif /* HAVE_CMIGEMO */
+
keys_of_casefiddle ();
keys_of_cmds ();
keys_of_buffer ();
--- ./src/frame.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/frame.c 2015-04-11 07:27:30.596121900 +0900
@@ -2744,6 +2744,9 @@
{"fullscreen", &Qfullscreen},
{"font-backend", &Qfont_backend},
{"alpha", &Qalpha},
+#ifdef USE_W32_IME
+ {"ime-font", &Qime_font},
+#endif /* USE_W32_IME */
{"sticky", &Qsticky},
{"tool-bar-position", &Qtool_bar_position},
};
--- ./src/frame.h.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/frame.h 2015-04-11 07:27:30.604123000 +0900
@@ -1217,6 +1217,9 @@
extern Lisp_Object Qbuffer_predicate;
extern Lisp_Object Qcursor_color, Qcursor_type;
extern Lisp_Object Qfont;
+#ifdef USE_W32_IME
+extern Lisp_Object Qime_font;
+#endif /* USE_W32_IME */
extern Lisp_Object Qbackground_color, Qforeground_color;
extern Lisp_Object Qicon, Qicon_name, Qicon_type, Qicon_left, Qicon_top;
extern Lisp_Object Qinternal_border_width;
--- ./src/image.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/image.c 2015-04-11 07:27:30.613127900 +0900
@@ -536,6 +536,10 @@
static struct image_type *image_types;
+/* "Alist of (IMAGE-TYPE . FIT-OPTION) pairs used by image loader to specify image size. */
+
+//static Lisp_Object Vimage_fit_option_alist;
+
/* The symbol `xbm' which is used as the type symbol for XBM images. */
static Lisp_Object Qxbm;
@@ -544,6 +548,7 @@
Lisp_Object QCascent, QCmargin, QCrelief;
Lisp_Object QCconversion;
+Lisp_Object QCfit;
static Lisp_Object QCheuristic_mask;
static Lisp_Object QCcolor_symbols;
static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
@@ -617,6 +622,102 @@
return p;
}
+Lisp_Object Qnever, Qframe, Qwidth_or_height;
+
+static void image_error (const char *, Lisp_Object, Lisp_Object);
+static int get_fit_size(Lisp_Object opt, const struct frame *f,
+ int *w, int *h,
+ Lisp_Object image_type, int rise_error)
+{
+ if (NILP(opt))
+ return 0;
+
+ if (EQ(opt, Qnever)) {
+ *w = *h = 0;
+ } else if (EQ(opt, Qframe)) {
+ *w = FRAME_PIXEL_WIDTH (f) - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) - FRAME_SCROLL_BAR_AREA_WIDTH (f);
+ *h = FRAME_PIXEL_HEIGHT (f);
+ } else if (EQ(opt, Qwidth_or_height)) {
+ *w = -(FRAME_PIXEL_WIDTH (f) - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) - FRAME_SCROLL_BAR_AREA_WIDTH (f));
+ *h = -FRAME_PIXEL_HEIGHT (f);
+ } else if (EQ(opt, Qwidth)) {
+ *w = FRAME_PIXEL_WIDTH (f) - FRAME_CONFIG_SCROLL_BAR_WIDTH (f) - FRAME_SCROLL_BAR_AREA_WIDTH (f);
+ *h = 0;
+ } else if (EQ(opt, Qheight)) {
+ *w = 0;
+ *h = FRAME_PIXEL_HEIGHT (f);
+ } else {
+ if (rise_error)
+ xsignal2 (Qnil, build_string("unknown fit type"), opt);
+ else
+ image_error ("Invalid fit option for %s", image_type, Qnil);
+ return -1;
+ }
+ return 1;
+}
+
+static Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, bool *);
+static int
+lookup_fit_size(Lisp_Object image_type,
+ const struct frame *f,
+ const struct image *img,
+ int *w, int *h, int rise_error)
+{
+ Lisp_Object a, err, pred;
+ static const struct frame f_ = {0};
+ int w_, h_;
+ int r;
+
+// assert(SYMBOLP (image_type));
+
+ if (img &&
+ (r = get_fit_size(image_spec_value(img->spec, QCfit, NULL),
+ f, w, h, image_type, rise_error)) != 0)
+ return r;
+
+#if 0
+ if (!CONSP (err = Vimage_fit_option_alist)) {
+ pred = Qconsp;
+ goto error;
+ }
+#endif
+
+ for (a = Vimage_fit_option_alist; !NILP(a); a = XCDR(a)) {
+ Lisp_Object o;
+ {
+ Lisp_Object e = XCAR(a);
+
+ if (!CONSP(err = e)) {
+ pred = Qconsp;
+ goto error;
+ }
+
+ if (!EQ(XCAR(e), image_type))
+ continue;
+ o = XCDR(e);
+ }
+
+ if (!SYMBOLP(err = o)) {
+ pred = Qsymbolp;
+ goto error;
+ }
+ if (f)
+ return get_fit_size(o, f, w, h, image_type, rise_error);
+ get_fit_size(o, &f_, &w_, &h_, image_type, rise_error);
+ }
+
+ /* not found */
+ if (f)
+ *w = *h = 0;
+ return 0;
+
+ error:
+ if (rise_error)
+ wrong_type_argument(pred, err);
+ else
+ image_error ("Invalid fit option for %s", image_type, Qnil);
+ return -1;
+}
/* Value is true if OBJECT is a valid Lisp image specification. A
valid image specification is a list whose car is the symbol
@@ -3096,6 +3197,8 @@
#define XImage xpm_XImage
#define Display xpm_Display
#define PIXEL_ALREADY_TYPEDEFED
+#undef close
+#undef open
#include "X11/xpm.h"
#undef FOR_MSW
#undef XColor
@@ -6483,6 +6586,10 @@
XImagePtr ximg = NULL;
unsigned long *colors;
int width, height;
+ int fit_width = 0, fit_height = 0;
+
+ if (lookup_fit_size (Qjpeg, f, img, &fit_width, &fit_height, !0) < 0)
+ return 0;
/* Open the JPEG file. */
specified_file = image_spec_value (img->spec, QCfile, NULL);
@@ -6560,6 +6667,43 @@
fn_jpeg_read_header (&mgr->cinfo, 1);
+#define JPEG8C_UNIT 8
+
+ if (fit_width > 0 && fit_height == 0) {
+ if (mgr->cinfo.image_width > fit_width) { /* fit to width */
+ mgr->cinfo.scale_num = ((double) fit_width / mgr->cinfo.image_width) * JPEG8C_UNIT;
+ mgr->cinfo.scale_denom = JPEG8C_UNIT;
+ }
+ } else if (fit_width == 0 && fit_height > 0) {
+ if (mgr->cinfo.image_height > fit_height) { /* fit to width */
+ mgr->cinfo.scale_num = ((double)fit_height / mgr->cinfo.image_height) * JPEG8C_UNIT;
+ mgr->cinfo.scale_denom = JPEG8C_UNIT;
+ }
+ } else if (fit_width > 0 && fit_height > 0) { /* fit to frame */
+ if (mgr->cinfo.image_width > fit_width ||
+ mgr->cinfo.image_height > fit_height) {
+ if ((double)fit_width / mgr->cinfo.image_width <
+ (double)fit_height / mgr->cinfo.image_height) {
+ mgr->cinfo.scale_num = ((double)fit_width / mgr->cinfo.image_width) * JPEG8C_UNIT;
+ } else {
+ mgr->cinfo.scale_num = ((double)fit_height / mgr->cinfo.image_height) * JPEG8C_UNIT;
+ mgr->cinfo.scale_denom = JPEG8C_UNIT;
+ }
+ }
+ } else if (fit_width < 0 && fit_height < 0) { /* fit to width or height */
+ if (mgr->cinfo.image_width > -fit_width &&
+ mgr->cinfo.image_height > -fit_height) {
+ if ((double)-fit_width / mgr->cinfo.image_width >
+ (double)-fit_height / mgr->cinfo.image_height) {
+ mgr->cinfo.scale_num = ((double)-fit_width / mgr->cinfo.image_width) * JPEG8C_UNIT;
+ mgr->cinfo.scale_denom = JPEG8C_UNIT;
+ } else {
+ mgr->cinfo.scale_num = ((double)-fit_height / mgr->cinfo.image_height) * JPEG8C_UNIT;
+ mgr->cinfo.scale_denom = JPEG8C_UNIT;
+ }
+ }
+ }
+
/* Customize decompression so that color quantization will be used.
Start decompression. */
mgr->cinfo.quantize_colors = 1;
@@ -8512,6 +8656,12 @@
{
bool success_p = 0;
Lisp_Object file_name;
+ int w, h;
+
+#if 0
+ if (lookup_fit_size(Qjpeg, NULL, NULL, NULL, NULL, !0) < 0)
+ return 0;
+#endif
/* If IMG->spec specifies a file name, create a non-file spec from it. */
file_name = image_spec_value (img->spec, QCfile, NULL);
@@ -8722,6 +8872,7 @@
LOAD_IMGLIB_FN (library, rsvg_handle_write);
LOAD_IMGLIB_FN (library, rsvg_handle_close);
LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
+ LOAD_IMGLIB_FN (library, rsvg_handle_set_size_callback);
LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
@@ -8749,6 +8900,7 @@
#define fn_rsvg_handle_write rsvg_handle_write
#define fn_rsvg_handle_close rsvg_handle_close
#define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
+#define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
#define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
#define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
@@ -8819,6 +8971,48 @@
return success_p;
}
+static void rsvg_size_callback (gint *width,
+ gint *height,
+ gpointer user_data)
+{
+ int *fit_size = (int *)user_data;
+
+ /*
+ * 0, 0: never
+ * 0, +: fit to height
+ * +, 0: fit to width
+ * +, +: fit to frame
+ * -, -: fit to width or height
+ */
+ if (fit_size[0] > 0 && fit_size[1] == 0) {
+ *height *= (double)fit_size[0] / *width;
+ *width = (gint)fit_size[0];
+ } else if (fit_size[0] == 0 && fit_size[1] > 0) {
+ *width *= (double)fit_size[1] / *height;
+ *height = (gint)fit_size[1];
+ } else if (fit_size[0] > 0 && fit_size[1] > 0) { /* fit to frame */
+ if ((double)fit_size[0] / *width < (double)fit_size[1] / *height) {
+ /* fit to width */
+ *height *= (double)fit_size[0] / *width;
+ *width = (gint)fit_size[0];
+ } else {
+ /* fit to height */
+ *width *= (double)fit_size[1] / *height;
+ *height = (gint)fit_size[1];
+ }
+ } else if (fit_size[0] < 0 && fit_size[1] < 0) { /* fit to width or height */
+ if ((double)-fit_size[0] / *width < (double)-fit_size[1] / *height) {
+ /* fit to height */
+ *width *= (double)-fit_size[1] / *height;
+ *height = (gint)-fit_size[1];
+ } else {
+ /* fit to width */
+ *height *= (double)-fit_size[0] / *width;
+ *width = (gint)-fit_size[0];
+ }
+ }
+}
+
/* svg_load_image is a helper function for svg_load, which does the
actual loading given contents and size, apart from frame and image
structures, passed from svg_load.
@@ -8845,6 +9039,10 @@
XColor background;
int x;
int y;
+ int fit_size[2] = {0, 0};
+
+ if (lookup_fit_size(Qsvg, f, img, fit_size, fit_size+1, 0) < 0)
+ return 0;
#if ! GLIB_CHECK_VERSION (2, 36, 0)
/* g_type_init is a glib function that must be called prior to
@@ -8855,6 +9053,9 @@
/* Make a handle to a new rsvg object. */
rsvg_handle = fn_rsvg_handle_new ();
+ if (fit_size[0] || fit_size[1])
+ fn_rsvg_handle_set_size_callback(rsvg_handle, rsvg_size_callback, fit_size, NULL);
+
/* Parse the contents argument and fill in the rsvg_handle. */
fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
if (err) goto rsvg_error;
@@ -9438,6 +9639,7 @@
DEFSYM (QCmatrix, ":matrix");
DEFSYM (QCcolor_adjustment, ":color-adjustment");
DEFSYM (QCmask, ":mask");
+ DEFSYM (QCfit, ":fit");
DEFSYM (Qlaplace, "laplace");
DEFSYM (Qemboss, "emboss");
@@ -9484,12 +9686,26 @@
);
#endif
+ DEFVAR_LISP ("image-fit-option-alist", Vimage_fit_option_alist,
+ doc: /* Alist of (IMAGE-TYPE . FIT-OPTION) pairs used by image loader to specify image size.
+the FIT-OPTION is one of 'never, 'frame, 'width-or-height, 'width or 'height.
+Note: All image loaders are not supporting this `fit' capability. */);
+ Vimage_fit_option_alist = Qnil;
+
DEFSYM (Qpbm, "pbm");
ADD_IMAGE_TYPE (Qpbm);
DEFSYM (Qxbm, "xbm");
ADD_IMAGE_TYPE (Qxbm);
+ Qnever = intern_c_string("never");
+ staticpro (&Qnever);
+ Qframe = intern_c_string("frame");
+ staticpro (&Qframe);
+ Qwidth_or_height = intern_c_string("width-or-height");
+ staticpro (&Qwidth_or_height);
+
+
#if defined (HAVE_XPM) || defined (HAVE_NS)
DEFSYM (Qxpm, "xpm");
ADD_IMAGE_TYPE (Qxpm);
@@ -9523,7 +9739,7 @@
#if defined (HAVE_RSVG)
DEFSYM (Qsvg, "svg");
ADD_IMAGE_TYPE (Qsvg);
-#ifdef HAVE_NTGUI
+#if defined HAVE_NTGUI && !defined CYGWIN
/* Other libraries used directly by svg code. */
DEFSYM (Qgdk_pixbuf, "gdk-pixbuf");
DEFSYM (Qglib, "glib");
--- ./src/keyboard.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/keyboard.c 2015-04-11 07:27:30.625123200 +0900
@@ -4779,7 +4779,11 @@
"junja", /* VK_JUNJA 0x17 */
"final", /* VK_FINAL 0x18 */
"kanji", /* VK_KANJI/VK_HANJA 0x19 */
+#ifdef USE_W32_IME
+ "compend", /* VK_COMPEND 0x1A */
+#else
0, /* 0x1A */
+#endif /* USE_W32_IME */
"escape", /* VK_ESCAPE 0x1B */
"convert", /* VK_CONVERT 0x1C */
"non-convert", /* VK_NONCONVERT 0x1D */
@@ -8851,6 +8855,13 @@
{
ptrdiff_t count = SPECPDL_INDEX ();
+ /* To control IME */
+#ifdef USE_W32_IME
+ extern Lisp_Object Fime_force_on (), Fime_force_off (), Fime_get_mode ();
+ Lisp_Object VIME_command_off_flag = Qnil;
+ Lisp_Object IME_command_loop_flag = Qnil;
+#endif /* USE_W32_IME */
+
/* How many keys there are in the current key sequence. */
int t;
@@ -8966,6 +8977,12 @@
keybuf[0..mock_input] holds the sequence we should reread. */
replay_sequence:
+#ifdef USE_W32_IME
+/* If key sequences are to replay, IME_loop_flag should not be set.
+ Because event has never been occured. */
+ IME_command_loop_flag = Qnil;
+#endif /* USE_W32_IME */
+
starting_buffer = current_buffer;
first_unbound = bufsize + 1;
@@ -9045,6 +9062,16 @@
goto replay_sequence;
}
+#ifdef USE_W32_IME
+ if (!NILP (IME_command_loop_flag) && NILP (VIME_command_off_flag))
+ {
+ VIME_command_off_flag = Fime_get_mode ();
+ if (!NILP (VIME_command_off_flag))
+ Fime_force_off (Qnil);
+ }
+ IME_command_loop_flag = Qt;
+#endif /* USE_W32_IME */
+
if (t >= bufsize)
error ("Key sequence too long");
@@ -9708,6 +9735,12 @@
? Fcommand_remapping (read_key_sequence_cmd, Qnil, Qnil)
: Qnil;
+ /* to control IME */
+#ifdef USE_W32_IME
+ if (!NILP (VIME_command_off_flag))
+ Fime_force_on (Qnil);
+#endif /* USE_W32_IME */
+
unread_switch_frame = delayed_switch_frame;
unbind_to (count, Qnil);
--- ./src/lisp.h.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/lisp.h 2015-04-11 07:27:30.637122000 +0900
@@ -286,6 +286,17 @@
# define USE_LSB_TAG true
# endif
# endif
+# if defined (_MSC_VER)
+# define ALIGN_BITS_0 1
+# define ALIGN_BITS_1 2
+# define ALIGN_BITS_2 4
+# define ALIGN_BITS_3 8
+# define ALIGN_BITS_4 16
+# define ALIGN_BITS_(x) ALIGN_BITS_ ## x
+# define ALIGN_BITS(x) ALIGN_BITS_(x)
+# define DECL_ALIGN(type, var) \
+ type __declspec (align(ALIGN_BITS(GCTYPEBITS))) var
+# endif
# endif
#endif
#ifdef USE_LSB_TAG
@@ -3652,7 +3663,26 @@
#endif
extern const char *pending_malloc_warning;
extern Lisp_Object zero_vector;
+#if !defined(USE_W32_CALL_LISP_THREAD)
extern Lisp_Object *stack_base;
+#else /* USE_W32_CALL_LISP_THREAD */
+#ifndef TLS
+#ifdef _MSC_VER
+#define TLS __declspec( thread )
+#else
+#ifdef __GNUC__
+#define TLS __thread
+#else
+#define TLS
+#endif
+#endif
+#endif
+#ifdef __GNUC__
+extern TLS Lisp_Object *stack_base;
+#else
+TLS extern Lisp_Object *stack_base;
+#endif
+#endif /* USE_W32_CALL_LISP_THREAD */
extern EMACS_INT consing_since_gc;
extern EMACS_INT gc_relative_threshold;
extern EMACS_INT memory_full_cons_threshold;
--- ./src/lisp.mk.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/lisp.mk 2015-04-11 07:27:30.646122500 +0900
@@ -152,6 +152,7 @@
$(lispsource)/term/w32-win.elc \
$(lispsource)/ls-lisp.elc \
$(lispsource)/disp-table.elc \
+ $(lispsource)/international/w32-ime.elc \
$(lispsource)/w32-common-fns.elc \
$(lispsource)/dos-w32.elc \
$(lispsource)/w32-fns.elc \
--- ./src/Makefile.in.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/Makefile.in 2015-04-11 07:27:30.650126500 +0900
@@ -355,7 +355,7 @@
process.o gnutls.o callproc.o \
region-cache.o sound.o atimer.o \
doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
- profiler.o decompress.o \
+ profiler.o decompress.o cmigemo.o \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
obj = $(base_obj) $(NS_OBJC_OBJ)
--- ./src/w32.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32.c 2015-04-11 07:27:30.658123200 +0900
@@ -332,7 +332,7 @@
GetProcessTimes_Proc get_process_times_fn = NULL;
-#ifdef _UNICODE
+#if defined(_UNICODE) || defined(UNICODE)
const char * const LookupAccountSid_Name = "LookupAccountSidW";
#else
const char * const LookupAccountSid_Name = "LookupAccountSidA";
@@ -2030,7 +2030,7 @@
Otherwise, the default group name was already set to
"None" in globals_of_w32. */
if (lookup_account_sid (NULL, group_token.PrimaryGroup,
- gname, &glength, NULL, &dlength,
+ gname, &glength, domain, &dlength,
&user_type))
strcpy (dflt_group_name, gname);
}
@@ -2530,6 +2530,7 @@
for (i = 0; i < imax ; i++)
{
const char *tmp = tempdirs[i];
+ struct stat b;
if (*tmp == '$')
tmp = getenv (tmp + 1);
@@ -2809,6 +2810,8 @@
filename_from_ansi (astartup_dir, startup_dir);
}
+ dostounix_filename (startup_dir);
+
{
static char modname[MAX_PATH];
@@ -3216,7 +3219,7 @@
while (name < path)
*str++ = *name++; /* skip past UNC header */
- while ((c = *name++))
+ for (; c = *name; name = _mbsinc(name))
{
switch ( c )
{
@@ -3235,9 +3238,9 @@
but leave . and .. as they are. This allows .emacs
to be read as _emacs, for example. */
- if (! *name ||
- *name == '.' ||
- IS_DIRECTORY_SEP (*name))
+ if (! name[1] ||
+ name[1] == '.' ||
+ IS_DIRECTORY_SEP (name[1]))
{
*str++ = '.';
dots--;
@@ -3263,11 +3266,20 @@
break;
case '~':
case '#': /* don't lose these, they're important */
- if ( ! left )
- str[-1] = c; /* replace last character of part */
+ if ( ! left ) {
+ char *p = _mbsdec(shortname, str);
+ left += str - p;
+ *p++ = c; /* replace last character of part */
+ str = p;
+ }
/* FALLTHRU */
default:
- if ( left && 'A' <= c && c <= 'Z' )
+ if (IsDBCSLeadByte(c) && left > 1) {
+ *str++ = c;
+ *str++ = name[1];
+ left -= 2;
+ dots = 0; /* started a path component */
+ } else if ( left && 'A' <= c && c <= 'Z' )
{
*str++ = tolower (c); /* map to lower case (looks nicer) */
left--;
@@ -3293,13 +3305,19 @@
static int
is_exec (const char * name)
{
+ char * ext = getenv("PATHEXT");
char * p = strrchr (name, '.');
+ size_t l;
+
+ ext = ext
+ ? (char *) _mbslwr(strcpy(alloca(strlen(ext) + 1), ext))
+ : ".exe;.com;.bat;.cmd";
+
return
(p != NULL
- && (xstrcasecmp (p, ".exe") == 0 ||
- xstrcasecmp (p, ".com") == 0 ||
- xstrcasecmp (p, ".bat") == 0 ||
- xstrcasecmp (p, ".cmd") == 0));
+ && (p = _mbslwr(strcpy(alloca((l = strlen(p)) + 1), p))) != NULL
+ && (p = strstr(ext, p)) != NULL
+ && (p[l] == ';' || p[l] == 0));
}
/* Emulate the Unix directory procedures opendir, closedir, and
@@ -6853,7 +6871,7 @@
dlength = sizeof (domain);
result =
lookup_account_sid (NULL, group_token.PrimaryGroup,
- gname, &glength, NULL, &dlength,
+ gname, &glength, domain, &dlength,
&user_type);
if (result)
w32_add_to_cache (group_token.PrimaryGroup,
@@ -7290,7 +7308,11 @@
static int socket_to_fd (SOCKET s);
+#ifdef __MINGW64__
+SOCKET
+#else
int
+#endif
sys_socket (int af, int type, int protocol)
{
SOCKET s;
@@ -8081,7 +8103,7 @@
{
int nchars;
int to_read;
- DWORD waiting;
+ unsigned long waiting;
char * orig_buffer = buffer;
if (fd < 0)
@@ -8155,8 +8177,10 @@
if (fd_info[fd].flags & FILE_PIPE)
{
- PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
- to_read = min (waiting, (DWORD) count);
+ DWORD w;
+ PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &w, NULL);
+ waiting = w; /* avoid cast, because cast to DWORD is danger */
+ to_read = min (waiting, count);
if (to_read > 0)
nchars += _read (fd, buffer, to_read);
@@ -8823,14 +8847,14 @@
int needed;
sprintf (buffer,
- "The Emacs Windows initialization file \"%s.el\" "
+ TEXT ("The Emacs Windows initialization file \"%s.el\" "
"could not be found in your Emacs installation. "
"Emacs checked the following directories for this file:\n"
"\n%s\n\n"
"When Emacs cannot find this file, it usually means that it "
"was not installed properly, or its distribution file was "
"not unpacked properly.\nSee the README.W32 file in the "
- "top-level Emacs directory for more information.",
+ "top-level Emacs directory for more information."),
init_file_name, load_path);
needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer,
-1, NULL, 0);
@@ -8853,7 +8877,7 @@
}
MessageBox (NULL,
msg,
- "Emacs Abort Dialog",
+ TEXT ("Emacs Abort Dialog"),
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
/* Use the low-level system abort. */
abort ();
@@ -8876,6 +8900,9 @@
term_winsock ();
term_w32select ();
+#ifdef USE_W32_CALL_LISP_THREAD
+ w32_apc_mutex_term();
+#endif
}
void
@@ -8897,6 +8924,14 @@
if (getenv ("PRELOAD_WINSOCK") != NULL)
init_winsock (TRUE);
+ /* remove current directory from dll search path */
+ {
+ BOOL (WINAPI * pSetDllDirectory)(LPCTSTR) = (BOOL (WINAPI *)(LPCTSTR))
+ GetProcAddress(GetModuleHandle ("kernel32.dll"), "SetDllDirectoryA");
+ if (pSetDllDirectory)
+ pSetDllDirectory("");
+ }
+
/* Initial preparation for subprocess support: replace our standard
handles with non-inheritable versions. */
{
@@ -8984,6 +9019,10 @@
/* Reset the volume info cache. */
volume_cache = NULL;
}
+
+#ifdef USE_W32_CALL_LISP_THREAD
+ w32_apc_mutex_init();
+#endif
}
/*
@@ -9370,4 +9409,58 @@
}
#endif /* HAVE_GNUTLS */
+Lisp_Object
+w32_get_memory_info (void)
+{
+ PROCESS_MEMORY_COUNTERS_EX pmc = {sizeof(PROCESS_MEMORY_COUNTERS_EX)};
+ MEMORY_STATUS_EX msx = {sizeof(MEMORY_STATUS_EX)};
+ OSVERSIONINFO osi = {sizeof(OSVERSIONINFO)};
+
+ int os_version;
+ struct gcpro gcpro1, gcpro2;
+ Lisp_Object pm, sm;
+
+ if (GetVersionEx(&osi) == 0)
+ return Qnil;
+
+ os_version = (osi.dwMajorVersion << 8) | osi.dwMinorVersion ;
+ if (os_version < 0x501)
+ pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
+
+ if (global_memory_status_ex(&msx) == 0 ||
+ get_process_memory_info(GetCurrentProcess(),
+ (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc)) == 0)
+ return Qnil;
+
+ GCPRO2(sm, pm);
+
+ sm = Qnil;
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailExtendedVirtual), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailVirtual), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullTotalVirtual), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailPageFile), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullTotalPageFile), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullAvailPhys), sm);
+ sm = Fcons(make_fixnum_or_float(msx.ullTotalPhys), sm);
+ sm = Fcons(make_fixnum_or_float(msx.dwMemoryLoad), sm);
+
+ pm = Qnil;
+ if (os_version >= 0x501)
+ pm = Fcons(make_fixnum_or_float(pmc.PrivateUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PeakPagefileUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PagefileUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaNonPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaPeakNonPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.QuotaPeakPagedPoolUsage), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.WorkingSetSize), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PeakWorkingSetSize), pm);
+ pm = Fcons(make_fixnum_or_float(pmc.PageFaultCount), pm);
+ pm = Fcons(pm, Qnil);
+
+ sm = Fcons(sm, pm);
+
+ RETURN_UNGCPRO(Fcons(make_fixnum_or_float(reserved_heap_size), sm));
+}
+
/* end of w32.c */
--- ./src/w32.h.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32.h 2015-04-11 07:27:30.667123700 +0900
@@ -29,6 +29,15 @@
/* File descriptor set emulation. */
/* MSVC runtime library has limit of 64 descriptors by default */
+
+#ifdef _MSC_VER
+#define TLS __declspec( thread )
+#else
+#ifdef __GNUC__
+#define TLS __thread
+#endif
+#endif
+
#define FD_SETSIZE 64
typedef struct {
unsigned int bits[FD_SETSIZE / 32];
@@ -218,4 +227,13 @@
const void* buf, size_t sz);
#endif /* HAVE_GNUTLS */
+#ifdef USE_W32_CALL_LISP_THREAD
+extern void w32_apc_mutex_init (void);
+extern void w32_apc_mutex_term (void);
+extern void w32_apc_mutex_acquire (void);
+extern void w32_apc_mutex_release (void);
+#endif
+
+extern Lisp_Object w32_get_memory_info (void);
+
#endif /* EMACS_W32_H */
--- ./src/w32fns.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32fns.c 2015-04-11 07:27:30.688132700 +0900
@@ -68,9 +68,13 @@
#include <ctype.h>
#include <winspool.h>
#include <objbase.h>
+#include <shlobj.h>
#include <dlgs.h>
#include <imm.h>
+#ifndef CYGWIN
+#include <mbstring.h>
+#endif
#include "font.h"
#include "w32font.h"
@@ -79,6 +83,13 @@
#define FOF_NO_CONNECTED_ELEMENTS 0x2000
#endif
+#ifdef IME_UNICODE
+#define __T(x) L ## x
+#define _T(x) __T(x)
+#else
+#define _T(x) x
+#endif
+
void syms_of_w32fns (void);
void globals_of_w32fns (void);
@@ -89,6 +100,26 @@
extern const char *map_w32_filename (const char *, const char **);
extern char * w32_strerror (int error_no);
+#if defined (RECONVERSION) || defined (DOCUMENTFEED)
+#ifdef IME_UNICODE
+#define CHRSZ sizeof(short)
+#else
+#define CHRSZ sizeof(char)
+#endif
+#endif
+
+#if defined (RECONVERSION) && defined (USE_W32_IME)
+#define RECONV_LENG 100
+#define DOCFEED_LENG 100
+static LRESULT w32_get_ime_reconversion_string (HWND, RECONVERTSTRING*);
+static BOOL w32_perform_reconversion (HWND, RECONVERTSTRING*);
+#endif
+
+#if defined (DOCUMENTFEED) && defined (USE_W32_IME)
+#define DOCFEED_CSTR_LENG 64
+static LRESULT w32_get_ime_documentfeed_string (HWND, RECONVERTSTRING*);
+#endif
+
/* If non-NULL, a handle to a frame where to display the hourglass cursor. */
static HWND hourglass_hwnd = NULL;
@@ -98,6 +129,50 @@
Lisp_Object Qsuppress_icon;
Lisp_Object Qundefined_color;
+
+#ifdef USE_W32_IME
+Lisp_Object Qw32_ime_buffer_switch_p;
+// Lisp_Object Vw32_ime_composition_window;
+Lisp_Object Qime_font;
+static int set_ime_font = 0;
+#if !defined(USE_W32_CALL_LISP_THREAD)
+static LOGFONT ime_logfont = {0};
+#endif
+static int IME_event_off_count;
+Lisp_Object Fime_get_mode();
+const char * const ImmGetOpenStatus_Name = "ImmGetOpenStatus";
+const char * const ImmSetOpenStatus_Name = "ImmSetOpenStatus";
+const char * const ImmSetCompositionWindow_Name = "ImmSetCompositionWindow";
+const char * const ImmGetContext_Name = "ImmGetContext";
+const char * const ImmGetConversionStatus_Name = "ImmGetConversionStatus";
+const char * const ImmSetConversionStatus_Name = "ImmSetConversionStatus";
+const char * const ImmNotifyIME_Name = "ImmNotifyIME";
+
+const char * const ImmReleaseContext_Name = "ImmReleaseContext";
+const char * const ImmCreateContext_Name = "ImmCreateContext";
+const char * const ImmDestroyContext_Name = "ImmDestroyContext";
+const char * const ImmAssociateContext_Name = "ImmAssociateContext";
+const char * const ImmGetHotKey_Name = "ImmGetHotKey";
+const char * const ImmGetProperty_Name = "ImmGetProperty";
+#ifdef IME_UNICODE
+const char * const ImmGetCompositionString_Name = "ImmGetCompositionStringW";
+const char * const ImmSetCompositionString_Name = "ImmSetCompositionStringW";
+const char * const ImmSetCompositionFont_Name = "ImmSetCompositionFontA"; /* LOGFONTA */
+const char * const ImmGetConversionList_Name = "ImmGetConversionListW";
+const char * const ImmConfigureIME_Name = "ImmConfigureIMEW";
+const char * const ImmGetCandidateList_Name = "ImmGetCandidateListW";
+const char * const ImmGetCandidateListCount_Name = "ImmGetCandidateListCountW";
+#else
+const char * const ImmGetCompositionString_Name = "ImmGetCompositionStringA";
+const char * const ImmSetCompositionString_Name = "ImmSetCompositionStringA";
+const char * const ImmSetCompositionFont_Name = "ImmSetCompositionFontA";
+const char * const ImmGetConversionList_Name = "ImmGetConversionListA";
+const char * const ImmConfigureIME_Name = "ImmConfigureIMEA";
+const char * const ImmGetCandidateList_Name = "ImmGetCandidateListA";
+const char * const ImmGetCandidateListCount_Name = "ImmGetCandidateListCountA";
+#endif
+#endif
+
Lisp_Object Qcancel_timer;
Lisp_Object Qfont_param;
Lisp_Object Qhyper;
@@ -171,12 +246,14 @@
typedef BOOL (WINAPI * TrackMouseEvent_Proc)
(IN OUT LPTRACKMOUSEEVENT lpEventTrack);
+#ifndef USE_W32_IME
typedef LONG (WINAPI * ImmGetCompositionString_Proc)
(IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
typedef HWND (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context);
typedef HWND (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context,
IN COMPOSITIONFORM *form);
+#endif /* !USE_W32_IME */
typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
typedef BOOL (WINAPI * GetMonitorInfo_Proc)
(IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
@@ -188,10 +265,12 @@
(IN HDC hdc, IN RECT *rcClip, IN MonitorEnum_Proc fnEnum, IN LPARAM dwData);
TrackMouseEvent_Proc track_mouse_event_fn = NULL;
+#ifndef USE_W32_IME
ImmGetCompositionString_Proc get_composition_string_fn = NULL;
ImmGetContext_Proc get_ime_context_fn = NULL;
ImmReleaseContext_Proc release_ime_context_fn = NULL;
ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
+#endif /* !USE_W32_IME */
MonitorFromPoint_Proc monitor_from_point_fn = NULL;
GetMonitorInfo_Proc get_monitor_info_fn = NULL;
MonitorFromWindow_Proc monitor_from_window_fn = NULL;
@@ -203,8 +282,10 @@
extern AppendMenuW_Proc unicode_append_menu;
#endif /* NTGUI_UNICODE */
+#ifndef USE_W32_IME
/* Flag to selectively ignore WM_IME_CHAR messages. */
static int ignore_ime_char = 0;
+#endif
/* W95 mousewheel handler */
unsigned int msh_mousewheel = 0;
@@ -238,6 +319,11 @@
static void w32_show_hourglass (struct frame *);
static void w32_hide_hourglass (void);
+#ifdef USE_W32_CALL_LISP_THREAD
+/* Function prototypes for APC */
+static Lisp_Object w32_call_lisp_thread (Lisp_Object (*)(Lisp_Object), void *arg);
+#endif
+
#ifdef WINDOWSNT
/* From w32inevt.c */
extern int faked_key;
@@ -266,6 +352,22 @@
static unsigned int sound_type = 0xFFFFFFFF;
#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
+#ifdef USE_W32_CALL_LISP_THREAD
+static void *cons2ptr(Lisp_Object c)
+{
+ return (void *) (XFASTINT(XCAR(c)) << sizeof(EMACS_INT) /2 * 8 |
+ XFASTINT(XCDR(c)) & ((EMACS_INT)1 <<
+ sizeof(EMACS_INT) /2 * 8) - 1);
+}
+
+static Lisp_Object ptr2cons(const void *p)
+{
+ return Fcons(make_number((EMACS_INT)p >> sizeof(EMACS_UINT)/2*8),
+ make_number((EMACS_INT)p &
+ ((EMACS_INT)1 << sizeof(EMACS_UINT)/2*8)-1));
+}
+#endif
+
/* Let the user specify a display with a frame.
nil stands for the selected frame--or, if that is not a w32 frame,
the first display on the list. */
@@ -337,6 +439,21 @@
void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
+#ifdef USE_W32_IME
+static void w32_set_ime_conv_window (HWND, struct frame *);
+static void w32_set_ime_status (HWND, int);
+static int w32_get_ime_status (HWND);
+static int w32_set_ime_mode (HWND, int, int);
+#if !defined(USE_W32_CALL_LISP_THREAD)
+void w32_set_ime_logfont (HWND, struct frame *);
+static void w32_set_ime_font (HWND);
+#else
+static void w32_set_ime_font (HWND, struct frame *);
+#endif
+static BOOL w32_get_ime_composition_string (HWND);
+static LRESULT CALLBACK conversion_agent_wndproc (HWND, UINT, WPARAM, LPARAM);
+static int initialize_conversion_agent (void);
+#endif /* USE_W32_IME */
@@ -1886,14 +2003,14 @@
Cursor
w32_load_cursor (LPCTSTR name)
{
- /* Try first to load cursor from application resource. */
- Cursor cursor = LoadImage ((HINSTANCE) GetModuleHandle (NULL),
- name, IMAGE_CURSOR, 0, 0,
+ /* Try first to load a shared predefined cursor. */
+ Cursor cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0,
LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
if (!cursor)
{
- /* Then try to load a shared predefined cursor. */
- cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0,
+ /* Then try to load cursor from application resource. */
+ cursor = LoadImage ((HINSTANCE) GetModuleHandle (NULL),
+ name, IMAGE_CURSOR, 0, 0,
LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
}
return cursor;
@@ -1985,12 +2102,20 @@
if (hwnd)
{
+ static int initialized = 0;
+
SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
+ if (!initialized && (w32_major_version > 6 || w32_major_version >= 6 && w32_minor_version >= 2))
+ {
+ ShowWindow (hwnd, SW_MINIMIZE); ShowWindow (hwnd, SW_RESTORE);
+ initialized = 1;
+ }
+
/* Enable drag-n-drop. */
DragAcceptFiles (hwnd, TRUE);
@@ -2463,6 +2588,25 @@
*/
+
+#ifdef USE_W32_CALL_LISP_THREAD
+/* enable APC */
+static BOOL w32_getmessage(LPMSG msg, HWND hwnd,
+ UINT msg_low, UINT msg_high)
+{
+ BOOL ret;
+ DWORD v;
+ /* some message was marked as seened. so we should peek message queue */
+ while ((ret = (w32_unicode_gui ? PeekMessageW : PeekMessageA)(msg, hwnd, msg_low, msg_high, PM_REMOVE)) == 0)
+ while ((v = MsgWaitForMultipleObjectsEx
+ (0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE)) != WAIT_OBJECT_0)
+ if (v != WAIT_IO_COMPLETION)
+ abort();
+
+ return (msg->message != WM_QUIT) ? ret : 0;
+}
+#endif
+
/* Main message dispatch loop. */
static void
@@ -2474,7 +2618,11 @@
msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
+#if !defined(USE_W32_CALL_LISP_THREAD)
while ((w32_unicode_gui ? GetMessageW : GetMessageA) (&msg, NULL, 0, 0))
+#else
+ while (w32_getmessage (&msg, NULL, 0, 0))
+#endif
{
/* DebPrint (("w32_msg_pump: %s time:%u\n", */
@@ -2687,7 +2835,13 @@
{
MSG msg;
deferred_msg dummy_buf;
+#ifdef USE_W32_CALL_LISP_THREAD
+#if GC_MARK_STACK
+ Lisp_Object dummy;
+ stack_base = &dummy;
+#endif
+#endif /* USE_W32_CALL_LISP_THREAD */
/* Ensure our message queue is created */
PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
@@ -2822,10 +2976,16 @@
f = x_window_to_frame (dpyinfo, hwnd);
if (f)
{
+#if 0
HDC hdc = get_frame_dc (f);
GetUpdateRect (hwnd, &wmsg.rect, FALSE);
w32_clear_rect (f, hdc, &wmsg.rect);
release_frame_dc (f, hdc);
+#else
+ HDC hdc = (HDC)wParam;
+ GetUpdateRect (hwnd, &wmsg.rect, FALSE);
+ w32_clear_rect (f, hdc, &wmsg.rect);
+#endif
#if defined (W32_DEBUG_DISPLAY)
DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
@@ -3149,6 +3309,24 @@
TranslateMessage (&windows_msg);
goto dflt;
}
+#ifdef USE_W32_IME
+ else
+ {
+ MSG ime_undo_test_msg;
+
+ if (wParam == VK_BACK
+ && ctrl_modifier == w32_get_key_modifiers (wParam, lParam)
+ && w32_get_ime_status (hwnd) != 0
+ && PeekMessage (&ime_undo_test_msg, hwnd, WM_KEYDOWN, WM_KEYDOWN, PM_NOYIELD | PM_NOREMOVE) != 0
+ && ime_undo_test_msg.wParam == VK_BACK
+ && ime_undo_test_msg.lParam == 0x40000001
+ )
+ {
+ post_character_message (hwnd, msg, wParam, lParam, 0);
+ break;
+ }
+ }
+#endif
/* Fall through */
@@ -3168,6 +3346,7 @@
w32_get_key_modifiers (wParam, lParam));
break;
+#ifndef USE_W32_IME
case WM_UNICHAR:
/* WM_UNICHAR looks promising from the docs, but the exact
circumstances in which TranslateMessage sends it is one of those
@@ -3286,6 +3465,7 @@
case WM_IME_ENDCOMPOSITION:
ignore_ime_char = 0;
goto dflt;
+#endif /* USE_W32_IME */
/* Simulate middle mouse button events when left and right buttons
are used together, but only if user has two button mouse. */
@@ -4074,8 +4254,86 @@
case WM_EMACS_FILENOTIFY:
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
return 1;
+#ifdef USE_W32_IME
+ case WM_IME_NOTIFY:
+ if (wParam == IMN_SETOPENSTATUS)
+ {
+ if (w32_get_ime_status(hwnd)){
+ struct frame *f = x_window_to_frame (dpyinfo, hwnd);
+ if (f) {
+ set_ime_font = 0;
+ w32_set_ime_conv_window (hwnd, f);
+ }
+ }
+ if (!IME_event_off_count)
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_STATUS, 0, 0);
+ else
+ IME_event_off_count--;
+ }
+ goto dflt;
+
+ case WM_IME_STARTCOMPOSITION:
+ {
+ struct frame *f = x_window_to_frame (dpyinfo, hwnd);
+ if (f && !set_ime_font)
+ {
+#if !defined(USE_W32_CALL_LISP_THREAD)
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_SET_FONT, (WPARAM) f, 0);
+#else /* USE_W32_CALL_LISP_THREAD */
+ w32_set_ime_font(hwnd, f);
+#endif /* USE_W32_CALL_LISP_THREAD */
+ set_ime_font = 1;
+ }
+ }
+ goto dflt;
+
+ case WM_IME_SETCONTEXT:
+ set_ime_font = 0;
+ goto dflt;
+
+ case WM_IME_COMPOSITION:
+ if (lParam & GCS_RESULTSTR)
+ if (w32_get_ime_composition_string (hwnd))
+ return 0;
+ else
+ break;
+ goto dflt;
+
+#ifdef RECONVERSION
+ case WM_IME_REQUEST:
+ if (wParam == IMR_RECONVERTSTRING)
+ {
+ if (!ime_enable_reconversion || !w32_get_ime_status (hwnd))
+ return 0;
+ if (lParam)
+ return w32_get_ime_reconversion_string (hwnd,
+ (RECONVERTSTRING*) lParam);
+ else
+ return sizeof (RECONVERTSTRING) + (RECONV_LENG * 2 + 1) * CHRSZ;
+ }
+#ifdef DOCUMENTFEED
+ else if (wParam == IMR_DOCUMENTFEED)
+ {
+ if (!ime_enable_document_feed)
+ return 0;
+ if (lParam)
+ return w32_get_ime_documentfeed_string (hwnd,
+ (RECONVERTSTRING*) lParam);
+ else
+ return sizeof (RECONVERTSTRING) + (DOCFEED_LENG * 2 + DOCFEED_CSTR_LENG + 1) * CHRSZ;
+ }
+#endif
+ goto dflt;
+#endif
+#endif /* USE_W32_IME */
default:
+
+#ifdef USE_W32_IME
+ if (MESSAGE_IMM_COM_P(msg))
+ return conversion_agent_wndproc (hwnd, msg, wParam, lParam);
+#endif /* USE_W32_IME */
+
/* Check for messages registered at runtime. */
if (msg == msh_mousewheel)
{
@@ -4348,7 +4606,8 @@
{
int i;
static char *names[]
- = { "Courier New-10",
+ = { "MS Gothic-12",
+ "Courier New-10",
"-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
"-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
"Fixedsys",
@@ -4370,6 +4629,10 @@
x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
}
x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
+#ifdef USE_W32_IME
+ x_default_parameter (f, parms, Qime_font, Qnil,
+ "ime-font", "IME-Font", RES_TYPE_STRING);
+#endif
}
DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
@@ -6486,6 +6749,17 @@
return 0;
}
+#ifndef CYGWIN
+static int CALLBACK
+browse_folder_callback(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)
+{
+ if(uMsg==BFFM_INITIALIZED){
+ SendMessage(hwnd,BFFM_SETSELECTION,(WPARAM)TRUE,lpData);
+ }
+ return 0;
+}
+#endif
+
DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
doc: /* Read file name, prompting with PROMPT in directory DIR.
Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
@@ -6510,6 +6784,10 @@
BOOL file_opened = FALSE;
Lisp_Object orig_dir = dir;
Lisp_Object orig_prompt = prompt;
+#ifndef CYGWIN
+ Lisp_Object file = Qnil;
+ ptrdiff_t count = SPECPDL_INDEX ();
+#endif
/* If we compile with _WIN32_WINNT set to 0x0400 (for NT4
compatibility) we end up with the old file dialogs. Define a big
@@ -6551,6 +6829,9 @@
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, filename);
+#ifndef CYGWIN
+ if (NILP (only_dir_p))
+#endif
{
struct gcpro gcpro1, gcpro2;
GCPRO2 (orig_dir, orig_prompt); /* There is no GCPRON, N>6. */
@@ -6726,14 +7007,14 @@
block_input ();
if (use_unicode)
{
- file_details_w->lpfnHook = file_dialog_callback;
+ file_details_w->lpfnHook = (LPOFNHOOKPROC) file_dialog_callback;
file_opened = GetOpenFileNameW (file_details_w);
}
#ifndef NTGUI_UNICODE
else
{
- file_details_a->lpfnHook = file_dialog_callback;
+ file_details_a->lpfnHook = (LPOFNHOOKPROC) file_dialog_callback;
file_opened = GetOpenFileNameA (file_details_a);
}
@@ -6786,6 +7067,69 @@
UNGCPRO;
}
+#ifndef CYGWIN
+ else
+ {
+ BROWSEINFO bi = {
+ FRAME_W32_WINDOW (f),
+ NULL,
+ SDATA (filename),
+ SDATA (prompt),
+#ifdef BIF_EDITBOX
+ (!NILP (mustmatch) ? 0 : BIF_EDITBOX) |
+#endif
+#ifdef BIF_BROWSEINCLUDEFILES
+ BIF_BROWSEINCLUDEFILES |
+#endif
+#ifdef BIF_BROWSEINCLUDEURLS
+ BIF_BROWSEINCLUDEURLS |
+#endif
+#ifdef BIF_NEWDIALOGSTYLE
+ BIF_NEWDIALOGSTYLE |
+#endif
+#ifdef BIF_UAHINT
+ BIF_UAHINT |
+#endif
+#ifdef BIF_RETURNONLYFSDIRS
+ BIF_RETURNONLYFSDIRS |
+#endif
+ BIF_BROWSEFORCOMPUTER,
+ (BFFCALLBACK)browse_folder_callback,
+ (LPARAM) SDATA (dir),
+ 0
+ };
+ LPITEMIDLIST pidl = NULL;
+
+ /* Prevent redisplay. */
+ specbind (Qinhibit_redisplay, Qt);
+ block_input ();
+
+ pidl = SHBrowseForFolder(&bi);
+ if (pidl) {
+ SHGetPathFromIDList(pidl, SDATA (filename));
+ CoTaskMemFree(pidl);
+ }
+
+ unblock_input ();
+
+ if (pidl)
+ {
+ memcpy (filename_buf_a, SDATA (filename), SBYTES (filename) + 1);
+ dostounix_filename (filename_buf_a);
+
+ file = DECODE_FILE (build_string (filename_buf_a));
+ }
+ /* User cancelled the dialog without making a selection. */
+ else if (!CommDlgExtendedError ())
+ file = Qnil;
+ /* An error occurred, fallback on reading from the mini-buffer. */
+ else
+ file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
+ dir, mustmatch, dir, Qfile_name_history,
+ default_filename, Qnil);
+ file = unbind_to (count, file);
+ }
+#endif
/* Make "Cancel" equivalent to C-g. */
if (NILP (filename))
@@ -6895,6 +7239,1470 @@
/***********************************************************************
+ Input Method Editor
+ ***********************************************************************/
+#ifdef USE_W32_IME
+BOOL fIME = FALSE;
+
+typedef BOOL (WINAPI *IMMGETOPENSTATUSPROC)(HIMC);
+IMMGETOPENSTATUSPROC ImmGetOpenStatusProc;
+
+typedef BOOL (WINAPI *IMMSETOPENSTATUSPROC)(HIMC, BOOL);
+IMMSETOPENSTATUSPROC ImmSetOpenStatusProc;
+
+typedef BOOL (WINAPI *IMMSETCOMPOSITIONWINDOWPROC)(HIMC, LPCOMPOSITIONFORM);
+IMMSETCOMPOSITIONWINDOWPROC ImmSetCompositionWindowProc;
+
+typedef LONG (WINAPI *IMMGETCOMPOSITIONSTRINGPROC)
+ (HIMC, DWORD, LPVOID, DWORD);
+IMMGETCOMPOSITIONSTRINGPROC ImmGetCompositionStringProc;
+
+typedef LONG (WINAPI *IMMSETCOMPOSITIONSTRINGPROC)
+ (HIMC, DWORD, LPCVOID, DWORD, LPCVOID, DWORD);
+IMMSETCOMPOSITIONSTRINGPROC ImmSetCompositionStringProc;
+
+typedef BOOL (WINAPI *IMMSETCOMPOSITIONFONTPROC) (HIMC, LPLOGFONTA);
+IMMSETCOMPOSITIONFONTPROC ImmSetCompositionFontProc;
+
+typedef HIMC (WINAPI *IMMGETCONTEXTPROC)(HWND);
+IMMGETCONTEXTPROC ImmGetContextProc;
+
+typedef BOOL (WINAPI *IMMGETCONVERSIONSTATUSPROC)(HIMC, LPDWORD, LPDWORD);
+IMMGETCONVERSIONSTATUSPROC ImmGetConversionStatusProc;
+
+typedef BOOL (WINAPI *IMMSETCONVERSIONSTATUSPROC)(HIMC, DWORD, DWORD);
+IMMSETCONVERSIONSTATUSPROC ImmSetConversionStatusProc;
+
+typedef BOOL (WINAPI *IMMGETCONVERSIONLISTPROC)
+ (HKL, HIMC, LPCTSTR, LPCANDIDATELIST, DWORD, UINT);
+IMMGETCONVERSIONLISTPROC ImmGetConversionListProc;
+
+typedef BOOL (WINAPI *IMMCONFIGUREIMEPROC)(HKL, HWND, DWORD, LPVOID);
+IMMCONFIGUREIMEPROC ImmConfigureIMEProc;
+
+typedef BOOL (WINAPI *IMMNOTIFYIMEPROC)(HIMC, DWORD, DWORD, DWORD);
+IMMNOTIFYIMEPROC ImmNotifyIMEProc;
+
+typedef BOOL (WINAPI *IMMRELEASECONTEXTPROC)(HWND, HIMC);
+IMMRELEASECONTEXTPROC ImmReleaseContextProc;
+
+typedef HIMC (WINAPI *IMMCREATECONTEXTPROC)(void);
+IMMCREATECONTEXTPROC ImmCreateContextProc;
+
+typedef BOOL (WINAPI *IMMDESTROYCONTEXTPROC)(HIMC);
+IMMDESTROYCONTEXTPROC ImmDestroyContextProc;
+
+typedef HIMC (WINAPI *IMMASSOCIATECONTEXTPROC) (HWND, HIMC);
+IMMASSOCIATECONTEXTPROC ImmAssociateContextProc;
+
+typedef BOOL (WINAPI *IMMGETCANDIDATELISTPROC)
+ (HIMC, DWORD, LPCANDIDATELIST, DWORD);
+IMMGETCANDIDATELISTPROC ImmGetCandidateListProc;
+
+typedef BOOL (WINAPI *IMMGETCANDIDATELISTCOUNTPROC) (HIMC, LPDWORD);
+IMMGETCANDIDATELISTCOUNTPROC ImmGetCandidateListCountProc;
+
+typedef BOOL (WINAPI *IMMGETHOTKEYPROC)(DWORD, LPUINT, LPUINT, LPHKL);
+IMMGETHOTKEYPROC ImmGetHotKeyProc;
+
+typedef BOOL (WINAPI *IMMGETPROPERTYPROC)(HKL, DWORD);
+IMMGETPROPERTYPROC ImmGetPropertyProc;
+
+// Lisp_Object Vime_control;
+
+static void
+w32_set_ime_conv_window (hwnd, f)
+ HWND hwnd;
+ struct frame *f;
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HIMC himc;
+ COMPOSITIONFORM compform;
+ struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+
+ /* If Vw32_ime_composition_window is set, try it. */
+ if (!NILP (Vw32_ime_composition_window)
+ && WINDOWP (Vw32_ime_composition_window)
+ && WINDOW_FRAME (XWINDOW (Vw32_ime_composition_window))
+ == WINDOW_FRAME (w))
+ w = XWINDOW (Vw32_ime_composition_window);
+
+ himc = (ImmGetContextProc) (hwnd);
+ compform.dwStyle = CFS_RECT;
+
+ compform.ptCurrentPos.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+
+ compform.ptCurrentPos.y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
+#if 0
+ if (FRAME_FONT (f)->vertical_centering == 1)
+ compform.ptCurrentPos.y += FRAME_FONT (f)->baseline_offset;
+#endif
+
+ compform.rcArea.left = (WINDOW_BOX_LEFT_EDGE_X (w)
+ + WINDOW_LEFT_MARGIN_WIDTH (w)
+ + WINDOW_LEFT_FRINGE_WIDTH (w));
+
+ compform.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
+ + WINDOW_HEADER_LINE_HEIGHT (w));
+
+ compform.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
+ - WINDOW_RIGHT_MARGIN_WIDTH (w)
+ - WINDOW_RIGHT_FRINGE_WIDTH (w)) + 1;
+
+ compform.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
+ - WINDOW_MODE_LINE_HEIGHT (w));
+
+ (ImmSetCompositionWindowProc) (himc, &compform);
+ (ImmReleaseContextProc) (hwnd, himc);
+ }
+}
+
+static void
+w32_set_ime_status (hwnd, openp)
+ HWND hwnd;
+ int openp;
+{
+ HIMC himc;
+
+ himc = (ImmGetContextProc) (hwnd);
+ (ImmSetOpenStatusProc) (himc, openp);
+ (ImmReleaseContextProc) (hwnd, himc);
+}
+
+static int
+w32_get_ime_status (hwnd)
+ HWND hwnd;
+{
+ HIMC himc;
+ int ret;
+
+ himc = (ImmGetContextProc) (hwnd);
+ ret = (ImmGetOpenStatusProc) (himc);
+ (ImmReleaseContextProc) (hwnd, himc);
+
+ return ret;
+}
+
+static int
+w32_set_ime_mode (hwnd, mode, mask)
+ HWND hwnd;
+ int mode;
+ int mask;
+{
+ HIMC himc;
+ DWORD cmode, smode;
+
+ himc = (ImmGetContextProc) (hwnd);
+ if (!(ImmGetConversionStatusProc) (himc, &cmode, &smode))
+ return 0;
+
+ cmode = (cmode & (~mask)) | (mode & mask);
+
+ (ImmSetConversionStatusProc) (himc, cmode, smode);
+ (ImmReleaseContextProc) (hwnd, himc);
+
+ return 1;
+}
+
+static BOOL
+w32_get_ime_composition_string (hwnd)
+ HWND hwnd;
+{
+ HIMC hIMC;
+ int size;
+ HANDLE himestr;
+#ifdef IME_UNICODE
+ LPWSTR lpstr;
+#else
+ LPSTR lpstr;
+#endif
+
+ struct frame *f;
+
+ hIMC = (ImmGetContextProc) (hwnd);
+ if (!hIMC)
+ return FALSE;
+
+ size = (ImmGetCompositionStringProc) (hIMC, GCS_RESULTSTR, NULL, 0);
+#ifdef IME_UNICODE
+ size += sizeof (WCHAR);
+#else
+ size += sizeof (CHAR);
+#endif
+ himestr = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, size);
+ if (!himestr)
+ abort ();
+
+ (ImmGetCompositionStringProc) (hIMC, GCS_RESULTSTR, himestr, size);
+ (ImmReleaseContextProc) (hwnd, hIMC);
+ {
+ W32Msg wmsg;
+ f = SELECTED_FRAME ();
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_REPORT,
+ (WPARAM) himestr, (LPARAM) f);
+ }
+ return TRUE;
+}
+
+#ifdef RECONVERSION
+#ifdef USE_W32_CALL_LISP_THREAD
+struct get_reconversion_string_arg {
+ WPARAM wparam;
+ RECONVERTSTRING *reconv; /* in */
+#ifdef IME_UNICODE
+ unsigned short *compstr; /* in */
+#else
+ unsigned char *compstr; /* in */
+#endif
+ DWORD size; /* in,out */
+};
+#endif /* USE_W32_CALL_LISP_THREAD */
+
+static EMACS_INT compstr_beginning_pos(int max_char)
+{
+ EMACS_INT bol, point = PT, pt;
+ for (bol = XFASTINT(Fline_beginning_position(Qnil)), pt = PT;
+ PT >= bol && PT > point - max_char; ) {
+ pt = PT;
+ if (NILP(Fforward_word (make_number (-1))))
+ break;
+ }
+ Fgoto_char (make_number(point));
+ return pt;
+}
+
+static EMACS_INT compstr_end_pos(int max_char)
+{
+ EMACS_INT eol, point = PT, pt;
+
+ for (eol = XFASTINT(Fline_end_position(Qnil)), pt = PT;
+ PT <= eol && PT < point + max_char;) {
+ pt = PT;
+ if (NILP(Fforward_word (make_number (1))))
+ break;
+ }
+ Fgoto_char (make_number(point));
+ return pt;
+}
+
+#if !defined(USE_W32_CALL_LISP_THREAD)
+static LRESULT
+get_reconversion_string (HWND hwnd,
+ RECONVERTSTRING *reconv,
+ unsigned short *compstr)
+{
+ EMACS_INT pt, pt_byte, start, end, len, t_start, t_end, compstr_len;
+ W32Msg wmsg;
+
+ if (!NILP (BVAR (current_buffer, read_only)))
+ return 0;
+
+ pt = PT;
+ pt_byte = PT_BYTE;
+
+ if (compstr)
+ {
+ t_start = PT;
+ start = compstr_beginning_pos (DOCFEED_LENG);
+ end = compstr_end_pos (DOCFEED_LENG);
+ }
+ else if (!NILP (BVAR (current_buffer, mark_active))
+ && !NILP (Vtransient_mark_mode))
+ {
+ if (marker_position (BVAR (current_buffer, mark)) < PT)
+ {
+ t_start = marker_position (BVAR (current_buffer, mark));
+ t_end = PT;
+ }
+ else
+ {
+ t_start = PT;
+ t_end = marker_position (BVAR (current_buffer, mark));
+ }
+ Fgoto_char (make_number (t_end));
+ while (!NILP (Fbolp ()) && t_start < PT)
+ Fforward_char (make_number (-1));
+ if (t_start >= PT)
+ return 0;
+ t_end = PT;
+ }
+ else
+ {
+ if (NILP (Feobp ()))
+ Fforward_char (make_number (1));
+ if (!NILP (Fforward_word (make_number (-1))))
+ t_start = PT;
+ else
+ {
+ SET_PT_BOTH (pt, pt_byte);
+ return 0;
+ }
+ Fforward_word (make_number (1));
+ t_end = PT;
+ SET_PT_BOTH (pt, pt_byte);
+ if (t_end < PT)
+ return 0;
+ }
+
+ if (!compstr)
+ {
+ if (t_start == t_end)
+ return 0;
+
+ Fgoto_char (make_number (t_start));
+ start = compstr_beginning_pos (RECONV_LENG);
+ Fgoto_char (make_number (t_end));
+ end = compstr_end_pos (RECONV_LENG);
+ }
+
+ len = end - start;
+ if (reconv)
+ {
+ int pos;
+ WCHAR *s;
+
+ s = (WCHAR *) (reconv + 1);
+
+ for (pos = start; pos < t_start; pos++)
+ *s++ = (WCHAR) FETCH_CHAR (CHAR_TO_BYTE (pos));
+
+ if (compstr)
+ {
+ for (compstr_len = 0; compstr[compstr_len]; compstr_len++)
+ *s++ = compstr[compstr_len];
+
+ len += compstr_len;
+ }
+ else
+ compstr_len = t_end - t_start;
+
+ for (; pos < end; pos++)
+ *s++ = (WCHAR) FETCH_CHAR (CHAR_TO_BYTE (pos));
+
+ *s = 0;
+ }
+ else
+ {
+ SET_PT_BOTH (pt, pt_byte);
+ if (compstr)
+ {
+ for (compstr_len = 0; compstr[compstr_len]; compstr_len++)
+ ;
+
+ len += compstr_len;
+ }
+ return (sizeof (RECONVERTSTRING) + (len + 1) * CHRSZ);
+ }
+
+ reconv->dwStrOffset = sizeof (RECONVERTSTRING);
+ reconv->dwStrLen = len;
+ reconv->dwCompStrOffset =
+ reconv->dwTargetStrOffset = (t_start - start) * CHRSZ;
+ reconv->dwCompStrLen =
+ reconv->dwTargetStrLen = compstr_len;
+
+ if (!compstr)
+ my_post_msg (&wmsg, hwnd, WM_MULE_IME_DEL_RANGE, (WPARAM) t_start, (LPARAM) t_end);
+
+ return (reconv->dwSize = sizeof (RECONVERTSTRING) + (len + 1) * CHRSZ);
+}
+
+static LRESULT
+w32_get_ime_reconversion_string (HWND hwnd,
+ RECONVERTSTRING *reconv)
+{
+ return get_reconversion_string (hwnd, reconv, NULL);
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+static Lisp_Object
+get_reconversion_string (Lisp_Object arg_)
+{
+ struct get_reconversion_string_arg *arg = cons2ptr(arg_);
+ EMACS_INT pt, pt_byte, point, start, end, len,
+ t_start, t_end, del_start, del_end, compstr_len = 0;
+ Lisp_Object str;
+ struct gcpro gcpro1;
+
+ if (!NILP (BVAR (current_buffer, read_only))) {
+ arg->size = 0;
+ return Qnil;
+ }
+
+ pt = PT;
+ pt_byte = PT_BYTE;
+
+ if (arg->compstr) { /* DOCUMENT_FEED */
+#ifdef DOCUMENTFEED
+ t_start = compstr_beginning_pos(DOCFEED_LENG);
+ t_end = compstr_end_pos(DOCFEED_LENG);
+ point = PT;
+#endif
+ } else if (!NILP (BVAR (current_buffer, mark_active))
+ && !NILP (Vtransient_mark_mode)) {
+ if (marker_position (BVAR (current_buffer, mark)) < PT) {
+ t_start = marker_position (BVAR (current_buffer, mark));
+ point = t_end = PT;
+ } else {
+ point = t_start = PT;
+ t_end = marker_position (BVAR (current_buffer, mark));
+ }
+ Fgoto_char(make_number(t_end));
+ while (!NILP(Fbolp()) && t_start < PT)
+ Fforward_char(make_number(-1));
+ if (t_start >= PT)
+ return Qnil;
+ t_end = PT;
+ } else {
+ point = PT;
+
+ while (!NILP(Fbolp()) && NILP(Fbobp()))
+ Fforward_char(make_number(1));
+ if (!NILP(Fbobp()))
+ return Qnil;
+
+ t_end = PT;
+ Fforward_word (make_number (-1));
+ t_start = PT;
+ }
+ if (t_start == t_end) {
+ arg->size = 0;
+ return Qnil;
+ }
+
+ if (arg->compstr) {
+ start = t_start;
+ end = t_end;
+ t_start = point - t_start;
+ } else {
+
+ start = compstr_beginning_pos(RECONV_LENG);
+ end = compstr_end_pos(RECONV_LENG);
+
+ del_start = t_start;
+ del_end = t_end;
+
+ t_start -= start;
+ t_end -= start;
+ }
+
+ GCPRO1(str);
+ str = make_buffer_string (start, end, 1);
+
+#ifdef IME_UNICODE
+ len = end - start;
+ if (arg->reconv) {
+ int pos;
+ WCHAR *uc_code, *s;
+
+ uc_code = (WCHAR *) (arg->reconv + 1);
+ s = uc_code;
+
+ for (pos = 0; pos < t_start; pos++)
+ *s++ = (WCHAR) XFASTINT(Faref(str, make_number(pos)));
+
+ if (arg->compstr)
+ for (compstr_len = 0; arg->compstr[compstr_len]; compstr_len++)
+ *s++ = arg->compstr[compstr_len];
+
+ for (; pos < len; pos++)
+ *s++ = (WCHAR) XFASTINT(Faref(str, make_number(pos)));
+
+ *s = 0;
+ } else {
+ if (arg->compstr)
+ for (compstr_len = 0; arg->compstr[compstr_len]; compstr_len++)
+ ;
+ }
+
+#define STROFFSET(s,o) ((o) * CHRSZ)
+#define STRSIZE(s, b, e) ((e) - (b))
+#else /* IME_UNICODE */
+ if (!arg->reconv
+ && !NILP (Ftext_property_any (make_number (0),
+ Flength (str),
+ intern ("read-only"),
+ Qt,
+ str))) {
+ SET_PT_BOTH (pt, pt_byte);
+ UNGCPRO;
+ return Qt; /* Cannot signal here */
+ }
+ str = ENCODE_SYSTEM (str);
+
+ len = SBYTES(str);
+ if (arg->compstr)
+ compstr_len = strlen(arg->compstr);
+
+#define STROFFSET(s,o) (_mbsninc(SDATA(s), (o)) - SDATA(s))
+#define STRSIZE(s, b, e) (_mbsninc(SDATA(s), (e)) - _mbsninc(SDATA(s), (b)))
+
+ if (arg->reconv) {
+ if (arg->compstr) {
+ LPSTR s = (LPSTR)(arg->reconv + 1);
+ strncpy(s, SDATA(str), STROFFSET(str, t_start));
+ strcpy(s + STROFFSET(str, t_start), arg->compstr);
+ strcpy(s + STROFFSET(str, t_start) + compstr_len,
+ SDATA(str) + STROFFSET(str, t_start));
+ } else
+ strcpy ((LPSTR)(arg->reconv + 1), SDATA(str));
+ }
+#endif
+
+ if (arg->reconv) {
+ arg->reconv->dwStrOffset = sizeof (RECONVERTSTRING);
+ arg->reconv->dwStrLen = len + compstr_len;
+
+ if (arg->compstr) {
+ arg->reconv->dwCompStrOffset =
+ arg->reconv->dwTargetStrOffset = STROFFSET(str, t_start);
+ arg->reconv->dwCompStrLen =
+ arg->reconv->dwTargetStrLen = compstr_len;
+
+ } else {
+ arg->reconv->dwTargetStrOffset =
+ arg->reconv->dwCompStrOffset = STROFFSET(str, t_start);
+ arg->reconv->dwTargetStrLen =
+ arg->reconv->dwCompStrLen = STRSIZE(str, t_start, t_end);
+
+ del_range(del_start, del_end);
+ Fgoto_char (make_number(del_start));
+ }
+ } else {
+ SET_PT_BOTH (pt, pt_byte);
+ }
+ arg->size = sizeof(RECONVERTSTRING) + (len + compstr_len + 1) * CHRSZ;
+ if (arg->reconv != NULL && arg->compstr != NULL)
+ arg->compstr[0] = 0;
+
+ UNGCPRO;
+ return Qt;
+}
+
+static LRESULT
+w32_get_ime_reconversion_string(HWND hwnd,
+ RECONVERTSTRING *reconv)
+{
+ struct get_reconversion_string_arg grs =
+ {IMR_RECONVERTSTRING, reconv, NULL, 0};
+
+ if (NILP(w32_call_lisp_thread(get_reconversion_string, &grs)))
+ return 0;
+ return reconv->dwSize;
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#endif /* RECONVERSION */
+
+#if defined(DOCUMENTFEED)
+#if !defined(USE_W32_CALL_LISP_THREAD)
+static LRESULT
+w32_get_ime_documentfeed_string (HWND hwnd,
+ RECONVERTSTRING *reconv)
+{
+ unsigned short ime_compstr[DOCFEED_CSTR_LENG];
+ HIMC hIMC;
+ LONG l;
+
+ if (hIMC = (ImmGetContextProc) (hwnd))
+ {
+ if ((ImmGetCompositionStringProc) (hIMC, GCS_COMPSTR, NULL, 0)
+ >= DOCFEED_CSTR_LENG * CHRSZ)
+ {
+ (ImmReleaseContextProc) (hwnd, hIMC);
+ return 0;
+ }
+
+ switch (l = (ImmGetCompositionStringProc)
+ (hIMC, GCS_COMPSTR, ime_compstr,
+ (DOCFEED_CSTR_LENG - 1) * CHRSZ))
+ {
+ case IMM_ERROR_NODATA:
+ case IMM_ERROR_GENERAL:
+ ime_compstr[0] = 0;
+ break;
+ default:
+ ime_compstr[l / CHRSZ] = 0;
+ break;
+ }
+ (ImmReleaseContextProc) (hwnd, hIMC);
+
+ return get_reconversion_string (hwnd, reconv, ime_compstr);
+ }
+
+ return 0;
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+static LRESULT
+w32_get_ime_documentfeed_string(HWND hwnd,
+ RECONVERTSTRING *reconv)
+{
+#ifdef IME_UNICODE
+ unsigned short ime_compstr[DOCFEED_CSTR_LENG];
+#else
+ unsigned char ime_compstr[DOCFEED_CSTR_LENG];
+#endif
+ struct get_reconversion_string_arg grs =
+ {IMR_DOCUMENTFEED, reconv, ime_compstr, 0} ;
+ HIMC himc;
+ LONG l;
+
+ if (!(himc = (ImmGetContextProc) (hwnd)))
+ return 0;
+
+ if (ImmGetCompositionStringProc(himc, GCS_COMPSTR, NULL, 0)
+ >= DOCFEED_CSTR_LENG * CHRSZ) {
+ (ImmReleaseContextProc) (hwnd, himc);
+ return 0;
+ }
+
+ switch (l = (ImmGetCompositionStringProc)
+ (himc, GCS_COMPSTR, ime_compstr,
+ (DOCFEED_CSTR_LENG - 1) * CHRSZ)) {
+
+ case IMM_ERROR_NODATA:
+ case IMM_ERROR_GENERAL:
+ ime_compstr[0] = 0;
+ break;
+ default:
+ ime_compstr[l / CHRSZ] = 0;
+ break;
+ }
+ (ImmReleaseContextProc) (hwnd, himc);
+
+ grs.size = l;
+
+ if (NILP(w32_call_lisp_thread(get_reconversion_string, &grs)))
+ return 0;
+ return reconv->dwSize;
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#endif /* DOCUMENTFEED */
+
+void
+w32_ime_control_init (void)
+{
+ HMODULE hImm32;
+ HMODULE hUser32;
+
+ hImm32 = GetModuleHandle ("IMM32.DLL");
+ if (!hImm32)
+ hImm32 = LoadLibrary ("IMM32.DLL");
+
+ fIME = FALSE;
+ Vime_control = Qnil;
+ IME_event_off_count = 0;
+
+ if (hImm32)
+ {
+ ImmGetOpenStatusProc =
+ (IMMGETOPENSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmGetOpenStatus_Name);
+ ImmSetOpenStatusProc =
+ (IMMSETOPENSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmSetOpenStatus_Name);
+ ImmSetCompositionWindowProc =
+ (IMMSETCOMPOSITIONWINDOWPROC)
+ GetProcAddress (hImm32,
+ ImmSetCompositionWindow_Name);
+ ImmGetContextProc =
+ (IMMGETCONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmGetContext_Name);
+ ImmGetConversionStatusProc =
+ (IMMGETCONVERSIONSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmGetConversionStatus_Name);
+ ImmSetConversionStatusProc =
+ (IMMSETCONVERSIONSTATUSPROC)
+ GetProcAddress (hImm32,
+ ImmSetConversionStatus_Name);
+ ImmNotifyIMEProc =
+ (IMMNOTIFYIMEPROC)
+ GetProcAddress (hImm32,
+ ImmNotifyIME_Name);
+ ImmReleaseContextProc =
+ (IMMRELEASECONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmReleaseContext_Name);
+ ImmCreateContextProc =
+ (IMMCREATECONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmCreateContext_Name);
+ ImmDestroyContextProc =
+ (IMMDESTROYCONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmDestroyContext_Name);
+ ImmAssociateContextProc =
+ (IMMASSOCIATECONTEXTPROC)
+ GetProcAddress (hImm32,
+ ImmAssociateContext_Name);
+ ImmGetHotKeyProc =
+ (IMMGETHOTKEYPROC)
+ GetProcAddress (hImm32,
+ ImmGetHotKey_Name);
+ ImmGetPropertyProc =
+ (IMMGETPROPERTYPROC)
+ GetProcAddress (hImm32, ImmGetProperty_Name);
+ ImmGetCompositionStringProc =
+ (IMMGETCOMPOSITIONSTRINGPROC)
+ GetProcAddress (hImm32, ImmGetCompositionString_Name);
+ ImmSetCompositionStringProc =
+ (IMMSETCOMPOSITIONSTRINGPROC)
+ GetProcAddress (hImm32, ImmSetCompositionString_Name);
+ ImmSetCompositionFontProc =
+ (IMMSETCOMPOSITIONFONTPROC)
+ GetProcAddress (hImm32, ImmSetCompositionFont_Name);
+ ImmGetConversionListProc =
+ (IMMGETCONVERSIONLISTPROC)
+ GetProcAddress (hImm32,
+ ImmGetConversionList_Name);
+ ImmConfigureIMEProc =
+ (IMMCONFIGUREIMEPROC)
+ GetProcAddress (hImm32,
+ ImmConfigureIME_Name);
+ ImmGetCandidateListProc =
+ (IMMGETCANDIDATELISTPROC)
+ GetProcAddress (hImm32,
+ ImmGetCandidateList_Name);
+ ImmGetCandidateListCountProc =
+ (IMMGETCANDIDATELISTCOUNTPROC)
+ GetProcAddress (hImm32,
+ ImmGetCandidateListCount_Name);
+
+ if (ImmGetOpenStatusProc &&
+ ImmSetOpenStatusProc &&
+ ImmSetCompositionWindowProc &&
+ ImmGetCompositionStringProc &&
+ ImmSetCompositionStringProc &&
+ ImmSetCompositionFontProc &&
+ ImmGetPropertyProc &&
+ ImmGetContextProc &&
+ ImmGetConversionStatusProc &&
+ ImmSetConversionStatusProc &&
+ ImmGetConversionListProc &&
+ ImmConfigureIMEProc &&
+ ImmNotifyIMEProc &&
+ ImmReleaseContextProc &&
+ ImmCreateContextProc &&
+ ImmDestroyContextProc &&
+ ImmAssociateContextProc &&
+ ImmGetCandidateListProc &&
+ ImmGetCandidateListCountProc &&
+ ImmGetHotKeyProc)
+ {
+ fIME = TRUE;
+ Vime_control = Qt;
+ }
+ }
+}
+
+#ifdef USE_W32_CALL_LISP_THREAD
+struct apc_data {
+ Lisp_Object (*func)(Lisp_Object);
+ Lisp_Object val;
+ void *arg;
+ HANDLE ev;
+};
+
+static Lisp_Object apc_error_handler (Lisp_Object arg)
+{
+ return Qnil;
+}
+
+static VOID CALLBACK apc_func_stub(ULONG_PTR data_)
+{
+ struct apc_data *apc_data = (struct apc_data *)data_;
+ Lisp_Object arg = ptr2cons(apc_data->arg);
+ struct gcpro gcpro1;
+
+ GCPRO1(arg);
+ apc_data->val =
+ internal_condition_case_1
+ (apc_data->func, arg, Qt, apc_error_handler);
+
+ UNGCPRO;
+ SetEvent(apc_data->ev);
+}
+
+static Lisp_Object w32_call_lisp_thread
+(Lisp_Object (*func)(Lisp_Object), void *arg)
+{
+ struct apc_data apc_data = {
+ func, Qnil, arg,
+ CreateEvent(NULL, FALSE, FALSE, NULL)
+ };
+ DWORD v;
+ deferred_msg dummy = {0};
+
+ dummy.completed = 1;
+
+
+ w32_apc_mutex_acquire();
+ if (apc_data.ev == NULL)
+ abort();
+
+ if (QueueUserAPC(apc_func_stub,
+ hMainThread, (ULONG_PTR)&apc_data) == 0)
+ abort ();
+
+ while ((v = MsgWaitForMultipleObjectsEx
+ (1, &apc_data.ev, INFINITE, QS_SENDMESSAGE, MWMO_ALERTABLE)) != WAIT_OBJECT_0)
+ if (v == WAIT_OBJECT_0 + 1)
+ w32_msg_pump(&dummy);
+ else if (v != WAIT_IO_COMPLETION)
+ abort();
+
+ w32_apc_mutex_release();
+ return apc_data.val;
+}
+#endif
+
+#ifdef HAVE_NTGUI
+EXFUN (Ffont_at, 3);
+#if !defined(USE_W32_CALL_LISP_THREAD)
+static int
+need_set_ime_font (PLOGFONT p)
+{
+ if (!p ||
+ (p->lfHeight == ime_logfont.lfHeight
+ && p->lfWidth == ime_logfont.lfWidth
+ && p->lfEscapement == ime_logfont.lfEscapement
+ && p->lfOrientation == ime_logfont.lfOrientation
+ && p->lfWeight == ime_logfont.lfWeight
+ && p->lfItalic == ime_logfont.lfItalic
+ && p->lfUnderline == ime_logfont.lfUnderline
+ && p->lfStrikeOut == ime_logfont.lfStrikeOut
+ && p->lfCharSet == ime_logfont.lfCharSet
+ && p->lfOutPrecision == ime_logfont.lfOutPrecision
+ && p->lfClipPrecision == ime_logfont.lfClipPrecision
+ && p->lfQuality == ime_logfont.lfQuality
+ && p->lfPitchAndFamily == ime_logfont.lfPitchAndFamily
+ && strncmp (p->lfFaceName, ime_logfont.lfFaceName, LF_FACESIZE) == 0))
+ return 0;
+ else
+ return 1;
+}
+void
+w32_set_ime_logfont (hwnd, f)
+ HWND hwnd;
+ struct frame *f;
+{
+ Lisp_Object ime_font = Qnil, temp = Qnil, font = Qnil, family;
+ struct gcpro gcpro1, gcpro2;
+ extern Lisp_Object QCfamily;
+ int fsid = -1;
+ LOGFONT logfont = {0};
+
+ if (!IsWindow (hwnd))
+ return;
+
+ if (!fIME || NILP(Vime_control))
+ return;
+
+ GCPRO2(font, temp);
+
+ if (STRINGP(ime_font = get_frame_param (f, Qime_font))
+ /* fontset */
+ && ((fsid = fs_query_fontset(ime_font, 0)) >= 0
+ && !NILP(font = fontset_ascii(fsid))
+ && !NILP(font = font_spec_from_name(font))
+ && !NILP(temp = Ffontset_font(temp, make_number(0x3042), Qnil))
+ && !NILP(family = XCAR(temp))
+ /* font */
+ || !NILP(font = font_spec_from_name(ime_font))
+ && SYMBOLP(family = AREF (font, FONT_FAMILY_INDEX))
+ && STRINGP(family = SYMBOL_NAME(family)))
+
+ /* use font object */
+ /* frame-parameter */
+ || (FONTP(font = ime_font)
+ /* frame fontset */
+ || ((fsid = FRAME_FONTSET(f)) >= 0
+ && !NILP(font =
+ Ffont_at(make_number(0), Qnil,
+ temp = Fchar_to_string(make_number(0x3042))))))
+ && SYMBOLP(family = Ffont_get(font, QCfamily))
+ && STRINGP(family = SYMBOL_NAME(family))
+ && !NILP(font = copy_font_spec(font))) {
+ Lisp_Object tail;
+
+ fill_in_logfont (f, &logfont, font);
+
+ logfont.lfWidth = 0;
+
+ family = ENCODE_SYSTEM(family);
+
+ strcpy(logfont.lfFaceName, SDATA(family));
+
+ /* rescale */
+ for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail)) {
+ temp = XCAR (tail);
+ if (!FLOATP (XCDR (temp)))
+ continue;
+
+ if (STRINGP (XCAR (temp))) {
+ if (fast_string_match_ignore_case (XCAR (temp), family) >= 0) {
+ logfont.lfHeight *= XFLOAT_DATA (XCDR (temp));
+ break;
+ }
+ } else if (FONT_SPEC_P (XCAR (temp))) {
+ Lisp_Object name;
+ if (!NILP(name = Ffont_get(XCAR (temp), QCfamily)) &&
+ STRINGP(name) &&
+ xstrcasecmp(SDATA(name), SDATA(family)) == 0) {
+ logfont.lfHeight *= XFLOAT_DATA (XCDR (temp));
+ break;
+ }
+ }
+ }
+ } else {
+ HFONT hfont = FONT_HANDLE (FRAME_FONT (f));
+ GetObject (hfont, sizeof (logfont), &logfont);
+ }
+ UNGCPRO;
+
+ if (need_set_ime_font (&logfont))
+ {
+ ime_logfont = logfont;
+ PostMessage (hwnd, WM_MULE_IMM_SET_IMEFONT, (WPARAM) f, 0);
+ }
+}
+static void
+w32_set_ime_font (hwnd)
+ HWND hwnd;
+{
+ HIMC himc;
+
+ if (!fIME || NILP (Vime_control))
+ return;
+
+ himc = (ImmGetContextProc) (hwnd);
+ if (!himc)
+ return;
+ (ImmSetCompositionFontProc) (himc, &ime_logfont);
+ (ImmReleaseContextProc) (hwnd, himc);
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+
+struct get_imefont_arg {
+ HWND hwnd;
+ struct frame *f;
+ LOGFONT lf;
+};
+
+static Lisp_Object
+w32_get_ime_font (Lisp_Object arg_)
+{
+ struct get_imefont_arg *arg = cons2ptr(arg_);
+
+ Lisp_Object ime_font = Qnil, temp = Qnil, font = Qnil, family;
+ struct gcpro gcpro1, gcpro2;
+ extern Lisp_Object QCfamily;
+ int fsid = -1;
+
+ if (!fIME || NILP(Vime_control))
+ return Qnil;
+
+ GCPRO2(font, temp);
+
+ if (STRINGP(ime_font = get_frame_param (arg->f, Qime_font))
+ /* fontset */
+ && ((fsid = fs_query_fontset(ime_font, 0)) >= 0
+ && !NILP(font = fontset_ascii(fsid))
+ && !NILP(font = font_spec_from_name(font))
+ && !NILP(temp = Ffontset_font(temp, make_number(0x3042), Qnil))
+ && !NILP(family = XCAR(temp))
+ /* font */
+ || !NILP(font = font_spec_from_name(ime_font))
+ && SYMBOLP(family = AREF (font, FONT_FAMILY_INDEX))
+ && STRINGP(family = SYMBOL_NAME(family)))
+
+ /* use font object */
+ /* frame-parameter */
+ || (FONTP(font = ime_font)
+ /* frame fontset */
+ || ((fsid = FRAME_FONTSET(arg->f)) >= 0
+ && !NILP(font =
+ Ffont_at(make_number(0), Qnil,
+ temp = Fchar_to_string(make_number(0x3042))))))
+ && SYMBOLP(family = Ffont_get(font, QCfamily))
+ && STRINGP(family = SYMBOL_NAME(family))
+ && !NILP(font = copy_font_spec(font))) {
+ Lisp_Object tail;
+
+ fill_in_logfont (arg->f, &arg->lf, font);
+ arg->lf.lfWidth = 0;
+
+ family = ENCODE_SYSTEM(family);
+
+#ifdef _MSC_VER
+ strcpy_s(arg->lf.lfFaceName,
+ sizeof(arg->lf.lfFaceName), SDATA(family));
+#else
+ strcpy(arg->lf.lfFaceName, SDATA(family));
+#endif
+
+ /* rescale if ime font isn't ascii*/
+ for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail)) {
+ temp = XCAR (tail);
+ if (!FLOATP (XCDR (temp)))
+ continue;
+
+ if (STRINGP (XCAR (temp))) {
+ if (fast_string_match_ignore_case (XCAR (temp), family) >= 0) {
+ arg->lf.lfHeight *= XFLOAT_DATA (XCDR (temp));
+ break;
+ }
+ } else if (FONT_SPEC_P (XCAR (temp))) {
+ Lisp_Object name;
+ if (!NILP(name = Ffont_get(XCAR (temp), QCfamily)) &&
+ STRINGP(name) &&
+ xstrcasecmp(SDATA(name), SDATA(family)) == 0) {
+ arg->lf.lfHeight *= XFLOAT_DATA (XCDR (temp));
+ break;
+ }
+ }
+ }
+ } else {
+ HFONT hfont = FONT_HANDLE (FRAME_FONT (arg->f));
+ GetObject (hfont, sizeof (arg->lf), &arg->lf);
+ }
+ UNGCPRO;
+
+ return Qt;
+}
+
+static void
+w32_set_ime_font (hwnd, f)
+ HWND hwnd;
+ struct frame *f;
+{
+ HIMC himc;
+ struct get_imefont_arg gia = {
+ hwnd, f, {0}
+ };
+
+ if (NILP(w32_call_lisp_thread(w32_get_ime_font, &gia)) ||
+ !(himc = (ImmGetContextProc) (hwnd)))
+ return;
+
+ (ImmSetCompositionFontProc) (himc, &gia.lf);
+ (ImmReleaseContextProc) (hwnd, himc);
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#endif /* HAVE_NTGUI */
+
+static LRESULT CALLBACK
+conversion_agent_wndproc (HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+/* HWND hwnd;
+ UINT message;
+ WPARAM wparam;
+ LPARAM lparam; */
+{
+ HIMC himc, holdimc;
+
+ switch (message)
+ {
+ case WM_MULE_IMM_SET_STATUS:
+ if (InSendMessage())
+ ReplyMessage(1);
+ w32_set_ime_status (hwnd, (int) wparam);
+ break;
+
+ case WM_MULE_IMM_GET_STATUS:
+ return w32_get_ime_status (hwnd);
+
+ case WM_MULE_IMM_SET_MODE:
+ return w32_set_ime_mode (hwnd, (int) wparam, (int) lparam);
+
+#if !defined(USE_W32_CALL_LISP_THREAD)
+ case WM_MULE_IMM_SET_IMEFONT:
+ w32_set_ime_font (hwnd);
+#endif
+ case WM_MULE_IMM_SET_CONVERSION_WINDOW:
+ if (w32_get_ime_status (hwnd))
+ w32_set_ime_conv_window (hwnd, (struct frame *) wparam);
+ break;
+
+#ifdef RECONVERSION
+ case WM_MULE_IMM_PERFORM_RECONVERSION:
+ if (ime_enable_reconversion)
+ w32_perform_reconversion(hwnd, (RECONVERTSTRING*)lparam);
+ break;
+#endif
+
+#if 0
+ case WM_MULE_IMM_GET_COMPOSITION_STRING:
+ return w32_get_ime_composition_string (hwnd);
+#endif
+
+ default:
+ return DefWindowProc (hwnd, message, wparam, lparam);
+ }
+ return 0;
+}
+
+
+/*
+ Emacs Lisp function entries
+*/
+
+DEFUN ("ime-force-on", Fime_force_on, Sime_force_on, 0, 1, 0,
+ doc: /* Force status of IME open. */)
+ (Lisp_Object eventp)
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HIMC himc;
+ HWND hwnd;
+
+ if (!NILP (Fime_get_mode ()))
+ return Qnil;
+#ifdef HAVE_NTGUI
+ if (NILP (eventp))
+ IME_event_off_count++;
+ hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+#else
+ hwnd = hwndConsole;
+#endif
+ SendMessage (hwnd, WM_MULE_IMM_SET_STATUS, 1, 0);
+ }
+ return Qnil;
+}
+
+DEFUN ("ime-force-off", Fime_force_off, Sime_force_off, 0, 1, 0,
+ doc: /* Force status of IME close. */)
+ (Lisp_Object eventp)
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HIMC himc;
+ HWND hwnd;
+
+ if (NILP (Fime_get_mode ()))
+ return Qnil;
+#ifdef HAVE_NTGUI
+ if (NILP (eventp))
+ IME_event_off_count++;
+ hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+#else
+ hwnd = hwndConsole;
+#endif
+ SendMessage (hwnd, WM_MULE_IMM_SET_STATUS, 0, 0);
+ }
+ return Qnil;
+}
+
+DEFUN ("ime-get-mode", Fime_get_mode, Sime_get_mode, 0, 0, "",
+ doc: /* Get IME status.
+t means status of IME is open. nil means it is close. */)
+ (void)
+{
+ if (fIME && !NILP (Vime_control))
+ {
+ HWND hwnd;
+ int result;
+
+#ifdef HAVE_NTGUI
+ hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+#else
+ hwnd = hwndConsole;
+#endif
+ result = SendMessage (hwnd, WM_MULE_IMM_GET_STATUS, 0, 0);
+
+ return result ? Qt : Qnil;
+ }
+ else
+ return Qnil;
+}
+
+DEFUN ("w32-set-ime-mode",
+ Fw32_set_ime_mode,
+ Sw32_set_ime_mode, 1, 2, 0,
+ doc: /* Set IME mode to MODE. If FRAME is omitted, the selected frame is used. */)
+ (Lisp_Object mode, Lisp_Object frame)
+{
+ struct frame *f;
+
+ if (NILP (frame))
+ {
+ f = SELECTED_FRAME ();
+ }
+ else
+ {
+ CHECK_FRAME (frame);
+ f = XFRAME (frame);
+ }
+ if (fIME && !NILP (Vime_control))
+ {
+ HWND hwnd;
+ int ret;
+ int newmode, mask;
+
+ newmode = 0;
+ mask = 0;
+
+ hwnd = FRAME_W32_WINDOW (f);
+
+ if (EQ (mode, intern ("katakana")))
+ {
+ newmode |= IME_CMODE_KATAKANA;
+ mask |= IME_CMODE_KATAKANA;
+ }
+ else if (EQ (mode, intern ("hiragana")))
+ {
+ newmode &= ~IME_CMODE_KATAKANA;
+ mask |= IME_CMODE_KATAKANA;
+ }
+ else if (EQ (mode, intern ("kanji")))
+ {
+ newmode |= IME_CMODE_HANJACONVERT;
+ mask |= IME_CMODE_HANJACONVERT;
+ }
+ else if (EQ (mode, intern ("nokanji")))
+ {
+ newmode &= ~IME_CMODE_HANJACONVERT;
+ mask |= IME_CMODE_HANJACONVERT;
+ }
+ else if (EQ (mode, intern ("code")))
+ {
+ newmode |= IME_CMODE_CHARCODE;
+ mask |= IME_CMODE_CHARCODE;
+ }
+ else if (EQ (mode, intern ("nocode")))
+ {
+ newmode &= ~IME_CMODE_CHARCODE;
+ mask |= IME_CMODE_CHARCODE;
+ }
+ else if (EQ (mode, intern ("non-convert")))
+ {
+ newmode |= IME_CMODE_NOCONVERSION;
+ mask |= IME_CMODE_NOCONVERSION;
+ }
+ else if (EQ (mode, intern ("convert")))
+ {
+ newmode &= ~IME_CMODE_NOCONVERSION;
+ mask |= IME_CMODE_NOCONVERSION;
+ }
+ else
+ error ("unknown mode!!");
+
+ ret = SendMessage (hwnd, WM_MULE_IMM_SET_MODE,
+ (WPARAM) newmode, (LPARAM) mask);
+
+ if (!ret)
+ return Qnil;
+
+ return Qt;
+ }
+ return Qnil;
+}
+
+DEFUN ("w32-ime-register-word-dialog",
+ Fw32_ime_register_word_dialog,
+ Sw32_ime_register_word_dialog, 2, 2, 0,
+ doc: /* Open IME regist word dialog. */)
+ (Lisp_Object reading, Lisp_Object word)
+{
+ HKL hkl;
+ int reading_len, word_len;
+ REGISTERWORD regword;
+ Lisp_Object encoded_reading, encoded_word;
+
+ CHECK_STRING (reading);
+ CHECK_STRING (word);
+
+ if (fIME && !NILP (Vime_control) && ImmConfigureIMEProc)
+ {
+ hkl = GetKeyboardLayout (0);
+ encoded_reading = Fencode_coding_string (reading,
+ Vlocale_coding_system,
+ Qnil, Qnil);
+ reading_len = SBYTES (encoded_reading);
+ regword.lpReading = SDATA (encoded_reading);
+
+ encoded_word = Fencode_coding_string (word,
+ Vlocale_coding_system,
+ Qnil, Qnil);
+ word_len = SBYTES (encoded_word);
+ regword.lpWord = SDATA (encoded_word);
+ (ImmConfigureIMEProc) (hkl, FRAME_W32_WINDOW (SELECTED_FRAME ()),
+ IME_CONFIG_REGISTERWORD, &regword);
+ }
+ return Qnil;
+}
+
+DEFUN ("ime-get-property", Fime_get_property, Sime_get_property, 1, 1, 0,
+ doc: /* Retrieves the property and capabilities of the IME associated with the specified input locale.
+INDEX is one of igp-property, igp-conversion, igp-sentence, igp-ui, igp-setcompstr, igp-select of igp-getimeversion*/)
+ (Lisp_Object index)
+{
+ int i;
+ Lisp_Object val;
+ DWORD v;
+ struct gcpro gcpro1;
+
+ static const struct {
+ const char *name;
+ DWORD index;
+ } index_map[] = {
+ {"property", IGP_PROPERTY},
+ {"conversion", IGP_CONVERSION},
+ {"sentence", IGP_SENTENCE},
+ {"ui", IGP_UI},
+ {"setcompstr", IGP_SETCOMPSTR},
+ {"select", IGP_SELECT},
+ {"getimeversion", IGP_GETIMEVERSION},
+ }, prop_map[] = {
+ {"at-caret", IME_PROP_AT_CARET},
+ {"special-ui", IME_PROP_SPECIAL_UI},
+ {"candlist-start-from-1", IME_PROP_CANDLIST_START_FROM_1},
+ {"unicode", IME_PROP_UNICODE},
+ {"complete-on-unselect", IME_PROP_COMPLETE_ON_UNSELECT},
+ }, ui_map[] = {
+ {"rot2700", UI_CAP_2700},
+ {"rot90", UI_CAP_ROT90},
+ {"rotany", UI_CAP_ROTANY},
+ }, setcompstr_map[] = {
+ {"compstr", SCS_CAP_COMPSTR},
+ {"makeread", SCS_CAP_MAKEREAD},
+ {"setreconvertstring", SCS_CAP_SETRECONVERTSTRING},
+ }, select_map[] = {
+ {"conversion", SELECT_CAP_CONVERSION},
+ {"sentence", SELECT_CAP_SENTENCE},
+ }, imeversion_map[] = {
+ {"ver-0310", IMEVER_0310},
+ {"ver-0400", IMEVER_0400},
+ };
+
+ CHECK_SYMBOL(index);
+ for (i = 0; i < sizeof(index_map) / sizeof(index_map[0]); i++)
+ if (EQ(index, intern(index_map[i].name)))
+ break;
+ if (i >= sizeof(index_map) / sizeof(index_map[0]))
+ return Qnil;
+
+ v = (*ImmGetPropertyProc)(GetKeyboardLayout(0), index_map[i].index);
+ val = Qnil;
+ GCPRO1(val);
+#define MAKE_CAP_LIST(map) do { \
+ int j; \
+ for (j = sizeof(map) / sizeof(map[0]) - 1; j >= 0 ; j--) \
+ if (v & map[j].index) \
+ val = Fcons(intern(map[j].name), val); \
+} while(0)
+
+ switch (index_map[i].index) {
+ case IGP_PROPERTY:
+ MAKE_CAP_LIST(prop_map);
+ break;
+ case IGP_UI:
+ MAKE_CAP_LIST(ui_map);
+ break;
+ case IGP_SETCOMPSTR:
+ MAKE_CAP_LIST(setcompstr_map);
+ break;
+ case IGP_SELECT:
+ MAKE_CAP_LIST(select_map);
+ break;
+ case IGP_GETIMEVERSION:
+ MAKE_CAP_LIST(imeversion_map);
+ break;
+ }
+ UNGCPRO;
+ return val;
+}
+
+#ifdef RECONVERSION
+BOOL w32_perform_reconversion(HWND hwnd, RECONVERTSTRING *reconv)
+{
+ struct frame *f = SELECTED_FRAME ();
+ HIMC himc;
+ BOOL result = FALSE;
+
+ himc = (ImmGetContextProc) (hwnd);
+ if (!himc) {
+ xfree(reconv);
+ return FALSE;
+ }
+
+ if ((*ImmSetCompositionStringProc) (himc,
+ SCS_QUERYRECONVERTSTRING,
+ reconv, reconv->dwSize,
+ NULL, 0 )
+ && (*ImmSetCompositionStringProc) (himc,
+ SCS_SETRECONVERTSTRING,
+ reconv, reconv->dwSize,
+ NULL, 0)) {
+ /* Set the position of candidate list dialog. */
+ (ImmReleaseContextProc) (hwnd, himc);
+ w32_set_ime_conv_window (hwnd, f);
+ result = TRUE;
+ } else
+ (ImmReleaseContextProc) (hwnd, himc);
+ xfree(reconv);
+ return result;
+}
+
+DEFUN ("w32-ime-perform-reconversion",
+ Fw32_ime_perform_reconversion,
+ Sw32_ime_perform_reconversion, 0, 0, "",
+ doc: /* perfom ime reconversion. */)
+ (void)
+#if !defined(USE_W32_CALL_LISP_THREAD)
+{
+ HWND hwnd = FRAME_W32_WINDOW(SELECTED_FRAME());
+ DWORD size;
+ RECONVERTSTRING *reconv;
+
+ if (!ime_enable_reconversion ||
+ NILP(Fime_get_mode()))
+ return Qnil;
+
+ if ((size = get_reconversion_string (hwnd, NULL, NULL))
+ && (reconv = xmalloc (size)) != NULL
+ && (memset (reconv, 0, size), (reconv->dwSize = size))
+ && get_reconversion_string (hwnd, reconv, NULL))
+ PostMessage(hwnd, WM_MULE_IMM_PERFORM_RECONVERSION, 0, (LPARAM) reconv);
+
+ return Qt;
+}
+#else /* USE_W32_CALL_LISP_THREAD */
+{
+ Lisp_Object temp;
+ struct gcpro gcpro1;
+ struct get_reconversion_string_arg grs = {0, NULL, NULL, 0};
+
+ if (!ime_enable_reconversion ||
+ NILP(Fime_get_mode()))
+ return Qnil;
+
+ GCPRO1(temp);
+
+ if (!NILP(get_reconversion_string(temp = ptr2cons(&grs)))
+ && grs.size > 0
+ && (grs.reconv = xmalloc(grs.size)) != NULL
+ && (memset(grs.reconv, 0, grs.size),
+ (grs.reconv->dwSize = grs.size))
+ && !NILP(get_reconversion_string(temp))) {
+
+ // del_range(grs.start, grs.end);
+
+ PostMessage(FRAME_W32_WINDOW(SELECTED_FRAME()),
+ WM_MULE_IMM_PERFORM_RECONVERSION, 0, (LPARAM)grs.reconv);
+ }
+ UNGCPRO;
+ return Qt;
+}
+#endif /* USE_W32_CALL_LISP_THREAD */
+#endif
+
+#endif /* USE_W32_IME */
+
+
+/***********************************************************************
w32 specialized functions
***********************************************************************/
@@ -7595,7 +9403,9 @@
{
if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
break;
- *str++ = *name++;
+ *str = *name;
+ str = _mbsinc(str);
+ name = _mbsinc(name);
}
while ( *name );
@@ -7771,6 +9581,37 @@
return DECODE_FILE (build_unibyte_string (pname_buf));
}
+
+DEFUN ("w32-memory-info", Fw32_memory_info, Sw32_memory_info,
+ 0, 0, 0, doc: /* Retrieves information about the memory usage.
+return value is a list of
+
+reserved_heap_size
+
+GlobalMemoryStatusEx:
+ MemoryLoad;
+ TotalPhys;
+ AvailPhys;
+ TotalPageFile;
+ AvailPageFile;
+ TotalVirtual;
+ AvailVirtual;
+ AvailExtendedVirtual;
+
+GetProcessMemoryInfo:
+ PageFaultCount;
+ PeakWorkingSetSize;
+ WorkingSetSize;
+ QuotaPeakPagedPoolUsage;
+ QuotaPagedPoolUsage;
+ QuotaPeakNonPagedPoolUsage;
+ QuotaNonPagedPoolUsage;
+ PagefileUsage;
+ PeakPagefileUsage;
+ PrivateUsage; (Xp or above) */) (void)
+{
+ return w32_get_memory_info ();
+}
#endif /* WINDOWSNT */
@@ -8115,6 +9956,9 @@
x_set_fullscreen,
x_set_font_backend,
x_set_alpha,
+#ifdef USE_W32_IME
+ 0, /* ime-font */
+#endif /* USE_W32_IME */
0, /* x_set_sticky */
0, /* x_set_tool_bar_position */
};
@@ -8129,6 +9973,10 @@
DEFSYM (Qsuppress_icon, "suppress-icon");
DEFSYM (Qundefined_color, "undefined-color");
+#ifdef USE_W32_IME
+ DEFSYM (Qw32_ime_buffer_switch_p, "w32-ime-buffer-switch-p");
+ DEFSYM (Qime_font, "ime-font");
+#endif /* USE_W32_IME */
DEFSYM (Qcancel_timer, "cancel-timer");
DEFSYM (Qhyper, "hyper");
DEFSYM (Qsuper, "super");
@@ -8405,6 +10253,27 @@
only be necessary if the default setting causes problems. */);
w32_strict_painting = 1;
+#ifdef USE_W32_IME
+#ifdef RECONVERSION
+ DEFVAR_BOOL ("ime-enable-reconversion", ime_enable_reconversion,
+ doc: /* Non-nil enables IME reconversion capability. */);
+ ime_enable_reconversion = 1;
+#endif
+#ifdef DOCUMENTFEED
+ DEFVAR_BOOL ("ime-enable-document-feed", ime_enable_document_feed,
+ doc: /* Non-nil enables IME document feed capability. */);
+ ime_enable_document_feed = 1;
+#endif
+ DEFVAR_LISP ("ime-control", Vime_control, doc: /* IME control flag. */);
+ Vime_control = Qnil;
+
+ DEFVAR_LISP ("w32-ime-composition-window",
+ Vw32_ime_composition_window,
+ doc: /* If this is a window of current frame, IME composition window appears on the
+window instead of current window. */);
+ Vw32_ime_composition_window = Qnil;
+#endif /* USE_W32_IME */
+
#if 0 /* TODO: Port to W32 */
defsubr (&Sx_change_window_property);
defsubr (&Sx_delete_window_property);
@@ -8449,6 +10318,20 @@
defsubr (&Sw32_frame_rect);
defsubr (&Sw32_battery_status);
defsubr (&Sw32__menu_bar_in_use);
+#ifndef CYGWIN
+ defsubr (&Sw32_memory_info);
+#endif
+#ifdef USE_W32_IME
+ defsubr (&Sw32_set_ime_mode);
+ defsubr (&Sw32_ime_register_word_dialog);
+ defsubr (&Sime_force_on);
+ defsubr (&Sime_force_off);
+ defsubr (&Sime_get_mode);
+ defsubr (&Sime_get_property);
+#ifdef RECONVERSION
+ defsubr (&Sw32_ime_perform_reconversion);
+#endif
+#endif /* USE_W32_IME */
#ifdef WINDOWSNT
defsubr (&Sfile_system_info);
@@ -8534,7 +10417,7 @@
{
int button;
button = MessageBox (NULL,
- "A fatal error has occurred!\n\n"
+ TEXT("A fatal error has occurred!\n\n"
"Would you like to attach a debugger?\n\n"
"Select:\n"
"YES -- to debug Emacs, or\n"
@@ -8544,7 +10427,7 @@
"\n\n(type \"gdb -p <emacs-PID>\" and\n"
"\"continue\" inside GDB before clicking YES.)"
#endif
- , "Emacs Abort Dialog",
+ ), TEXT("Emacs Abort Dialog"),
MB_ICONEXCLAMATION | MB_TASKMODAL
| MB_SETFOREGROUND | MB_YESNO);
switch (button)
@@ -8662,6 +10545,7 @@
enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
GetProcAddress (user32_lib, "EnumDisplayMonitors");
+#ifndef USE_W32_IME
{
HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
get_composition_string_fn = (ImmGetCompositionString_Proc)
@@ -8673,6 +10557,7 @@
set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
}
+#endif /* !USE_W32_IME */
except_code = 0;
except_addr = 0;
@@ -8685,9 +10570,11 @@
doc: /* The ANSI code page used by the system. */);
w32_ansi_code_page = GetACP ();
+#if !defined(USE_W32_CALL_LISP_THREAD) || defined(IME_UNICODE)
if (os_subtype == OS_NT)
w32_unicode_gui = 1;
else
+#endif
w32_unicode_gui = 0;
/* MessageBox does not work without this when linked to comctl32.dll 6.0. */
@@ -8707,3 +10594,63 @@
}
#endif /* NTGUI_UNICODE */
+
+
+#ifdef USE_W32_CALL_LISP_THREAD
+#ifdef _MSC_VER
+#include <intrin.h>
+#pragma intrinsic(_InterlockedCompareExchange, _InterlockedExchange)
+#endif
+
+static long apc_mutex;
+static HANDLE apc_mutex_ev;
+
+void w32_apc_mutex_init(void)
+{
+#if 0
+ apc_mutex = 0;
+ apc_mutex_ev = CreateEvent(NULL, FALSE, FALSE, NULL);
+#endif
+}
+
+void w32_apc_mutex_term(void)
+{
+#if 0
+ CloseHandle(apc_mutex_ev);
+#endif
+}
+
+void w32_apc_mutex_acquire(void)
+{
+#if 0
+ const DWORD tid = GetCurrentThreadId();
+ const BOOL proc_msg = dwWindowsThreadId == tid;
+ DWORD locker, v;
+ deferred_msg dummy = {0};
+ MSG msg;
+ dummy.completed = 1;
+
+ while ((locker =
+ InterlockedCompareExchange(&apc_mutex, tid, 0)) != 0
+ && locker != tid)
+ while ((v = proc_msg
+ ? MsgWaitForMultipleObjectsEx
+ (1, &apc_mutex_ev, INFINITE,
+ QS_ALLINPUT | QS_ALLPOSTMESSAGE, MWMO_ALERTABLE)
+ : WaitForSingleObjectEx(apc_mutex_ev, INFINITE, TRUE))
+ != WAIT_OBJECT_0)
+ if (v == WAIT_OBJECT_0 + 1)
+ w32_msg_pump(&dummy);
+ else if (v != WAIT_IO_COMPLETION)
+ abort();
+#endif
+}
+
+void w32_apc_mutex_release(void)
+{
+#if 0
+ InterlockedExchange(&apc_mutex, 0);
+ SetEvent(apc_mutex_ev);
+#endif
+}
+#endif
--- ./src/w32font.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32font.c 2015-04-11 07:27:30.699125900 +0900
@@ -102,7 +102,10 @@
/* Font spacing symbols - defined in font.c. */
extern Lisp_Object Qc, Qp, Qm;
-static void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
+#ifndef USE_W32_IME
+static
+#endif
+void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
static BYTE w32_antialias_type (Lisp_Object);
static Lisp_Object lispy_antialias_type (BYTE);
@@ -1962,7 +1965,10 @@
}
/* Fill in all the available details of LOGFONT from FONT_SPEC. */
-static void
+#ifndef USE_W32_IME
+static
+#endif
+void
fill_in_logfont (struct frame *f, LOGFONT *logfont, Lisp_Object font_spec)
{
Lisp_Object tmp, extra;
--- ./src/w32font.h.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32font.h 2015-04-11 07:27:30.705127000 +0900
@@ -83,6 +83,9 @@
int uniscribe_check_otf (LOGFONT *font, Lisp_Object otf_spec);
Lisp_Object intern_font_name (char *);
+#ifdef USE_W32_IME
+void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
+#endif
extern void syms_of_w32font (void);
extern void globals_of_w32font (void);
--- ./src/w32heap.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32heap.c 2015-04-11 07:27:30.714128400 +0900
@@ -60,6 +60,86 @@
return data_region_end;
}
+#ifdef _WIN64
+static char *
+allocate_heap (void)
+{
+ /* Try to get as much as possible of the address range from the end of
+ the preload heap section up to the usable address limit. Since GNU
+ malloc can handle gaps in the memory it gets from sbrk, we can
+ simply set the sbrk pointer to the base of the new heap region. */
+ MEMORYSTATUSEX msx = {sizeof(MEMORYSTATUSEX)};
+ uintptr_t size =
+ (GlobalMemoryStatusEx(&msx) != 0) ?
+ msx.ullTotalPhys * 2 : (uintptr_t)256 * 1024 * 1024 * 1024;
+ uintptr_t decr, low_blocks, i;
+ void *ptr = NULL;
+ char *p, *hsize = getenv("EMACS_MAX_HEAP"), **ptr0;
+
+ if (hsize) {
+ size = (EMACS_INT)strtol(hsize, &p, 10);
+ switch (*p == 0 ? 0 : tolower(*p)) {
+ case 'k':
+ size *= (EMACS_UINT)1024;
+ break;
+ case 'm':
+ size *= (EMACS_UINT)1024 * 1024;
+ break;
+ case 'g':
+ size *= (EMACS_UINT)1024 * 1024 * 1024;
+ break;
+ case 't':
+ size *= (EMACS_UINT)1024 * 1024 * 1024 * 1024;
+ break;
+ default:
+ return NULL;
+ }
+ }
+
+ if (size > (EMACS_UINT)16 * 1024 * 1024 * 1024) // 16G
+ decr = (EMACS_UINT)1 * 1024 * 1024 * 1024; // 1G
+ else if (size > (EMACS_UINT)4 * 1024 * 1024 * 1024) // 4G
+ decr = (EMACS_UINT)128 * 1024 * 1024; // 128MB
+ else if (size > (EMACS_UINT)1 * 1024 * 1024 * 1024) // 1G
+ decr = (EMACS_UINT)128 * 1024 * 1024; // 64MB
+ else
+ decr = (EMACS_UINT)16 * 1024 * 1024; // 16MB
+
+ /*
+ * gmalloc expect sbrk is grater than preload_heap.
+ * we'll preserve the regions below preload_head.
+ */
+ if ((low_blocks = (uintptr_t)
+ RVA_TO_PTR(preload_heap_section->VirtualAddress) / size) > 0) {
+ ptr0 = alloca(sizeof(void *) * low_blocks);
+ for (i = 0; i < low_blocks; i++)
+ if ((ptr0[i] =
+ VirtualAlloc (NULL, size, MEM_RESERVE , PAGE_NOACCESS)) >
+ (char *) RVA_TO_PTR(preload_heap_section->VirtualAddress)) {
+ VirtualFree(ptr0[i], size, MEM_RELEASE);
+ ptr0[i] = NULL;
+ break;
+ }
+ while (i < low_blocks)
+ ptr0[i++] = NULL;
+ }
+
+ for (ptr = NULL; !ptr && size > 0; size -= decr)
+ {
+ reserved_heap_size = size;
+ ptr = VirtualAlloc (NULL,
+ get_reserved_heap_size (),
+ MEM_RESERVE , PAGE_NOACCESS);
+ }
+
+ /* free preserved region */
+ for (i = 0; i < low_blocks; i++)
+ if (ptr0[i])
+ VirtualFree(ptr0[i], size, MEM_RELEASE);
+
+ return ptr;
+}
+#else
#if !USE_LSB_TAG
static char *
allocate_heap (void)
@@ -119,6 +199,7 @@
return ptr;
}
#endif /* USE_LSB_TAG */
+#endif /* !_WIN64 */
/* Emulate Unix sbrk. Note that ralloc.c expects the return value to
--- ./src/w32proc.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32proc.c 2015-04-11 07:27:30.722127100 +0900
@@ -43,7 +43,7 @@
#undef kill
#include <windows.h>
-#if defined(__GNUC__) && !defined(__MINGW64__)
+#if defined(__GNUC__) && !defined(_W64)
/* This definition is missing from mingw.org headers, but not MinGW64
headers. */
extern BOOL WINAPI IsValidLocale (LCID, DWORD);
@@ -66,6 +66,8 @@
#include "dispextern.h" /* for xstrcasecmp */
#include "coding.h"
+#include <mbstring.h>
+
#define RVA_TO_PTR(var,section,filedata) \
((void *)((section)->PointerToRawData \
+ ((DWORD_PTR)(var) - (section)->VirtualAddress) \
@@ -1845,7 +1847,7 @@
if (*p == 0)
need_quotes = 1;
- for ( ; *p; p++)
+ for ( ; *p; p = _mbsinc (p))
{
if (escape_char == '"' && *p == '\\')
/* If it's a Cygwin app, \ needs to be escaped. */
@@ -1897,7 +1899,7 @@
if (do_quoting)
{
- for ( ; *p; p++)
+ for ( ; *p; p = _mbsinc (p))
if ((strchr (sepchars, *p) != NULL) || *p == '"')
need_quotes = 1;
}
@@ -1925,7 +1927,7 @@
*parg++ = *p++;
}
#else
- for ( ; *p; p++)
+ for ( ; *p; )
{
if (*p == '"')
{
@@ -1940,12 +1942,15 @@
}
else if (escape_char == '"' && *p == '\\')
*parg++ = '\\';
- *parg++ = *p;
if (*p == escape_char && escape_char != '"')
escape_char_run++;
else
escape_char_run = 0;
+ {
+ char *px = _mbsinc (p);
+ while (px != p) *parg++ = *p++;
+ }
}
/* double escape chars before enclosing quote */
while (escape_char_run > 0)
@@ -2240,7 +2245,11 @@
errno = EINTR;
return -1;
}
+#if !defined(USE_W32_CALL_LISP_THREAD)
else if (active == WAIT_TIMEOUT)
+#else
+ else if (active == WAIT_TIMEOUT || active == WAIT_IO_COMPLETION)
+#endif
{
if (noninteractive)
{
--- ./src/w32term.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32term.c 2015-04-11 07:27:30.733129100 +0900
@@ -64,6 +64,7 @@
#include "font.h"
#include "w32font.h"
+#pragma warning(error : 4013)
/* Fringe bitmaps. */
@@ -4909,6 +4910,110 @@
break;
#endif
+#ifdef USE_W32_IME
+ case WM_MULE_IME_STATUS:
+ f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+
+ if (f && !f->iconified && f->visible)
+ {
+ inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.code = VK_KANJI;
+ inev.modifiers = 0;
+ XSETFRAME (inev.frame_or_window, f);
+ inev.timestamp = msg.msg.time;
+ }
+ break;
+
+ case WM_MULE_IME_REPORT:
+ {
+#ifdef IME_UNICODE
+ LPWSTR lpStr;
+#else
+ LPSTR lpStr;
+#endif
+ struct input_event buf;
+ HANDLE hw32_ime_string = (HANDLE) msg.msg.wParam;
+
+ f = (struct frame *) msg.msg.lParam;
+ if (f && !f->iconified && f->visible)
+ {
+#ifdef IME_UNICODE
+ lpStr = (LPWSTR) hw32_ime_string;
+#else
+ lpStr = (LPSTR) hw32_ime_string;
+#endif
+ while(lpStr)
+ {
+ wchar_t code;
+
+ EVENT_INIT (buf);
+ XSETFRAME (buf.frame_or_window, f);
+ buf.timestamp = msg.msg.time;
+ buf.modifiers = 0;
+ if (*lpStr)
+ {
+#ifdef IME_UNICODE
+ if (*lpStr < 0x80)
+ buf.kind = ASCII_KEYSTROKE_EVENT;
+ else
+ buf.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ if ((*lpStr & 0xFC00) == 0xD800
+ && (*(lpStr + 1) & 0xFC00) == 0xDC00)
+ {
+ buf.code = 0x10000
+ + (((*lpStr & 0x3FF) << 10)
+ | *(lpStr + 1) & 0x3FF);
+ lpStr++;
+ }
+ else
+ buf.code = *(lpStr++);
+#else
+ if (IsDBCSLeadByteEx (w32_keyboard_codepage, *lpStr)) {
+ if (!lpStr[1] ||
+ !MultiByteToWideChar (w32_keyboard_codepage, 0,
+ lpStr, 2, &code, 1)) {
+ lpStr++;
+ continue;
+ }
+ lpStr += 2;
+ } else {
+ if (!MultiByteToWideChar (w32_keyboard_codepage, 0,
+ lpStr++, 1, &code, 1))
+ continue;
+ }
+ buf.code = code;
+ buf.kind = buf.code < 0x80 ?
+ ASCII_KEYSTROKE_EVENT : MULTIBYTE_CHAR_KEYSTROKE_EVENT;;
+#endif
+ kbd_buffer_store_event (&buf);
+ }
+ else
+ {
+ buf.kind = NON_ASCII_KEYSTROKE_EVENT;
+ buf.code = VK_COMPEND;
+ kbd_buffer_store_event (&buf);
+ break;
+ }
+ }
+ HeapFree (GetProcessHeap (), 0, (LPVOID) hw32_ime_string);
+ }
+ }
+ break;
+
+#if !defined(USE_W32_CALL_LISP_THREAD)
+ case WM_MULE_IME_DEL_RANGE:
+ del_range ((ptrdiff_t) msg.msg.wParam, (ptrdiff_t) msg.msg.lParam);
+ Fgoto_char (make_number (msg.msg.wParam));
+ redisplay ();
+ break;
+
+ case WM_MULE_IME_SET_FONT:
+ w32_set_ime_logfont (msg.msg.hwnd, (struct frame *) msg.msg.wParam);
+ break;
+#endif
+
+#endif /* USE_W32_IME */
+
default:
/* Check for messages registered at runtime. */
if (msg.msg.message == msh_mousewheel)
@@ -5274,7 +5379,12 @@
w32_system_caret_hdr_height = WINDOW_HEADER_LINE_HEIGHT (w);
w32_system_caret_mode_height = WINDOW_MODE_LINE_HEIGHT (w);
+#ifdef USE_W32_IME
+ if (f && f == FRAME_DISPLAY_INFO (f)->x_highlight_frame)
+ PostMessage (hwnd, WM_MULE_IMM_SET_CONVERSION_WINDOW, (WPARAM) f, 0);
+#else
PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
+#endif
/* If the size of the active cursor changed, destroy the old
system caret. */
@@ -6563,6 +6673,9 @@
vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
= GetSystemMetrics (SM_CYVSCROLL);
}
+#ifdef USE_W32_IME
+ w32_ime_control_init();
+#endif /* USE_W32_IME */
}
void
--- ./src/w32term.h.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/w32term.h 2015-04-11 07:27:30.743128300 +0900
@@ -569,6 +569,8 @@
#endif /* WM_MOUSEHWHEEL */
#ifndef WM_APPCOMMAND
#define WM_APPCOMMAND 0x319
+#endif
+#ifndef GET_APPCOMMAND_LPARAM
#define GET_APPCOMMAND_LPARAM(lParam) (HIWORD(lParam) & 0x7fff)
#endif
#ifndef WM_UNICHAR
@@ -605,14 +607,128 @@
#define WM_EMACS_FILENOTIFY (WM_EMACS_START + 23)
#define WM_EMACS_END (WM_EMACS_START + 24)
-#define WND_FONTWIDTH_INDEX (0)
-#define WND_LINEHEIGHT_INDEX (4)
-#define WND_BORDER_INDEX (8)
-#define WND_SCROLLBAR_INDEX (12)
-#define WND_BACKGROUND_INDEX (16)
-#define WND_LAST_INDEX (20)
+#ifdef CYGWIN
+#undef USE_W32_CALL_LISP_THREAD
+#endif
+
+#ifdef USE_W32_IME
+#if !defined(USE_W32_CALL_LISP_THREAD)
+#undef IME_UNICODE
+#define IME_UNICODE
+#endif
+
+#ifndef VK_KANJI
+#define VK_KANJI 0x19
+#endif
+#ifndef VK_KANA
+#define VK_KANA 0x15
+#endif
+#define VK_COMPEND 0x1A
+
+#ifdef RECONVERSION
+#ifndef WM_IME_REQUEST
+#define WM_IME_REQUEST 0x288
+#endif
+#ifndef IMR_COMPOSITIONWINDOW
+#define IMR_COMPOSITIONWINDOW 0x0001
+#endif
+#ifndef IMR_CANDIDATEWINDOW
+#define IMR_CANDIDATEWINDOW 0x0002
+#endif
+#ifdef IMR_COMPOSITIONFONT
+#define IMR_COMPOSITIONFONT 0x0003
+#endif
+#ifndef IMR_RECONVERTSTRING
+#define IMR_RECONVERTSTRING 0x0004
+#endif
+#ifndef IMR_CONFIRMRECONVERTSTRING
+#define IMR_CONFIRMRECONVERTSTRING 0x0005
+#endif
+#endif
+#ifndef IME_PROP_COMPLETE_ON_UNSELECT
+#define IME_PROP_COMPLETE_ON_UNSELECT 0x00100000
+#endif
+#ifndef SCS_CAP_SETRECONVERTSTRING
+#define SCS_CAP_SETRECONVERTSTRING 0x00000004
+#endif
+
+/* For internal communications
+ from window procedure to event loop. */
+#define WM_MULE_IME_REPORT (WM_USER+2200)
+#define WM_MULE_IME_STATUS (WM_USER+2201)
+#if !defined(USE_W32_CALL_LISP_THREAD)
+#define WM_MULE_IME_DEL_RANGE (WM_USER+2202)
+#define WM_MULE_IME_SET_FONT (WM_USER+2203)
+#endif
+
+/* For internal communications
+ from main thread to window procedure. */
+#define WM_MULE_IMM_MESSAGE_START (WM_USER+2300)
+#define WM_MULE_IMM_SET_STATUS (WM_USER+2300)
+#define WM_MULE_IMM_GET_STATUS (WM_USER+2301)
+#if 0
+#define WM_MULE_IMM_DEAL_WITH_CONTEXT (WM_USER+2302)
+#define WM_MULE_IMM_SET_COMPOSITION_STRING (WM_USER+2303)
+#endif
+#define WM_MULE_IMM_GET_COMPOSITION_STRING (WM_USER+2304)
+#define WM_MULE_IMM_SET_MODE (WM_USER+2305)
+#if 0
+#define WM_MULE_IMM_NOTIFY (WM_USER+2310)
+#define WM_MULE_IMM_GET_UNDETERMINED_STRING_LENGTH (WM_USER+2320)
+#endif
+#define WM_MULE_IMM_SET_IMEFONT (WM_USER+2311)
+#define WM_MULE_IMM_SET_CONVERSION_WINDOW (WM_USER+2312)
+
+#define WM_MULE_IMM_PERFORM_RECONVERSION (WM_USER+2320)
-#define WND_EXTRA_BYTES (WND_LAST_INDEX)
+#define WM_MULE_IMM_MESSAGE_END (WM_USER+2399)
+#define MESSAGE_IMM_COM_P(message) \
+ (((message) >= WM_MULE_IMM_MESSAGE_START) && \
+ ((message) <= WM_MULE_IMM_MESSAGE_END))
+
+#ifdef RECONVERSION
+#ifndef HAVE_RECONVERTSTRING
+typedef struct tagRECONVERTSTRING {
+ DWORD dwSize;
+ DWORD dwVersion;
+ DWORD dwStrLen;
+ DWORD dwStrOffset;
+ DWORD dwCompStrLen;
+ DWORD dwCompStrOffset;
+ DWORD dwTargetStrLen;
+ DWORD dwTargetStrOffset;
+} RECONVERTSTRING, *PRECONVERTSTRING;
+#endif
+#ifndef SCS_SETRECONVERTSTRING
+#define SCS_SETRECONVERTSTRING 0x00010000
+#endif
+#ifndef SCS_QUERYRECONVERTSTRING
+#define SCS_QUERYRECONVERTSTRING 0x00020000
+#endif
+#endif /* RECONVERSION */
+#endif /* USE_W32_IME */
+
+#pragma pack(push, 4)
+struct wnd_extra {
+ LONG fontwidth;
+ LONG lineheight;
+ LONG border;
+ LONG scrollbar;
+ LONG background;
+};
+#pragma pack(pop)
+
+#ifndef offsetof
+#define offsetof(s,m) (size_t)&(((s *)0)->m)
+#endif
+#define WND_FONTWIDTH_INDEX offsetof(struct wnd_extra, fontwidth)
+#define WND_LINEHEIGHT_INDEX offsetof(struct wnd_extra, lineheight)
+#define WND_BORDER_INDEX offsetof(struct wnd_extra, border)
+#define WND_SCROLLBAR_INDEX offsetof(struct wnd_extra, scrollbar)
+#define WND_BACKGROUND_INDEX offsetof(struct wnd_extra, background)
+#define WND_LAST_INDEX (sizeof(struct wnd_extra))
+
+#define WND_EXTRA_BYTES (WND_LAST_INDEX)
extern DWORD dwWindowsThreadId;
extern HANDLE hWindowsThread;
@@ -794,3 +910,8 @@
#ifdef CYGWIN
extern int w32_message_fd;
#endif /* CYGWIN */
+
+#ifdef USE_W32_IME
+extern void w32_set_ime_logfont (HWND, struct frame *);
+extern void w32_ime_control_init (void);
+#endif /* USE_W32_IME */
--- ./src/w32xfns.c.orig 2015-02-02 02:27:17.000000000 +0900
+++ ./src/w32xfns.c 2015-04-11 07:27:30.750130200 +0900
@@ -178,12 +178,30 @@
/* The while loop takes care of multiple sets */
+#if !defined(USE_W32_CALL_LISP_THREAD)
while (!nQueue && bWait)
{
leave_crit ();
WaitForSingleObject (input_available, INFINITE);
enter_crit ();
}
+#else
+ if (bWait)
+ while (!nQueue)
+ {
+ leave_crit ();
+ while (WaitForSingleObjectEx
+ (input_available, INFINITE, TRUE) == WAIT_IO_COMPLETION)
+ ;
+ enter_crit ();
+ }
+ else if (nQueue == 0)
+ {
+ leave_crit ();
+ SleepEx(0, TRUE);
+ enter_crit ();
+ }
+#endif
if (nQueue)
{
--- ./src/window.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/window.c 2015-04-11 07:27:30.759130600 +0900
@@ -132,6 +132,12 @@
/* Same for window_scroll_line_based. */
static EMACS_INT window_scroll_preserve_hpos;
static EMACS_INT window_scroll_preserve_vpos;
+#ifdef USE_W32_IME
+Lisp_Object Vset_selected_window_buffer_functions;
+Lisp_Object Qset_selected_window_buffer_functions;
+Lisp_Object Vselect_window_functions;
+Lisp_Object Qselect_window_functions;
+#endif /* USE_W32_IME */
static void
CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
@@ -474,6 +480,9 @@
{
register struct window *w;
struct frame *sf;
+#ifdef USE_W32_IME
+ Lisp_Object oldwin = selected_window;
+#endif /* USE_W32_IME */
CHECK_LIVE_WINDOW (window);
@@ -526,6 +535,11 @@
record_buffer (w->contents);
}
+#ifdef USE_W32_IME
+ if (!NILP (Vselect_window_functions))
+ run_hook_with_args_2 (Qselect_window_functions, oldwin, window);
+#endif /* USE_W32_IME */
+
return window;
}
@@ -3561,6 +3575,18 @@
set_window_buffer (window, buffer, 1, !NILP (keep_margins));
+#ifdef USE_W32_IME
+ if (! NILP (Vset_selected_window_buffer_functions))
+ {
+ Lisp_Object temp[4];
+ temp[0] = Qset_selected_window_buffer_functions;
+ temp[1] = tem;
+ temp[2] = window;
+ temp[3] = buffer;
+ Frun_hook_with_args (4, temp);
+ }
+#endif /* USE_W32_IME */
+
return Qnil;
}
@@ -7247,6 +7273,10 @@
Fput (Qscroll_down, Qscroll_command, Qt);
DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
+#ifdef USE_W32_IME
+ DEFSYM (Qset_selected_window_buffer_functions, "set-selected-window-buffer-functions");
+ DEFSYM (Qselect_window_functions, "select-window-functions");
+#endif
DEFSYM (Qwindowp, "windowp");
DEFSYM (Qwindow_configuration_p, "window-configuration-p");
DEFSYM (Qwindow_live_p, "window-live-p");
--- ./src/xdisp.c.orig 2015-04-02 16:23:06.000000000 +0900
+++ ./src/xdisp.c 2015-04-11 07:27:30.776131800 +0900
@@ -11683,8 +11683,24 @@
/* Prepare for redisplay by updating menu-bar item lists when
appropriate. This can call eval. */
+#ifdef USE_W32_IME
+static void prepare_menu_bars_0 ();
+static void
+prepare_menu_bars()
+{
+ extern Lisp_Object Qw32_ime_buffer_switch_p;
+ int count = SPECPDL_INDEX ();
+
+ specbind (Qw32_ime_buffer_switch_p, Qnil);
+ prepare_menu_bars_0 ();
+ unbind_to (count, Qnil);
+}
+static void
+prepare_menu_bars_0 ()
+#else
static void
prepare_menu_bars (void)
+#endif
{
bool all_windows = windows_or_buffers_changed || update_mode_lines;
bool some_windows = REDISPLAY_SOME_P ();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment