1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004
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., 59 Temple Place, Suite 330, Boston, MA
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 Outout 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 Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
85 ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
100 #include <X11/keysym.h>
101 #include <X11/Xatom.h>
102 #include <X11/Intrinsic.h>
103 #include <X11/StringDefs.h>
104 #include <X11/Shell.h>
106 #include <m17n-gui.h>
107 #include <m17n-misc.h>
112 #ifdef HAVE_X11_XAW_COMMAND_H
114 #include <X11/Xaw/Command.h>
115 #include <X11/Xaw/Box.h>
116 #include <X11/Xaw/Form.h>
117 #include <X11/Xaw/Dialog.h>
118 #include <X11/Xaw/Scrollbar.h>
119 #include <X11/Xaw/Toggle.h>
120 #include <X11/Xaw/SimpleMenu.h>
121 #include <X11/Xaw/SmeBSB.h>
122 #include <X11/Xaw/SmeLine.h>
123 #include <X11/Xaw/MenuButton.h>
125 #define VERSION "1.2.0"
127 /* Global variables. */
132 /* For the X Window System. */
135 /* GCs for normal drawing, filling by background color, normal drawing
136 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
138 GC gc, gc_inv, mono_gc, mono_gc_inv;
140 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
141 XtAppContext context;
142 int default_font_size;
146 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
147 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
148 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
149 +- Body -- Sbar, Text
153 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
154 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
155 Widget SbarWidget, TextWidget;
156 Widget FileShellWidget, FileDialogWidget;
157 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
158 Widget CurIMLang, CurIMStatus;
160 int win_width, win_height; /* Size of TextWidget. */
163 Pixmap input_status_pixmap;
164 int input_status_width, input_status_height;
166 /* Bitmap for "check" glyph. */
167 #define check_width 9
168 #define check_height 8
169 static unsigned char check_bits[] = {
170 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
171 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
174 /* For the m17n library. */
177 int nchars; /* == mtext_len (mt) */
178 MDrawControl control, input_status_control;
179 MTextProperty *selection;
184 MFace *face_xxx_large;
186 MFace *face_courier, *face_helvetica, *face_times;
187 MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
188 MFace *face_default_fontset, *face_no_ctl_fontset;
189 MFace *face_input_status;
191 MSymbol Mcoding_compound_text;
193 int logical_move = 1; /* If 0, move cursor visually. */
197 MSymbol language, name;
201 InputMethodInfo *input_method_table;
203 int num_input_methods;
204 int current_input_method = -1; /* i.e. none */
205 int auto_input_method = 0;
206 MInputContext *current_input_context;
213 { {"Menu Size", NULL},
214 {"xx-small", &mface_xx_small},
215 {"x-small", &mface_x_small},
216 {"small", &mface_small},
217 {"normalsize", &mface_normalsize},
218 {"large", &mface_large},
219 {"x-large", &mface_x_large},
220 {"xx-large", &mface_xx_large},
221 {"xxx-large", &face_xxx_large},
223 {"Menu Family", NULL},
224 {"courier", &face_courier},
225 {"helvetica", &face_helvetica},
226 {"times", &face_times},
227 {"dv-ttyogesh", &face_dv_ttyogesh},
228 {"freesans", &face_freesans},
229 {"freeserif", &face_freeserif},
230 {"freemono", &face_freemono},
232 {"Menu Style", NULL},
233 {"medium", &mface_medium},
234 {"bold", &mface_bold},
235 {"italic", &mface_italic},
237 {"Menu Color", NULL},
238 {"black", &mface_black},
239 {"white", &mface_white},
241 {"green", &mface_green},
242 {"blue", &mface_blue},
243 {"cyan", &mface_cyan},
244 {"yello", &mface_yellow},
245 {"magenta", &mface_magenta},
248 {"normal", &mface_normal_video},
249 {"reverse", &mface_reverse_video},
250 {"underline", &mface_underline},
252 {"No CTL", &face_no_ctl_fontset} };
255 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
257 /* Information about a physical line metric. */
260 int from; /* BOL position of the line. */
261 int to; /* BOL position of the next line. */
262 int y0, y1; /* Top and bottom Y position of the line. */
263 int ascent; /* Height of the top Y position. */
266 struct LineInfo top; /* Topmost line. */
267 struct LineInfo cur; /* Line containing cursor. */
268 struct LineInfo sel_start; /* Line containing selection start. */
269 struct LineInfo sel_end; /* Line containing selection end. */
271 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
273 /* X position to keep on vertical (up and down) cursor motion. */
274 int target_x_position;
276 /* Interface macros for m17n-lib drawing routines. */
278 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
279 coordinate ($X, $Y) */
280 #define DRAW_TEXT(x, y, from, to) \
281 mdraw_text_with_control \
282 (frame, (MDrawWindow) win, \
283 control.orientation_reversed ? x + win_width : x, y, \
284 mt, from, to, &control)
286 /* Store the extents of a text in the range $FROM to $TO in the
287 structure $RECT (type MDrawMetric). */
288 #define TEXT_EXTENTS(from, to, rect) \
289 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
291 /* Store the glyph information of a character at the position $POS in
292 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
293 $FROM is written at the coordinate (0, 0). */
294 #define GLYPH_INFO(from, pos, info) \
295 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
297 /* Set $X and $Y to the coordinate of character at position $POS
298 assuming that the text from $FROM is written at the coordinate (0,
300 #define COORDINATES_POSITION(from, pos, x, y) \
301 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
303 /* Interface macros for X library. */
304 #define COPY_AREA(y0, y1, to) \
305 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
307 #define CLEAR_AREA(x, y, w, h) \
308 XClearArea (display, win, (x), (y), (w), (h), False)
310 #define SELECTEDP() \
311 mtext_property_mtext (selection)
313 /* Format MSG by FMT and print the result to the stderr, and exit. */
314 #define FATAL_ERROR(fmt, arg) \
316 fprintf (stderr, fmt, arg); \
321 /* If POS is greater than zero, move POS back to the beginning of line
322 (BOL) position. If FORWARD is nonzero, move POS forward instead.
323 Return the new position. */
325 bol (int pos, int forward)
327 int limit = forward ? nchars : 0;
329 pos = mtext_character (mt, pos, limit, '\n');
330 return (pos < 0 ? limit : pos + 1);
333 /* Update the structure #TOP (struct LineInfo) to make $POS the first
334 character position of the screen. */
338 int from = bol (pos, 0);
341 GLYPH_INFO (from, pos, info);
342 top.from = info.line_from;
343 top.to = info.line_to;
345 top.y1 = info.metrics.height;
346 top.ascent = - info.metrics.y;
350 /* Update the scroll bar so that the text of the range $FROM to $TO
351 are shown on the window. */
353 update_scroll_bar (int from, int to)
355 float top = (float) from / nchars;
356 float shown = (float) (to - from) / nchars;
357 XtArgVal *l_top = (XtArgVal *) ⊤
358 XtArgVal *l_shown = (XtArgVal *) &shown;
360 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
361 XtSetArg (arg[1], XtNshown, *l_shown);
362 XtSetValues (SbarWidget, arg, 2);
366 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
367 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
368 is nonzero, update the scoll bar. */
370 redraw (int y0, int y1, int clear, int scroll_bar)
375 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
376 struct LineInfo *line;
378 if (clear || control.anti_alias)
379 CLEAR_AREA (0, y0, win_width, y1 - y0);
381 /* Find a line closest to y0. It is a cursor line if the cursor is
382 Y0, otherwise the top line. */
387 /* If there exists a selected region, check it too. */
388 if (sel_y0 > line->y0 && y0 >= sel_y0)
393 info.metrics.height = line->y1 - y;
394 info.metrics.y = - line->ascent;
395 info.line_to = line->to;
396 while (from < nchars && y + info.metrics.height <= y0)
398 y += info.metrics.height;
400 GLYPH_INFO (from, from, info);
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)
510 /* CUR is inaccurate. We can trust only TOP. */
511 GLYPH_INFO (top.from, pos, cursor);
512 cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
514 else if (pos < cur.from)
516 int from = bol (pos, 0);
518 TEXT_EXTENTS (from, cur.from, rect);
519 GLYPH_INFO (from, pos, cursor);
520 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
522 else if (pos < cur.to)
524 GLYPH_INFO (cur.from, pos, cursor);
528 GLYPH_INFO (cur.from, pos, cursor);
529 cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
532 cur.from = cursor.line_from;
533 cur.to = cursor.line_to;
534 cur.y1 = cur.y0 + cursor.metrics.height;
535 cur.ascent = - cursor.metrics.y;
539 /* Update the information about the selected region. */
549 from = mtext_property_start (selection);
550 to = mtext_property_end (selection);
554 int pos = bol (from, 0);
556 TEXT_EXTENTS (pos, top.from, rect);
557 sel_start.y0 = top.y0 - rect.height;
558 sel_start.ascent = - rect.y;
559 GLYPH_INFO (pos, from, info);
560 if (pos < info.line_from)
561 sel_start.y0 += - rect.y + info.y + info.metrics.y;
565 GLYPH_INFO (top.from, from, info);
566 sel_start.y0 = top.ascent + info.y + info.metrics.y;
568 sel_start.ascent = -info.metrics.y;
569 sel_start.y1 = sel_start.y0 + info.metrics.height;
570 sel_start.from = info.line_from;
571 sel_start.to = info.line_to;
573 if (to <= sel_start.to)
579 GLYPH_INFO (sel_start.from, to, info);
580 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
581 sel_end.y1 = sel_end.y0 + info.metrics.height;
582 sel_end.ascent = - info.metrics.y;
583 sel_end.from = info.line_from;
584 sel_end.to = info.line_to;
589 /* Select the text in the region from $FROM to $TO. */
591 select_region (int from, int to)
596 pos = from, from = to, to = pos;
597 mtext_push_property (mt, from, to, selection);
602 /* Setup the window to display the character of $POS at the top left
608 /* Top and bottom Y positions to redraw. */
611 if (pos + 1000 < top.from)
612 y0 = 0, y1 = win_height;
613 else if (pos < top.from)
616 TEXT_EXTENTS (pos, top.from, rect);
617 if (rect.height >= win_height * 0.9)
622 COPY_AREA (0, win_height - y1, y1);
625 else if (pos < top.to)
627 /* No need of redrawing. */
630 else if (pos < top.from + 1000)
632 TEXT_EXTENTS (top.from, pos, rect);
633 if (rect.height >= win_height * 0.9)
637 y0 = win_height - rect.height;
638 COPY_AREA (rect.height, win_height, 0);
643 y0 = 0, y1 = win_height;
649 update_cursor (pos, 1);
651 update_cursor (cursor.from, 1);
653 redraw (y0, y1, 1, 1);
657 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
660 /* Select an input method accoding to $IDX. If $IDX is negative, turn
661 off the current input method, otherwide turn on the input method
662 input_method_table[$IDX]. */
664 select_input_method (idx)
666 if (idx == current_input_method)
668 if (current_input_context)
670 minput_destroy_ic (current_input_context);
671 current_input_context = NULL;
672 current_input_method = -1;
676 InputMethodInfo *im = input_method_table + idx;
678 if (im->language == Mnil)
680 MInputXIMArgIC arg_xic;
681 Window win = XtWindow (TextWidget);
683 arg_xic.input_style = 0;
684 arg_xic.client_win = arg_xic.focus_win = win;
685 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
686 current_input_context = minput_create_ic (im->im, &arg_xic);
690 MInputGUIArgIC arg_ic;
692 arg_ic.frame = frame;
693 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
694 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
695 current_input_context = minput_create_ic (im->im, &arg_ic);
698 if (current_input_context)
700 set_input_method_spot ();
701 current_input_method = idx;
704 if (current_input_method >= 0)
707 XtSetArg (arg[0], XtNlabel, &label);
708 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
709 XtSetArg (arg[0], XtNlabel, label);
712 XtSetArg (arg[0], XtNlabel, "");
713 XtSetValues (CurIMLang, arg, 1);
716 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
719 /* Display cursor according to the current information of #CUR.
720 $CLIENT_DATA is ignore. Most callback functions add this function
721 as a background processing procedure the current application (by
722 XtAppAddWorkProc) via the function hide_cursor. */
724 show_cursor (XtPointer client_data)
726 MFaceHLineProp *hline;
732 update_cursor (cursor.from, 1);
734 while (cur.y1 > win_height)
737 update_cursor (cursor.from, 1);
740 control.cursor_pos = cursor.from;
743 control.with_cursor = 1;
746 if (current_input_context)
747 set_input_method_spot ();
751 int pos = (SELECTEDP () ? mtext_property_start (selection)
752 : cursor.from > 0 ? cursor.from - 1
754 MFace *face = mface ();
755 MTextProperty *props[256];
756 int n = mtext_get_properties (mt, pos, Mface, props, 256);
758 char buf[256], *p = buf;
764 int size = (int) mfont_get_prop (cursor.font, Msize);
765 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
766 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
767 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
768 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
770 sprintf (p, "%dpt", size / 10), p += strlen (p);
772 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
774 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
776 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
778 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
782 mface_merge (face, face_default);
783 for (i = 0; i < n; i++)
784 if (props[i] != selection)
785 mface_merge (face, (MFace *) mtext_property_value (props[i]));
786 sym = (MSymbol) mface_get_prop (face, Mforeground);
788 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
789 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
790 strcat (p, ",rev"), p += strlen (p);
791 hline = mface_get_prop (face, Mhline);
792 if (hline && hline->width > 0)
793 strcat (p, ",ul"), p += strlen (p);
794 box = mface_get_prop (face, Mbox);
795 if (box && box->width > 0)
796 strcat (p, ",box"), p += strlen (p);
797 m17n_object_unref (face);
799 XtSetArg (arg[0], XtNborderWidth, 1);
800 XtSetArg (arg[1], XtNlabel, buf);
801 XtSetValues (CurFaceWidget, arg, 2);
804 if (control.cursor_pos < nchars)
806 MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
810 XtSetArg (arg[0], XtNborderWidth, 0);
811 XtSetArg (arg[1], XtNlabel, "");
815 XtSetArg (arg[0], XtNborderWidth, 1);
816 XtSetArg (arg[1], XtNlabel,
817 msymbol_name (msymbol_get (sym, Mlanguage)));
818 XtSetValues (CurLangWidget, arg, 2);
820 XtSetValues (CurLangWidget, arg, 2);
822 if (auto_input_method)
825 select_input_method (-1);
830 for (i = 0; i < num_input_methods; i++)
831 if (input_method_table[i].language == sym)
833 if (i < num_input_methods
834 && input_method_table[i].available >= 0)
836 if (! input_method_table[i].im)
838 input_method_table[i].im =
839 minput_open_im (input_method_table[i].language,
840 input_method_table[i].name, NULL);
841 if (! input_method_table[i].im)
842 input_method_table[i].available = -1;
844 if (input_method_table[i].im)
845 select_input_method (i);
847 select_input_method (-1);
850 select_input_method (-1);
855 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
861 /* Hide the cursor. */
865 control.with_cursor = 0;
867 XtAppAddWorkProc (context, show_cursor, NULL);
871 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
872 $Y1 and $NEW_Y1 assuming that the text in the other area is not
875 update_region (int y0, int old_y1, int new_y1)
881 if (old_y1 < win_height)
883 COPY_AREA (old_y1, win_height, new_y1);
884 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
887 redraw (new_y1, win_height, 1, 0);
889 else if (new_y1 > old_y1)
891 if (new_y1 < win_height)
892 COPY_AREA (old_y1, win_height, new_y1);
894 if (new_y1 > win_height)
896 redraw (y0, new_y1, 1, 1);
900 /* Delete the next $N characters. If $N is negative delete the
901 precious (- $N) characters. */
907 int y0, old_y1, new_y1;
909 int line_from = cursor.line_from;
912 from = cursor.from, to = from + n;
915 if (cursor.from == cur.from)
917 /* We are at the beginning of line. */
918 int pos = cursor.prev_from;
920 if (cursor.from == top.from)
922 /* We are at the beginning of screen. We must scroll
924 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
925 reseat (info.line_from);
927 update_cursor (pos, 1);
933 from = cursor.from - 1;
938 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
939 old_y1 = cur.y0 + rect.height;
941 /* Now delete a character. */
942 mtext_del (mt, from, to);
944 if (from >= top.from && from < top.to)
945 update_top (top.from);
946 update_cursor (from, 1);
949 if (line_from != cursor.line_from)
952 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
953 new_y1 = cur.y0 + rect.height;
955 update_region (cur.y0, old_y1, new_y1);
959 /* Insert M-text $NEWTEXT at the current cursor position. */
961 insert_chars (MText *newtext)
963 int n = mtext_len (newtext);
965 int y0, old_y1, new_y1;
970 int n = (mtext_property_end (selection)
971 - mtext_property_start (selection));
972 mtext_detach_property (selection);
977 if (cursor.line_from > 0
978 && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
979 y0 -= control.min_line_descent;
981 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
982 old_y1 = y0 + rect.height;
984 line_from = cursor.line_from;
986 /* Now insert chars. */
987 mtext_ins (mt, cursor.from, newtext);
989 if (cur.from == top.from)
990 update_top (top.from);
991 update_cursor (cursor.from + n, 1);
993 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
994 new_y1 = cur.y0 + rect.height;
996 update_region (y0, old_y1, new_y1);
1002 word_constituent_p (int c)
1004 MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
1005 char *name = category != Mnil ? msymbol_name (category) : NULL;
1007 return (name && (name[0] == 'L' || name[0] == 'M'));
1014 int pos = cursor.from;
1016 while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
1020 MTextProperty *prop = mtext_get_property (mt, pos, Mword);
1023 pos = mtext_property_end (prop);
1025 while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
1028 update_cursor (pos, 0);
1034 int pos = cursor.from;
1036 while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
1040 MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
1043 pos = mtext_property_start (prop);
1045 while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
1048 update_cursor (pos, 0);
1052 /* Convert the currently selected text to UTF8-STRING or
1053 COMPOUND-TEXT. It is called when someone requests the current
1054 value of the selection. */
1056 covert_selection (Widget w, Atom *selection_atom,
1057 Atom *target, Atom *return_type,
1058 XtPointer *value, unsigned long *length, int *format)
1060 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1061 MText *this_mt = mtext ();
1062 int from = mtext_property_start (selection);
1063 int to = mtext_property_end (selection);
1067 mtext_copy (this_mt, 0, mt, from, to);
1068 if (*target == XA_TEXT)
1070 #ifdef X_HAVE_UTF8_STRING
1071 coding = Mcoding_utf_8;
1072 *return_type = XA_UTF8_STRING;
1074 coding = Mcoding_compound_text;
1075 *return_type = XA_COMPOUND_TEXT;
1078 else if (*target == XA_UTF8_STRING)
1080 coding = Mcoding_utf_8;
1081 *return_type = XA_UTF8_STRING;
1083 else if (*target == XA_STRING)
1088 for (i = 0; i < len; i++)
1089 if (mtext_ref_char (this_mt, i) >= 0x100)
1090 /* Can't encode in XA_STRING */
1092 coding = Mcoding_iso_8859_1;
1093 *return_type = XA_STRING;
1095 else if (*target == XA_COMPOUND_TEXT)
1097 coding = Mcoding_compound_text;
1098 *return_type = XA_COMPOUND_TEXT;
1103 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1104 m17n_object_unref (this_mt);
1108 *value = (XtPointer) buf;
1114 /* Unselect the text. It is called when we loose the selection. */
1116 lose_selection (Widget w, Atom *selection_atom)
1120 mtext_detach_property (selection);
1121 redraw (sel_start.y0, sel_end.y1, 1, 0);
1126 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1127 XtPointer value, unsigned long *length, int *format)
1132 if (*type == XT_CONVERT_FAIL || ! value)
1134 if (*type == XA_STRING)
1136 else if (*type == XA_COMPOUND_TEXT)
1137 coding = msymbol ("compound-text");
1138 #ifdef X_HAVE_UTF8_STRING
1139 else if (*type == XA_UTF8_STRING)
1140 coding = msymbol ("utf-8");
1145 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1146 if (! this_mt && *type != XA_UTF8_STRING)
1148 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1155 insert_chars (this_mt);
1156 m17n_object_unref (this_mt);
1165 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1167 XExposeEvent *expose = (XExposeEvent *) event;
1171 Dimension width_max, width;
1173 XtSetArg (arg[0], XtNwidth, &width);
1174 XtGetValues (XtParent (w), arg, 1);
1176 XtGetValues (HeadWidget, arg, 1);
1177 if (width_max < width)
1179 XtGetValues (FaceWidget, arg, 1);
1180 if (width_max < width)
1182 XtGetValues (LangWidget, arg, 1);
1183 if (width_max < width)
1185 XtSetArg (arg[0], XtNwidth, width_max);
1186 XtSetValues (HeadWidget, arg, 1);
1187 XtSetValues (FaceWidget, arg, 1);
1188 XtSetValues (LangWidget, arg, 1);
1189 XtSetValues (XtParent (w), arg, 1);
1190 XtSetValues (TailWidget, arg, 1);
1193 update_cursor (0, 1);
1194 redraw (0, win_height, 0, 1);
1195 if (current_input_method >= 0)
1197 int idx = current_input_method;
1199 current_input_method = -1;
1200 input_method_table[idx].im =
1201 minput_open_im (input_method_table[idx].language,
1202 input_method_table[idx].name, NULL);
1203 if (input_method_table[idx].im)
1204 select_input_method (idx);
1206 input_method_table[idx].available = -1;
1212 redraw (expose->y, expose->y + expose->height, 0, 0);
1213 if (current_input_context
1214 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1215 set_input_method_spot ();
1220 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1222 XConfigureEvent *configure = (XConfigureEvent *) event;
1225 control.max_line_width = win_width = configure->width;
1226 win_height = configure->height;
1227 mdraw_clear_cache (mt);
1229 update_cursor (0, 1);
1230 redraw (0, win_height, 1, 1);
1231 if (current_input_context)
1232 set_input_method_spot ();
1236 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1239 int x = event->xbutton.x;
1240 int y = event->xbutton.y - top.ascent;
1242 if (control.orientation_reversed)
1244 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1247 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1248 mtext_detach_property (selection);
1249 redraw (sel_start.y0, sel_end.y1, 1, 0);
1252 if (current_input_context)
1254 MText *produced = mtext ();
1256 minput_reset_ic (current_input_context);
1257 minput_lookup (current_input_context, Mnil, NULL, produced);
1258 if (mtext_len (produced) > 0)
1260 insert_chars (produced);
1261 if (pos >= cursor.from)
1262 pos += mtext_len (produced);
1264 m17n_object_unref (produced);
1266 update_cursor (pos, 0);
1271 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1276 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1277 covert_selection, lose_selection, NULL);
1278 update_cursor (mtext_property_start (selection), 0);
1283 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1287 /* We don't have a local selection. */
1288 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1293 int from = mtext_property_start (selection);
1294 int to = mtext_property_end (selection);
1297 int x = event->xbutton.x;
1298 int y = event->xbutton.y - top.ascent;
1300 if (control.orientation_reversed)
1302 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1304 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1305 mtext_detach_property (selection);
1307 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1308 update_cursor (pos, 0);
1309 insert_chars (this_mt);
1310 m17n_object_unref (this_mt);
1315 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1318 int x = event->xbutton.x;
1319 int y = event->xbutton.y;
1321 if (control.orientation_reversed)
1324 pos = top.from, y -= top.ascent;
1326 pos = cur.from, y -= cur.y0 + cur.ascent;
1327 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1329 if (pos == cursor.from)
1335 /* Selection range changed. */
1336 int from = mtext_property_start (selection);
1337 int to = mtext_property_end (selection);
1338 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1339 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1341 if (cursor.from == from)
1343 /* Starting position changed. */
1346 /* Enlarged. We can simply overdraw. */
1347 select_region (pos, to);
1348 redraw (sel_start.y0, start_y1, 0, 0);
1352 /* Shrunken. Previous selection face must be cleared. */
1353 select_region (pos, to);
1354 redraw (start_y0, sel_start.y1, 1, 0);
1358 /* Shrunken to zero. */
1359 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1360 mtext_detach_property (selection);
1361 redraw (start_y0, end_y1, 1, 0);
1365 /* Full update is necessary. */
1366 select_region (to, pos);
1367 redraw (start_y0, sel_end.y1, 1, 0);
1372 /* Ending position changed. */
1375 /* Full update is necessary. */
1376 select_region (pos, from);
1377 redraw (sel_start.y0, end_y1, 1, 0);
1379 else if (pos == from)
1381 /* Shrunken to zero. */
1382 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1383 mtext_detach_property (selection);
1384 redraw (start_y0, end_y1, 1, 0);
1388 /* Shrunken. Previous selection face must be cleared. */
1389 select_region (from, pos);
1390 redraw (sel_end.y0, end_y1, 1, 0);
1394 /* Enlarged. We can simply overdraw. */
1395 select_region (from, pos);
1396 redraw (end_y0, sel_end.y1, 0, 0);
1402 /* Newly selected. */
1403 select_region (pos, cursor.from);
1404 redraw (sel_start.y0, sel_end.y1, 0, 0);
1406 update_cursor (pos, 1);
1410 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1413 MDrawGlyphInfo info;
1415 int cursor_pos = cursor.from;
1417 if (((int) position) < 0)
1423 height = top.y1 - top.y0;
1426 pos = bol (from - 1, 0);
1427 GLYPH_INFO (pos, from - 1, info);
1428 if (height + info.metrics.height > win_height)
1430 height += info.metrics.height;
1431 from = info.line_from;
1433 if (cursor_pos >= top.to)
1435 cursor_pos = top.from;
1437 while (cursor_pos < nchars)
1439 GLYPH_INFO (pos, pos, info);
1440 if (height + info.metrics.height > win_height)
1442 height += info.metrics.height;
1448 else if (cur.to < nchars)
1450 /* Scroll up, but leave at least one line. */
1453 while (from < nchars)
1455 GLYPH_INFO (from, from, info);
1456 if (height + info.metrics.height > win_height
1457 || info.line_to >= nchars)
1459 height += info.metrics.height;
1460 from = info.line_to;
1463 from = info.line_from;
1464 if (cursor_pos < from)
1468 /* Scroll up to make the cursor line top. */
1472 update_cursor (cursor_pos, 1);
1476 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1478 float persent = *(float *) persent_ptr;
1479 int pos1, pos2 = nchars * persent;
1480 MDrawGlyphInfo info;
1483 pos1 = bol (pos2, 0);
1484 GLYPH_INFO (pos1, pos2, info);
1485 pos1 = info.line_from;
1487 update_cursor (pos1, 1);
1492 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1494 XKeyEvent *key_event = (XKeyEvent *) event;
1496 KeySym keysym = NoSymbol;
1498 /* If set to 1, do not update target_x_position. */
1499 int keep_target_x_position = 0;
1502 if (current_input_context
1503 && minput_filter (current_input_context, Mnil, event))
1505 if (event->type == KeyRelease)
1510 produced = mtext ();
1511 ret = minput_lookup (current_input_context, Mnil, event, produced);
1512 if (mtext_len (produced) > 0)
1513 insert_chars (produced);
1515 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1516 m17n_object_unref (produced);
1526 n = (mtext_property_end (selection)
1527 - mtext_property_start (selection));
1528 mtext_detach_property (selection);
1530 else if (cursor.from < nchars)
1532 /* Delete the following grapheme cluster. */
1533 n = cursor.to - cursor.from;
1546 /* Delete selected region. */
1547 n = (mtext_property_end (selection)
1548 - mtext_property_start (selection));
1549 mtext_detach_property (selection);
1551 else if (cursor.from > 0)
1553 /* Delete the preceding character. */
1564 mtext_detach_property (selection);
1565 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1569 if (cursor.prev_from >= 0)
1570 update_cursor (cursor.prev_from, 0);
1574 if (cursor.left_from >= 0)
1575 update_cursor (cursor.left_from, 0);
1582 mtext_detach_property (selection);
1583 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1587 if (cursor.next_to >= 0)
1588 update_cursor (cursor.to, 0);
1592 if (cursor.right_from >= 0)
1593 update_cursor (cursor.right_from, 0);
1600 mtext_detach_property (selection);
1601 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1603 if (cur.to <= nchars)
1605 MDrawGlyphInfo info;
1608 GLYPH_INFO (cur.from, cur.to, info);
1609 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1610 target_x_position, info.y);
1611 keep_target_x_position = 1;
1612 update_cursor (pos, 0);
1619 mtext_detach_property (selection);
1620 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1626 int pos = bol (cur.from - 1, 0);
1628 TEXT_EXTENTS (pos, cur.from - 1, rect);
1629 y = rect.height + rect.y - 1;
1630 pos = COORDINATES_POSITION (pos, nchars,
1631 target_x_position, y);
1632 keep_target_x_position = 1;
1633 update_cursor (pos, 0);
1640 mtext_detach_property (selection);
1641 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1643 if (top.from < nchars)
1644 ScrollProc (w, NULL, (XtPointer) 1);
1650 mtext_detach_property (selection);
1651 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1654 ScrollProc (w, NULL, (XtPointer) -1);
1658 if (key_event->state >= Mod1Mask)
1660 lose_selection (NULL, NULL);
1666 if (key_event->state >= Mod1Mask)
1668 lose_selection (NULL, NULL);
1676 if (buf[0] == 17) /* C-q */
1678 XtAppSetExitFlag (context);
1681 else if (buf[0] == 12) /* C-l */
1683 redraw (0, win_height, 1, 1);
1688 MText *temp = mtext ();
1690 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1691 : ((unsigned char *) buf)[0]);
1692 if (current_input_context)
1693 mtext_put_prop (temp, 0, 1, Mlanguage,
1694 current_input_context->im->language);
1695 insert_chars (temp);
1696 m17n_object_unref (temp);
1701 if (! keep_target_x_position)
1702 target_x_position = cursor.x;
1706 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1708 char *name = (char *) client_data;
1710 int from = -1, to = 0;
1715 filename = strdup (name);
1718 fp = fopen (filename, "w");
1721 fprintf (stderr, "Open for write fail: %s", filename);
1727 from = mtext_property_start (selection);
1728 to = mtext_property_end (selection);
1729 mtext_detach_property (selection);
1732 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1735 select_region (from, to);
1739 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1745 mtext_detach_property (selection);
1746 serialized = (int) client_data;
1748 new = mtext_deserialize (mt);
1751 MPlist *plist = mplist ();
1753 mplist_push (plist, Mt, Mface);
1754 mplist_push (plist, Mt, Mlanguage);
1755 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1756 m17n_object_unref (plist);
1760 m17n_object_unref (mt);
1762 serialized = ! serialized;
1763 nchars = mtext_len (mt);
1766 update_cursor (0, 1);
1767 redraw (0, win_height, 1, 1);
1771 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1773 XtAppSetExitFlag (context);
1779 FILE *fp = fopen (filename, "r");
1782 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1783 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1786 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1791 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1793 int data = (int) client_data;
1798 control.enable_bidi = 0;
1799 control.orientation_reversed = 0;
1803 control.enable_bidi = 1;
1804 control.orientation_reversed = data == 2;
1806 for (i = 0; i < 3; i++)
1809 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1811 XtSetArg (arg[0], XtNleftBitmap, None);
1812 XtSetValues (BidiMenus[i], arg, 1);
1815 update_cursor (cursor.from, 1);
1816 redraw (0, win_height, 1, 0);
1820 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1822 int data = (int) client_data;
1826 control.max_line_width = 0;
1829 control.max_line_width = win_width;
1830 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1832 for (i = 0; i < 3; i++)
1835 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1837 XtSetArg (arg[0], XtNleftBitmap, None);
1838 XtSetValues (LineBreakMenus[i], arg, 1);
1841 update_cursor (cursor.from, 1);
1842 redraw (0, win_height, 1, 0);
1846 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1848 char *filter_module = (char *) client_data;
1850 void (*func) (MText *, int, int);
1854 handle = dlopen (filter_module, RTLD_NOW);
1857 *(void **) (&func) = dlsym (handle, "filter");
1859 (*func) (mt, mtext_property_start (selection),
1860 mtext_property_end (selection));
1865 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1867 int data = (int) client_data;
1881 control.cursor_bidi = 0, control.cursor_width = -1;
1885 control.cursor_bidi = 0, control.cursor_width = 2;
1889 control.cursor_bidi = 1;
1894 for (i = from; i < to; i++)
1897 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1899 XtSetArg (arg[0], XtNleftBitmap, None);
1900 XtSetValues (CursorMenus[i], arg, 1);
1903 update_cursor (cursor.from, 0);
1904 redraw (0, win_height, 1, 0);
1908 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1910 int idx = (int) client_data;
1912 if (idx == -2 ? current_input_method < 0
1913 : idx == -1 ? auto_input_method
1914 : idx == current_input_method)
1917 XtSetArg (arg[0], XtNleftBitmap, None);
1918 if (auto_input_method)
1920 XtSetValues (InputMethodMenus[1], arg, 1);
1921 auto_input_method = 0;
1923 else if (current_input_method < 0)
1924 XtSetValues (InputMethodMenus[0], arg, 1);
1926 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1930 auto_input_method = 1;
1933 else if (input_method_table[idx].available >= 0)
1935 if (! input_method_table[idx].im)
1937 input_method_table[idx].im =
1938 minput_open_im (input_method_table[idx].language,
1939 input_method_table[idx].name, NULL);
1940 if (! input_method_table[idx].im)
1941 input_method_table[idx].available = -1;
1943 if (input_method_table[idx].im)
1944 select_input_method (idx);
1946 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1947 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1950 MPlist *default_face_list;
1953 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1955 int idx = (int) client_data;
1966 MFace *face = mframe_get_prop (frame, Mface);
1968 for (plist = default_face_list; mplist_key (plist) != Mnil;
1969 plist = mplist_next (plist))
1970 mface_merge (face, mplist_value (plist));
1971 mplist_add (plist, Mt, *face_table[idx].face);
1972 mface_merge (face, *face_table[idx].face);
1974 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1976 MFace *face = mframe_get_prop (frame, Mface);
1978 for (plist = default_face_list;
1979 mplist_key (mplist_next (plist)) != Mnil;
1980 plist = mplist_next (plist))
1981 mface_merge (face, mplist_value (plist));
1985 update_cursor (0, 1);
1986 redraw (0, win_height, 1, 1);
1991 XtAppAddWorkProc (context, show_cursor, NULL);
1992 from = mtext_property_start (selection);
1993 to = mtext_property_end (selection);
1994 old_y1 = sel_end.y1;
1996 mtext_detach_property (selection);
1999 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
2000 MTEXTPROP_REAR_STICKY);
2001 mtext_push_property (mt, from, to, prop);
2002 m17n_object_unref (prop);
2005 mtext_pop_prop (mt, from, to, Mface);
2007 update_top (top.from);
2008 update_cursor (cursor.from, 1);
2009 select_region (from, to);
2010 update_region (sel_start.y0, old_y1, sel_end.y1);
2011 if (cur.y1 > win_height)
2013 while (cur.y1 > win_height)
2016 update_cursor (cursor.from, 1);
2022 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2024 MSymbol sym = (MSymbol) client_data;
2031 XtAppAddWorkProc (context, show_cursor, NULL);
2032 from = mtext_property_start (selection);
2033 to = mtext_property_end (selection);
2034 old_y1 = sel_end.y1;
2036 mtext_detach_property (selection);
2038 mtext_put_prop (mt, from, to, Mlanguage, sym);
2040 mtext_pop_prop (mt, from, to, Mlanguage);
2043 update_top (top.from);
2044 update_cursor (cursor.from, 1);
2045 select_region (from, to);
2046 update_region (sel_start.y0, old_y1, sel_end.y1);
2047 if (cur.y1 > win_height)
2049 while (cur.y1 > win_height)
2052 update_cursor (cursor.from, 1);
2058 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2060 int narrowed = (int) client_data;
2063 MConverter *converter;
2069 from = mtext_property_start (selection);
2070 to = mtext_property_end (selection);
2079 mdump = popen ("mdump -q -p a4", "w");
2081 mdump = popen ("mdump -q", "w");
2084 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2085 mconv_encode_range (converter, mt, from, to);
2086 mconv_free_converter (converter);
2091 input_status (MInputContext *ic, MSymbol command)
2093 XFillRectangle (display, input_status_pixmap, gc_inv,
2094 0, 0, input_status_width, input_status_height);
2095 if (command == Minput_status_draw)
2099 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2100 Mface, face_input_status);
2101 if (ic->im->language != Mnil)
2102 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2103 Mlanguage, ic->im->language);
2104 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2105 &input_status_control, NULL, NULL, &rect);
2106 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2107 input_status_width - rect.width - 2, - rect.y,
2108 ic->status, 0, mtext_len (ic->status),
2109 &input_status_control);
2111 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2112 XtSetValues (CurIMStatus, arg, 1);
2116 compare_input_method (const void *elt1, const void *elt2)
2118 const InputMethodInfo *im1 = elt1;
2119 const InputMethodInfo *im2 = elt2;
2120 MSymbol lang1, lang2;
2122 if (im1->language == Mnil)
2124 if (im1->language == im2->language)
2125 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2126 if (im1->language == Mt)
2128 if (im2->language == Mt)
2130 lang1 = msymbol_get (im1->language, Mlanguage);
2131 lang2 = msymbol_get (im2->language, Mlanguage);
2132 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2136 setup_input_methods (int with_xim, char *initial_input_method)
2138 MInputMethod *im = NULL;
2139 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2142 char *lang_name = NULL, *method_name = NULL;
2144 if (initial_input_method)
2146 char *p = strchr (initial_input_method, '-');
2148 lang_name = initial_input_method, method_name = p + 1, *p = '\0';
2150 method_name = initial_input_method;
2153 num_input_methods = plist ? mplist_length (plist) : 0;
2157 MInputXIMArgIM arg_xim;
2159 arg_xim.display = display;
2161 arg_xim.res_name = arg_xim.res_class = NULL;
2162 arg_xim.locale = NULL;
2163 arg_xim.modifier_list = NULL;
2164 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2166 num_input_methods++;
2168 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2171 input_method_table[i].available = 1;
2172 input_method_table[i].language = Mnil;
2173 input_method_table[i].name = im->name;
2174 input_method_table[i].im = im;
2180 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2182 MDatabase *mdb = mplist_value (pl);
2183 MSymbol *tag = mdatabase_tag (mdb);
2187 input_method_table[i].language = tag[1];
2188 input_method_table[i].name = tag[2];
2193 m17n_object_unref (plist);
2195 num_input_methods = i;
2196 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2197 compare_input_method);
2198 current_input_context = NULL;
2200 mplist_put (minput_driver->callback_list, Minput_status_start,
2201 (void *) input_status);
2202 mplist_put (minput_driver->callback_list, Minput_status_draw,
2203 (void *) input_status);
2204 mplist_put (minput_driver->callback_list, Minput_status_done,
2205 (void *) input_status);
2208 for (i = 0; i < num_input_methods; i++)
2209 if (strcmp (method_name, msymbol_name (input_method_table[i].name)) == 0
2211 ? strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0
2212 : input_method_table[i].language == Mt))
2214 current_input_method = i;
2221 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2225 if (num && *num > 0)
2229 for (i = 0; i < *num; i++)
2230 bytes += strlen (str[i]) + 1;
2231 msg = alloca (bytes);
2232 strcpy (msg, str[0]);
2233 for (i = 1; i < *num; i++)
2234 strcat (msg, " "), strcat (msg, str[i]);
2236 else if (cursor.from < nchars)
2238 int c = mtext_ref_char (mt, cursor.from);
2239 char *name = mchar_get_prop (c, Mname);
2243 msg = alloca (10 + strlen (name));
2244 sprintf (msg, "U+%04X %s", c, name);
2250 XtSetArg (arg[0], XtNlabel, msg);
2251 XtSetValues (MessageWidget, arg, 1);
2257 char *name1, *name2;
2258 XtCallbackProc proc;
2259 XtPointer client_data;
2264 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2266 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2268 MenuRec FileMenu[] =
2269 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2270 { 0, "Save", NULL, SaveProc, NULL, -1 },
2271 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2273 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2274 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2276 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2277 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2279 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2282 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2284 MenuRec *rec = (MenuRec *) client_data;
2287 XtSetArg (arg[0], XtNvalue, "");
2288 XtSetArg (arg[1], XtNlabel, rec->name1);
2289 XtSetValues (FileDialogWidget, arg, 2);
2290 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2291 XtSetArg (arg[0], XtNx, x + 20);
2292 XtSetArg (arg[1], XtNy, y + 10);
2293 XtSetValues (FileShellWidget, arg, 2);
2294 XtPopup (FileShellWidget, XtGrabExclusive);
2298 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2303 XtPopdown (FileShellWidget);
2304 if ((int) client_data == 1)
2306 XtSetArg (arg[0], XtNlabel, &label);
2307 XtGetValues (FileDialogWidget, arg, 1);
2308 if (strcmp (label, FileMenu[0].name1) == 0)
2312 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2313 fp = fopen (filename, "r");
2315 m17n_object_unref (mt);
2318 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2326 nchars = mtext_len (mt);
2328 update_cursor (0, 1);
2329 redraw (0, win_height, 1, 1);
2331 else if (strcmp (label, FileMenu[2].name1) == 0)
2332 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2334 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2337 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2338 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2339 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2340 (MENU).status = (STATUS))
2344 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2345 char *menu_name, MenuRec *menus, int num_menus, char *help)
2347 Widget button, menu;
2348 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2349 <LeaveWindow>: reset() MenuHelp()\n\
2350 <BtnDown>: reset() PopupMenu()\n\
2351 <BtnUp>: highlight()";
2357 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2358 for (i = 0; i < num_menus; i++)
2369 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2371 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2373 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2375 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2379 XtSetArg (arg[0], XtNsensitive, False);
2380 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2386 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2391 trans = alloca (strlen (fmt) + strlen (help));
2392 sprintf (trans, fmt, help);
2393 XtSetArg (arg[0], XtNmenuName, menu_name);
2394 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2395 XtSetArg (arg[2], XtNinternalWidth, 2);
2396 XtSetArg (arg[3], XtNhighlightThickness, 1);
2397 XtSetArg (arg[4], XtNleft, XawChainLeft);
2398 XtSetArg (arg[5], XtNright, XawChainLeft);
2401 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2402 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2407 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2408 int *len = alloca (sizeof (int) * num_menus);
2411 XFontSetExtents *fontset_extents;
2413 XtSetArg (arg[0], XtNfontSet, &font_set);
2414 XtGetValues (button, arg, 1);
2416 fontset_extents = XExtentsOfFontSet (font_set);
2417 height = fontset_extents->max_logical_extent.height;
2418 ascent = - fontset_extents->max_logical_extent.y;
2420 for (i = 0; i < num_menus; i++)
2423 len[i] = strlen (menus[i].name2);
2424 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2425 if (max_width < width[i])
2426 max_width = width[i];
2428 for (i = 0; i < num_menus; i++)
2431 Pixmap pixmap = XCreatePixmap (display,
2432 RootWindow (display, screen),
2433 max_width, height, 1);
2434 XFillRectangle (display, pixmap, mono_gc_inv,
2435 0, 0, max_width, height);
2436 XmbDrawString (display, pixmap, font_set, mono_gc,
2437 max_width - width[i], ascent,
2438 menus[i].name2, len[i]);
2439 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2440 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2441 XtSetValues (menus[i].w, arg, 2);
2449 XtActionsRec actions[] = {
2450 {"Expose", ExposeProc},
2451 {"Configure", ConfigureProc},
2453 {"ButtonPress", ButtonProc},
2454 {"ButtonRelease", ButtonReleaseProc},
2455 {"ButtonMotion", ButtonMoveProc},
2456 {"Button2Press", Button2Proc},
2457 {"MenuHelp", MenuHelpProc}
2461 /* Print the usage of this program (the name is PROG), and exit with
2465 help_exit (char *prog, int exit_code)
2473 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2474 printf ("Display FILE on a window and allow users to edit it.\n");
2475 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2476 printf ("The following OPTIONs are available.\n");
2477 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2478 "Use the specified fontset\n");
2479 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2480 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2481 "Input method activated initially.\n");
2482 printf (" %-13s %s", "--version", "print version number\n");
2483 printf (" %-13s %s", "-h, --help", "print this message\n");
2489 main (int argc, char **argv)
2491 Widget form, BodyWidget, w;
2492 char *fontset_name = NULL;
2494 char *initial_input_method = NULL;
2495 int col = 80, row = 32;
2496 /* Translation table for TextWidget. */
2497 String trans = "<Expose>: Expose()\n\
2498 <Configure>: Configure()\n\
2501 <Btn1Down>: ButtonPress()\n\
2502 <Btn1Up>: ButtonRelease()\n\
2503 <Btn1Motion>: ButtonMotion()\n\
2504 <Btn2Down>: Button2Press()";
2505 /* Translation table for the top form widget. */
2506 String trans2 = "<Key>: Key()\n\
2508 String pop_face_trans
2509 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2510 <LeaveWindow>: MenuHelp() reset()\n\
2511 <Btn1Down>: set()\n\
2512 <Btn1Up>: notify() unset()";
2513 String pop_lang_trans
2514 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2515 <LeaveWindow>: MenuHelp() reset()\n\
2516 <Btn1Down>: set()\n\
2517 <Btn1Up>: notify() unset()";
2518 int font_width, font_ascent, font_descent;
2521 char *filter = NULL;
2523 setlocale (LC_ALL, "");
2524 /* Create the top shell. */
2525 XtSetLanguageProc (NULL, NULL, NULL);
2526 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2527 NULL, sessionShellWidgetClass, NULL, 0);
2528 display = XtDisplay (ShellWidget);
2529 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2531 /* Parse the remaining command line arguments. */
2532 for (i = 1; i < argc; i++)
2534 if (! strcmp (argv[i], "--help")
2535 || ! strcmp (argv[i], "-h"))
2536 help_exit (argv[0], 0);
2537 else if (! strcmp (argv[i], "--version"))
2539 printf ("m17n-edit (m17n library) %s\n", VERSION);
2540 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2543 else if (! strcmp (argv[i], "--geometry"))
2546 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2547 help_exit (argv[0], 1);
2549 else if (! strcmp (argv[i], "-s"))
2552 fontsize = atoi (argv[i]);
2556 else if (! strcmp (argv[i], "--fontset"))
2559 fontset_name = strdup (argv[i]);
2561 else if (! strcmp (argv[i], "--im"))
2564 initial_input_method = strdup (argv[i]);
2566 else if (! strcmp (argv[i], "--with-xim"))
2570 else if (! strcmp (argv[i], "--filter"))
2575 else if (argv[i][0] != '-')
2577 filename = strdup (argv[i]);
2581 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2582 help_exit (argv[0], 1);
2586 filename = strdup ("/dev/null");
2588 mdatabase_dir = ".";
2589 /* Initialize the m17n library. */
2591 if (merror_code != MERROR_NONE)
2592 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2593 minput_driver = &minput_gui_driver;
2595 mt = read_file (filename);
2598 nchars = mtext_len (mt);
2600 Mword = msymbol ("word");
2603 MFace *face = mface ();
2605 mface_put_prop (face, Mforeground, msymbol ("blue"));
2606 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2607 mface_put_prop (face, Mvideomode, Mreverse);
2608 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2609 m17n_object_unref (face);
2612 /* This tells ExposeProc to initialize everything. */
2615 XA_TEXT = XInternAtom (display, "TEXT", False);
2616 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2617 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2618 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2619 if (Mcoding_compound_text == Mnil)
2620 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2623 MPlist *plist = mplist ();
2627 mplist_put (plist, msymbol ("widget"), ShellWidget);
2628 if (fontset_name || fontsize > 0)
2630 MFontset *fontset = mfontset (fontset_name);
2633 mface_put_prop (face, Mfontset, fontset);
2634 mface_put_prop (face, Msize, (void *) fontsize);
2635 m17n_object_unref (fontset);
2636 mplist_add (plist, Mface, face);
2637 m17n_object_unref (face);
2639 frame = mframe (plist);
2641 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2642 m17n_object_unref (plist);
2643 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2644 default_face_list = mplist ();
2645 mplist_add (default_face_list, Mt, face_default);
2646 face_default_fontset = mface ();
2647 mface_put_prop (face_default_fontset, Mfontset,
2648 mface_get_prop (face_default, Mfontset));
2650 font = (MFont *) mframe_get_prop (frame, Mfont);
2651 default_font_size = (int) mfont_get_prop (font, Msize);
2654 font_width = (int) mframe_get_prop (frame, Mfont_width);
2655 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2656 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2657 win_width = font_width * col;
2658 win_height = (font_ascent + font_descent) * row;
2664 prop.color_top = prop.color_left = msymbol ("magenta");
2665 prop.color_bottom = prop.color_right = msymbol ("red");
2666 prop.inner_hmargin = prop.inner_vmargin = 1;
2667 prop.outer_hmargin = prop.outer_vmargin = 2;
2669 face_box = mface ();
2670 mface_put_prop (face_box, Mbox, &prop);
2673 face_courier = mface ();
2674 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2675 face_helvetica = mface ();
2676 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2677 face_times = mface ();
2678 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2679 face_dv_ttyogesh = mface ();
2680 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2681 face_freesans = mface ();
2682 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2683 face_freeserif = mface ();
2684 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2685 face_freemono = mface ();
2686 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2688 face_xxx_large = mface ();
2689 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2691 MFont *latin_font = mframe_get_prop (frame, Mfont);
2692 MFont *dev_font = mfont ();
2693 MFont *thai_font = mfont ();
2694 MFont *tib_font = mfont ();
2696 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2697 MSymbol no_ctl = msymbol ("no-ctl");
2699 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2700 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2701 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2702 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2703 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2704 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2706 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2707 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2708 latin_font, Mnil, 0);
2709 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2710 dev_font, no_ctl, 0);
2711 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2712 thai_font, no_ctl, 0);
2713 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2714 tib_font, no_ctl, 0);
2715 face_no_ctl_fontset = mface ();
2716 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2717 m17n_object_unref (fontset);
2724 setup_input_methods (with_xim, initial_input_method);
2726 gc = DefaultGC (display, screen);
2728 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2729 XtSetArg (arg[1], XtNdefaultDistance, 2);
2730 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2732 XtSetArg (arg[0], XtNborderWidth, 0);
2733 XtSetArg (arg[1], XtNdefaultDistance, 2);
2734 XtSetArg (arg[2], XtNtop, XawChainTop);
2735 XtSetArg (arg[3], XtNbottom, XawChainTop);
2736 XtSetArg (arg[4], XtNleft, XawChainLeft);
2737 XtSetArg (arg[5], XtNright, XawChainRight);
2738 XtSetArg (arg[6], XtNresizable, True);
2739 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2740 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2741 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2742 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2743 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2744 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2745 XtSetArg (arg[7], XtNfromVert, LangWidget);
2746 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2747 XtSetArg (arg[2], XtNtop, XawChainBottom);
2748 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2749 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2751 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2752 HeadWidget, NULL, 0);
2753 XtSetArg (arg[0], XtNvalue, "");
2754 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2755 FileShellWidget, arg, 1);
2756 XawDialogAddButton (FileDialogWidget, "OK",
2757 FileDialogProc, (XtPointer) 0);
2758 XawDialogAddButton (FileDialogWidget, "CANCEL",
2759 FileDialogProc, (XtPointer) 1);
2761 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2762 (char *) check_bits,
2763 check_width, check_height);
2765 unsigned long valuemask = GCForeground;
2768 values.foreground = 1;
2769 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2770 values.foreground = 0;
2771 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2778 if (num_menus < num_input_methods + 2)
2779 num_menus = num_input_methods + 2;
2780 if (num_menus < num_faces + 1)
2781 num_menus = num_faces + 1;
2782 menus = alloca (sizeof (MenuRec) * num_menus);
2784 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2785 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2786 "File I/O, Serialization, Image, Quit");
2788 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2789 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2790 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2791 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2792 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2793 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2794 w = create_menu_button (ShellWidget, HeadWidget, w,
2795 "Cursor", "Cursor Menu",
2796 menus, 6, "Cursor Movement Mode, Cursor Shape");
2797 CursorMenus[0] = menus[0].w;
2798 CursorMenus[1] = menus[1].w;
2799 CursorMenus[2] = menus[3].w;
2800 CursorMenus[3] = menus[4].w;
2801 CursorMenus[4] = menus[5].w;
2803 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2804 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2805 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2806 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2807 menus, 3, "BIDI Processing Mode");
2808 for (i = 0; i < 3; i++)
2809 BidiMenus[i] = menus[i].w;
2811 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2812 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2813 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2814 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2816 menus, 3, "How to break lines");
2817 for (i = 0; i < 3; i++)
2818 LineBreakMenus[i] = menus[i].w;
2820 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2821 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2822 for (i = 0; i < num_input_methods; i++)
2824 InputMethodInfo *im = input_method_table + i;
2825 char *name1, *name2;
2827 if (im->language != Mnil && im->language != Mt)
2829 MSymbol sym = msymbol_get (im->language, Mlanguage);
2831 name1 = msymbol_name (im->language);
2833 name1 = msymbol_name (sym);
2834 name2 = msymbol_name (im->name);
2837 name1 = msymbol_name (im->name), name2 = NULL;
2839 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2841 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2842 "Input Method Menu", menus, i + 2,
2843 "Select input method");
2846 unsigned long valuemask = GCForeground;
2849 XtSetArg (arg[0], XtNbackground, &values.foreground);
2850 XtGetValues (w, arg, 1);
2851 gc_inv = XCreateGC (display, RootWindow (display, screen),
2852 valuemask, &values);
2855 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2856 for (i = 0; i < num_input_methods + 2; i++)
2857 InputMethodMenus[i] = menus[i].w;
2861 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2862 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2863 "Filter Menu", menus, 1,
2864 "Select filter to run");
2867 input_status_width = font_width * 8;
2868 input_status_height = (font_ascent + font_descent) * 2.4;
2869 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2871 input_status_height,
2872 DefaultDepth (display, screen));
2877 prop.color_top = prop.color_bottom
2878 = prop.color_left = prop.color_right = Mnil;
2879 prop.inner_hmargin = prop.inner_vmargin = 1;
2880 prop.outer_hmargin = prop.outer_vmargin = 0;
2881 face_input_status = mface_copy (face_default);
2882 mface_put_prop (face_input_status, Mbox, &prop);
2885 XFillRectangle (display, input_status_pixmap, gc_inv,
2886 0, 0, input_status_width, input_status_height);
2887 XtSetArg (arg[0], XtNfromHoriz, w);
2888 XtSetArg (arg[1], XtNleft, XawRubber);
2889 XtSetArg (arg[2], XtNright, XawChainRight);
2890 XtSetArg (arg[3], XtNborderWidth, 0);
2891 XtSetArg (arg[4], XtNlabel, " ");
2892 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2893 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2894 HeadWidget, arg, 6);
2895 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2896 XtSetArg (arg[1], XtNleft, XawChainRight);
2897 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2898 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2899 HeadWidget, arg, 5);
2901 XtSetArg (arg[0], XtNborderWidth, 0);
2902 XtSetArg (arg[1], XtNleft, XawChainLeft);
2903 XtSetArg (arg[2], XtNright, XawChainLeft);
2904 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2905 for (i = 0; i < num_faces;)
2907 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2908 char *label = label_menu + 5; /* "Xxxx" */
2910 for (j = i; j < num_faces && face_table[j].face; j++)
2911 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2913 w = create_menu_button (ShellWidget, FaceWidget, w,
2915 menus, j - i, "Push face property");
2919 XtSetArg (arg[0], XtNfromHoriz, w);
2920 XtSetArg (arg[1], XtNleft, XawChainLeft);
2921 XtSetArg (arg[2], XtNright, XawChainLeft);
2922 XtSetArg (arg[3], XtNhorizDistance, 10);
2923 XtSetArg (arg[4], XtNlabel, "Pop");
2924 XtSetArg (arg[5], XtNtranslations,
2925 XtParseTranslationTable (pop_face_trans));
2926 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2927 FaceWidget, arg, 6);
2928 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2930 XtSetArg (arg[0], XtNfromHoriz, w);
2931 XtSetArg (arg[1], XtNleft, XawChainLeft);
2932 XtSetArg (arg[2], XtNright, XawChainRight);
2933 XtSetArg (arg[3], XtNlabel, "");
2934 XtSetArg (arg[4], XtNborderWidth, 0);
2935 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2936 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2937 FaceWidget, arg, 6);
2939 XtSetArg (arg[0], XtNborderWidth, 0);
2940 XtSetArg (arg[1], XtNleft, XawChainLeft);
2941 XtSetArg (arg[2], XtNright, XawChainLeft);
2942 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2944 MPlist *plist[11], *pl;
2947 for (i = 0; i < 11; i++) plist[i] = NULL;
2949 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2950 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2952 MSymbol sym = msymbol_exist (langname);
2956 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2958 char *name = msymbol_name (fullname);
2961 if (c >= 'A' && c <= 'Z')
2963 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2967 pl = plist[idx] = mplist ();
2968 for (; mplist_next (pl); pl = mplist_next (pl))
2969 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2971 mplist_push (pl, sym, fullname);
2976 for (i = 0; i < 11; i++)
2979 char *name = alloca (9);
2981 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2984 for (j = 0, pl = plist[i]; mplist_next (pl);
2985 j++, pl = mplist_next (pl))
2986 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2987 msymbol_name (mplist_key (pl)),
2988 LangProc, mplist_key (pl), -1);
2989 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2990 menus, j, "Push language property");
2992 for (i = 0; i < 11; i++)
2994 m17n_object_unref (plist[i]);
2996 XtSetArg (arg[0], XtNfromHoriz, w);
2997 XtSetArg (arg[1], XtNleft, XawChainLeft);
2998 XtSetArg (arg[2], XtNright, XawChainLeft);
2999 XtSetArg (arg[3], XtNhorizDistance, 10);
3000 XtSetArg (arg[4], XtNlabel, "Pop");
3001 XtSetArg (arg[5], XtNtranslations,
3002 XtParseTranslationTable (pop_lang_trans));
3003 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3004 LangWidget, arg, 6);
3005 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3007 XtSetArg (arg[0], XtNfromHoriz, w);
3008 XtSetArg (arg[1], XtNleft, XawChainLeft);
3009 XtSetArg (arg[2], XtNright, XawChainRight);
3010 XtSetArg (arg[3], XtNlabel, "");
3011 XtSetArg (arg[4], XtNborderWidth, 0);
3012 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3013 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3014 LangWidget, arg, 6);
3017 XtSetArg (arg[0], XtNheight, win_height);
3018 XtSetArg (arg[1], XtNwidth, 10);
3019 XtSetArg (arg[2], XtNleft, XawChainLeft);
3020 XtSetArg (arg[3], XtNright, XawChainLeft);
3021 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3023 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3024 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3026 XtSetArg (arg[0], XtNheight, win_height);
3027 XtSetArg (arg[1], XtNwidth, win_width);
3028 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3029 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3030 XtSetArg (arg[4], XtNleft, XawChainLeft);
3031 XtSetArg (arg[5], XtNright, XawChainRight);
3032 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3035 XtSetArg (arg[0], XtNborderWidth, 0);
3036 XtSetArg (arg[1], XtNleft, XawChainLeft);
3037 XtSetArg (arg[2], XtNright, XawChainRight);
3038 XtSetArg (arg[3], XtNresizable, True);
3039 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3040 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3041 TailWidget, arg, 5);
3043 memset (&control, 0, sizeof control);
3044 control.two_dimensional = 1;
3045 control.enable_bidi = 1;
3046 control.anti_alias = 1;
3047 control.min_line_ascent = font_ascent;
3048 control.min_line_descent = font_descent;
3049 control.max_line_width = win_width;
3050 control.with_cursor = 1;
3051 control.cursor_width = 2;
3052 control.partial_update = 1;
3053 control.ignore_formatting_char = 1;
3055 memset (&input_status_control, 0, sizeof input_status_control);
3056 input_status_control.enable_bidi = 1;
3058 XtAppAddActions (context, actions, XtNumber (actions));
3059 XtRealizeWidget (ShellWidget);
3061 win = XtWindow (TextWidget);
3063 XtAppMainLoop (context);
3065 if (current_input_context)
3066 minput_destroy_ic (current_input_context);
3067 for (i = 0; i < num_input_methods; i++)
3068 if (input_method_table[i].im)
3069 minput_close_im (input_method_table[i].im);
3070 m17n_object_unref (frame);
3071 m17n_object_unref (mt);
3072 m17n_object_unref (face_xxx_large);
3073 m17n_object_unref (face_box);
3074 m17n_object_unref (face_courier);
3075 m17n_object_unref (face_helvetica);
3076 m17n_object_unref (face_times);
3077 m17n_object_unref (face_dv_ttyogesh);
3078 m17n_object_unref (face_freesans);
3079 m17n_object_unref (face_freeserif);
3080 m17n_object_unref (face_freemono);
3081 m17n_object_unref (face_default_fontset);
3082 m17n_object_unref (face_no_ctl_fontset);
3083 m17n_object_unref (face_input_status);
3084 m17n_object_unref (face_default);
3085 m17n_object_unref (default_face_list);
3086 m17n_object_unref (selection);
3088 XFreeGC (display, mono_gc);
3089 XFreeGC (display, mono_gc_inv);
3090 XFreeGC (display, gc_inv);
3091 XtUninstallTranslations (form);
3092 XtUninstallTranslations (TextWidget);
3093 XtDestroyWidget (ShellWidget);
3094 XtDestroyApplicationContext (context);
3098 free (fontset_name);
3100 free (input_method_table);
3101 free (InputMethodMenus);
3106 #else /* not HAVE_X11_XAW_COMMAND_H */
3109 main (int argc, char **argv)
3112 "Building of this program failed (lack of some header files)\n");
3116 #endif /* not HAVE_X11_XAW_COMMAND_H */
3118 #endif /* not FOR_DOXYGEN */