1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 @enpage m17n-edit edit multilingual text
26 @section m17n-edit-synopsis SYNOPSIS
28 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section m17n-edit-description DESCRIPTION
32 Display FILE on a window and allow users to edit it.
34 XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).
36 The following OPTIONs are available.
50 This program is to demonstrate how to use the m17n GUI API.
51 Although m17n-edit directly uses the GUI API, the API is mainly
52 for toolkit libraries or to implement XOM (X Output Method), not
53 for direct use from application programs.
56 @japage m17n-edit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section m17n-edit-synopsis SYNOPSIS
60 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section m17n-edit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit
83 ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é
84 ¥ê¤äXOM (X Output Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
85 ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
100 #ifdef HAVE_X11_XAW_COMMAND_H
102 #include <X11/keysym.h>
103 #include <X11/Xatom.h>
104 #include <X11/Intrinsic.h>
105 #include <X11/StringDefs.h>
106 #include <X11/Shell.h>
108 #include <m17n-gui.h>
109 #include <m17n-misc.h>
112 #include <X11/Xaw/Command.h>
113 #include <X11/Xaw/Box.h>
114 #include <X11/Xaw/Form.h>
115 #include <X11/Xaw/Dialog.h>
116 #include <X11/Xaw/Scrollbar.h>
117 #include <X11/Xaw/Toggle.h>
118 #include <X11/Xaw/SimpleMenu.h>
119 #include <X11/Xaw/SmeBSB.h>
120 #include <X11/Xaw/SmeLine.h>
121 #include <X11/Xaw/MenuButton.h>
123 /* Global variables. */
128 /* For the X Window System. */
131 /* GCs for normal drawing, filling by background color, normal drawing
132 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
134 GC gc, gc_inv, mono_gc, mono_gc_inv;
136 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
137 XtAppContext context;
138 int default_font_size;
142 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
143 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
144 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
145 +- Body -- Sbar, Text
149 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
150 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
151 Widget SbarWidget, TextWidget;
152 Widget FileShellWidget, FileDialogWidget;
153 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
154 Widget CurIMLang, CurIMStatus;
156 int win_width, win_height; /* Size of TextWidget. */
159 Pixmap input_status_pixmap;
160 int input_status_width, input_status_height;
162 /* Bitmap for "check" glyph. */
163 #define check_width 9
164 #define check_height 8
165 static unsigned char check_bits[] = {
166 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
167 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
170 /* For the m17n library. */
173 int nchars; /* == mtext_len (mt) */
175 MDrawControl control, input_status_control;
176 MTextProperty *selection;
181 MFace *face_xxx_large;
183 MFace *face_courier, *face_helvetica, *face_times;
184 MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
185 MFace *face_default_fontset, *face_no_ctl_fontset;
186 MFace *face_input_status;
188 MSymbol Mcoding_compound_text;
190 int logical_move = 1; /* If 0, move cursor visually. */
194 MSymbol language, name;
198 InputMethodInfo *input_method_table;
200 int num_input_methods;
201 int current_input_method = -1; /* i.e. none */
202 int unicode_input_method = -1;
203 int auto_input_method = 0;
204 int saved_input_method = -3;
205 MInputContext *current_input_context;
212 { {"Menu Size", NULL},
213 {"xx-small", &mface_xx_small},
214 {"x-small", &mface_x_small},
215 {"small", &mface_small},
216 {"normalsize", &mface_normalsize},
217 {"large", &mface_large},
218 {"x-large", &mface_x_large},
219 {"xx-large", &mface_xx_large},
220 {"xxx-large", &face_xxx_large},
222 {"Menu Family", NULL},
223 {"courier", &face_courier},
224 {"helvetica", &face_helvetica},
225 {"times", &face_times},
226 {"dv-ttyogesh", &face_dv_ttyogesh},
227 {"freesans", &face_freesans},
228 {"freeserif", &face_freeserif},
229 {"freemono", &face_freemono},
231 {"Menu Style", NULL},
232 {"medium", &mface_medium},
233 {"bold", &mface_bold},
234 {"italic", &mface_italic},
236 {"Menu Color", NULL},
237 {"black", &mface_black},
238 {"white", &mface_white},
240 {"green", &mface_green},
241 {"blue", &mface_blue},
242 {"cyan", &mface_cyan},
243 {"yello", &mface_yellow},
244 {"magenta", &mface_magenta},
247 {"normal", &mface_normal_video},
248 {"reverse", &mface_reverse_video},
249 {"underline", &mface_underline},
251 {"No CTL", &face_no_ctl_fontset} };
254 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
256 /* Information about a physical line metric. */
259 int from; /* BOL position of the line. */
260 int to; /* BOL position of the next line. */
261 int y0, y1; /* Top and bottom Y position of the line. */
262 int ascent; /* Height of the top Y position. */
265 struct LineInfo top; /* Topmost line. */
266 struct LineInfo cur; /* Line containing cursor. */
267 struct LineInfo sel_start; /* Line containing selection start. */
268 struct LineInfo sel_end; /* Line containing selection end. */
270 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
272 /* X position to keep on vertical (up and down) cursor motion. */
273 int target_x_position;
275 /* Interface macros for m17n-lib drawing routines. */
277 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
278 coordinate ($X, $Y) */
279 #define DRAW_TEXT(x, y, from, to) \
280 mdraw_text_with_control \
281 (frame, (MDrawWindow) win, \
282 control.orientation_reversed ? x + win_width : x, y, \
283 mt, from, to, &control)
285 /* Store the extents of a text in the range $FROM to $TO in the
286 structure $RECT (type MDrawMetric). */
287 #define TEXT_EXTENTS(from, to, rect) \
288 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
290 /* Store the glyph information of a character at the position $POS in
291 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
292 $FROM is written at the coordinate (0, 0). */
293 #define GLYPH_INFO(from, pos, info) \
294 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
296 /* Set $X and $Y to the coordinate of character at position $POS
297 assuming that the text from $FROM is written at the coordinate (0,
299 #define COORDINATES_POSITION(from, pos, x, y) \
300 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
302 /* Interface macros for X library. */
303 #define COPY_AREA(y0, y1, to) \
304 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
306 #define CLEAR_AREA(x, y, w, h) \
307 XClearArea (display, win, (x), (y), (w), (h), False)
309 #define SELECTEDP() \
310 mtext_property_mtext (selection)
312 /* Format MSG by FMT and print the result to the stderr, and exit. */
313 #define FATAL_ERROR(fmt, arg) \
315 fprintf (stderr, fmt, arg); \
320 /* If POS is greater than zero, move POS back to the beginning of line
321 (BOL) position. If FORWARD is nonzero, move POS forward instead.
322 Return the new position. */
324 bol (int pos, int forward)
326 int limit = forward ? nchars : 0;
328 pos = mtext_character (mt, pos, limit, '\n');
329 return (pos < 0 ? limit : pos + 1);
332 /* Update the structure #TOP (struct LineInfo) to make $POS the first
333 character position of the screen. */
337 int from = bol (pos, 0);
340 GLYPH_INFO (from, pos, info);
341 top.from = info.line_from;
342 top.to = info.line_to;
344 top.y1 = info.metrics.height;
345 top.ascent = - info.metrics.y;
349 /* Update the scroll bar so that the text of the range $FROM to $TO
350 are shown on the window. */
352 update_scroll_bar (int from, int to)
354 float top = (float) from / nchars;
355 float shown = (float) (to - from) / nchars;
357 XawScrollbarSetThumb (SbarWidget, top, shown);
361 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
362 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
363 is nonzero, update the scoll bar. */
365 redraw (int y0, int y1, int clear, int scroll_bar)
370 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
371 struct LineInfo *line;
373 if (clear || control.anti_alias)
374 CLEAR_AREA (0, y0, win_width, y1 - y0);
376 /* Find a line closest to y0. It is a cursor line if the cursor is
377 Y0, otherwise the top line. */
382 /* If there exists a selected region, check it too. */
383 if (sel_y0 > line->y0 && y0 >= sel_y0)
388 info.metrics.height = line->y1 - y;
389 info.metrics.y = - line->ascent;
390 info.line_to = line->to;
391 while (y + info.metrics.height <= y0)
393 y += info.metrics.height;
397 GLYPH_INFO (from, from, info);
399 if (y + info.metrics.height <= y0)
402 y0 = y - info.metrics.y;
404 while (to < nchars && y < y1)
406 GLYPH_INFO (to, to, info);
407 y += info.metrics.height;
413 DRAW_TEXT (0, y0, from, to);
418 GLYPH_INFO (to, to, info);
419 if (y + info.metrics.height >= win_height)
422 y += info.metrics.height;
424 update_scroll_bar (top.from, to);
429 /* Set the current input method spot to the correct position. */
431 set_input_method_spot ()
433 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
434 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
437 int size = 0, ratio = 0, i;
440 n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
442 for (i = n - 1; i >= 0; i--)
445 size = (int) mface_get_prop (faces[i], Msize);
447 ratio = (int) mface_get_prop (faces[i], Mratio);
450 size = default_font_size;
452 size = size * ratio / 100;
453 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
454 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
459 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
462 redraw_cursor (int clear)
464 if (control.cursor_bidi)
466 /* We must update the whole line of the cursor. */
467 int beg = bol (cur.from, 0);
468 int end = bol (cur.to - 1, 1);
470 int y0 = cur.y0, y1 = cur.y1;
474 TEXT_EXTENTS (beg, cur.from, rect);
479 TEXT_EXTENTS (cur.to, end, rect);
482 redraw (y0, y1, clear, 0);
490 if (control.orientation_reversed)
491 x += win_width - cursor.logical_width;
492 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
494 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
499 /* Update the information about the location of cursor to the position
500 $POS. If $FULL is nonzero, update the information fully only from
501 the information about the top line. Otherwise, trust the current
502 information in the structure $CUR. */
504 update_cursor (int pos, int full)
508 control.cursor_pos = pos;
511 /* CUR is inaccurate. We can trust only TOP. */
512 GLYPH_INFO (top.from, pos, cursor);
513 cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
515 else if (pos < cur.from)
517 int from = bol (pos, 0);
519 TEXT_EXTENTS (from, cur.from, rect);
520 GLYPH_INFO (from, pos, cursor);
521 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
523 else if (pos < cur.to)
525 GLYPH_INFO (cur.from, pos, cursor);
529 GLYPH_INFO (cur.from, pos, cursor);
530 cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
533 cur.from = cursor.line_from;
534 cur.to = cursor.line_to;
535 cur.y1 = cur.y0 + cursor.metrics.height;
536 cur.ascent = - cursor.metrics.y;
540 /* Update the information about the selected region. */
550 from = mtext_property_start (selection);
551 to = mtext_property_end (selection);
555 int pos = bol (from, 0);
557 TEXT_EXTENTS (pos, top.from, rect);
558 sel_start.y0 = top.y0 - rect.height;
559 sel_start.ascent = - rect.y;
560 GLYPH_INFO (pos, from, info);
561 if (pos < info.line_from)
562 sel_start.y0 += - rect.y + info.y + info.metrics.y;
566 GLYPH_INFO (top.from, from, info);
567 sel_start.y0 = top.ascent + info.y + info.metrics.y;
569 sel_start.ascent = -info.metrics.y;
570 sel_start.y1 = sel_start.y0 + info.metrics.height;
571 sel_start.from = info.line_from;
572 sel_start.to = info.line_to;
574 if (to <= sel_start.to)
580 GLYPH_INFO (sel_start.from, to, info);
581 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
582 sel_end.y1 = sel_end.y0 + info.metrics.height;
583 sel_end.ascent = - info.metrics.y;
584 sel_end.from = info.line_from;
585 sel_end.to = info.line_to;
590 /* Select the text in the region from $FROM to $TO. */
592 select_region (int from, int to)
597 pos = from, from = to, to = pos;
598 mtext_push_property (mt, from, to, selection);
603 /* Setup the window to display the character of $POS at the top left
609 /* Top and bottom Y positions to redraw. */
612 if (pos + 1000 < top.from)
613 y0 = 0, y1 = win_height;
614 else if (pos < top.from)
617 TEXT_EXTENTS (pos, top.from, rect);
618 if (rect.height >= win_height * 0.9)
623 COPY_AREA (0, win_height - y1, y1);
626 else if (pos < top.to)
628 /* No need of redrawing. */
631 else if (pos < top.from + 1000)
633 TEXT_EXTENTS (top.from, pos, rect);
634 if (rect.height >= win_height * 0.9)
638 y0 = win_height - rect.height;
639 COPY_AREA (rect.height, win_height, 0);
644 y0 = 0, y1 = win_height;
650 update_cursor (pos, 1);
652 update_cursor (cursor.from, 1);
654 redraw (y0, y1, 1, 1);
658 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
661 /* Select an input method accoding to $IDX. If $IDX is negative, turn
662 off the current input method, otherwide turn on the input method
663 input_method_table[$IDX]. */
665 select_input_method (idx)
667 int previous_input_method = current_input_method;
669 if (idx == current_input_method)
671 if (current_input_method >= 0)
673 minput_destroy_ic (current_input_context);
674 current_input_context = NULL;
675 current_input_method = -1;
679 && input_method_table[idx].available >= 0)
681 InputMethodInfo *im = input_method_table + idx;
683 if (im->available == 0)
686 im->im = minput_open_im (im->language, im->name, NULL);
689 MInputXIMArgIM arg_xim;
691 arg_xim.display = display;
693 arg_xim.res_name = arg_xim.res_class = NULL;
694 arg_xim.locale = NULL;
695 arg_xim.modifier_list = NULL;
696 im->im = minput_open_im (Mnil, im->name, &arg_xim);
698 im->available = im->im ? 1 : -1;
702 if (im->language == Mnil)
704 MInputXIMArgIC arg_xic;
705 Window win = XtWindow (TextWidget);
707 arg_xic.input_style = 0;
708 arg_xic.client_win = arg_xic.focus_win = win;
709 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
710 current_input_context = minput_create_ic (im->im, &arg_xic);
714 MInputGUIArgIC arg_ic;
716 arg_ic.frame = frame;
717 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
718 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
719 current_input_context = minput_create_ic (im->im, &arg_ic);
722 if (current_input_context)
724 current_input_method = idx;
725 set_input_method_spot ();
729 minput_close_im (im->im);
732 current_input_method = -1;
736 if (! auto_input_method)
738 XtSetArg (arg[0], XtNleftBitmap, None);
739 if (previous_input_method >= 0)
740 XtSetValues (InputMethodMenus[previous_input_method + 2], arg, 1);
742 XtSetValues (InputMethodMenus[0], arg, 1);
743 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
744 if (current_input_method >= 0)
745 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
747 XtSetValues (InputMethodMenus[0], arg, 1);
750 if (current_input_method >= 0)
754 XtSetArg (arg[0], XtNlabel, &label);
755 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
756 XtSetArg (arg[0], XtNlabel, label);
760 XtSetArg (arg[0], XtNlabel, "");
762 XtSetValues (CurIMLang, arg, 1);
765 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
768 /* Display cursor according to the current information of #CUR.
769 $CLIENT_DATA is ignore. Most callback functions add this function
770 as a background processing procedure the current application (by
771 XtAppAddWorkProc) via the function hide_cursor. */
773 show_cursor (XtPointer client_data)
775 MFaceHLineProp *hline;
781 update_cursor (cursor.from, 1);
783 while (cur.y1 > win_height)
786 update_cursor (cursor.from, 1);
789 control.cursor_pos = cursor.from;
792 control.with_cursor = 1;
795 if (current_input_context)
796 set_input_method_spot ();
800 int pos = (SELECTEDP () ? mtext_property_start (selection)
801 : cursor.from > 0 ? cursor.from - 1
803 MFace *face = mface ();
804 MTextProperty *props[256];
805 int n = mtext_get_properties (mt, pos, Mface, props, 256);
807 char buf[256], *p = buf;
813 int size = (int) mfont_get_prop (cursor.font, Msize);
814 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
815 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
816 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
817 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
819 sprintf (p, "%dpt", size / 10), p += strlen (p);
821 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
823 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
825 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
827 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
831 mface_merge (face, face_default);
832 for (i = 0; i < n; i++)
833 if (props[i] != selection)
834 mface_merge (face, (MFace *) mtext_property_value (props[i]));
835 sym = (MSymbol) mface_get_prop (face, Mforeground);
837 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
838 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
839 strcat (p, ",rev"), p += strlen (p);
840 hline = mface_get_prop (face, Mhline);
841 if (hline && hline->width > 0)
842 strcat (p, ",ul"), p += strlen (p);
843 box = mface_get_prop (face, Mbox);
844 if (box && box->width > 0)
845 strcat (p, ",box"), p += strlen (p);
846 m17n_object_unref (face);
848 XtSetArg (arg[0], XtNborderWidth, 1);
849 XtSetArg (arg[1], XtNlabel, buf);
850 XtSetValues (CurFaceWidget, arg, 2);
853 if (control.cursor_pos < nchars)
855 MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
859 XtSetArg (arg[0], XtNborderWidth, 0);
860 XtSetArg (arg[1], XtNlabel, "");
864 XtSetArg (arg[0], XtNborderWidth, 1);
865 sym = mlanguage_name (sym);
866 XtSetArg (arg[1], XtNlabel, msymbol_name (sym));
867 XtSetValues (CurLangWidget, arg, 2);
869 XtSetValues (CurLangWidget, arg, 2);
871 if (auto_input_method)
874 select_input_method (-1);
879 for (i = 0; i < num_input_methods; i++)
880 if (input_method_table[i].language == sym
881 && input_method_table[i].available >= 0)
883 if (i < num_input_methods)
884 select_input_method (i);
886 select_input_method (-1);
891 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
897 /* Hide the cursor. */
901 control.with_cursor = 0;
903 XtAppAddWorkProc (context, show_cursor, NULL);
907 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
908 $Y1 and $NEW_Y1 assuming that the text in the other area is not
911 update_region (int y0, int old_y1, int new_y1)
917 if (old_y1 < win_height)
919 COPY_AREA (old_y1, win_height, new_y1);
920 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
923 redraw (new_y1, win_height, 1, 0);
925 else if (new_y1 > old_y1)
927 if (new_y1 < win_height)
928 COPY_AREA (old_y1, win_height, new_y1);
930 if (new_y1 > win_height)
932 redraw (y0, new_y1, 1, 1);
936 /* Delete the next $N characters. If $N is negative delete the
937 precious (- $N) characters. */
943 int y0, old_y1, new_y1;
945 int line_from = cursor.line_from;
948 from = cursor.from, to = from + n;
951 from = cursor.from + n;
953 if (cursor.from == cur.from)
955 /* We are at the beginning of line. */
956 int pos = cursor.prev_from;
958 if (cursor.from == top.from)
960 /* We are at the beginning of screen. We must scroll
962 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
963 reseat (info.line_from);
965 update_cursor (pos, 1);
969 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
970 old_y1 = cur.y0 + rect.height;
972 /* Now delete a character. */
973 mtext_del (mt, from, to);
975 if (from >= top.from && from < top.to)
976 update_top (top.from);
977 update_cursor (from, 1);
980 if (line_from != cursor.line_from)
983 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
984 new_y1 = cur.y0 + rect.height;
986 update_region (cur.y0, old_y1, new_y1);
990 /* Insert M-text $NEWTEXT at the current cursor position. */
992 insert_chars (MText *newtext)
994 int n = mtext_len (newtext);
996 int y0, old_y1, new_y1;
1001 int n = (mtext_property_end (selection)
1002 - mtext_property_start (selection));
1003 mtext_detach_property (selection);
1008 if (cursor.line_from > 0
1009 && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
1010 y0 -= control.min_line_descent;
1012 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1013 old_y1 = y0 + rect.height;
1015 line_from = cursor.line_from;
1017 /* Now insert chars. */
1018 mtext_ins (mt, cursor.from, newtext);
1020 if (cur.from == top.from)
1021 update_top (top.from);
1022 update_cursor (cursor.from + n, 1);
1024 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1025 new_y1 = cur.y0 + rect.height;
1027 update_region (y0, old_y1, new_y1);
1028 update_selection ();
1033 word_constituent_p (int c)
1035 MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
1036 char *name = category != Mnil ? msymbol_name (category) : NULL;
1038 return (name && (name[0] == 'L' || name[0] == 'M'));
1045 int pos = cursor.from;
1047 while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
1051 MTextProperty *prop = mtext_get_property (mt, pos, Mword);
1054 pos = mtext_property_end (prop);
1056 while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
1059 update_cursor (pos, 0);
1065 int pos = cursor.from;
1067 while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
1071 MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
1074 pos = mtext_property_start (prop);
1076 while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
1079 update_cursor (pos, 0);
1083 /* Convert the currently selected text to UTF8-STRING or
1084 COMPOUND-TEXT. It is called when someone requests the current
1085 value of the selection. */
1087 covert_selection (Widget w, Atom *selection_atom,
1088 Atom *target, Atom *return_type,
1089 XtPointer *value, unsigned long *length, int *format)
1091 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1092 MText *this_mt = mtext ();
1093 int from = mtext_property_start (selection);
1094 int to = mtext_property_end (selection);
1098 mtext_copy (this_mt, 0, mt, from, to);
1099 if (*target == XA_TEXT)
1101 #ifdef X_HAVE_UTF8_STRING
1102 coding = Mcoding_utf_8;
1103 *return_type = XA_UTF8_STRING;
1105 coding = Mcoding_compound_text;
1106 *return_type = XA_COMPOUND_TEXT;
1109 else if (*target == XA_UTF8_STRING)
1111 coding = Mcoding_utf_8;
1112 *return_type = XA_UTF8_STRING;
1114 else if (*target == XA_STRING)
1119 for (i = 0; i < len; i++)
1120 if (mtext_ref_char (this_mt, i) >= 0x100)
1121 /* Can't encode in XA_STRING */
1123 coding = Mcoding_iso_8859_1;
1124 *return_type = XA_STRING;
1126 else if (*target == XA_COMPOUND_TEXT)
1128 coding = Mcoding_compound_text;
1129 *return_type = XA_COMPOUND_TEXT;
1134 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1135 m17n_object_unref (this_mt);
1139 *value = (XtPointer) buf;
1145 /* Unselect the text. It is called when we loose the selection. */
1147 lose_selection (Widget w, Atom *selection_atom)
1151 mtext_detach_property (selection);
1152 redraw (sel_start.y0, sel_end.y1, 1, 0);
1157 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1158 XtPointer value, unsigned long *length, int *format)
1163 if (*type == XT_CONVERT_FAIL || ! value)
1165 if (*type == XA_STRING)
1167 else if (*type == XA_COMPOUND_TEXT)
1168 coding = msymbol ("compound-text");
1169 #ifdef X_HAVE_UTF8_STRING
1170 else if (*type == XA_UTF8_STRING)
1171 coding = msymbol ("utf-8");
1176 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1177 if (! this_mt && *type != XA_UTF8_STRING)
1179 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1186 insert_chars (this_mt);
1187 m17n_object_unref (this_mt);
1196 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1198 XExposeEvent *expose = (XExposeEvent *) event;
1202 Dimension width_max, width;
1204 XtSetArg (arg[0], XtNwidth, &width);
1205 XtGetValues (XtParent (w), arg, 1);
1207 XtGetValues (HeadWidget, arg, 1);
1208 if (width_max < width)
1210 XtGetValues (FaceWidget, arg, 1);
1211 if (width_max < width)
1213 XtGetValues (LangWidget, arg, 1);
1214 if (width_max < width)
1216 XtSetArg (arg[0], XtNwidth, width_max);
1217 XtSetValues (HeadWidget, arg, 1);
1218 XtSetValues (FaceWidget, arg, 1);
1219 XtSetValues (LangWidget, arg, 1);
1220 XtSetValues (XtParent (w), arg, 1);
1221 XtSetValues (TailWidget, arg, 1);
1224 update_cursor (0, 1);
1225 redraw (0, win_height, 0, 1);
1226 if (current_input_method >= 0)
1228 int idx = current_input_method;
1230 current_input_method = -1;
1231 select_input_method (idx);
1237 redraw (expose->y, expose->y + expose->height, 0, 0);
1238 if (current_input_context
1239 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1240 set_input_method_spot ();
1245 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1247 XConfigureEvent *configure = (XConfigureEvent *) event;
1250 control.max_line_width = win_width = configure->width;
1251 win_height = configure->height;
1252 mdraw_clear_cache (mt);
1254 update_cursor (0, 1);
1255 redraw (0, win_height, 1, 1);
1256 if (current_input_context)
1257 set_input_method_spot ();
1261 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1264 int x = event->xbutton.x;
1265 int y = event->xbutton.y - top.ascent;
1267 if (control.orientation_reversed)
1269 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1272 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1273 mtext_detach_property (selection);
1274 redraw (sel_start.y0, sel_end.y1, 1, 0);
1277 if (current_input_context
1278 && minput_filter (current_input_context, Minput_focus_move, NULL) == 0)
1280 MText *produced = mtext ();
1282 minput_lookup (current_input_context, Mnil, NULL, produced);
1283 if (mtext_len (produced) > 0)
1285 insert_chars (produced);
1286 if (pos >= cursor.from)
1287 pos += mtext_len (produced);
1289 m17n_object_unref (produced);
1291 update_cursor (pos, 0);
1296 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1301 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1302 covert_selection, lose_selection, NULL);
1303 update_cursor (mtext_property_start (selection), 0);
1308 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1312 /* We don't have a local selection. */
1313 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1318 int from = mtext_property_start (selection);
1319 int to = mtext_property_end (selection);
1322 int x = event->xbutton.x;
1323 int y = event->xbutton.y - top.ascent;
1325 if (control.orientation_reversed)
1327 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1329 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1330 mtext_detach_property (selection);
1332 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1333 update_cursor (pos, 0);
1334 insert_chars (this_mt);
1335 m17n_object_unref (this_mt);
1340 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1343 int x = event->xbutton.x;
1344 int y = event->xbutton.y;
1346 if (control.orientation_reversed)
1349 pos = top.from, y -= top.ascent;
1351 pos = cur.from, y -= cur.y0 + cur.ascent;
1352 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1354 if (pos == cursor.from)
1360 /* Selection range changed. */
1361 int from = mtext_property_start (selection);
1362 int to = mtext_property_end (selection);
1363 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1364 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1366 if (cursor.from == from)
1368 /* Starting position changed. */
1371 /* Enlarged. We can simply overdraw. */
1372 select_region (pos, to);
1373 redraw (sel_start.y0, start_y1, 0, 0);
1377 /* Shrunken. Previous selection face must be cleared. */
1378 select_region (pos, to);
1379 redraw (start_y0, sel_start.y1, 1, 0);
1383 /* Shrunken to zero. */
1384 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1385 mtext_detach_property (selection);
1386 redraw (start_y0, end_y1, 1, 0);
1390 /* Full update is necessary. */
1391 select_region (to, pos);
1392 redraw (start_y0, sel_end.y1, 1, 0);
1397 /* Ending position changed. */
1400 /* Full update is necessary. */
1401 select_region (pos, from);
1402 redraw (sel_start.y0, end_y1, 1, 0);
1404 else if (pos == from)
1406 /* Shrunken to zero. */
1407 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1408 mtext_detach_property (selection);
1409 redraw (start_y0, end_y1, 1, 0);
1413 /* Shrunken. Previous selection face must be cleared. */
1414 select_region (from, pos);
1415 redraw (sel_end.y0, end_y1, 1, 0);
1419 /* Enlarged. We can simply overdraw. */
1420 select_region (from, pos);
1421 redraw (end_y0, sel_end.y1, 0, 0);
1427 /* Newly selected. */
1428 select_region (pos, cursor.from);
1429 redraw (sel_start.y0, sel_end.y1, 0, 0);
1431 update_cursor (pos, 1);
1435 FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num)
1437 if (current_input_context
1438 && minput_filter (current_input_context, Minput_focus_in, NULL) == 0)
1440 MText *produced = mtext ();
1442 minput_lookup (current_input_context, Mnil, NULL, produced);
1443 if (mtext_len (produced) > 0)
1446 insert_chars (produced);
1448 m17n_object_unref (produced);
1453 FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num)
1455 if (current_input_context
1456 && minput_filter (current_input_context, Minput_focus_out, NULL) == 0)
1458 MText *produced = mtext ();
1460 minput_lookup (current_input_context, Mnil, NULL, produced);
1461 if (mtext_len (produced) > 0)
1464 insert_chars (produced);
1466 m17n_object_unref (produced);
1471 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1474 MDrawGlyphInfo info;
1476 int cursor_pos = cursor.from;
1478 if (((int) position) < 0)
1484 height = top.y1 - top.y0;
1487 pos = bol (from - 1, 0);
1488 GLYPH_INFO (pos, from - 1, info);
1489 if (height + info.metrics.height > win_height)
1491 height += info.metrics.height;
1492 from = info.line_from;
1494 if (cursor_pos >= top.to)
1496 cursor_pos = top.from;
1498 while (cursor_pos < nchars)
1500 GLYPH_INFO (pos, pos, info);
1501 if (height + info.metrics.height > win_height)
1503 height += info.metrics.height;
1509 else if (cur.to < nchars)
1511 /* Scroll up, but leave at least one line. */
1514 while (from < nchars)
1516 GLYPH_INFO (from, from, info);
1517 if (height + info.metrics.height > win_height
1518 || info.line_to >= nchars)
1520 height += info.metrics.height;
1521 from = info.line_to;
1524 from = info.line_from;
1525 if (cursor_pos < from)
1529 /* Scroll up to make the cursor line top. */
1533 update_cursor (cursor_pos, 1);
1537 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1539 float persent = *(float *) persent_ptr;
1540 int pos1, pos2 = nchars * persent;
1541 MDrawGlyphInfo info;
1544 pos1 = bol (pos2, 0);
1545 GLYPH_INFO (pos1, pos2, info);
1546 pos1 = info.line_from;
1548 update_cursor (pos1, 1);
1551 static void InputMethodProc (Widget, XtPointer, XtPointer);
1554 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1556 XKeyEvent *key_event = (XKeyEvent *) event;
1558 KeySym keysym = NoSymbol;
1560 /* If set to 1, do not update target_x_position. */
1561 int keep_target_x_position = 0;
1563 int y0, old_y1, new_y1;
1570 if (current_input_context
1571 && minput_filter (current_input_context, Mnil, event))
1576 update_region (y0, old_y1, new_y1);
1580 if (event->type == KeyRelease)
1583 produced = mtext ();
1584 ret = minput_lookup (current_input_context, Mnil, event, produced);
1585 if (mtext_len (produced) > 0)
1586 insert_chars (produced);
1588 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1589 m17n_object_unref (produced);
1591 if (saved_input_method > -3)
1593 InputMethodProc (w, (XtPointer) saved_input_method, NULL);
1594 saved_input_method = -3;
1605 n = (mtext_property_end (selection)
1606 - mtext_property_start (selection));
1607 mtext_detach_property (selection);
1609 else if (cursor.from < nchars)
1611 /* Delete the following grapheme cluster. */
1612 n = cursor.to - cursor.from;
1625 /* Delete selected region. */
1626 n = (mtext_property_end (selection)
1627 - mtext_property_start (selection));
1628 mtext_detach_property (selection);
1630 else if (cursor.from > 0)
1632 /* Delete the preceding character. */
1643 mtext_detach_property (selection);
1644 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1648 if (cursor.prev_from >= 0)
1649 update_cursor (cursor.prev_from, 0);
1653 if (cursor.left_from >= 0)
1654 update_cursor (cursor.left_from, 0);
1661 mtext_detach_property (selection);
1662 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1666 if (cursor.next_to >= 0)
1667 update_cursor (cursor.to, 0);
1671 if (cursor.right_from >= 0)
1672 update_cursor (cursor.right_from, 0);
1679 mtext_detach_property (selection);
1680 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1682 if (cur.to <= nchars)
1684 MDrawGlyphInfo info;
1687 GLYPH_INFO (cur.from, cur.to, info);
1688 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1689 target_x_position, info.y);
1690 keep_target_x_position = 1;
1691 update_cursor (pos, 0);
1698 mtext_detach_property (selection);
1699 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1705 int pos = bol (cur.from - 1, 0);
1707 TEXT_EXTENTS (pos, cur.from - 1, rect);
1708 y = rect.height + rect.y - 1;
1709 pos = COORDINATES_POSITION (pos, nchars,
1710 target_x_position, y);
1711 keep_target_x_position = 1;
1712 update_cursor (pos, 0);
1719 mtext_detach_property (selection);
1720 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1722 if (top.from < nchars)
1723 ScrollProc (w, NULL, (XtPointer) 1);
1729 mtext_detach_property (selection);
1730 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1733 ScrollProc (w, NULL, (XtPointer) -1);
1737 if (key_event->state >= Mod1Mask)
1739 lose_selection (NULL, NULL);
1745 if (key_event->state >= Mod1Mask)
1747 lose_selection (NULL, NULL);
1755 if (buf[0] == 17) /* C-q */
1757 XtAppSetExitFlag (context);
1760 else if (buf[0] == 12) /* C-l */
1762 redraw (0, win_height, 1, 1);
1765 else if (buf[0] == '='
1766 && (event->xkey.state & ControlMask)
1767 && unicode_input_method >= 0)
1769 saved_input_method = current_input_method;
1770 InputMethodProc (w, (XtPointer) unicode_input_method, NULL);
1771 minput_filter (current_input_context, msymbol ("C-u"), NULL);
1775 MText *temp = mtext ();
1777 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1778 : ((unsigned char *) buf)[0]);
1779 if (current_input_context)
1780 mtext_put_prop (temp, 0, 1, Mlanguage,
1781 current_input_context->im->language);
1782 insert_chars (temp);
1783 m17n_object_unref (temp);
1788 if (! keep_target_x_position)
1789 target_x_position = cursor.x;
1793 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1795 char *name = (char *) client_data;
1797 int from = -1, to = 0;
1802 filename = strdup (name);
1805 fp = fopen (filename, "w");
1808 fprintf (stderr, "Open for write fail: %s", filename);
1814 from = mtext_property_start (selection);
1815 to = mtext_property_end (selection);
1816 mtext_detach_property (selection);
1819 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1822 select_region (from, to);
1826 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1832 mtext_detach_property (selection);
1833 serialized = (int) client_data;
1835 new = mtext_deserialize (mt);
1838 MPlist *plist = mplist ();
1840 mplist_push (plist, Mt, Mface);
1841 mplist_push (plist, Mt, Mlanguage);
1842 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1843 m17n_object_unref (plist);
1847 m17n_object_unref (mt);
1849 serialized = ! serialized;
1850 nchars = mtext_len (mt);
1853 update_cursor (0, 1);
1854 redraw (0, win_height, 1, 1);
1858 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1860 XtAppSetExitFlag (context);
1866 FILE *fp = fopen (filename, "r");
1869 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1870 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1873 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1878 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1880 int data = (int) client_data;
1885 control.enable_bidi = 0;
1886 control.orientation_reversed = 0;
1890 control.enable_bidi = 1;
1891 control.orientation_reversed = data == 2;
1893 for (i = 0; i < 3; i++)
1896 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1898 XtSetArg (arg[0], XtNleftBitmap, None);
1899 XtSetValues (BidiMenus[i], arg, 1);
1902 update_cursor (cursor.from, 1);
1903 redraw (0, win_height, 1, 0);
1907 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1909 int data = (int) client_data;
1913 control.max_line_width = 0;
1916 control.max_line_width = win_width;
1917 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1919 for (i = 0; i < 3; i++)
1922 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1924 XtSetArg (arg[0], XtNleftBitmap, None);
1925 XtSetValues (LineBreakMenus[i], arg, 1);
1928 update_cursor (cursor.from, 1);
1929 redraw (0, win_height, 1, 0);
1933 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1935 char *filter_module = (char *) client_data;
1937 void (*func) (MText *, int, int);
1941 handle = dlopen (filter_module, RTLD_NOW);
1944 func = (void (*) (MText *, int, int)) dlsym (handle, "filter");
1946 (*func) (mt, mtext_property_start (selection),
1947 mtext_property_end (selection));
1952 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1954 int data = (int) client_data;
1968 control.cursor_bidi = 0, control.cursor_width = -1;
1972 control.cursor_bidi = 0, control.cursor_width = 2;
1976 control.cursor_bidi = 1;
1981 for (i = from; i < to; i++)
1984 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1986 XtSetArg (arg[0], XtNleftBitmap, None);
1987 XtSetValues (CursorMenus[i], arg, 1);
1990 update_cursor (cursor.from, 0);
1991 redraw (0, win_height, 1, 0);
1995 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1997 int idx = (int) client_data;
1999 if (idx == -2 ? (! auto_input_method && current_input_method < 0)
2000 : idx == -1 ? auto_input_method
2001 : idx == current_input_method)
2004 if (auto_input_method)
2006 select_input_method (-1);
2007 XtSetArg (arg[0], XtNleftBitmap, None);
2008 XtSetValues (InputMethodMenus[1], arg, 1);
2009 auto_input_method = 0;
2014 select_input_method (-1);
2015 XtSetArg (arg[0], XtNleftBitmap, None);
2016 XtSetValues (InputMethodMenus[0], arg, 1);
2017 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
2018 XtSetValues (InputMethodMenus[1], arg, 1);
2019 auto_input_method = 1;
2024 select_input_method (idx);
2028 MPlist *default_face_list;
2031 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
2033 int idx = (int) client_data;
2044 MFace *face = mframe_get_prop (frame, Mface);
2046 for (plist = default_face_list; mplist_key (plist) != Mnil;
2047 plist = mplist_next (plist))
2048 mface_merge (face, mplist_value (plist));
2049 mplist_add (plist, Mt, *face_table[idx].face);
2050 mface_merge (face, *face_table[idx].face);
2052 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
2054 MFace *face = mframe_get_prop (frame, Mface);
2056 for (plist = default_face_list;
2057 mplist_key (mplist_next (plist)) != Mnil;
2058 plist = mplist_next (plist))
2059 mface_merge (face, mplist_value (plist));
2063 update_cursor (0, 1);
2064 redraw (0, win_height, 1, 1);
2069 XtAppAddWorkProc (context, show_cursor, NULL);
2070 from = mtext_property_start (selection);
2071 to = mtext_property_end (selection);
2072 old_y1 = sel_end.y1;
2074 mtext_detach_property (selection);
2077 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
2078 MTEXTPROP_REAR_STICKY);
2079 mtext_push_property (mt, from, to, prop);
2080 m17n_object_unref (prop);
2083 mtext_pop_prop (mt, from, to, Mface);
2085 update_top (top.from);
2086 update_cursor (cursor.from, 1);
2087 select_region (from, to);
2088 update_region (sel_start.y0, old_y1, sel_end.y1);
2089 if (cur.y1 > win_height)
2091 while (cur.y1 > win_height)
2094 update_cursor (cursor.from, 1);
2100 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2102 MSymbol sym = (MSymbol) client_data;
2109 XtAppAddWorkProc (context, show_cursor, NULL);
2110 from = mtext_property_start (selection);
2111 to = mtext_property_end (selection);
2112 old_y1 = sel_end.y1;
2114 mtext_detach_property (selection);
2116 mtext_put_prop (mt, from, to, Mlanguage, sym);
2118 mtext_pop_prop (mt, from, to, Mlanguage);
2121 update_top (top.from);
2122 update_cursor (cursor.from, 1);
2123 select_region (from, to);
2124 update_region (sel_start.y0, old_y1, sel_end.y1);
2125 if (cur.y1 > win_height)
2127 while (cur.y1 > win_height)
2130 update_cursor (cursor.from, 1);
2136 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2138 int narrowed = (int) client_data;
2141 MConverter *converter;
2147 from = mtext_property_start (selection);
2148 to = mtext_property_end (selection);
2157 mdump = popen ("mdump -q -p a4", "w");
2159 mdump = popen ("mdump -q", "w");
2162 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2163 mconv_encode_range (converter, mt, from, to);
2164 mconv_free_converter (converter);
2169 input_status (MInputContext *ic, MSymbol command)
2171 XFillRectangle (display, input_status_pixmap, gc_inv,
2172 0, 0, input_status_width, input_status_height);
2173 if (command == Minput_status_draw)
2177 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2178 Mface, face_input_status);
2179 if (ic->im->language != Mnil)
2180 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2181 Mlanguage, ic->im->language);
2182 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2183 &input_status_control, NULL, NULL, &rect);
2184 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2185 input_status_width - rect.width - 2, - rect.y,
2186 ic->status, 0, mtext_len (ic->status),
2187 &input_status_control);
2189 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2190 XtSetValues (CurIMStatus, arg, 1);
2194 surrounding_text_handler (MInputContext *ic, MSymbol command)
2196 if (command == Minput_get_surrounding_text)
2198 int len = (int) mplist_value (ic->plist);
2204 pos = cursor.from + len;
2207 surround = mtext_duplicate (mt, pos, cursor.from);
2211 pos = cursor.from + len;
2214 surround = mtext_duplicate (mt, cursor.from, pos);
2217 surround = mtext ();
2218 mplist_set (ic->plist, Mtext, surround);
2219 m17n_object_unref (surround);
2221 else if (command == Minput_delete_surrounding_text)
2223 int len = (int) mplist_value (ic->plist);
2227 if (cursor.from + len < 0)
2228 len = - cursor.from;
2229 mtext_del (mt, cursor.from + len, cursor.from);
2231 update_cursor (cursor.from + len, 1);
2235 if (cursor.from + len > nchars)
2236 len = nchars - cursor.from;
2237 mtext_del (mt, cursor.from, cursor.from + len);
2239 update_cursor (cursor.from, 1);
2247 compare_input_method (const void *elt1, const void *elt2)
2249 const InputMethodInfo *im1 = elt1;
2250 const InputMethodInfo *im2 = elt2;
2251 MSymbol lang1, lang2;
2253 if (im1->language == Mnil)
2255 if (im1->language == im2->language)
2256 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2257 if (im1->language == Mt)
2259 if (im2->language == Mt)
2261 lang1 = mlanguage_name (im1->language);
2262 lang2 = mlanguage_name (im2->language);
2263 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2267 setup_input_methods (int with_xim, char *initial_input_method)
2269 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2272 MSymbol Municode = msymbol ("unicode");
2274 num_input_methods = plist ? mplist_length (plist) : 0;
2276 num_input_methods++;
2277 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2282 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
2284 MDatabase *mdb = mplist_value (pl);
2285 MSymbol *tag = mdatabase_tag (mdb);
2288 i--, num_input_methods--;
2291 input_method_table[i].language = tag[1];
2292 input_method_table[i].name = tag[2];
2295 m17n_object_unref (plist);
2299 input_method_table[i].language = Mnil;
2300 input_method_table[i].name = msymbol ("xim");
2304 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2305 compare_input_method);
2306 for (i = 0; i < num_input_methods; i++)
2307 if (input_method_table[i].language == Mt
2308 && input_method_table[i].name == Municode)
2310 unicode_input_method = i;
2313 mplist_put_func (minput_driver->callback_list, Minput_status_start,
2314 M17N_FUNC (input_status));
2315 mplist_put_func (minput_driver->callback_list, Minput_status_draw,
2316 M17N_FUNC (input_status));
2317 mplist_put_func (minput_driver->callback_list, Minput_status_done,
2318 M17N_FUNC (input_status));
2319 mplist_put_func (minput_driver->callback_list, Minput_get_surrounding_text,
2320 M17N_FUNC (surrounding_text_handler));
2321 mplist_put_func (minput_driver->callback_list, Minput_delete_surrounding_text,
2322 M17N_FUNC (surrounding_text_handler));
2324 current_input_context = NULL;
2325 current_input_method = -1;
2327 if (initial_input_method)
2329 char *lang_name, *method_name;
2330 char *p = strchr (initial_input_method, '-');
2333 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2335 lang_name = "t", method_name = initial_input_method;
2337 for (i = 0; i < num_input_methods; i++)
2338 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2340 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2342 current_input_method = i;
2350 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2354 if (num && *num > 0)
2358 for (i = 0; i < *num; i++)
2359 bytes += strlen (str[i]) + 1;
2360 msg = alloca (bytes);
2361 strcpy (msg, str[0]);
2362 for (i = 1; i < *num; i++)
2363 strcat (msg, " "), strcat (msg, str[i]);
2365 else if (cursor.from < nchars)
2367 int c = mtext_ref_char (mt, cursor.from);
2368 char *name = mchar_get_prop (c, Mname);
2372 msg = alloca (10 + strlen (name));
2373 sprintf (msg, "U+%04X %s", c, name);
2379 XtSetArg (arg[0], XtNlabel, msg);
2380 XtSetValues (MessageWidget, arg, 1);
2386 char *name1, *name2;
2387 XtCallbackProc proc;
2388 XtPointer client_data;
2393 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2395 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2397 MenuRec FileMenu[] =
2398 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2399 { 0, "Save", NULL, SaveProc, NULL, -1 },
2400 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2402 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2403 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2405 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2406 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2408 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2411 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2413 MenuRec *rec = (MenuRec *) client_data;
2416 XtSetArg (arg[0], XtNvalue, "");
2417 XtSetArg (arg[1], XtNlabel, rec->name1);
2418 XtSetValues (FileDialogWidget, arg, 2);
2419 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2420 XtSetArg (arg[0], XtNx, x + 20);
2421 XtSetArg (arg[1], XtNy, y + 10);
2422 XtSetValues (FileShellWidget, arg, 2);
2423 XtPopup (FileShellWidget, XtGrabExclusive);
2427 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2432 XtPopdown (FileShellWidget);
2433 if ((int) client_data == 1)
2435 XtSetArg (arg[0], XtNlabel, &label);
2436 XtGetValues (FileDialogWidget, arg, 1);
2437 if (strcmp (label, FileMenu[0].name1) == 0)
2441 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2442 fp = fopen (filename, "r");
2444 m17n_object_unref (mt);
2447 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2455 nchars = mtext_len (mt);
2457 update_cursor (0, 1);
2458 redraw (0, win_height, 1, 1);
2460 else if (strcmp (label, FileMenu[2].name1) == 0)
2461 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2463 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2466 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2467 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2468 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2469 (MENU).status = (STATUS))
2473 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2474 char *menu_name, MenuRec *menus, int num_menus, char *help)
2476 Widget button, menu;
2477 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2478 <LeaveWindow>: reset() MenuHelp()\n\
2479 <BtnDown>: reset() PopupMenu()\n\
2480 <BtnUp>: highlight()";
2486 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2487 for (i = 0; i < num_menus; i++)
2498 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2500 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2502 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2504 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2508 XtSetArg (arg[0], XtNsensitive, False);
2509 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2515 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2520 trans = alloca (strlen (fmt) + strlen (help));
2521 sprintf (trans, fmt, help);
2522 XtSetArg (arg[0], XtNmenuName, menu_name);
2523 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2524 XtSetArg (arg[2], XtNinternalWidth, 2);
2525 XtSetArg (arg[3], XtNhighlightThickness, 1);
2526 XtSetArg (arg[4], XtNleft, XawChainLeft);
2527 XtSetArg (arg[5], XtNright, XawChainLeft);
2528 XtSetArg (arg[6], XtNinternational, True);
2531 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2532 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2537 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2538 int *len = alloca (sizeof (int) * num_menus);
2541 XFontSetExtents *fontset_extents;
2543 XtSetArg (arg[0], XtNfontSet, &font_set);
2544 XtGetValues (button, arg, 1);
2546 fontset_extents = XExtentsOfFontSet (font_set);
2547 height = fontset_extents->max_logical_extent.height;
2548 ascent = - fontset_extents->max_logical_extent.y;
2550 for (i = 0; i < num_menus; i++)
2553 len[i] = strlen (menus[i].name2);
2554 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2555 if (max_width < width[i])
2556 max_width = width[i];
2558 for (i = 0; i < num_menus; i++)
2561 Pixmap pixmap = XCreatePixmap (display,
2562 RootWindow (display, screen),
2563 max_width, height, 1);
2564 XFillRectangle (display, pixmap, mono_gc_inv,
2565 0, 0, max_width, height);
2566 XmbDrawString (display, pixmap, font_set, mono_gc,
2567 max_width - width[i], ascent,
2568 menus[i].name2, len[i]);
2569 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2570 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2571 XtSetValues (menus[i].w, arg, 2);
2579 XtActionsRec actions[] = {
2580 {"Expose", ExposeProc},
2581 {"Configure", ConfigureProc},
2583 {"ButtonPress", ButtonProc},
2584 {"ButtonRelease", ButtonReleaseProc},
2585 {"ButtonMotion", ButtonMoveProc},
2586 {"Button2Press", Button2Proc},
2587 {"MenuHelp", MenuHelpProc},
2588 {"FocusIn", FocusInProc},
2589 {"FocusOut", FocusOutProc}
2593 /* Print the usage of this program (the name is PROG), and exit with
2597 help_exit (char *prog, int exit_code)
2605 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2606 printf ("Display FILE on a window and allow users to edit it.\n");
2607 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2608 printf ("The following OPTIONs are available.\n");
2609 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2610 "Use the specified fontset\n");
2611 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2612 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2613 "Input method activated initially.\n");
2614 printf (" %-13s %s", "--version", "print version number\n");
2615 printf (" %-13s %s", "-h, --help", "print this message\n");
2621 main (int argc, char **argv)
2623 Widget form, BodyWidget, w;
2624 char *fontset_name = NULL;
2625 char *font_name = NULL;
2627 char *initial_input_method = NULL;
2628 int col = 80, row = 32;
2629 /* Translation table for TextWidget. */
2630 String trans = "<Expose>: Expose()\n\
2631 <Configure>: Configure()\n\
2634 <Btn1Down>: ButtonPress()\n\
2635 <Btn1Up>: ButtonRelease()\n\
2636 <Btn1Motion>: ButtonMotion()\n\
2637 <Btn2Down>: Button2Press()";
2638 /* Translation table for the top form widget. */
2639 String trans2 = "<Key>: Key()\n\
2641 <FocusIn>: FocusIn()\n\
2642 <FocusOut>: FocusOut()";
2643 String pop_face_trans
2644 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2645 <LeaveWindow>: MenuHelp() reset()\n\
2646 <Btn1Down>: set()\n\
2647 <Btn1Up>: notify() unset()";
2648 String pop_lang_trans
2649 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2650 <LeaveWindow>: MenuHelp() reset()\n\
2651 <Btn1Down>: set()\n\
2652 <Btn1Up>: notify() unset()";
2653 int font_width, font_ascent, font_descent;
2656 char *filter = NULL;
2659 setlocale (LC_ALL, "");
2660 /* Create the top shell. */
2661 XtSetLanguageProc (NULL, NULL, NULL);
2662 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2663 NULL, sessionShellWidgetClass, NULL, 0);
2664 display = XtDisplay (ShellWidget);
2665 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2667 /* Parse the remaining command line arguments. */
2668 for (i = 1; i < argc; i++)
2670 if (! strcmp (argv[i], "--help")
2671 || ! strcmp (argv[i], "-h"))
2672 help_exit (argv[0], 0);
2673 else if (! strcmp (argv[i], "--version"))
2675 printf ("m17n-edit (m17n library) %s\n", M17NLIB_VERSION_NAME);
2676 printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 AIST, JAPAN\n");
2679 else if (! strcmp (argv[i], "--geometry"))
2682 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2683 help_exit (argv[0], 1);
2685 else if (! strcmp (argv[i], "-s"))
2688 fontsize = atoi (argv[i]);
2692 else if (! strcmp (argv[i], "--fontset"))
2695 fontset_name = strdup (argv[i]);
2697 else if (! strcmp (argv[i], "--font"))
2700 font_name = strdup (argv[i]);
2702 else if (! strcmp (argv[i], "--im"))
2705 initial_input_method = strdup (argv[i]);
2707 else if (! strcmp (argv[i], "--with-xim"))
2711 else if (! strcmp (argv[i], "--filter"))
2716 else if (argv[i][0] != '-')
2718 filename = strdup (argv[i]);
2722 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2723 help_exit (argv[0], 1);
2727 filename = strdup ("/dev/null");
2729 mdatabase_dir = ".";
2730 /* Initialize the m17n library. */
2732 if (merror_code != MERROR_NONE)
2733 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2734 minput_driver = &minput_gui_driver;
2736 mt = read_file (filename);
2739 nchars = mtext_len (mt);
2741 Mword = msymbol ("word");
2744 MFace *face = mface ();
2746 mface_put_prop (face, Mforeground, msymbol ("blue"));
2747 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2748 mface_put_prop (face, Mvideomode, Mreverse);
2749 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2750 m17n_object_unref (face);
2753 /* This tells ExposeProc to initialize everything. */
2756 XA_TEXT = XInternAtom (display, "TEXT", False);
2757 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2758 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2759 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2760 if (Mcoding_compound_text == Mnil)
2761 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2764 MPlist *plist = mplist ();
2767 mplist_put (plist, msymbol ("widget"), ShellWidget);
2768 if (fontset_name || font_name || fontsize > 0)
2774 font = mfont_parse_name (font_name, Mnil);
2776 face = mface_from_font (font);
2784 MFontset *fontset = mfontset (fontset_name);
2786 mface_put_prop (face, Mfontset, fontset);
2787 m17n_object_unref (fontset);
2790 mface_put_prop (face, Msize, (void *) fontsize);
2791 mplist_add (plist, Mface, face);
2792 m17n_object_unref (face);
2794 frame = mframe (plist);
2796 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2797 m17n_object_unref (plist);
2798 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2799 default_face_list = mplist ();
2800 mplist_add (default_face_list, Mt, face_default);
2801 face_default_fontset = mface ();
2802 mface_put_prop (face_default_fontset, Mfontset,
2803 mface_get_prop (face_default, Mfontset));
2805 font = (MFont *) mframe_get_prop (frame, Mfont);
2806 default_font_size = (int) mfont_get_prop (font, Msize);
2809 font_width = (int) mframe_get_prop (frame, Mfont_width);
2810 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2811 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2812 win_width = font_width * col;
2813 win_height = (font_ascent + font_descent) * row;
2819 prop.color_top = prop.color_left = msymbol ("magenta");
2820 prop.color_bottom = prop.color_right = msymbol ("red");
2821 prop.inner_hmargin = prop.inner_vmargin = 1;
2822 prop.outer_hmargin = prop.outer_vmargin = 2;
2824 face_box = mface ();
2825 mface_put_prop (face_box, Mbox, &prop);
2828 face_courier = mface ();
2829 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2830 face_helvetica = mface ();
2831 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2832 face_times = mface ();
2833 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2834 face_dv_ttyogesh = mface ();
2835 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2836 face_freesans = mface ();
2837 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2838 face_freeserif = mface ();
2839 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2840 face_freemono = mface ();
2841 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2843 face_xxx_large = mface ();
2844 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2846 MFont *latin_font = mframe_get_prop (frame, Mfont);
2847 MFont *dev_font = mfont ();
2848 MFont *thai_font = mfont ();
2849 MFont *tib_font = mfont ();
2850 MFontset *fontset, *fontset_no_ctl;
2851 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2852 MSymbol no_ctl = msymbol ("no-ctl");
2854 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2855 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2856 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2857 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2858 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2859 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2861 fontset = mfontset (fontset_name);
2862 fontset_no_ctl = mfontset_copy (fontset, "no-ctl");
2863 m17n_object_unref (fontset);
2864 mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil,
2865 latin_font, Mnil, 0);
2866 mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil,
2867 dev_font, no_ctl, 0);
2868 mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil,
2869 thai_font, no_ctl, 0);
2870 mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil,
2871 tib_font, no_ctl, 0);
2872 face_no_ctl_fontset = mface ();
2873 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl);
2874 m17n_object_unref (fontset_no_ctl);
2881 setup_input_methods (with_xim, initial_input_method);
2883 gc = DefaultGC (display, screen);
2885 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2886 XtSetArg (arg[1], XtNdefaultDistance, 2);
2887 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2889 XtSetArg (arg[0], XtNborderWidth, 0);
2890 XtSetArg (arg[1], XtNdefaultDistance, 2);
2891 XtSetArg (arg[2], XtNtop, XawChainTop);
2892 XtSetArg (arg[3], XtNbottom, XawChainTop);
2893 XtSetArg (arg[4], XtNleft, XawChainLeft);
2894 XtSetArg (arg[5], XtNright, XawChainRight);
2895 XtSetArg (arg[6], XtNresizable, True);
2896 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2897 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2898 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2899 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2900 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2901 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2902 XtSetArg (arg[7], XtNfromVert, LangWidget);
2903 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2904 XtSetArg (arg[2], XtNtop, XawChainBottom);
2905 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2906 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2908 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2909 HeadWidget, NULL, 0);
2910 XtSetArg (arg[0], XtNvalue, "");
2911 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2912 FileShellWidget, arg, 1);
2913 XawDialogAddButton (FileDialogWidget, "OK",
2914 FileDialogProc, (XtPointer) 0);
2915 XawDialogAddButton (FileDialogWidget, "CANCEL",
2916 FileDialogProc, (XtPointer) 1);
2918 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2919 (char *) check_bits,
2920 check_width, check_height);
2922 unsigned long valuemask = GCForeground;
2925 values.foreground = 1;
2926 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2927 values.foreground = 0;
2928 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2935 if (num_menus < num_input_methods + 2)
2936 num_menus = num_input_methods + 2;
2937 if (num_menus < num_faces + 1)
2938 num_menus = num_faces + 1;
2939 menus = alloca (sizeof (MenuRec) * num_menus);
2941 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2942 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2943 "File I/O, Serialization, Image, Quit");
2945 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2946 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2947 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2948 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2949 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2950 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2951 w = create_menu_button (ShellWidget, HeadWidget, w,
2952 "Cursor", "Cursor Menu",
2953 menus, 6, "Cursor Movement Mode, Cursor Shape");
2954 CursorMenus[0] = menus[0].w;
2955 CursorMenus[1] = menus[1].w;
2956 CursorMenus[2] = menus[3].w;
2957 CursorMenus[3] = menus[4].w;
2958 CursorMenus[4] = menus[5].w;
2960 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2961 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2962 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2963 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2964 menus, 3, "BIDI Processing Mode");
2965 for (i = 0; i < 3; i++)
2966 BidiMenus[i] = menus[i].w;
2968 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2969 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2970 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2971 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2973 menus, 3, "How to break lines");
2974 for (i = 0; i < 3; i++)
2975 LineBreakMenus[i] = menus[i].w;
2977 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2978 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2979 for (i = 0; i < num_input_methods; i++)
2981 InputMethodInfo *im = input_method_table + i;
2982 char *name1, *name2;
2984 if (im->language != Mnil && im->language != Mt)
2986 MSymbol sym = mlanguage_name (im->language);
2988 name1 = msymbol_name (im->language);
2990 name1 = msymbol_name (sym);
2991 name2 = msymbol_name (im->name);
2994 name1 = msymbol_name (im->name), name2 = NULL;
2996 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2998 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2999 "Input Method Menu", menus, i + 2,
3000 "Select input method");
3003 unsigned long valuemask = GCForeground;
3006 XtSetArg (arg[0], XtNbackground, &values.foreground);
3007 XtGetValues (w, arg, 1);
3008 gc_inv = XCreateGC (display, RootWindow (display, screen),
3009 valuemask, &values);
3012 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
3013 for (i = 0; i < num_input_methods + 2; i++)
3014 InputMethodMenus[i] = menus[i].w;
3018 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
3019 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
3020 "Filter Menu", menus, 1,
3021 "Select filter to run");
3024 input_status_width = font_width * 8;
3025 input_status_height = (font_ascent + font_descent) * 2.4;
3026 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
3028 input_status_height,
3029 DefaultDepth (display, screen));
3034 prop.color_top = prop.color_bottom
3035 = prop.color_left = prop.color_right = Mnil;
3036 prop.inner_hmargin = prop.inner_vmargin = 1;
3037 prop.outer_hmargin = prop.outer_vmargin = 0;
3038 face_input_status = mface_copy (face_default);
3039 mface_put_prop (face_input_status, Mbox, &prop);
3042 XFillRectangle (display, input_status_pixmap, gc_inv,
3043 0, 0, input_status_width, input_status_height);
3044 XtSetArg (arg[0], XtNfromHoriz, w);
3045 XtSetArg (arg[1], XtNleft, XawRubber);
3046 XtSetArg (arg[2], XtNright, XawChainRight);
3047 XtSetArg (arg[3], XtNborderWidth, 0);
3048 XtSetArg (arg[4], XtNlabel, " ");
3049 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3050 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
3051 HeadWidget, arg, 6);
3052 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
3053 XtSetArg (arg[1], XtNleft, XawChainRight);
3054 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
3055 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
3056 HeadWidget, arg, 5);
3058 XtSetArg (arg[0], XtNborderWidth, 0);
3059 XtSetArg (arg[1], XtNleft, XawChainLeft);
3060 XtSetArg (arg[2], XtNright, XawChainLeft);
3061 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
3062 for (i = 0; i < num_faces;)
3064 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
3065 char *label = label_menu + 5; /* "Xxxx" */
3067 for (j = i; j < num_faces && face_table[j].face; j++)
3068 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
3070 w = create_menu_button (ShellWidget, FaceWidget, w,
3072 menus, j - i, "Push face property");
3076 XtSetArg (arg[0], XtNfromHoriz, w);
3077 XtSetArg (arg[1], XtNleft, XawChainLeft);
3078 XtSetArg (arg[2], XtNright, XawChainLeft);
3079 XtSetArg (arg[3], XtNhorizDistance, 10);
3080 XtSetArg (arg[4], XtNlabel, "Pop");
3081 XtSetArg (arg[5], XtNtranslations,
3082 XtParseTranslationTable (pop_face_trans));
3083 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
3084 FaceWidget, arg, 6);
3085 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
3087 XtSetArg (arg[0], XtNfromHoriz, w);
3088 XtSetArg (arg[1], XtNleft, XawChainLeft);
3089 XtSetArg (arg[2], XtNright, XawChainRight);
3090 XtSetArg (arg[3], XtNlabel, "");
3091 XtSetArg (arg[4], XtNborderWidth, 0);
3092 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3093 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
3094 FaceWidget, arg, 6);
3096 XtSetArg (arg[0], XtNborderWidth, 0);
3097 XtSetArg (arg[1], XtNleft, XawChainLeft);
3098 XtSetArg (arg[2], XtNright, XawChainLeft);
3099 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
3101 MPlist *plist[11], *pl;
3104 for (i = 0; i < 11; i++) plist[i] = NULL;
3106 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
3107 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
3109 MSymbol sym = msymbol_exist (langname);
3113 && ((fullname = mlanguage_name (sym)) != Mnil))
3115 char *name = msymbol_name (fullname);
3118 if (c >= 'a' && c <= 'z')
3120 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
3124 pl = plist[idx] = mplist ();
3125 for (; mplist_next (pl); pl = mplist_next (pl))
3126 if (strcmp (name, (char *) mplist_value (pl)) < 0)
3128 mplist_push (pl, sym, fullname);
3133 for (i = 0; i < 11; i++)
3136 char *name = alloca (9);
3138 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
3141 for (j = 0, pl = plist[i]; mplist_next (pl);
3142 j++, pl = mplist_next (pl))
3143 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
3144 msymbol_name (mplist_key (pl)),
3145 LangProc, mplist_key (pl), -1);
3146 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
3147 menus, j, "Push language property");
3149 for (i = 0; i < 11; i++)
3151 m17n_object_unref (plist[i]);
3153 XtSetArg (arg[0], XtNfromHoriz, w);
3154 XtSetArg (arg[1], XtNleft, XawChainLeft);
3155 XtSetArg (arg[2], XtNright, XawChainLeft);
3156 XtSetArg (arg[3], XtNhorizDistance, 10);
3157 XtSetArg (arg[4], XtNlabel, "Pop");
3158 XtSetArg (arg[5], XtNtranslations,
3159 XtParseTranslationTable (pop_lang_trans));
3160 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3161 LangWidget, arg, 6);
3162 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3164 XtSetArg (arg[0], XtNfromHoriz, w);
3165 XtSetArg (arg[1], XtNleft, XawChainLeft);
3166 XtSetArg (arg[2], XtNright, XawChainRight);
3167 XtSetArg (arg[3], XtNlabel, "");
3168 XtSetArg (arg[4], XtNborderWidth, 0);
3169 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3170 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3171 LangWidget, arg, 6);
3174 XtSetArg (arg[0], XtNheight, win_height);
3175 XtSetArg (arg[1], XtNwidth, 10);
3176 XtSetArg (arg[2], XtNleft, XawChainLeft);
3177 XtSetArg (arg[3], XtNright, XawChainLeft);
3178 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3180 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3181 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3183 XtSetArg (arg[0], XtNheight, win_height);
3184 XtSetArg (arg[1], XtNwidth, win_width);
3185 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3186 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3187 XtSetArg (arg[4], XtNleft, XawChainLeft);
3188 XtSetArg (arg[5], XtNright, XawChainRight);
3189 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3192 XtSetArg (arg[0], XtNborderWidth, 0);
3193 XtSetArg (arg[1], XtNleft, XawChainLeft);
3194 XtSetArg (arg[2], XtNright, XawChainRight);
3195 XtSetArg (arg[3], XtNresizable, True);
3196 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3197 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3198 TailWidget, arg, 5);
3200 memset (&control, 0, sizeof control);
3201 control.two_dimensional = 1;
3202 control.enable_bidi = 1;
3203 control.anti_alias = 1;
3204 control.min_line_ascent = font_ascent;
3205 control.min_line_descent = font_descent;
3206 control.max_line_width = win_width;
3207 control.with_cursor = 1;
3208 control.cursor_width = 2;
3209 control.partial_update = 1;
3210 control.ignore_formatting_char = 1;
3212 memset (&input_status_control, 0, sizeof input_status_control);
3213 input_status_control.enable_bidi = 1;
3215 XtAppAddActions (context, actions, XtNumber (actions));
3216 XtRealizeWidget (ShellWidget);
3218 win = XtWindow (TextWidget);
3220 XtAppMainLoop (context);
3222 if (current_input_context)
3223 minput_destroy_ic (current_input_context);
3224 for (i = 0; i < num_input_methods; i++)
3225 if (input_method_table[i].im)
3226 minput_close_im (input_method_table[i].im);
3227 m17n_object_unref (frame);
3228 m17n_object_unref (mt);
3229 m17n_object_unref (face_xxx_large);
3230 m17n_object_unref (face_box);
3231 m17n_object_unref (face_courier);
3232 m17n_object_unref (face_helvetica);
3233 m17n_object_unref (face_times);
3234 m17n_object_unref (face_dv_ttyogesh);
3235 m17n_object_unref (face_freesans);
3236 m17n_object_unref (face_freeserif);
3237 m17n_object_unref (face_freemono);
3238 m17n_object_unref (face_default_fontset);
3239 m17n_object_unref (face_no_ctl_fontset);
3240 m17n_object_unref (face_input_status);
3241 m17n_object_unref (face_default);
3242 m17n_object_unref (default_face_list);
3243 m17n_object_unref (selection);
3247 XFreeGC (display, mono_gc);
3248 XFreeGC (display, mono_gc_inv);
3249 XFreeGC (display, gc_inv);
3250 XtUninstallTranslations (form);
3251 XtUninstallTranslations (TextWidget);
3252 XtDestroyWidget (ShellWidget);
3253 XtDestroyApplicationContext (context);
3258 free (fontset_name);
3260 free (input_method_table);
3261 free (InputMethodMenus);
3266 #else /* not HAVE_X11_XAW_COMMAND_H */
3269 main (int argc, char **argv)
3272 "Building of this program failed (lack of some header files)\n");
3276 #endif /* not HAVE_X11_XAW_COMMAND_H */
3278 #endif /* not FOR_DOXYGEN */