1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004, 2005, 2006, 2007
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 auto_input_method = 0;
203 MInputContext *current_input_context;
210 { {"Menu Size", NULL},
211 {"xx-small", &mface_xx_small},
212 {"x-small", &mface_x_small},
213 {"small", &mface_small},
214 {"normalsize", &mface_normalsize},
215 {"large", &mface_large},
216 {"x-large", &mface_x_large},
217 {"xx-large", &mface_xx_large},
218 {"xxx-large", &face_xxx_large},
220 {"Menu Family", NULL},
221 {"courier", &face_courier},
222 {"helvetica", &face_helvetica},
223 {"times", &face_times},
224 {"dv-ttyogesh", &face_dv_ttyogesh},
225 {"freesans", &face_freesans},
226 {"freeserif", &face_freeserif},
227 {"freemono", &face_freemono},
229 {"Menu Style", NULL},
230 {"medium", &mface_medium},
231 {"bold", &mface_bold},
232 {"italic", &mface_italic},
234 {"Menu Color", NULL},
235 {"black", &mface_black},
236 {"white", &mface_white},
238 {"green", &mface_green},
239 {"blue", &mface_blue},
240 {"cyan", &mface_cyan},
241 {"yello", &mface_yellow},
242 {"magenta", &mface_magenta},
245 {"normal", &mface_normal_video},
246 {"reverse", &mface_reverse_video},
247 {"underline", &mface_underline},
249 {"No CTL", &face_no_ctl_fontset} };
252 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
254 /* Information about a physical line metric. */
257 int from; /* BOL position of the line. */
258 int to; /* BOL position of the next line. */
259 int y0, y1; /* Top and bottom Y position of the line. */
260 int ascent; /* Height of the top Y position. */
263 struct LineInfo top; /* Topmost line. */
264 struct LineInfo cur; /* Line containing cursor. */
265 struct LineInfo sel_start; /* Line containing selection start. */
266 struct LineInfo sel_end; /* Line containing selection end. */
268 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
270 /* X position to keep on vertical (up and down) cursor motion. */
271 int target_x_position;
273 /* Interface macros for m17n-lib drawing routines. */
275 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
276 coordinate ($X, $Y) */
277 #define DRAW_TEXT(x, y, from, to) \
278 mdraw_text_with_control \
279 (frame, (MDrawWindow) win, \
280 control.orientation_reversed ? x + win_width : x, y, \
281 mt, from, to, &control)
283 /* Store the extents of a text in the range $FROM to $TO in the
284 structure $RECT (type MDrawMetric). */
285 #define TEXT_EXTENTS(from, to, rect) \
286 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
288 /* Store the glyph information of a character at the position $POS in
289 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
290 $FROM is written at the coordinate (0, 0). */
291 #define GLYPH_INFO(from, pos, info) \
292 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
294 /* Set $X and $Y to the coordinate of character at position $POS
295 assuming that the text from $FROM is written at the coordinate (0,
297 #define COORDINATES_POSITION(from, pos, x, y) \
298 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
300 /* Interface macros for X library. */
301 #define COPY_AREA(y0, y1, to) \
302 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
304 #define CLEAR_AREA(x, y, w, h) \
305 XClearArea (display, win, (x), (y), (w), (h), False)
307 #define SELECTEDP() \
308 mtext_property_mtext (selection)
310 /* Format MSG by FMT and print the result to the stderr, and exit. */
311 #define FATAL_ERROR(fmt, arg) \
313 fprintf (stderr, fmt, arg); \
318 /* If POS is greater than zero, move POS back to the beginning of line
319 (BOL) position. If FORWARD is nonzero, move POS forward instead.
320 Return the new position. */
322 bol (int pos, int forward)
324 int limit = forward ? nchars : 0;
326 pos = mtext_character (mt, pos, limit, '\n');
327 return (pos < 0 ? limit : pos + 1);
330 /* Update the structure #TOP (struct LineInfo) to make $POS the first
331 character position of the screen. */
335 int from = bol (pos, 0);
338 GLYPH_INFO (from, pos, info);
339 top.from = info.line_from;
340 top.to = info.line_to;
342 top.y1 = info.metrics.height;
343 top.ascent = - info.metrics.y;
347 /* Update the scroll bar so that the text of the range $FROM to $TO
348 are shown on the window. */
350 update_scroll_bar (int from, int to)
352 float top = (float) from / nchars;
353 float shown = (float) (to - from) / nchars;
354 XtArgVal *l_top = (XtArgVal *) ⊤
355 XtArgVal *l_shown = (XtArgVal *) &shown;
357 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
358 XtSetArg (arg[1], XtNshown, *l_shown);
359 XtSetValues (SbarWidget, arg, 2);
363 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
364 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
365 is nonzero, update the scoll bar. */
367 redraw (int y0, int y1, int clear, int scroll_bar)
372 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
373 struct LineInfo *line;
375 if (clear || control.anti_alias)
376 CLEAR_AREA (0, y0, win_width, y1 - y0);
378 /* Find a line closest to y0. It is a cursor line if the cursor is
379 Y0, otherwise the top line. */
384 /* If there exists a selected region, check it too. */
385 if (sel_y0 > line->y0 && y0 >= sel_y0)
390 info.metrics.height = line->y1 - y;
391 info.metrics.y = - line->ascent;
392 info.line_to = line->to;
393 while (y + info.metrics.height <= y0)
395 y += info.metrics.height;
399 GLYPH_INFO (from, from, info);
401 if (y + info.metrics.height <= y0)
404 y0 = y - info.metrics.y;
406 while (to < nchars && y < y1)
408 GLYPH_INFO (to, to, info);
409 y += info.metrics.height;
415 DRAW_TEXT (0, y0, from, to);
420 GLYPH_INFO (to, to, info);
421 if (y + info.metrics.height >= win_height)
424 y += info.metrics.height;
426 update_scroll_bar (top.from, to);
431 /* Set the current input method spot to the correct position. */
433 set_input_method_spot ()
435 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
436 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
439 int size = 0, ratio = 0, i;
442 n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
444 for (i = n - 1; i >= 0; i--)
447 size = (int) mface_get_prop (faces[i], Msize);
449 ratio = (int) mface_get_prop (faces[i], Mratio);
452 size = default_font_size;
454 size = size * ratio / 100;
455 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
456 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
461 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
464 redraw_cursor (int clear)
466 if (control.cursor_bidi)
468 /* We must update the whole line of the cursor. */
469 int beg = bol (cur.from, 0);
470 int end = bol (cur.to - 1, 1);
472 int y0 = cur.y0, y1 = cur.y1;
476 TEXT_EXTENTS (beg, cur.from, rect);
481 TEXT_EXTENTS (cur.to, end, rect);
484 redraw (y0, y1, clear, 0);
492 if (control.orientation_reversed)
493 x += win_width - cursor.logical_width;
494 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
496 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
501 /* Update the information about the location of cursor to the position
502 $POS. If $FULL is nonzero, update the information fully only from
503 the information about the top line. Otherwise, trust the current
504 information in the structure $CUR. */
506 update_cursor (int pos, int full)
512 /* CUR is inaccurate. We can trust only TOP. */
513 GLYPH_INFO (top.from, pos, cursor);
514 cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
516 else if (pos < cur.from)
518 int from = bol (pos, 0);
520 TEXT_EXTENTS (from, cur.from, rect);
521 GLYPH_INFO (from, pos, cursor);
522 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
524 else if (pos < cur.to)
526 GLYPH_INFO (cur.from, pos, cursor);
530 GLYPH_INFO (cur.from, pos, cursor);
531 cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
534 cur.from = cursor.line_from;
535 cur.to = cursor.line_to;
536 cur.y1 = cur.y0 + cursor.metrics.height;
537 cur.ascent = - cursor.metrics.y;
541 /* Update the information about the selected region. */
551 from = mtext_property_start (selection);
552 to = mtext_property_end (selection);
556 int pos = bol (from, 0);
558 TEXT_EXTENTS (pos, top.from, rect);
559 sel_start.y0 = top.y0 - rect.height;
560 sel_start.ascent = - rect.y;
561 GLYPH_INFO (pos, from, info);
562 if (pos < info.line_from)
563 sel_start.y0 += - rect.y + info.y + info.metrics.y;
567 GLYPH_INFO (top.from, from, info);
568 sel_start.y0 = top.ascent + info.y + info.metrics.y;
570 sel_start.ascent = -info.metrics.y;
571 sel_start.y1 = sel_start.y0 + info.metrics.height;
572 sel_start.from = info.line_from;
573 sel_start.to = info.line_to;
575 if (to <= sel_start.to)
581 GLYPH_INFO (sel_start.from, to, info);
582 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
583 sel_end.y1 = sel_end.y0 + info.metrics.height;
584 sel_end.ascent = - info.metrics.y;
585 sel_end.from = info.line_from;
586 sel_end.to = info.line_to;
591 /* Select the text in the region from $FROM to $TO. */
593 select_region (int from, int to)
598 pos = from, from = to, to = pos;
599 mtext_push_property (mt, from, to, selection);
604 /* Setup the window to display the character of $POS at the top left
610 /* Top and bottom Y positions to redraw. */
613 if (pos + 1000 < top.from)
614 y0 = 0, y1 = win_height;
615 else if (pos < top.from)
618 TEXT_EXTENTS (pos, top.from, rect);
619 if (rect.height >= win_height * 0.9)
624 COPY_AREA (0, win_height - y1, y1);
627 else if (pos < top.to)
629 /* No need of redrawing. */
632 else if (pos < top.from + 1000)
634 TEXT_EXTENTS (top.from, pos, rect);
635 if (rect.height >= win_height * 0.9)
639 y0 = win_height - rect.height;
640 COPY_AREA (rect.height, win_height, 0);
645 y0 = 0, y1 = win_height;
651 update_cursor (pos, 1);
653 update_cursor (cursor.from, 1);
655 redraw (y0, y1, 1, 1);
659 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
662 /* Select an input method accoding to $IDX. If $IDX is negative, turn
663 off the current input method, otherwide turn on the input method
664 input_method_table[$IDX]. */
666 select_input_method (idx)
668 int previous_input_method = current_input_method;
670 if (idx == current_input_method)
672 if (current_input_method >= 0)
674 minput_destroy_ic (current_input_context);
675 current_input_context = NULL;
676 current_input_method = -1;
680 && input_method_table[idx].available >= 0)
682 InputMethodInfo *im = input_method_table + idx;
684 if (im->available == 0)
687 im->im = minput_open_im (im->language, im->name, NULL);
690 MInputXIMArgIM arg_xim;
692 arg_xim.display = display;
694 arg_xim.res_name = arg_xim.res_class = NULL;
695 arg_xim.locale = NULL;
696 arg_xim.modifier_list = NULL;
697 im->im = minput_open_im (Mnil, im->name, &arg_xim);
699 im->available = im->im ? 1 : -1;
703 if (im->language == Mnil)
705 MInputXIMArgIC arg_xic;
706 Window win = XtWindow (TextWidget);
708 arg_xic.input_style = 0;
709 arg_xic.client_win = arg_xic.focus_win = win;
710 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
711 current_input_context = minput_create_ic (im->im, &arg_xic);
715 MInputGUIArgIC arg_ic;
717 arg_ic.frame = frame;
718 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
719 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
720 current_input_context = minput_create_ic (im->im, &arg_ic);
723 if (current_input_context)
725 current_input_method = idx;
726 set_input_method_spot ();
730 minput_close_im (im->im);
733 current_input_method = -1;
737 if (! auto_input_method)
739 XtSetArg (arg[0], XtNleftBitmap, None);
740 if (previous_input_method >= 0)
741 XtSetValues (InputMethodMenus[previous_input_method + 2], arg, 1);
743 XtSetValues (InputMethodMenus[0], arg, 1);
744 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
745 if (current_input_method >= 0)
746 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
748 XtSetValues (InputMethodMenus[0], arg, 1);
751 if (current_input_method >= 0)
755 XtSetArg (arg[0], XtNlabel, &label);
756 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
757 XtSetArg (arg[0], XtNlabel, label);
761 XtSetArg (arg[0], XtNlabel, "");
763 XtSetValues (CurIMLang, arg, 1);
766 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
769 /* Display cursor according to the current information of #CUR.
770 $CLIENT_DATA is ignore. Most callback functions add this function
771 as a background processing procedure the current application (by
772 XtAppAddWorkProc) via the function hide_cursor. */
774 show_cursor (XtPointer client_data)
776 MFaceHLineProp *hline;
782 update_cursor (cursor.from, 1);
784 while (cur.y1 > win_height)
787 update_cursor (cursor.from, 1);
790 control.cursor_pos = cursor.from;
793 control.with_cursor = 1;
796 if (current_input_context)
797 set_input_method_spot ();
801 int pos = (SELECTEDP () ? mtext_property_start (selection)
802 : cursor.from > 0 ? cursor.from - 1
804 MFace *face = mface ();
805 MTextProperty *props[256];
806 int n = mtext_get_properties (mt, pos, Mface, props, 256);
808 char buf[256], *p = buf;
814 int size = (int) mfont_get_prop (cursor.font, Msize);
815 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
816 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
817 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
818 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
820 sprintf (p, "%dpt", size / 10), p += strlen (p);
822 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
824 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
826 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
828 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
832 mface_merge (face, face_default);
833 for (i = 0; i < n; i++)
834 if (props[i] != selection)
835 mface_merge (face, (MFace *) mtext_property_value (props[i]));
836 sym = (MSymbol) mface_get_prop (face, Mforeground);
838 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
839 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
840 strcat (p, ",rev"), p += strlen (p);
841 hline = mface_get_prop (face, Mhline);
842 if (hline && hline->width > 0)
843 strcat (p, ",ul"), p += strlen (p);
844 box = mface_get_prop (face, Mbox);
845 if (box && box->width > 0)
846 strcat (p, ",box"), p += strlen (p);
847 m17n_object_unref (face);
849 XtSetArg (arg[0], XtNborderWidth, 1);
850 XtSetArg (arg[1], XtNlabel, buf);
851 XtSetValues (CurFaceWidget, arg, 2);
854 if (control.cursor_pos < nchars)
856 MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
860 XtSetArg (arg[0], XtNborderWidth, 0);
861 XtSetArg (arg[1], XtNlabel, "");
865 XtSetArg (arg[0], XtNborderWidth, 1);
866 XtSetArg (arg[1], XtNlabel, mlanguage_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);
1553 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1555 XKeyEvent *key_event = (XKeyEvent *) event;
1557 KeySym keysym = NoSymbol;
1559 /* If set to 1, do not update target_x_position. */
1560 int keep_target_x_position = 0;
1562 int y0, old_y1, new_y1;
1569 if (current_input_context
1570 && minput_filter (current_input_context, Mnil, event))
1575 update_region (y0, old_y1, new_y1);
1579 if (event->type == KeyRelease)
1582 produced = mtext ();
1583 ret = minput_lookup (current_input_context, Mnil, event, produced);
1584 if (mtext_len (produced) > 0)
1585 insert_chars (produced);
1587 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1588 m17n_object_unref (produced);
1598 n = (mtext_property_end (selection)
1599 - mtext_property_start (selection));
1600 mtext_detach_property (selection);
1602 else if (cursor.from < nchars)
1604 /* Delete the following grapheme cluster. */
1605 n = cursor.to - cursor.from;
1618 /* Delete selected region. */
1619 n = (mtext_property_end (selection)
1620 - mtext_property_start (selection));
1621 mtext_detach_property (selection);
1623 else if (cursor.from > 0)
1625 /* Delete the preceding character. */
1636 mtext_detach_property (selection);
1637 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1641 if (cursor.prev_from >= 0)
1642 update_cursor (cursor.prev_from, 0);
1646 if (cursor.left_from >= 0)
1647 update_cursor (cursor.left_from, 0);
1654 mtext_detach_property (selection);
1655 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1659 if (cursor.next_to >= 0)
1660 update_cursor (cursor.to, 0);
1664 if (cursor.right_from >= 0)
1665 update_cursor (cursor.right_from, 0);
1672 mtext_detach_property (selection);
1673 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1675 if (cur.to <= nchars)
1677 MDrawGlyphInfo info;
1680 GLYPH_INFO (cur.from, cur.to, info);
1681 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1682 target_x_position, info.y);
1683 keep_target_x_position = 1;
1684 update_cursor (pos, 0);
1691 mtext_detach_property (selection);
1692 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1698 int pos = bol (cur.from - 1, 0);
1700 TEXT_EXTENTS (pos, cur.from - 1, rect);
1701 y = rect.height + rect.y - 1;
1702 pos = COORDINATES_POSITION (pos, nchars,
1703 target_x_position, y);
1704 keep_target_x_position = 1;
1705 update_cursor (pos, 0);
1712 mtext_detach_property (selection);
1713 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1715 if (top.from < nchars)
1716 ScrollProc (w, NULL, (XtPointer) 1);
1722 mtext_detach_property (selection);
1723 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1726 ScrollProc (w, NULL, (XtPointer) -1);
1730 if (key_event->state >= Mod1Mask)
1732 lose_selection (NULL, NULL);
1738 if (key_event->state >= Mod1Mask)
1740 lose_selection (NULL, NULL);
1748 if (buf[0] == 17) /* C-q */
1750 XtAppSetExitFlag (context);
1753 else if (buf[0] == 12) /* C-l */
1755 redraw (0, win_height, 1, 1);
1760 MText *temp = mtext ();
1762 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1763 : ((unsigned char *) buf)[0]);
1764 if (current_input_context)
1765 mtext_put_prop (temp, 0, 1, Mlanguage,
1766 current_input_context->im->language);
1767 insert_chars (temp);
1768 m17n_object_unref (temp);
1773 if (! keep_target_x_position)
1774 target_x_position = cursor.x;
1778 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1780 char *name = (char *) client_data;
1782 int from = -1, to = 0;
1787 filename = strdup (name);
1790 fp = fopen (filename, "w");
1793 fprintf (stderr, "Open for write fail: %s", filename);
1799 from = mtext_property_start (selection);
1800 to = mtext_property_end (selection);
1801 mtext_detach_property (selection);
1804 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1807 select_region (from, to);
1811 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1817 mtext_detach_property (selection);
1818 serialized = (int) client_data;
1820 new = mtext_deserialize (mt);
1823 MPlist *plist = mplist ();
1825 mplist_push (plist, Mt, Mface);
1826 mplist_push (plist, Mt, Mlanguage);
1827 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1828 m17n_object_unref (plist);
1832 m17n_object_unref (mt);
1834 serialized = ! serialized;
1835 nchars = mtext_len (mt);
1838 update_cursor (0, 1);
1839 redraw (0, win_height, 1, 1);
1843 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1845 XtAppSetExitFlag (context);
1851 FILE *fp = fopen (filename, "r");
1854 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1855 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1858 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1863 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1865 int data = (int) client_data;
1870 control.enable_bidi = 0;
1871 control.orientation_reversed = 0;
1875 control.enable_bidi = 1;
1876 control.orientation_reversed = data == 2;
1878 for (i = 0; i < 3; i++)
1881 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1883 XtSetArg (arg[0], XtNleftBitmap, None);
1884 XtSetValues (BidiMenus[i], arg, 1);
1887 update_cursor (cursor.from, 1);
1888 redraw (0, win_height, 1, 0);
1892 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1894 int data = (int) client_data;
1898 control.max_line_width = 0;
1901 control.max_line_width = win_width;
1902 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1904 for (i = 0; i < 3; i++)
1907 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1909 XtSetArg (arg[0], XtNleftBitmap, None);
1910 XtSetValues (LineBreakMenus[i], arg, 1);
1913 update_cursor (cursor.from, 1);
1914 redraw (0, win_height, 1, 0);
1918 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1920 char *filter_module = (char *) client_data;
1922 void (*func) (MText *, int, int);
1926 handle = dlopen (filter_module, RTLD_NOW);
1929 *(void **) (&func) = dlsym (handle, "filter");
1931 (*func) (mt, mtext_property_start (selection),
1932 mtext_property_end (selection));
1937 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1939 int data = (int) client_data;
1953 control.cursor_bidi = 0, control.cursor_width = -1;
1957 control.cursor_bidi = 0, control.cursor_width = 2;
1961 control.cursor_bidi = 1;
1966 for (i = from; i < to; i++)
1969 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1971 XtSetArg (arg[0], XtNleftBitmap, None);
1972 XtSetValues (CursorMenus[i], arg, 1);
1975 update_cursor (cursor.from, 0);
1976 redraw (0, win_height, 1, 0);
1980 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1982 int idx = (int) client_data;
1984 if (idx == -2 ? (! auto_input_method && current_input_method < 0)
1985 : idx == -1 ? auto_input_method
1986 : idx == current_input_method)
1989 if (auto_input_method)
1991 select_input_method (-1);
1992 XtSetArg (arg[0], XtNleftBitmap, None);
1993 XtSetValues (InputMethodMenus[1], arg, 1);
1994 auto_input_method = 0;
1999 select_input_method (-1);
2000 XtSetArg (arg[0], XtNleftBitmap, None);
2001 XtSetValues (InputMethodMenus[0], arg, 1);
2002 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
2003 XtSetValues (InputMethodMenus[1], arg, 1);
2004 auto_input_method = 1;
2009 select_input_method (idx);
2013 MPlist *default_face_list;
2016 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
2018 int idx = (int) client_data;
2029 MFace *face = mframe_get_prop (frame, Mface);
2031 for (plist = default_face_list; mplist_key (plist) != Mnil;
2032 plist = mplist_next (plist))
2033 mface_merge (face, mplist_value (plist));
2034 mplist_add (plist, Mt, *face_table[idx].face);
2035 mface_merge (face, *face_table[idx].face);
2037 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
2039 MFace *face = mframe_get_prop (frame, Mface);
2041 for (plist = default_face_list;
2042 mplist_key (mplist_next (plist)) != Mnil;
2043 plist = mplist_next (plist))
2044 mface_merge (face, mplist_value (plist));
2048 update_cursor (0, 1);
2049 redraw (0, win_height, 1, 1);
2054 XtAppAddWorkProc (context, show_cursor, NULL);
2055 from = mtext_property_start (selection);
2056 to = mtext_property_end (selection);
2057 old_y1 = sel_end.y1;
2059 mtext_detach_property (selection);
2062 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
2063 MTEXTPROP_REAR_STICKY);
2064 mtext_push_property (mt, from, to, prop);
2065 m17n_object_unref (prop);
2068 mtext_pop_prop (mt, from, to, Mface);
2070 update_top (top.from);
2071 update_cursor (cursor.from, 1);
2072 select_region (from, to);
2073 update_region (sel_start.y0, old_y1, sel_end.y1);
2074 if (cur.y1 > win_height)
2076 while (cur.y1 > win_height)
2079 update_cursor (cursor.from, 1);
2085 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2087 MSymbol sym = (MSymbol) client_data;
2094 XtAppAddWorkProc (context, show_cursor, NULL);
2095 from = mtext_property_start (selection);
2096 to = mtext_property_end (selection);
2097 old_y1 = sel_end.y1;
2099 mtext_detach_property (selection);
2101 mtext_put_prop (mt, from, to, Mlanguage, sym);
2103 mtext_pop_prop (mt, from, to, Mlanguage);
2106 update_top (top.from);
2107 update_cursor (cursor.from, 1);
2108 select_region (from, to);
2109 update_region (sel_start.y0, old_y1, sel_end.y1);
2110 if (cur.y1 > win_height)
2112 while (cur.y1 > win_height)
2115 update_cursor (cursor.from, 1);
2121 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2123 int narrowed = (int) client_data;
2126 MConverter *converter;
2132 from = mtext_property_start (selection);
2133 to = mtext_property_end (selection);
2142 mdump = popen ("mdump -q -p a4", "w");
2144 mdump = popen ("mdump -q", "w");
2147 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2148 mconv_encode_range (converter, mt, from, to);
2149 mconv_free_converter (converter);
2154 input_status (MInputContext *ic, MSymbol command)
2156 XFillRectangle (display, input_status_pixmap, gc_inv,
2157 0, 0, input_status_width, input_status_height);
2158 if (command == Minput_status_draw)
2162 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2163 Mface, face_input_status);
2164 if (ic->im->language != Mnil)
2165 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2166 Mlanguage, ic->im->language);
2167 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2168 &input_status_control, NULL, NULL, &rect);
2169 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2170 input_status_width - rect.width - 2, - rect.y,
2171 ic->status, 0, mtext_len (ic->status),
2172 &input_status_control);
2174 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2175 XtSetValues (CurIMStatus, arg, 1);
2179 surrounding_text_handler (MInputContext *ic, MSymbol command)
2181 if (command == Minput_get_surrounding_text)
2183 int len = (int) mplist_value (ic->plist);
2189 pos = cursor.from + len;
2192 surround = mtext_duplicate (mt, pos, cursor.from);
2196 pos = cursor.from + len;
2199 surround = mtext_duplicate (mt, cursor.from, pos);
2202 surround = mtext ();
2203 mplist_set (ic->plist, Mtext, surround);
2204 m17n_object_unref (surround);
2206 else if (command == Minput_delete_surrounding_text)
2208 int len = (int) mplist_value (ic->plist);
2212 if (cursor.from + len < 0)
2213 len = - cursor.from;
2214 mtext_del (mt, cursor.from + len, cursor.from);
2216 update_cursor (cursor.from + len, 1);
2220 if (cursor.from + len > nchars)
2221 len = nchars - cursor.from;
2222 mtext_del (mt, cursor.from, cursor.from + len);
2224 update_cursor (cursor.from, 1);
2232 compare_input_method (const void *elt1, const void *elt2)
2234 const InputMethodInfo *im1 = elt1;
2235 const InputMethodInfo *im2 = elt2;
2236 MSymbol lang1, lang2;
2238 if (im1->language == Mnil)
2240 if (im1->language == im2->language)
2241 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2242 if (im1->language == Mt)
2244 if (im2->language == Mt)
2246 lang1 = mlanguage_name (im1->language);
2247 lang2 = mlanguage_name (im2->language);
2248 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2252 setup_input_methods (int with_xim, char *initial_input_method)
2254 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2258 num_input_methods = plist ? mplist_length (plist) : 0;
2260 num_input_methods++;
2261 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2266 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
2268 MDatabase *mdb = mplist_value (pl);
2269 MSymbol *tag = mdatabase_tag (mdb);
2272 i--, num_input_methods--;
2275 input_method_table[i].language = tag[1];
2276 input_method_table[i].name = tag[2];
2279 m17n_object_unref (plist);
2283 input_method_table[i].language = Mnil;
2284 input_method_table[i].name = msymbol ("xim");
2288 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2289 compare_input_method);
2290 mplist_put_func (minput_driver->callback_list, Minput_status_start,
2291 M17N_FUNC (input_status));
2292 mplist_put_func (minput_driver->callback_list, Minput_status_draw,
2293 M17N_FUNC (input_status));
2294 mplist_put_func (minput_driver->callback_list, Minput_status_done,
2295 M17N_FUNC (input_status));
2296 mplist_put_func (minput_driver->callback_list, Minput_get_surrounding_text,
2297 M17N_FUNC (surrounding_text_handler));
2298 mplist_put_func (minput_driver->callback_list, Minput_delete_surrounding_text,
2299 M17N_FUNC (surrounding_text_handler));
2301 current_input_context = NULL;
2302 current_input_method = -1;
2304 if (initial_input_method)
2306 char *lang_name, *method_name;
2307 char *p = strchr (initial_input_method, '-');
2310 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2312 lang_name = "t", method_name = initial_input_method;
2314 for (i = 0; i < num_input_methods; i++)
2315 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2317 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2319 current_input_method = i;
2327 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2331 if (num && *num > 0)
2335 for (i = 0; i < *num; i++)
2336 bytes += strlen (str[i]) + 1;
2337 msg = alloca (bytes);
2338 strcpy (msg, str[0]);
2339 for (i = 1; i < *num; i++)
2340 strcat (msg, " "), strcat (msg, str[i]);
2342 else if (cursor.from < nchars)
2344 int c = mtext_ref_char (mt, cursor.from);
2345 char *name = mchar_get_prop (c, Mname);
2349 msg = alloca (10 + strlen (name));
2350 sprintf (msg, "U+%04X %s", c, name);
2356 XtSetArg (arg[0], XtNlabel, msg);
2357 XtSetValues (MessageWidget, arg, 1);
2363 char *name1, *name2;
2364 XtCallbackProc proc;
2365 XtPointer client_data;
2370 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2372 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2374 MenuRec FileMenu[] =
2375 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2376 { 0, "Save", NULL, SaveProc, NULL, -1 },
2377 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2379 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2380 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2382 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2383 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2385 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2388 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2390 MenuRec *rec = (MenuRec *) client_data;
2393 XtSetArg (arg[0], XtNvalue, "");
2394 XtSetArg (arg[1], XtNlabel, rec->name1);
2395 XtSetValues (FileDialogWidget, arg, 2);
2396 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2397 XtSetArg (arg[0], XtNx, x + 20);
2398 XtSetArg (arg[1], XtNy, y + 10);
2399 XtSetValues (FileShellWidget, arg, 2);
2400 XtPopup (FileShellWidget, XtGrabExclusive);
2404 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2409 XtPopdown (FileShellWidget);
2410 if ((int) client_data == 1)
2412 XtSetArg (arg[0], XtNlabel, &label);
2413 XtGetValues (FileDialogWidget, arg, 1);
2414 if (strcmp (label, FileMenu[0].name1) == 0)
2418 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2419 fp = fopen (filename, "r");
2421 m17n_object_unref (mt);
2424 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2432 nchars = mtext_len (mt);
2434 update_cursor (0, 1);
2435 redraw (0, win_height, 1, 1);
2437 else if (strcmp (label, FileMenu[2].name1) == 0)
2438 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2440 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2443 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2444 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2445 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2446 (MENU).status = (STATUS))
2450 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2451 char *menu_name, MenuRec *menus, int num_menus, char *help)
2453 Widget button, menu;
2454 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2455 <LeaveWindow>: reset() MenuHelp()\n\
2456 <BtnDown>: reset() PopupMenu()\n\
2457 <BtnUp>: highlight()";
2463 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2464 for (i = 0; i < num_menus; i++)
2475 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2477 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2479 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2481 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2485 XtSetArg (arg[0], XtNsensitive, False);
2486 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2492 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2497 trans = alloca (strlen (fmt) + strlen (help));
2498 sprintf (trans, fmt, help);
2499 XtSetArg (arg[0], XtNmenuName, menu_name);
2500 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2501 XtSetArg (arg[2], XtNinternalWidth, 2);
2502 XtSetArg (arg[3], XtNhighlightThickness, 1);
2503 XtSetArg (arg[4], XtNleft, XawChainLeft);
2504 XtSetArg (arg[5], XtNright, XawChainLeft);
2505 XtSetArg (arg[6], XtNinternational, True);
2508 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2509 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2514 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2515 int *len = alloca (sizeof (int) * num_menus);
2518 XFontSetExtents *fontset_extents;
2520 XtSetArg (arg[0], XtNfontSet, &font_set);
2521 XtGetValues (button, arg, 1);
2523 fontset_extents = XExtentsOfFontSet (font_set);
2524 height = fontset_extents->max_logical_extent.height;
2525 ascent = - fontset_extents->max_logical_extent.y;
2527 for (i = 0; i < num_menus; i++)
2530 len[i] = strlen (menus[i].name2);
2531 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2532 if (max_width < width[i])
2533 max_width = width[i];
2535 for (i = 0; i < num_menus; i++)
2538 Pixmap pixmap = XCreatePixmap (display,
2539 RootWindow (display, screen),
2540 max_width, height, 1);
2541 XFillRectangle (display, pixmap, mono_gc_inv,
2542 0, 0, max_width, height);
2543 XmbDrawString (display, pixmap, font_set, mono_gc,
2544 max_width - width[i], ascent,
2545 menus[i].name2, len[i]);
2546 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2547 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2548 XtSetValues (menus[i].w, arg, 2);
2556 XtActionsRec actions[] = {
2557 {"Expose", ExposeProc},
2558 {"Configure", ConfigureProc},
2560 {"ButtonPress", ButtonProc},
2561 {"ButtonRelease", ButtonReleaseProc},
2562 {"ButtonMotion", ButtonMoveProc},
2563 {"Button2Press", Button2Proc},
2564 {"MenuHelp", MenuHelpProc},
2565 {"FocusIn", FocusInProc},
2566 {"FocusOut", FocusOutProc}
2570 /* Print the usage of this program (the name is PROG), and exit with
2574 help_exit (char *prog, int exit_code)
2582 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2583 printf ("Display FILE on a window and allow users to edit it.\n");
2584 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2585 printf ("The following OPTIONs are available.\n");
2586 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2587 "Use the specified fontset\n");
2588 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2589 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2590 "Input method activated initially.\n");
2591 printf (" %-13s %s", "--version", "print version number\n");
2592 printf (" %-13s %s", "-h, --help", "print this message\n");
2598 main (int argc, char **argv)
2600 Widget form, BodyWidget, w;
2601 char *fontset_name = NULL;
2602 char *font_name = NULL;
2604 char *initial_input_method = NULL;
2605 int col = 80, row = 32;
2606 /* Translation table for TextWidget. */
2607 String trans = "<Expose>: Expose()\n\
2608 <Configure>: Configure()\n\
2611 <Btn1Down>: ButtonPress()\n\
2612 <Btn1Up>: ButtonRelease()\n\
2613 <Btn1Motion>: ButtonMotion()\n\
2614 <Btn2Down>: Button2Press()";
2615 /* Translation table for the top form widget. */
2616 String trans2 = "<Key>: Key()\n\
2618 <FocusIn>: FocusIn()\n\
2619 <FocusOut>: FocusOut()";
2620 String pop_face_trans
2621 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2622 <LeaveWindow>: MenuHelp() reset()\n\
2623 <Btn1Down>: set()\n\
2624 <Btn1Up>: notify() unset()";
2625 String pop_lang_trans
2626 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2627 <LeaveWindow>: MenuHelp() reset()\n\
2628 <Btn1Down>: set()\n\
2629 <Btn1Up>: notify() unset()";
2630 int font_width, font_ascent, font_descent;
2633 char *filter = NULL;
2636 setlocale (LC_ALL, "");
2637 /* Create the top shell. */
2638 XtSetLanguageProc (NULL, NULL, NULL);
2639 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2640 NULL, sessionShellWidgetClass, NULL, 0);
2641 display = XtDisplay (ShellWidget);
2642 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2644 /* Parse the remaining command line arguments. */
2645 for (i = 1; i < argc; i++)
2647 if (! strcmp (argv[i], "--help")
2648 || ! strcmp (argv[i], "-h"))
2649 help_exit (argv[0], 0);
2650 else if (! strcmp (argv[i], "--version"))
2652 printf ("m17n-edit (m17n library) %s\n", M17NLIB_VERSION_NAME);
2653 printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007 AIST, JAPAN\n");
2656 else if (! strcmp (argv[i], "--geometry"))
2659 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2660 help_exit (argv[0], 1);
2662 else if (! strcmp (argv[i], "-s"))
2665 fontsize = atoi (argv[i]);
2669 else if (! strcmp (argv[i], "--fontset"))
2672 fontset_name = strdup (argv[i]);
2674 else if (! strcmp (argv[i], "--font"))
2677 font_name = strdup (argv[i]);
2679 else if (! strcmp (argv[i], "--im"))
2682 initial_input_method = strdup (argv[i]);
2684 else if (! strcmp (argv[i], "--with-xim"))
2688 else if (! strcmp (argv[i], "--filter"))
2693 else if (argv[i][0] != '-')
2695 filename = strdup (argv[i]);
2699 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2700 help_exit (argv[0], 1);
2704 filename = strdup ("/dev/null");
2706 mdatabase_dir = ".";
2707 /* Initialize the m17n library. */
2709 if (merror_code != MERROR_NONE)
2710 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2711 minput_driver = &minput_gui_driver;
2713 mt = read_file (filename);
2716 nchars = mtext_len (mt);
2718 Mword = msymbol ("word");
2721 MFace *face = mface ();
2723 mface_put_prop (face, Mforeground, msymbol ("blue"));
2724 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2725 mface_put_prop (face, Mvideomode, Mreverse);
2726 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2727 m17n_object_unref (face);
2730 /* This tells ExposeProc to initialize everything. */
2733 XA_TEXT = XInternAtom (display, "TEXT", False);
2734 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2735 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2736 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2737 if (Mcoding_compound_text == Mnil)
2738 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2741 MPlist *plist = mplist ();
2744 mplist_put (plist, msymbol ("widget"), ShellWidget);
2745 if (fontset_name || font_name || fontsize > 0)
2751 font = mfont_parse_name (font_name, Mnil);
2753 face = mface_from_font (font);
2761 MFontset *fontset = mfontset (fontset_name);
2763 mface_put_prop (face, Mfontset, fontset);
2764 m17n_object_unref (fontset);
2767 mface_put_prop (face, Msize, (void *) fontsize);
2768 mplist_add (plist, Mface, face);
2769 m17n_object_unref (face);
2771 frame = mframe (plist);
2773 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2774 m17n_object_unref (plist);
2775 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2776 default_face_list = mplist ();
2777 mplist_add (default_face_list, Mt, face_default);
2778 face_default_fontset = mface ();
2779 mface_put_prop (face_default_fontset, Mfontset,
2780 mface_get_prop (face_default, Mfontset));
2782 font = (MFont *) mframe_get_prop (frame, Mfont);
2783 default_font_size = (int) mfont_get_prop (font, Msize);
2786 font_width = (int) mframe_get_prop (frame, Mfont_width);
2787 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2788 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2789 win_width = font_width * col;
2790 win_height = (font_ascent + font_descent) * row;
2796 prop.color_top = prop.color_left = msymbol ("magenta");
2797 prop.color_bottom = prop.color_right = msymbol ("red");
2798 prop.inner_hmargin = prop.inner_vmargin = 1;
2799 prop.outer_hmargin = prop.outer_vmargin = 2;
2801 face_box = mface ();
2802 mface_put_prop (face_box, Mbox, &prop);
2805 face_courier = mface ();
2806 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2807 face_helvetica = mface ();
2808 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2809 face_times = mface ();
2810 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2811 face_dv_ttyogesh = mface ();
2812 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2813 face_freesans = mface ();
2814 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2815 face_freeserif = mface ();
2816 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2817 face_freemono = mface ();
2818 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2820 face_xxx_large = mface ();
2821 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2823 MFont *latin_font = mframe_get_prop (frame, Mfont);
2824 MFont *dev_font = mfont ();
2825 MFont *thai_font = mfont ();
2826 MFont *tib_font = mfont ();
2827 MFontset *fontset, *fontset_no_ctl;
2828 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2829 MSymbol no_ctl = msymbol ("no-ctl");
2831 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2832 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2833 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2834 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2835 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2836 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2838 fontset = mfontset (fontset_name);
2839 fontset_no_ctl = mfontset_copy (fontset, "no-ctl");
2840 m17n_object_unref (fontset);
2841 mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil,
2842 latin_font, Mnil, 0);
2843 mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil,
2844 dev_font, no_ctl, 0);
2845 mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil,
2846 thai_font, no_ctl, 0);
2847 mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil,
2848 tib_font, no_ctl, 0);
2849 face_no_ctl_fontset = mface ();
2850 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl);
2851 m17n_object_unref (fontset_no_ctl);
2858 setup_input_methods (with_xim, initial_input_method);
2860 gc = DefaultGC (display, screen);
2862 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2863 XtSetArg (arg[1], XtNdefaultDistance, 2);
2864 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2866 XtSetArg (arg[0], XtNborderWidth, 0);
2867 XtSetArg (arg[1], XtNdefaultDistance, 2);
2868 XtSetArg (arg[2], XtNtop, XawChainTop);
2869 XtSetArg (arg[3], XtNbottom, XawChainTop);
2870 XtSetArg (arg[4], XtNleft, XawChainLeft);
2871 XtSetArg (arg[5], XtNright, XawChainRight);
2872 XtSetArg (arg[6], XtNresizable, True);
2873 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2874 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2875 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2876 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2877 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2878 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2879 XtSetArg (arg[7], XtNfromVert, LangWidget);
2880 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2881 XtSetArg (arg[2], XtNtop, XawChainBottom);
2882 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2883 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2885 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2886 HeadWidget, NULL, 0);
2887 XtSetArg (arg[0], XtNvalue, "");
2888 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2889 FileShellWidget, arg, 1);
2890 XawDialogAddButton (FileDialogWidget, "OK",
2891 FileDialogProc, (XtPointer) 0);
2892 XawDialogAddButton (FileDialogWidget, "CANCEL",
2893 FileDialogProc, (XtPointer) 1);
2895 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2896 (char *) check_bits,
2897 check_width, check_height);
2899 unsigned long valuemask = GCForeground;
2902 values.foreground = 1;
2903 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2904 values.foreground = 0;
2905 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2912 if (num_menus < num_input_methods + 2)
2913 num_menus = num_input_methods + 2;
2914 if (num_menus < num_faces + 1)
2915 num_menus = num_faces + 1;
2916 menus = alloca (sizeof (MenuRec) * num_menus);
2918 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2919 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2920 "File I/O, Serialization, Image, Quit");
2922 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2923 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2924 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2925 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2926 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2927 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2928 w = create_menu_button (ShellWidget, HeadWidget, w,
2929 "Cursor", "Cursor Menu",
2930 menus, 6, "Cursor Movement Mode, Cursor Shape");
2931 CursorMenus[0] = menus[0].w;
2932 CursorMenus[1] = menus[1].w;
2933 CursorMenus[2] = menus[3].w;
2934 CursorMenus[3] = menus[4].w;
2935 CursorMenus[4] = menus[5].w;
2937 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2938 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2939 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2940 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2941 menus, 3, "BIDI Processing Mode");
2942 for (i = 0; i < 3; i++)
2943 BidiMenus[i] = menus[i].w;
2945 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2946 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2947 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2948 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2950 menus, 3, "How to break lines");
2951 for (i = 0; i < 3; i++)
2952 LineBreakMenus[i] = menus[i].w;
2954 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2955 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2956 for (i = 0; i < num_input_methods; i++)
2958 InputMethodInfo *im = input_method_table + i;
2959 char *name1, *name2;
2961 if (im->language != Mnil && im->language != Mt)
2963 MSymbol sym = mlanguage_name (im->language);
2965 name1 = msymbol_name (im->language);
2967 name1 = msymbol_name (sym);
2968 name2 = msymbol_name (im->name);
2971 name1 = msymbol_name (im->name), name2 = NULL;
2973 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2975 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2976 "Input Method Menu", menus, i + 2,
2977 "Select input method");
2980 unsigned long valuemask = GCForeground;
2983 XtSetArg (arg[0], XtNbackground, &values.foreground);
2984 XtGetValues (w, arg, 1);
2985 gc_inv = XCreateGC (display, RootWindow (display, screen),
2986 valuemask, &values);
2989 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2990 for (i = 0; i < num_input_methods + 2; i++)
2991 InputMethodMenus[i] = menus[i].w;
2995 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2996 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2997 "Filter Menu", menus, 1,
2998 "Select filter to run");
3001 input_status_width = font_width * 8;
3002 input_status_height = (font_ascent + font_descent) * 2.4;
3003 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
3005 input_status_height,
3006 DefaultDepth (display, screen));
3011 prop.color_top = prop.color_bottom
3012 = prop.color_left = prop.color_right = Mnil;
3013 prop.inner_hmargin = prop.inner_vmargin = 1;
3014 prop.outer_hmargin = prop.outer_vmargin = 0;
3015 face_input_status = mface_copy (face_default);
3016 mface_put_prop (face_input_status, Mbox, &prop);
3019 XFillRectangle (display, input_status_pixmap, gc_inv,
3020 0, 0, input_status_width, input_status_height);
3021 XtSetArg (arg[0], XtNfromHoriz, w);
3022 XtSetArg (arg[1], XtNleft, XawRubber);
3023 XtSetArg (arg[2], XtNright, XawChainRight);
3024 XtSetArg (arg[3], XtNborderWidth, 0);
3025 XtSetArg (arg[4], XtNlabel, " ");
3026 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3027 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
3028 HeadWidget, arg, 6);
3029 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
3030 XtSetArg (arg[1], XtNleft, XawChainRight);
3031 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
3032 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
3033 HeadWidget, arg, 5);
3035 XtSetArg (arg[0], XtNborderWidth, 0);
3036 XtSetArg (arg[1], XtNleft, XawChainLeft);
3037 XtSetArg (arg[2], XtNright, XawChainLeft);
3038 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
3039 for (i = 0; i < num_faces;)
3041 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
3042 char *label = label_menu + 5; /* "Xxxx" */
3044 for (j = i; j < num_faces && face_table[j].face; j++)
3045 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
3047 w = create_menu_button (ShellWidget, FaceWidget, w,
3049 menus, j - i, "Push face property");
3053 XtSetArg (arg[0], XtNfromHoriz, w);
3054 XtSetArg (arg[1], XtNleft, XawChainLeft);
3055 XtSetArg (arg[2], XtNright, XawChainLeft);
3056 XtSetArg (arg[3], XtNhorizDistance, 10);
3057 XtSetArg (arg[4], XtNlabel, "Pop");
3058 XtSetArg (arg[5], XtNtranslations,
3059 XtParseTranslationTable (pop_face_trans));
3060 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
3061 FaceWidget, arg, 6);
3062 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
3064 XtSetArg (arg[0], XtNfromHoriz, w);
3065 XtSetArg (arg[1], XtNleft, XawChainLeft);
3066 XtSetArg (arg[2], XtNright, XawChainRight);
3067 XtSetArg (arg[3], XtNlabel, "");
3068 XtSetArg (arg[4], XtNborderWidth, 0);
3069 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3070 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
3071 FaceWidget, arg, 6);
3073 XtSetArg (arg[0], XtNborderWidth, 0);
3074 XtSetArg (arg[1], XtNleft, XawChainLeft);
3075 XtSetArg (arg[2], XtNright, XawChainLeft);
3076 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
3078 MPlist *plist[11], *pl;
3081 for (i = 0; i < 11; i++) plist[i] = NULL;
3083 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
3084 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
3086 MSymbol sym = msymbol_exist (langname);
3090 && ((fullname = mlanguage_name (sym)) != Mnil))
3092 char *name = msymbol_name (fullname);
3095 if (c >= 'a' && c <= 'z')
3097 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
3101 pl = plist[idx] = mplist ();
3102 for (; mplist_next (pl); pl = mplist_next (pl))
3103 if (strcmp (name, (char *) mplist_value (pl)) < 0)
3105 mplist_push (pl, sym, fullname);
3110 for (i = 0; i < 11; i++)
3113 char *name = alloca (9);
3115 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
3118 for (j = 0, pl = plist[i]; mplist_next (pl);
3119 j++, pl = mplist_next (pl))
3120 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
3121 msymbol_name (mplist_key (pl)),
3122 LangProc, mplist_key (pl), -1);
3123 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
3124 menus, j, "Push language property");
3126 for (i = 0; i < 11; i++)
3128 m17n_object_unref (plist[i]);
3130 XtSetArg (arg[0], XtNfromHoriz, w);
3131 XtSetArg (arg[1], XtNleft, XawChainLeft);
3132 XtSetArg (arg[2], XtNright, XawChainLeft);
3133 XtSetArg (arg[3], XtNhorizDistance, 10);
3134 XtSetArg (arg[4], XtNlabel, "Pop");
3135 XtSetArg (arg[5], XtNtranslations,
3136 XtParseTranslationTable (pop_lang_trans));
3137 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3138 LangWidget, arg, 6);
3139 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3141 XtSetArg (arg[0], XtNfromHoriz, w);
3142 XtSetArg (arg[1], XtNleft, XawChainLeft);
3143 XtSetArg (arg[2], XtNright, XawChainRight);
3144 XtSetArg (arg[3], XtNlabel, "");
3145 XtSetArg (arg[4], XtNborderWidth, 0);
3146 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3147 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3148 LangWidget, arg, 6);
3151 XtSetArg (arg[0], XtNheight, win_height);
3152 XtSetArg (arg[1], XtNwidth, 10);
3153 XtSetArg (arg[2], XtNleft, XawChainLeft);
3154 XtSetArg (arg[3], XtNright, XawChainLeft);
3155 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3157 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3158 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3160 XtSetArg (arg[0], XtNheight, win_height);
3161 XtSetArg (arg[1], XtNwidth, win_width);
3162 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3163 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3164 XtSetArg (arg[4], XtNleft, XawChainLeft);
3165 XtSetArg (arg[5], XtNright, XawChainRight);
3166 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3169 XtSetArg (arg[0], XtNborderWidth, 0);
3170 XtSetArg (arg[1], XtNleft, XawChainLeft);
3171 XtSetArg (arg[2], XtNright, XawChainRight);
3172 XtSetArg (arg[3], XtNresizable, True);
3173 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3174 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3175 TailWidget, arg, 5);
3177 memset (&control, 0, sizeof control);
3178 control.two_dimensional = 1;
3179 control.enable_bidi = 1;
3180 control.anti_alias = 1;
3181 control.min_line_ascent = font_ascent;
3182 control.min_line_descent = font_descent;
3183 control.max_line_width = win_width;
3184 control.with_cursor = 1;
3185 control.cursor_width = 2;
3186 control.partial_update = 1;
3187 control.ignore_formatting_char = 1;
3189 memset (&input_status_control, 0, sizeof input_status_control);
3190 input_status_control.enable_bidi = 1;
3192 XtAppAddActions (context, actions, XtNumber (actions));
3193 XtRealizeWidget (ShellWidget);
3195 win = XtWindow (TextWidget);
3197 XtAppMainLoop (context);
3199 if (current_input_context)
3200 minput_destroy_ic (current_input_context);
3201 for (i = 0; i < num_input_methods; i++)
3202 if (input_method_table[i].im)
3203 minput_close_im (input_method_table[i].im);
3204 m17n_object_unref (frame);
3205 m17n_object_unref (mt);
3206 m17n_object_unref (face_xxx_large);
3207 m17n_object_unref (face_box);
3208 m17n_object_unref (face_courier);
3209 m17n_object_unref (face_helvetica);
3210 m17n_object_unref (face_times);
3211 m17n_object_unref (face_dv_ttyogesh);
3212 m17n_object_unref (face_freesans);
3213 m17n_object_unref (face_freeserif);
3214 m17n_object_unref (face_freemono);
3215 m17n_object_unref (face_default_fontset);
3216 m17n_object_unref (face_no_ctl_fontset);
3217 m17n_object_unref (face_input_status);
3218 m17n_object_unref (face_default);
3219 m17n_object_unref (default_face_list);
3220 m17n_object_unref (selection);
3224 XFreeGC (display, mono_gc);
3225 XFreeGC (display, mono_gc_inv);
3226 XFreeGC (display, gc_inv);
3227 XtUninstallTranslations (form);
3228 XtUninstallTranslations (TextWidget);
3229 XtDestroyWidget (ShellWidget);
3230 XtDestroyApplicationContext (context);
3235 free (fontset_name);
3237 free (input_method_table);
3238 free (InputMethodMenus);
3243 #else /* not HAVE_X11_XAW_COMMAND_H */
3246 main (int argc, char **argv)
3249 "Building of this program failed (lack of some header files)\n");
3253 #endif /* not HAVE_X11_XAW_COMMAND_H */
3255 #endif /* not FOR_DOXYGEN */