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!");
2594 mt = read_file (filename);
2597 nchars = mtext_len (mt);
2599 Mword = msymbol ("word");
2602 MFace *face = mface ();
2604 mface_put_prop (face, Mforeground, msymbol ("blue"));
2605 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2606 mface_put_prop (face, Mvideomode, Mreverse);
2607 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2608 m17n_object_unref (face);
2611 /* This tells ExposeProc to initialize everything. */
2614 XA_TEXT = XInternAtom (display, "TEXT", False);
2615 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2616 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2617 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2618 if (Mcoding_compound_text == Mnil)
2619 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2622 MPlist *plist = mplist ();
2626 mplist_put (plist, msymbol ("widget"), ShellWidget);
2627 if (fontset_name || fontsize > 0)
2629 MFontset *fontset = mfontset (fontset_name);
2632 mface_put_prop (face, Mfontset, fontset);
2633 mface_put_prop (face, Msize, (void *) fontsize);
2634 m17n_object_unref (fontset);
2635 mplist_add (plist, Mface, face);
2636 m17n_object_unref (face);
2638 frame = mframe (plist);
2640 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2641 m17n_object_unref (plist);
2642 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2643 default_face_list = mplist ();
2644 mplist_add (default_face_list, Mt, face_default);
2645 face_default_fontset = mface ();
2646 mface_put_prop (face_default_fontset, Mfontset,
2647 mface_get_prop (face_default, Mfontset));
2649 font = (MFont *) mframe_get_prop (frame, Mfont);
2650 default_font_size = (int) mfont_get_prop (font, Msize);
2653 font_width = (int) mframe_get_prop (frame, Mfont_width);
2654 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2655 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2656 win_width = font_width * col;
2657 win_height = (font_ascent + font_descent) * row;
2663 prop.color_top = prop.color_left = msymbol ("magenta");
2664 prop.color_bottom = prop.color_right = msymbol ("red");
2665 prop.inner_hmargin = prop.inner_vmargin = 1;
2666 prop.outer_hmargin = prop.outer_vmargin = 2;
2668 face_box = mface ();
2669 mface_put_prop (face_box, Mbox, &prop);
2672 face_courier = mface ();
2673 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2674 face_helvetica = mface ();
2675 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2676 face_times = mface ();
2677 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2678 face_dv_ttyogesh = mface ();
2679 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2680 face_freesans = mface ();
2681 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2682 face_freeserif = mface ();
2683 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2684 face_freemono = mface ();
2685 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2687 face_xxx_large = mface ();
2688 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2690 MFont *latin_font = mframe_get_prop (frame, Mfont);
2691 MFont *dev_font = mfont ();
2692 MFont *thai_font = mfont ();
2693 MFont *tib_font = mfont ();
2695 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2696 MSymbol no_ctl = msymbol ("no-ctl");
2698 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2699 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2700 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2701 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2702 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2703 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2705 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2706 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2707 latin_font, Mnil, 0);
2708 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2709 dev_font, no_ctl, 0);
2710 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2711 thai_font, no_ctl, 0);
2712 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2713 tib_font, no_ctl, 0);
2714 face_no_ctl_fontset = mface ();
2715 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2716 m17n_object_unref (fontset);
2723 setup_input_methods (with_xim, initial_input_method);
2725 gc = DefaultGC (display, screen);
2727 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2728 XtSetArg (arg[1], XtNdefaultDistance, 2);
2729 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2731 XtSetArg (arg[0], XtNborderWidth, 0);
2732 XtSetArg (arg[1], XtNdefaultDistance, 2);
2733 XtSetArg (arg[2], XtNtop, XawChainTop);
2734 XtSetArg (arg[3], XtNbottom, XawChainTop);
2735 XtSetArg (arg[4], XtNleft, XawChainLeft);
2736 XtSetArg (arg[5], XtNright, XawChainRight);
2737 XtSetArg (arg[6], XtNresizable, True);
2738 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2739 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2740 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2741 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2742 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2743 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2744 XtSetArg (arg[7], XtNfromVert, LangWidget);
2745 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2746 XtSetArg (arg[2], XtNtop, XawChainBottom);
2747 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2748 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2750 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2751 HeadWidget, NULL, 0);
2752 XtSetArg (arg[0], XtNvalue, "");
2753 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2754 FileShellWidget, arg, 1);
2755 XawDialogAddButton (FileDialogWidget, "OK",
2756 FileDialogProc, (XtPointer) 0);
2757 XawDialogAddButton (FileDialogWidget, "CANCEL",
2758 FileDialogProc, (XtPointer) 1);
2760 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2761 (char *) check_bits,
2762 check_width, check_height);
2764 unsigned long valuemask = GCForeground;
2767 values.foreground = 1;
2768 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2769 values.foreground = 0;
2770 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2777 if (num_menus < num_input_methods + 2)
2778 num_menus = num_input_methods + 2;
2779 if (num_menus < num_faces + 1)
2780 num_menus = num_faces + 1;
2781 menus = alloca (sizeof (MenuRec) * num_menus);
2783 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2784 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2785 "File I/O, Serialization, Image, Quit");
2787 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2788 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2789 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2790 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2791 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2792 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2793 w = create_menu_button (ShellWidget, HeadWidget, w,
2794 "Cursor", "Cursor Menu",
2795 menus, 6, "Cursor Movement Mode, Cursor Shape");
2796 CursorMenus[0] = menus[0].w;
2797 CursorMenus[1] = menus[1].w;
2798 CursorMenus[2] = menus[3].w;
2799 CursorMenus[3] = menus[4].w;
2800 CursorMenus[4] = menus[5].w;
2802 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2803 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2804 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2805 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2806 menus, 3, "BIDI Processing Mode");
2807 for (i = 0; i < 3; i++)
2808 BidiMenus[i] = menus[i].w;
2810 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2811 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2812 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2813 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2815 menus, 3, "How to break lines");
2816 for (i = 0; i < 3; i++)
2817 LineBreakMenus[i] = menus[i].w;
2819 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2820 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2821 for (i = 0; i < num_input_methods; i++)
2823 InputMethodInfo *im = input_method_table + i;
2824 char *name1, *name2;
2826 if (im->language != Mnil && im->language != Mt)
2828 MSymbol sym = msymbol_get (im->language, Mlanguage);
2830 name1 = msymbol_name (im->language);
2832 name1 = msymbol_name (sym);
2833 name2 = msymbol_name (im->name);
2836 name1 = msymbol_name (im->name), name2 = NULL;
2838 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2840 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2841 "Input Method Menu", menus, i + 2,
2842 "Select input method");
2845 unsigned long valuemask = GCForeground;
2848 XtSetArg (arg[0], XtNbackground, &values.foreground);
2849 XtGetValues (w, arg, 1);
2850 gc_inv = XCreateGC (display, RootWindow (display, screen),
2851 valuemask, &values);
2854 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2855 for (i = 0; i < num_input_methods + 2; i++)
2856 InputMethodMenus[i] = menus[i].w;
2860 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2861 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2862 "Filter Menu", menus, 1,
2863 "Select filter to run");
2866 input_status_width = font_width * 8;
2867 input_status_height = (font_ascent + font_descent) * 2.4;
2868 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2870 input_status_height,
2871 DefaultDepth (display, screen));
2876 prop.color_top = prop.color_bottom
2877 = prop.color_left = prop.color_right = Mnil;
2878 prop.inner_hmargin = prop.inner_vmargin = 1;
2879 prop.outer_hmargin = prop.outer_vmargin = 0;
2880 face_input_status = mface_copy (face_default);
2881 mface_put_prop (face_input_status, Mbox, &prop);
2884 XFillRectangle (display, input_status_pixmap, gc_inv,
2885 0, 0, input_status_width, input_status_height);
2886 XtSetArg (arg[0], XtNfromHoriz, w);
2887 XtSetArg (arg[1], XtNleft, XawRubber);
2888 XtSetArg (arg[2], XtNright, XawChainRight);
2889 XtSetArg (arg[3], XtNborderWidth, 0);
2890 XtSetArg (arg[4], XtNlabel, " ");
2891 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2892 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2893 HeadWidget, arg, 6);
2894 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2895 XtSetArg (arg[1], XtNleft, XawChainRight);
2896 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2897 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2898 HeadWidget, arg, 5);
2900 XtSetArg (arg[0], XtNborderWidth, 0);
2901 XtSetArg (arg[1], XtNleft, XawChainLeft);
2902 XtSetArg (arg[2], XtNright, XawChainLeft);
2903 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2904 for (i = 0; i < num_faces;)
2906 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2907 char *label = label_menu + 5; /* "Xxxx" */
2909 for (j = i; j < num_faces && face_table[j].face; j++)
2910 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2912 w = create_menu_button (ShellWidget, FaceWidget, w,
2914 menus, j - i, "Push face property");
2918 XtSetArg (arg[0], XtNfromHoriz, w);
2919 XtSetArg (arg[1], XtNleft, XawChainLeft);
2920 XtSetArg (arg[2], XtNright, XawChainLeft);
2921 XtSetArg (arg[3], XtNhorizDistance, 10);
2922 XtSetArg (arg[4], XtNlabel, "Pop");
2923 XtSetArg (arg[5], XtNtranslations,
2924 XtParseTranslationTable (pop_face_trans));
2925 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2926 FaceWidget, arg, 6);
2927 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2929 XtSetArg (arg[0], XtNfromHoriz, w);
2930 XtSetArg (arg[1], XtNleft, XawChainLeft);
2931 XtSetArg (arg[2], XtNright, XawChainRight);
2932 XtSetArg (arg[3], XtNlabel, "");
2933 XtSetArg (arg[4], XtNborderWidth, 0);
2934 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2935 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2936 FaceWidget, arg, 6);
2938 XtSetArg (arg[0], XtNborderWidth, 0);
2939 XtSetArg (arg[1], XtNleft, XawChainLeft);
2940 XtSetArg (arg[2], XtNright, XawChainLeft);
2941 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2943 MPlist *plist[11], *pl;
2946 for (i = 0; i < 11; i++) plist[i] = NULL;
2948 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2949 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2951 MSymbol sym = msymbol_exist (langname);
2955 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2957 char *name = msymbol_name (fullname);
2960 if (c >= 'A' && c <= 'Z')
2962 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2966 pl = plist[idx] = mplist ();
2967 for (; mplist_next (pl); pl = mplist_next (pl))
2968 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2970 mplist_push (pl, sym, fullname);
2975 for (i = 0; i < 11; i++)
2978 char *name = alloca (9);
2980 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2983 for (j = 0, pl = plist[i]; mplist_next (pl);
2984 j++, pl = mplist_next (pl))
2985 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2986 msymbol_name (mplist_key (pl)),
2987 LangProc, mplist_key (pl), -1);
2988 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2989 menus, j, "Push language property");
2991 for (i = 0; i < 11; i++)
2993 m17n_object_unref (plist[i]);
2995 XtSetArg (arg[0], XtNfromHoriz, w);
2996 XtSetArg (arg[1], XtNleft, XawChainLeft);
2997 XtSetArg (arg[2], XtNright, XawChainLeft);
2998 XtSetArg (arg[3], XtNhorizDistance, 10);
2999 XtSetArg (arg[4], XtNlabel, "Pop");
3000 XtSetArg (arg[5], XtNtranslations,
3001 XtParseTranslationTable (pop_lang_trans));
3002 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3003 LangWidget, arg, 6);
3004 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3006 XtSetArg (arg[0], XtNfromHoriz, w);
3007 XtSetArg (arg[1], XtNleft, XawChainLeft);
3008 XtSetArg (arg[2], XtNright, XawChainRight);
3009 XtSetArg (arg[3], XtNlabel, "");
3010 XtSetArg (arg[4], XtNborderWidth, 0);
3011 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3012 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3013 LangWidget, arg, 6);
3016 XtSetArg (arg[0], XtNheight, win_height);
3017 XtSetArg (arg[1], XtNwidth, 10);
3018 XtSetArg (arg[2], XtNleft, XawChainLeft);
3019 XtSetArg (arg[3], XtNright, XawChainLeft);
3020 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3022 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3023 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3025 XtSetArg (arg[0], XtNheight, win_height);
3026 XtSetArg (arg[1], XtNwidth, win_width);
3027 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3028 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3029 XtSetArg (arg[4], XtNleft, XawChainLeft);
3030 XtSetArg (arg[5], XtNright, XawChainRight);
3031 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3034 XtSetArg (arg[0], XtNborderWidth, 0);
3035 XtSetArg (arg[1], XtNleft, XawChainLeft);
3036 XtSetArg (arg[2], XtNright, XawChainRight);
3037 XtSetArg (arg[3], XtNresizable, True);
3038 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3039 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3040 TailWidget, arg, 5);
3042 memset (&control, 0, sizeof control);
3043 control.two_dimensional = 1;
3044 control.enable_bidi = 1;
3045 control.anti_alias = 1;
3046 control.min_line_ascent = font_ascent;
3047 control.min_line_descent = font_descent;
3048 control.max_line_width = win_width;
3049 control.with_cursor = 1;
3050 control.cursor_width = 2;
3051 control.partial_update = 1;
3052 control.ignore_formatting_char = 1;
3054 memset (&input_status_control, 0, sizeof input_status_control);
3055 input_status_control.enable_bidi = 1;
3057 XtAppAddActions (context, actions, XtNumber (actions));
3058 XtRealizeWidget (ShellWidget);
3060 win = XtWindow (TextWidget);
3062 XtAppMainLoop (context);
3064 if (current_input_context)
3065 minput_destroy_ic (current_input_context);
3066 for (i = 0; i < num_input_methods; i++)
3067 if (input_method_table[i].im)
3068 minput_close_im (input_method_table[i].im);
3069 m17n_object_unref (frame);
3070 m17n_object_unref (mt);
3071 m17n_object_unref (face_xxx_large);
3072 m17n_object_unref (face_box);
3073 m17n_object_unref (face_courier);
3074 m17n_object_unref (face_helvetica);
3075 m17n_object_unref (face_times);
3076 m17n_object_unref (face_dv_ttyogesh);
3077 m17n_object_unref (face_freesans);
3078 m17n_object_unref (face_freeserif);
3079 m17n_object_unref (face_freemono);
3080 m17n_object_unref (face_default_fontset);
3081 m17n_object_unref (face_no_ctl_fontset);
3082 m17n_object_unref (face_input_status);
3083 m17n_object_unref (face_default);
3084 m17n_object_unref (default_face_list);
3085 m17n_object_unref (selection);
3087 XFreeGC (display, mono_gc);
3088 XFreeGC (display, mono_gc_inv);
3089 XFreeGC (display, gc_inv);
3090 XtUninstallTranslations (form);
3091 XtUninstallTranslations (TextWidget);
3092 XtDestroyWidget (ShellWidget);
3093 XtDestroyApplicationContext (context);
3097 free (fontset_name);
3099 free (input_method_table);
3100 free (InputMethodMenus);
3105 #else /* not HAVE_X11_XAW_COMMAND_H */
3108 main (int argc, char **argv)
3111 "Building of this program failed (lack of some header files)\n");
3115 #endif /* not HAVE_X11_XAW_COMMAND_H */
3117 #endif /* not FOR_DOXYGEN */