emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master a370cd8: Add brief.el v5.80, Brief editor mode, an emulato


From: Luke Lee
Subject: [elpa] master a370cd8: Add brief.el v5.80, Brief editor mode, an emulator of Brief editor.
Date: Mon, 13 Aug 2018 10:51:05 -0400 (EDT)

branch: master
commit a370cd8089c1f80e3ccc5e2c69de1ab85aa3eb6f
Author: Luke Lee <address@hidden>
Commit: Luke Lee <address@hidden>

    Add brief.el v5.80, Brief editor mode, an emulator of Brief editor.
---
 packages/brief/brief.el | 7136 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 7136 insertions(+)

diff --git a/packages/brief/brief.el b/packages/brief/brief.el
new file mode 100644
index 0000000..26d503f
--- /dev/null
+++ b/packages/brief/brief.el
@@ -0,0 +1,7136 @@
+;;; brief.el --- Brief Editor Emulator
+
+;; Copyright (C) 2018  Free Software Foundation, Inc.
+
+;; Author:     Luke Lee <address@hidden>
+;; Maintainer: Luke Lee <address@hidden>
+;; Keywords:   brief, emulations, crisp
+;; Version:    5.80
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs 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.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This Brief editor emulator was originally based on the CRiSP mode
+;; emulator (listed below), with extensive rewriting.
+;;
+;;  CRiSP mode from XEmacs: revision 1.34 at 1998/08/11 21:18:53.
+;;
+;;   CRiSP mode was created on 01 Mar 1996 by by
+;;   "Gary D. Foster <address@hidden>"
+
+;; There is also an Emacs version of "crisp.el" which is now obsolete
+;; but still (temporarily) exists in the Emacs source code repository
+;; at "<emacs>/src/lisp/obsolete/crisp.el".  In case of it being
+;; removed from Emacs source tree someday, I moved the whole
+;; development history from Emacs source into ELPA repository at
+;; "<elpa>/packages/crisp".  To check the whole development history
+;; log you need to clone the ELPA git repository, then go to
+;; sub-directory "packages/crisp" and type the command
+;; "git log --follow crisp.el".  Notice the "--follow" argument,
+;; lacking it git will only give you the history "after" the
+;; directory structure changed, which was introduced when moving
+;; CRiSP from Emacs source repository to ELPA.
+
+;;; History:
+
+;; Starting from 31 May 2001 I started modifying XEmacs CRiSP mode
+;; emulator for my own use on Linux, in order to get a similar
+;; finger-feel like the MS-DOS-based Brief editor which I had been
+;; using for ~10 years at that time.  Those days around 2001 the
+;; MS-DOS backward compatibility was getting worse and worse for
+;; every MS-Windows release and which forced me to find a free
+;; replacement for Brief.  Then I found the XEmacs+CRiSP mode that
+;; seems to be the best candidate at that moment.  It implemented at
+;; least the basic Brief editor functionality but far from a complete
+;; emulator.  Therefore I started doing modifications and adding
+;; missing Brief features on a per-need basis.
+;;
+;; After 17+ years of intermittent development (as the release of
+;; version 5.80), the code is almost completely rewritten compare to
+;; the original XEmacs CRiSP mode code.
+;;
+;; A lot of editor behaviors were also adapted to Emacs.  One example
+;; is that Brief mode emulator could respect `visual-line-mode',
+;; `toggle-truncate-lines' and hidden/abbreviated mode texts (which
+;; usually shown as "..." in Emacs) such as org-mode, hideshow mode
+;; and hideif (hide "#ifdef", conditional compilation units, another
+;; package that I had rewritten).  When texts are hidden at cursor
+;; line, Brief line-oriented commands like line-cut, line-copy,
+;; line-deletion ... will operate on all hidden lines.
+;;
+
+;;; Brief Extension:
+
+;;
+;; This Brief mode extends a lot of functionalities that the original
+;; Brief editor don't have.  For example, the original Brief <ctrl>-<->
+;; (C--) kills current buffer; however, when prefixed with <ctrl>-<u>
+;; (C-u) the <ctrl>-<-> (C--) command will restore the just killed
+;; buffer.  This is convenient as sometimes user accidentally hit C--
+;; for some reason and lost the buffer.  Another simple example is the
+;; original Brief command <alt>-<f> (M-f) which shows the file name of
+;; the current buffer; while prefixed with C-u it will also copy the
+;; file name into the clipboard.  The following sections list some of
+;; the major extensions of this extended Brief mode.
+;;
+;; * Visual mode, line truncation and hidden texts:
+;;   (config option: `brief-linecmd-respect-visual')
+;;
+;; In the original DOS Brief editor, press [home] key once brings the
+;; cursor to the beginning of the current line; a second [home] key to
+;; the top of the window and the third [home] to the beginning of the
+;; file.  In Emacs it's a bit different; it has `toggle-truncate-lines'
+;; to wrap long lines and `visual-line-mode' to do smart word-warp.
+;; This Brief mode emulator thus adapted to Emacs accordingly: if long
+;; lines are wrapped, the first [home] keystroke brings the cursor to
+;; the beginning of the "visual line"; a second [home] then brings the
+;; cursor to the beginning of the "physical line".  The third [home] to
+;; the top of the window and finally the fourth [home] to the beginning
+;; of the file.  When `toggle-truncate-lines' is enabled and
+;; `visual-line-mode' is off, Brief mode then behaves the same as DOS
+;; Brief.  Similar behavior applies to the [end] key, as well as many
+;; other keyboard commands like clipboard copy/paste functions.
+;;
+;; This further leads to an user-customizable option:
+;; `brief-linecmd-respect-visual'.  This customized variable determines
+;; if a user would like to have line commands (like line-copy, line-cut,
+;; line-deletion...) by default respect visual mode or not.  That
+;; variable is by default nil and thus line commands will by default
+;; operate on "physical" line(s) instead of "visual" lines.  They
+;; can be overridden by a common prefix C-u or a negative prefix
+;; number.
+;;
+;; See the comments of the function `brief-is-visual-operation' for
+;; more detail.
+;;
+;;  Basically, the rules are:
+;;
+;;   1. `brief-linecmd-respect-visual' determines the current default
+;;      mode, either visual or physical line mode.
+;;   2. Either a common prefix C-u (\\[universal-argument]) or negative
+;;      prefix reverse the current mode; aka,
+;;      (not `brief-linecmd-respect-visual').
+;;
+;;  Example:
+;;
+;; Try editing a text using line deletion command [M-d] on some very
+;; long lines a few times longer than the window width (or shrink
+;; window size), or an org-mode document with long lines. Now either
+;; turn on `visual-line-mode' or enable line wrapping using
+;; `toggle-truncate-lines'.  Assuming `brief-linecmd-respect-visual'
+;; is kept default value 'nil' which means physical line operations
+;; are expected by default, now try the following key combinations:
+;;
+;;   1. [M-d]               : delete one "physical" line.
+;;   2. [C-u] [M-d]         : delete one "visual" line.
+;;   3. [C-4] [M-d]         : delete four "physical" lines as it's
+;;                            prefixed with integer '4'.
+;;   4. [C-u] [-] [4] [M-d] : delete four "visual" lines as it's
+;;                            prefixed with integer '-4'.
+;;
+;; On the other hand, cursor movement always respects visual mode
+;; unless prefixed with C-u or negative prefix number.
+;;
+;; * Fast line number computation cache:
+;;   (config option: `brief-replace-emacs-func:line-number-at-pos')
+;;
+;; Brief editor window operation relies heavily on cursor position to
+;; determine which window is going to be operated.  As the original
+;; Emacs line number computation is too slow (especially when a lot
+;; of texts are hidden within a window) so a line counting caching
+;; mechanism is implemented.  By default, the original Emacs function
+;; `line-number-at-pos' is replaced by `brief-fast-line-number-at-pos'
+;; if Emacs version is older than 27 where native line numbering is
+;; not yet supported.  There is actually a custom variable named
+;; `brief-replace-emacs-func:line-number-at-pos' defined near the end
+;; of this file.  It controls if the `line-number-at-pos' is going
+;; to be replaced or not, regardless of the Brief mode is on or off.
+;;
+;; It is recommended to keep the default value for fast line number
+;; calculation which helps Linum mode as well, otherwise, you might
+;; experience big slow down when switching windows using Brief window
+;; commands (i.e. [F1-<arrow>] key).
+;;
+;; * Huge clipboard/Xselection texts:
+;;   (config option: `brief-enable-postpone-selection')
+;;
+;; In the following context and code the term Xselection and clipboard
+;; are used interchangeably and refer to the same thing - the XWindow
+;; selection (mainly "primary" and "clipboard", "secondary" is not
+;; used) or the Windows clipboard.  This emulator tries to sync kill-
+;; ring with Xselection even in terminal mode (Xterm).
+;;
+;; This Brief mode also implements an asynchronous mechanism to
+;; prevent the selected texts from immediately going into the
+;; Xselection, as all (most) *NIX GUI program currently do -- any
+;; marked/selected text got copied into Xselection with no delay.
+;;
+;; This helps to boost performance a lot especially when huge texts
+;; (say, 500Mb texts) are being selected.  There is no point to keep
+;; copying texts into clipboard before user completed the text
+;; selection.  When the user tries to enlarge the huge selection area,
+;; copying texts into clipboard could take very long and the system
+;; seems to stop responding.  The auto-repeated cursor movement key
+;; commands are then accumulated into the key queue and make things
+;; worse.  Our Brief mode does not immediately copy texts into
+;; Xselection until the cursor movement key is released, which usually
+;; means a user has completed (say, at least temporarily) the
+;; selection.  Unfortunately, this key-releasing event cannot be seen
+;; within Emacs Lisp so we workaround this by detecting if the keyboard
+;; is idle or not. Functions are called asynchronously by the idle
+;; timer.
+;;
+;; There is also another important reason for doing so, on Xservers
+;; running on MS Windows with MS office running in the background,
+;; this problem is fatal and usually caused a system crash in the end.
+;; With this selection postponement, we prevented that.  For more
+;; detail description about the MS problem, please search the comments
+;; in the following source code containing "Xselection Postponement:".
+;; The solution is not perfect but works for most cases.
+;;
+;; A custom option `brief-enable-postpone-selection' is defined to
+;; control if the selection postponement is enabled or not.  By
+;; default, it's turned on.
+;;
+;; * External Xselection helper programs `xsel' and `xclip':
+;;   (config option: `brief-use-external-clipboard-when-possible')
+;;
+;; In order to further boost the performance when a user selects huge
+;; texts, external Xselection helper programs are used, although it
+;; increased the complexity of the asynchronous event handling.  The
+;; main reason is that the internal Emacs Xselection code is
+;; un-interruptible and not quit-able.  When Emacs tries to get/set
+;; Xselection, the operation is blocking and Emacs is not responding
+;; to any key before the operation completes.
+;;
+;; For example, when a user selects some huge texts using arrow keys
+;; and paused a short period of time then try to continue enlarging/
+;; shrinking the selection area using arrow keys, the previous Emacs
+;; Xselection get/set operation is usually not completed yet (due to
+;; the size of huge text).  Therefore the attempt to continue
+;; enlarging/shrinking texts will be blocked and user will experience
+;; no response until Emacs completed the Xselection operation.  What's
+;; more, those continued arrow keys then in turn queued in the Xwindow
+;; system.  When Emacs eventually resume responding, the selection
+;; area will be changed accordingly to some earlier keys in the queue
+;; that the user typed a few seconds ago.  This kind of non-real-time
+;; response usually confuse the user and sometimes cause problems.
+;;
+;; To workaround this we implemented our own non-blocking and quit-able
+;; Xselection get/set functions, with the help of external X utilities
+;; like `xsel' or `xclip'.  Therefore user needs to install `xsel' or
+;; `xclip' in the *NIX system to get the benefit.  If neither xsel nor
+;; xclip is installed, it will fall back using the Emacs internal
+;; blocking Xselection code.  With our non-blocking implementation,
+;; when a user tries to enlarge/shrink/quit a huge text selection
+;; while the Xselection gets/sets operation is in-progress, the
+;; unfinished operation will be interrupted immediately.  A user gets
+;; an immediate response.
+;;
+;; A custom variable `brief-use-external-clipboard-when-possible' (by
+;; default 't) controls if this Brief mode would invoke external helper
+;; or not.  For further detail consult the help message for function
+;; `brief-external-set-selection' and `brief-external-get-selection'.
+;; There are also a few other configuration options controlling if
+;; the progress is showing in the message area or not:
+;;    `brief-show-external-clipboard-recv-progress'
+;;    `brief-show-external-clipboard-send-progress' ...
+;; With these two options, the user can see the progress when big
+;; clipboard data are transferring.
+;;
+;; Also, notice that for terminal mode Emacs under X running Brief mode
+;; the external helpers are always invoked in order to copy/paste texts
+;; with any other windowed mode applications.
+;;
+;; * Fast cursor movement:
+;;
+;; What I like most about the old DOS Brief editor is its super fast
+;; cursor movement.  On a lot of occasions, I didn't even need to do
+;; page-up or page-down.  Once you get used to the cursor speed you
+;; really don't want to return to the normal speed.  Unfortunately,
+;; this cannot be done in Emacs.  However, there is an alternative way
+;; to achieve similar effect -- setting X keyboard autorepeat rate
+;; using the command line `xset' X utility:
+;;
+;;  # xset r rate 255 100
+;;
+;; Although it's still not as fast as DOS Brief editor, it's at least
+;; closer.  Also, notice that this will affect the global X window
+;; environment.
+;;
+
+;;; Key Binding Compatibility Note:
+
+;; Notice that the original brief commands keypad-'+' (copy line) and
+;; keypad-'-' (cut line) are now duplicated into <control>-<insert>
+;; (copy line) and <shift>-<delete> (cut line).  This is mainly for
+;; keyboards and notebooks without a keypad.
+;;
+;; As both <Alt>-<n> (M-n) and <Alt>-<p> (M-p) are so widely used in
+;; various Emacs modes so in the Brief mode M-n and M-p are assigned
+;; "weakly". This means any major mode can override the assignment of
+;; M-n and M-p.  In Brief mode, M-n is used for switching to next
+;; buffer while M-- for the previous buffer.  Both of them are
+;; frequently used commands, therefore, we also weakly assigned M-+
+;; and M-= for M-n and M-_ for M--.  However, for M-p (brief-print)
+;; we do not provide other key combinations for the same key.
+;;
+;; For line marking commands, as Emacs regions always start/end at
+;; cursor so the Brief mode region commands <Alt>-<L> <arrow> (M-L
+;; prefixed arrow keys) behave a bit differently from the original
+;; Brief ones (unless I implemented it using the secondary Xselection,
+;; which could lead to more issues).  This Brief mode does not
+;; immediately mark the current line until the followed arrow key user
+;; typed.  Also, the 'paste' command key <insert> also insert keys
+;; starting from the cursor position instead of the beginning of
+;; current line.  On the other hand, 'copy line', 'cut line' and
+;; 'delete line' commands work on the beginning of current line like
+;; the original Brief editor did.
+;;
+;; For a complete keybinding list, check the following source code
+;; commented with "Brief mode key bindings".
+
+;;; Platform Compatibility Notes:
+
+;; This brief mode is mainly tested for X window system, as there are
+;; too many combinations of versions (EmacsVers x {OSes} x {XServers})
+;; need to be tested but I don't have all environments (and time).
+;; Therefore, I mainly tested recent Emacs versions on Linux machines
+;; on a daily use basis.  For other combinations listed below they
+;; are not heavily tested; usually tested when they are been used.
+;;
+;; Test Matrix (note: all 64-bit systems):
+;;
+;; On Linux: (including native X11 Emacs, terminal mode Emacs on xterm
+;;            and Linux X11 Emacs running on VcXsrv (1.19.3.4+) under
+;;            Win10):
+;;      Emacs 23.3.1, 24.4.50.2, 25.2.2, 26.0.50, 26.1 and 27.0.50.
+;;      Mainly focusing on Emacs 25 ~ 27.
+;;      For Emacs23 and 24, not all the functionality behaves the same
+;;        as in Emacs 25 ~ 27 (ex. search/replace in region/rectangle).
+;; On Cygwin:
+;;      Emacs 25.3.1, 26.1.
+;; On Win10:
+;;      Emacs 25.1.1 (x86_64-w64-mingw32).
+;; On WSL (Windows Subsystem for Linux):
+;;      Emacs 24.5.1, terminal mode and on VcXsrv (1.19.3.4+).
+;;
+
+;;; Enabling Brief Mode:
+
+;; Enable this package by putting "(require 'brief)" in your .emacs
+;; and "(brief-mode 1)" to enable it.  If you want to toggle it later
+;; interactively just use "M-x brief-mode" to toggle it on or off.
+;; Notice that "M-x" may be overridden if `brief-override-meta-x' is
+;; set to non-nil (default value) when you enable brief mode.  In this
+;; case use function key #10 "F10 brief-mode" to toggle it off.
+
+;; The default keybindings for Brief mode override the M-x key to exit
+;; the editor.  If you don't like this functionality, you can prevent
+;; this behavior (or redefine it dynamically) by customizing the value
+;; of `brief-override-meta-x' either in your .emacs or interactively.
+;; The default setting is t, which means that M-x will by default
+;; by default run `save-buffers-kill-emacs' instead of the command
+;; `execute-extended-command'.
+
+;; It is recommended to load the Ibuffer package "(require 'ibuffer)"
+;; before or after loading Brief mode.  "M-b" will invoke ibuffer
+;; to show buffer menu if ibuffer package presents, otherwise it by
+;; default runs `buffer-menu'.
+
+;; This package will automatically load the "scroll-lock.el" package if
+;; you put "(setq brief-load-scroll-lock t)" in your .emacs before
+;; loading this package.  If this feature is enabled, it will bind
+;; "<Scroll_Lock>" to the scroll-lock mode toggle.  The scroll-lock
+;; package provides the scroll-locking feature in Brief.
+
+;; Finally, if you want to change the string displayed in the modeline
+;; when this mode is in effect, override the definition of
+;; `brief-mode-mode-line-string' in your .emacs.  The default value is
+;; " Brief" which may be a bit lengthy if you have a lot of things
+;; being displayed there.
+
+;; All these overrides should go *before* the (require 'brief)
+;; statement.
+
+;;; Cygwin 2.x Users:
+
+;; When the default "mintty" application is used to lunch Cygwin, if
+;; you would like to run Emacs with Brief mode enabled in mintty's
+;; special terminal mode, some mintty window settings need to be
+;; changed:
+;;
+;; 1. Right-click in the Cygwin "mintty" window on the title bar
+;; 2. Choose "Options"
+;; 3. At the left sided pane choose "Keys" category
+;; 4. Disable (uncheck) the following shortcuts:
+;;
+;;      Copy and Paste (Ctrl/Shift+Ins)
+;;      Switch window (Ctrl+[Shift+]Tab)
+;;      Zoom (Ctrl+plus/minus/zero)
+;;      Alt+Fn shortcuts
+;;      Ctrl+Shift+letter shortcuts
+;;
+;; 5. Click 'Apply' and 'Save'
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl)
+  ;; Quiet byte-compiler about argument number changes due to advice functions,
+  ;; as well as other warnings that's known to be not important.
+  (setq byte-compile-warnings
+        '(not
+          ;; For backward compatibility's sake, obsolete functions and
+          ;; unresolved function (like w32 ones) might be used
+          obsolete
+          unresolved
+          ;; Some advised function causing arguments count change, ignore them
+          redefine))
+  (if (version< emacs-version "25.0")
+      (setq byte-compile-warnings
+            (append byte-compile-warnings '(free-vars callargs)))))
+;;(eval-when-compile (require 'cl-lib))
+;; local variables
+;; Relys on `cua-rectangle-mark-mode' to perform rectangle operations.
+(require 'cua-base)
+(require 'cua-rect)
+;; "replace" package is Emacs26 only, for `query-replace', it's autoloaded
+;; so we don't need to "require" it explicitly, otherwise it will cause
+;; backward compatibility issues.
+;;(require 'replace)
+
+(defconst brief-version "5.80"
+  "The version of this Brief emulator.")
+
+;;
+;; Backward compatibility and inter-platform operative compatibility:
+;;
+
+(defvar brief-is-cygwin nil
+  "Check if we're currently running under Cygwin")
+
+;; This value don't change so we only need to check at load/eval time.
+(setq brief-is-cygwin
+      (or (eq system-type 'cygwin)
+          (and (file-exists-p "/dev/clipboard")
+               (file-exists-p "/dev/windows")
+               (file-exists-p "/proc/version")
+               (string= (with-temp-buffer
+                          (insert-file-contents "/proc/version" nil 0 10)
+                          (buffer-string))
+                        "CYGWIN_NT-"))))
+
+(defvar brief-selection-op-legacy nil)
+
+(eval-when (compile load eval)
+
+  (defmacro brief-is-x ()
+    `(eq (framep (selected-frame)) 'x))
+
+  (defmacro brief-is-terminal ()
+    `(eq (framep (selected-frame)) 't))
+
+  (defmacro brief-is-winnt ()
+    `(or (eq system-type 'windows-nt) ;; Is there a terminal mode Emacs for 
winnt?
+         (eq (framep (selected-frame)) 'w32)   ;; Win64 Emacs still return w32
+         (eq (framep (selected-frame)) 'w64))) ;; for future, just in case
+
+  (defmacro brief-input-pending-p ()
+    (if (version< emacs-version "24.0")
+        `(input-pending-p)
+      `(input-pending-p t)))
+
+  ;; Define macros for all cases, byte-compilation, interpreting, or loading.
+  (if (and (version< emacs-version "25.1")
+           ;; in case some backward compatibility layer already loaded
+           (not (fboundp 'save-mark-and-excursion)))
+      (defmacro save-mark-and-excursion (&rest body)
+        "A backward compatibility macro for Emacs version below 25.1.
+This macro behaves exactly like `save-excursion' before Emacs 25.1.
+After Emacs 25.1 `save-excursion' no longer save mark and point."
+        `(save-excursion ,@body)))
+
+  ;; Emacs <= v25
+  (unless (boundp 'inhibit-message)
+    (defvar inhibit-message nil))
+
+  (unless (fboundp 'process-live-p)
+    ;; Copy&paste from Emacs26 for older Emacs
+    (defun process-live-p (process)
+      "Returns non-nil if PROCESS is alive.
+A process is considered alive if its status is `run', `open',
+`listen', `connect' or `stop'.  Value is nil if PROCESS is not a
+process."
+      (and (processp process)
+           (memq (process-status process)
+                 '(run open listen connect stop)))))
+
+  ;; Backward compatibility functions for Emacs23
+  (when (version< emacs-version "24.0")
+
+    (if (and (not (fboundp 'x-get-selection-value))
+             (fboundp 'x-get-selection))
+      (defun x-get-selection-value ()
+        (x-get-selection 'PRIMARY)))
+
+    (unless (fboundp 'file-equal-p)
+      ;; Code copy&pasted from Emacs26 files.el for Emacs-23 backward 
compatibility
+      (defun file-equal-p (file1 file2)
+        "Return non-nil if files FILE1 and FILE2 name the same file.
+If FILE1 or FILE2 does not exist, the return value is unspecified."
+        (let ((handler (or (find-file-name-handler file1 'file-equal-p)
+                           (find-file-name-handler file2 'file-equal-p))))
+          (if handler
+              (funcall handler 'file-equal-p file1 file2)
+            (let (f1-attr f2-attr)
+              (and (setq f1-attr (file-attributes (file-truename file1)))
+                   (setq f2-attr (file-attributes (file-truename file2)))
+                   (equal f1-attr f2-attr)))))))
+
+    (unless (fboundp 'read-char-choice)
+      (defun read-char-choice (prompt chars &optional inhibit-keyboard-quit)
+        (let ((inhibit-quit inhibit-keyboard-quit)
+              c)
+          (while (not (member
+                       (setq c (read-char prompt))
+                       chars)))
+          c))))
+
+  (if (version< emacs-version "24.0")
+      ;; a wrapper function to ignore arguments
+      (defmacro bookmark-jump-wrapper (bmk func regionp)
+        `(bookmark-jump ,bmk ,func))
+    (defmacro bookmark-jump-wrapper (bmk func regionp)
+      `(bookmark-jump ,bmk ,func ,regionp)))
+
+  ;; Selection/clipboard related functions and variables
+  (when (version< emacs-version "25.1")
+
+    (unless (boundp 'saved-region-selection)
+      (defvar saved-region-selection nil))
+
+    (unless (boundp 'gui--last-selected-text-primary)
+      (if (boundp 'x-last-selected-text-primary)
+          (defvaralias 'gui--last-selected-text-primary
+            'x-last-selected-text-primary)
+        (defvar gui--last-selected-text-primary nil)))
+
+    (unless (boundp 'gui--last-selected-text-clipboard)
+      (if (boundp 'x-last-selected-text-clipboard)
+          (defvaralias 'gui--last-selected-text-clipboard
+            'x-last-selected-text-clipboard)
+      (defvar gui--last-selected-text-clipboard nil)))
+
+    ;; Also try to prevent cases that someone write his own compatibility codes
+    (if (brief-is-winnt)
+        (progn
+          (unless (fboundp 'gui-get-selection)
+            (setq brief-selection-op-legacy t)
+            (defalias 'gui-get-selection 'w32-get-clipboard-data))
+          (unless (fboundp 'gui-set-selection)
+            (defun gui-set-selection (type data)
+              (w32-set-selection data)))
+          (unless (fboundp 'gui-backend-get-selection)
+            (defun gui-backend-get-selection (selection-symbol target-type)
+              (w32-get-clipboard-data)))
+          (unless (fboundp 'gui-backend-set-selection)
+            (defun gui-backend-set-selection (selection value)
+              (w32-set-selection value))))
+
+      (unless (fboundp 'gui-get-selection)
+        (setq brief-selection-op-legacy t)
+        (defalias 'gui-get-selection 'x-get-selection))
+      (unless (fboundp 'gui-set-selection)
+        (defalias 'gui-set-selection 'x-set-selection))
+      (unless (fboundp 'gui-backend-get-selection)
+        (defun gui-backend-get-selection (selection-symbol target-type)
+          (x-get-selection selection-symbol target-type)))
+      (unless (fboundp 'gui-backend-set-selection)
+        (defun gui-backend-set-selection (selection value)
+          (x-set-selection selection value))))))
+
+(eval-when-compile
+  ;; Backward compatibility for Emacs versions without `defvar-local', which
+  ;; might not have `make-variable-buffer-local' defined so use
+  ;; `make-local-variable' here.
+  (unless (fboundp 'defvar-local)
+    (defmacro defvar-local (var val &optional doc)
+      `(progn
+         (defvar ,var ,val ,doc)
+         (make-local-variable ',var))))
+
+  (unless (fboundp 'window-body-width) ;; Emacs23
+    (defmacro window-body-width ()
+      `(window-width))))
+
+;; [07/11/2007] modified old function no longer works
+;;(defun brief-region-active ()
+;;  "Compatibility function to test for an active region."
+;;  (if (boundp 'zmacs-region-active-p)
+;;      zmacs-region-active-p
+;;    mark-active))
+
+;; replaced by (use-region-p)
+;;;; mark active means either line region active or rectangle active
+;;(defalias 'brief-mark-active 'use-region-p)
+;;  "Compatibility function to test for an active marked area."
+;;  mark-active)
+
+;; Helper functions and macros
+(defun brief-current-time ()
+  "Epoch time in floating point."
+  (let ((ct (current-time)))
+    (+ (logior (lsh (car ct) 16)
+               (cadr ct))
+       (* 1e-6 (caddr ct)))))
+
+(defvar brief-calibration-value 0.0
+  "Latest calibration value of UI performance.
+This value is a measurement of the performance when running Brief in a
+slow remote connection.")
+
+(defvar brief-calibration-count 0
+  "Number of worst case calibration done so far.")
+
+(defvar brief-calibration-sum 0.0
+  "The sum of worst case calibration values measured so far.")
+
+(defvar brief-calibration-ref 0.0
+  "Average worst case calibration value of UI performance.
+This value an average of `brief-calibration-value' measured so far.
+A lot of timeout values are adjusted accordingly to the slowdown
+referencing this value.")
+
+(defvar brief-slowdown-factor 1.0
+  "A slowdown measurement according to the calibration.
+This value is an empirical obtained thru various experiemnts.")
+
+(defun brief-calibration ()
+  "Compute the UI performance reference values.
+Notice that this function sometimes works only if called interactively."
+  (interactive)
+  ;; Yes, these can be done in a single setq, but this make things clearer.
+  (setq brief-calibration-value
+        (- (- (brief-current-time)
+              (progn
+                (redisplay t)
+                (brief-current-time)))))
+  ;; Record only the worst case. In a lot of cases it takes very short
+  ;; period of time to calculate the value.
+  (when (> brief-calibration-value
+           brief-calibration-ref)
+    (setq brief-calibration-sum
+          (+ brief-calibration-sum
+             brief-calibration-value))
+    (setq brief-calibration-count
+          (1+ brief-calibration-count))
+    (setq brief-calibration-ref
+          (/ brief-calibration-sum brief-calibration-count))
+    ;; Purely empirical and conjecture values.
+    (cond
+     ((< brief-calibration-ref 0.1)
+      (setq brief-slowdown-factor 1.0))
+     ((< brief-calibration-ref 0.2)
+      (setq brief-slowdown-factor 2.0))
+     ((< brief-calibration-ref 0.3)
+      (setq brief-slowdown-factor 3.0))
+     ;; Very slow systems
+     ((< brief-calibration-ref 0.4)
+      (setq brief-slowdown-factor 4.0))
+     ((< brief-calibration-ref 0.5)
+      (setq brief-slowdown-factor 5.0))
+     ((< brief-calibration-ref 0.6)
+      (setq brief-slowdown-factor 6.0))
+     ((< brief-calibration-ref 0.7)
+      (setq brief-slowdown-factor 7.0))
+     ;; Extremely slow systems, I wonder if anyone would work in such kind
+     ;; of enrironments.
+     (t (setq brief-slowdown-factor 8.0)))))
+
+;;(defvar brief-debugging t) ;; enable debugging here
+(eval-when (compile load eval)
+  (if (boundp 'brief-debugging)
+      (defun brief-dbg-message (&rest args)
+        (let ((inhibit-message t)
+              (msg (apply 'format args)))
+          ;;    (apply 'message args)
+          (message "%s %s" (format-time-string "[%H:%M:%S.%3N]" (current-time))
+                   msg)))
+    (defmacro brief-dbg-message (&rest args))))
+
+(defmacro brief-rectangle-active ()
+  "Compatibility macro to test for an active rectangle."
+  ;; For earlier versions of Emacs:
+  ;;   * Line region active: (region-active-p) = t and mark-active = t
+  ;;   * Rectangle active: (region-active-p) = nil and mark-active = t
+  ;; (not (region-active-p))
+  ;;
+  ;; For XEmacs:
+  ;;   * Line region active: mouse-track-rectangle-p = nil and mark-active = t
+  ;;   * Rectangle active:   mouse-track-rectangle-p = t   and mark-active = t
+  `cua--rectangle)
+
+(eval-when (compile load eval)
+  (if (version< emacs-version "24.0")
+      ;; for Emacs23, rectangle won't activate region
+      (defmacro brief-use-region ()
+        "In Brief this means either a line region or rectangle is active."
+        `(or (ignore-errors
+               ;; In Emacs23 sometimes this will invoke (region-end) and cause
+               ;; error: "The mark is not set now, so there is no region"
+               (use-region-p))
+             (brief-rectangle-active)))
+    (defmacro brief-use-region ()
+      "In Brief this means either a line region or rectangle is active."
+      `(or (use-region-p)
+           ;; [2018-02-01 Thu] If we don't include `brief-rectangle-active'
+           ;; here, on some rare cases the `use-region-p' will return NIL
+           ;; while `brief-rectangle-active' remains non-NIL.  For example, it
+           ;; once happened when: (1) marking a rectangle (2) use 
self-inserting
+           ;; commands (3) undo -- at this moment the rectangle will disappear
+           ;; and `deactivate-mark-hook' will be executed.  During this period
+           ;; of time, any function in the hook will experienced `use-region-p'
+           ;; be NIL while `brief-rectangle-active' be non-NIL.
+           (brief-rectangle-active)))))
+
+(defun brief-region-beginning ()
+  "Safe version of `region-beginning' to prevent error signaling."
+  (and (brief-use-region)
+       (region-beginning)))
+
+(defun brief-region-end ()
+  "Safe version of `region-end' to prevent error signaling."
+  (and (brief-use-region)
+       (region-end)))
+
+(defmacro brief-line-region-active ()
+  "Compatibility function to test for an active line region."
+  ;; (region-active-p) return t for either rectangle or region
+  `(and (region-active-p)
+        (not cua--rectangle)))
+
+(defmacro brief-keep-rectangle-unchanged ()
+  "Keep rectangle unchanged after cursor commands."
+  ;; This prevents CUA post-command handler resize rectangle
+  ;; after we changed the `point'
+  `(setq cua--buffer-and-point-before-command nil))
+
+(defmacro brief-xor (a b)
+  "A macro for exclusive or (xor a b), side effects prevented."
+  `(let ((A ,a)  ;; expand only once, prevent side effect
+         (B ,b))
+     (and (or A B)
+          (not (and A B)))))
+
+;;; Customization
+
+(defgroup brief nil
+  "Emulator for Brief key bindings."
+  :prefix "brief-"
+  :group 'emulations)
+
+(defvar brief-mode-original-keymap (current-global-map)
+  "The original keymap before Brief emulation mode remaps anything.
+This keymap is restored when Brief emulation mode is disabled.")
+
+(defvar brief-global-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map brief-mode-original-keymap)
+    map)
+  "Brief global keymap for Brief emulation mode.
+All the bindings are assigned here instead of directly into the
+inherited current global keymap.  In this way we can have brief mode
+key assignments placed in the least priority place in order to respect
+other minor modes.")
+
+;;[2015-04-13 15:42:21 +0800] I found setting its parent will slow down
+;; the system, especially if brief-prefix-F1's parent is set to
+;; `brief-global-mode-map', when openning the menu items (shift-f10)
+;; it will take "extremely" long to open. Seems that it will lengthen
+;; the key searching route a lot.
+;;(defvar brief-prefix-meta-l
+;;  (let ((map (make-sparse-keymap)))
+;;    (set-keymap-parent map `brief-global-mode-map')
+;;    map)
+;;  "Prefix key M-l for Brief emulation mode.")
+(defvar brief-prefix-meta-l (make-sparse-keymap)
+  "Prefix key M-l for Brief emulation mode.")
+
+(defvar brief-prefix-F1 (make-sparse-keymap)
+  "Prefix key F1 for Brief emulation mode.")
+
+(defvar brief-prefix-F2 (make-sparse-keymap)
+  "Prefix key F2 for Brief emulation mode.")
+
+(defvar brief-prefix-F3 (make-sparse-keymap)
+  "Prefix key F3 for Brief emulation mode.")
+
+(defvar brief-prefix-F4 (make-sparse-keymap)
+  "Prefix key F4 for Brief emulation mode.")
+
+;;
+;; Customized Settings
+;;
+
+;;;###autoload
+(defcustom brief-mode nil
+  "Track status of Brief emulation mode.
+A value of nil means Brief mode is not enabled.  A value of t
+indicates Brief mode is enabled.
+
+Setting this variable directly does not take effect;
+use either M-x customize or the function `brief-mode'."
+  :set        (lambda (symbol value) (brief-mode (if value t nil)))
+  :initialize 'custom-initialize-default
+  :require    'brief
+  :type       'boolean
+  :group      'brief)
+
+(defcustom brief-mode-mode-line-string " Brief"
+  "String to display in the mode line when Brief emulation mode is enabled."
+  :type  'string
+  :group 'brief)
+
+(defcustom brief-override-meta-x t
+  "*Controls overriding the normal Emacs M-x key binding in this Brief
+emulator.  Normally the Brief emulator rebinds M-x to 
`save-buffers-exit-emacs',
+and provides the usual M-x functionality on the F10 key.  If this
+variable is non-nil, M-x will exit Emacs."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-warn-meta-x-moved t
+  "Show help message when `brief-override-meta-x' is non-nil.
+New user might be wondering where the original <M-x> key has gone,
+so this shows a message on Brief mode start to notify that that key
+combination has been moved to '<f10>' key."
+  :type 'boolean
+  :group 'brief)
+
+(defcustom brief-query-exit-emacs t
+  "Ask if user really want to exit Emacs, when `brief-override-meta-x' is t.
+This option is useful for people who has already been accustomed to
+treat M-x as `execute-extended-command' \\[execute-extended-command].  This 
gives user
+the second chance without quitting Emacs immediately and accidentally."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-load-scroll-lock nil
+  "Controls loading of the Scroll Lock in the Brief emulator.
+Its default behavior is to load and enable the Scroll Lock minor mode
+package when enabling the Brief emulator.
+
+If this variable is nil when you start the Brief emulator, it
+does not load the scroll-lock package."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-load-hook nil
+  "Hooks to run after loading the Brief emulator package."
+  :type  'hook
+  :group 'brief)
+
+;; Some X systems use 'PRIMARY while some use 'CLIPBOARD.
+;; Enabling both can ensure data sync but night become slow when
+;; clipboard data is huge.
+(defcustom brief-select-enable-primary t
+  "On XWinodws enable Brief to use 'PRIMARY selection.
+For Windows NT systems we always use 'CLIPBOARD and this option has
+no effect."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-select-enable-clipboard nil
+  "On XWindows enable Brief to use 'CLIPBOARD selection.
+For Windows NT systems we always use 'CLIPBOARD and this option has
+no effect."
+  :type  'boolean
+  :group 'brief)
+
+;;
+;; Xselection get/set Postponement
+;;
+
+(defun brief-set:brief-enable-postpone-selection (sym val)
+  "Enable/disable the postponement of setting Xselection.
+For more detail check `brief-enable-postpone-selection'."
+  (when brief-mode
+    ;; Forward references, available only after brief mode is loaded
+    (brief-resume-gui-set-selection)
+    (if val
+        (brief-enable-clipboard-postponement)
+
+      (brief-disable-clipboard-postponement)))
+  (set sym val))
+
+(defcustom brief-enable-postpone-selection t
+  "Flag for enabling/disabling of the postponement of setting Xselection.
+
+When region/rectangle is being marked, Emacs actively copies marked
+region/rectangle into Xselection and behaves like any other X
+applications.  However this is sometimes too excessive if the marked
+region is huge: a tiny change of the selection requires a huge update
+of the Xselection which could take very long.  Moreover, when doing
+this under Xservers on Microsoft Windows with any MS-office application
+running, it could cause problems if there are a lot of opened Xwindows,
+say, 20 Emacs Xwindow frames opened.
+
+For more detail explanation, see the comments in the source code before
+the definition of the variable `brief-is-gui-set-selection-postponed'.
+
+Notice that to change the setting of this value, `custom-set-variables'
+need to be used or only the value of is changed but it won't have any
+real effect until `brief-mode' changed."
+  :type  'boolean
+  :group 'brief
+  :set   'brief-set:brief-enable-postpone-selection)
+
+(defcustom brief-debounce-keys-microsoft-office nil
+;; Workaround MS-office issue, for detail explanation, see the comments
+;; in the source code before the definition of the variable
+;; `brief-is-gui-set-selection-postponed'.
+  "Debounce commands setting Xselection when MS office application is running.
+Keyboard commands that \"sets\" Xselection (e.g. marking region) could
+be problematic.  This problem only happens when running Emacs on
+Xservers under MS-Windows operating system, with *any* of the Microsoft
+Office applications running.
+
+This Brief mode already try to prevent this problem by postponing Xselection
+copying if the customized variable `brief-enable-postpone-selection' is
+set to non-NIL.  However, in case this problem persists on some slower
+machines this option is provided to allow users workaround it.
+
+Currently debouncing only implemented in `brief-kill-line' 
(\\[brief-kill-line]),
+`brief-delete-entire-line'(\\[brief-delete-entire-line]) and 
`brief-copy-line'(\\[brief-copy-line])."
+  :type  'boolean
+  :group 'brief)
+
+;;
+;; External Xselection (clipboard) helper function related
+;;
+
+(defcustom brief-force-set-external-selection t
+  "When setting current kill data, always set external selection.
+This is useful when multiple editors are sharing the external clipboard."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-external-xclipboard-timeout 5 ;; most-positive-fixnum
+  "Timeout seconds for Brief to invoke external xclipboard helper program."
+  :type  'number
+  :group 'brief)
+
+(defcustom brief-use-external-clipboard-when-possible t
+  "Use external clipboard program helper to read clipboard whenever possible.
+Emacs internal clipboard function has certain limitations, especially
+when processing huge clipboard contents.  With this flag enabled Brief
+will always use external clipboard program like 'xclip' to read
+clipboard data.  Notice when Brief is running in terminal mode it
+always use external clipboard program no matter if this flag is on
+or off."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-show-external-clipboard-recv-progress t
+  "Show progress when reading data from external clipboard helper program.
+This is useful when the clipboard data is very large.  Without this
+option there might be no visual indication about the (in)completion
+of clipboard reading.  By enabling this option the user can see the
+progress."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-show-external-clipboard-send-progress t
+  "Show progress when writing data to external clipboard helper program.
+This is useful when the clipboard data is very large.  Without this
+option there might be no visual indication about the (in)completion
+of clipboard writing.  By enabling this option the user can see the
+progress."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-external-clipboard-coding-system 'utf-8 ;; 'buffer
+  "Customized coding system for external clipboard, default UTF-8.
+When set to 'buffer, it will apply current `buffer-file-coding-system'.
+This sounds safe but actually it might still cause issues.  For example,
+when current buffer is of coding system `utf-8-with-signature-unix'.
+When copy and paste strings it sometimes will insert BOM (byte order
+mark) into the beginning of the pasted text.
+
+Set this variable to any other fixed coding system symbol like 'utf-16le
+is also possible, but might also lead to some unexpected result if the
+coding system does not match your buffer.  For a complete list of
+available coding system symbols, check the completion list (press
+\\[minibuffer-complete]) when running `set-buffer-file-coding-system'
+(\\[set-buffer-file-coding-system])"
+  :type  'symbol
+  :group 'brief)
+
+(defcustom brief-cygwin-use-clipboard-dev t
+  "When running under Cygwin use /dev/clipboard to speed things up.
+Forking a subprocess is expensive in Cygwin.  Running external helper
+could cause a lot of delay comparing to its virtual clipboard device."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-giveup-clipboard-backup-if-huge t
+  "Give up backing up original clipboard data if it's huge.
+Usually when brief is about to change external clipboard data it will
+backup its original data so that if user cancelled current operation
+it could restore clipboard.  However, the data size of current clipboard
+is not known so it's possible that we are backing up a very huge data.
+With this option enabled we can skip backing up to prevent Emacs waits
+long."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-giveup-clipboard-backup-timeout 1.5
+  "Timeout value to give up backing up clipboard data if it's huge.
+This works only if `brief-giveup-clipboard-backup-if-huge' is enabled.
+Note that there is no direct way to detect the size of current clipboard
+contents without first reading it in first.  Therefore we use a general
+timeout value instead."
+  :type  'number
+  :group 'brief)
+
+(defcustom brief-giveup-clipboard-backup-message t
+  "Show visual message if backup timeout reached and we're giving up backup.
+This works only if `brief-giveup-clipboard-backup-if-huge' is enabled."
+  :type  'boolean
+  :group 'brief)
+
+
+(defvar brief-xclipboard-args nil
+  "Brief internal variable for external Xselection helper.")
+;; format: (get-arg
+;;          set-arg
+;;          select-arg
+;;          primary clipboard secondary
+;;          (must-have-args-for-get...))
+
+(defvar brief-xclipboard-cmd nil
+  "Brief internal variable for external Xselection helper.")
+
+(defconst brief-in-favor-of-xsel-default nil
+  "Default value of the `brief-in-favor-of-xsel'.")
+
+(defun brief-xclipboard-cmd-search ()
+  "Search for external Xclipboard helper program.
+Find either 'xsel' or 'xclip', if both exists in favor of 'xsel' when
+`brief-in-favor-of-xsel' is non-nil.  If none-exists only Emacs
+internal Xselection functions will be used and terminal mode won't
+react to Xselection change.
+However, care need to be taken that in some Linux environment, using
+'xsel' sometimes produce some extra bytes when getting data from the
+Xclipboard."
+  (let* ((xsel  (executable-find "xsel"))
+         (xclip (executable-find "xclip"))
+         ;; Forward reference to brief-in-favor-of-xsel, if
+         ;; not yet defined, use its default
+         (xc    (if (or (and (boundp 'brief-in-favor-of-xsel)
+                             (eval 'brief-in-favor-of-xsel))
+                        brief-in-favor-of-xsel-default)
+                    (or xsel xclip)
+                  (or xclip xsel))))
+    (setq brief-xclipboard-cmd xc)
+    (cond
+     ((string= xc xsel)
+      (setq brief-xclipboard-args
+            '("-o"
+              "-i"
+              "-n" ;; nil
+              "-p"      "-b"        "-s"
+              nil)))
+     ((string= xc xclip)
+      (setq brief-xclipboard-args
+            '("-o"
+              nil
+              "-selection"
+              "primary" "clipboard" "secondary"
+              ("-l" " 1")))))))
+
+(defun brief-set:brief-in-favor-of-xsel (sym val)
+  "Reset `brief-xclipboard-cmd' and `brief-xclipboard-args' so that
+it won't stick on 'xclip'."
+  (set sym val)
+  ;; Reset and search again
+  (setq brief-xclipboard-cmd nil
+        brief-xclipboard-args nil)
+  (brief-xclipboard-cmd-search))
+
+(defcustom brief-in-favor-of-xsel brief-in-favor-of-xsel-default
+  "When both 'xclip' and 'xsel' exist, choose 'xsel'.
+This is an emperical value.  My original personal experiemnts shows
+that 'xsel' seems to respond faster than 'xclip'.  However, on Ubuntu
+18, the associated 'xsel' is buggy and tend to return extra garbage at
+the end of the pasted data, sigh.  Considering the wide acceptance of
+Ubuntu, this force me to set the default setting to use 'xclip'
+instead.
+For Ubuntu 18 users that would like to use 'xsel' and set this option
+as non-nil, please rebuild the 'xsel' from author's git repository:
+\"https://github.com/kfish/xsel.git\"; and checkout at least commit id
+\"9bfc13d\"."
+  :type  'boolean
+  :group 'brief
+  :set   'brief-set:brief-in-favor-of-xsel)
+
+;;
+;; Miscellaneous behavioral configurations
+;;
+
+(defcustom brief-shorter-bookmark-jump-key t
+  "Swap M-j with M-# key for simpler keystroke for bookmark jump.
+The original key combination of jumping to a bookmark is M-j followed
+by a digit key, while setting a bookmark is M-# (# is the digit key)
+which is a shorter key combination.  However, in real cases jumping
+bookmarks happens much more frequently than setting bookmarks,
+therefore a shorter key sequence is sometimes more desired.  Setting
+this flag non-NIL will achieve this goal."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-open-file-use-dialog-when-possible nil
+  "Use the file dialog box X window manager provided when possible."
+  :type  'boolean
+  :group 'brief)
+
+;; This option works only if `brief-open-file-use-dialog-when-possible' is t,
+;;  it also seems not working on some older GTK+ systems. But anyway,
+;;  it doesn't cause any problems to be either 't or 'nil.
+(defcustom brief-open-file-show-hidden-files t
+  "Show hidden files in the file dialog box."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-search-recenter-vertically t
+  "Recenter cursor vertically when doing search or replacement.
+By recentering the cursor, context above/below are shown."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-search-recenter-horizontally t
+  "Recenter cursor horizontally to the right when doing search or replacement.
+By recentering the cursor to the right, context left to the cursor
+are shown."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-group-undo-replacement t
+  "Group undos for search&replace in a (rectangle) region."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-search-fake-region-mark t ;nil
+  "Mark a fake region when doing search within it.
+If we use the same background color as other normal region, it looks
+as if our marked region is still there when cursor moved.  Normally
+marked region changed according to our cursor."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-fake-region-face 'region ; 'secondary-selection
+  "The face (color) of fake region when `brief-search-fake-region-mark' is t."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-after-search-hook nil
+  "Hook for user defined search behavior.
+This hook gets called after each brief search operation."
+  :type  'hook
+  :group 'brief)
+
+(defcustom brief-linecmd-respect-visual nil
+  "Set this to t if line commands must respect visual/truncation mode.
+Line-oriented commands like \"line deletion\" (\\[brief-delete-entire-line]), 
\"delete till end
+of line\" (\\[brief-delete-end-of-line]), \"copy line\" (\\[brief-copy-line]) 
and \"cut line\" (\\[brief-kill-line]),
+usually operate on the whole physical line regardless of current
+visual/truncation mode.  With this option enabled, it *will* operate
+only on the visual part of current line, *unless* that command is
+prefixed (\\[universal-argument]).  Similarly, when visual/truncation mode is 
turned on,
+prefixed (\\[universal-argument]) line commands *will* only operate on visual 
part of
+the line."
+  :type 'boolean
+  :group 'brief)
+
+(defcustom brief-skip-buffers '("TAGS")
+  "Define the buffer names that Brief don't want to switch to."
+  :type 'sexp
+  :group 'brief)
+
+(defcustom brief-apply-slowdown-factor  t
+  "Apply the calibrated slowdown factor to all related timeout values.
+Under a lot of circumstances the calibrated slowdown factor is too
+small.  However, it is not known that if there could be environments
+that make this slowdown factor too high and make Brief performance
+poor.  If that's the case, set this value to nil to prevent applying
+the slowdown factor."
+  :type  'boolean
+  :group 'brief)
+
+(defcustom brief-init-multi-cursor-cmd  t
+  "Initialize multiple-cursors package for Brief commands.
+If this option is set to NIL, when multiple-cursors mode is ON, user
+will need to choose if a command is to be executed for each cursor or
+just run-once for all cursors and multiple-cursors package will then
+register user's selection.  With this option set non-NIL, the choice
+of all Brief mode commands are set initially without the need of
+user's attention."
+  :type  'boolean
+  :group 'brief)
+
+;;
+;; End of customization variables
+;;
+
+(defun brief-slowdown-factor ()
+  "Get the calibrated slowdown factor or keep it as 1.0.
+If `brief-apply-slowdown-factor' is non-NIL, return the calibrated
+slowdown factor; otherwise, return 1.0."
+  (or (and brief-apply-slowdown-factor
+           brief-slowdown-factor)
+      1.0))
+
+;; The cut and paste routines are different between XEmacs and Emacs
+;; so we need to set up aliases for the functions.
+
+(defalias 'brief-set-clipboard
+  (if (fboundp 'clipboard-kill-ring-save)
+      'clipboard-kill-ring-save
+    'copy-primary-selection))
+
+(defalias 'brief-kill-region
+  (if (fboundp 'clipboard-kill-region)
+      'clipboard-kill-region
+    'kill-primary-selection))
+
+(defalias 'brief-yank-clipboard
+  (if (fboundp 'clipboard-yank)
+      'clipboard-yank
+    'yank-clipboard-selection))
+
+(defvar brief-last-search-action-forward 't)
+;;(defvar brief-query-replace-to-history nil)
+;;(defvar query-replace-from-history-variable nil)
+;;(defvar query-replace-to-history-variable nil)
+(defvar brief-last-query-replace-forward 't)
+
+(defvar brief-orig-query-replace-from-history-variable nil)
+(defvar brief-orig-query-replace-to-history-variable nil)
+(defvar brief-query-replace-from-history nil)
+(defvar brief-query-replace-to-history nil)
+;;(defvar c-basic-offset nil)
+(defvar brief-c-tabs-always-indent nil)
+;;(defvar brief-c-insert-tab-function nil)
+
+;; TODO: [2016-05-10 Tue] Should we distinguish the following two?
+;; Shouldn't we use the same one?
+(defvar brief-search-last nil)
+
+(defvar brief-query-replace-last nil)
+
+;;;;[2011-04-14 Thu 13:53] rem 1
+;;(defvar brief-global-case-fold-search nil) ;;;; default nil : case-sensitive
+(defvar brief-get-current-word nil)
+(defvar brief-search-history nil)
+
+;;
+;; Brief key commands
+;;
+
+(defun brief-buffer-list-window ()
+  "Display buffer list.
+If `ibuffer' package is loaded it will invoke `ibuffer', otherwise
+it calls `buffer-menu' instead."
+  (interactive)
+  ;; Doing calibration here won't work, the measured delay is very low here.
+  ;; (call-interactively 'brief-calibration)
+  (if (fboundp #'ibuffer-make-column-filename) ;; prefered buffer mode
+      (let ((search-str (ibuffer-make-column-filename (current-buffer) nil))
+            (pos -1))
+        (if (zerop (length search-str))
+            (setq search-str (buffer-name)))
+        (ibuffer nil)
+        (redisplay) ;; sometimes if we don't do this the texts in buffer won't 
be ready
+        (when search-str
+          (save-mark-and-excursion
+            (goto-char (point-min))
+            (ignore-errors
+              (setq pos (search-forward search-str))))
+          (when (/= pos -1)
+            (goto-char pos)
+            (beginning-of-line)
+            (recenter)))
+        ;; Sometimes the mark got activated, probably due to earlier marking
+        ;; operation in the buffer.
+        (deactivate-mark))
+    (call-interactively 'buffer-menu)))
+
+(defvar brief-latest-killed-buffer-info nil
+  "This variable records the info of the most recently killed file
+buffer.  If user accidentally killed a file buffer, it can be
+recovered accordingly.
+Information is a list of:
+
+  buffer file name
+  point
+  buffer-undo-list
+  major mode
+  current visual row
+  linum-mode (optional, only if linum-mode package is loaded)
+  nlinum-mode (optional, only if nlinum-mode package is loaded)
+  display-line-numbers-mode (optional, only if supported)
+  ;;TODO: font/fontsize/scaled-size/ruler-mode/user-defined-hook
+")
+
+(defun brief-kill-current-buffer ()
+  "Kill current buffer, or restore latest killed file buffer if prefixed.
+When prefix argument presents (\\[universal-argument]) it will try to restore 
the latest
+killed buffer if it's a file buffer, otherwise it warns the user and
+do nothing. For non-prefixed calls, it will invoke `kill-buffer' which
+usually in turn ask user to save the changes if current buffer was
+modified."
+  (interactive)
+  (if current-prefix-arg
+
+      ;; Restore latest killed buffer
+      (let* ((filename (pop brief-latest-killed-buffer-info))
+             (buf (and filename
+                       (find-file filename)))
+             (inhibit-message nil)
+             item)
+        (if (null filename)
+            (message "No killed file buffer to restore")
+          (if (null buf)
+              (progn
+                (setq brief-latest-killed-buffer-info nil)
+                (message "Fail restoring killed buffer %S" filename))
+            (with-current-buffer buf
+              (setq inhibit-message t)
+              ;; restore point position
+              (goto-char (pop brief-latest-killed-buffer-info))
+              ;; restore undo list
+              (setq buffer-undo-list (pop brief-latest-killed-buffer-info))
+              ;; restore major mode
+              (call-interactively (pop brief-latest-killed-buffer-info))
+              ;; restore cursor position relative to window
+              (and (setq item (pop brief-latest-killed-buffer-info))
+                   (fboundp #'undo-window-pos)
+                   (apply #'undo-window-pos item nil))
+              ;; restore `linum-mode' or `nlinum-mode' if packages loaded
+              (and (setq item (pop brief-latest-killed-buffer-info))
+                   (boundp 'linum-mode)
+                   ;; Use `call-interactively' instead of calling `linum-mode'
+                   ;; directly in case `linum-mode' package is not loaded
+                   (call-interactively 'linum-mode))
+              (and (setq item (pop brief-latest-killed-buffer-info))
+                   (boundp 'nlinum-mode)
+                   (call-interactively 'nlinum-mode))
+              (and (setq item (pop brief-latest-killed-buffer-info))
+                   (boundp 'display-line-numbers-mode)
+                   (call-interactively 'display-line-numbers-mode)))
+            (setq inhibit-message nil)
+            (message "Killed buffer %S restored" filename))))
+
+    ;; Save buffer info before killing it for later restoring it
+    (let ((latest-killed-buffer-info nil))
+      (when buffer-file-name
+        (setq latest-killed-buffer-info
+              (list major-mode
+                    buffer-undo-list
+                    (point)
+                    buffer-file-name))
+        (push (if (fboundp #'undo-window-pos)
+                  (brief-current-row-visual))
+              latest-killed-buffer-info)
+        ;; Run-time detection of `linum-mode', `nlinum-mode' and
+        ;; `display-line-numbers-mode'
+        (push (if (boundp 'linum-mode)
+                  linum-mode)
+              latest-killed-buffer-info)
+        (push (if (boundp 'nlinum-mode)
+                  nlinum-mode)
+             latest-killed-buffer-info)
+        (push (if (boundp 'display-line-numbers-mode)
+                  display-line-numbers-mode)
+              latest-killed-buffer-info)
+        (setq latest-killed-buffer-info
+              (nreverse latest-killed-buffer-info))
+        (message
+         "To restore killed buffer, prefix buffer kill command [C-u C--] to 
restore it."))
+      (kill-buffer (current-buffer))
+      (and latest-killed-buffer-info
+           (setq brief-latest-killed-buffer-info
+                 latest-killed-buffer-info)))))
+
+(defun brief-delete-region (start end)
+  "Delete texts without going into kill-ring or clipboard."
+  (delete-region start end))
+
+(defun brief-delete-char (count)
+  (delete-char count))
+
+(defun brief-forward-1-char-noerror ()
+  "Forward one char and ignore \"end-of-buffer\" error."
+  (ignore-errors
+      (forward-char 1))
+  (point))
+
+(defun brief-rectangle-mode (arg)
+  "Start marking rectangle region."
+  (interactive "p")
+  (cua-set-rectangle-mark))
+
+;; [2016-04-20 Wed] support multiple cursors
+(defun brief-multiple-cursor-in-action ()
+  "Check if we are currently running a command on a fake cursor."
+  (and (boundp 'mc--executing-command-for-fake-cursor)
+       mc--executing-command-for-fake-cursor))
+
+;; [2016-05-24 17:06:41 +0800] support multiple-cursors mode
+(defun brief-multiple-cursor-mode-is-on ()
+  "Check if we are currently in multiple-cursor mode.
+This check differs from `brief-multiple-cursor-in-action' since this
+function returns t no matter if we are currently at a real cursor or
+fake cursor."
+  (and (boundp 'multiple-cursors-mode)
+       multiple-cursors-mode))
+
+;; 06/01/2011 ins 5 for Emacs, use kill-whole-line.
+;; <2011-06-09 Thu 14:13> removed since it will enter kill-ring
+
+;; 07/03/2007 ins 3 for emacs
+;; (define-key brief-global-mode-map [(meta d)]
+;;   (lambda ()
+;;     (interactive)
+;;     (beginning-of-line) (kill-line)))
+
+(defun brief-find-file ()
+  "Use file dialog or minibuffer to open a file according to user's 
preference."
+  (interactive)
+  (if brief-open-file-use-dialog-when-possible
+      (let ((last-nonmenu-event '(t))
+            (use-dialog-box t)
+            (use-file-dialog t)
+            ;; This option seems not working on some old GTK+ systems
+            (x-gtk-show-hidden-files brief-open-file-show-hidden-files))
+        (find-file (read-file-name
+                    (format "Brief: open file in %S" default-directory)
+                    nil default-directory nil)))
+    (call-interactively 'find-file)))
+
+(defun brief-current-filename ()
+  "Dispaly file name of current buffer if it has one.
+When prefixed (\\[universal-argument]) it will put current buffer file name 
into clipboard."
+  (interactive)
+  (if (not buffer-file-name)
+      (message "Current buffer does not have a file name")
+    (if (null current-prefix-arg)
+        (message "%S" buffer-file-name)
+      (brief-copy-region-into-clipboard buffer-file-name)
+      (message "%S copied into clipboard"
+               buffer-file-name))))
+
+(defun brief-version (&optional arg)
+  "Version number of the Brief emulator package.
+If ARG is non-NIL, insert results at point."
+  (interactive "P")
+  (let ((foo (concat "Brief version " brief-version)))
+    (if arg
+        (insert (message foo))
+      (message foo))))
+
+;; For Emacs in case mouse-track-rectangle-p not defined
+
+;; <2011-06-02 Thu 17:03> ins func, derived from pc-mode.el
+(defun brief-set-mark-here-if-not-active ()
+  "Sets the mark at point if it is not active."
+  (if (not (brief-use-region))
+      ;;(set-mark (point))
+      (push-mark (point) t)))
+
+(defun brief-call-list-interactively (alist)
+  (if (not (equal alist nil))
+      (progn
+        (call-interactively (car alist))
+        (brief-call-list-interactively (cdr alist)))))
+
+(defun brief-call-mark-line-up-with-key (key)
+  (brief-call-list-interactively
+   (cons 'brief-mark-line-up (list (key-binding key)))))
+
+(defun brief-call-mark-line-down-with-key (key)
+  (brief-call-list-interactively
+   (cons 'brief-mark-line-down (list (key-binding key)))))
+
+;;
+;; Brief bookmarks
+;;
+
+(defcustom brief-bookmark-nearby 256
+  "Define the distance (chars) of two bookmarks that brief considered nearby."
+  :type 'number
+  :group 'brief)
+
+(defvar brief-inhibit-bookmark-try-switch-frame-window nil
+  "An internal flag to prevent bookmark jumps switching frame and window.")
+
+(defun brief-bookmark-try-switch-frame-window (bookmark)
+  "Try to find a window containing this bookmark then jump to the frame and 
win.
+If found, return 't; if not found, jump to the first frame/window
+containing the buffer and return symbol 'frame.  If no such buffer/
+window/frame exists, keep current frame/window and return NIL.
+
+  This can be used to advice all bookmark jumping functions. For
+example, add the following into .emacs:
+
+  (defun bookmark-jump-restoring-frame-window (bookmark &rest args)
+    (brief-bookmark-try-switch-frame-window bookmark))
+
+  (advice-add 'bookmark-jump
+              :before 'bookmark-jump-restoring-frame-window)
+  (advice-add 'bookmark-jump-other-window
+              :before 'bookmark-jump-restoring-frame-window)"
+
+  (unless brief-inhibit-bookmark-try-switch-frame-window
+    (let ((fname (ignore-errors ;; prevent non-existing bookmark error
+                   (bookmark-get-filename bookmark)))
+          bname ;; buffer name, no file (e.g. *scratch* buffer)
+          (currf (selected-frame))
+          (foundframe nil)
+          (foundwin nil)
+          (result nil)
+          bpos
+          buf bfname
+          tmp)
+
+      (and fname
+           (not (file-exists-p (file-truename fname)))
+           (setq bname
+                 (or (and (setq tmp
+                                (cdr (assoc
+                                      'buffer-name
+                                      (cdr (bookmark-get-bookmark bookmark)))))
+                          (stringp tmp)
+                          tmp)
+                     (and ;;(car
+                      ;; (last (car (bookmark-get-bookmark-record bookmark))))
+                      (listp (setq tmp
+                                   (bookmark-get-bookmark-record bookmark)))
+                      (setq tmp (car tmp))
+                      (listp (setq tmp (last tmp)))
+                      (car tmp)))
+                 fname nil))
+      (when (or fname bname)
+        (catch 'found
+          (dolist (f (cons currf ;; let current frame be the 1st frame to test
+                           (remove currf (frame-list))))
+            (select-frame f)
+            (dolist (w (window-list))
+              (and (setq buf (window-buffer w))
+                   (or
+                    (and fname ;; bookmark is in a filed buffer
+                         (setq bfname (buffer-file-name buf))
+                         (file-equal-p bfname fname))
+                    (and bname ;; bookmark is in a buffer with no file
+                         (string= bname (buffer-name buf))))
+                   ;; Record the first found frame/win
+                   (if foundframe
+                       t
+                     (setq foundframe f
+                           foundwin w))
+                   ;; Check if bookmark position is already
+                   ;; displayed in the window
+                   (ignore-errors
+                     (setq bpos (bookmark-get-position bookmark))
+                     (when (and (>= bpos (window-start w))
+                                (<= bpos (window-end w t)))
+                       (select-frame-set-input-focus f)
+                       (raise-frame f)
+                       (select-window w)
+                       (throw 'found (setq result t)))))))
+          ;; Did not found a window containing bookmark, jump
+          ;; to the first window containing the buffer if there is
+          (if foundwin
+              (ignore-errors
+                (select-frame-set-input-focus foundframe)
+                (raise-frame foundframe)
+                (select-window foundwin)
+                (setq result 'frame))
+            ;; Not found, back to original frame
+            (select-frame currf))))
+
+      result)))
+
+(defun brief-bookmark-do-jump (bookmark)
+  "Jump to Brief bookmark #0~#9.  ARG is a char within '0'~'9'."
+  (setq bookmark (char-to-string bookmark))
+  ;; If not prefixed, try to switch to a existing window that continaing the
+  ;; bookmarked file/buffer in order to keep current window/buffer intact.
+  (and (boundp 'bookmarks-already-loaded)
+       (fboundp 'bookmark-maybe-load-default-file)
+       (or bookmarks-already-loaded (bookmark-maybe-load-default-file)))
+
+  ;; Prefixed jump (C-u) won't switch frame/buffer.
+  (let ((brief-inhibit-bookmark-try-switch-frame-window current-prefix-arg))
+    (brief-bookmark-try-switch-frame-window bookmark)
+
+    (condition-case nil
+        (progn
+          (bookmark-jump-wrapper bookmark
+                                 'switch-to-buffer
+                                 (brief-use-region))
+          (if (fboundp 'bmkp-light-bookmark)
+              (bmkp-light-bookmark (bookmark-get-bookmark bookmark)))
+          (message "Jump to bookmark %S" bookmark))
+      (error (message (format "Bookmark %S not existed." bookmark))))))
+
+(defun brief-bookmark-do-set (arg) ;; 06/02/'08 ins 1 func
+  "Set Brief bookmark #0~#9.  ARG is a char within '0'~'9'."
+  (if (minibufferp)
+      (error "Can't set bookmark in a minibuffer")
+    (setq arg (char-to-string arg))
+    (let* ((argn  (string-to-number arg))
+           (reg   (+ #36rBRIEF argn)) ;; make it unique
+           (temp  (+ #36rTEMP argn))
+           (temp2 (+ #36rTEMP2 argn))
+           (orig  (get-register reg))
+           mark1 mark2
+           bmk)
+      (ignore-errors
+        ;; Try to save current bookmark into REG register
+        (save-mark-and-excursion
+          (save-window-excursion
+            (point-to-register temp)
+            (setq mark1 (or (and current-prefix-arg
+                                 orig
+                                 (jump-to-register reg))
+                            (get-register temp)))
+            (setq mark2 (ignore-errors
+                          (bookmark-jump arg)
+                          (point-to-register temp2)))
+            (unless
+                ;; (equal marker1 marker2)  ;; Do not overwrite REG we're
+                                            ;;; bookmarking the same position
+                (and (markerp mark1) ;; Do not overwrite REG if two bookmarks
+                                     ;;; are nearby, in case we
+                     (markerp mark2) ;; accidentally moved a little bit left,
+                                     ;;; right,up or down and mark.
+                     (eq (marker-buffer mark1) (marker-buffer mark2))
+                     (<= (abs (- (marker-position mark1)
+                                 (marker-position mark2)))
+                         brief-bookmark-nearby))
+              (set-register reg (get-register temp2))))))
+
+      ;; If prefixed by C-u, restore bookmark.
+      ;; This help restoring the original bookmark.
+      (if (and current-prefix-arg orig)
+          (ignore-errors
+            (set-register temp orig)
+            (save-mark-and-excursion
+              (save-window-excursion
+                (jump-to-register temp 't)
+                (bookmark-delete arg)
+                (bookmark-set arg)))
+            (message (concat "Backup bookmark #" arg " restored")))
+
+        (bookmark-delete arg)
+        (bookmark-set arg)
+        (setq bmk (bookmark-get-bookmark arg))
+        ;; Support `bookmark+-1' from EmacsWiki
+        (and (fboundp 'bmkp-make-bookmark-savable)
+             (bmkp-make-bookmark-savable bmk))
+        (and (fboundp 'bmkp-light-bookmark)
+             (bmkp-light-bookmark bmk))
+        (message (concat "Brief bookmark #" arg " set")))
+
+      ;; Now really jump to the bookmark
+      (let ((current-prefix-arg nil))
+        (brief-bookmark-do-jump (string-to-char arg))))))
+
+
+(defun brief-bookmark-jump-set (bookmark) ;; 06/02/'08 ins 1 func
+  "Jump to bookmark 0~9 if `brief-shorter-bookmark-jump-key' is t.
+Otherwise, set the bookmark at cursor.
+When prefixed with (\\[universal-argument]), it tries to restore the previous 
bookmark
+if there is one.  This is useful when user miss-typed a bookmark-set
+command somewhere but forgot where it originally was.  When the
+bookmark is successfully restored, again restoring the bookmark will
+bring it back to its new location (where user might just miss-typed)."
+    (if brief-shorter-bookmark-jump-key
+        (brief-bookmark-do-jump bookmark)
+      (brief-bookmark-do-set bookmark)))
+
+(defun brief-bookmark-set-jump (bookmark)
+  "Set bookmark 0-9 if `brief-shorter-bookmark-jump-key' is t (default).
+Otherwise, jump to it.
+When prefixed it won't switch current frame or buffer."
+  (interactive (list (read-char-choice
+                      (concat
+                       (if brief-shorter-bookmark-jump-key
+                           (if current-prefix-arg "Try restoring" "Set")
+                         "Jump to")
+                       " bookmark 0-9 ")
+                      '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?\r ?\e))))
+
+  (if (or (= bookmark ?\r)  ;; press return
+          (= bookmark ?\e)) ;; press escape
+      (keyboard-quit)
+    (if brief-shorter-bookmark-jump-key
+        (brief-bookmark-do-set bookmark)
+      (brief-bookmark-do-jump bookmark))))
+
+(defun brief-bookmark-jump-set-0 ()
+  "Jump/set bookmark '0'."
+  (interactive)
+  (brief-bookmark-jump-set ?0))
+
+(defun brief-bookmark-jump-set-1 ()
+  "Jump/set bookmark '1'."
+  (interactive)
+  (brief-bookmark-jump-set ?1))
+
+(defun brief-bookmark-jump-set-2 ()
+  "Jump/set bookmark '2'."
+  (interactive)
+  (brief-bookmark-jump-set ?2))
+
+(defun brief-bookmark-jump-set-3 ()
+  "Jump/set bookmark '3'."
+  (interactive)
+  (brief-bookmark-jump-set ?3))
+
+(defun brief-bookmark-jump-set-4 ()
+  "Jump/set bookmark '4'."
+  (interactive)
+  (brief-bookmark-jump-set ?4))
+
+(defun brief-bookmark-jump-set-5 ()
+  "Jump/set bookmark '5'."
+  (interactive)
+  (brief-bookmark-jump-set ?5))
+
+(defun brief-bookmark-jump-set-6 ()
+  "Jump/set bookmark '6'."
+  (interactive)
+  (brief-bookmark-jump-set ?6))
+
+(defun brief-bookmark-jump-set-7 ()
+  "Jump/set bookmark '7'."
+  (interactive)
+  (brief-bookmark-jump-set ?7))
+
+(defun brief-bookmark-jump-set-8 ()
+  "Jump/set bookmark '8'."
+  (interactive)
+  (brief-bookmark-jump-set ?8))
+
+(defun brief-bookmark-jump-set-9 ()
+  "Jump/set bookmark '9'."
+  (interactive)
+  (brief-bookmark-jump-set ?9))
+
+;;
+;; Window locating functions
+;;
+(defun brief-switch-to-window (window)
+  "Switch to the specified window in the current frame."
+  (interactive)
+  (if window
+      (let ((top (selected-window))
+            (curr (next-window))
+            (count 1))
+        (catch 'break
+          ;; Repeat no more than the number of exinsting windows
+          (dolist (l (window-list))
+            (if (eq window curr)
+                (throw 'break nil))
+            (incf count 1)
+            (setf curr (next-window curr))))
+        (if (eq window curr)
+            (other-window count)))))
+
+;; Window:
+;; (x0,y0)*------------+
+;;        |            |
+;;        |        c   |  c:cursor position
+;;        |            |
+;;        +------------* (x1,y1)
+
+(defun brief-is-crlf (c)
+  (or (= c #x0a)   ;; end of line 'LF'
+      (= c #x0d))) ;; end of line 'CR'
+
+;;(defun brief-text-scaled-width (width)
+;;  "Compute scaled text width according to current font scaling.
+;;Convert a width of char units into a text-scaled char width units,
+;;Ex. `window-hscroll'. The return value is rounded up to the closest
+;;integer."
+;;  (let ((def (default-font-width)))
+;;    (/ (+ (* width (frame-char-width))
+;;          (lsh def -1))
+;;       def)))
+
+;; No need to round up because the remainder of the division means the 
character
+;; is still partially displayed, therefore we can't consider hscroll scrolled 
to
+;; that character, but its previous one.
+;; A 'truncation' instead of 'round up' is more correct.
+(defun brief-text-scaled-width (width)
+  "Compute scaled text width according to current font scaling.
+Convert a width of char units into a text-scaled char width units,
+Ex. `window-hscroll'."
+  (if (fboundp #'default-font-width)
+      (/ (* width (frame-char-width)) (default-font-width))
+    ;; For Emacs version<=24. A not exact value but close to.
+    (round (/ width
+              (or (and (boundp 'text-scale-mode-remapping)
+                       (caddr text-scale-mode-remapping))
+                  1)))))
+
+(defun brief-text-unscaled-width (width)
+  "Reverse operation of `brief-text-scaled-width'.
+Convert a width of text-scaled char unit back to units of
+`frame-char-width'."
+  (if (fboundp #'default-font-width)
+      (/ (* width (default-font-width)) (frame-char-width))
+    ;; For Emacs version<=24. A not exact value but close to.
+    (round (* width
+              (or (and (boundp 'text-scale-mode-remapping)
+                       (caddr text-scale-mode-remapping))
+                  1)))))
+
+(defun brief-text-scaled-char-width ()
+  "Text scaled char width."
+  (if (fboundp #'default-font-width)
+      (default-font-width)
+    (round (* (frame-char-width)
+              (or (and (boundp 'text-scale-mode-remapping)
+                       (caddr text-scale-mode-remapping))
+                  1)))))
+
+(defun brief-text-scaled-char-height ()
+  "Text scaled char height."
+  (if (fboundp #'default-font-height)
+      (default-font-height)
+    (round (* (frame-char-height)
+              (or (and (boundp 'text-scale-mode-remapping)
+                       (caddr text-scale-mode-remapping))
+                  1)))))
+
+(defun brief-text-unscaled-current-column ()
+  "Non-text-scaled version of `current-column'."
+  (brief-text-unscaled-width (current-column)))
+
+(defun brief-current-column-visual () ;; base:0
+  "Compute the relative column number of cursor for current window.
+Supports all 3 modes: line truncation, line wrapping and visual line
+mode, as well as hidden texts."
+  (save-mark-and-excursion
+    (let* ((p       (point))
+           (c       (following-char))
+           ;; Notice that we must use `current-column' instead of `point' here,
+           ;; otherwise abbreviated texts (like the hyperlink texts in 
org-mode)
+           ;; will have incorrect value
+           (currcol (current-column))
+           (begcol  (progn (beginning-of-visual-line) (current-column)))
+           ;; [2017-04-19 Wed] `window-hscroll' not working well on
+           ;; `text-scale-mode', also does `ruler-mode' (tested Emacs 
"25.1.50.16").
+           ;; This is a workaround but still not able to calculate the
+           ;; *exact* hscroll value.
+           ;;(text-scale-mode-amount 0) ;; try to temporarily disable
+           ;;                           ;; `text-scale-mode', no use
+           (hscroll
+            ;;(or (and (string= emacs-version "25.1.50.16") ; also emacs 25.2.2
+            ;;(round (/ (window-hscroll) ;; Not exact [2017-05-23 Tue]
+            ;;          (or (and (boundp 'text-scale-mode-remapping)
+            ;;                   (caddr text-scale-mode-remapping))
+            ;;              1)))
+                    (brief-text-scaled-width (window-hscroll)))
+           (x       (- currcol begcol hscroll))) ;; hscroll will be nonzero
+                                                 ;;; only if in truncation mode
+      (if (not (brief-is-crlf c))
+          (if (not (minibufferp))
+              x
+            ;; Minibuffer usually contain a prefix string, count it in
+            (if (/= begcol ;; not in the 1st minibuffer visual line?
+                   (progn
+                     (beginning-of-line) (current-column)))
+                x
+              (+ x begcol)))
+        ;; It's possible that we "were" at the end of abbreviated texts (like
+        ;; the '...' in compressed org mode)
+        (end-of-line) ;;; `end-of-visual-line' will bypass the trailing '...'
+                      ;;; so we try `end-of-line' first
+        (if (= p (point))
+            x  ;; We "were" at the left side of '...', so do we are "now",
+               ;; so just return it
+          ;; We "were" at the right side of '...', must be at 
`end-of-visual-line'
+          ;;(if (/= p (progn (end-of-visual-line) (point)))
+          ;;    ;; we 'were' neither at `end-of-line' nor at
+          ;;    ;; `end-of-visual-line', where could we be?
+          ;;    (error "Assertion failed: Unexpected case!!"))
+          (+ 3 (- (current-column) ;; We "are" now at `end-of-line'
+                                  ;;; since '...' take 3 characters
+                  begcol hscroll)))))))
+
+(defun brief-move-to-column (arg)
+  (if (and (= 3 (- arg (move-to-column arg))) ;; (length "...") = 3
+           (brief-is-crlf (following-char)))
+      (let ((p1 (point)))
+        (end-of-visual-line) ;; We're now at here
+        (if (not (brief-is-crlf (following-char)))
+            (goto-char p1)))))
+
+;;
+;; Brief Fast Line/Row Counting and relative window position calculation
+;;
+
+(defun brief-count-physical-lines (start end)
+  ;; Modified from `count-lines' of simple.el.
+  ;; It's different from `count-lines' as it will return 0 if both START and 
END
+  ;; are at the same line; `count-lines' will return 1 on such cases.
+  ;; [2017-11-23 17:56:33 +0800]
+  ;; Notice we can't use `count-lines' directly here since it sometimes 
returns 1
+  ;; more than expected, we have to search if there is really an EOL there.
+  "Return number of lines between START and END.
+START point is included while END point is excluded. Thus when
+START=END it always return 0.  This function returns the number of
+newlines between them.
+
+Counting UNIX style EOL 'LF' (line-feed) when using unix encoding;
+counting MAC style EOL 'CR' (carrage-return) when using mac encoding;
+counting DOS style EOL 'CRLF' when using DOS encoding."
+  (save-mark-and-excursion
+    (save-restriction
+      (let* ((done 0)
+             (encoding (symbol-name buffer-file-coding-system))
+             ;; default unix encoding
+             (eol "\n"))
+        (if (string-match "-dos$" encoding) ;; dos encoding
+            (setq eol "\r\n")
+          (if (string-match "-mac$" encoding) ;; mac encoding
+              (setq eol "\r")))
+        (narrow-to-region start end)
+        (goto-char (point-min))
+        (if (eq selective-display t)
+            (save-match-data
+              ;; sometimes a lot of ^M are in a text file so don't include them
+              (while (search-forward eol nil t 64) ; was re-search-forward 
"[\n\C-m]"
+                (setq done (+ 64 done)))
+              (while (search-forward eol nil t 1)
+                (incf done))
+              done)
+          (setq done
+                (- (buffer-size) (forward-line (buffer-size))))
+          (if (not (bolp))
+              (1- done)
+            done))))))
+
+(defconst brief-flcbs 32768 ; 65536
+  "Fast line counting block size (flcbs).")
+
+;; Each item in this cache list denotes line numbers within this [start,end) 
block
+;; (including START, excluding END)
+(defvar-local brief-fast-line-number-list nil
+  "A list (cache) to store number of lines within each `brief-flcbs' chars 
block.")
+
+;;(defun brief-fast-line-number-at-pos (&optional pos)
+;;  "Much faster version for replacing `line-number-at-pos'.
+;;This function will also update cache `brief-fast-line-number-list'."
+;;  ;; replace `line-number-at-pos'
+;;  (let* ((p (or pos (point)))
+;;         (q (/ p brief-flcbs))
+;;         (r (% p brief-flcbs))
+;;         (s (min (length brief-fast-line-number-list)
+;;                 q))
+;;         (l brief-fast-line-number-list)
+;;         (lines 0))
+;;    (cl-loop for i from 0 to (1- s) do
+;;             (setq lines (+ lines (car l)))
+;;             (setq l (cdr l)))
+;;    (setq lines (+ lines (brief-count-physical-lines (1+ (* brief-flcbs s)) 
p)))
+;;    ;; Append into `brief-fast-line-number-list'
+;;    (when (< (length brief-fast-line-number-list) q)
+;;      (setq brief-fast-line-number-list (nreverse 
brief-fast-line-number-list))
+;;      (cl-loop for i from (1+ (* brief-flcbs s)) to p by brief-flcbs do
+;;               (when (<= (+ i brief-flcbs -1) (point-max))
+;;                 (push (brief-count-physical-lines i (+ i brief-flcbs -1))
+;;                       ;; [start,end), not including end point
+;;                       brief-fast-line-number-list)))
+;;      (setq brief-fast-line-number-list (nreverse 
brief-fast-line-number-list)))
+;;    (1+ lines))) ; base 1
+
+(defun brief-fast-line-number-at-pos (&optional pos)
+  "Much faster version for replacing `line-number-at-pos'.
+This function will also update cache `brief-fast-line-number-list'."
+  ;; replace `line-number-at-pos'
+  (let* ((p (or pos (point)))            ;; pos
+         (l brief-fast-line-number-list) ;; cache list
+         (lines 0)                       ;; line number
+         (rev nil)                       ;; reversed?
+         (c 1)                           ;; curr line-counted pos
+         i                               ;; item/index
+         (n brief-flcbs))                ;; next
+    ;; Use as many cached line numbers as possible
+    (while (and (<= n p) ;; pos not reached yet
+                l) ;; list not exhausted
+      (setq lines (+ lines (car l)) ;; accumulate cached line numbers
+            l     (cdr l)
+            c     n
+            n     (+ n brief-flcbs)))
+    ;; Either cache exhausted or p reached/passed
+    ;;  * cache exhausted: l = nil, which means n <= p still true
+    ;;  * pos reached: n > p, l could be either nil or not
+    (if (setq rev (<= n p))
+        ;; Cache exhausted, preparing appending items into cache.
+        ;; In order to prevent `append', reverse the list and pushing
+        (setq brief-fast-line-number-list
+              (nreverse brief-fast-line-number-list)))
+    ;; Push into reversed `brief-fast-line-number-list' if cache miss
+    (while (<= n p)
+      (setq i     (brief-count-physical-lines c n) ;; [c,n)
+            lines (+ lines i)                      ;;   [c,n)
+            c     n                                ;;     [c,n)
+            n     (+ n brief-flcbs))
+      (push i     brief-fast-line-number-list))
+    (if rev
+        (setq brief-fast-line-number-list
+              (nreverse brief-fast-line-number-list)))
+    ;; Calculate the remaining lines within a `brief-flcbs', base 1
+    (if (< c p)
+        (+ 1 lines (brief-count-physical-lines c p)) ;; [c,p)
+      (1+ lines))))
+
+(defun brief-trim-fast-line-number-list (beg end)
+  "Trim off cached line number counting list.
+Any text change invalidates the list from the point of editing.
+This save us the time to change line numbers for all the cached
+blocks after the editing point.  This function is meant to be
+placed in `before-change-functions' so we try to finish it as
+soon as possible in order not to cause any delay when editing."
+
+  ;;(assert (>= beg end))
+
+  (let ((len (safe-length brief-fast-line-number-list))
+        (q   (/ (min beg end) brief-flcbs)))
+    (when (> len q)
+      (setq brief-fast-line-number-list
+            (nbutlast brief-fast-line-number-list (- len q)))))
+  t)
+
+;;(add-hook 'before-change-functions 'brief-trim-fast-line-number-list)
+
+(defun brief-fast-count-physical-lines (start end)
+  "Return number of lines between START and END.
+This is the number of newlines between them."
+  ;;    |<-brief-flcbs->|<-brief-flcbs->|         |<-brief-flcbs->|
+  ;; ...|---------------|-----s---------|--...----|------e--------|---...
+  ;;                          ^         sq        eq     ^
+  (let* ((s (min start end))
+         (e (max start end))
+         (sq (/ (+ s brief-flcbs -1) brief-flcbs)) ;; sq always >= 1
+         (eq (/ e brief-flcbs))
+         (c  (- eq sq))
+         (lines 1)
+         ;;verify
+         l)
+    (if (>= sq eq)
+        (brief-count-physical-lines s e)
+      (if (< (safe-length brief-fast-line-number-list) eq)
+          (- (brief-fast-line-number-at-pos e)
+             (brief-fast-line-number-at-pos (max (1- s) 1)))
+        (setq lines (+ (brief-count-physical-lines s (max (1- (* sq 
brief-flcbs))
+                                                          1))
+                       (brief-count-physical-lines (* eq brief-flcbs) e))
+
+              l (last brief-fast-line-number-list
+                      (- (safe-length brief-fast-line-number-list) sq)))
+        ;;(cl-loop for i from sq to (1- eq) by 1 do
+        ;;       (setq lines (+ lines (car l))
+        ;;             l (cdr l)))
+        (while (> c 0)
+          (decf c)
+          (setq lines (+ lines (car l))
+                l (cdr l)))
+        ;;;; Verification
+        ;;(setq verify (- (brief-fast-line-number-at-pos e)
+        ;;                (brief-fast-line-number-at-pos (max (1- s) 1))))
+        ;;(when (/= lines verify)
+        ;;  (message "error %d /= %d" lines verify)
+        ;;  (setq lines verify))
+        lines))))
+
+;;(defun brief-fast-line-number-at-pos (&optional pos)
+;;  "Much faster version for replacing `line-number-at-pos'."
+;;  (1+ (brief-fast-count-physical-lines 1 (or pos (point))))) ; base 1
+
+(defun brief-current-row-visual () ;; base:0
+  "Compute the relative row number of cursor for current window.
+Supports all 3 modes: line truncation, line wrapping and visual line mode."
+  (save-mark-and-excursion
+    (let* ((point0 (point))
+           ;;(line0 (line-number-at-pos))
+           ;;(linum-mode nil) ;; TODO: line number mode can make big org mode
+           ;;                 ;; file becomes very very slow, but it seems no
+           ;;                 ;; use to disable it this way
+           ;;line
+           (column0 (current-column))
+           (count 0)
+           (disable-local-cursor-tracking '(t)))
+      (goto-char (window-start))
+      (while (or (and (< (point) point0)
+                      ;;(< (setq line (line-number-at-pos)) line0)
+                      (> (brief-fast-count-physical-lines (point) point0) 0))
+
+                 (and (zerop (brief-fast-count-physical-lines point0 (point)))
+                      ;;(= line line0)
+                      (< (current-column) column0)))
+        ;;(ignore-errors
+        ;;  ;; When `eobp' is t, error occurs and do not increase count
+        ;;  ;; Using `forward-line' will fail on visual line mode. Only
+        ;;  ;; `next-line' can we move to the correct visual line, especially
+        ;;  ;; when we enabled line wrapping or visual line mode, but in some
+        ;;  ;; cases it will cause the cursor moving visible
+        ;;  (call-interactively 'next-line)
+        ;;  (setq count (1+ count))))
+        (vertical-motion 1)
+        (setq count (1+ count)))
+      (if (or (and (> (point) point0)
+                   (> (brief-fast-count-physical-lines point0 (point))
+                      0)) ;;(> line line0)
+              (and (zerop ;; (= line line0)
+                    (brief-fast-count-physical-lines point0 (point)))
+                   (> (current-column) column0)))
+          (1- count)
+        count))))
+
+(defun brief-window-pos-delta ()
+  "Get the Emacs on XWindow server internal error value of window position.
+This error happened when running Cygwin/X, VcXsrv in combination with
+some Emacs versions along with some font settings.  Not sure what
+combination could cause this but anyway it happens so do this
+calculation here.
+  Sometimes the (left,top) position reported by `window-inside-edges'
+is not the same as the window found by `window-at' (left,top),
+especially if customized fontsize is used. This function tries to find
+out the internal delta value of the current window."
+  (let* ((curr (selected-window))
+         (wie  (window-inside-edges))
+         (left (car wie))
+         (top  (cadr wie))
+         (xdelta 0)
+         (ydelta 0))
+    ;; Increment at most 3 on X and 2 on Y directions, at the size of a
+    ;; block cursor.
+    (and (not (eq curr (window-at (+ xdelta left) (+ ydelta top))))
+         (incf xdelta) ;; x+1
+         (not (eq curr (window-at (+ xdelta left) (+ ydelta top))))
+         (incf ydelta) ;; y+1
+         (not (eq curr (window-at (+ xdelta left) (+ ydelta top))))
+         (incf xdelta) ;; x+2 !
+         (not (eq curr (window-at (+ xdelta left) (+ ydelta top))))
+         (incf ydelta) ;; y+2 !
+         (not (eq curr (window-at (+ xdelta left) (+ ydelta top))))
+         (incf xdelta) ;; x+3 ?!
+         (not (eq curr (window-at (+ xdelta left) (+ ydelta top))))
+         (error ;; No, not trying y+3, it's an error
+          "Either this window system or this code has a big problem"))
+    (list xdelta ydelta)))
+
+(defun brief-window-cursor-xpos ()  ;; x position at cursor
+  "Get the relative column number of cursor position comparing to 
`window-start'."
+  (+ (car (window-inside-edges))
+     (brief-current-column-visual)
+     (car (brief-window-pos-delta))))
+
+(defun brief-window-cursor-xpos-pixel ()
+  "Get the relative X pixel coordinate of cursor comparing to `window-start'."
+  (+ (car (window-inside-pixel-edges))
+     (* (+ (brief-current-column-visual) (car (brief-window-pos-delta))
+           )
+        ;;(or (and (boundp 'text-scale-mode-remapping)
+        ;;         (caddr text-scale-mode-remapping))
+        ;;    1)
+        ;;(frame-char-width)
+        (brief-text-scaled-char-width))))
+
+(defun brief-window-cursor-ypos ()
+  "Get the relative line number of cursor position comparing to 
`window-start'."
+  (+ (cadr (window-inside-edges))
+     (brief-current-row-visual)
+     (cadr (brief-window-pos-delta))))
+
+(defun brief-window-cursor-ypos-pixel ()
+  "Get the relative Y pixel coordinate of cursor comparing to `window-start'."
+  (+ (cadr (window-inside-pixel-edges))
+     (* (+ (brief-current-row-visual) (cadr (brief-window-pos-delta))
+           )
+        ;;(or (and (boundp 'text-scale-mode-remapping)
+        ;;         (caddr text-scale-mode-remapping))
+        ;;    1)
+        ;;(frame-char-height)
+        (brief-text-scaled-char-height))))
+
+(defun brief-upside-window ()
+  "Get window located above current window.
+If more than one window there, choose the window located right above
+the cursor."
+  (let* ((edges (window-edges))
+         ;;(x0 (brief-window-cursor-xpos))
+         (x0 (round (/ (* 1.0 (brief-window-cursor-xpos-pixel))
+                       (frame-char-width)))) ; consider font rescaling
+         (y0 (cadr edges))
+         (curr (selected-window))
+         (win curr))
+    (while (and win (>= y0 0) (eq win curr))
+      (setq y0 (1- y0)
+            win (window-at x0 y0)))
+    win))
+
+(defun brief-downside-window ()
+  "Get window located below current window.
+If more than one window there, choose the window located right below
+the cursor."
+  (let* ((edges (window-edges))
+         ;;(x0 (brief-window-cursor-xpos))
+         (x0 (round (/ (* 1.0 (brief-window-cursor-xpos-pixel))
+                       (frame-char-width)))) ; consider font rescaling
+         (y1 (cadddr edges))
+         (curr (selected-window))
+         (win curr))
+    (while (and win (eq win curr))
+      (setq win (window-at x0 y1)
+            y1 (1+ y1)))
+    (if (eq win (minibuffer-window))
+        (and (> (minibuffer-depth) 0)
+             (minibuffer-window-active-p (minibuffer-window))
+             win)
+      win)))
+
+(defun brief-leftside-window ()
+  "Get window located left side of current window.
+If more than one window there, choose the window pointed leftward
+from cursor."
+  (let* ((edges (window-edges))
+         (x0 (car edges))
+         ;;(yy (brief-window-cursor-ypos))
+         (yy (round (/ (* 1.0 (brief-window-cursor-ypos-pixel))
+                       (frame-char-height)))) ; consider font scaling
+         (curr (selected-window))
+         (win curr))
+    (while (and win (>= x0 0) (eq win curr))
+      (setq win (window-at x0 yy)
+            ;; workaround for hidden lines like org-mode, but it's incorrect
+            ;; win (or win (window-at x0 y0))
+            x0 (1- x0)))
+    win))
+
+(defun brief-rightside-window ()
+  "Get window located right side of current window.
+If more than one window there, choose the window pointed rightward
+from cursor."
+  (let* ((edges (window-edges))
+         (x1 (caddr edges))
+         ;;(yy (brief-window-cursor-ypos))
+         (yy (round (/ (* 1.0 (brief-window-cursor-ypos-pixel))
+                       (frame-char-height)))) ; consider font scaling
+         (curr (selected-window))
+         (win curr))
+    (while (and win (eq win curr))
+      (setq win (window-at x1 yy)
+            ;; workaround for hidden lines like org-mode, but it's incorrect
+            ;; win (or win (window-at x1 y0))
+            x1 (1+ x1)))
+    win))
+
+(defun brief-switch-window-up ()
+  "Switch current window to the one above current cursor position."
+  (interactive)
+  (brief-switch-to-window (brief-upside-window)))
+
+(defun brief-switch-window-down ()
+  "Switch current window to the one below current cursor position."
+  (interactive)
+  (brief-switch-to-window (brief-downside-window)))
+
+(defun brief-switch-window-left ()
+  "Switch current window to the one left to current cursor position."
+  (interactive)
+  (brief-switch-to-window (brief-leftside-window)))
+
+(defun brief-switch-window-right ()
+  "Switch current window to the one right to current cursor position."
+  (interactive)
+  (brief-switch-to-window (brief-rightside-window)))
+
+(defun brief-split-window-up ()
+  "Split window vertically to be the upper neighbor of current window."
+  (interactive)
+  (split-window-vertically)
+  (other-window 1))
+
+(defun brief-split-window-left ()
+  "Split window horizontally to be the left neighbor of current window."
+  (interactive)
+  (split-window-horizontally)
+  (other-window 1))
+
+(defun brief-delete-window-up ()
+  (interactive)
+  (delete-window (brief-upside-window)))
+
+(defun brief-delete-window-down ()
+  (interactive)
+  (delete-window (brief-downside-window)))
+
+(defun brief-delete-window-left ()
+  (interactive)
+  (delete-window (brief-leftside-window)))
+
+(defun brief-delete-window-right ()
+  (interactive)
+  (delete-window (brief-rightside-window)))
+
+(defun brief-delete-current-window ()
+  (interactive)
+  (delete-window)
+  (other-window -1))
+
+;;
+;; Brief cursor commands
+;;
+
+(defun brief-forward-physical-line (arg)
+  "Move forward a physical line instead of visual line."
+  (let ((col (brief-current-column-visual)))
+    (forward-line arg)
+    (brief-move-to-column
+     (max col
+          (or (and (consp temporary-goal-column)
+                   (truncate
+                    (+ (car temporary-goal-column)
+                       (cdr temporary-goal-column))))
+              temporary-goal-column)))))
+
+(defun brief-previous-physical-line (arg)
+  "Move cursor vertically up (a) physical line(s)"
+  (interactive "^p")
+  (setq this-command 'previous-line)
+  (brief-forward-physical-line (- arg)))
+
+(defun brief-next-physical-line (arg)
+  "Move cursor vertically down (a) physical line(s)"
+  (interactive "^p")
+  (setq this-command 'next-line)
+  (brief-forward-physical-line arg))
+
+(defun brief-previous-line (arg)
+  "Move cursor vertically up (a) visual line(s).
+When prefixed with a number, it move up several visual lines.
+Negative prefix number move up several physical lines instead.  If the
+prefix is simply a \\[universal-argument], it move up one physical line."
+  (interactive "^p")
+  ;; In order to keep `temporary-goal-column' unchanged, we need to set
+  ;; current command as 'previous-line here. (Refer to `line-move-visual'.)
+  (setq this-command 'previous-line)
+  (if (brief-rectangle-active)
+      (call-interactively 'cua-resize-rectangle-up)
+    (if (equal current-prefix-arg '(4)) ;; only C-u without numbers
+          (brief-previous-physical-line 1)
+      (if (< arg 0)
+          (brief-forward-physical-line arg)
+        (call-interactively 'previous-line)))))
+
+(defun brief-next-line (arg)
+  "Move cursor vertically down (a) visual line(s).
+When prefixed with a number, it move down several visual lines.
+Negative prefix number move down several physical lines instead.
+If the prefix is simply a \\[universal-argument], it move down one physical 
line."
+  (interactive "^p")
+  ;; In order to keep `temporary-goal-column' unchanged, we need to set
+  ;; current command as 'next-line here. (Refer to `line-move-visual'.)
+  (setq this-command 'next-line)
+  (if (brief-rectangle-active)
+      (call-interactively 'cua-resize-rectangle-down)
+    (if (equal current-prefix-arg '(4)) ;; only C-u without numbers
+        (brief-next-physical-line 1)
+      (if (< arg 0)
+          (brief-forward-physical-line (- arg))
+        (call-interactively 'next-line)))))
+
+
+;;; Xselection Postponement:
+
+;; Postpone changing Xselection till keyboard is idle for a while.
+;;
+;; This prevents message flooding on some X server systems that runs an
+;; application broadcasting messages whenever clipboard changes.
+
+;; A sample environment is a remote Linux machine running X11 Emacs displayed 
on
+;; Xservers (VcXsrv, CygwinX, ... etc) running under Windows 10, with any of
+;; Microsoft Office running (eg. MS Outlook, which usually sit in the 
background
+;; for emails).
+;;
+;; With MS office application running, any change of the clipboard will cause
+;; MS office application to broadcast 'WM_MSO_BROADCASTCHANGE' messages.  If
+;; there are, say, 25 Xwindows on screen (for example, remote Emacs showing
+;; 25 frames as VcXsrv/CygwinX windows), this broadcasted message will flood
+;; into VcXsrv/CygwinX server message loop and cause problems.  Here are the
+;; details I find it the hard way, after a long investigateion (notice that
+;; Xserver here refers to Xservers running on MsWindows, say VcXsrv):
+;;
+;;   1. Usually a Emacs keyboard command is executed right after Xserver
+;;      received the 'WM_KEYDOWN' message(s) of that command.  This happens
+;;      *BEFORE* the 'WM_KEYUP' message(s) of that keyboard command.
+;;   2. If that Emacs keyboard command changes the clipboard, this will
+;;      immediately make MS office application fire 'WM_MSO_BROADCASTCHANGE'
+;;      message broadcasted into all existing Windows, including all windows
+;;      opened by Xserver.
+;;   3. Now these messages goes into Xserver's message loop, it usually take
+;;      a while to digest this message, this period sometimes exceed the
+;;      keyboard auto-repeat time period and therefore that Emacs keyboard
+;;      command start to repeat again and again.
+;;   4. These auto-repeated keyboard commands changes the clipboard again
+;;      and again and cause a lot more broadcasted messages and flood into the
+;;      message loop of Xserver, causing infinite loop.
+;;   5. The 'WM_KEYUP' message of that keyboard command thus never got a chance
+;;      to be processed and thus this keyboard command repeats forever.
+;;
+;; An example of this is the region marking commands.  In Brief mode we press
+;; [M-l] and '[up]/[down]'s to enlarge/shrink the marked region.  A common
+;; behavior of *NIX terminals and editors are that they copy the selection
+;; texts into clipboard in realtime as the selected texts area changes.  Emacs
+;; region marking also do the same.  Thus marking region initiates the above
+;; message flood.  The last up/down key will take effect and repeats forever.
+;; Each time the up/down key command ran it resized the region, changed the
+;; clipboard and make the flood grew bigger.  Eventually 'WM_KEYUP' message of
+;; that up/down key is postponed forever.  What we can see on the screen is the
+;; marked region grows bigger and bigger till the beginning/end of the edited
+;; file is reached.
+;;
+;; Since Emacs and Xserver are now not responding, the only ways to stop it
+;; are:
+;;  1. Wait till the beginning/end of file is reached.  However this could take
+;;     very long depend on the file size.
+;;  2. Terminate Emacs by force, by login into this Linux machine with another
+;;     machine and terminate it.
+;;  3. Close all MS office applications.
+;;
+;; Sometimes if we waited too long the message flood will grow so big that all
+;; CPUs runs in 100% and the host Windows system hangs (message queues of
+;; Xserver and all windows will grow and eat up system memory fast).  To make
+;; system respond again we need to unplug the network cable for a while (if
+;; Emacs is running on a remote machine) or even reboot the host Windows 
machine.
+
+;; To workaround this problem, we need to detect the KEY-UP message.  If system
+;; do commands only *after* key-up, we won't have this problem as the key won't
+;; be automatically repeated before all the messages in the message queue got
+;; digested.  Unfortunately there is no way to detect KEY-UP message in eLisp.
+;; Therefore, we need to emulate the key-up using idle timer.  When idle timer
+;; expires it means all keys are already up for a while.  The workaround 
provided
+;; here is that we postponed the copy of data into Xselection till a certain
+;; period of keyboard idle-time.
+
+;; However, without the exact detection of the KEY-UP, this problem is still
+;; potentially happening if the Xserver host machine is either too slow or too
+;; heavily loaded, while our idle time setting may still not be not long 
enough.
+;; For those systems we also provides another mean to workaround this: turn on
+;; the custom option `brief-debounce-keys-microsoft-office'.  It will debounce
+;; the key commands if they are happening too fast: `brief-copy-line',
+;; `brief-kill-line' and `brief-delete-entire-line'.
+
+
+
+;; [2017-01-13 16:39:37 +0800]
+;; Add mark-activation/deactivation hooks to prevent keep modifying Xselection
+;; on marking region.  Whatever make clipboard change will cause Microsoft
+;; office to broadcast WM_MSO_BROADCASTCHANGE to *ALL* openned windows which
+;; could flood X server if a lot of X windows are currently openned.  This even
+;; cause VcXsrv to drop important message like WM_KEYDOWN/WM_KEYUP and cause 
the
+;; region marking operation goes forever, until network disconnect or all MS
+;; Office applications closed.
+;; (this issue take me almost a week to track down, using Visual Studio Spy++).
+
+;; TODO 1: merge this hook operation with the
+;;         `brief-region-backup-clipboard-selection' hook function
+;; TODO 2: with this, there should be no need to disable clipboard backup
+;;         for multiple-cursor mode?
+(defvar-local brief-is-gui-set-selection-postponed nil)
+
+;;;;The following will produce error:
+;;;; apply: Wrong number of arguments:
+;;;; (lambda nil (setq brief-is-gui-set-selection-postponed t)), 3 [12 times]
+;;;;This should be an Emacs advice-add internal issue.
+;;;;
+;;(defun brief-postpone-gui-set-selection (orig-func &rest args)
+;;  (unless brief-is-gui-set-selection-postponed
+;;    (apply orig-func args)))
+;;
+;;(advice-add 'gui-set-selection :around #'brief-postpone-gui-set-selection)
+;;(advice-remove 'gui-set-selection #'brief-postpone-gui-set-selection)
+
+;;
+;; Use idle-timer to detect key-released, whenever key is pressed,
+;; idle-timer never runs
+;;
+(defvar-local brief-postpone-gui-selection-idle-timer  nil
+  "The per-buffer postponed `gui-selection' timer.")
+
+(defvar-local brief-postpone-idle-timer-buffer         nil
+  "This variable records in which buffer do we starts the idle timer.
+User might switch to another buffer before idle timer starts.  Therefore
+when idle timer starts it shouldn't do anything if buffer changes")
+
+(defvar brief-postpone-gui-selection-idle-period 0.4)
+
+(defun brief-cancel-postpone-gui-selection-timer ()
+  (brief-dbg-message "brief-cancel-postpone-gui-selection-timer")
+  (unless window-system
+    ;; We could have two frames with one frame in terminal mode while another
+    ;; in window-system, this prevents the window-system frame removed the
+    ;; terminal frame's hook, since `post-command-hook' is global.  Unless we
+    ;; can put it buffer-local but Emacs manual already says it's risky to put
+    ;; that as file-local so I wonder it might be risky as well to do that
+    ;; buffer-local.
+    ;; TODO: verify this, confirm `post-command-hook' risky as buffer-local.
+    (remove-hook 'post-command-hook
+                 #'brief-terminal-mode-activate-gui-selection-idle-timer))
+  (and brief-postpone-gui-selection-idle-timer
+       (cancel-timer brief-postpone-gui-selection-idle-timer))
+  (setq brief-postpone-gui-selection-idle-timer nil))
+
+;;
+;; Copy into clipboard after key-up, emulated by idle timer.
+;;
+
+(defvar-local brief-copy-to-clipboard-on-keyup-data nil
+  "Region/rectangle data to be copied to clipboard when all keys are 
released.")
+
+(defvar-local brief-keep-postpone-gui-selection-timer nil
+  "A flag to prevent timer killed by deactivating mark.
+This flag is used by `brief-copy-to-clipboard-on-keyup' and
+`brief-resume-gui-set-selection'")
+
+;; [2017-10-25 Wed] When debouncing is on, MS office is ON with lots of
+;; VcXsrv windows, 0.01 always debouncing, 0.05 often debouncing, 0.1 sometimes
+;; debouncing and 0.2 seems not. 0.15 rarely need debouncing but sometimes do.
+;; Hence we use a more conservative value 0.25 here.
+(defvar brief-postpone-copy-to-clipboard-idle-period 0.25
+  "Keyboard idle period for postponing copying data into clipboard.
+This emulates the 'key up' event. We copy things into clipboard only when
+keyboard is idle.")
+
+(defvar brief-postponed-mark-selection-copy-completed nil
+  "Brief internal info to identify if the previous clipboard copy was
+done.  If we try to do `brief-copy-line' (\\[brief-copy-line]) right after 
this we don't
+need to copy the whole clipboard again otherwise when clipboard data
+is huge it's just a waste of time.")
+
+(defun brief-copy-to-clipboard-on-keyup (&optional thetext)
+  "Postpone `brief-copy-region-into-clipboard' till key-up.
+The 'key-up' is actually emulated by running an idle timer."
+  (brief-dbg-message "enter brief-copy-to-clipboard-on-keyup")
+
+  (if (not brief-enable-postpone-selection)
+
+      ;; Don't wait till key-up (idle)
+      (brief-copy-region-into-clipboard (or thetext
+                                            (car kill-ring)
+                                            "")
+                                        'quitable)
+
+    ;; Wait till key-up (idle)
+    (unless (and brief-postponed-mark-selection-copy-completed
+                 (equal (list (region-beginning) (region-end))
+                        brief-postponed-mark-selection-copy-completed))
+      (setq brief-copy-to-clipboard-on-keyup-data
+            (or thetext
+                (car kill-ring)
+                ""))
+      (setq brief-keep-postpone-gui-selection-timer t)
+      ;; Run not too soon after key-up detected, otherwise MS office
+      ;; WM_MSO_BROADCASTCHANGE broadcat message will still cause problems.
+      (brief-activate-postpone-gui-selection-timer
+       brief-postpone-copy-to-clipboard-idle-period))
+
+    (setq brief-postponed-mark-selection-copy-completed nil))
+
+  (brief-dbg-message "leave brief-copy-to-clipboard-on-keyup"))
+
+(defvar brief-postponed-running nil)
+(defvar brief-is-external-interruptible nil)
+(defvar-local brief-postponed-clipboard-ran nil)
+(defvar-local brief-external-set-selection-interrupted nil)
+
+(defun brief-run-postponed-gui-set-selection ()
+  "The timer postponed gui-set-selection is run here."
+  ;; Emulate the X-window clipboard behavior that clipboard content is being 
set
+  ;; as the marked region grows/shrinks
+  (brief-dbg-message "enter brief-run-postponed-gui-set-selection")
+
+  ;; Postponed gui-set-selection ran, wait till next key-stroke (that will
+  ;; invoke `gui-set-selection' if we're marking a region) to activate it.
+  (brief-cancel-postpone-gui-selection-timer)
+
+  (setq brief-postponed-mark-selection-copy-completed nil)
+
+  (let ((brief-is-gui-set-selection-postponed nil) ;; prevent reenter
+        (brief-postponed-running t)
+        ;; By default we use 'PRIMARY only, and disable 'CLIPBOARD (For VcXsrv,
+        ;; the option "Clipboard may use PRIMARY selection" in its context menu
+        ;; need to be turned ON).  These values are used by `gui-select-text' 
and
+        ;; `cua-copy-region'.
+        (select-enable-primary   (and (not (brief-is-winnt))
+                                      brief-select-enable-primary))
+        (select-enable-clipboard (or (brief-is-winnt)
+                                     brief-select-enable-clipboard))
+        ;; Hide global `kill-ring' here otherwise `cua-copy-region' will
+        ;; insert the temp selection into kill-ring.
+        kill-ring
+        kill-ring-yank-pointer) ; also hide `kill-ring-yank-pointer'
+
+    (if (null brief-copy-to-clipboard-on-keyup-data)
+
+        ;; Postponed due to region marking
+        (if (not (brief-use-region))
+            ;; We are expecting user is marking a region here
+            (if (or
+                 ;; Just start marking `cua-set-mark' (C-space)
+                 (and (region-active-p)
+                      (eq (region-beginning) (region-end)))
+
+                 ;; `string-rectangle' in action, no need to copy clipboard.
+                 (and (minibufferp)
+                      (or (and (boundp 'rectangle--string-preview-state)
+                               rectangle--string-preview-state)
+                          (and (boundp 'rectangle--string-preview-window)
+                               rectangle--string-preview-window)))
+
+                 ;; User switch to another buffer before postponed timer 
starts.
+                 (not (eq (current-buffer) brief-postpone-idle-timer-buffer))
+
+                 ;; TODO: could there be other cases?
+                 ;; Note:
+                 ;;  Test ok: if user switch to menu bar before timer starts
+                 )
+
+                t ;; do nothing
+
+              ;; This should not happen, but sometimes it does.  According to
+              ;; the comments in `region-active-p':
+              ;;  > FIXME: Somehow we sometimes end up with mark-active non-nil
+              ;;  > but without the mark being set (e.g. bug#17324).  We really
+              ;;  > should fix that problem, but in the mean time, let's make
+              ;;  > sure we don't say the region is active when there's no 
mark.
+              ;; We probably having the same issue here so we fire a warning
+              ;; message here.
+              (message (concat
+                        "Brief: expecting marked region"
+                        (and (minibufferp)
+                             ;; There could be some other similar situation 
like
+                             ;; `string-rectangle' so we notify user about 
that.
+                             " (currently in minibuffer)"))))
+
+          ;; User is currently marking a region
+          (unless brief-postponed-clipboard-ran
+            ;; First run after mark activated?
+            (setq brief-postponed-clipboard-ran t)
+            ;; backup current clipboard since we're going to change it
+            (brief-backup-clipboard-selection))
+
+          (let ((brief-is-external-interruptible 'interruptible)
+                (regbeg (region-beginning))
+                (regend (region-end)))
+            ;; This function will invoke `gui-set-selection', then copy
+            ;; data into `kill-ring', later `brief-copy-region-into-clipboard'
+            ;; will use it.
+            ;;(call-interactively 'cua-copy-region) ;; allow rectangle
+            (cua-copy-region nil) ;; allow rectangle
+
+            ;; If we was using external clipboard set and got interrupted,
+            ;; there is no need to copy that again.
+            (unless brief-external-set-selection-interrupted
+              ;; The following will activate `gui-set-selection' function
+              ;; `gui-select-text' -> `gui-set-selection'.  In terminal mode if
+              ;; we don't set `brief-is-gui-set-selection-postponed' nil it 
will
+              ;; got postponed again.
+              (brief-copy-region-into-clipboard nil 'interruptible))
+
+            (unless brief-external-set-selection-interrupted
+              ;; Region completely copied into external selection, mark it.
+              (setq brief-postponed-mark-selection-copy-completed
+                    (list regbeg regend)))))
+
+      ;; Postponed due to clipboard copy command like `brief-copy-line' and
+      ;; `brief-kill-line'.  These commands should not be interrupted but can
+      ;; be forced quitting with C-g.
+      (condition-case err
+          (progn
+            ;; `brief-copy-region-into-clipboard' will invoke `gui-select-text'
+            ;; which checks if our text is identical with the previous one.  If
+            ;; yes it will not set selection to external clipboard.  However,
+            ;; When sharing clipboard with other editor (or other Emacs) the
+            ;; external clipboard might already changed but this Emacs is not
+            ;; going to know that.  If we are currently trying to copy again
+            ;; the same string to another editor we will fail.  Therefore the
+            ;; customized variable `brief-force-set-external-selection' decides
+            ;; if we're overwriting the external clipboard without comparing to
+            ;; our previous copy or not.
+            (when (and select-enable-primary
+                       brief-force-set-external-selection)
+              (setq gui--last-selected-text-primary nil))
+            (when (and select-enable-clipboard
+                       brief-force-set-external-selection)
+              (setq gui--last-selected-text-clipboard nil))
+
+            (brief-copy-region-into-clipboard
+             brief-copy-to-clipboard-on-keyup-data 'quitable)
+
+            (setq brief-copy-to-clipboard-on-keyup-data nil))
+
+        ;; If user quit, reset data or it will confuse our next run, then
+        ;; propagate the quit signal.
+        (quit (progn
+                (brief-dbg-message
+                 "User quit from brief-run-postponed-gui-set-selection")
+                (setq brief-copy-to-clipboard-on-keyup-data nil)
+                (signal 'quit nil)))
+
+        ;; Catch all other kinds of errors
+        (error (progn
+                 (setq brief-copy-to-clipboard-on-keyup-data nil)
+                 (error (or (and (stringp (cdr err))
+                                 (cdr err))
+                            (format "Error:%S" err))))))))
+
+  ;; In terminal mode `gui-set-selection' run only once at the 1st idle,
+  ;; we need to use pre/post-command-hook to activate idle timer again if
+  ;; key-stroke happens.
+  (when (and (not window-system)
+             brief-is-gui-set-selection-postponed)
+    (add-hook 'post-command-hook
+              #'brief-terminal-mode-activate-gui-selection-idle-timer))
+  (brief-dbg-message "leave brief-run-postponed-gui-set-selection"))
+
+(defun brief-activate-postpone-gui-selection-timer (&optional idle-period)
+  (setq idle-period
+        (or idle-period brief-postpone-gui-selection-idle-period))
+  ;; Instead of preventing creating multiple idle timers, we restart the timer
+  ;; to prevent continuous activation. Continuous activation means we're not
+  ;; idle for long enough.
+  (when brief-postpone-gui-selection-idle-timer
+    ;;(brief-cancel-postpone-gui-selection-timer)
+    (cancel-timer brief-postpone-gui-selection-idle-timer)
+    (setq brief-postpone-gui-selection-idle-timer nil))
+
+  (setq brief-postpone-gui-selection-idle-timer
+        ;; Notice that letting this timer auto-repeat itself is a bit dangerous
+        ;; if for some reason the deactivate-mark hook is not run (e.g. quit?)
+        ;; -- the timer function will keep repeating whenever idle occurs.
+        (run-with-idle-timer (* idle-period (brief-slowdown-factor))
+                             nil
+                             #'brief-run-postponed-gui-set-selection))
+
+  (setq brief-postpone-idle-timer-buffer (current-buffer))
+  ;; Region/mark changed, reset completion flag
+  (setq brief-postponed-mark-selection-copy-completed nil))
+
+(defun brief-terminal-mode-activate-gui-selection-idle-timer ()
+  ;; For emacsclient we could have two frames with one on window-system while
+  ;; the other on terminal, as `post-command-hook' is global for both frames
+  ;; we must remove the hook only if we're running in terminal mode.
+  (when (and (not window-system)
+             brief-is-gui-set-selection-postponed)
+    (brief-activate-postpone-gui-selection-timer)
+    (remove-hook 'post-command-hook
+                 #'brief-terminal-mode-activate-gui-selection-idle-timer))
+  t)
+
+(defun brief-enable-clipboard-postponement ()
+  (add-hook 'activate-mark-hook
+            'brief-postpone-gui-set-selection 't)
+  (add-hook 'deactivate-mark-hook
+            'brief-resume-gui-set-selection))
+
+(defun brief-disable-clipboard-postponement ()
+  (remove-hook 'activate-mark-hook
+               'brief-postpone-gui-set-selection)
+  (remove-hook 'deactivate-mark-hook
+               'brief-resume-gui-set-selection)
+  ;; In case any terminal mode frame in work
+  (remove-hook 'post-command-hook
+               'brief-terminal-mode-activate-gui-selection-idle-timer))
+
+;;
+;; External Xselection selection get/set helper using programs like 'xsel' or
+;; 'xclip'.  This also allows terminal mode programs running under X able to
+;; interact with Xselection.  These functions are mainly for *NIX systems;
+;; native win32/win64 systems cannot use them.
+;;
+;; 'xsel' is in favor when 'xsel' and 'xclip' are both available.  Accodring to
+;; my personal experience 'xsel' responds faster.  However, the default value
+;; was set to 'xclip' due to Ubuntu 18.  Check the documentation string for the
+;; custom variable `brief-in-favor-of-xsel'.
+;;
+;; The implemetation is both non-blocking and quittable.  When huge clipboard
+;; data is transfering between Emacs and Xselection, it could take very long
+;; using Emacs native functions which is not even interruptible or quit-able
+;; (C-g).  The native implementation always copy the full content of selection
+;; into Xselection whenever region size changed, this is also very inefficient
+;; and slow when huge texts are selected.  In this implementation when region
+;; size changed the previous unfinished Emacs selection <-> Xselection
+;; transferring operation will be interrupted and terminated so it's more
+;; efficient.  User won't be blocked and waiting there without any visible
+;; response and feel like Emacs hangs.
+
+(defun brief-xclipboard-get-type-arg (type)
+  (or (and (eq (or type 'PRIMARY) 'PRIMARY)
+           (nth 3 brief-xclipboard-args))
+      (and (eq type 'CLIPBOARD)
+           (nth 4 brief-xclipboard-args))
+      (and (eq type 'SECONDARY)
+           (nth 5 brief-xclipboard-args))
+      (error "Invalid TYPE")))
+
+(defvar <brief-external-bytes-received> 0
+  "Brief internal variable to store received bytes count.")
+
+(defvar <brief-backing-up-clipboard> nil
+  "Brief internal flag to indicate we're currently backing up external 
clipboard")
+
+(defun <brief-external-clipboard-filter> (proc string)
+  "Brief internal function to filter external clipboard helper program data."
+  (when (buffer-live-p (process-buffer proc))
+    (with-current-buffer (process-buffer proc)
+      ;;(message "<string> %S:%S" (process-mark proc) (length string))
+      ;; Insert the text, advancing the process marker.
+      (goto-char (process-mark proc))
+      (insert string)
+      (setq <brief-external-bytes-received>
+            (+ <brief-external-bytes-received>
+               (string-bytes string)))
+      (set-marker (process-mark proc) (point)))))
+
+(defvar brief-external-process-status-changed 0
+  "A brief internal variable for Emacs <= v24 to detect process done.
+This is used in `brief-external-get-selection'")
+
+(defun <brief-external-clipboard-sentinel> (proc event)
+  "Brief internal function, discard process status message string.
+Also indicate the status change of the external helper process.  For
+Emacs <= v24 this is required before getting all the output of the
+external helper process."
+  (incf brief-external-process-status-changed)
+  ;;(message "<brief-external-clipboard-sentinel> %S %S %d"
+  ;;         (process-exit-status proc) event
+  ;;         brief-external-process-status-changed)
+  t)
+
+(defun brief-external-clipboard-process-coding-system ()
+  "Prepare coding system before running external clipboard program.
+The return value will be applied to `default-process-coding-system'
+before creating new process."
+  ;; Leave the decision of coding-system to the user.  When
+  ;; user is editing a buffer, the buffer coding should already
+  ;; set to the correct encoding or things might display
+  ;; incorrectly.  The sender/receiver of the clipboard should
+  ;; use the same coding system to be able to transfer the
+  ;; correct clipboard data.
+  (let ((coding (if (eq brief-external-clipboard-coding-system
+                        'buffer)
+                    buffer-file-coding-system
+                  brief-external-clipboard-coding-system)))
+    (cons coding coding)))
+
+(defun brief-external-get-selection (&optional type mode)
+  "Helper function for `brief-gui-get-selection' using an external program.
+TYPE is clipboard type, can be either 'PRIMARY, 'CLIPBOARD or 'SECONDARY.
+MODE is either 'interrupt (default) or 'timeout.  With 'interrupt MODE
+user is able to break this function by the 'quit signal (\\[keyboard-quit]).
+
+This function does not support native Win32/Win64; but it does support
+Cygwin.  For Cygwin if the customized option `brief-cygwin-use-clipboard-dev'
+is set to non-NIL (default value 't'), it will use Cygwin's '/dev/clipboard'
+virtual device instead and which is much faster then forking a helper
+program."
+
+  (let ((currbuf (current-buffer)) ;; we are about to switch to a temp buffer
+        (result nil)
+        (coding-system (brief-external-clipboard-process-coding-system)))
+
+    (if (and brief-is-cygwin
+             brief-cygwin-use-clipboard-dev)
+        ;; Cygwin is so slow on forking process so we prevent external
+        ;; process and use /dev/clipboard if configured to do so.
+        (with-temp-buffer
+          (save-match-data
+            (insert-file-contents "/dev/clipboard") ;; nil nil nil nil)
+            (goto-char (point-min))
+            ;; Convert from DOS line-ending to UNIX line-ending, or
+            ;; MAC line endings according to current coding system
+            (let ((encoding (symbol-name buffer-file-coding-system))
+                  eol)
+              (unless (string-match "-dos$" encoding) ;; dos encoding
+                (setq eol
+                      (if (string-match "-mac$" encoding) ;; mac encoding
+                          "\r"
+                        ;; default unix encoding
+                        "\n"))
+                (while (search-forward "\r\n" nil t)
+                  (replace-match eol))))
+            ;;(message "dbg: read from /dev/clipboard")
+            (setq result (buffer-string))))
+
+      ;; non-Cygwin environment
+      (if (or (and (null brief-xclipboard-cmd) ;; no external helper
+                   (null (brief-xclipboard-cmd-search)))
+              ;; For pure terminal we don't have shared clipboard, unless 
someone
+              ;; write a Cygwin-like /dev/clipboard ;)
+              (string= "" (or (getenv "DISPLAY") ""))) ;; no display setting
+
+          ;; No external helper available, use native backend functions
+          (setq result
+                (gui-backend-get-selection type 'STRING))
+
+        ;; Running external helper program
+        (with-temp-buffer
+          (let*
+              ((buf (current-buffer))
+               ;;(process-connection-type nil) ; pipe
+               (msgbuf (get-buffer "*Messages*"))
+               ;; Set/Create a standalone STDERR buffer to be different from
+               ;; current buffer in order to prevent process status string
+               ;; being injected into stdout.
+               (stderr (or msgbuf
+                           (get-buffer-create
+                            "*brief-external-clipboard-stderr*")))
+
+               (default-process-coding-system coding-system)
+
+               (proc (if (not (fboundp 'make-process))
+                         ;; Emacs <= v24
+                         (let ((proc
+                                (apply
+                                 'start-process
+                                 (nconc
+                                  (list brief-xclipboard-cmd
+                                        (current-buffer)
+                                        brief-xclipboard-cmd
+                                        (car brief-xclipboard-args))
+                                  ;; selection arg
+                                  (and (nth 2 brief-xclipboard-args)
+                                       (list (nth 2 brief-xclipboard-args)))
+                                  (list (brief-xclipboard-get-type-arg type))
+                                  ;; must-have args
+                                  (and (nth 6 brief-xclipboard-args)
+                                       (nth 6 brief-xclipboard-args))))))
+                           (set-process-filter
+                            proc
+                            '<brief-external-clipboard-filter>)
+                           (set-process-sentinel
+                            proc
+                            '<brief-external-clipboard-sentinel>)
+                           (set-process-query-on-exit-flag proc nil)
+                           proc)
+
+                       ;; Emacs >= v25
+                       (make-process
+                        :name "brief-xclip"
+                        :buffer buf
+                        :command (nconc
+                                  (list brief-xclipboard-cmd
+                                        (car brief-xclipboard-args))
+                                  ;; selection arg
+                                  (and (nth 2 brief-xclipboard-args)
+                                       (list (nth 2 brief-xclipboard-args)))
+                                  (list (brief-xclipboard-get-type-arg type))
+                                  ;; must-have args
+                                  (and (nth 6 brief-xclipboard-args)
+                                       (nth 6 brief-xclipboard-args)))
+                        :connection-type 'pipe
+                        :noquery t
+                        ;; Prevent extern process status message get into the 
buffer
+                        :filter   '<brief-external-clipboard-filter>
+                        :sentinel '<brief-external-clipboard-sentinel>
+                        :stderr   stderr)))
+
+               ;; Prevent message if already inhibited or in minibuffer
+               (inhibit-message (or inhibit-message
+                                    (minibufferp currbuf)))
+               (garbage-collection-messages t)
+               (count 0)
+               (start-wait-time (brief-current-time))
+               (clipboard-timeout
+                (case (or mode 'interrupt) ;; default 'interrupt mode
+                  ('timeout   (* brief-external-xclipboard-timeout
+                                 (brief-slowdown-factor)))
+                  ('interrupt most-positive-fixnum)
+                  (otherwise
+                   (error
+                    "Brief: unknown mode %S for brief-external-get-selection"
+                    mode))))
+               (timeout nil))
+
+            (unless (eq msgbuf stderr)
+              ;; Empty the stderr buffer to remove old contents in case
+              ;; we later need to parse the information there (e.g.
+              ;; "Can't display" and get the outdated information accidentally.
+              (with-current-buffer stderr
+                (erase-buffer)))
+
+            (setq <brief-external-bytes-received> 0)
+            (setq brief-external-process-status-changed 0)
+            ;;(set-process-query-on-exit-flag proc nil)
+            ;;(set-process-sentinel proc '<brief-external-clipboard-sentinel>)
+
+            ;; Force timeout for big clipboard data, if in 'timeout mode
+            (if (with-timeout
+                    (clipboard-timeout
+                     ;;(message "@@ Timeout in buffer %S!!" (current-buffer))
+                     (setq timeout t)
+                     (delete-process proc)
+                     nil)
+                  (condition-case err
+                      (catch 'break
+                        (progn
+                          ;; Wait till process ends
+                          (while (process-live-p proc)
+                            ;;(sit-for 0.2) ;; extremely slow
+                            (accept-process-output proc
+                                                   (* 0.01
+                                                      (brief-slowdown-factor)))
+                            (incf count)
+
+                            (when (zerop (logand count #xf))
+                              ;; 0.01 * 15 = 0.15 second each iteration.
+                              ;; We need to actually calculate the elapsed time
+                              ;; to conclude a timeout.
+                              ;;
+                              ;; If we're just trying to backup clipboard in
+                              ;; order to be nice to other APs, give up if it's
+                              ;; too big, or if the external xclipboard program
+                              ;; respond too slow: wait no more than
+                              ;; `brief-giveup-clipboard-backup-timeout'
+                              ;; seconds. By default it's 1.0 second.
+                              (when
+                                  (and brief-giveup-clipboard-backup-if-huge
+                                       <brief-backing-up-clipboard>
+                                       (> (- (brief-current-time)
+                                             start-wait-time)
+                                          (* 
brief-giveup-clipboard-backup-timeout
+                                             (brief-slowdown-factor))))
+                                (when brief-giveup-clipboard-backup-message
+                                  (message
+                                   "* Xselection data too big, giving up 
backup")
+                                  (sit-for (* 0.01 (brief-slowdown-factor))))
+                                (delete-process proc)
+                                (throw 'break 'giveup))
+
+                              (when brief-show-external-clipboard-recv-progress
+                                (message
+                                 "Receiving data from Xselection : %d chunks 
..."
+                                 count)
+                                ;; This `sit-for' allows message buffer 
updating
+                                (sit-for (* 0.01 (brief-slowdown-factor))))))
+
+                          (if (not (fboundp 'make-process))
+                              ;; Wait till process sentinel reached which means
+                              ;; the process status changed for some reason.
+                              ;; Usually for process exited.  Only Emacs<=24
+                              ;; require this.  If we enable this in Emacs26,
+                              ;; it sometimes cause problems.
+                              (while
+                                  (and (= 0 
brief-external-process-status-changed)
+                                       (not (and
+                                             
brief-giveup-clipboard-backup-if-huge
+                                             <brief-backing-up-clipboard>
+                                             (> (- (brief-current-time)
+                                                   start-wait-time)
+                                                
brief-giveup-clipboard-backup-timeout))))
+                                (accept-process-output proc)
+                                (sit-for 0.01)))
+
+                          ;; Show total bytes received if user had waited long
+                          ;; enough to see the earlier recv message.
+                          (when (and 
brief-show-external-clipboard-recv-progress
+                                     (> <brief-external-bytes-received> 0))
+                            (message
+                             "Total %d bytes received from Xselection in %.3f 
seconds"
+                             <brief-external-bytes-received>
+                             (- (brief-current-time) start-wait-time)))))
+
+                    ;; User quit
+                    (quit
+                     (progn
+                       (if (process-live-p proc)
+                           (delete-process proc))
+                       (if brief-show-external-clipboard-recv-progress
+                           (message "* Quit receiving data from Xselection"))
+                       (signal 'quit nil)))
+
+                    ;; Catch all other kinds of errors
+                    (error
+                     (progn
+                       (if (process-live-p proc)
+                           (delete-process proc))
+                       (if brief-show-external-clipboard-recv-progress
+                           (message
+                            "* Error %S occurs when receiving Xselection"
+                            err))
+                       ;; propagate the error up
+                       (error (or (and (stringp (cdr err))
+                                       (cdr err))
+                                  (format "Error:%S" err))))))
+                  ;; Everything fine, go get the `buffer-string'
+                  t)
+
+                ;; Process done.
+                ;; We *won't* get any data (will get empty string, after
+                ;; some experiments) if 'giveup was thrown during receiving.
+                (setq result (buffer-string))
+
+              ;; Process timeout.
+              (if timeout
+                  (message "Error: timeout running process %S" proc)
+                ;; TODO: try to understand why it fails.  May need to get the
+                ;; `process-exit-status' and parse the STDERR buffer to show
+                ;; some error message.  In this case we can't use MSGBUF to
+                ;; be the STDERR in this function.
+                'TODO))
+
+            ;; In case any unhandled interruption here that leaves
+            ;; an useless idle proc
+            (when (process-live-p proc)
+              ;; Unhandled error, but no abort here since we still can
+              ;; create a new process next time.
+              (message "Warning: Process %S is still alive, killed it."
+                       proc)
+              (delete-process proc))
+
+            ;; Kill stderr buf, seems not necessary, anyway, do it for safe
+            (unless (eq stderr msgbuf)
+              (let ((kill-buffer-query-functions nil)
+                    ;;(delq 'process-kill-buffer-query-function
+                    ;;      kill-buffer-query-functions)
+                    (kill-buffer-hook nil))
+                ;;(message "@@ Killing stderr %S" stderr) ;;DBG
+                (kill-buffer stderr))))))
+
+      ;; Finally, return the result
+      (case type
+        ('PRIMARY
+         (setq gui--last-selected-text-primary result))
+        ('CLIPBOARD
+         (setq gui--last-selected-text-clipboard result))
+        (otherwise
+         ;; don't shoot an error since we can still work
+         (message "Unsupported TYPE '%S' for `brief-external-get-selection'" 
type)))
+      result)))
+
+;;(defvar brief-external-sending 0) ;;DBG
+(defconst brief-external-send-blocksize (* 2 65536)
+  "Maximum block size when sending string to external Xselection.
+The block size is counted in 'characters' with the current buffer
+encoding, not in bytes.")
+
+(defvar brief-external-set-selection-prev-proc nil
+  "Internal variable to store the lingering external helper process.
+This sometimes happens maybe due to some temporarily system burst load
+that make the external process postponed a bit.  Usually it will complete
+later so we won't kill it in the end of `brief-external-set-selection'.
+Usually before the next `brief-external-set-selection' run the process
+will complete its job in the background.  In case it didn't we then
+kill it as our new operation is going to overwrite it.")
+
+(defun brief-kill-lingering-external-set-helper (&optional msg)
+  "Kill lingering Xselection set process.
+See `brief-external-set-selection-prev-proc' for more detail."
+  (when (and brief-external-set-selection-prev-proc
+             (process-live-p brief-external-set-selection-prev-proc))
+    (unless msg
+      (message "Warning: lingering process %S is still alive, killed it."
+               brief-external-set-selection-prev-proc))
+    (delete-process brief-external-set-selection-prev-proc))
+  (setq brief-external-set-selection-prev-proc nil)
+  t)
+
+(defun brief-external-set-selection (type data)
+  "Helper function for `brief-gui-set-selection' using an external helper 
program.
+
+This function is non-blocking if external helper program is available,
+unlike the default Emacs behavior that is usually blocking and not
+interruptible.  If data is huge this blocking behavior could take very
+long and the whole system respond time would be reduced a lot.
+
+For Cygwin launching an external program is expensive so we use the
+cygwin specific \"/dev/clipboard\" if user set the custom variable
+`brief-cygwin-use-clipboard-dev' to be non-NIL.
+
+When external helper program is launched, this non-blocking function
+can be interrupted in two ways:
+
+When marking a region, it's in \"interruptible\" mode; any keystroke
+will interrupt current in-progress clipboard copying.  When performing
+a `brief-copy-line' (\\[brief-copy-line]) it's in \"quittable\" mode where we
+can only use `keyboard-quit' (\\[keyboard-quit]) command to interrupt it.
+
+This function has an internal mode: `brief-is-external-interruptible'
+which defines how this function can be interrupted.  If this variable
+is not set this function is by default blocking and it will return
+only when data are completely sent to the helper program.
+
+This function does not support native Win32/Win64."
+
+  ;; Notice that this function is a replacement for `gui-set-selection' which
+  ;; has no mode.  Therefore the actual mode relies on the global flag
+  ;; `brief-is-external-interruptible' which is controlled by function
+  ;; `brief-run-postponed-gui-set-selection', which again calls
+  ;; `brief-copy-region-into-clipboard' that sets this variable.
+  ;;
+  ;; Terminal support, we don't do `gui-get-selection' here to compare
+  ;; existing clipboard, in order to reduce overheads because we are
+  ;; invoking external program to process clipboards.
+  (if (and brief-is-cygwin
+           brief-cygwin-use-clipboard-dev)
+      ;; Cygwin only
+      (and (or (eq type 'PRIMARY)
+               (eq type 'CLIPBOARD))
+           (if (boundp 'gui--last-selected-text-primary)
+               (not (or (eq gui--last-selected-text-primary data)
+                        (string= gui--last-selected-text-primary data)))
+             t)
+           ;;(message "dbg: write to /dev/clipboard")
+           (let ((encoding (symbol-name buffer-file-coding-system))
+                 eol)
+             (unless (string-match "-dos$" encoding) ;; already dos encoding
+               (setq eol
+                     (if (string-match "-mac$" encoding) ;; mac encoding
+                         "\r"
+                       ;; default unix encoding
+                       "\n"))
+               (with-temp-buffer
+                 ;; Convert to DOS line-ending
+                 (insert data)
+                 (goto-char (point-min))
+                 (while (search-forward eol nil t)
+                   (if (/= (char-before (1- (point))) ?\r)
+                       ;; ?\r already there? don't convert
+                       (replace-match "\r\n")))
+                 (write-region (buffer-string)
+                               nil "/dev/clipboard" nil 'nomsg)))))
+    ;; Non-cygwin
+    (if (or (and (null brief-xclipboard-cmd) ;; No external helper available
+                 (null (brief-xclipboard-cmd-search)))
+            (string= "" (or (getenv "DISPLAY") ""))) ;; no display setting
+        ;; Use native backend functions
+        (gui-backend-set-selection type data)
+
+      ;; Run external helper
+      (when (if (boundp 'gui--last-selected-text-primary)
+                (and (or (eq type 'PRIMARY)
+                         (eq type 'CLIPBOARD))
+                     (not (or (eq gui--last-selected-text-primary data)
+                              (string= gui--last-selected-text-primary data))))
+              t)
+
+        (case type
+          ('PRIMARY
+           (setq gui--last-selected-text-primary data))
+          ('CLIPBOARD
+           (setq gui--last-selected-text-clipboard data))
+          (otherwise
+           (message "Unsupported TYPE for `brief-external-set-selection'")))
+
+        ;; Delete the lingering process as we're going to overwrite the
+        ;; Xselection which it has been lingering on.
+        (brief-kill-lingering-external-set-helper
+         brief-show-external-clipboard-send-progress)
+
+        (let* ((process-connection-type nil) ; pipe
+               (default-process-coding-system ;;'(utf-8 . utf-8))
+                 (brief-external-clipboard-process-coding-system))
+               (proc (apply
+                      'start-process
+                      (nconc (list
+                              brief-xclipboard-cmd nil
+                              ;;"timeout"
+                              ;;(number-to-string 
brief-external-xclipboard-timeout)
+                              brief-xclipboard-cmd)
+                             ;; input arg
+                             (and (cadr brief-xclipboard-args)
+                                  (list (cadr brief-xclipboard-args)))
+                             ;; selection arg
+                             (and (nth 2 brief-xclipboard-args)
+                                  (list (nth 2 brief-xclipboard-args)))
+                             (list
+                              (brief-xclipboard-get-type-arg type))
+                             ;; must have args only needed for 'get'
+                             ;;(last brief-xclipboard-args
+                             ;;      (- (length brief-xclipboard-args) 6))
+                             )))
+               ;; inhibit message if already did or in minibuffer
+               (inhibit-message  (or inhibit-message (minibufferp)))
+               (count 0)
+               (datalen (length data))
+               (databytes (string-bytes data))
+               (databeg 0)
+               (sentbytes 0)
+               (sendstr "")
+               (dataend brief-external-send-blocksize))
+
+          (set-process-query-on-exit-flag proc nil)
+          ;;(message "*proc %S starts*" proc) ;;DBG
+          (condition-case err
+              ;; Catch 'quit signal or proc will stay alive after quit
+              (progn
+                ;; Send pieces during idle, till user inputs something
+                (while (and
+                        (case brief-is-external-interruptible
+                          ;; Interruptible mode
+                          ('interruptible
+                           ;; any input event breaks the loop
+                           (not (brief-input-pending-p)))
+                          ;; Quitable mode
+                          ('quitable
+                           ;; continue, but check 'quit signal
+                           ;;(if
+                           (brief-input-pending-p) ;; checking timer
+                           ;;    (accept-process-output nil 0.05))
+                           t)
+                          ;; Continuous mode, no break
+                          (otherwise
+                           t))
+                        (< databeg datalen)
+                        (process-live-p proc))
+
+                  (setq sendstr
+                        (substring-no-properties data
+                                                 databeg
+                                                 (min dataend datalen)))
+                  (setq sentbytes
+                        (+ sentbytes (string-bytes sendstr)))
+                  (process-send-string proc sendstr)
+
+                  (when (zerop (logand count 3))
+                    ;; Notice that this `sit-for' MUST be placed *BEFORE*
+                    ;; showing the message, otherwise the `process-live-p'
+                    ;; will think the PROC to be still running even if
+                    ;; it's already exited or aborted.
+                    (accept-process-output)
+                    (sit-for 0.01 nil) ;; cannot be zero
+                    (and brief-show-external-clipboard-send-progress
+                         (process-live-p proc)
+                         (message "* Sent %d bytes to Xselection"
+                                  sentbytes)))
+
+                  (when brief-is-external-interruptible
+                    ;; Allow Emacs updating its internal status, or
+                    ;; receive the 'quit signal.
+                    (accept-process-output)
+                    ;;(sit-for 0.01 t)
+                    )
+                  (incf count)
+                  (setq databeg dataend
+                        dataend (+ dataend brief-external-send-blocksize)))
+
+                (if (process-live-p proc)
+                    (progn
+                      (if (and brief-show-external-clipboard-send-progress
+                               (> databeg 0))
+                          (if (>= databeg datalen)
+                              (message
+                               "* Complete sending %d bytes to Xselection"
+                               databytes)
+                            (message "* Interrupted sending to Xselection")))
+                      (process-send-eof proc))
+
+                  ;; TODO: Try to understand why process ends.  Showing error
+                  ;; messages here is not favored as it will keep showing if
+                  ;; it's a persistent error (e.g. some X display server 
failure
+                  ;; or incorrect "DISPLAY" environment variable.); unless we
+                  ;; limit the times that the error messages shown.  If the
+                  ;; display server come back to live again we should restart
+                  ;; to show that error message in case it again failed.
+                  ;; Another possible reason is that it crashed or been killed
+                  ;; by other process.
+                  'TODO)
+
+                (if (>= dataend datalen)
+                    ;; Completed sending
+                    (progn
+                      (setq brief-external-set-selection-interrupted nil)
+                      data)
+                  ;; Interrupted by user input
+                  (if (process-live-p proc)
+                      (delete-process proc))
+                  (setq brief-external-set-selection-interrupted t)
+                  nil))
+
+            ;; Kill proc in case of 'quit signal
+            (quit (progn
+                    (process-send-eof proc)
+                    (if (process-live-p proc)
+                        (delete-process proc))
+                    (if brief-show-external-clipboard-send-progress
+                        (progn
+                          (message "* Quit sending data to Xselection")
+                          (brief-dbg-message "  (quit sending in %S mode)"
+                                             brief-is-external-interruptible)))
+
+                    (setq brief-external-set-selection-interrupted 'quit)
+                    ;; Propagate quit signal forwards
+                    (signal 'quit nil)))
+
+            ;; Catch all other kinds of errors
+            (error (progn
+                     (process-send-eof proc)
+                     (if (process-live-p proc)
+                         (delete-process proc))
+                     (if brief-show-external-clipboard-send-progress
+                         (message
+                          "* Error %S occurs when sending to Xselection" err))
+
+                     (setq brief-external-set-selection-interrupted 'error)
+                     ;; propagate the error up
+                     (error (or (and (stringp (cdr err))
+                                     (cdr err))
+                                (format "Error:%S" err))))))
+
+          ;; If in any case the process might not complete its job here, we 
don't
+          ;; need to wait as we have already sent it all our data.  Neither can
+          ;; we kill it since it might still be processing the data we sent in
+          ;; the background.
+          (when (process-live-p proc)
+            (setq brief-external-set-selection-prev-proc proc)))))))
+
+(defun brief-gui-select-text (text)
+  "Override the default `gui-select-text' system function (select.el).
+Conditionally set `gui--last-selected-text-primary' and
+`gui--last-selected-text-clipboard'.  If our previous external clipboard
+invoking was interrupted, clear them."
+  (let ((select-enable-primary   (and (not (brief-is-winnt))
+                                      brief-select-enable-primary))
+        (select-enable-clipboard (or (brief-is-winnt)
+                                     brief-select-enable-clipboard)))
+    (setq brief-external-set-selection-interrupted nil)
+    (when select-enable-primary
+      (gui-set-selection 'PRIMARY text)
+      (setq gui--last-selected-text-primary
+            (if brief-external-set-selection-interrupted
+                nil
+              text)))
+    (when select-enable-clipboard
+      (setq saved-region-selection text)
+      (gui-set-selection 'CLIPBOARD text)
+      (setq gui--last-selected-text-clipboard
+            (if brief-external-set-selection-interrupted
+                nil
+              text)))))
+
+(defvar brief-previous-clipboard-selection nil
+  "Backup Xselection before start marking texts.
+The region/rectangle marking operation could later be canceled.  We
+therefore need to backup first otherwise Xselection will be immediately
+replaced by the marking texts; when operation canceled we will not be
+able to restore it back if we have no backups.")
+
+;; The core modification that prevent Windows X server failure
+;; due to too much flooding message as clipboard change
+(if (not (fboundp 'advice-add))
+    (progn
+      (if brief-selection-op-legacy
+          (defadvice x-get-selection (around brief-advice-gui-get-selection
+                                             (&optional type data-type)
+                                             disable activate compile)
+            (if window-system
+                ad-do-it
+              (brief-external-get-selection type)))
+        (defadvice gui-get-selection (around brief-advice-gui-get-selection
+                                             (&optional type data-type)
+                                             disable activate compile)
+          ;; [2017-07-14 Fri] When clipboard data is huge,
+          ;; `gui-backend-get-selection', which was implemented as
+          ;; `x-get-selection-internal', will stop responding.
+          (if window-system
+              ad-do-it
+            (brief-external-get-selection type))))
+
+      (if brief-selection-op-legacy
+          (defadvice x-set-selection (around brief-advice-gui-set-selection
+                                             (type data) disable activate 
compile)
+            (if (eq type 'SECONDARY)
+                ad-do-it
+              (if brief-is-gui-set-selection-postponed
+                  (brief-activate-postpone-gui-selection-timer)
+                (unless (brief-multiple-cursor-in-action)
+                  (if (and (brief-is-x)
+                           (not brief-use-external-clipboard-when-possible))
+                      ad-do-it
+                    (brief-external-set-selection type data))))))
+
+        (defadvice gui-set-selection (around brief-advice-gui-set-selection
+                                             (type data) disable activate 
compile)
+          (if (eq type 'SECONDARY)
+              ad-do-it
+            (if brief-is-gui-set-selection-postponed
+                ;; Activate timer to start postponing gui-set-selection.
+                ;; In terminal mode this will not run.
+                (brief-activate-postpone-gui-selection-timer)
+              (unless (brief-multiple-cursor-in-action)
+                (if (or (brief-is-winnt)
+                        (and (brief-is-x)
+                             ;; [2017-12-12 Tue] The following is no longer 
true.
+                             ;; Cannot reproduce it any longer, maybe a glitch
+                             ;; during the development?
+                             ;; [2017-07-13 Thu] When running in X11, the
+                             ;; function `x-own-selection-internal' will fail
+                             ;; if the data is longer than 262040 bytes.  This
+                             ;; bug is caught thru many experiments.
+                             ;; When data is long, use external helper program.
+                             ;;(< (length data) 262041)
+                             (not brief-use-external-clipboard-when-possible)))
+                    ad-do-it
+                  (brief-external-set-selection type data))))))))
+  ;;
+  ;; `advice-add' defined
+  ;;
+  (defun brief-gui-get-selection (orig-func &rest args)
+    ;; [2017-07-14 Fri] When clipboard data is huge, 
`gui-backend-get-selection'
+    ;; which was implemented as `x-get-selection-internal' will stop 
responding.
+    (if (or (and (brief-is-x)
+                 brief-use-external-clipboard-when-possible)
+            (brief-is-terminal))
+        (brief-external-get-selection (or (car args)
+                                          'PRIMARY))
+      (if (and (brief-is-winnt)
+               ;; On Win32/Win64 we by default use 'CLIPBOARD
+               (eq (or (car args)
+                       'CLIPBOARD)
+                   'CLIPBOARD))
+          (or (w32-get-clipboard-data)
+              (w32--get-selection)
+              (apply orig-func args))
+        (apply orig-func args))))
+
+  ;;(advice-remove 'gui-get-selection 'brief-gui-get-selection)
+  ;;(advice-add 'gui-get-selection :around 'brief-gui-get-selection)
+
+;;(defvar brief-gui-set-debouncer
+;;  "Debouncing info for brief-gui-set-selection due to MS Office message 
flood.
+;;Format: (time selection-data)"
+;;    nil)
+;;
+  ;; The core modification that prevent Windows X server failure
+  ;; due to too much flooding message as clipboard change caused by
+  ;; Microsoft Office
+  (defun brief-gui-set-selection (orig-func &rest args)
+    (if (boundp 'brief-gui-set-selection-reentry)
+        (brief-dbg-message "Reenter brief-gui-set-selection, exit")
+      (brief-dbg-message "enter brief-gui-set-selection")
+      (let ((type (car args))
+            (data (cadr args))
+            (brief-gui-set-selection-reentry t))
+        (if (eq type 'SECONDARY)
+            (apply orig-func args)
+          (if brief-is-gui-set-selection-postponed
+              ;; Activate timer to start postponing gui-set-selection
+              ;; (in terminal mode this will not run)
+              (brief-activate-postpone-gui-selection-timer)
+
+            ;;(deactivate-mark) ;; this will cause reenter as this will invoke
+            ;;                  ;; `gui-set-selection'
+            (unless (brief-multiple-cursor-in-action)
+              (if (or (brief-is-winnt)
+                      (and (brief-is-x)
+                           ;; [2017-12-12 Tue] The following is no longer true.
+                           ;; Cannot reproduce it any longer, maybe a glitch
+                           ;; during the development?
+                           ;; [2017-07-13 Thu] When running in X11, the 
function
+                           ;; `x-own-selection-internal' will fail if the data
+                           ;; is longer than 262040 bytes.  This bug is caught
+                           ;; by many experiments.
+                           ;; When data is long, use external helper program.
+                           ;; TODO: verify if this bug persists for emacs 
version
+                           ;; > 26.0.50. if bug persists, fix it.
+                           ;;(< (length data) 262041)
+                           (not brief-use-external-clipboard-when-possible)))
+                  (apply orig-func args)
+                (apply 'brief-external-set-selection args))))))
+      (brief-dbg-message "leave brief-gui-set-selection"))))
+
+;;
+;; Xselection/Windows-clipboard backward compatibility functions for older 
Emacs
+;;
+
+;;(when (brief-is-winnt) ;; TODO: fix this here, also use gui-xxxx function 
here
+;;  (defalias 'x-selection-exists-p 'w32-selection-exists-p)
+;;  (defvar x-last-selected-text nil)
+;;  (defun x-get-selection ()
+;;    (setq x-last-selected-text (w32-get-clipboard-data)))
+;;  (defun x-get-selection-value ()
+;;    (w32-get-clipboard-data)))
+
+;; A shared local variable between `brief-selection-exists-p' and
+;; `brief-get-selection-value' to prevent `brief-yank' invoking
+;; `gui-get-selection' twice in terminal mode.
+;; When clipboard data is big, this invokes external program twice,
+;; which is very inefficient.
+(defvar-local brief-terminal-getclip-when-check-existence nil)
+
+;; No need to check the existence, as it works only in the very beginning.
+;; Once Xselection is set once, this should always returns true. Even if it's
+;; empty, just read it back and compare with empty string.
+;;(defun brief-selection-exists-p ()
+;;  (if (brief-is-x)
+;;      (x-selection-exists-p 'PRIMARY)
+;;    (if (brief-is-terminal)
+;;        (not (zerop (length
+;;                     (or (setq brief-terminal-getclip-when-check-existence
+;;                               (gui-get-selection 'PRIMARY))
+;;                         ""))))
+;;      (and (brief-is-winnt)
+;;           (w32-selection-exists-p 'CLIPBOARD)))))
+
+(defvar brief-last-selected-text nil) ;; for w32 environment
+(defun brief-last-selected-text ()
+  "Local function called only by these backward compatibility functions."
+  (if (brief-is-x)
+      gui--last-selected-text-primary
+    (and (brief-is-winnt)
+         brief-last-selected-text)))
+
+(defun brief-get-selection-value ()
+  "Legacy function called by `brief-yank' for older Emacs only."
+  (let ((result nil))
+    (if (or (brief-is-x)
+            (brief-is-terminal))
+        (if (fboundp #'gui-get-selection)
+            ;; Here we choose primary only since we consider primary is in sync
+            ;; with clipboard when editing with Brief mode
+            (if brief-terminal-getclip-when-check-existence
+                ;; We just get it using external program, use it, don't invoke
+                ;; external program again
+                (setq result brief-terminal-getclip-when-check-existence
+                      brief-terminal-getclip-when-check-existence nil)
+              (setq result (gui-get-selection 'PRIMARY)))
+          (setq result (x-get-selection-value)))
+      (and (brief-is-winnt)
+           (let ((clipdata (or (w32-get-clipboard-data)
+                               (w32--get-selection))))
+             (setq result
+                   (and clipdata
+                        (setq brief-last-selected-text clipdata))))))
+    result))
+
+(defun brief-get-selection ()
+  "Local function called by `brief-get-clipboard-selection' only."
+  (if (brief-is-x)
+      (x-get-selection)
+    (and (brief-is-winnt)
+         (let ((clipdata (or (w32-get-clipboard-data)
+                             (w32--get-selection))))
+           (and clipdata
+                (setq brief-last-selected-text clipdata))))))
+
+;;(if (fboundp #'w32-selection-exists-p)
+;;    (defun brief-get-clipboard-selection ()
+;;      "Function to get system clipboard text on X or MS-WIN systems."
+;;      (and (brief-is-winnt)
+;;           (w32-selection-exists-p 'CLIPBOARD)
+;;           (w32--get-selection)))
+(defun brief-get-clipboard-selection ()
+  "Function to get system clipboard text on X or MS-WIN systems."
+;;;  (or (and (brief-is-x)
+;;;           (x-selection-exists-p 'PRIMARY)
+;;;           ;;(x-get-selection brief-X-selection-target)
+;;;           (x-get-selection-value))
+;;;      (and (brief-is-winnt)
+;;;           (x-selection-exists-p 'CLIPBOARD)
+;;;           (or (x-get-selection-value)
+;;;               x-last-selected-text))))
+  (if (brief-is-winnt)
+      (and (w32-selection-exists-p 'CLIPBOARD)
+           (or (brief-get-selection)
+               brief-last-selected-text))
+    ;;(if (brief-is-x)
+    ;;    (and (x-selection-exists-p 'PRIMARY)
+    ;;         ;;(x-get-selection brief-X-selection-target)
+    ;;         (x-get-selection-value)))
+    ;; [2017-01-19 Thu] The following now works for both terminal and X
+    (gui-get-selection)))
+
+;; This will sometimes make `wg-restore-window' fails. I modified
+;; `wg-restore-window' and add a advice function in init.el to prevent this.
+;;(add-hook 'activate-mark-hook 'brief-region-backup-clipboard-selection)
+
+;;
+;; Xselection backup and restore
+;;
+;; Whenever mark is activated, for either rectangle or region, we need to
+;; backup Xselection before it got changed, in case user later would like
+;; to cancel current operation.
+;;
+
+(defun brief-copy-region-into-clipboard (&optional thetext interruptible)
+  "Copy current region or THETEXT into X clipboard, return text"
+  ;;(if window-system ;; <2011-09-19 Mon 15:01> prevent run this on pure 
terminals
+  (unless (brief-multiple-cursor-mode-is-on)
+    ;; [2016-05-24 17:06:41 +0800] support multiple-cursors mode
+    ;;(and (boundp 'multiple-cursors-mode)
+    ;;     multiple-cursors-mode)
+    (let ((text
+           ;;(or (and (boundp 'cua--last-killed-rectangle)
+           ;;         cua--last-killed-rectangle
+           ;;         (car cua--last-killed-rectangle))
+           ;;    (buffer-substring-no-properties
+           ;;     (region-beginning) (region-end)))
+           (or thetext
+               ;; [2017-01-25 Wed] must not use (current-kill 0)
+               ;; otherwise the kill-ring will grow.
+               (car kill-ring)
+               ""))
+          (brief-is-gui-set-selection-postponed
+           nil) ; this function won't work if this flag is t
+          (brief-is-external-interruptible interruptible)
+          ;; Some system use 'PRIMARY, some use 'CLIPBOARD
+          (x-select-enable-primary 't)
+          (x-select-enable-clipboard 'nil)
+          ;; Emacs >= 25.1
+          (select-enable-primary   (and (not (brief-is-winnt))
+                                        brief-select-enable-primary))
+          (select-enable-clipboard (or (brief-is-winnt)
+                                       brief-select-enable-clipboard)))
+
+      (unless (zerop (length text))
+        ;;(x-set-selection brief-X-selection-target text)
+        (if (fboundp #'gui-select-text)
+            (gui-select-text text) ;; -> `brief-gui-select-text'
+          (x-select-text text));;)
+        ;;(setq x-select-enable-primary t)
+        ;;        (x-set-selection 'PRIMARY text)
+        ;;(setq x-select-enable-clipboard t)
+        ;;        (x-set-selection 'CLIPBOARD text)
+        ;;(x-set-selection 'SECONDARY text)
+        ;;(x-select-text text)
+        ;;(set-register 'brief text)
+        ))))
+
+(defun brief-backup-clipboard-selection ()
+  "Force backup clipboard data before selection changed.
+If user cancelled the selection, we can restore it."
+  (let ((brief-is-gui-set-selection-postponed nil)
+        (<brief-backing-up-clipboard> t))
+    (setq brief-previous-clipboard-selection
+          (brief-get-clipboard-selection))))
+
+(defun brief-region-backup-clipboard-selection ()
+  ;; [2016-04-15 Fri] If we're marking rectangle and do editing (say, inserting
+  ;; chars for all column), we'll `cua-set-rectangle-mark' repeatedly called
+  ;; before region deactivated, and therefore corrupt the clipboard backup.
+  ;; Therefore we backup only when region is not yet activated.
+  (unless (or (region-active-p) ;; For Emacs23 we need to test 
`region-active-p' first
+              (brief-use-region)
+              (brief-multiple-cursor-in-action))
+    (brief-backup-clipboard-selection))
+  t)
+
+(defun brief-no-longer-need-restore-clipboard ()
+  "Destroy Xselection backup data.
+We do this either if we completed the backup or no need to keep it."
+  (setq brief-previous-clipboard-selection nil))
+
+(defun brief-restore-clipboard-selection ()
+  "Restore just backed up clipboard data if there is one.
+Return the restored text if previously backed up data successfully
+restored, otherwise NIL."
+  (let ((brief-is-gui-set-selection-postponed nil)
+        (text brief-previous-clipboard-selection))
+    (and ;;(brief-use-region) ;;; Don't check this, see comments in
+                              ;;; `brief-use-region'. When that happens this
+                              ;;; TEXT will not be restored.
+         text
+         (progn
+           (brief-copy-region-into-clipboard text)
+           (brief-no-longer-need-restore-clipboard)
+           text))))
+
+;;
+;; Mark activate/deactivate hook for Xselection postpone/backup/restore
+;;
+;;(defvar brief-garbage-collection-message-stack nil)
+
+(defun brief-postpone-gui-set-selection ()
+  "Hook function for `activate-mark-hook' to activate Xselection postponment."
+  (unless brief-is-gui-set-selection-postponed
+    ;; When marking a CUA rectangle, any self-inserting command will 
re-activate
+    ;; the marking, so this function will be called again without any
+    ;; `deactivate-mark-hook' called in between.  Therefore we need to test
+    ;; if `brief-is-gui-set-selection-postponed' is already true.
+    (setq brief-is-gui-set-selection-postponed t)
+    (setq brief-postponed-clipboard-ran nil)
+    (brief-activate-postpone-gui-selection-timer))
+  ;; When marking a very big region, I would like to see why system is pausing
+  ;; intermittently.
+  ;; I found it usually because of the garbage collection.
+  ;;
+  ;; This is not very good because quit signal sometimes not popping this flag
+  ;; out, only for debugging.
+  ;;(push garbage-collection-messages brief-garbage-collection-message-stack)
+  ;;(setq garbage-collection-messages t)
+  t)
+
+(defun brief-resume-gui-set-selection ()
+  "Hook function for `deactivate-mark-hook' to deactivate Xselection 
postponment."
+  ;;(message "@ brief-resume-gui-set-selection")
+  (if brief-keep-postpone-gui-selection-timer
+      ;; If `brief-copy-to-clipboard-on-keyup' was called, we *MUST* not cancel
+      ;; idle timer as that copy was postponed but need to be done on idle 
time.
+      (setq brief-keep-postpone-gui-selection-timer nil)
+    (brief-cancel-postpone-gui-selection-timer))
+  (setq brief-is-gui-set-selection-postponed nil)
+  ;; Restore backup if not done yet.
+  (brief-restore-clipboard-selection)
+  (setq brief-postponed-clipboard-ran nil)
+  ;;(setq garbage-collection-messages
+  ;;      (pop brief-garbage-collection-message-stack))
+  t)
+
+;;(add-hook 'activate-mark-hook   'brief-postpone-gui-set-selection 't)
+;;(add-hook 'deactivate-mark-hook 'brief-resume-gui-set-selection)
+
+;;
+;; Various advice functions
+;;
+;; So far I have not found a good way to eliminate all these necessary
+;; advice functions.  Some of the hook functions are not invoked when
+;; a command is canceled or interrupted.  Once there is a good way to
+;; do this these advice functions will be removed.
+
+;; [2017-07-10 Mon] Even Emacs 23.3.1 still having `activate-mark-hook' called.
+;; (defadvice cua-set-rectangle-mark (before brief-cua-set-rectangle-mark ()
+;;                                           activate compile)
+;;   ;; [2017-07-10 Mon] The following comments was written on 2015-05-13 
commit
+;;   ;; 5579b35d, but seems not valid. My local tests shows even for Emacs
+;;   ;; 24.4.50, `activate-mark-hook' still got invoked.
+;;   ;; [2015-05-13]
+;;   ;; cua-set-rectangle-mark will not invoke activate-mark-hook so we do it
+;;   ;; using advice
+;;   ;; TODO: is there a better way without using advice?
+;;   (brief-region-backup-clipboard-selection)))
+
+;; When undo restored the cua rectangle, we need to backup the clipboard or the
+;; same issue happens
+;; (defadvice cua--rect-undo-handler (around brief-cua--rect-undo-handler
+;;                                           activate compile)
+;;   (let ((backup-clipboard (use-region-p)))
+;;     (or backup-clipboard
+;;         (brief-region-backup-clipboard-selection))
+;;     ad-do-it
+;;     (or backup-clipboard
+;;         (brief-region-backup-clipboard-selection))))
+
+(defun brief-reset-for-command-cancellation (&rest args)
+  "Restore selection and reset internal variables due to command cancellation."
+  (brief-restore-clipboard-selection)
+  (and (brief-use-region) (deactivate-mark))
+  (brief-cancel-postpone-gui-selection-timer)
+  (setq brief-postponed-mark-selection-copy-completed nil))
+
+(defun brief-cua-rectangle-undo-helper ()
+  ;; `cua--rect-undo-handler' relies on this function to restore rectangle,
+  ;; so we do advice here
+  (and cua--restored-rectangle
+       (brief-region-backup-clipboard-selection)))
+
+;; TODO: Is there a better way then defining an advice for restoring clipboard?
+
+;; Note that `deactivate-mark-hook' is not adequate as in many situation
+;; involving command cancellation, that hook never got invoked.
+(eval-when (compile eval load)
+  (unless (fboundp #'advice-add)
+    ;; Initially we disable our advises but hooked, till Brief mode is enabled
+    (if (fboundp 'cua--rectangle-post-command)
+        (defadvice cua--rectangle-post-command
+            (before brief-cua--rectangle-post-command () disable activate 
compile)
+          (brief-cua-rectangle-undo-helper)))
+
+    ;; Starting from Emacs23 the CUA mode is builtin.
+    (defadvice cua-cancel (before brief-cua-cancel () disable activate compile)
+      (brief-reset-for-command-cancellation))
+
+    (defadvice keyboard-quit
+        (before brief-keyboard-quit () disable activate compile)
+      (brief-reset-for-command-cancellation))
+
+    (defadvice keyboard-escape-quit
+        (before brief-keyboard-escape-quit () disable activate compile)
+      (brief-reset-for-command-cancellation))
+
+    (when (fboundp 'cua-clear-rectangle-mark)
+      (defadvice cua-clear-rectangle-mark
+          (before brief-clear-rectangle-mark () disable activate compile)
+        "Extend `cua-clear-rectangle-mark' by a Xselection backup.
+The implementation of `cua-clear-rectangle-mark' does not invoke the
+`deactivate-mark-hook' thus we need to do that ourselves."
+        (brief-reset-for-command-cancellation)))
+
+    (when (fboundp 'cua-close-rectangle)
+      (defadvice cua-close-rectangle
+          (before brief-close-rectangle () disable activate compile)
+        "Extend `cua-close-rectangle' by a Xselection backup.
+The implementation of `cua-close-rectangle' does not invoke the
+`deactivate-mark-hook' thus we need to do that ourselves."
+        (brief-reset-for-command-cancellation)))))
+
+;;
+;; Various Brief mode interactive commands
+;;
+
+(defun brief-scan-rectangle (text)
+  "Scan text and set its yank properties as rectangle if it is a rectangle."
+  ;; Refer to function `rectangle--extract-region' for rectangle
+  (let* ((strs nil)
+         (width nil)
+         (widtheq nil)
+         (eol 0)
+         (start 0))
+    (while (and (setq eol (string-match "\n" text start))
+                (or width (setq width (- eol start)))
+                (setq widtheq (= width (- eol start))))
+      (setq strs (cons (substring-no-properties text start eol) strs)
+            start (1+ eol)))
+    ;; Rectangles should not have the ending EOL
+    (if (and widtheq
+               (= (- (length text) start) width))
+      (put-text-property 0 (length text) 'yank-handler
+                         `(rectangle--insert-for-yank
+                           ,(nreverse (cons (substring-no-properties
+                                             text start
+                                             (length text)) strs))
+                           t)
+                         text)))
+  text)
+
+(defun brief-yank (arg)
+  "Yank kill-ring/Xselection or rectangle into current text."
+  (interactive "p")
+  (let* ((interprogram-cut-function nil)
+         (interprogram-paste-function nil))
+
+    ;; If the previous `brief-copy-line' has not yet completed (keyup timeout
+    ;; not reached yet), then flush the pending operation which must be
+    ;; uninterruptible.
+    (if brief-copy-to-clipboard-on-keyup-data
+        (brief-run-postponed-gui-set-selection))
+
+    (unless (brief-multiple-cursor-mode-is-on)
+      ;; For multiple cursors mode we probably want different texts to be
+      ;; yanked on different cursors so grabbing a shared Xselection is not
+      ;; correct here.
+      (let ((clip-select (or (brief-restore-clipboard-selection)
+                             (if (and (fboundp #'gui-get-selection)
+                                      (not (brief-is-winnt)))
+                                 ;; Here we don't invoke `gui-selection-value'
+                                 ;; as it favors 'CLIPBOARD over 'PRIMARY.
+                                 ;; If user just switch from using 'CLIPBOARD
+                                 ;; to 'PRIMARY, we might get the old data
+                                 ;; in the 'CLIPBOARD.
+                                 (gui-get-selection
+                                  (or (and brief-select-enable-primary
+                                           'PRIMARY)
+                                      (and brief-select-enable-clipboard
+                                           'CLIPBOARD)))
+                               ;; For older Emacs and WinNT
+                               (brief-get-selection-value))))
+            (deactivate-mark nil))
+        (unless (or (zerop (length clip-select))
+                    ;;(message "/clip-select=%S" clip-select) ;;dbg
+                    ;;(message "\\kill-ring=%S" (car kill-ring)) ;;dbg
+                    (string= clip-select ; is it the same as clipboard ?
+                             (or (car  kill-ring) ""))
+                    (string= clip-select (or (cadr kill-ring) "")))
+          ;; The below is too slow, when kill-ring is huge, so comment it out
+          ;;(member clip-select kill-ring)) ;; is it already in kill-ring ?
+          (save-mark-and-excursion  ; Sync with kill-ring
+            ;;(message "kill-new %S" clip-select) ;;dbg
+            (ignore-errors
+              ;; on EmacsW32 it once failed to call `menu-bar-update-yank-menu'
+              (kill-new
+               ;; Scan if it's a rectangle
+               (brief-scan-rectangle clip-select)))))))
+    (let ((inhibit-message t))
+      (save-mark-and-excursion
+        ;; TODO: use 'delete-selection property instead
+        ;; (see 'delsel.el and delete-selection-mode)
+        ;; eg. (put 'brief-yank 'delete-selection ...)
+        (when (brief-use-region)
+          (and (brief-rectangle-active)
+               (goto-char (cua--rectangle-top))
+               (move-to-column (cua--rectangle-left)))
+          (cua-delete-region))
+        (call-interactively 'cua-paste)))
+    (brief-no-longer-need-restore-clipboard)))
+
+;; 04/15/'08 ins function
+(defun brief-print (arg)
+  "Print buffer or region"
+  (interactive "p")
+  (if (brief-use-region)
+      (call-interactively 'print-region)
+    (call-interactively 'print-buffer)))
+
+;; 06/21/2005 ins function
+(defun brief-buffer-read-only-toggle (arg)
+  "Toggle buffer read only status ON/OFF"
+  (interactive "P")
+  ;;(if (and (buffer-modified-p) (not buffer-read-only))
+  ;;    ;;if it's modified, it must not be read-only
+  ;;    ;; - [2013-01-31 10:06:48 +0800] false assumption, buffers created by
+  ;;    ;; '*Find*' will be such case.
+  ;;    (message
+  ;;     "Buffer modified, cannot set to read-only. Please save the buffer 
first.")
+  (setq buffer-read-only (not buffer-read-only))
+  (force-mode-line-update) ;;;; 05/07/2008 ins 1
+  (if buffer-read-only
+      (message "Buffer set to read-only")
+    (message
+     "Buffer set to read-write, careful not to modify read-only files!")))
+
+(defun brief-mark-line (arg)
+  "Set mark at the end of the line.
+ARG behaves the same as `beginning-of-line'."
+  (interactive "p")
+  (let (newmark)
+    (save-excursion
+      ;; 06/17/'05 rem 1 ins 1
+      ;; 04/15/'08 rem 1 unrem 1, a region always starts from the
+      ;;           top-of-mark-stack to '(point)'
+      ;;    (end-of-line arg)
+      (beginning-of-line arg)
+      (setq newmark (point)))
+    ;;(push-mark newmark t t)
+    (set-mark newmark)))
+
+;; 04/15/2008 ins function, modified from brief-mark-line
+(defun brief-mark-line-up (arg)
+  "Set mark at the end of the line.
+ARG behaves the same as `end-of-line'."
+  ;; TODO: take care of visual line mode
+  (interactive "p")
+  (let ((inhibit-message t)
+        newmark)
+    (cua-set-mark)
+    ;;(message nil)
+    (save-excursion
+      (end-of-line arg)
+      (setq newmark (1+ (point))))  ;; include EOL
+    ;;(push-mark newmark t t)
+    (set-mark newmark)))
+
+;; 04/15/2008 ins function, modified from brief-mark-line
+(defun brief-mark-line-down (arg)
+  "Set mark at the begin of the line.
+ARG behaves the same as `beginning-of-line'."
+  ;; TODO: take care of visual line mode
+  (interactive "p")
+  (let ((inhibit-message t)
+        newmark)
+    (cua-set-mark)
+    ;;(message nil)
+    (save-excursion
+      (beginning-of-line arg)
+      (setq newmark (point)))
+    ;;(push-mark newmark t t)
+    (set-mark newmark)))
+
+;;;; 04/15/'08 add function for `brief-kill-line'
+(unless (fboundp 'move-to-column)
+  (defun move-to-column (column
+                         &optional insert-white) ;; [06/12/2008] ins &optional
+    "Goto column number in current line.
+This is a backward compatibility function for older Emacs versions."
+    (let ((i 0) (max-column 0))
+      (save-mark-and-excursion
+        (end-of-line)
+        (setq max-column (current-column)))
+      (beginning-of-line)
+      (while (and (< i column) (< (current-column) column))
+        (if (= (current-column) max-column)
+            (progn
+              (if (not insert-white)    ;; [06/12/2008] ins 2
+                  (setq i (1- column))  ; set exit while condition
+                (insert " ") ;; fill with spaces
+                (setq max-column (1+ max-column))))
+          (brief-forward-1-char-noerror))
+        (setq i (1+ i))))))
+
+;;
+;; Line Oriented Commands
+;;
+
+(defvar brief-delete-entire-line-debounce nil
+  "MSoffice debouncing variable for `brief-delete-entire-line' command")
+
+(defun brief-is-visual-operation ()
+  "Test if Brief need to respect visual mode or not.
+This function implements the following truth table, according to
+current command prefix and the value of `brief-linecmd-respect-visual'.
+The basic logic are:
+ 1. `brief-linecmd-respect-visual' determines the current default mode,
+    either visual or physical line mode.
+ 2. Either a common prefix \\[universal-argument] or negative prefix
+    reverse the current mode; aka, ~`brief-linecmd-respect-visual'.
+
+         Prefix  |  brief-linecmd- || result:
+         command |  respect-visual || visual?
+        ---------+-----------------||--------
+            F    |        F        ||   F
+            F    |        T        ||   T
+          '(4)   |        F        ||   T
+          '(4)   |        T        ||   F
+        ---------+-----------------||--------
+           #n    |        F        ||   F
+           #n    |        T        ||   T
+          -#n    |        F        ||   T
+          -#n    |        T        ||   F
+
+Therefore, it's basically an XOR operation between {common prefix 
\\[universal-argument]
+or negative prefix} and {`brief-linecmd-respect-visual'}."
+
+    (brief-xor (and current-prefix-arg
+                    (or (and (numberp current-prefix-arg)
+                             (< current-prefix-arg 0))
+                        (equal current-prefix-arg '(4))))
+               brief-linecmd-respect-visual))
+
+(defun brief-move-to-column-visual (vcol)
+  "Move to visual column VCOL but not exceeding EOL."
+  (let* (p
+         (vend (save-mark-and-excursion
+                 (end-of-visual-line) ;; move to current visual line end
+                 (setq p (brief-current-column-visual))
+                 (if (not (zerop p))
+                     p
+                   (left-char 1)
+                   (brief-current-column-visual)))))
+    (right-char (- (min vcol vend) (brief-current-column-visual)))))
+
+(defun brief-delete-entire-line (arg)
+  ;; <2011-06-09 Thu 14:14> for Emacs, use 'delete' as name since it does not
+  ;; go into kill-ring
+  "Delete entire (visual) line(s) where cursor located.
+
+When a region is selected, the marked region is deleted without going
+into the kill-ring or clipboard.  Otherwise, it operates only on
+current line, which in turn considering the setting of visual mode,
+hidden texts and command prefix.
+
+When marked region is not present and `brief-linecmd-respect-visual'
+is non-nil, this command respect visual mode (line truncation, and
+hidden texts) so it only deletes the visible part of current line
+unless prefixed with a \\[universal-argument] which told this command to do 
delete
+the entire current line (or lines if hidden texts present).
+
+On the contrary, when `brief-linecmd-respect-visual' is nil (default),
+this command deletes the entire line unless prefixed with a 
\\[universal-argument] which
+told this command to respect visual mode."
+  (interactive "*p")
+
+  (let ((this-command this-command)
+        (last-command last-command)
+        (cmd-time (brief-current-time))
+        (debounce (list (point) (brief-use-region))))
+    (if (and brief-debounce-keys-microsoft-office
+             (not executing-kbd-macro)
+             brief-delete-entire-line-debounce
+             (eq this-command last-command)
+             (< (- cmd-time
+                   (car brief-delete-entire-line-debounce))
+                (* 0.02 (brief-slowdown-factor)))
+             (equal (list (point) (brief-use-region))
+                    (cadr brief-delete-entire-line-debounce)))
+        ;; Debouncing for M$ Office weird behavior, otherwise this command will
+        ;; be repeatedly invoked and cause infinite loop
+        nil
+      (if (brief-use-region)
+          (brief-delete arg)
+        (let* ((visual (brief-is-visual-operation)) ;; delete only visual part
+               (column (brief-current-column-visual)) ;; (current-column)
+               p1 p2)
+          (if (equal current-prefix-arg '(4))
+              (setq arg 1)) ;; When prefixed with C-u, ARG=4 so fix it
+          (brief-delete-region
+           ;; Use `move-beginning-of-line' or `beginning-of-visual-line' to
+           ;; bypass hidden texts '...' if we're at the end of it '...'. 
Current
+           ;; version of `beginning-of-visual-line' move to the very beginning
+           ;; of current line.  However, in order to prevent later version 
Emacs
+           ;; changing `beginning-of-visual-line' to behaves like
+           ;; `end-of-visual-line' (move to end of visual screen width end
+           ;; instead of the real line end), I choose `move-beginning-of-line'.
+           (setq p1 (if visual
+                        (beginning-of-visual-line 1)
+                      (move-beginning-of-line 1)))
+           (if (= p1 (progn
+                       (if visual
+                           (vertical-motion (abs arg))
+                         (move-beginning-of-line (1+ (abs arg))))
+                       (setq p2 (point)))) ;; are we at `eobp' ?
+               (progn (move-end-of-line 1) (point))
+             p2))
+          (if (/= p1 p2)
+              (brief-move-to-column-visual column)))))
+    (setq brief-delete-entire-line-debounce
+          (list cmd-time debounce))))
+
+(defvar brief-kill-line-debounce nil)
+
+(defun brief-kill-line (arg)
+  "Kill/cut (visual) line(s) into kill-ring and clipboard.
+Marks from point to end of the current line (honoring prefix arguments),
+copies the region to the kill ring and clipboard, and then deletes it."
+  (interactive "*p")
+
+  (let ((interprogram-cut-function nil)
+        (interprogram-paste-function nil)
+        (old-column (brief-current-column-visual)) ;; (current-column)
+        (prev-point (point))
+        (enable-cursor-tracking nil)
+        (this-command this-command)
+        (last-command last-command)
+        (visual (brief-is-visual-operation))
+        (curr-prefix-arg current-prefix-arg)
+        ;; Debouncing
+        (cmd-time (brief-current-time)))
+    (if (and brief-debounce-keys-microsoft-office
+             (not executing-kbd-macro)
+             brief-kill-line-debounce
+             (eq this-command last-command)
+             (< (- cmd-time (car brief-kill-line-debounce)) 0.3)
+             (= (point) (cadr brief-kill-line-debounce)))
+        ;; Debouncing for M$ Office weird behavior, this command will be
+        ;; repeatedly invoked and cause infinite loop
+        (brief-dbg-message (format "deboucing %S:%S"
+                                   this-command brief-kill-line-debounce))
+
+      (if (brief-use-region)
+          (let ((inhibit-message t)) ; preventing `cua-set-mark' saying "Mark 
Set"
+            (call-interactively 'cua-cut-region)
+            ;;(brief-copy-region-into-clipboard)
+            (brief-copy-to-clipboard-on-keyup))
+
+        (save-mark-and-excursion
+          ;;(cua-set-mark)
+          ;;(message nil) ; clear the "Mark Set" message due to cua-set-mark
+          (set-mark (if visual
+                        (save-mark-and-excursion
+                          ;; There could be more than one lines hidden
+                          ;; in this visual line.
+                          (beginning-of-visual-line 1))
+                      (line-beginning-position)))
+          ;;(ignore-errors ; prevent "end of buffer" error
+          ;;  ;;(next-line arg)
+          ;;  ;;(forward-line 1) does not work for org-mode hidden lines
+          ;;  ;; Use call-interactively to prevent compilation warning message
+          ;;  ;; like "Warning: `next-line' is for interactive use only; use
+          ;;  ;; `forward-line' instead."
+          ;;  (call-interactively 'next-line))
+          ;;(vertical-motion 1)
+          ;;(if (> (brief-fast-count-physical-lines prev-point (point)) 0)
+          ;;    (beginning-of-line))
+          (ignore-errors ; prevent `end-of-buffer' error
+            ;;(let ((current-prefix-arg
+            ;;       (if (and curr-prefix-arg
+            ;;                (not (equal curr-prefix-arg '(4))))
+            ;;           curr-prefix-arg ;; other prefix than C-u
+            ;;         (if visual nil
+            ;;           '(4)))))
+            ;;  (brief-next-line)) ; honor `current-prefix-arg', will jump a
+            ;;                    ;;physical line if prefixed on line wrapping
+            (if visual
+                (vertical-motion (abs arg))
+              (move-beginning-of-line (1+ (abs arg))))
+            (if (or (not visual)
+                    (= (brief-fast-count-physical-lines prev-point (point))
+                       arg)) ; physical line(s) moved
+                (beginning-of-line) ; goto column 1 of current physical line
+              (beginning-of-visual-line)))
+
+          (call-interactively 'brief-kill-region)
+          (brief-copy-to-clipboard-on-keyup)) 
;;(brief-copy-region-into-clipboard)
+        ;;(move-to-column old-column 't)
+        (brief-move-to-column-visual old-column)))
+
+    (and brief-debounce-keys-microsoft-office
+         (not executing-kbd-macro)
+         (setq brief-kill-line-debounce (list cmd-time (point))))))
+
+(defvar brief-copy-line-debounce '(0 (0 0 0)))
+
+(defun brief-copy-line (arg)
+  "Copy (visual) line(s) into kill-ring and clipboard.
+
+When a region is selected, the marked region is copy into kill-ring
+and clipboard, the mark is then deactivated.
+
+When marked region is not present and `brief-linecmd-respect-visual'
+is non-nil, this command respect visual mode (line truncation, and
+hidden texts) so it only copy the visible part of current line unless
+prefixed with a \\[universal-argument] which told this command to copy the 
entire
+physical line (or lines if hidden texts present).
+
+On the contrary, when `brief-linecmd-respect-visual' is nil (default),
+this command copy the entire line(s) unless prefixed with a 
\\[universal-argument] which
+told this command to respect visual mode and copy only visual line(s).
+
+To copy exactly 4 lines use C-4 as prefix instead of a single 
\\[universal-argument]."
+  (interactive "p")
+  (let ((fdebounce
+         ;; `flet' was obsoleted since 24.3, while older emacs don't have
+         ;; `cl-flet'.  For backward compatibility's sake we use lambda
+         ;; function here.
+         (lambda () (list (point)
+                          (brief-region-beginning)
+                          (brief-region-end)))))
+    (if (and brief-debounce-keys-microsoft-office
+             (not executing-kbd-macro)
+             brief-copy-line-debounce
+             (eq this-command last-command)
+             (< (- (brief-current-time) (car brief-copy-line-debounce)) 0.3)
+             (equal (funcall fdebounce) (cadr brief-copy-line-debounce)))
+        ;; Debouncing for MS Office clipboard behavior, this command will be
+        ;; repeatedly invoked and cause infinite loop
+        (progn
+          ;;(setq brief-copy-line-debounce
+          ;;  (cons (brief-current-time) (cadr brief-copy-line-debounce)))
+          (and brief-debounce-keys-microsoft-office
+               (not executing-kbd-macro)
+               (setq brief-copy-line-debounce
+                     (list (brief-current-time) (funcall fdebounce)))))
+
+      (let* ((interprogram-cut-function nil)
+             (interprogram-paste-function nil)
+             (prev-point (point))
+             (inhibit-message t) ; preventing `cua-set-mark' saying "Mark Set"
+             (curr-prefix-arg current-prefix-arg)
+             (is-physical-line (not (brief-is-visual-operation)))
+             ;; make `current-prefix-arg' a local variable, override the 
original
+             (current-prefix-arg current-prefix-arg))
+        ;;    (when (brief-multiple-cursor-mode-is-on)
+        ;;      (redisplay)) ;; [2017-03-13 Mon] sometimes `use-region-p'
+        ;;                   ;; supposed to be 't but is nil in multiple cursor
+        ;;                   ;; mode, not sure why so try `redisplay' here
+        (and brief-debounce-keys-microsoft-office
+             (not executing-kbd-macro)
+             (setq brief-copy-line-debounce
+                   (list (brief-current-time)
+                         (funcall fdebounce))))
+        (brief-dbg-message
+         (format "%S:%S:dbc:%S"
+                 (- (brief-current-time) (car brief-copy-line-debounce))
+                 (< (- (brief-current-time) (car brief-copy-line-debounce)) 
0.5)
+                 brief-copy-line-debounce))
+        (if (brief-use-region)
+            ;; Copy region/rectangle
+            (progn
+              (cua-copy-region nil) ;; in case using rectangle
+              ;;(copy-region-as-kill (mark) (point) 'region)
+              (brief-no-longer-need-restore-clipboard)
+              (brief-copy-to-clipboard-on-keyup))
+          ;; Copy line(s)
+          (save-mark-and-excursion
+            ;;(cua-set-mark)
+            ;;(message nil) ; clear the annoying "Mark Set" message from 
cua-set-mark
+            ;;(push-mark (line-beginning-position) t t)
+            (let (this-command ;; prevent var `this/last-command' got changed
+                  last-command)
+              (if (equal current-prefix-arg '(4))
+                  (setq arg 1)) ;; When prefixed with C-u, ARG=4 so fix it
+              (set-mark (if is-physical-line
+                            (line-beginning-position)
+                          (save-mark-and-excursion
+                            ;; There could be more than one lines abbreviated
+                            ;; in this visual line.
+                            (beginning-of-visual-line 1))))
+              (ignore-errors ; prevent `end-of-buffer' error
+                ;; (next-line arg)
+                ;; (forward-line 1) does not work for org-mode hidden lines
+                ;;(brief-next-line) ; honor `current-prefix-arg', will jump a
+                ;;                  ;;physical line if prefixed on line 
wrapping
+                (if is-physical-line
+                    (move-beginning-of-line (1+ (abs arg)))
+                  (vertical-motion (abs arg)))
+                (if (or is-physical-line
+                        (= ;; calculate physical line moved, was
+                           ;; (- (line-number) curr-line)
+                           (brief-fast-count-physical-lines prev-point (point))
+                           ;;(or (and (null curr-prefix-arg) 1) ; no prefix
+                           ;;    (and (listp curr-prefix-arg)
+                           ;;         (car curr-prefix-arg)) ;; C-<#num> 
prefixed
+                           ;;    curr-prefix-arg)
+                           arg)) ; physical line(s) moved
+                    (beginning-of-line) ; goto column 1 of current physical 
line
+                  ;; Wrap long lines
+                  ;; [2017-03-03 Fri] The earlier `brief-next-line' already
+                  ;; honored `current-prefix-arg' so we don't need the 
following
+                  ;; block of code anymore
+                  ;; (if (not (equal curr-prefix-arg '(4))) ; long line 
wrapped,
+                  ;;     ;; if a single 'C-u' prefix was pressed we copy the
+                  ;;     ;; while line instead of the visual line. To copy 
exact
+                  ;;     ;; 4 visual lines use 'C-4' as prefix instead of a 
single
+                  ;;     ;; 'C-u'
+                  ;;     (beginning-of-visual-line)
+                  ;;   (end-of-line) ; no prefix argument, we want the whole 
line
+                  ;;   ;; instead of visual line
+                  ;;   (right-char))
+                  (beginning-of-visual-line))))
+            ;; Set the overidden prefix arg to nil so that the following
+            ;; `cua-copy-region' won't be prefixed
+            (setq current-prefix-arg nil)
+            (cua-copy-region nil) ; this will insert region into `kill-ring'
+            ;;(copy-region-as-kill (mark) (point) 'region) ; this will insert
+            ;;                                      ;; region into `kill-ring'
+            (brief-no-longer-need-restore-clipboard)
+            (brief-copy-to-clipboard-on-keyup))))
+
+      ;; Clear the region after the operation is complete
+      ;; XEmacs does this automatically, Emacs doesn't.
+      (if (fboundp 'deactivate-mark)
+          (deactivate-mark)))))
+
+;;
+;; Page down/Page up
+;;
+
+(defvar brief-fixed-cursor-scroll-column)
+(defvar brief-fixed-cursor-scroll-line)
+
+(make-local-variable 'brief-fixed-cursor-scroll-column)
+(make-local-variable 'brief-fixed-cursor-scroll-line)
+
+(defmacro smooth-scroll-mode-activate ()
+  "Older Emacs need `smooth-scroll-mode' package to be able to scroll 
smoothly."
+  `(and (boundp 'smooth-scroll-mode)
+        smooth-scroll-mode))
+
+(defun brief-discard-input ()
+  "Discard inputs when doing a time consuming operation.
+If not doing so, the autorepeat key settings might cause that command to
+start again.  For example, page-down and page-up commands."
+  (or defining-kbd-macro ;; discard input will make macro definition fail
+      (discard-input)))
+
+;; Modified from the obsoleted pc-mode.el
+(defun brief-fixed-cursor-scroll-down-internal (arg)
+  "Acts like scroll-down, but leaves cursor fixed relative to window.
+Just like previous-line and forward-line, this function should not be
+used in programs."
+  (if (and arg (< arg 0))
+      (brief-fixed-cursor-scroll-up-internal (- arg))
+    (or (or (eq last-command 'brief-fixed-cursor-page-down)
+            (eq last-command 'brief-fixed-cursor-page-up))
+        (and (setq brief-fixed-cursor-scroll-column
+                   (brief-current-column-visual))
+             (setq brief-fixed-cursor-scroll-line
+                   (brief-current-row-visual))))
+    (let ((scroll-by (* (or arg 1)
+                        (1- (- (window-height)
+                               next-screen-context-lines)))))
+      (condition-case err
+          ;; <2011-06-08 Wed 18:48> modified for smooth-scroll
+          (if (= 1 (window-start))
+              (goto-char 1)
+            (if (smooth-scroll-mode-activate)
+                (smooth-scroll/orig-scroll-down scroll-by)
+              (scroll-down scroll-by))
+            (move-to-window-line brief-fixed-cursor-scroll-line)
+            (brief-move-to-column (+ (current-column)
+                                     brief-fixed-cursor-scroll-column))
+            (and (= brief-fixed-cursor-scroll-column (1- (window-width)))
+                 (null (eolp))
+                 (forward-char -1)))
+        (beginning-of-buffer
+         (progn (goto-char (point-min)) (message "Beginning of buffer")))
+        (end-of-buffer
+         (progn (goto-char (point-max)) (message "End of buffer")))
+        (error nil))
+      ;; scroll up/down is slow so for complicated file the queued pgup/pgdown
+      ;; keys will take a lot of time to process, so discard the inputs
+      (brief-discard-input))))
+
+(defun brief-fixed-cursor-scroll-up-internal (arg)
+  "Acts like scroll-up, but leaves cursor fixed relative to window.
+Just like previous-line and forward-line, this function should not
+be used in programs."
+  (if (and arg (< arg 0))
+      (brief-fixed-cursor-scroll-down-internal (- arg))
+    (or (or (eq last-command 'brief-fixed-cursor-page-down)
+            (eq last-command 'brief-fixed-cursor-page-up))
+        (and (setq brief-fixed-cursor-scroll-column
+                   (brief-current-column-visual))
+             (setq brief-fixed-cursor-scroll-line
+                   (brief-current-row-visual))))
+    (let ((scroll-by (* (or arg 1)
+                        (1- (- (window-height)
+                               next-screen-context-lines)))))
+      (condition-case err
+          (progn ;; <2011-06-08 Wed 18:48> modified for smooth-scroll
+            (if (smooth-scroll-mode-activate)
+                (smooth-scroll/orig-scroll-up scroll-by)
+              (scroll-up scroll-by))
+            (if (not (eobp)) (move-to-window-line
+                              brief-fixed-cursor-scroll-line))
+            (brief-move-to-column (+ (current-column)
+                                     brief-fixed-cursor-scroll-column))
+            (and (= brief-fixed-cursor-scroll-column (1- (window-width)))
+                 (null (eolp))
+                 (forward-char -1)))
+        (beginning-of-buffer
+         (progn (goto-char (point-min)) (message "Beginning of buffer")))
+        (end-of-buffer
+         (progn (goto-char (point-max)) (message "End of buffer")))
+        (error nil))
+      (brief-discard-input))))
+
+;; <2011-06-02 Thu 12:05> ins 2 functions
+(defun brief-fixed-cursor-page-down (arg)
+  "Scroll up a full page by going down to the next page.
+The page size is determined by the window size.  With a prefix it
+scroll several pages.  Negative prefix scrolls page in the reverse
+direction."
+  (interactive "^p")
+  (if (brief-rectangle-active)
+      (call-interactively 'cua-resize-rectangle-page-down)
+    (brief-fixed-cursor-scroll-up-internal arg)))
+
+(defun brief-fixed-cursor-page-up (arg)
+  "Scroll down a full page by going up to the previous page.
+The page size is determined by the window size.  With a prefix it
+scroll several pages.  Negative prefix scrolls page in the reverse
+direction."
+  (interactive "^p")
+  (if (brief-rectangle-active)
+      (call-interactively 'cua-resize-rectangle-page-up)
+    (brief-fixed-cursor-scroll-down-internal arg)))
+
+(defconst brief-recenter-horizontal-positions '(middle left right))
+
+(defvar-local brief-recenter-horizontal-last-op nil
+  "Indicates the last recenter operation performed.
+Possible values: `left', `middle', `right', integer or float numbers.
+It can also be nil, which means the first value in
+`brief-recenter-horizontal-positions'.")
+
+(defun brief-recenter-horizontally (&optional arg)
+  "Recenter horizontally according to ARG.
+ARG is a integer or list of a integer."
+  (set-window-hscroll
+   (selected-window)
+   (or (and (null arg)
+            (- (brief-text-unscaled-current-column)
+               (/ (window-body-width) 2)))
+       (and (listp arg) (not (null arg)) (car arg))
+       (and (integerp arg) arg)
+       (window-hscroll))))
+
+(defun brief-recenter-horizontally-left ()
+  (brief-recenter-horizontally (brief-text-unscaled-current-column)))
+
+(defun brief-recenter-horizontally-right ()
+  (brief-recenter-horizontally (max 0 (- (brief-text-unscaled-current-column)
+                                         (window-body-width)))))
+
+(defun brief-recenter-left-right (arg)
+  "Recenter cursor horizontally, like `recenter-top-bottom' does.
+Reference to `recenter-top-bottom'.  Note that it won't do anything
+if cursor position is currently at the beginning of a line."
+  (interactive "P")
+  (cond
+   (arg (brief-recenter-horizontally arg)) ; Always respect ARG.
+   (t
+    (message "Recentering horizontally to the %S."
+             (setq brief-recenter-horizontal-last-op
+                   (if (eq this-command last-command)
+                       (car
+                        (or (cdr
+                             (member
+                              brief-recenter-horizontal-last-op
+                              brief-recenter-horizontal-positions))
+                            brief-recenter-horizontal-positions))
+                     (car brief-recenter-horizontal-positions))))
+    (cond ((eq brief-recenter-horizontal-last-op 'middle)
+           (brief-recenter-horizontally))
+
+          ((eq brief-recenter-horizontal-last-op 'left)
+           (brief-recenter-horizontally-left))
+
+          ((eq brief-recenter-horizontal-last-op 'right)
+           (brief-recenter-horizontally-right))
+
+          ((integerp brief-recenter-horizontal-last-op)
+           (brief-recenter-horizontally brief-recenter-horizontal-last-op))
+
+          ((floatp brief-recenter-horizontal-last-op)
+           (brief-recenter-horizontally
+            (round (* brief-recenter-horizontal-last-op
+                      (window-body-width)))))))))
+
+(defun brief-recenter ()
+  "Recenter cursor to show contexts around.
+If `brief-search-recenter-vertically' is t, this function will
+recenter cursor vertically to show contexts above/below.
+If `brief-search-recenter-horizontally' is t and line truncation is
+ON, this will also recenter horizontally to the right side to show
+contexts left to the cursor."
+  (and brief-search-recenter-vertically
+       (not (window-minibuffer-p)) ;; no re-center in minibuffer
+       (recenter))
+  (and brief-search-recenter-horizontally
+       (or visual-line-mode
+           (not truncate-lines)
+           (brief-recenter-horizontally-right))))
+
+;;
+;; Search
+;;
+
+(defun brief-toggle-search-case-sensitivity ()
+  "Toggle case sensitivity for search or replace commands."
+  (interactive)
+  (setf case-fold-search (not case-fold-search))
+  (message (concat "Toggle search in this buffer to case-"
+                   (if case-fold-search "in") "sensitive.")))
+
+;; Search/Query&replace command type test functions
+(defun brief-is-prefix-command (cmd)
+  "Check if CMD is a prefix command."
+  (member cmd '(universal-argument      ; C-u
+                digit-argument)))       ; C-<digits>
+
+(defun brief-is-search-forward-command (cmd)
+  "Check if CMD is a forward search command."
+  (or (member cmd '(brief-search-forward
+                    brief-search-forward-currword
+                    brief-repeat-search-forward))
+      (and (eq cmd 'brief-repeat-search)
+           brief-last-search-action-forward)))
+
+(defun brief-is-search-backward-command (cmd)
+  "Check if CMD is a backward search command."
+  (or (member cmd '(brief-search-backward
+                    brief-search-backward-currword
+                    brief-repeat-search-backward))
+      (and (eq cmd 'brief-repeat-search)
+           (not brief-last-search-action-forward))))
+
+(defun brief-is-search-command (cmd)
+  "Check if CMD is a search command."
+  (or (eq cmd 'brief-repeat-search)
+      (brief-is-search-forward-command cmd)
+      (brief-is-search-backward-command cmd)
+      (eq cmd 'brief-toggle-search-case-sensitivity)))
+
+
+(defun brief-is-query-replace-forward-command (cmd)
+  "Check if CMD is a query replace forward command."
+  (or (member cmd '(brief-query-replace-forward
+                    brief-query-replace-forward-currword
+                    brief-repeat-query-replace-forward))
+      (and (eq cmd 'brief-repeat-query-replace)
+           brief-last-query-replace-forward)))
+
+(defun brief-is-query-replace-backward-command (cmd)
+  "Check if CMD is a query replace backward command."
+  (or (member cmd '(brief-query-replace-backward
+                    brief-query-replace-backward-currword
+                    brief-repeat-query-replace-backward))
+      (and (eq cmd 'brief-repeat-query-replace)
+           (not brief-last-query-replace-forward))))
+
+(defun brief-is-query-replace-command (cmd)
+  "Check if CMD is a query replace command."
+  (or (eq cmd 'brief-repeat-query-replace)
+      (brief-is-query-replace-forward-command cmd)
+      (brief-is-query-replace-backward-command cmd)))
+
+(defvar-local brief-search-overlay nil
+  "A buffer local overlay which records the current search selection.
+It is deleted when the search ends or region deactivated.")
+
+(defvar brief-hold-overlay nil
+  "A dynamically scoped temporarily variable to allow region deactivation
+not affecting the overylay.  Used by `brief-search-replace'.")
+
+(defun brief-delete-search-overlay ()
+  "Delete the search overlay when region deactivated."
+  (and (overlayp brief-search-overlay)
+       (not brief-hold-overlay)
+       (eq (overlay-buffer brief-search-overlay) (current-buffer))
+       (delete-overlay brief-search-overlay))
+  t)
+
+;;(add-hook 'deactivate-mark-hook 'brief-delete-search-overlay)
+
+;;(defvar-local brief-last-query-replace-region nil)
+(defvar-local brief-last-search-region nil ; (is-rect is-region count/beg end)
+  "This local variable records the last region/rectangle used in search.")
+
+(defun brief-undo (&optional arg)
+  "Wrapper for the default `undo' for brief specific operations.
+If we're searching in a region, this undo will restore the region."
+  (interactive "P")
+  ;; TODO: undo everything in the region (check `undo' then restore
+  ;;       the region. (Find text "Undo in region" in `undo' source)
+  (let ((was-replace nil))
+    (if (not (or (brief-is-search-command last-command)
+                 (brief-is-prefix-command last-command)
+                 (setq was-replace
+                       (brief-is-query-replace-command last-command))))
+        ;; It was not a search or query&replace command, do usual undo
+        (undo arg)
+
+      ;; It was a search or query&replace command
+
+      ;;(when (and was-replace
+      ;;           brief-last-query-replace-region)
+      ;;  (deactivate-mark)
+      ;;  (goto-char (car brief-last-query-replace-region))
+      ;;  (set-mark (mark t))
+      ;;  (goto-char (cadr brief-last-query-replace-region))
+      ;;  (setq brief-last-query-replace-region nil))
+      (setq brief-last-search-region nil) ; (is-rect is-region count/beg end)
+      (if (and (overlayp brief-search-overlay)
+               (eq (overlay-buffer brief-search-overlay) (current-buffer))
+               (overlay-start brief-search-overlay)
+               (overlay-end   brief-search-overlay))
+          ;; Line region?
+          (progn
+            ;; restore region
+            (if (brief-is-search-forward-command last-command)
+                (progn
+                  (set-mark (overlay-end brief-search-overlay))
+                  (goto-char (overlay-start brief-search-overlay)))
+              ;; was a backward search
+              (set-mark (overlay-start brief-search-overlay))
+              (goto-char (overlay-end brief-search-overlay)))
+            (delete-overlay brief-search-overlay))
+        ;; Rectangle?
+        (if (brief-rectangle-active)
+            (progn
+              (brief-keep-rectangle-unchanged)
+              (goto-char (cua--rectangle-top))
+              (move-to-column (cua--rectangle-left)))
+          ;; Neither line region nor rectangle, old undo
+          (undo arg))))))
+
+(defun brief-reset-new-search ()
+  "Reset search and delete the overlay if not continuing searching.
+For example, moving cursor around should reshape the region."
+  (unless (or (brief-is-search-command this-command)
+              (brief-is-prefix-command this-command)
+              (eq this-command 'brief-undo))
+    (setq brief-last-search-region nil)
+    (brief-delete-search-overlay)
+    (remove-hook 'pre-command-hook 'brief-reset-new-search))
+  t)
+
+(defvar-local brief-search-failed nil)
+
+(defun brief-search-complete ()
+  "Completion function for search."
+  (and (not (minibuffer-window-active-p (selected-window)))
+       (message "Search completed.")
+       (brief-recenter))
+  (setq brief-search-failed nil))
+
+(defun brief-search-failed ()
+  "Failure function for search."
+  (when (and (or (car brief-last-search-region) ;; region/rectangle search 
ended
+                 (cadr brief-last-search-region))
+             brief-search-failed)
+    ;; In order not to deactivate user's region so easily, for the first 
failure,
+    ;; we only warns; for the second failure we then deactivate the mark.  In
+    ;; this way if user insist on searching with the same pattern, the next
+    ;; search will go beyond the region and continue globally.
+    (setq brief-last-search-region nil)
+    (deactivate-mark))
+  (and (not (minibuffer-window-active-p (selected-window)))
+       (message "Pattern not found."))
+  (setq brief-search-failed t))
+
+;;
+;; Forward Search
+;;
+(defun brief-search-forward-rectangle-regexp (regexp
+                                              &optional regend noerror count)
+  "Search REGEXP forwards within current rectangle.
+If REGEND presents, the forward search does not extend beyond of REGEND.
+When repeat searching within a rectangle, the cursor will temporarily
+stopped at the searched point if found.  If we really want to set cursor
+there, press \\[keyboard-quit] to cancel the rectangle."
+  (setq count (or count 1))
+  (let* (regstart
+         (left (cua--rectangle-left))
+         (width (1+ (- (cua--rectangle-right) left)))
+         (lineend (save-mark-and-excursion ;; end point of the rectangle at
+                                           ;; current line
+                    (move-to-column (cua--rectangle-right))
+                    (min (1+ (point))
+                         (line-end-position))))
+         (cnt 0)
+         (result (catch 'found
+                   (save-mark-and-excursion
+                     ;;(goto-char (cua--rectangle-top))
+                     ;;(move-to-column left)
+                     ;;(setq lineend (+ (point) width))
+                     (while (< (point) regend)
+                       (if (search-forward-regexp
+                            regexp
+                            (min lineend
+                                 (line-end-position)
+                                 (+ (point) width))
+                            noerror 1)
+                           (and (incf cnt)
+                                (= cnt count)
+                                (throw 'found (point)))
+                         (forward-line 1)
+                         (move-to-column left)
+                         (setq lineend (+ (point) width))))
+                   nil))))
+    (and result
+         (progn
+           (brief-keep-rectangle-unchanged)
+           (goto-char result)))))
+
+;;(defvar brief-last-search-prefix-arg nil)
+
+;; Two local variables to record latest search begin/end for horizontal
+;; recentering.
+(defvar-local brief-last-search-begin  nil)
+(defvar-local brief-last-search-end    nil)
+
+(defun brief-search-forward-regexp (regexp &optional bound noerror count)
+  "Search forwards for a REGEXP.
+The search is limited in the currently marked (rectangle) region.
+Cursor will jump the match position only if the search is successful.
+The cursor jump is only temporarily when searching in a (rectangle)
+region.  To settle the cursor there, cancel the (rectangle) region."
+
+  (let* ((point      (point))
+         (is-rect    (brief-rectangle-active))
+         (is-region  (or (brief-use-region)
+                         ;; previous search was a region but happen to end up
+                         ;; having region size reduced to zero after the search
+                         ;; (the end point of region is exactly the end of the
+                         ;; search pattern)
+                         (and (cadr brief-last-search-region)
+                              (eq (region-beginning) (region-end)))))
+         (is-overlay (and brief-search-fake-region-mark
+                          (overlayp brief-search-overlay)))
+         (reg-start  (or (and is-overlay
+                              (overlay-start brief-search-overlay))
+                         (and is-rect
+                              (cua--rectangle-top))
+                         (and is-region
+                              (region-beginning))))
+         (reg-end    (or (and is-overlay
+                              (overlay-end brief-search-overlay))
+                         (and is-rect
+                              (cua--rectangle-bot))
+                         (and is-region
+                              (region-end))))
+         (new-search (and (or is-rect is-region)
+                          (brief-is-search-command this-command)
+                          (not (brief-is-search-command last-command))))
+         (result     nil))
+
+    (when new-search
+      ;; Reset `brief-search-failed' for a new search
+      (setq brief-search-failed nil)
+      (add-hook 'pre-command-hook 'brief-reset-new-search))
+
+    ;; Activate the search overlay for a region if it's not activated
+    (and is-region
+         (not is-rect)
+         new-search
+         brief-search-fake-region-mark
+         (if brief-search-overlay
+             (when (null (overlay-start brief-search-overlay))
+               (move-overlay brief-search-overlay reg-start reg-end))
+           ;; Create buffer specific overlay
+           (setq brief-search-overlay
+                 (make-overlay (point-min) (point-min)))
+           (delete-overlay brief-search-overlay)
+           (overlay-put brief-search-overlay 'face brief-fake-region-face)
+           (move-overlay brief-search-overlay reg-start reg-end)))
+
+    ;; Check if we're continuing a search within a region
+    (if (brief-is-search-forward-command last-command)
+        ;; Check if we're continuing a search within a region/rectangle
+        (if (pop brief-last-search-region)
+            ;; Previous search was in a rectangle
+            ;; (is-rect| point count ignore)
+            (progn
+              ;;(setq count (1+ (or (cadr brief-last-search-region) 1)))
+              (goto-char (pop brief-last-search-region))) ;; previous point
+          (when (pop brief-last-search-region)
+            ;; Previous search was in a region
+            ;; (is-rect| is-region| beg end)
+            (pop brief-last-search-region) ;; drop BEG
+            (goto-char (pop brief-last-search-region)) ;; END
+            ;; previous forward search stopped at the end of the pattern
+            (set-mark (point)) ; mark backwards
+            (goto-char point))))
+
+    ;; [2017-06-21 Wed] When a rectangle is at the same line, either REG-START
+    ;; and REG-END, or [2017-06-27 Tue] REG-END and `cua--rect-start-position'
+    ;; will be equal.  We therefore need to adjust REG-END otherwise the search
+    ;; will fail.
+    (if (and is-rect
+             (or (= reg-start reg-end)
+                 (= reg-end (cua--rect-start-position))))
+        (save-mark-and-excursion
+          ;; rect at the same line
+          (move-to-column (cua--rectangle-right))
+          (setq reg-end (min (1+ (point))
+                             (point-max)))))
+
+    ;; DONE [2017-06-22 Thu]: when repeatedly performing a failure search in a
+    ;;       region/rectangle means user is trying to expand current selection
+    ;;       region/rectangle via search, we need to go back to
+    ;;       `search-forward-regexp' to resize current selection (hint: keep
+    ;;       typing shift-f5 3 times when region is active and no result found)
+    ;; Note: [2014-09-15 Mon 11:36] when prefix command "ctrl-u" presents, it
+    ;; will force the search not limited in the region
+    ;;(setq brief-last-search-prefix-arg current-prefix-arg)
+    (save-mark-and-excursion
+      ;; When region active, search from the beginning of the region
+      (if new-search
+          (if is-rect
+              ;; If new search begins, goto top of rectangle
+              (progn
+                (goto-char (cua--rectangle-top))
+                (move-to-column (cua--rectangle-left)))
+            (if is-region
+                (unless (eq reg-start (point))
+                  ;; We are marking forwards, change it backwards; or the
+                  ;; region will end at the cursor and thus stop further
+                  ;; region-searching.
+                  ;;(push-mark (mark t) t t)
+                  (cua-exchange-point-and-mark nil)))))
+
+      (setq result
+            (funcall (or (and (brief-rectangle-active)
+                              'brief-search-forward-rectangle-regexp)
+                         'search-forward-regexp)
+                     (car brief-search-history)
+                     reg-end
+                     noerror count))
+      (setq point (point))) ;; save the point we find the pattern
+
+    ;; If the initial search failed, restore the region right away
+    ;; TODO: [2017-06-28 11:33:55 +0800]
+    ;;       Since we now use `save-mark-and-excursion' do we still need this??
+    ;;(when (and new-search
+    ;;           is-region
+    ;;           (not is-rect)
+    ;;           (not result)
+    ;;           ;; was not marking backwards
+    ;;           (not (eq reg-start (point))))
+    ;;  ;;(pop-mark) ;; this will deactivate overlay as well
+    ;;  ;;(set-mark (mark t))
+    ;;  (cua-exchange-point-and-mark nil))
+
+    (setq brief-last-search-region
+          (if is-rect
+              (list is-rect point count reg-end)
+            (list is-rect is-region reg-start reg-end)))
+    (setq brief-last-search-begin (match-beginning 0)
+          brief-last-search-end   (match-end 0))
+
+    (and result
+         (goto-char result)
+         (progn
+           ;;(and is-region
+           ;;     (= (region-beginning)
+           ;;        (region-end)) ;; region reduced to zero now
+           ;;     (progn ;; prevent region keep extending on next search
+           ;;       (setq brief-last-search-region nil)
+           ;;       (deactivate-mark)))
+           (ignore-errors (run-hook-with-args 'brief-after-search-hook result))
+           result))))
+
+;; added function 02/09/2006
+(defun brief-search-forward (arg)
+  "Search string/regexp forwards."
+  (interactive
+   (list
+    (if (brief-multiple-cursor-in-action)
+        brief-search-last
+      (read-string "Search forwards: " nil 'brief-search-history nil))))
+  ;;[2011-04-14 Thu 13:53] rem 1;
+  ;; (setq case-fold-search brief-global-case-fold-search)
+  (if (prog1 (brief-search-forward-regexp arg nil t)
+        ;;(prog1 (setq brief-search-forward-last
+        ;;             (car minibuffer-history)) ;; 04/03/2008 rem 1 ins 1
+        (setq brief-search-last (car brief-search-history))
+        ;;(defalias 'brief-last-search-function 'brief-search-forward)
+        (setq brief-last-search-action-forward t))
+      (brief-search-complete)
+    (brief-search-failed)
+    nil))
+
+;; added function 02/10/2006
+(defun brief-search-forward-currword (arg)
+  "Search forwards for the word that cursor is focusing on."
+  (interactive
+   (list
+    (let ((default (or (current-word) "")))
+      (if (brief-multiple-cursor-in-action)
+          (and (string= default "")
+               default)
+        (read-string "Search forwards: "
+                     default 'brief-search-history default)))))
+  ;;[2011-04-14 Thu 13:53] rem 1;
+  ;; (setq case-fold-search brief-global-case-fold-search)
+  (if (prog1 (brief-search-forward-regexp arg nil t)
+        ;;(prog1 (setq brief-search-forward-last
+        ;;       (car minibuffer-history)) ;; 04/03/2008 rem 1 ins 1
+        (setq brief-search-last (car brief-search-history))
+        ;;(defalias 'brief-last-search-function 'brief-search-forward-currword)
+        (setq brief-last-search-action-forward t))
+      (brief-search-complete)
+    (brief-search-failed)
+    nil))
+
+;;
+;; Backward Search
+;;
+
+(defun brief-search-backward-rectangle-regexp (regexp
+                                               &optional regstart noerror 
count)
+  "Search REGEXP backwards within current rectangle.
+If REGSTART presents, the backward search does not go ahead of REGSTART.
+When repeat searching within a rectangle, the cursor will temporarily
+stopped at the searched point if found.  If we really want to set
+cursor there, press \\[keyboard-quit] to cancel the rectangle."
+  (setq count (or count 1))
+  (let* ((lastline 0)
+         (right (1+ (cua--rectangle-right))) ;; 1+: including the rightmost 
char
+         (width (- right (cua--rectangle-left)))
+         (linestart (save-mark-and-excursion ;; start point of the rectangle
+                                             ;; at that line
+                      (move-to-column (cua--rectangle-left))
+                      (max (1- (point))
+                           (line-beginning-position))))
+         (cnt 0)
+         (result (catch 'found
+                   (save-mark-and-excursion
+                     (while (> (point) regstart)
+                       (if (search-backward-regexp
+                            regexp
+                            (max linestart
+                                 (line-beginning-position)
+                                 (- (point) width))
+                            noerror 1)
+                           (and (incf cnt)
+                                (= cnt count)
+                                (throw 'found (point)))
+                         (if (= lastline
+                                (progn (forward-line -1)
+                                       (setq lastline (point))))
+                             (throw 'found nil)) ; Top of file
+                         (move-to-column right)
+                         (setq linestart (- (point) width))))
+                     nil))))
+    (and result
+         (progn
+           (brief-keep-rectangle-unchanged)
+           (goto-char result)))))
+
+(defun brief-search-backward-regexp (regexp &optional bound noerror count)
+  "Search backwards for a REGEXP.
+The search is limited in the currently marked (rectangle) region.
+Cursor will jump the match position only if the search is successful.
+The cursor jump is only temporarily when searching in a (rectangle)
+region.  To settle the cursor there, cancel the (rectangle) region."
+
+  (let* ((point      (point))
+         (is-rect    (brief-rectangle-active))
+         (is-region  (or (brief-use-region)
+                         ;; previous search was a region but happen to end up
+                         ;; having region size reduced to zero after the search
+                         ;; (the end point of region is exactly the end of the
+                         ;; search pattern)
+                         (and (cadr brief-last-search-region)
+                              (eq (region-beginning) (region-end)))))
+         (is-overlay (and brief-search-fake-region-mark
+                          (overlayp brief-search-overlay)))
+         (reg-start  (or (and is-overlay
+                              (overlay-start brief-search-overlay))
+                         (and is-rect
+                              (cua--rectangle-top))
+                         (and is-region
+                              (region-beginning))))
+         (reg-end    (or (and is-overlay
+                              (overlay-end brief-search-overlay))
+                         (and is-rect
+                              (cua--rectangle-bot))
+                         (and is-region
+                              (region-end))))
+         (new-search (and (or is-rect is-region)
+                          (brief-is-search-command this-command)
+                          (not (brief-is-search-command last-command))))
+         (result     nil))
+
+    (when new-search
+      ;; Reset `brief-search-failed' for a new search
+      (setq brief-search-failed nil)
+      (add-hook 'pre-command-hook 'brief-reset-new-search))
+
+    ;; Activate the search overlay for a region if it's not activated
+    (and is-region
+         (not is-rect)
+         new-search
+         brief-search-fake-region-mark
+         (if brief-search-overlay
+             (when (null (overlay-start brief-search-overlay))
+               (move-overlay brief-search-overlay reg-start reg-end))
+           ;; Create buffer specific overlay
+           (setq brief-search-overlay
+                 (make-overlay (point-min) (point-min)))
+           (delete-overlay brief-search-overlay)
+           (overlay-put brief-search-overlay 'face brief-fake-region-face)
+           (move-overlay brief-search-overlay reg-start reg-end)))
+
+    ;; Check if we're continuing a search within a region
+    (if (brief-is-search-forward-command last-command)
+        ;; Check if we're continuing a search within a region/rectangle
+        (if (pop brief-last-search-region)
+            ;; Previous search was in a rectangle
+            ;; (is-rect| point count ignore)
+            (progn
+              ;;(setq count (1+ (or (cadr brief-last-search-region) 1)))
+              (goto-char (pop brief-last-search-region))) ;; previous point
+          (when (pop brief-last-search-region)
+            ;; Previous search was in a region
+            ;; (is-rect| is-region| beg end)
+            (goto-char (pop brief-last-search-region)) ; BEG
+            ;; previous backward search stopped at the beginning of the pattern
+            (set-mark (point)) ; mark forwards
+            (goto-char point))))
+
+    ;; [2017-06-21 Wed] When a rectangle is at the same line, either REG-START
+    ;; and REG-END, or [2017-06-27 Tue] REG-END and `cua--rect-start-position'
+    ;; will be equal.  We therefore need to adjust REG-START otherwise the 
search
+    ;; will fail.
+    (if (and is-rect
+             (or (= reg-start reg-end)
+                 (= reg-end (cua--rect-start-position))))
+        (save-mark-and-excursion
+          ;; rect at the same line
+          (move-to-column (cua--rectangle-left))
+          (setq reg-start (point))))
+
+    (save-mark-and-excursion
+      ;; When region active, search from the end of the region
+      (if new-search
+          ;; If new search begins, goto end of rectangle
+          (if is-rect
+              ;; If new search begins, goto end of rectangle
+              (progn
+                (goto-char (cua--rectangle-bot))
+                ;; need to plus one or we'll miss the pattern if it's at the
+                ;; end of rectangle
+                (move-to-column (1+ (cua--rectangle-right))))
+            (if is-region
+                (unless (eq reg-end (point))
+                  ;; We are marking backwards, change it forwards; or the
+                  ;; region will end at the cursor and thus stop further
+                  ;; region-searching.
+                  ;;(push-mark (mark t) t t)
+                  (cua-exchange-point-and-mark nil)))))
+
+      (setq result
+            (funcall (or (and (brief-rectangle-active)
+                              'brief-search-backward-rectangle-regexp)
+                         'search-backward-regexp)
+                     (car brief-search-history)
+                     reg-start
+                     noerror count))
+      (setq point (point))) ;; save the point we find the pattern
+
+    ;; If the initial search failed, restore the region right away
+    ;; TODO: [2017-06-28 11:35:28 +0800]
+    ;;     After we used `save-mark-and-excursion', do we still need this??
+    ;;(when (and new-search
+    ;;           is-region
+    ;;           (not is-rect)
+    ;;           (not result)
+    ;;           ;; was not marking forwards
+    ;;           (not (eq reg-end (point))))
+    ;;  (pop-mark) ;; this will deactivate overlay as well
+    ;;  (set-mark (mark t)))
+
+    (setq brief-last-search-region
+          (if is-rect
+              (list is-rect point count reg-end)
+            (list is-rect is-region reg-start reg-end)))
+    (setq brief-last-search-begin (match-beginning 0)
+          brief-last-search-end   (match-end 0))
+
+    (and result
+         (goto-char result)
+         (progn
+           ;;(and is-region
+           ;;     (= (region-beginning)
+           ;;        (region-end)) ;; region reduced to zero now
+           ;;     (progn ;; prevent region keep extending on next search
+           ;;       (setq brief-last-search-region nil)
+           ;;       (deactivate-mark)))
+           (ignore-errors (run-hook-with-args 'brief-after-search-hook result))
+           result))))
+
+;; added function 02/09/2006
+(defun brief-search-backward (arg)
+  "Search string/regexp backwards."
+  (interactive
+   (list
+    (if (brief-multiple-cursor-in-action)
+        brief-search-last
+      (read-string "Search backwards: " nil 'brief-search-history nil))))
+  ;;[2011-04-14 Thu 13:53] rem 1
+  ;; (setq case-fold-search brief-global-case-fold-search)
+  (if (prog1 (brief-search-backward-regexp arg nil t)
+        ;;(prog1 (setq brief-search-backward-last
+        ;;             (car minibuffer-history)) ;; 04/03/2008 rem 1 ins 1
+        (prog1 (setq brief-search-last (car brief-search-history))
+          ;;(defalias 'brief-last-search-function 'brief-search-backward)
+          (setq brief-last-search-action-forward nil)))
+      (brief-search-complete)
+    (brief-search-failed)
+    nil))
+
+;; added function 02/10/2006
+(defun brief-search-backward-currword (arg)
+  "Search backwards for the word that the cursor is focusing on."
+  (interactive
+   (list
+    (let ((default (or (current-word) "")))
+      (if (brief-multiple-cursor-in-action)
+          (and (string= default "")
+               default)
+        (read-string "Search backwards: "
+                     default 'brief-search-history default)))))
+  ;;[2011-04-14 Thu 13:53] rem 1
+  ;; (setq case-fold-search brief-global-case-fold-search)
+  (if (prog1 (brief-search-backward-regexp arg nil t)
+        ;;(prog1 (setq brief-search-backward-last
+        ;;             (car minibuffer-history)) ;; 04/03/2008 rem 1 ins 1
+        (setq brief-search-last (car brief-search-history))
+        ;;(defalias 'brief-last-search-function 
'brief-search-backward-currword)
+        (setq brief-last-search-action-forward nil))
+      (brief-search-complete)
+    (brief-search-failed)
+    nil))
+
+;; added 03/09/2006
+(defun brief-repeat-search ()
+  "Repeat the most recent forward/backward search command.
+Notice that if the latest search command is prefixed with a prefix
+command (\\[universal-argument]), it is also repeated."
+  (interactive "")
+  (let* ((current-prefix-arg current-prefix-arg))
+    (if brief-search-last
+        (if brief-last-search-action-forward
+            (brief-search-forward brief-search-last)
+          (brief-search-backward brief-search-last))
+      (call-interactively (if brief-last-search-action-forward
+                              'brief-search-forward
+                            'brief-search-backward)))))
+
+(defun brief-repeat-search-forward ()
+  "Repeat the latest search operation but change direction forwards."
+  (interactive "")
+  (setq brief-last-search-action-forward t)
+  (brief-repeat-search))
+
+(defun brief-repeat-search-backward ()
+  "Repeat the latest search operation but change direction backwards."
+  (interactive "")
+  (setq brief-last-search-action-forward nil)
+  (brief-repeat-search))
+
+(defvar brief-query-replace-automatic-keys nil)
+(defvar brief-query-replace-quit-keys nil)
+
+(eval-after-load 'replace
+  '(progn
+     (map-keymap (lambda (ev bind)
+                   (if (or (eq bind 'automatic)
+                           (eq bind 'automatic-all))
+                       (push ev brief-query-replace-automatic-keys)))
+                 query-replace-map)
+     (map-keymap (lambda (ev bind)
+                   (if (eq bind 'exit)
+                       (push ev brief-query-replace-quit-keys)))
+                 query-replace-map)))
+
+;;;(defalias query-replace brief-query-replace)
+(defun brief-query-replace-rectangle-regexp (regexp to
+                                             &optional delimited start end)
+  "Backward compatibility function for Emacs version < 25.1."
+  ;;(save-excursion ;; `apply-on-rectangle' already did this
+  (let* ((message-list nil)
+         (replace-count 0)
+         (result
+          (catch 'break
+            (apply-on-rectangle
+             (lambda (startcol endcol regexp to)
+               (move-to-column startcol)
+               (let ((last-key (aref (this-command-keys)
+                                     (1- (length (this-command-keys))))))
+                 (if (memq last-key brief-query-replace-quit-keys)
+                     (throw 'break nil)
+                   (funcall (or
+                             (and
+                              (memq last-key
+                                    brief-query-replace-automatic-keys)
+                              'replace-regexp) ; No query, go through all lines
+                             'query-replace-regexp) ;; Query one by one
+                            regexp to nil
+                            (point)
+                            (min (line-end-position)
+                                 ;; Not safe so comment it out, since cua
+                                 ;; rectangle might not be compatible with
+                                 ;; simple rect.
+                                 ;;(+ 1 (point) (- endcol startcol)))))))
+                                 (+ 1 (point) (- (cua--rectangle-right)
+                                                 (cua--rectangle-left)))))
+                   ;; For later calculating how many "Replaced #n 
occurrence(s)"
+                   (push (current-message) message-list))))
+             start end regexp to))))
+    (dolist (m message-list)
+      ;; TODO: if `preform-replace' change the following text message,
+      ;; the following need to be changed as well.
+      ;; TODO: also parse the remaining "(skip ...)" in the message string
+      (and (string-match "Replaced \\([0-9]+\\) occurrence" m)
+           (setq replace-count (+ replace-count (string-to-number
+                                                 (match-string 1 m))))))
+    (message "Replaced %d occurrence%s"
+             replace-count
+             (if (= replace-count 1) "" "s"))
+    result))
+
+(defun brief-query-replace-regexp (regexp to-string
+                                          &optional delimited start end 
backward)
+  "Backward compatibility function for Emacs version < 25.1."
+  (let ((reg-start (or (and (brief-rectangle-active)
+                            (cua--rectangle-top))
+                       (and (brief-use-region)
+                            (region-beginning))))
+        (reg-end   (or (and (brief-rectangle-active)
+                            (cua--rectangle-bot))
+                       (and (brief-use-region)
+                            (region-end))))
+        (undo-len  (and brief-group-undo-replacement
+                        (length buffer-undo-list)))
+        undo-before)
+    ;;(and
+    (funcall (or (and ;;(brief-use-region)
+                      (brief-rectangle-active)
+                      'brief-query-replace-rectangle-regexp)
+                 'query-replace-regexp)
+             (car brief-query-replace-from-history)
+             (car brief-query-replace-to-history)
+             nil reg-start reg-end)
+    ;;(brief-recenter)) ;; recenter after replacements is a bit weird so 
comment
+    ;;                  ;; it out.
+    ;;(when brief-group-undo-replacement
+    ;;  (setq undo-before (last buffer-undo-list undo-len))
+    ;;  (if (car undo-before) ;; delimit the original undo list with 'nil'
+    ;;      (push nil undo-before))
+    ;;  (setq buffer-undo-list
+    ;;        (append ;; `nconc' seems to cause unknown problems here, some
+    ;;                ;; pointers must be corrupted
+    ;;         '(nil)
+    ;;         (delq nil ;; remove the undo boundary in the undo-after list
+    ;;               (butlast buffer-undo-list undo-len))
+    ;;         undo-before)))
+    ))
+
+(defun brief-query-replace (&optional from to)
+  "Query and replace pattern forwards.
+If a marked (rectangle) region is active, the search and replacement
+will be restricted within the (rectangle) region."
+  (interactive "*")
+  (let* ((point       (point))
+         (is-rect     (brief-rectangle-active))
+         ;;(use-empty-active-region nil)
+         (is-region   (brief-use-region))
+         (reg-start   (or (and is-rect
+                               (cua--rectangle-top))
+                          (and is-region
+                               (region-beginning))))
+         (reg-end     (or (and is-rect
+                               (cua--rectangle-bot))
+                          (and is-region
+                               (region-end))))
+         ;; Reference to `cua--deactivate-rectangle' for the format
+         ;; of `cua--last-rectangle'
+         (rect        (and is-rect
+                           (cons (current-buffer)
+                                 (cons (point)
+                                       cua--rectangle))))
+         ;;(backward    (< (prefix-numeric-value current-prefix-arg) 0))
+         (undo-len    (and brief-group-undo-replacement
+                           (length buffer-undo-list)))
+         (undo-before nil)
+         ;; query&replace might change these, if `undo' was done
+         (last-command last-command)
+         (this-command this-command)
+         (brief-hold-overlay t)
+         (justquit    nil)
+         (result      nil))
+
+    (when is-region
+      ;;(setq brief-last-query-replace-region (list (mark) point))
+      (push-mark (mark t) t t)
+      (and (not is-rect)
+           brief-search-fake-region-mark
+           (if brief-search-overlay
+               (when (null (overlay-start brief-search-overlay))
+                 (move-overlay brief-search-overlay reg-start reg-end))
+             ;; Create buffer specific overlay
+             (setq brief-search-overlay
+                   (make-overlay (point-min) (point-min)))
+             (delete-overlay brief-search-overlay)
+             (overlay-put brief-search-overlay 'face brief-fake-region-face)
+             (move-overlay brief-search-overlay reg-start reg-end))))
+
+    (save-mark-and-excursion
+      (condition-case err
+          ;; Catch 'quit signal
+          (progn
+            (when is-rect
+              ;; Always move to corner 3 first (bottom/right)
+              ;; (refernece to `cua--rectangle-set-corners'
+              (goto-char (cua--rectangle-top))
+              (move-to-column (cua--rectangle-left))
+              (set-mark (point))
+              (setq reg-start (point))
+              (goto-char (cua--rectangle-bot))
+              ;; Need to plus one or we'll miss the pattern, if it's
+              ;; right at the right-bottom end of the rectangle.
+              ;; Is this `query-replace' bug when operating in rectangle?
+              (move-to-column (1+ (cua--rectangle-right)))
+              (setq reg-end (point)))
+            (setq result
+                  (if (not (version< emacs-version "25.1"))
+                      ;; Emacs 25.1 and above
+                      (if (and from to)
+                          (query-replace-regexp from to nil
+                                                reg-start reg-end
+                                                (> 0 (prefix-numeric-value
+                                                      current-prefix-arg))
+                                                is-rect)
+                        (call-interactively 'query-replace-regexp))
+
+                    ;; Emacs version below 25.1, no backward replacement
+                    ;; supported here.
+                    (let ((default
+                            (car (symbol-value
+                                  query-replace-from-history-variable))))
+                      (unless (and from to)
+                        (unless
+                            (string=
+                             ""
+                             (read-string (format "Query replace: ")
+                                          default
+                                          query-replace-from-history-variable
+                                          default))
+                          (setq default
+                                (car (symbol-value
+                                      query-replace-to-history-variable)))
+                          (read-string
+                           (format "Query replace %s with: "
+                                   (car (symbol-value
+                                         query-replace-from-history-variable)))
+                           default
+                           query-replace-to-history-variable
+                           nil)))
+                      (brief-query-replace-regexp
+                       (car (symbol-value query-replace-from-history-variable))
+                       (car (symbol-value query-replace-to-history-variable)))
+                      ;; Remove the just-pushed empty string if in the
+                      ;; `query-replace-from-history'
+                      (if (string= ""
+                                   (car (symbol-value
+                                         query-replace-from-history-variable)))
+                          (set query-replace-from-history-variable
+                               (cdr (symbol-value
+                                     query-replace-from-history-variable))))
+                      )) ))
+        ;; Take care of 'quit signal
+        ;; Quit signal will cancel the (rectangle) region operation and keep
+        ;; cursor at the current position
+        (quit (progn
+                (setq justquit t
+                      point (point))))))
+
+    ;; Restore the (rectangle) region if not quit
+    (when is-region
+      (pop-mark)
+      ;; This `pop-mark' won't deactivate the overlay as `brief-hold-overlay'
+      ;; is still 't, in case we immediately reactivate the region which
+      ;; cause the region background flickers (turn off and immediately on).
+
+      (if justquit ;; quit?
+          (goto-char point)
+        ;; Reactivate mark if not quitting
+        (set-mark (mark t)))
+
+      ;; If we don't set `deactivate-mark' as nil in the end, we
+      ;; will need this. Or if we did 'undo' during `query-replace',
+      ;; we will also need to restore rectangle here.
+      ;; To detect if we just 'undid', test if `this-command' is 'mode-exited.
+      (when (and is-rect
+                 (eq this-command 'mode-exited)) ;; undo?
+        ;; Reactivate rectangle
+        (setq cua--last-rectangle rect)
+        (cua--activate-rectangle) ;;(cua-set-rectangle-mark t)
+        (brief-keep-rectangle-unchanged))
+
+      ;; Remove overlay after the region is re-activated, to prevent
+      ;; region background flicker
+      (setq brief-hold-overlay nil)
+      (brief-delete-search-overlay))
+
+    ;; Group undo records in a replacement, remove boundaries within the list
+    (when brief-group-undo-replacement
+      (setq undo-before (last buffer-undo-list undo-len))
+      (if (car undo-before) ;; delimit the original undo list with 'nil'
+          (push nil undo-before))
+      (setq buffer-undo-list
+            (append ;; `nconc' seems to cause unknown problems here, some
+                    ;; pointers must be corrupted
+             '(nil)
+             (delq nil ;; remove the undo boundary in the undo-after list
+                   (butlast buffer-undo-list undo-len))
+             undo-before)))
+
+    ;; prevent existing mark from being deactivated
+    (setq deactivate-mark nil)
+    result))
+
+(defun brief-query-replace-forward ()
+  "Query and replace pattern forwards.
+Perform `brief-query-replace' in forward direction."
+  (interactive "*")
+  (setq brief-last-query-replace-forward t)
+  (call-interactively 'brief-query-replace))
+
+(defun brief-query-replace-backward ()
+  "Query and replace pattern backwards.
+Perform `brief-query-replace' in backward direction."
+  (interactive "*")
+  (let ((current-prefix-arg '-))
+    (setq brief-last-query-replace-forward nil)
+    (brief-query-replace current-prefix-arg)))
+
+(defun brief-query-prompt ()
+  (concat "Query replace"
+          (if (< (prefix-numeric-value current-prefix-arg) 0)
+              " backward" " word")
+          (if (brief-use-region) " in region" "")))
+
+(defun brief-repeat-query-replace ()
+  "Repeat the latest query and replacement operation."
+  (interactive "*")
+  (if (eq (symbol-value query-replace-from-history-variable) nil)
+      ;; no previous 'from', make query for both 'from' and 'to'
+      (call-interactively 'brief-query-replace)
+    (if (eq (symbol-value query-replace-to-history-variable) nil)
+        ;; no previous 'to', make query for 'to'
+        (query-replace-read-to
+         (car (symbol-value query-replace-from-history-variable))
+         (brief-query-prompt) t))
+    (brief-query-replace
+     (car (symbol-value query-replace-from-history-variable))
+     (car (symbol-value query-replace-to-history-variable)))
+    ;;(setf deactivate-mark nil)
+    ))
+
+(defun brief-repeat-query-replace-forward ()
+  "Repeat the latest query and replacement operation forwards."
+  (interactive "*")
+  (let ((current-prefix-arg nil))
+    (setq brief-last-query-replace-forward t)
+    (call-interactively 'brief-repeat-query-replace)))
+
+(defun brief-repeat-query-replace-backward ()
+  "Repeat the latest query and replacement operation backwards."
+  (interactive "*")
+  (let ((current-prefix-arg '-))
+    (setq brief-last-query-replace-forward nil)
+    (call-interactively 'brief-repeat-query-replace)))
+
+(defun brief-query-replace-forward-currword ()
+  "Query and replace current word in forward direction."
+  (interactive "*")
+  ;; Don't set `brief-last-query-replace-forward' as 't in this function as 
this
+  ;; function is also called by `brief-query-replace-backward-currword'. Set
+  ;; that variable by `brief-query-replace' function.
+  (let ((default (current-word)))
+    (if (or (null default)
+            (string= "" default))
+        (call-interactively 'brief-query-replace)
+      ;; push current word into 'from' history if it's not in the head
+      (unless (string= default
+                       (car (symbol-value 
query-replace-from-history-variable)))
+        (set query-replace-from-history-variable
+             (cons default (symbol-value 
query-replace-from-history-variable))))
+      (query-replace-read-to default (brief-query-prompt) t)
+      (brief-query-replace
+       (car (symbol-value query-replace-from-history-variable))
+       (car (symbol-value query-replace-to-history-variable))))))
+
+(defun brief-query-replace-backward-currword ()
+  "Query and replace current word in backward direction."
+  (interactive "*")
+  (let ((current-prefix-arg '-))
+    (call-interactively 'brief-query-replace-forward-currword)))
+
+(defun brief-delete (arg)
+  "Delete marked region/rectangle or delete a char"
+  (interactive "*p")
+  (if (brief-use-region)
+      ;; <2011-06-02 Thu 15:24> Fix for Emacs 23
+      (progn
+        (if (brief-line-region-active) ;; for Emacs
+            (call-interactively 'cua-delete-region)
+          (if (fboundp 'cua-delete-rectangle) ;; it does not exist in Emacs 
24.3
+              (call-interactively 'cua-delete-rectangle)
+            (call-interactively 'cua-delete-region)))
+        (brief-restore-clipboard-selection))
+    (brief-delete-char arg)))
+
+(defun brief-forward-word (&optional arg)
+  "New implementation of `forward-word' which won't be that greedy."
+  (interactive "^p")
+  (ignore-errors ;; prevent begin of buffer or end of buffer
+    (if (< arg 0)
+        (let ((currsyn (char-syntax (char-before)))
+              (iswhite (char-syntax ?\t )))
+          (ignore-errors
+            (loop for i from arg to -1 by 1 do
+                  (while (= (char-syntax (char-before)) iswhite)
+                    (backward-char))
+                  (while (= (char-syntax (char-before)) currsyn)
+                    (backward-char)))))
+      (let ((currsyn (char-syntax (char-after)))
+            (iswhite (char-syntax ?\t )))
+        (ignore-errors
+          (loop for i downfrom (or arg 1) to 1 by 1 do
+                (while (= (char-syntax (char-after)) currsyn)
+                  (forward-char))
+                (while (= (char-syntax (char-after)) iswhite)
+                  (forward-char)))))))
+  t)
+
+(defun brief-backward-word (&optional arg)
+  "New implementation of `backward-word' which is not as greedy."
+  (interactive "^p")
+  (brief-forward-word (- (or arg 1))))
+
+;; <2011-06-14 Tue 16:51> modified from XEmacs simple.el 'kill-word'
+(defun brief-delete-word (&optional count)
+  "Delete characters forward until encountering the end of a word.
+With optional argument COUNT, do this that many times."
+  (interactive "*p")
+  (brief-delete-region (point) (save-mark-and-excursion
+                                 (brief-forward-word count) (point))))
+
+;; <2011-06-14 Tue 18:05> modified from XEmacs simple.el 'backward-kill-word'
+(defun brief-backward-delete-word (&optional count)
+  "Delete characters backward until encountering the end of a word.
+With argument, do this that many times."
+  (interactive "*p")
+  (brief-delete-word (- (or count 1))))
+
+(defun brief-delete-end-of-line (arg)
+  "Delete characters till end of current (visual) line(s).
+
+The deleted texts does not go into the kill-ring or clipboard.  If
+that is expected use the cut-line command (\\[brief-kill-line]) instead.  Mark
+the texts then do \\[brief-kill-line].
+
+When `brief-linecmd-respect-visual' is non-nil, this command respect
+visual mode, which means it delete texts till end of visual line,
+unless prefixed with \\[universal-argument] which will delete texts till the 
end
+of a physical line.
+
+On the otherhand, when `brief-linecmd-respect-visual' is nil, this
+command delete texts till the end of a physical line unless prefixed
+with \\[universal-argument] which will delete texts till the end of visual 
line."
+  (interactive "*P")
+  (brief-delete-region
+   (point)
+   (if (and (or (null truncate-lines)
+                visual-line-mode)
+            (brief-is-visual-operation))
+       (progn (end-of-visual-line 1) (point))
+     (progn (move-end-of-line 1)
+            (point))))) ;; bypass the hidden texts ('...') if there is
+
+;; [06/02/'08] rem 2 func, ins 1 func.
+;; No more checking for is-cc-mode. Tab always refer to indent region when
+;; region is active
+;;(defun brief-is-cc-mode () ;; [07/11/2007] add
+;;  (or (string= mode-name "C")
+;;      (string= mode-name "C++")
+;;      (string= mode-name "C++/l")))
+
+(defun brief-indent-tab (arg)
+  "Indent the region if marked, otherwise insert a normal TAB character.
+When in minibuffer it will do completion unless prefixed with 
\\[universal-argument]."
+  (interactive "*p")
+  (if (and (window-minibuffer-p)
+           (null current-prefix-arg))
+      ;;(call-interactively 'minibuffer-complete)
+      (completion-at-point)
+    (if (brief-use-region)
+        (progn
+          (call-interactively 'indent-region)
+          (brief-restore-clipboard-selection))
+      (indent-for-tab-command))))
+
+(defun brief-goto-xy (x y)  ;; [06/12/2008] ins 1 func
+  ;;  (goto-line y)
+  (goto-char (point-min))
+  (forward-line (1- y)) ;; <2011-06-09 Thu 14:56> for emacs, according to the
+  ;;           ;; help page of 'goto-line' : "not to use 'goto-line' directly"
+  (move-to-column x))
+
+;; TODO: rewrite this ugly function, remove `brief-goto-xy'
+(defun brief-indent-buffer ()
+  "Indent and untabify the whole buffer."
+  (interactive "*")
+  (let ((x (current-column))
+        (y (line-number-at-pos))
+        reg-min reg-min-x reg-min-y
+        reg-max reg-max-x reg-max-y)
+    (message "Indenting & untabifying ...")
+    (if (brief-use-region)
+        (progn
+          (setq reg-min (region-beginning) reg-max (region-end))
+          (goto-char reg-min)
+          (setq reg-min-x (current-column) reg-min-y (line-number-at-pos))
+          (goto-char reg-max)
+          (setq reg-max-x (current-column) reg-max-y (line-number-at-pos))
+          (indent-region reg-min reg-max nil)
+          (brief-goto-xy reg-min-x reg-min-y)
+          (setq reg-min (point))
+          (brief-goto-xy reg-max-x reg-max-y)
+          (setq reg-max (point))
+          (untabify reg-min reg-max)
+          (if (= y reg-min-y)
+              (brief-goto-xy reg-max-x reg-max-y)
+            (brief-goto-xy reg-min-x reg-min-y))
+          (push-mark (point) t t))
+      (indent-region (point-min) (point-max) nil)
+      (untabify (point-min) (point-max)))
+    (message ;; <2011-06-09 Thu 14:56> add done message
+     "Indenting & untabifying ... done")
+    (brief-goto-xy x y)))
+
+;;;; <2010-07-21 Wed 11:25> add
+;;(defun is-gdb-doing-trace ()
+;;  (if (boundp 'gdb-arrow-extent)
+;;      (eval '(and (not (equal gdb-arrow-extent nil))
+;;                  (equal (extent-object gdb-arrow-extent) (current-buffer))))
+;;    nil))
+
+;;
+;; Brief mode macro commands
+;;
+
+(defun brief-define-macro (arg)
+  "Start defining a keyboard macro. Press another (\\[brief-define-macro]) to 
end defining."
+  (interactive "p")
+  (call-interactively (if defining-kbd-macro
+                          'end-kbd-macro
+                        'start-kbd-macro)))
+
+;; <2010-07-21 Wed 11:57> added
+(defun brief-call-last-kbd-macro (arg)
+  "Run the latest defined keyboard macro."
+  (interactive "p")
+  ;; (if (is-gdb-doing-trace)
+  ;;     (progn (switch-to-buffer-other-window
+  ;;             (eval 'current-gdb-buffer)) ;;; <2010-07-22 Thu 11:23> ins 1
+  ;;            (call-interactively 'gdb-next))
+  (let ((oldlen (length buffer-undo-list))
+        newhead item count)
+    (call-interactively 'call-last-kbd-macro)
+    ;; Trim off undo boundaries inserted in the last macro
+    (setq count (- (length buffer-undo-list) oldlen))
+    (while (> count 0)
+      (setq item (pop buffer-undo-list))
+      (or (null item)
+          (push item newhead))
+      (setq count (1- count)))
+    (setq buffer-undo-list (append (nreverse newhead) buffer-undo-list))
+    (or (car buffer-undo-list)
+        (push nil buffer-undo-list))))
+
+(defun brief-save-kbd-macro (arg)
+  "Save last keyboard macro into a file"
+  (interactive (or (and last-kbd-macro
+                        (call-interactively
+                         '(lambda (filename)
+                            (interactive
+                             "GSave current keyboard macro to file : ")
+                            (list filename))))
+                   (error
+                    "Keyboard macro not defined yet, press <f7> to define 
one.")))
+  (if (eq t ;; is a directory, i.e. no filename inputed
+          (car (file-attributes arg)))
+      (error "No file name specified.")
+    (with-temp-buffer
+      (insert-kbd-macro (intern ""))
+      (ignore-errors
+        (write-file arg t)
+        t))))
+
+(defun brief-load-kbd-macro (arg)
+  "Load keyboard macro from a file"
+  (interactive "fLoading keyboard macro file : ")
+  (save-current-buffer
+    (and (find-file arg "*.kbm")
+         (or (eval-buffer) t)
+         (kill-buffer)
+         (message (format "Keyboard macro file \"%s\" loaded" arg)))))
+
+;; [06/17/2008] commented out, no need, <alt>-<left> and <alt>-<right> servers
+;; for left/right paren searching.
+;;;; added, modified from 'simple.el'
+;;(defun brief-matching-open ()
+;;  "Move cursor to the beginning of the sexp before point."
+;;  (interactive)
+;;  (and (> (point) (1+ (point-min)))
+;;       blink-matching-paren
+;;       ;; Verify an even number of quoting characters precede the close.
+;;       (= 1 (logand 1 (- (point)
+;;                         (save-excursion
+;;                           (forward-char -1)
+;;                           (skip-syntax-backward "/\\")
+;;                           (point)))))
+;;       (let* ((oldpos (point))
+;;              (blinkpos)
+;;              (mismatch))
+;;         (save-restriction
+;;           (if blink-matching-paren-distance
+;;               (narrow-to-region
+;;                (max (point-min)
+;;                     (- (point) blink-matching-paren-distance))
+;;                oldpos))
+;;           (condition-case ()
+;;               (let ((parse-sexp-ignore-comments
+;;                      (and parse-sexp-ignore-comments
+;;                           (not blink-matching-paren-dont-ignore-comments))))
+;;                 (setq blinkpos (scan-sexps oldpos -1)))
+;;             (error nil)))
+;;         (and blinkpos
+;;              (/= (char-syntax (char-after blinkpos))
+;;                  ?\$)
+;;              (setq mismatch
+;;                    (or (null (matching-paren (char-after blinkpos)))
+;;                        (/= (char-after (1- oldpos))
+;;                            (matching-paren (char-after blinkpos))))))
+;;         (if mismatch (setq blinkpos nil))
+;;         (if blinkpos
+;;             ;; Don't log messages about paren matching.
+;;             (let () ;;(message-log-max) [07/11/2007] remove from varlist
+;;               (goto-char blinkpos)
+;;               (if (pos-visible-in-window-p)
+;;                   (and blink-matching-paren-on-screen
+;;                        (sit-for blink-matching-delay))
+;;                 (goto-char blinkpos)))
+;;           (cond (mismatch
+;;                  (message "Mismatched parentheses"))
+;;                 ((not blink-matching-paren-distance)
+;;                  (message "Unmatched parenthesis")))))))
+
+(defvar brief-last-last-command nil
+  "The previous value of `last-command'.")
+
+(defvar brief-last-3rd-command nil
+  "The previous value of `brief-last-last-command'.")
+
+(defun brief-home (arg)
+  "\"Home\" the cursor the way that Brief editor do it.
+
+When `visual-line-mode' is nil and `truncate-lines' is non-nil, the
+first \\[brief-home] moves point to beginning of the line.
+Second consecutive \\[brief-home] moves point to top of the screen.
+Third consecutive \\[brief-home] moves point to the beginning of the buffer.
+
+When `visual-line-mode' is non-nil or `truncate-lines' is nil, the first
+\\[brief-home] goes to the beginning of visible line and the second 
\\[brief-home] then
+goes to the physical beginning of line.  Consecutive 3rd and 4th 
\\[brief-home]s
+then goes to the top of screen and beginning of buffer."
+  (interactive "^p")
+  (let ((home4  (eq brief-last-3rd-command  'brief-home))
+        (home3  (eq brief-last-last-command 'brief-home))
+        (home2  (eq last-command            'brief-home)))
+    (cond
+     ;; 4th press
+     ((and home4 home3 home2)
+      (goto-char (point-min)))
+     ;; 3rd press
+     ((and home3 home2)
+      (if truncate-lines
+          (goto-char (point-min))
+        (let ((p1 (save-mark-and-excursion (beginning-of-line) (point)))
+              (p2 (window-start)))
+          (goto-char (if (/= p1 p2)
+                         (min p1 p2)
+                       (point-min))))))
+     ;; 2nd press
+     (home2
+      (if truncate-lines
+          (move-to-window-line 0)
+        (let ((p1 (save-mark-and-excursion (beginning-of-line) (point)))
+              (p2 (window-start)))
+          (goto-char (if (/= (point) (max p1 p2))
+                         (max p1 p2)
+                       (min p1 p2)))))) ;; do 3rd press home
+     ;; 1st press
+     (t
+      (beginning-of-visual-line))))
+  (setq brief-last-3rd-command brief-last-last-command
+        brief-last-last-command last-command))
+
+;;;; <2011-06-02 Thu 17:03> ins func
+;;(defun brief-shift-home (arg)
+;;  "\"Home\" the point, the way Brief would do it, with marker activated.
+;;The first use moves point to beginning of the line.  Second
+;;consecutive use moves point to beginning of the screen.  Third
+;;consecutive use moves point to the beginning of the buffer."
+;;  (interactive "p")
+;;  (brief-set-mark-here-if-not-active)
+;;  (call-interactively 'brief-home (list arg)))
+
+(defun brief-goto-window-end ()
+  "Move cursor to the end of current window."
+  (let ((we (window-end)))
+    (goto-char (if (/= (point-max) we)
+                   (1- we)
+                 we))))
+
+(defun brief-end (arg)
+  "\"End\" the cursor the way that Brief editor do it.
+
+When `visual-line-mode' is nil and `truncate-lines' is non-nil, the
+first \\[brief-end] moves point to end of the line.
+Second consecutive \\[brief-end] moves point to bottom of the screen.
+Third consecutive \\[brief-end] moves point to the end of the buffer.
+
+When `visual-line-mode' is non-nil or `truncate-lines' is nil, the first
+\\[brief-end] goes to the end of visible line and the second \\[brief-end] 
then goes to
+the physical end of line.  Consecutive 3rd and 4th \\[brief-end]s goes to the
+bottom of screen and end of buffer."
+
+  (interactive "^p")
+  (let ((end4  (eq brief-last-3rd-command  'brief-end))
+        (end3  (eq brief-last-last-command 'brief-end))
+        (end2  (eq last-command            'brief-end))
+        p1 p2 c1 c2)
+    (cond
+     ;; 4th press
+     ((and end4 end3 end2)
+      (goto-char (point-max)))
+     ;; 3rd press
+     ((and end3 end2)
+      (if truncate-lines
+          (goto-char (point-max))
+        (setq p1 (save-mark-and-excursion (move-end-of-line 1) (point))
+              p2 (save-mark-and-excursion (brief-goto-window-end)))
+        (goto-char (if (/= p1 p2)
+                       (max p1 p2)
+                     (point-max)))))
+     ;; 2rd press
+     (end2
+      (if truncate-lines
+          (brief-goto-window-end)
+        (setq p1 (save-mark-and-excursion
+                   ;; if we're at the abbreviated text '...' we will need to
+                   ;; go beyond that.
+                   (move-end-of-line 1) (point))
+              p2 (save-mark-and-excursion (brief-goto-window-end)))
+        (goto-char (if (/= (point) (min p1 p2))
+                       (min p1 p2)
+                     (max p1 p2)))))
+     ;; 1st press
+     (t
+      (if truncate-lines
+          (move-end-of-line 1)
+        (setq p1 (save-mark-and-excursion
+                   (end-of-visual-line)
+                   (setq c1 (following-char)) (point))
+              p2 (save-mark-and-excursion
+                   (end-of-line) (point))) ;; `end-of-line' of course is at 
crlf
+        (goto-char (if (and (/= p1 p2)
+                            ;; Check if we're at the abbreviated text '...'
+                            (not (brief-is-crlf c1)))
+                       (1- p1)
+                     ;; `end-of-visual-line' on line wrapping will have cursor
+                     ;; at the beginning of next line
+                     p1))))))
+  (setq brief-last-3rd-command brief-last-last-command
+        brief-last-last-command last-command))
+
+(defun brief-move-to-window-line-0 ()
+  (interactive)
+  (move-to-window-line 0))
+
+(defun brief-mark-move-to-window-line-0 ()
+  (interactive) ;; <2011-06-02 Thu 17:40>
+  (brief-set-mark-here-if-not-active)
+  (move-to-window-line 0))
+
+(defun brief-move-to-window-line-end ()
+  (interactive)
+  (move-to-window-line -1))
+
+(defun brief-mark-move-to-window-line-end () ;; <2011-06-02 Thu 17:40>
+  (interactive)
+  (brief-set-mark-here-if-not-active)
+  (move-to-window-line -1))
+
+;;(defun brief-shift-end (arg)
+;;  "\"End\" the point, the way Brief would do it, with marker activated.
+;;The first use moves point to end of the line.  Second
+;;consecutive use moves point to the end of the screen.  Third
+;;consecutive use moves point to the end of the buffer."
+;;  (interactive "p")
+;;  (brief-set-mark-here-if-not-active)
+;;  (call-interactively 'brief-end (list arg)))
+
+(defun brief-is-unwanted-buffer (bufname)
+  "Check if BUF is a hidden buffer or match any customized unwanted buffer."
+  (or
+   ;; Skip hidden buffers
+   (and (>= (length bufname) 2)
+        (string= (substring bufname 0 2) " *"))
+   ;; Skip any customized buffer
+   (member bufname  brief-skip-buffers)))
+
+(defun brief-unbury-buffer ()
+  "Go back one buffer in the global buffer list."
+  (interactive)
+  (let ((startbuf (car (buffer-list))))
+    (while (progn ;; 09/12/2005 ins while loop
+             (switch-to-buffer (car (last (buffer-list))))
+             (and (not (eq startbuf (current-buffer)))
+                  ;; prevent go back to the same buffer if no other
+                  ;; valid buffer exists
+                  (brief-is-unwanted-buffer (buffer-name)))))))
+
+(defun brief-previous-buffer ()
+  "In selected window switch to previous buffer.
+Notice that this function will skip any buffer name that listed in
+`brief-skip-buffers'.  When prefixed, it bury current buffer in a
+global buffer list instead of a per-window/frame buffer list."
+  (interactive)
+  (let ((curr     (current-buffer))
+        (fskipbuf (if current-prefix-arg
+                      'bury-buffer
+                    (or (and (fboundp 'switch-to-prev-buffer)
+                             'switch-to-prev-buffer)
+                        'previous-buffer))))
+    (while (progn
+             (call-interactively fskipbuf)
+             (and (brief-is-unwanted-buffer (buffer-name))
+                  ;; Break if loop back to original buffer
+                  (not (eq curr (current-buffer))))))))
+
+(defun brief-next-buffer ()
+  "In selected window switch to next buffer.
+Notice that this function will skip any buffer name that listed in
+`brief-skip-buffers'.  When prefixed, it un-bury current buffer in a
+global buffer list instead of a per-window/frame buffer list."
+  (interactive)
+  (if current-prefix-arg
+      (call-interactively 'brief-unbury-buffer)
+    (let ((curr (current-buffer)))
+      (while (progn
+               (call-interactively
+                (or (and (fboundp 'switch-to-next-buffer)
+                         'switch-to-next-buffer)
+                    'next-buffer))
+               (and (brief-is-unwanted-buffer (buffer-name))
+                    ;; Break if loop back to original buffer
+                    (not (eq curr (current-buffer)))))))))
+
+(defun brief-color-message (text &optional color)
+  "Same as `message' but with specified foreground COLOR.
+COLOR could be either a string like \"red\" or an existing face
+like 'font-lock-warning-face."
+  (or color
+      (setq color "white"))
+  (message "%s"
+           (propertize text 'face
+                       (or (and (stringp color)
+                                `(:foreground ,color))
+                           color))))
+
+(defun brief-meta-x-wrapper ()
+  "Wrapper function to conditionally override the normal M-x bindings.
+When `brief-override-meta-x' is non-nil, M-x will exit Emacs (the
+normal Brief binding) and when it is nil M-x will run
+`execute-extended-command' (the normal Emacs binding).
+
+It also works for emacs client/server.  For editing with emacs-client,
+When `brief-override-meta-x' it ends emacs-client editing.
+
+Notice that the original `execute-extended-command' was moved to 
\\[execute-extended-command]
+when M-x is overridden by Brief mode.
+Also notice that the keybinding \\[save-buffers-kill-emacs] is a shortcut
+key of `save-buffers-kill-emacs' to bypass all these checks."
+  (interactive)
+  (if brief-override-meta-x
+
+      (if (and (boundp 'server-process) server-process)
+
+          ;; Emacs Client/Server mode editing
+
+          (if server-clients
+              ;; Client connected
+              (cond
+               ;; <2011-09-20 Tue 10:40> modified from `server-edit' and
+               ;; `server-switch-buffer' (server.el.gz) to deal with the
+               ;; special case the invoking emacs-client without giving
+               ;; a file.
+               ((or (not server-process)
+                    (memq (process-status server-process) '(signal exit)))
+                (server-mode 1))
+
+               (server-clients
+                (let ((next-buffer (server-done))
+                      (rest server-clients))
+                  (if next-buffer
+                      (apply 'server-switch-buffer next-buffer)
+                    (while (and rest (not next-buffer))
+                      (let ((proc (car rest)))
+                        ;; Only look at frameless clients, or those in the
+                        ;; selected frame.
+                        (when (or (not (process-get proc 'frame))
+                                  (eq (process-get proc 'frame)
+                                      (selected-frame)))
+                          (setq next-buffer
+                                (car (process-get proc 'buffers))))
+                        (setq rest (cdr rest))))
+                    (and next-buffer
+                         (server-switch-buffer next-buffer))
+                    (unless (or next-buffer (window-dedicated-p
+                                             (selected-window)))
+                      ;; just in case
+                      (if (= 1 (length (frame-list)))
+                          (when
+                              (progn
+                                (discard-input)
+                                (and
+                                 (y-or-n-p
+                                  "No buffers remain to edit, quit server? ")
+                                 (yes-or-no-p "Really quit server? ")))
+                            (server-force-stop)
+                            (kill-emacs))
+                        (delete-frame (selected-frame) t))))))
+
+               (t (message "No server editing buffers exists")))
+
+            ;; No client connected
+            (if (progn
+                  (discard-input)
+                  (and
+                   (y-or-n-p
+                    "Running as server but no client connected, exit? ")
+                   (yes-or-no-p "Really quit server? ")))
+                (save-buffers-kill-emacs)
+              (message "Keep running server-mode")))
+
+        ;; Normal Emacs exit path
+
+        (if (or (not brief-query-exit-emacs)
+                (let ((use-dialog-box nil))
+                  (discard-input)
+                  (brief-color-message
+                   "Brief: really exit Emacs ? (y or n) "
+                   'minibuffer-prompt)
+                  (y-or-n-p "Brief: really exit Emacs ? ")))
+            (save-buffers-kill-emacs)
+          (message "Brief: cancel exiting Emacs")))
+
+    ;; not `brief-override-meta-x'
+    (call-interactively 'execute-extended-command)))
+
+(defun brief-save-buffer (filename)
+  "Save whole buffer or a region, a rectangle.
+The interactive code part (read file name, check overwrite) is copied
+from `write-file'."
+  (interactive
+   (list (if (brief-use-region)
+             (read-file-name "Write region to file: " default-directory
+                             (expand-file-name
+                              (file-name-nondirectory (buffer-name))
+                              default-directory)
+                             nil nil))))
+  (if (not (brief-use-region))
+      (save-buffer)
+    (or (null filename) (string-equal filename "")
+        (progn
+          ;; If arg is just a directory,
+          ;; use the default file name, but in that directory.
+          (if (file-directory-p filename)
+              (setq filename (concat (file-name-as-directory filename)
+                                     (file-name-nondirectory
+                                      (or buffer-file-name (buffer-name))))))
+          (and buffer-file-name
+               (string-equal (expand-file-name filename)
+                             (expand-file-name buffer-file-name))
+               (error "Cannot overwrite current buffer file with a region."))
+          (and (file-exists-p filename)
+               ;; NS does its own confirm dialog.
+               (not (and (eq (framep-on-display) 'ns)
+                         (listp last-nonmenu-event)
+                         use-dialog-box))
+               (or (y-or-n-p
+                    (format "File `%s' exists; overwrite? " filename))
+                   (error "Canceled"))) ))
+    (if (brief-rectangle-active)
+        ;; Write rectangle line by line, append white spaces at the end
+        ;; if not long enough
+        (let ((regionstr "")
+              width
+              str)
+          (apply-on-rectangle
+           (lambda (startcol endcol)
+             (setq endcol (cua--rectangle-right)
+                   startcol (cua--rectangle-left)
+                   width (+ 1 (- endcol startcol))
+                   str (buffer-substring-no-properties
+                        (min (line-end-position) (+ startcol (point)))
+                        (min (line-end-position) (+ 1 endcol (point))))
+                   regionstr (concat regionstr
+                                     str
+                                     (if (< (length str) width)
+                                         (spaces-string
+                                          (- width (length str))))
+                                     "\n")))
+           (region-beginning) (region-end))
+          (write-region regionstr nil filename))
+      ;; Write lines region
+      (write-region (region-beginning) (region-end) filename))
+    (deactivate-mark)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Brief mode key bindings
+;;
+
+(defmacro brief-key (key def)
+  "Define key in `brief-global-mode-map'."
+  `(define-key brief-global-mode-map ,key ,def))
+
+;; Brief window commands: F1-<arrow> F2-<arrow> F3-<arrow> F4-<arrow>
+
+;; Defining F1 keymap bindings
+(brief-key                  [(f1)]  brief-prefix-F1)
+
+(define-key brief-prefix-F1 [(up)]         'brief-switch-window-up)
+(define-key brief-prefix-F1 [(down)]       'brief-switch-window-down)
+(define-key brief-prefix-F1 [(left)]       'brief-switch-window-left)
+(define-key brief-prefix-F1 [(right)]      'brief-switch-window-right)
+
+;; Defining F2 keymap bindings
+;; TODO: enlarge/shrink according to current window position and layouts
+(brief-key                  [(f2)]  brief-prefix-F2)
+
+(define-key brief-prefix-F2 [(down)]       'enlarge-window)
+(define-key brief-prefix-F2 [(left)]       'shrink-window-horizontally)
+(define-key brief-prefix-F2 [(right)]      'enlarge-window-horizontally)
+(define-key brief-prefix-F2 [(up)]         'shrink-window)
+
+;; Defining F3 keymap bindings
+
+(brief-key                  [(f3)]  brief-prefix-F3)
+
+(define-key brief-prefix-F3 [(down)]       'split-window-vertically)
+(define-key brief-prefix-F3 [(up)]         'brief-split-window-up)
+(define-key brief-prefix-F3 [(right)]      'split-window-horizontally)
+(define-key brief-prefix-F3 [(left)]       'brief-split-window-left)
+
+;;;; Defining F4 keymap bindings
+(brief-key                  [(f4)]  brief-prefix-F4)
+
+(define-key brief-prefix-F4 [(up)]         'brief-delete-window-up)
+(define-key brief-prefix-F4 [(down)]       'brief-delete-window-down)
+(define-key brief-prefix-F4 [(left)]       'brief-delete-window-left)
+(define-key brief-prefix-F4 [(right)]      'brief-delete-window-right)
+
+
+(brief-key [(control f4)]           'brief-delete-current-window)
+
+;; Search commands
+
+;; "shift"   key means "repeat"
+;; "meta"    key means "backward"
+;; "control" key means "forward/current"
+
+(brief-key               [(f5)]     'brief-search-forward)
+(brief-key          [(meta f5)]     'brief-search-backward)
+
+(brief-key         [(shift f5)]     'brief-repeat-search)
+(brief-key [(control shift f5)]     'brief-repeat-search-forward)
+(brief-key    [(meta shift f5)]     'brief-repeat-search-backward)
+;; 06/17/2005 ins 1 : as (shift f5) does not work, add control f5
+;; 02/09/2005 as [(shift f5)] works, comment this line
+;;(brief-key [(control f5)]           'brief-search-again)
+;; 02/10/2005 ins 2, Search forward/backward, default current word
+;; "control" key here means "current", as "f5" without "meta" already means 
"forward"
+(brief-key       [(control f5)]     'brief-search-forward-currword)
+(brief-key  [(meta control f5)]     'brief-search-backward-currword)
+
+;; Replace commands
+
+;; 04/03/'08 rem 1 ins 1
+(brief-key               [(f6)]     'brief-query-replace-forward)
+(brief-key          [(meta f6)]     'brief-query-replace-backward)
+
+(brief-key         [(shift f6)]     'brief-repeat-query-replace)
+(brief-key [(control shift f6)]     'brief-repeat-query-replace-forward)
+(brief-key    [(meta shift f6)]     'brief-repeat-query-replace-backward)
+;; 06/17/2005 ins 1 : as (shift f6) does not work, add control f6
+;; add 04/02/2008 brief-query-replace-currword for ctrl-f6
+(brief-key       [(control f6)]     'brief-query-replace-forward-currword)
+(brief-key  [(meta control f6)]     'brief-query-replace-backward-currword)
+
+(brief-key [(control s)]            'isearch-forward)
+(brief-key [(meta s)]               'isearch-backward)
+
+;; File/Buffer commands
+
+(brief-key [(meta e)]               'brief-find-file)
+(brief-key [(meta f)]               'brief-current-filename)
+
+(brief-key [(f9)]                   'find-file)
+(brief-key [(meta f9)]              'load-library)
+
+(brief-key [(meta o)]               'write-file)
+(brief-key [(meta r)]               'insert-file)
+
+(brief-key [(f10)]                  'execute-extended-command)
+(brief-key [(meta f10)]             'compile)
+
+(brief-key [(meta b)]               'brief-buffer-list-window)
+;; added function brief-indent-tab
+;; <2012-01-03 Tue 16:29> !!! This key-binding is too strong for Info mode !!!
+;;   Info mode use "\t" instead of <tab>.
+;;(brief-key [(tab)]                  'brief-indent-tab)
+;; <2012-01-03 Tue 16:29> This weak binding will enable <TAB> in Info mode.
+;; [2012-02-24 14:35:58 +0800] This seems to work only after Emacs 24,
+;;  Emacs 23 won't work.
+(brief-key "\t"                     'brief-indent-tab)
+;; 02/21/2006 modify from <f12> to <ctrl>-<alt>-<tab>
+;; 06/02/2008 Original function can be replaced by 'ctrl-q' <tab>,
+;;   change this key combination to brief-indent-buffer
+(brief-key [(control meta tab)]     'brief-indent-buffer)
+;; 06/21/2005 ins 1 08/10/2005 change to meta-f11 for Fedora4
+;;(brief-key [(meta f12)]             'brief-buffer-read-only-toggle)
+(brief-key [(meta f11)]             'brief-buffer-read-only-toggle)
+(brief-key [(meta p)]               'brief-print) ;; 04/15/'08 ins 1
+
+;;(brief-key [(control ?-)]          'kill-buffer)
+(brief-key [(control ?-)]           'brief-kill-current-buffer)
+(brief-key [(control kp-subtract)]  'kill-buffer)
+
+(brief-key [(meta ?-)]              'brief-previous-buffer)
+(brief-key [(meta ?_)]              'brief-previous-buffer)
+
+(brief-key [(meta n)]               'brief-next-buffer)
+;; 2009/12/1 add since meta-n (next) is a so widely used key combination
+;;   with meta-p (prev)
+(brief-key [(meta ?+)]              'brief-next-buffer)
+(brief-key [(meta ?=)]              'brief-next-buffer)
+
+(brief-key [(meta w)]               'brief-save-buffer)
+
+(brief-key [(meta x)]               'brief-meta-x-wrapper)
+(brief-key [(control meta shift x)] 'save-buffers-kill-emacs)
+(brief-key [(control meta shift X)] 'save-buffers-kill-emacs)
+
+(brief-key [(meta h)]               'help)
+
+
+;; Macro commands
+
+;; modify start-kbd-macro to brief-define-macro
+(brief-key [(f7)]                   'brief-define-macro)
+;;(brief-key [(f7)]                   'start-kbd-macro)
+;; modify end-kbd-macro to load-kbd-macro
+(brief-key [(meta f7)]              'brief-load-kbd-macro)
+;;(brief-key [(meta f7)]              'end-kbd-macro)
+
+;; <2010-07-21 Wed 11:26> change call-last-kbd-macro to 
brief-call-last-kbd-macro
+(brief-key [(f8)]                   'brief-call-last-kbd-macro)
+(brief-key [(meta f8)]              'brief-save-kbd-macro)
+
+;; Region / Xselection(Clipboard) commands
+
+(brief-key [(kp-add)]               'brief-copy-line)
+(brief-key [(kp-subtract)]          'brief-kill-line)
+;; just to cover all the bases (GNU Emacs, for instance)
+
+;; <2011-06-10 Fri 14:35> for Emacs X clipboard
+(brief-key [(insert)]               'brief-yank)
+
+;; Preventing the need of a keypad; for notebooks and a lot of new keyboards
+(brief-key [(control insert)]       'brief-copy-line)
+(brief-key [(shift delete)]         'brief-kill-line)
+
+;; Defining meta-L keymaps
+(brief-key [(meta l)]               brief-prefix-meta-l)
+(brief-key [(meta L)]               brief-prefix-meta-l)
+
+(define-key brief-prefix-meta-l [(up)]
+  (lambda () (interactive) (brief-call-mark-line-up-with-key [up])))
+(define-key brief-prefix-meta-l [(left)]
+  (lambda () (interactive) (brief-call-mark-line-up-with-key [left])))
+(define-key brief-prefix-meta-l [(home)]
+  (lambda () (interactive) (brief-call-mark-line-up-with-key [home])))
+(define-key brief-prefix-meta-l [(prior)]
+  (lambda () (interactive) (brief-call-mark-line-up-with-key [prior])))
+
+(define-key brief-prefix-meta-l [(control up)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-up-with-key [(control up)])))
+(define-key brief-prefix-meta-l [(control left)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-up-with-key [(control left)])))
+(define-key brief-prefix-meta-l [(control home)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-up-with-key [(control home)])))
+(define-key brief-prefix-meta-l [(control prior)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-up-with-key [(control prior)])))
+
+(define-key brief-prefix-meta-l [(meta l)]  ;; 04/28/2008 ins 2
+  (lambda ()
+    (interactive)
+    (brief-call-list-interactively (list 'brief-mark-line-down))))
+
+(define-key brief-prefix-meta-l [(down)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [down])))
+(define-key brief-prefix-meta-l [(right)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [right])))
+(define-key brief-prefix-meta-l [(end)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [end])))
+(define-key brief-prefix-meta-l [(next)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [next])))
+
+(define-key brief-prefix-meta-l [(control down)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [control down])))
+(define-key brief-prefix-meta-l [(control right)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [control right])))
+(define-key brief-prefix-meta-l [(control end)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [control end])))
+(define-key brief-prefix-meta-l [(control next)]
+  (lambda ()
+    (interactive)
+    (brief-call-mark-line-down-with-key [control next])))
+
+(brief-key [(meta m)]               'set-mark-command)
+
+;; Rectangle open/close/clear
+(brief-key [(meta c)]               'cua-set-rectangle-mark)
+
+(brief-key [(meta u)]               'brief-undo)
+;;(brief-key [(control u)]            'undo) ;; a prefix key
+
+;; General editing commands
+
+(brief-key [(meta d)]               'brief-delete-entire-line)
+(brief-key [(meta k)]               'brief-delete-end-of-line)
+
+;;(brief-key [(control ?])]          'brief-matching-open)
+
+;; <2011-06-30 Thu 15:04> rename 'kill' to 'delete'
+;; <2012-10-31 Wed 16:00> remove brief-delete-word due to the 
brief-forward-word
+;;   fix that it's now identical to brief-delete-word
+(brief-key [(meta backspace)]       'brief-delete-word)
+;; <2011-06-14 Tue 18:06> Add brief-backward-delete-word
+(brief-key [(control backspace)]    'brief-backward-delete-word)
+
+(brief-key [(delete)]               'brief-delete)
+(brief-key [(shift backspace)]      'backward-kill-word)
+
+;;(brief-key [(control f)]    'fill-paragraph-or-region) ;; no such function
+
+(brief-key [(meta i)]               'overwrite-mode)
+
+;; Bookmark commands
+
+;; [06/02/'08] All bookmark set are changed to 'brief-bookmark-set'
+(brief-key [(meta ?0)]              'brief-bookmark-jump-set-0)
+(brief-key [(meta ?1)]              'brief-bookmark-jump-set-1)
+(brief-key [(meta ?2)]              'brief-bookmark-jump-set-2)
+(brief-key [(meta ?3)]              'brief-bookmark-jump-set-3)
+(brief-key [(meta ?4)]              'brief-bookmark-jump-set-4)
+(brief-key [(meta ?5)]              'brief-bookmark-jump-set-5)
+(brief-key [(meta ?6)]              'brief-bookmark-jump-set-6)
+(brief-key [(meta ?7)]              'brief-bookmark-jump-set-7)
+(brief-key [(meta ?8)]              'brief-bookmark-jump-set-8)
+(brief-key [(meta ?9)]              'brief-bookmark-jump-set-9)
+
+(brief-key [(meta j)]               'brief-bookmark-set-jump)
+
+;; Cursor commands
+
+(brief-key [(meta left)]            'backward-sexp)
+(brief-key [(meta right)]           'forward-sexp)
+
+(brief-key [(control left)]         'brief-backward-word)
+(brief-key [(control right)]        'brief-forward-word)
+
+(brief-key [(home)]                 'brief-home)
+;; <2011-06-02 Thu 17:02> ins 1
+;;(brief-key [(shift home)]           'brief-shift-home)
+(brief-key [(control home)]         'brief-move-to-window-line-0)
+(brief-key [(control shift home)]   'brief-mark-move-to-window-line-0)
+
+(brief-key [(meta home)]            'beginning-of-line)
+(brief-key [(end)]                  'brief-end)
+;; <2011-06-02 Thu 17:03> ins 1
+;;(brief-key [(shift end)]            'brief-shift-end)
+(brief-key [(control end)]          'brief-move-to-window-line-end)
+(brief-key [(control shift end)]    'brief-mark-move-to-window-line-end)
+(brief-key [(meta end)]             'end-of-line)
+
+;;(brief-key [(control c) (b)]        'brief-submit-bug-report)
+
+(brief-key [prior]                  'brief-fixed-cursor-page-up)
+(brief-key [next]                   'brief-fixed-cursor-page-down)
+
+(brief-key [(meta up)]              'brief-previous-physical-line)
+(brief-key [(meta down)]            'brief-next-physical-line)
+
+(brief-key [(meta g)]               'goto-line)
+
+;;(brief-key [up]                     'brief-previous-line)
+;;(brief-key [down]                   'brief-next-line)
+(brief-key [remap previous-line]    'brief-previous-line)
+(brief-key [remap next-line]        'brief-next-line)
+
+(brief-key [(control shift l)]      'brief-recenter-left-right)
+
+;; [2016-04-01 18:20:22 +0800] Fix CUA C-v behavior which is not consistent
+;; with my brief-yank All CUA keymaps starts from `cua--keymap-alist', which
+;; exists in `emulation-mode-map-alists'. In `cua--keymap-alist', the
+;; `cua--cua-keys-keymap' was listed near the head so it got higher priority.
+(when (and (fboundp 'cua-paste)
+           (boundp 'cua--cua-keys-keymap))
+  (define-key cua--cua-keys-keymap [remap yank] 'brief-yank)
+  (define-key cua--cua-keys-keymap [(control v)] 'brief-yank))
+
+(eval-after-load 'cc-cmds
+  '(progn
+     (defun brief-indent-shift-tab (arg)
+       "Indent region or line for C/C++ code."
+       (interactive "*p")
+       (if (brief-use-region)
+           (and (fboundp #'c-indent-line-or-region)
+                (c-indent-line-or-region))
+         (setq brief-c-tabs-always-indent t)
+         (and (fboundp #'c-indent-command)
+              (c-indent-command))))
+     (define-key brief-global-mode-map [(backtab)] ;; <2012-01-03 Tue 15:45>
+       'brief-indent-shift-tab)
+     (define-key brief-global-mode-map [(shift tab)]
+       'brief-indent-shift-tab)))
+
+;;
+;; Brief mode definitions
+;;
+
+(defvar prev-brief-mode nil
+  "Brief internal variable to store previous brief mode's status.")
+
+(defun brief-mode-setter (arg)
+  "Set function for the global `brief-mode' variable.
+Also set `prev-brief-mode'."
+  (setq prev-brief-mode brief-mode
+        brief-mode arg))
+
+;; If our global map is named as `brief-mode-map' instead of the current
+;; `brief-global-mode-map'; we will need to define an empty mode map to
+;; override its minor-mode association as `define-minor-mode' by default
+;; automatically finds symbol named "brief-mode-map" if it exists and is
+;; a keymap.
+;;(defvar brief-local-map nil
+;;  "Brief dummy empty local map.")
+
+(defvar brief-backup-select-enable-clipboard
+  (and (boundp 'select-enable-clipboard) select-enable-clipboard)
+  "(Backup variable for Win32/Win64 only)")
+(defvar brief-backup-select-enable-primary
+  (and (boundp 'select-enable-primary) select-enable-primary)
+  "(Backup variable for Win32/Win64 only)")
+
+(defvar brief-backup-cua-mode cua-mode
+  "Backup variable for cua-mode, before enabling brief-mode.")
+
+;;;###autoload
+(define-minor-mode brief-mode
+  "Enable/Disable/Toggle Brief emulation mode.
+With a prefix argument ARG, enable Brief mode if ARG is positive,
+and disable it otherwise.  If called from Lisp, enable the mode
+if ARG is omitted or nil.  If called interactively without ARG,
+toggle brief-mode."
+  ;;:keymap brief-local-map
+  ;;:keymap brief-global-mode-map       ; we can't use `brief-global-mode-map'
+                                        ; here otherwise it will be enabled
+                                        ; as a minor-mode keymap and will get
+                                        ; searched ahead of `special-mode's
+                                        ; like `ibuffer-mode', `help-mode'
+                                        ; , `info-mode' ... etc.  Keys like
+                                        ; <enter>, <tab> or 'q' defined in
+                                        ; those special modes will fail since
+                                        ; `brief-global-mode-map' is searched
+                                        ; first.
+  :lighter brief-mode-mode-line-string
+  ;;
+  ;; Enabling either of the following (:variable, :global) will cause problems
+  ;; ("M-: brief-mode <enter>" will fail on <enter> key, guess it's because 
we're
+  ;; using `use-global-map'.  However, without them `brief-mode' will be buffer
+  ;; local and will not showing 't even if `brief-mode' is currently on.  Check
+  ;; `global-brief-mode' instead to make sure brief mode is ON or OFF.
+  ;; [2017-06-07 18:09:47 +0800] After removed the `use-global-map' these two
+  ;; variables becomes consistent; however, it seems less efficient since 
restoring
+  ;; a session will invoke `brief-mode' fucntion for each buffer. However, this
+  ;; could be a `session-restore' issue since it does not differentiate global
+  ;; mode from local modes.
+  ;; [2017-06-13 11:34:47 +0800] The above mentioned problem is because of the
+  ;; :keymap.  When we defined a keymap with `brief-mode-map', 
`define-minor-mode'
+  ;; will associate this minor mode (no matter it's named `global-brief-mode' 
or
+  ;; `brief-mode') to that keymap in the `minor-mode-alist'.  When the mode 
variable
+  ;; is ON, the keymap in the active `minor-mode-alist' is searched when 
translating
+  ;; a key.  This will make those keys in `special-mode' failed 
(`ibuffer-mode',
+  ;; `help-mode', and `info-mode', minibuffer... ). As `special-mode' is also a
+  ;; minor mode but not presented in the `minor-mode-alist' so our keymap take
+  ;; precedence and fail `special-mode' keys.
+  ;;:variable global-brief-mode
+  ;;:global t
+
+  ;; Define my global `brief-mode' variable and a setter function to prevent
+  ;; `define-minor-mode' define a buffer-local `brief-mode' associated with
+  ;; this minor-mode.
+  :variable (brief-mode . brief-mode-setter)
+
+  (unless (eq prev-brief-mode brief-mode)
+    (if (not brief-mode)
+        ;;
+        ;; Disable brief mode
+        ;;
+        (progn
+          ;; restore cua-mode
+          (cua-mode (if brief-backup-cua-mode 1 -1))
+
+          (if (and (brief-is-winnt)
+                   (boundp 'select-enable-clipboard))
+              ;; Respect user's original selection, whatever reason it was
+              (setq select-enable-clipboard 
brief-backup-select-enable-clipboard
+                    select-enable-primary   
brief-backup-select-enable-primary))
+          ;; These gui-get/set-selection changes are also required for
+          ;; win32/win64 systems
+          (if (fboundp 'advice-add)
+              (if brief-selection-op-legacy
+                  (progn
+                    (advice-remove 'x-get-selection 'brief-gui-get-selection)
+                    (advice-remove 'x-set-selection 'brief-gui-set-selection)
+                    (advice-remove 'x-select-text   'brief-gui-select-text))
+                ;; newer emacs
+                (advice-remove 'gui-get-selection 'brief-gui-get-selection)
+                (advice-remove 'gui-set-selection 'brief-gui-set-selection)
+                (advice-remove 'gui-select-text   'brief-gui-select-text))
+
+            (if brief-selection-op-legacy
+                (progn
+                  ;; older emacs don't have gui-get/set-selection
+                  (ad-disable-advice 'x-get-selection
+                                     'around 'brief-advice-gui-get-selection)
+                  (ad-disable-advice 'x-set-selection
+                                     'around 'brief-advice-gui-set-selection)
+                  (ad-activate 'x-get-selection)
+                  (ad-activate 'x-set-selection))
+              ;; `advice-add' not present, but `gui-get-selection' exists,
+              ;; this combination is not likely to happen, just in case.
+              (ad-disable-advice 'gui-get-selection
+                                 'around 'brief-advice-gui-get-selection)
+              (ad-disable-advice 'gui-set-selection
+                                 'around 'brief-advice-gui-set-selection)
+              (ad-activate 'gui-get-selection)
+              (ad-activate 'gui-set-selection)))
+
+          (if (fboundp 'advice-add)
+              (progn
+                (advice-remove 'cua--rectangle-post-command
+                               'brief-cua--rectangle-post-command)
+                (advice-remove 'cua-cancel
+                               'brief-reset-for-command-cancellation)
+                (advice-remove 'keyboard-quit
+                               'brief-reset-for-command-cancellation)
+                (advice-remove 'keyboard-escape-quit
+                               'brief-reset-for-command-cancellation)
+                (advice-remove 'cua-clear-rectangle-mark
+                               'brief-reset-for-command-cancellation)
+                (advice-remove 'cua-close-rectangle
+                               'brief-reset-for-command-cancellation))
+            (when (fboundp 'cua--rectangle-post-command)
+              (ad-disable-advice 'cua--rectangle-post-command
+                                 'before 'brief-cua--rectangle-post-command)
+              (ad-activate 'cua--rectangle-post-command))
+            (ad-disable-advice 'cua-cancel
+                               'before 'brief-cua-cancel)
+            (ad-activate 'cua-cancel)
+            (ad-disable-advice 'keyboard-quit
+                               'before 'brief-keyboard-quit)
+            (ad-activate 'keyboard-quit)
+            (ad-disable-advice 'keyboard-escape-quit
+                               'before 'brief-keyboard-escape-quit)
+            (ad-activate 'keyboard-escape-quit)
+            (when (fboundp 'cua-clear-rectangle-mark)
+              (ad-disable-advice 'cua-clear-rectangle-mark
+                                 'before 'brief-clear-rectangle-mark)
+              (ad-activate 'cua-clear-rectangle-mark))
+            (when (fboundp 'cua-close-rectangle)
+              (ad-disable-advice 'cua-close-rectangle
+                                 'before 'brief-close-rectangle)
+              (ad-activate 'cua-close-rectangle)))
+
+          (remove-hook 'activate-mark-hook
+                       'brief-region-backup-clipboard-selection)
+          (remove-hook 'activate-mark-hook
+                       'brief-postpone-gui-set-selection)
+          (remove-hook 'deactivate-mark-hook
+                       'brief-resume-gui-set-selection)
+          (remove-hook 'before-change-functions
+                       'brief-trim-fast-line-number-list)
+          (remove-hook 'deactivate-mark-hook
+                       'brief-delete-search-overlay)
+
+          (use-global-map brief-mode-original-keymap)
+
+          (setq query-replace-from-history-variable
+                brief-orig-query-replace-from-history-variable)
+          (setq query-replace-to-history-variable
+                brief-orig-query-replace-to-history-variable)
+
+          (if (version< emacs-version "24.0")
+              (setq prev-brief-mode nil)))
+      ;;
+      ;; Enable brief mode
+      ;;
+
+      ;; Need to enable cua-mode for rectangle operation
+      (setq brief-backup-cua-mode cua-mode)
+      (cua-mode 1)
+
+      (if brief-enable-postpone-selection
+          (brief-enable-clipboard-postponement))
+
+      (if (and (brief-is-winnt)
+               (boundp 'select-enable-clipboard))
+          ;; On Windows only 'CLIPBOARD works, 'PRIMARY does not work
+          (setq select-enable-clipboard t
+                select-enable-primary   nil))
+      (if (fboundp 'advice-add)
+          ;; Emacs >= 24
+          (if brief-selection-op-legacy
+              (progn
+                (advice-add 'x-get-selection
+                            :around   'brief-gui-get-selection)
+                (advice-add 'x-set-selection
+                            :around   'brief-gui-set-selection)
+                (advice-add 'x-select-text
+                            :override 'brief-gui-select-text))
+            ;; Emacs >= 25
+            (advice-add 'gui-get-selection
+                        :around   'brief-gui-get-selection)
+            (advice-add 'gui-set-selection
+                        :around   'brief-gui-set-selection)
+            (advice-add 'gui-select-text
+                        :override 'brief-gui-select-text))
+        (if brief-selection-op-legacy
+            ;; Older emacs
+            (progn
+              (ad-enable-advice 'x-get-selection
+                                'around 'brief-advice-gui-get-selection)
+              (ad-enable-advice 'x-set-selection
+                                'around 'brief-advice-gui-set-selection)
+              (ad-activate 'x-get-selection)
+              (ad-activate 'x-set-selection))
+          ;; `advice-add' not present, but `gui-get-selection' exists
+          ;; not likely to happen, just in case.
+          (ad-enable-advice 'gui-get-selection
+                            'around 'brief-advice-gui-get-selection)
+          (ad-enable-advice 'gui-set-selection
+                            'around 'brief-advice-gui-set-selection)
+          (ad-activate 'gui-get-selection)
+          (ad-activate 'gui-set-selection)))
+
+      (if (fboundp 'advice-add)
+          (progn
+            (advice-add 'cua--rectangle-post-command
+                        :before   'brief-cua-rectangle-undo-helper)
+            (advice-add 'cua-cancel
+                        :before   'brief-reset-for-command-cancellation)
+            (advice-add 'keyboard-quit
+                        :before   'brief-reset-for-command-cancellation)
+            (advice-add 'keyboard-escape-quit
+                        :before   'brief-reset-for-command-cancellation)
+            (advice-add 'cua-clear-rectangle-mark
+                        :before   'brief-reset-for-command-cancellation)
+            (advice-add 'cua-close-rectangle
+                        :before   'brief-reset-for-command-cancellation))
+        (when (fboundp 'cua--rectangle-post-command)
+          (ad-enable-advice 'cua--rectangle-post-command
+                            'before 'brief-cua--rectangle-post-command)
+          (ad-activate 'cua--rectangle-post-command))
+        (ad-enable-advice 'cua-cancel
+                          'before 'brief-cua-cancel)
+        (ad-activate 'cua-cancel)
+        (ad-enable-advice 'keyboard-quit
+                          'before 'brief-keyboard-quit)
+        (ad-activate 'keyboard-quit)
+        (ad-enable-advice 'keyboard-escape-quit
+                          'before 'brief-keyboard-escape-quit)
+        (ad-activate 'keyboard-escape-quit)
+        (when (fboundp 'cua-clear-rectangle-mark)
+          (ad-enable-advice 'cua-clear-rectangle-mark
+                            'before 'brief-clear-rectangle-mark)
+          (ad-activate 'cua-clear-rectangle-mark))
+        (when (fboundp 'cua-close-rectangle)
+          (ad-enable-advice 'cua-close-rectangle
+                            'before 'brief-close-rectangle)
+          (ad-activate 'cua-close-rectangle)))
+
+      ;; This will sometimes make `wg-restore-window' fails. I modified
+      ;; `wg-restore-window' and add a advice function in init.el to prevent 
this
+      (add-hook 'activate-mark-hook
+                'brief-region-backup-clipboard-selection)
+      (when brief-enable-postpone-selection
+        (add-hook 'activate-mark-hook
+                  'brief-postpone-gui-set-selection 't)
+        (add-hook 'deactivate-mark-hook
+                  'brief-resume-gui-set-selection))
+      (add-hook 'deactivate-mark-hook
+                'brief-delete-search-overlay)
+
+      (use-global-map brief-global-mode-map)
+
+      ;; Force `transient-mark-mode' in Emacs, so that the marking routines 
work
+      ;; as expected.  If the user turns off transient mark mode, most things
+      ;; will still work fine but some region/rectangle marking functions won't
+      ;; work quite as nicely.
+
+      (if (fboundp 'transient-mark-mode)
+          (transient-mark-mode 't))
+
+      (if brief-load-scroll-lock
+          (require 'scroll-lock))
+      (if (featurep 'scroll-lock)
+          (define-key brief-global-mode-map [(Scroll_Lock)] 'scroll-lock-mode))
+
+      (add-hook 'before-change-functions 'brief-trim-fast-line-number-list)
+      ;;;; On Windows we can only interact with CLIPBOARD but not PRIMARY
+      ;;(if (eq window-system 'w32)
+      ;;    (setq brief-X-selection-target 'CLIPBOARD))
+      ;;(run-hooks 'brief-load-hook)
+      ;;(message "@@ Brief mode enabled")
+      (setq brief-orig-query-replace-from-history-variable
+            query-replace-from-history-variable)
+      (setq brief-orig-query-replace-to-history-variable
+            query-replace-to-history-variable)
+      (setq query-replace-from-history-variable
+            'brief-query-replace-from-history)
+      (setq query-replace-to-history-variable
+            'brief-query-replace-to-history)
+
+      ;; Search for Xclipboard helper
+      (brief-xclipboard-cmd-search)
+
+      (and brief-override-meta-x
+           brief-warn-meta-x-moved
+           (brief-color-message
+            "Brief: The original <M-x> key now moved to function key <f10>."
+            'minibuffer-prompt))
+      (if (version< emacs-version "24.0")
+          (setq prev-brief-mode t))))
+
+      ;; calibrate current system UI performance
+      (call-interactively 'brief-calibration))
+
+(if (fboundp 'add-minor-mode)
+    (add-minor-mode 'brief-mode 'brief-mode-mode-line-string
+                    nil nil 'brief-mode)
+  (or (assq 'brief-mode minor-mode-alist)
+      (setq minor-mode-alist
+            (cons '(brief-mode brief-mode-mode-line-string)
+                  minor-mode-alist))))
+
+;; Interaction with other packages.
+
+(eval-after-load 'cua-base
+  '(progn
+     (put 'brief-home 'CUA 'move)
+     (put 'brief-end  'CUA 'move)))
+
+;; Support multiple-cursors
+
+(eval-after-load 'multiple-cursors
+  '(progn
+    ;; Check if `brief-previous-clipboard-selection' is listed
+    ;; in `mc/cursor-specific-vars', if not, add it in.
+    ;; This make copy&paste works under multiple cursor mode.
+    (if (and (boundp 'mc/cursor-specific-vars)
+             (not (member 'brief-previous-clipboard-selection
+                          mc/cursor-specific-vars)))
+        (push 'brief-previous-clipboard-selection
+              mc/cursor-specific-vars))
+
+    ;; Setup `mc/cmds-to-run-for-all' and `mc/cmds-to-run-once'
+    (when brief-init-multi-cursor-cmd
+      ;; Run for all
+      (delete-dups
+       (nconc mc/cmds-to-run-for-all
+              '(brief-backward-delete-word
+                brief-backward-word
+                brief-copy-line
+                brief-delete
+                brief-delete-word
+                brief-end
+                brief-forward-word
+                brief-home
+                brief-next-line
+                brief-previous-line
+                brief-undo
+                brief-yank
+                brief-delete-end-of-line
+                brief-delete-entire-line
+                brief-indent-tab
+                brief-kill-line
+                brief-query-replace
+                brief-query-replace-forward
+                brief-query-replace-backward
+                brief-repeat-query-replace
+                brief-repeat-query-replace-forward
+                brief-repeat-query-replace-backward
+                brief-query-replace-forward-currword
+                brief-query-replace-backward-currword
+                brief-search-backward
+                brief-search-backward-currword
+                brief-repeat-search-backward
+                brief-search-forward
+                brief-search-forward-currword
+                brief-repeat-search-forward
+                brief-fixed-cursor-page-up
+                brief-fixed-cursor-page-down
+                brief-call-last-kbd-macro
+                beginning-of-line
+                end-of-line
+                forward-sexp
+                backward-sexp
+                eval-last-sexp)))
+      ;; Run once
+      (delete-dups
+       (nconc mc/cmds-to-run-once
+              '(brief-buffer-list-window
+                brief-save-buffer
+                brief-indent-buffer
+                brief-meta-x-wrapper
+                brief-find-file
+                find-file
+                load-library
+                write-file
+                insert-file
+                compile
+                brief-current-filename
+                brief-move-to-window-line-0
+                brief-mark-move-to-window-line-0
+                brief-move-to-window-line-end
+                brief-mark-move-to-window-line-end
+                kill-buffer
+                brief-kill-current-buffer
+                brief-buffer-read-only-toggle
+                brief-print
+                brief-search-again
+                brief-search-forward-currword
+                brief-switch-window-up
+                brief-switch-window-down
+                brief-switch-window-left
+                brief-switch-window-right
+                enlarge-window
+                shrink-window-horizontally
+                enlarge-window-horizontally
+                shrink-window
+                split-window-vertically
+                split-window-horizontally
+                brief-split-window-up
+                brief-split-window-left
+                brief-delete-window-up
+                brief-delete-window-down
+                brief-delete-window-left
+                brief-delete-window-right
+                brief-delete-current-window
+                brief-unbury-buffer
+                brief-previous-buffer
+                brief-next-buffer
+                brief-bookmark-set-jump
+                brief-bookmark-jump-set
+                brief-recenter-left-right
+                save-buffers-kill-emacs
+                brief-load-kbd-macro
+                brief-save-kbd-macro
+                brief-bookmark-jump-set-0
+                brief-bookmark-jump-set-1
+                brief-bookmark-jump-set-2
+                brief-bookmark-jump-set-3
+                brief-bookmark-jump-set-4
+                brief-bookmark-jump-set-5
+                brief-bookmark-jump-set-6
+                brief-bookmark-jump-set-7
+                brief-bookmark-jump-set-8
+                brief-bookmark-jump-set-9
+                brief-bookmark-set-jump
+                overwrite-mode
+                goto-line
+                brief-define-macro
+                help))))))
+
+;;
+;; Overriding `line-number-at-pos'
+;;
+
+(eval-when (compile load eval)
+  (when (version< emacs-version "24.0")
+    (message "Defining advice function `
+brief-override-line-number-at-pos'")
+    ;; Initially we disable it till brief mode is enabled
+    (defadvice line-number-at-pos
+        (around brief-override-line-number-at-pos (&optional pos)
+                disable compile activate)
+      (brief-fast-line-number-at-pos pos))))
+
+(defun brief-set:brief-replace-emacs-func:line-number-at-pos (sym val)
+  "Method 'set' of variable `brief-replace-emacs-func:line-number-at-pos'.
+This function dynamically override `line-number-at-pos' according to
+the VAL.  Notice this works only if functions like `custom-set-variables'
+are used to set this custom variable."
+  (if val
+      (if (fboundp #'advice-add)
+          (progn
+            (advice-add 'line-number-at-pos
+                        :override #'brief-fast-line-number-at-pos)
+            (message
+             "Overriding `line-number-at-pos' with Brief's fast version."))
+        (ad-enable-advice 'line-number-at-pos
+                          'around 'brief-override-line-number-at-pos)
+        (ad-activate 'line-number-at-pos)
+        (message "Advice `line-number-at-pos' with Brief's fast version."))
+    ;; Iterate through the buffer list and clean each buffer's line number 
cache
+    (dolist (b (buffer-list))
+      (with-current-buffer b
+        (setq brief-fast-line-number-list nil)))
+    (if (fboundp 'advice-remove)
+        (progn
+          (advice-remove 'line-number-at-pos #'brief-fast-line-number-at-pos)
+          (message
+           "Restoring `line-number-at-pos' to Emacs's default version."))
+      (ad-disable-advice 'line-number-at-pos
+                         'around 'brief-override-line-number-at-pos)
+      (ad-activate 'line-number-at-pos)
+      (message
+       "Disable advicing `line-number-at-pos' return to Emacs's default.")))
+  (set sym val))
+
+(defcustom brief-replace-emacs-func:line-number-at-pos
+  ;;(and (version< emacs-version "26.1")
+  ;;     (not (boundp 'display-line-numbers)))
+  ;; Although Emacs 26.1 supports native line numbering, for relative window
+  ;; position calculation line numbers are still heavily in use so keep this
+  ;; feature ON by default.
+  t
+  "Replace Emacs's `line-number-at-pos' with `brief-fast-line-number-at-pos'.
+Use advice function to replace the system default `line-number-at-pos'
+which is slow on very big files, especially when using `linum-mode'.
+Notice that this replacement is global once you loaded brief mode, no
+matter if brief-mode is enabled or not."
+  :type  'boolean
+  :group 'brief
+  :set   'brief-set:brief-replace-emacs-func:line-number-at-pos)
+
+(eval-when (eval load)
+  '(when brief-replace-emacs-func:line-number-at-pos
+     ;; Global replacement, no matter if Brief mode is enabled or not.
+     ;; Notice that to dynamically overriding the `line-number-at-pos' function
+     ;; according to `brief-replace-emacs-func:line-number-at-pos',
+     ;; `custom-set-variables' must to be used to change this custom value.
+     ;; Normal `setq', `set' and `set-default' will only change the value but
+     ;; will not change the replacement status of `line-number-at-pos'.
+     (if (fboundp 'advice-add)
+         ;; Its :set method already do this; here is just in case the user
+         ;; using `setq' to set the value.
+         (advice-add 'line-number-at-pos
+                     :override #'brief-fast-line-number-at-pos)
+       (defadvice line-number-at-pos
+           (around brief-replace-line-number-at-pos (pos) activate compile)
+         (if brief-replace-emacs-func:line-number-at-pos
+             (brief-fast-line-number-at-pos pos)
+           ad-do-it)))))
+
+(run-hooks 'brief-load-hook)
+
+(provide 'brief)
+
+;;; brief.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]