Initial Commit
[packages] / xemacs-packages / hyperbole / hui-em19-b.el
1 ;;; hui-em19-b.el --- GNU Emacs V19 button highlighting and flashing support.
2
3 ;; Copyright (C) 1992-1995, 2005, 2006 Free Software Foundation, Inc.
4 ;; Developed with support from Motorola Inc.
5
6 ;; Author: Bob Weiner, Brown U.
7 ;; Maintainer: Mats Lidell <matsl@contactor.se>
8 ;; Keywords: faces, hypermedia
9
10 ;; This file is part of GNU Hyperbole.
11
12 ;; GNU Hyperbole is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 3, or (at
15 ;; your option) any later version.
16
17 ;; GNU Hyperbole is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 ;; General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
26
27 ;;; Commentary:
28 ;;
29 ;;   This is truly prototype code.
30 ;;
31 ;;   Can't use read-only buttons here because then outline-mode
32 ;;   becomes unusable.
33 ;;
34
35 ;;; Code:
36
37 (if (and hyperb:emacs19-p (or noninteractive hyperb:window-system))
38     nil
39   (error "(hui-em19-b.el): Load only when running GNU Emacs V19 under a window system."))
40
41 ;;;
42 ;;; Other required Elisp libraries
43 ;;;
44
45 (require 'hvar)
46 (require 'hbut)
47
48 (defun hproperty:background ()
49   "Returns default background color for current frame."
50   (or (face-background (make-face 'default))
51       (cdr (assq 'background-color (frame-parameters)))
52       "White"))
53
54 (defun hproperty:foreground ()
55   "Returns default foreground color for current frame."
56   (or (face-foreground (make-face 'default))
57       (cdr (assq 'foreground-color (frame-parameters)))
58       "Black"))
59
60 ;;;
61 ;;; Public variables
62 ;;;
63
64 (defvar hproperty:but-emphasize-p nil
65   "*Non-nil means visually emphasize that button under mouse cursor is selectable.")
66
67 (defvar hproperty:but-flash-time 1000
68   "*Machine specific value for empty loop counter, Emacs 19 button flash delay.")
69
70 (defvar hproperty:item-highlight-color (hproperty:foreground)
71   "Color with which to highlight list/menu selections.
72 Call (hproperty:set-item-highlight <color>) to change value.")
73
74 ;;;
75 ;;; Public functions
76 ;;;
77
78 ;; Support NEXTSTEP and X window systems.
79 (and (not (fboundp 'display-color-p))
80      (fboundp 'x-display-color-p)
81      (fset 'display-color-p 'x-display-color-p))
82
83 (defun hproperty:but-add (start end face)
84   "Add between START and END a button using FACE in current buffer.
85 If 'hproperty:but-emphasize-p' is non-nil when this is called, emphasize that
86 button is selectable whenever the mouse cursor moves over it."
87   (let ((but (make-overlay start end)))
88     (overlay-put but 'face face)
89     (if hproperty:but-emphasize-p (overlay-put but 'mouse-face 'highlight))))
90
91 (defun hproperty:but-color ()
92   "Return current color of buffer's buttons."
93   (if hproperty:color-ptr
94       (car hproperty:color-ptr)
95     (hproperty:foreground)))
96
97 (defun hproperty:but-clear ()
98   "Delete all Hyperbole buttons from current buffer."
99   (interactive)
100   (let ((start (point-min)))
101     (while (< start (point-max))
102       (mapcar (function (lambda (props)
103                           (if (eq (overlay-get props 'face) hproperty:but-face)
104                               (delete-overlay props))))
105               (overlays-at start))
106       (setq start (next-overlay-change start)))))
107
108 (defun hproperty:but-create (&optional start-delim end-delim regexp-match)
109   "Highlight all hyper-buttons in buffer.
110 Will use optional strings START-DELIM and END-DELIM instead of default values.
111 If END-DELIM is a symbol, e.g. t, then START-DELIM is taken as a regular
112 expression which matches an entire button string.
113 If REGEXP-MATCH is non-nil, only buttons matching this argument are
114 highlighted.
115
116 If 'hproperty:but-emphasize-p' is non-nil when this is called, emphasize that
117 button is selectable whenever the mouse cursor moves over it."
118   (interactive)
119   (hproperty:but-clear)
120   (hproperty:but-create-all start-delim end-delim regexp-match))
121
122 (defun hproperty:but-create-all (&optional start-delim end-delim regexp-match)
123   "Mark all hyper-buttons in buffer for later highlighting.
124 Will use optional strings START-DELIM and END-DELIM instead of default values.
125 If END-DELIM is a symbol, e.g. t, then START-DELIM is taken as a regular
126 expression which matches an entire button string.
127 If REGEXP-MATCH is non-nil, only buttons matching this argument are
128 highlighted."
129   (ebut:map (function (lambda (lbl start end)
130                         (hproperty:but-add start end hproperty:but-face)))
131             start-delim end-delim regexp-match 'include-delims))
132                
133 (defun hproperty:but-delete (&optional pos)
134   (let ((but (hproperty:but-get pos)))
135     (if but (delete-overlay but))))
136
137 ;;;
138 ;;; Private functions
139 ;;;
140
141 (defun hproperty:but-get (&optional pos)
142   (car (delq nil
143              (mapcar (function (lambda (props)
144                                  (if (memq (overlay-get props 'face)
145                                            (list hproperty:but-face
146                                                  hproperty:flash-face))
147                                      props)))
148                      (overlays-at (or pos (point)))))))
149
150 (defmacro hproperty:list-cycle (list-ptr list)
151   "Move LIST-PTR to next element in LIST or when at end to first element."
152   (` (or (and (, list-ptr)
153               (setq (, list-ptr) (cdr (, list-ptr))))
154          (setq (, list-ptr) (, list)))))
155
156 ;;;
157 ;;; Private variables
158 ;;;
159
160 (defconst hproperty:color-list
161   (if (memq window-system '(x gtk))
162       '( "red" "blue" "paleturquoise4" "mediumpurple2"
163 "lightskyblue3" "springgreen2" "salmon" "yellowgreen" "darkorchid2"
164 "aquamarine4" "slateblue4" "slateblue1" "olivedrab1" "goldenrod4"
165 "goldenrod3" "cadetblue2" "burlywood1" "slategrey" "mistyrose"
166 "limegreen" "lightcyan" "goldenrod" "gainsboro" "skyblue1" "honeydew"
167 "yellow2" "tomato3" "skyblue" "purple4" "orange3" "bisque3" "bisque2"
168 "grey34" "gray99" "gray63" "gray44" "gray37" "gray33" "gray26" "azure1"
169 "snow4" "peru" "red" "lightgoldenrod4" "mediumseagreen" "blush"
170 "mediumorchid2" "lightskyblue1" "darkslateblue" "midnightblue"
171 "lightsalmon1" "lemonchiffon" "yellow" "lightsalmon" "coral"
172 "dodgerblue3" "darkorange4" "blue" "royalblue4" "red" "green" "cyan"
173 "darkviolet" "darksalmon" "darkorange" "blue" "pink" "magenta2"
174 "sienna4" "khaki2" "grey75" "grey74" "grey73" "grey69" "grey68" "grey35"
175 "grey13" "gray90" "gray81" "gray55" "gray51" "gray31" "snow2" "pink3"
176 "grey7" "gray1" "red4" "red3" "tan" "red" "yellow" "mediumvioletred"
177 "lightslategrey" "lavenderblush4" "turquoise" "darkturquoise"
178 "darkslategrey" "lightskyblue" "lightsalmon4" "lightsalmon3"
179 "forestgreen" "dodgerblue4" "orchid" "rosybrown4" "brown" "peachpuff3"
180 "palegreen3" "orangered2" "rose" "lightcyan4" "indianred4" "indianred3"
181 "seagreen2" "indianred" "deeppink1" "navyblue" "lavender" "grey"
182 "deeppink" "salmon4" "salmon3" "oldlace" "grey78" "grey77" "grey54"
183 "grey45" "grey21" "gray97" "gray96" "gray95" "gray88" "gray87" "gray86"
184 "gray70" "gray57" "gray38" "gray12" "gray11" "plum3" "linen" "gray9"
185 "gray8" "blue4" "beige" "turquoise" "blue" "lemonchiffon4"
186 "darkseagreen1" "antiquewhite3" "mediumorchid" "springgreen"
187 "turquoise4" "steelblue3" "mistyrose2" "lightcyan2" "red" "firebrick2"
188 "royalblue" "cadetblue" "skyblue3" "yellow3" "salmon1" "orange4"
189 "hotpink" "grey90" "gray56" "gray39" "gray18" "gray14" "plum4" "grey6"
190 "gray6" "gold3" "gold1" "blue2" "tan2" "cyan" "mediumspringgreen"
191 "darkolivegreen2" "goldenrod" "lightsteelblue" "brown" "whip"
192 "chartreuse3" "violetred4" "royalblue2" "royalblue1" "papayawhip"
193 "mistyrose3" "lightcyan1" "aquamarine" "skyblue4" "hotpink4" "hotpink3"
194 "hotpink2" "dimgray" "tomato" "grey66" "grey65" "grey64" "grey33"
195 "grey27" "gray76" "gray69" "gray68" "grey0" "azure" "green"
196 "darkgoldenrod4" "darkgoldenrod3" "darkgoldenrod2" "darkgoldenrod"
197 "brown" "lightsalmon2" "deepskyblue4" "deepskyblue3" "deepskyblue2"
198 "deepskyblue" "darkorange1" "violetred3" "violetred2" "violetred1"
199 "slateblue3" "slateblue2" "drab" "indianred1" "firebrick1" "cadetblue4"
200 "violetred" "rosybrown" "blue" "firebrick" "grey100" "wheat4" "grey79"
201 "grey76" "grey61" "gray93" "gray84" "gray65" "gray36" "gray32" "gray13"
202 "gray10" "azure3" "snow1" "tan1" "gray" "darkolivegreen1" "blue"
203 "almond" "lavenderblush3" "lavenderblush2" "lavenderblush1"
204 "darkolivegreen" "lavenderblush" "aquamarine2" "red" "olivedrab2"
205 "mistyrose4" "mistyrose1" "lightcyan3" "lightcoral" "chartreuse"
206 "peachpuff" "palegreen" "mintcream" "skyblue2" "moccasin" "tomato1"
207 "orchid3" "maroon3" "salmon" "grey81" "grey62" "grey39" "grey38"
208 "grey37" "gray92" "gray83" "gray66" "gray54" "gray50" "gray30" "gray19"
209 "gray15" "azure4" "grey3" "tan3" "pink" "gray" "blue" "lightsteelblue2"
210 "lightsteelblue1" "green" "lightslategray" "lemonchiffon2"
211 "springgreen1" "greenyellow" "chartreuse2" "grey" "royalblue3"
212 "powderblue" "peachpuff2" "palegreen2" "cream" "slateblue" "seashell2"
213 "deeppink2" "darkkhaki" "maroon4" "sienna" "grey71" "grey67" "grey18"
214 "gray59" "gray43" "gray25" "bisque" "red1" "mediumslateblue"
215 "lightgoldenrod1" "goldenrod" "paleturquoise3" "lightskyblue4" "green"
216 "yellow" "smoke" "blue" "white" "steelblue4" "rosybrown3" "peachpuff1"
217 "palegreen1" "blueviolet" "seashell4" "sienna3" "grey40" "gray91"
218 "gray82" "gray5" "cyan2" "cyan1" "blue1" "snow" "lightgoldenrod2"
219 "lightslateblue" "mediumorchid3" "darkseagreen4" "springgreen3" "green"
220 "slategray4" "slategray3" "slategray2" "blue" "peachpuff4" "palegreen4"
221 "green" "orangered3" "goldenrod1" "ghostwhite" "firebrick4" "firebrick3"
222 "cadetblue3" "slategray" "seashell3" "honeydew3" "cornsilk4" "cornsilk2"
223 "purple1" "dimgrey" "khaki1" "ivory3" "grey70" "grey60" "grey32"
224 "grey22" "grey12" "gray98" "gray89" "gray71" "gray64" "gray60" "gray49"
225 "azure2" "gray3" "paleturquoise1" "mediumpurple1" "purple"
226 "lemonchiffon1" "blue" "navajowhite3" "darkorchid1" "orange"
227 "goldenrod2" "khaki" "chocolate2" "burlywood2" "honeydew1" "darkgreen"
228 "thistle3" "thistle2" "thistle1" "thistle" "maroon2" "maroon1" "grey53"
229 "grey44" "grey25" "gray74" "gray45" "gray41" "gray35" "gray27" "gray23"
230 "gray16" "brown4" "wheat" "coral" "tan4" "lightgoldenrodyellow" "blue"
231 "green" "gray" "palevioletred3" "mediumpurple4" "mediumpurple3"
232 "saddlebrown" "blue" "darkorchid4" "darkorchid3" "puff" "olivedrab4"
233 "lightblue4" "lightpink" "lightgray" "honeydew2" "cornsilk1" "lace"
234 "sienna1" "bisque4" "orchid" "khaki3" "grey84" "grey83" "grey82"
235 "grey72" "grey52" "grey43" "grey26" "grey14" "grey10" "gray75" "gray53"
236 "gray21" "gray20" "brown3" "grey8" "red2" "navy" "grey" "gold"
237 "mediumaquamarine" "lightgoldenrod" "darkslategray4" "darkseagreen3"
238 "darkseagreen2" "antiquewhite4" "white" "springgreen4" "lightyellow4"
239 "white" "aquamarine1" "turquoise3" "steelblue2" "rosybrown2" "pink"
240 "gray" "indianred2" "dodgerblue" "green" "seagreen1" "deeppink4"
241 "aliceblue" "magenta1" "pink" "sienna2" "orchid1" "gray100" "grey97"
242 "grey94" "grey87" "grey86" "grey51" "grey42" "grey19" "gray94" "gray85"
243 "gray61" "brown2" "khaki" "grey1" "gold4" "blue" "green" "grey"
244 "turquoise" "paleturquoise" "mediumorchid4" "antiquewhite2"
245 "lightyellow2" "violet" "salmon" "chartreuse1" "turquoise1" "sandybrown"
246 "orangered1" "lightpink1" "lightblue2" "lightblue1" "grey" "seagreen4"
247 "seagreen3" "lightblue" "deeppink3" "burlywood" "seashell" "hotpink1"
248 "gray" "yellow4" "yellow" "purple" "orange" "ivory4" "grey99" "grey89"
249 "grey63" "grey58" "grey49" "grey31" "grey24" "grey20" "green4" "green1"
250 "gray73" "gray67" "coral3" "coral2" "plum2" "pink4" "ivory" "gray4"
251 "gray2" "gold2" "aquamarine" "grey" "lightgoldenrod3" "darkolivegreen3"
252 "darkgoldenrod1" "goldenrod" "orchid" "chiffon" "navajowhite4"
253 "deepskyblue1" "lightyellow" "floralwhite" "blue" "mediumblue"
254 "chocolate4" "chocolate3" "burlywood4" "turquoise" "steelblue" "green"
255 "lawngreen" "honeydew4" "seagreen" "orchid4" "wheat1" "violet" "ivory1"
256 "grey88" "grey85" "grey57" "grey56" "grey55" "grey48" "grey47" "grey46"
257 "grey30" "grey17" "gray47" "gray29" "pink2" "grey5" "grey4" "green"
258 "gray0" "brown" "lightsteelblue4" "darkolivegreen4" "palevioletred4"
259 "blue" "darkslategray3" "darkslategray2" "darkslategray1"
260 "blanchedalmond" "palegoldenrod" "blue" "lightseagreen" "lemonchiffon3"
261 "darkslategray" "green" "darkseagreen" "antiquewhite" "darkorange2"
262 "chartreuse4" "blue" "rosybrown1" "olivedrab3" "lightpink2" "orangered"
263 "thistle4" "blue" "cornsilk" "salmon2" "orchid2" "ivory2" "grey93"
264 "grey92" "grey91" "grey36" "grey29" "grey28" "grey16" "gray79" "gray78"
265 "gray77" "gray48" "gray17" "coral4" "coral1" "plum1" "pink1" "grey9"
266 "grey2" "gray7" "cyan4" "blue3" "plum" "cornflowerblue" "lightskyblue2"
267 "antiquewhite1" "navajowhite2" "navajowhite1" "lightyellow3"
268 "navajowhite" "darkorange3" "whitesmoke" "turquoise2" "steelblue1"
269 "lightpink4" "lightblue3" "green" "chocolate1" "blue" "olivedrab"
270 "lightgrey" "chocolate" "magenta4" "magenta3" "yellow1" "purple3"
271 "purple2" "orange2" "orange1" "magenta" "bisque1" "wheat2" "maroon"
272 "khaki4" "grey96" "grey95" "grey80" "grey50" "grey41" "grey15" "grey11"
273 "gray80" "gray58" "gray40" "gray34" "gray22" "brown1" "snow3"
274 "mediumturquoise" "lightsteelblue3" "palevioletred2" "palevioletred1"
275 "paleturquoise2" "green" "palevioletred" "mediumorchid1" "white"
276 "mediumpurple" "lightyellow1" "dodgerblue2" "dodgerblue1" "violet"
277 "aquamarine3" "slategray1" "gray" "orangered4" "lightpink3" "blue"
278 "darkorchid" "cadetblue1" "burlywood3" "seashell1" "cornsilk3" "tomato4"
279 "tomato2" "wheat3" "grey98" "grey59" "grey23" "green3" "green2" "gray72"
280 "gray62" "gray52" "gray46" "gray42" "gray28" "gray24" "white" "cyan3"
281 "black" )
282     '("Red" "Blue" "Purple" "Magenta" "Orange" "Yellow" "Green" "Brown"
283       "Dark Gray" "Light Gray" "Black" "Cyan")
284     ))
285
286
287 (defvar hproperty:color-ptr nil
288   "Pointer to current color name table to use for Hyperbole buttons.")
289
290 (defconst hproperty:good-colors
291   (if (memq window-system '(x gtk))
292       '(
293         "medium violet red" "indianred4" "firebrick1" "DarkGoldenrod"
294         "NavyBlue" "darkorchid" "tomato3" "mediumseagreen" "deeppink"
295         "forestgreen" "mistyrose4" "slategrey" "purple4" "dodgerblue3"
296         "mediumvioletred" "lightsalmon3" "orangered2" "turquoise4" "Gray55"
297         )
298     hproperty:color-list)
299   "Good colors for contrast against wheat background and black foreground.")
300
301
302 ;;;
303 ;;; Public functions
304 ;;;
305
306 (defun hproperty:cycle-but-color (&optional color)
307   "Switches button color to optional COLOR name or next item referenced by hproperty:color-ptr."
308   (interactive "sHyperbole button color: ")
309   (if (not (display-color-p))
310       nil
311     (if color (setq hproperty:color-ptr nil))
312     (set-face-foreground
313      hproperty:but-face (or color (car (hproperty:list-cycle hproperty:color-ptr hproperty:good-colors))))
314     (hproperty:set-flash-color)
315     (sit-for 0)  ;; Force display update
316     t))
317
318 (defun hproperty:set-flash-color ()
319   "Set button flashing colors based upon current color set."
320   (if (not (display-color-p))
321       nil
322     (set-face-background hproperty:flash-face (hproperty:but-color))
323     (set-face-foreground hproperty:flash-face (hproperty:background))))
324
325 (defun hproperty:but-p (&optional pos)
326   "Return non-nil at point or optional POS iff face is eq to hproperty:but-face."
327   (memq t (mapcar (function (lambda (props)
328                               (eq (overlay-get props 'face) hproperty:but-face)))
329                   (overlays-at (or pos (point))))))
330
331 (defun hproperty:set-but-face (pos face)
332   (let ((but (hproperty:but-get pos)))
333     (if but (overlay-put but 'face face))))
334
335 (defun hproperty:but-flash ()
336   "Flash a Hyperbole button at or near point to indicate selection."
337   (interactive)
338   (let ((ibut) (prev)
339         (start (hattr:get 'hbut:current 'lbl-start))
340         (end   (hattr:get 'hbut:current 'lbl-end))
341         (b) (a))
342     (if (and start end (setq prev (hproperty:but-p start)
343                              ibut t))
344         (if (not prev) (hproperty:but-add start end hproperty:but-face))
345       (setq start (point)))
346     (setq b (and (hproperty:but-p start) hproperty:but-face))
347     (if (setq a b)
348         (progn
349           (hproperty:set-but-face start hproperty:flash-face)
350           (sit-for 0) ;; Force display update
351           ;; Delay before redraw button
352           (let ((i 0)) (while (< i hproperty:but-flash-time) (setq i (1+ i))))
353           (hproperty:set-but-face start a)
354           (sit-for 0);; Force display update
355           ))
356     (if (and ibut (not prev)) (hproperty:but-delete start))
357     ))
358
359 (defun hproperty:set-item-highlight (&optional background foreground)
360   "Setup or reset item highlight face using optional BACKGROUND and FOREGROUND."
361   (make-local-variable 'hproperty:item-face)
362   (if (stringp background) (setq hproperty:item-highlight-color background))
363   (if (not hproperty:highlight-face)
364       (progn 
365         (setq hproperty:highlight-face (make-face 'hproperty:highlight-face))
366         (set-face-foreground hproperty:highlight-face (or foreground
367                                                           (hproperty:background)))
368         (set-face-underline-p hproperty:highlight-face nil)))
369
370   (let ((update-rolo-highlight-flag
371          (and (boundp 'rolo-highlight-face)
372               (facep rolo-highlight-face)
373               (or (null (face-foreground rolo-highlight-face))
374                   (face-equal hproperty:highlight-face rolo-highlight-face)))))
375     (if (not (equal (face-background hproperty:highlight-face)
376                     hproperty:item-highlight-color))
377         (set-face-background hproperty:highlight-face
378                              hproperty:item-highlight-color))
379     (and background (not (equal (face-background
380                                  hproperty:highlight-face) background))
381          (set-face-background hproperty:highlight-face background))
382     (and foreground (not (equal (face-foreground
383                                  hproperty:highlight-face) foreground))
384          (set-face-foreground hproperty:highlight-face foreground))
385     (setq hproperty:item-face hproperty:highlight-face)
386     (if update-rolo-highlight-flag
387         (copy-face hproperty:highlight-face rolo-highlight-face))))
388
389 (defun hproperty:select-item (&optional pnt)
390   "Select item in current buffer at optional position PNT using hproperty:item-face."
391   (if pnt (goto-char pnt))
392   (skip-chars-forward " \t")
393   (skip-chars-backward "^ \t\n")
394   (let ((start (point)))
395     (save-excursion
396       (skip-chars-forward "^ \t\n")
397       (hproperty:but-add start (point) hproperty:item-face)
398       ))
399   (sit-for 0)  ;; Force display update
400   )
401
402 (defun hproperty:select-line (&optional pnt)
403   "Select line in current buffer at optional position PNT using hproperty:item-face."
404   (if pnt (goto-char pnt))
405   (save-excursion
406     (beginning-of-line)
407     (hproperty:but-add (point) (progn (end-of-line) (point)) hproperty:item-face))
408   (sit-for 0)  ;; Force display update
409   )
410
411 ;;;
412 ;;; Private variables
413 ;;;
414
415 (defvar hproperty:but-face (progn (make-face 'hbut) 'hbut) "Face for hyper-buttons.")
416 (setq hproperty:but hproperty:but-face)
417 (set-face-foreground hproperty:but-face (hproperty:but-color))
418 (set-face-background hproperty:but-face (hproperty:background))
419
420 (defvar hproperty:flash-face (progn (make-face 'hbut-flash) 'hbut-flash)
421   "Face for flashing hyper-buttons.")
422 (hproperty:set-flash-color)
423
424 (defvar hproperty:item-button nil
425   "Button used to highlight an item in a listing buffer.")
426 (make-variable-buffer-local 'hproperty:item-button)
427 (defvar hproperty:item-face nil "Item marking face.")
428 (defvar hproperty:highlight-face nil
429   "Item highlighting face.  Use (hproperty:set-item-highlight) to set.")
430 (if hproperty:highlight-face
431     nil
432   ;; Reverse foreground and background colors for default block-style highlighting.
433   (hproperty:set-item-highlight (hproperty:foreground) (hproperty:background)))
434
435 (provide 'hui-em19-b)
436
437 ;;; hui-em19-b.el ends here