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 medit edit multilingual text
26 @section medit-synopsis SYNOPSIS
28 medit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section medit-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 medit directly uses the GUI API, the API is mainly for
52 toolkit libraries or to implement XOM (X Outout Method), not for
53 direct use from application programs.
56 @japage medit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section medit-synopsis SYNOPSIS
60 medit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section medit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£medit ¤Ïľ
83 ÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é¥ê¤ä
84 XOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é ¥à
85 ¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
99 #include <X11/keysym.h>
100 #include <X11/Xatom.h>
101 #include <X11/Intrinsic.h>
102 #include <X11/StringDefs.h>
103 #include <X11/Shell.h>
104 #include <X11/Xaw/Command.h>
105 #include <X11/Xaw/Box.h>
106 #include <X11/Xaw/Form.h>
107 #include <X11/Xaw/Dialog.h>
108 #include <X11/Xaw/Scrollbar.h>
109 #include <X11/Xaw/Toggle.h>
110 #include <X11/Xaw/SimpleMenu.h>
111 #include <X11/Xaw/SmeBSB.h>
112 #include <X11/Xaw/SmeLine.h>
113 #include <X11/Xaw/MenuButton.h>
115 #include <m17n-gui.h>
116 #include <m17n-misc.h>
119 #define VERSION "1.0.1"
121 /* Global variables. */
126 /* For the X Window System. */
129 /* GCs for normal drawing, filling by background color, normal drawing
130 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
132 GC gc, gc_inv, mono_gc, mono_gc_inv;
134 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
135 XtAppContext context;
136 int default_font_size;
140 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
141 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
142 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
143 +- Body -- Sbar, Text
147 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
148 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
149 Widget SbarWidget, TextWidget;
150 Widget FileShellWidget, FileDialogWidget;
151 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
152 Widget CurIMLang, CurIMStatus;
154 int win_width, win_height; /* Size of TextWidget. */
157 Pixmap input_status_pixmap;
158 int input_status_width, input_status_height;
160 /* Bitmap for "check" glyph. */
161 #define check_width 9
162 #define check_height 8
163 static unsigned char check_bits[] = {
164 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
165 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
168 /* For the m17n library. */
171 int nchars; /* == mtext_len (mt) */
172 MDrawControl control, input_status_control;
173 MTextProperty *selection;
176 MFace *face_xxx_large;
178 MFace *face_courier, *face_helvetica, *face_times;
179 MFace *face_dv_ttyogesh, *face_freesans, *face_freemono;
180 MFace *face_default_fontset, *face_no_ctl_fontset;
181 MFace *face_input_status;
183 int logical_move = 1; /* If 0, move cursor visually. */
187 MSymbol language, name;
191 InputMethodInfo *input_method_table;
193 int num_input_methods;
194 int current_input_method = -1; /* i.e. none */
195 int auto_input_method = 0;
196 MInputContext *current_input_context;
203 { {"Menu Size", NULL},
204 {"xx-small", &mface_xx_small},
205 {"x-small", &mface_x_small},
206 {"small", &mface_small},
207 {"normalsize", &mface_normalsize},
208 {"large", &mface_large},
209 {"x-large", &mface_x_large},
210 {"xx-large", &mface_xx_large},
211 {"xxx-large", &face_xxx_large},
213 {"Menu Family", NULL},
214 {"courier", &face_courier},
215 {"helvetica", &face_helvetica},
216 {"times", &face_times},
217 {"dv-ttyogesh", &face_dv_ttyogesh},
218 {"freesans", &face_freesans},
219 {"freemono", &face_freemono},
221 {"Menu Style", NULL},
222 {"medium", &mface_medium},
223 {"bold", &mface_bold},
224 {"italic", &mface_italic},
226 {"Menu Color", NULL},
227 {"black", &mface_black},
228 {"white", &mface_white},
230 {"green", &mface_green},
231 {"blue", &mface_blue},
232 {"cyan", &mface_cyan},
233 {"yello", &mface_yellow},
234 {"magenta", &mface_magenta},
237 {"normal", &mface_normal_video},
238 {"reverse", &mface_reverse_video},
239 {"underline", &mface_underline},
241 {"No CTL", &face_no_ctl_fontset} };
244 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
246 /* Information about a physical line metric. */
249 int from; /* BOL position of the line. */
250 int to; /* BOL position of the next line. */
251 int y0, y1; /* Top and bottom Y position of the line. */
252 int ascent; /* Height of the top Y position. */
255 struct LineInfo top; /* Topmost line. */
256 struct LineInfo cur; /* Line containing cursor. */
257 struct LineInfo sel_start; /* Line containing selection start. */
258 struct LineInfo sel_end; /* Line containing selection end. */
260 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
262 /* X position to keep on vertical (up and down) cursor motion. */
263 int target_x_position;
265 /* Interface macros for m17n-lib drawing routines. */
267 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
268 coordinate ($X, $Y) */
269 #define DRAW_TEXT(x, y, from, to) \
270 mdraw_text_with_control \
271 (frame, (MDrawWindow) win, \
272 control.orientation_reversed ? x + win_width : x, y, \
273 mt, from, to, &control)
275 /* Store the extents of a text in the range $FROM to $TO in the
276 structure $RECT (type MDrawMetric). */
277 #define TEXT_EXTENTS(from, to, rect) \
278 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
280 /* Store the glyph information of a character at the position $POS in
281 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
282 $FROM is written at the coordinate (0, 0). */
283 #define GLYPH_INFO(from, pos, info) \
284 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
286 /* Set $X and $Y to the coordinate of character at position $POS
287 assuming that the text from $FROM is written at the coordinate (0,
289 #define COORDINATES_POSITION(from, pos, x, y) \
290 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
292 /* Interface macros for X library. */
293 #define COPY_AREA(y0, y1, to) \
294 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
296 #define CLEAR_AREA(x, y, w, h) \
297 XClearArea (display, win, (x), (y), (w), (h), False)
299 #define SELECTEDP() \
300 mtext_property_mtext (selection)
302 /* Format MSG by FMT and print the result to the stderr, and exit. */
303 #define FATAL_ERROR(fmt, arg) \
305 fprintf (stderr, fmt, arg); \
310 /* If POS is greater than zero, move POS back to the beginning of line
311 (BOL) position. If FORWARD is nonzero, move POS forward instead.
312 Return the new position. */
314 bol (int pos, int forward)
316 int limit = forward ? nchars : 0;
318 pos = mtext_character (mt, pos, limit, '\n');
319 return (pos < 0 ? limit : pos + 1);
322 /* Update the structure #TOP (struct LineInfo) to make $POS the first
323 character position of the screen. */
327 int from = bol (pos, 0);
330 GLYPH_INFO (from, pos, info);
331 top.from = info.line_from;
332 top.to = info.line_to;
334 top.y1 = info.this.height;
335 top.ascent = - info.this.y;
339 /* Update the scroll bar so that the text of the range $FROM to $TO
340 are shown on the window. */
342 update_scroll_bar (int from, int to)
344 float top = (float) from / nchars;
345 float shown = (float) (to - from) / nchars;
346 XtArgVal *l_top = (XtArgVal *) ⊤
347 XtArgVal *l_shown = (XtArgVal *) &shown;
349 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
350 XtSetArg (arg[1], XtNshown, *l_shown);
351 XtSetValues (SbarWidget, arg, 2);
355 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
356 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
357 is nonzero, update the scoll bar. */
359 redraw (int y0, int y1, int clear, int scroll_bar)
364 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
365 struct LineInfo *line;
367 if (clear || control.anti_alias)
368 CLEAR_AREA (0, y0, win_width, y1 - y0);
370 /* Find a line closest to y0. It is a cursor line if the cursor is
371 Y0, otherwise the top line. */
376 /* If there exists a selected region, check it too. */
377 if (sel_y0 > line->y0 && y0 >= sel_y0)
382 info.this.height = line->y1 - y;
383 info.this.y = - line->ascent;
384 info.line_to = line->to;
385 while (from < nchars && y + info.this.height <= y0)
387 y += info.this.height;
389 GLYPH_INFO (from, from, info);
391 y0 = y - info.this.y;
393 while (to < nchars && y < y1)
395 GLYPH_INFO (to, to, info);
396 y += info.this.height;
402 DRAW_TEXT (0, y0, from, to);
407 GLYPH_INFO (to, to, info);
408 if (y + info.this.height >= win_height)
411 y += info.this.height;
413 update_scroll_bar (top.from, to);
418 /* Set the current input method spot to the correct position. */
420 set_input_method_spot ()
422 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
423 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
425 int n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
426 int size = 0, ratio = 0, i;
428 for (i = n - 1; i >= 0; i--)
431 size = (int) mface_get_prop (faces[i], Msize);
433 ratio = (int) mface_get_prop (faces[i], Mratio);
436 size = default_font_size;
438 size = size * ratio / 100;
439 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
440 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
445 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
448 redraw_cursor (int clear)
450 if (control.cursor_bidi)
452 /* We must update the whole line of the cursor. */
453 int beg = bol (cur.from, 0);
454 int end = bol (cur.to - 1, 1);
456 int y0 = cur.y0, y1 = cur.y1;
460 TEXT_EXTENTS (beg, cur.from, rect);
465 TEXT_EXTENTS (cur.to, end, rect);
468 redraw (y0, y1, clear, 0);
476 if (control.orientation_reversed)
477 x += win_width - cursor.this.width;
478 CLEAR_AREA (x, cur.y0, cursor.this.width, cursor.this.height);
480 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
485 /* Update the information about the location of cursor to the position
486 $POS. If $FULL is nonzero, update the information fully only from
487 the information about the top line. Otherwise, truct the current
488 information in the structure $CUR. */
490 update_cursor (int pos, int full)
496 /* CUR is inaccurate. We can trust only TOP. */
497 GLYPH_INFO (top.from, pos, cursor);
498 cur.y0 = top.ascent + cursor.y + cursor.this.y;
500 else if (pos < cur.from)
502 int from = bol (pos, 0);
504 TEXT_EXTENTS (from, cur.from, rect);
505 GLYPH_INFO (from, pos, cursor);
506 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y);
508 else if (pos < cur.to)
510 GLYPH_INFO (cur.from, pos, cursor);
514 GLYPH_INFO (cur.from, pos, cursor);
515 cur.y0 += cur.ascent + cursor.y + cursor.this.y;
518 cur.from = cursor.line_from;
519 cur.to = cursor.line_to;
520 cur.y1 = cur.y0 + cursor.this.height;
521 cur.ascent = - cursor.this.y;
525 /* Update the information about the selected region. */
535 from = mtext_property_start (selection);
536 to = mtext_property_end (selection);
540 int pos = bol (from, 0);
542 TEXT_EXTENTS (pos, top.from, rect);
543 sel_start.y0 = top.y0 - rect.height;
544 sel_start.ascent = - rect.y;
545 GLYPH_INFO (pos, from, info);
546 if (pos < info.line_from)
547 sel_start.y0 += - rect.y + info.y + info.this.y;
551 GLYPH_INFO (top.from, from, info);
552 sel_start.y0 = top.ascent + info.y + info.this.y;
554 sel_start.ascent = -info.this.y;
555 sel_start.y1 = sel_start.y0 + info.this.height;
556 sel_start.from = info.line_from;
557 sel_start.to = info.line_to;
559 if (to <= sel_start.to)
562 if (to >= sel_end.to)
564 GLYPH_INFO (sel_start.from, to, info);
565 sel_end.y1 = sel_end.y0 + info.y + info.this.height;
566 sel_end.to = info.line_to;
571 GLYPH_INFO (sel_start.from, to, info);
572 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
573 sel_end.y1 = sel_end.y0 + info.this.height;
574 sel_end.ascent = - info.this.y;
575 sel_end.from = info.line_from;
576 sel_end.to = info.line_to;
581 /* Select the text in the region from $FROM to $TO. */
583 select_region (int from, int to)
588 pos = from, from = to, to = pos;
589 mtext_push_property (mt, from, to, selection);
594 /* Setup the window to display the character of $POS at the top left
600 /* Top and bottom Y positions to redraw. */
603 if (pos + 1000 < top.from)
604 y0 = 0, y1 = win_height;
605 else if (pos < top.from)
608 TEXT_EXTENTS (pos, top.from, rect);
609 if (rect.height >= win_height * 0.9)
614 COPY_AREA (0, win_height - y1, y1);
617 else if (pos < top.to)
619 /* No need of redrawing. */
622 else if (pos < top.from + 1000)
624 TEXT_EXTENTS (top.from, pos, rect);
625 if (rect.height >= win_height * 0.9)
629 y0 = win_height - rect.height;
630 COPY_AREA (rect.height, win_height, 0);
635 y0 = 0, y1 = win_height;
641 update_cursor (pos, 1);
643 update_cursor (cursor.from, 1);
645 redraw (y0, y1, 1, 1);
649 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
652 /* Select an input method accoding to $IDX. If $IDX is negative, turn
653 off the current input method, otherwide turn on the input method
654 input_method_table[$IDX]. */
656 select_input_method (idx)
658 if (idx == current_input_method)
660 if (current_input_context)
662 minput_destroy_ic (current_input_context);
663 current_input_context = NULL;
664 current_input_method = -1;
668 InputMethodInfo *im = input_method_table + idx;
670 if (im->language == Mnil)
672 MInputXIMArgIC arg_xic;
673 Window win = XtWindow (TextWidget);
675 arg_xic.input_style = 0;
676 arg_xic.client_win = arg_xic.focus_win = win;
677 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
678 current_input_context = minput_create_ic (im->im, &arg_xic);
682 MInputGUIArgIC arg_ic;
684 arg_ic.frame = frame;
685 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
686 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
687 current_input_context = minput_create_ic (im->im, &arg_ic);
690 if (current_input_context)
692 set_input_method_spot ();
693 current_input_method = idx;
696 if (current_input_method >= 0)
699 XtSetArg (arg[0], XtNlabel, &label);
700 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
701 XtSetArg (arg[0], XtNlabel, label);
704 XtSetArg (arg[0], XtNlabel, "");
705 XtSetValues (CurIMLang, arg, 1);
708 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
711 /* Display cursor according to the current information of #CUR.
712 $CLIENT_DATA is ignore. Most callback functions add this function
713 as a background processing procedure the current application (by
714 XtAppAddWorkProc) via the function hide_cursor. */
716 show_cursor (XtPointer client_data)
718 MFaceHLineProp *hline;
724 update_cursor (cursor.from, 1);
726 while (cur.y1 > win_height)
729 update_cursor (cursor.from, 1);
732 control.cursor_pos = cursor.from;
735 control.with_cursor = 1;
738 if (current_input_context)
739 set_input_method_spot ();
742 int pos = (SELECTEDP () ? mtext_property_start (selection)
743 : cursor.from > 0 ? cursor.from - 1
745 MFace *face = mface ();
746 MTextProperty *props[256];
747 int n = mtext_get_properties (mt, pos, Mface, props, 256);
749 char buf[256], *p = buf;
755 int size = (int) mfont_get_prop (cursor.font, Msize);
756 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
757 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
758 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
759 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
761 sprintf (p, "%dpt", size / 10), p += strlen (p);
763 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
765 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
767 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
769 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
773 mface_merge (face, face_default);
774 for (i = 0; i < n; i++)
775 if (props[i] != selection)
776 mface_merge (face, (MFace *) mtext_property_value (props[i]));
777 sym = (MSymbol) mface_get_prop (face, Mforeground);
779 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
780 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
781 strcat (p, ",rev"), p += strlen (p);
782 hline = mface_get_prop (face, Mhline);
783 if (hline && hline->width > 0)
784 strcat (p, ",ul"), p += strlen (p);
785 box = mface_get_prop (face, Mbox);
786 if (box && box->width > 0)
787 strcat (p, ",box"), p += strlen (p);
788 m17n_object_unref (face);
790 XtSetArg (arg[0], XtNborderWidth, 1);
791 XtSetArg (arg[1], XtNlabel, buf);
792 XtSetValues (CurFaceWidget, arg, 2);
795 if (control.cursor_pos < nchars)
799 if (control.cursor_pos > 0
800 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
801 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
803 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
807 XtSetArg (arg[0], XtNborderWidth, 0);
808 XtSetArg (arg[1], XtNlabel, "");
812 XtSetArg (arg[0], XtNborderWidth, 1);
813 XtSetArg (arg[1], XtNlabel,
814 msymbol_name (msymbol_get (sym, Mlanguage)));
815 XtSetValues (CurLangWidget, arg, 2);
817 XtSetValues (CurLangWidget, arg, 2);
819 if (auto_input_method)
822 select_input_method (-1);
827 for (i = 0; i < num_input_methods; i++)
828 if (input_method_table[i].language == sym)
830 if (i < num_input_methods
831 && input_method_table[i].available >= 0)
833 if (! input_method_table[i].im)
835 input_method_table[i].im =
836 minput_open_im (input_method_table[i].language,
837 input_method_table[i].name, NULL);
838 if (! input_method_table[i].im)
839 input_method_table[i].available = -1;
841 if (input_method_table[i].im)
842 select_input_method (i);
844 select_input_method (-1);
847 select_input_method (-1);
852 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
858 /* Hide the cursor. */
862 control.with_cursor = 0;
864 XtAppAddWorkProc (context, show_cursor, NULL);
868 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
869 $Y1 and $NEW_Y1 assuming that the text in the other area is not
872 update_region (int y0, int old_y1, int new_y1)
878 if (old_y1 < win_height)
880 COPY_AREA (old_y1, win_height, new_y1);
881 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
884 redraw (new_y1, win_height, 1, 0);
886 else if (new_y1 > old_y1)
888 if (new_y1 < win_height)
889 COPY_AREA (old_y1, win_height, new_y1);
891 if (new_y1 > win_height)
893 redraw (y0, new_y1, 1, 1);
897 /* Delete the next $N characters. If $N is negative delete the
898 precious (- $N) characters. */
908 from = cursor.from, to = from + n;
911 if (cursor.from == cur.from)
913 /* We are at the beginning of line. */
914 int pos = cursor.prev_from;
916 if (cursor.from == top.from)
918 /* We are at the beginning of screen. We must scroll
920 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
921 reseat (info.line_from);
923 update_cursor (pos, 1);
929 from = cursor.from - 1;
934 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
935 old_y1 = cur.y0 + rect.height;
937 /* Now delete a character. */
938 mtext_del (mt, from, to);
940 if (from >= top.from && from < top.to)
941 update_top (top.from);
942 update_cursor (from, 1);
944 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
945 new_y1 = cur.y0 + rect.height;
947 update_region (cur.y0, old_y1, new_y1);
951 /* Insert M-text $NEWTEXT at the current cursor position. */
953 insert_chars (MText *newtext)
955 int n = mtext_len (newtext);
957 int y0, old_y1, new_y1;
961 int n = (mtext_property_end (selection)
962 - mtext_property_start (selection));
963 mtext_detach_property (selection);
968 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
969 old_y1 = y0 + rect.height;
971 /* Now insert chars. */
972 mtext_ins (mt, cursor.from, newtext);
974 if (cur.from == top.from)
975 update_top (top.from);
976 update_cursor (cursor.from + n, 1);
978 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
979 new_y1 = cur.y0 + rect.height;
981 update_region (y0, old_y1, new_y1);
986 /* Convert the currently selected text to COMPOUND-TEXT. It is called
987 when someone requests the current value of the selection. */
989 covert_selection (Widget w, Atom *selection_atom,
990 Atom *target, Atom *return_type,
991 XtPointer *value, unsigned long *length, int *format)
993 unsigned char *buf = (unsigned char *) XtMalloc (4096);
994 MText *this_mt = mtext ();
995 int from = mtext_property_start (selection);
996 int to = mtext_property_end (selection);
998 mtext_copy (this_mt, 0, mt, from, to);
999 *length = mconv_encode_buffer (msymbol ("compound-text"),
1000 this_mt, buf, 4096);
1001 *return_type = XA_COMPOUND_TEXT;
1002 *value = (XtPointer) buf;
1004 m17n_object_unref (this_mt);
1009 /* Unselect the text. It is called when we loose the selection. */
1011 lose_selection (Widget w, Atom *selection_atom)
1015 mtext_detach_property (selection);
1016 redraw (sel_start.y0, sel_end.y1, 1, 0);
1021 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1022 XtPointer value, unsigned long *length, int *format)
1027 if (*type == XT_CONVERT_FAIL || ! value)
1029 if (*type == XA_STRING)
1031 else if (*type == XA_COMPOUND_TEXT)
1032 coding = msymbol ("compound-text");
1033 else if (*type == XA_UTF8_STRING)
1034 coding = msymbol ("utf-8");
1038 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1042 insert_chars (this_mt);
1043 m17n_object_unref (this_mt);
1052 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1054 XExposeEvent *expose = (XExposeEvent *) event;
1058 Dimension width_max, width;
1060 XtSetArg (arg[0], XtNwidth, &width);
1061 XtGetValues (XtParent (w), arg, 1);
1063 XtGetValues (HeadWidget, arg, 1);
1064 if (width_max < width)
1066 XtGetValues (FaceWidget, arg, 1);
1067 if (width_max < width)
1069 XtGetValues (LangWidget, arg, 1);
1070 if (width_max < width)
1072 XtSetArg (arg[0], XtNwidth, width_max);
1073 XtSetValues (HeadWidget, arg, 1);
1074 XtSetValues (FaceWidget, arg, 1);
1075 XtSetValues (LangWidget, arg, 1);
1076 XtSetValues (XtParent (w), arg, 1);
1077 XtSetValues (TailWidget, arg, 1);
1080 update_cursor (0, 1);
1081 redraw (0, win_height, 0, 1);
1086 redraw (expose->y, expose->y + expose->height, 0, 0);
1087 if (current_input_context
1088 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1089 set_input_method_spot ();
1094 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1096 XConfigureEvent *configure = (XConfigureEvent *) event;
1099 control.max_line_width = win_width = configure->width;
1100 win_height = configure->height;
1101 mdraw_clear_cache (mt);
1103 update_cursor (0, 1);
1104 redraw (0, win_height, 1, 1);
1105 if (current_input_context)
1106 set_input_method_spot ();
1110 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1113 int x = event->xbutton.x;
1114 int y = event->xbutton.y - top.ascent;
1116 if (control.orientation_reversed)
1118 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1121 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1122 mtext_detach_property (selection);
1123 redraw (sel_start.y0, sel_end.y1, 1, 0);
1126 update_cursor (pos, 0);
1131 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1136 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1137 covert_selection, lose_selection, NULL);
1138 update_cursor (mtext_property_start (selection), 0);
1143 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1147 /* We don't have a local selection. */
1148 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1153 int from = mtext_property_start (selection);
1154 int to = mtext_property_end (selection);
1157 int x = event->xbutton.x;
1158 int y = event->xbutton.y - top.ascent;
1160 if (control.orientation_reversed)
1162 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1164 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1165 mtext_detach_property (selection);
1167 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1168 update_cursor (pos, 0);
1169 insert_chars (this_mt);
1170 m17n_object_unref (this_mt);
1175 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1178 int x = event->xbutton.x;
1179 int y = event->xbutton.y;
1181 if (control.orientation_reversed)
1184 pos = top.from, y -= top.ascent;
1186 pos = cur.from, y -= cur.y0 + cur.ascent;
1187 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1189 if (pos == cursor.from)
1195 /* Selection range changed. */
1196 int from = mtext_property_start (selection);
1197 int to = mtext_property_end (selection);
1198 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1199 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1201 if (cursor.from == from)
1203 /* Starting position changed. */
1206 /* Enlarged. We can simply overdraw. */
1207 select_region (pos, to);
1208 redraw (sel_start.y0, start_y1, 0, 0);
1212 /* Shrunken. Previous selection face must be cleared. */
1213 select_region (pos, to);
1214 redraw (start_y0, sel_start.y1, 1, 0);
1218 /* Shrunken to zero. */
1219 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1220 mtext_detach_property (selection);
1221 redraw (start_y0, end_y1, 1, 0);
1225 /* Full update is necessary. */
1226 select_region (to, pos);
1227 redraw (start_y0, sel_end.y1, 1, 0);
1232 /* Ending position changed. */
1235 /* Full update is necessary. */
1236 select_region (pos, from);
1237 redraw (sel_start.y0, end_y1, 1, 0);
1239 else if (pos == from)
1241 /* Shrunken to zero. */
1242 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1243 mtext_detach_property (selection);
1244 redraw (start_y0, end_y1, 1, 0);
1248 /* Shrunken. Previous selection face must be cleared. */
1249 select_region (from, pos);
1250 redraw (sel_end.y0, end_y1, 1, 0);
1254 /* Enlarged. We can simply overdraw. */
1255 select_region (from, pos);
1256 redraw (end_y0, sel_end.y1, 0, 0);
1262 /* Newly selected. */
1263 select_region (pos, cursor.from);
1264 redraw (sel_start.y0, sel_end.y1, 0, 0);
1266 update_cursor (pos, 1);
1270 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1273 MDrawGlyphInfo info;
1275 int cursor_pos = cursor.from;
1277 if (((int) position) < 0)
1283 height = top.y1 - top.y0;
1286 pos = bol (from - 1, 0);
1287 GLYPH_INFO (pos, from - 1, info);
1288 if (height + info.this.height > win_height)
1290 height += info.this.height;
1291 from = info.line_from;
1293 if (cursor_pos >= top.to)
1295 cursor_pos = top.from;
1297 while (cursor_pos < nchars)
1299 GLYPH_INFO (pos, pos, info);
1300 if (height + info.this.height > win_height)
1302 height += info.this.height;
1308 else if (cur.to < nchars)
1310 /* Scroll up, but leave at least one line. */
1313 while (from < nchars)
1315 GLYPH_INFO (from, from, info);
1316 if (height + info.this.height > win_height
1317 || info.line_to >= nchars)
1319 height += info.this.height;
1320 from = info.line_to;
1323 from = info.line_from;
1324 if (cursor_pos < from)
1328 /* Scroll up to make the cursor line top. */
1332 update_cursor (cursor_pos, 1);
1336 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1338 float persent = *(float *) persent_ptr;
1339 int pos1, pos2 = nchars * persent;
1340 MDrawGlyphInfo info;
1343 pos1 = bol (pos2, 0);
1344 GLYPH_INFO (pos1, pos2, info);
1345 pos1 = info.line_from;
1347 update_cursor (pos1, 1);
1352 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1354 XKeyEvent *key_event = (XKeyEvent *) event;
1356 KeySym keysym = NoSymbol;
1358 /* If set to 1, do not update target_x_position. */
1359 int keep_target_x_position = 0;
1362 if (current_input_context
1363 && minput_filter (current_input_context, Mnil, event))
1365 if (event->type == KeyRelease)
1370 produced = mtext ();
1371 ret = minput_lookup (current_input_context, Mnil, event, produced);
1372 if (mtext_len (produced) > 0)
1373 insert_chars (produced);
1375 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1376 m17n_object_unref (produced);
1386 n = (mtext_property_end (selection)
1387 - mtext_property_start (selection));
1388 mtext_detach_property (selection);
1390 else if (cursor.from < nchars)
1392 /* Delete the following grapheme cluster. */
1393 n = cursor.to - cursor.from;
1406 /* Delete selected region. */
1407 n = (mtext_property_end (selection)
1408 - mtext_property_start (selection));
1409 mtext_detach_property (selection);
1411 else if (cursor.from > 0)
1413 /* Delete the preceding character. */
1424 mtext_detach_property (selection);
1425 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1429 if (cursor.prev_from >= 0)
1430 update_cursor (cursor.prev_from, 0);
1434 if (cursor.left_from >= 0)
1435 update_cursor (cursor.left_from, 0);
1442 mtext_detach_property (selection);
1443 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1447 if (cursor.next_to >= 0)
1448 update_cursor (cursor.to, 0);
1452 if (cursor.right_from >= 0)
1453 update_cursor (cursor.right_from, 0);
1460 mtext_detach_property (selection);
1461 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1463 if (cur.to <= nchars)
1465 MDrawGlyphInfo info;
1468 GLYPH_INFO (cur.from, cur.to, info);
1469 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1470 target_x_position, info.y);
1471 keep_target_x_position = 1;
1472 update_cursor (pos, 0);
1479 mtext_detach_property (selection);
1480 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1486 int pos = bol (cur.from - 1, 0);
1488 TEXT_EXTENTS (pos, cur.from - 1, rect);
1489 y = rect.height + rect.y - 1;
1490 pos = COORDINATES_POSITION (pos, nchars,
1491 target_x_position, y);
1492 keep_target_x_position = 1;
1493 update_cursor (pos, 0);
1500 mtext_detach_property (selection);
1501 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1503 if (top.from < nchars)
1504 ScrollProc (w, NULL, (XtPointer) 1);
1510 mtext_detach_property (selection);
1511 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1514 ScrollProc (w, NULL, (XtPointer) -1);
1520 if (buf[0] == 17) /* C-q */
1522 XtAppSetExitFlag (context);
1525 else if (buf[0] == 12) /* C-l */
1527 redraw (0, win_height, 1, 1);
1532 MText *temp = mtext ();
1534 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1535 if (current_input_context)
1536 mtext_put_prop (temp, 0, 1, Mlanguage,
1537 current_input_context->im->language);
1538 insert_chars (temp);
1539 m17n_object_unref (temp);
1544 if (! keep_target_x_position)
1545 target_x_position = cursor.x;
1549 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1551 char *name = (char *) client_data;
1553 int from = -1, to = 0;
1558 filename = strdup (name);
1561 fp = fopen (filename, "w");
1564 fprintf (stderr, "Open for write fail: %s", filename);
1570 from = mtext_property_start (selection);
1571 to = mtext_property_end (selection);
1572 mtext_detach_property (selection);
1575 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1578 select_region (from, to);
1582 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1588 mtext_detach_property (selection);
1589 serialized = (int) client_data;
1591 new = mtext_deserialize (mt);
1594 MPlist *plist = mplist ();
1596 mplist_push (plist, Mt, Mface);
1597 mplist_push (plist, Mt, Mlanguage);
1598 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1599 m17n_object_unref (plist);
1603 m17n_object_unref (mt);
1605 serialized = ! serialized;
1606 nchars = mtext_len (mt);
1609 update_cursor (0, 1);
1610 redraw (0, win_height, 1, 1);
1614 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1616 XtAppSetExitFlag (context);
1622 FILE *fp = fopen (filename, "r");
1625 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1626 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1629 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1634 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1636 int data = (int) client_data;
1641 control.enable_bidi = 0;
1642 control.orientation_reversed = 0;
1646 control.enable_bidi = 1;
1647 control.orientation_reversed = data == 2;
1649 for (i = 0; i < 3; i++)
1652 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1654 XtSetArg (arg[0], XtNleftBitmap, None);
1655 XtSetValues (BidiMenus[i], arg, 1);
1658 update_cursor (cursor.from, 1);
1659 redraw (0, win_height, 1, 0);
1662 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1665 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1667 int data = (int) client_data;
1671 control.max_line_width = 0;
1674 control.max_line_width = win_width;
1675 control.line_break = (data == 1 ? NULL : line_break);
1677 for (i = 0; i < 3; i++)
1680 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1682 XtSetArg (arg[0], XtNleftBitmap, None);
1683 XtSetValues (LineBreakMenus[i], arg, 1);
1686 update_cursor (cursor.from, 1);
1687 redraw (0, win_height, 1, 0);
1691 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1693 int data = (int) client_data;
1707 control.cursor_bidi = 0, control.cursor_width = -1;
1711 control.cursor_bidi = 0, control.cursor_width = 2;
1715 control.cursor_bidi = 1;
1720 for (i = from; i < to; i++)
1723 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1725 XtSetArg (arg[0], XtNleftBitmap, None);
1726 XtSetValues (CursorMenus[i], arg, 1);
1729 redraw (0, win_height, 1, 0);
1733 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1735 int idx = (int) client_data;
1737 if (idx == -2 ? current_input_method < 0
1738 : idx == -1 ? auto_input_method
1739 : idx == current_input_method)
1742 XtSetArg (arg[0], XtNleftBitmap, None);
1743 if (auto_input_method)
1745 XtSetValues (InputMethodMenus[1], arg, 1);
1746 auto_input_method = 0;
1748 else if (current_input_method < 0)
1749 XtSetValues (InputMethodMenus[0], arg, 1);
1751 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1755 auto_input_method = 1;
1758 else if (input_method_table[idx].available >= 0)
1760 if (! input_method_table[idx].im)
1762 input_method_table[idx].im =
1763 minput_open_im (input_method_table[idx].language,
1764 input_method_table[idx].name, NULL);
1765 if (! input_method_table[idx].im)
1766 input_method_table[idx].available = -1;
1768 if (input_method_table[idx].im)
1769 select_input_method (idx);
1771 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1772 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1775 MPlist *default_face_list;
1778 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1780 int idx = (int) client_data;
1790 MFace *face = mframe_get_prop (frame, Mface);
1792 for (plist = default_face_list; mplist_key (plist) != Mnil;
1793 plist = mplist_next (plist))
1794 mface_merge (face, mplist_value (plist));
1795 mplist_add (plist, Mt, *face_table[idx].face);
1796 mface_merge (face, *face_table[idx].face);
1798 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1800 MFace *face = mframe_get_prop (frame, Mface);
1802 for (plist = default_face_list;
1803 mplist_key (mplist_next (plist)) != Mnil;
1804 plist = mplist_next (plist))
1805 mface_merge (face, mplist_value (plist));
1809 update_cursor (0, 1);
1810 redraw (0, win_height, 1, 1);
1815 XtAppAddWorkProc (context, show_cursor, NULL);
1816 from = mtext_property_start (selection);
1817 to = mtext_property_end (selection);
1818 old_y1 = sel_end.y1;
1820 mtext_detach_property (selection);
1823 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1824 MTEXTPROP_REAR_STICKY);
1825 mtext_push_property (mt, from, to, prop);
1826 m17n_object_unref (prop);
1829 mtext_pop_prop (mt, from, to, Mface);
1831 update_top (top.from);
1832 update_cursor (cursor.from, 1);
1833 select_region (from, to);
1834 update_region (sel_start.y0, old_y1, sel_end.y1);
1835 if (cur.y1 > win_height)
1837 while (cur.y1 > win_height)
1840 update_cursor (cursor.from, 1);
1846 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1848 MSymbol sym = (MSymbol) client_data;
1855 XtAppAddWorkProc (context, show_cursor, NULL);
1856 from = mtext_property_start (selection);
1857 to = mtext_property_end (selection);
1858 old_y1 = sel_end.y1;
1860 mtext_detach_property (selection);
1862 mtext_put_prop (mt, from, to, Mlanguage, sym);
1864 mtext_pop_prop (mt, from, to, Mlanguage);
1867 update_top (top.from);
1868 update_cursor (cursor.from, 1);
1869 select_region (from, to);
1870 update_region (sel_start.y0, old_y1, sel_end.y1);
1871 if (cur.y1 > win_height)
1873 while (cur.y1 > win_height)
1876 update_cursor (cursor.from, 1);
1882 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1884 int narrowed = (int) client_data;
1887 MConverter *converter;
1893 from = mtext_property_start (selection);
1894 to = mtext_property_end (selection);
1903 mdump = popen ("mdump -q -p a4", "w");
1905 mdump = popen ("mdump -q", "w");
1908 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1909 mconv_encode_range (converter, mt, from, to);
1910 mconv_free_converter (converter);
1915 input_status (MInputContext *ic, MSymbol command)
1917 XFillRectangle (display, input_status_pixmap, gc_inv,
1918 0, 0, input_status_width, input_status_height);
1919 if (command == Minput_status_draw)
1923 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1924 Mface, face_input_status);
1925 if (ic->im->language != Mnil)
1926 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1927 Mlanguage, ic->im->language);
1928 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1929 &input_status_control, NULL, NULL, &rect);
1930 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1931 input_status_width - rect.width - 2, - rect.y,
1932 ic->status, 0, mtext_len (ic->status),
1933 &input_status_control);
1935 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1936 XtSetValues (CurIMStatus, arg, 1);
1940 compare_input_method (const void *elt1, const void *elt2)
1942 const InputMethodInfo *im1 = elt1;
1943 const InputMethodInfo *im2 = elt2;
1944 MSymbol lang1, lang2;
1946 if (im1->language == Mnil)
1948 if (im1->language == im2->language)
1949 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1950 if (im1->language == Mt)
1952 if (im2->language == Mt)
1954 lang1 = msymbol_get (im1->language, Mlanguage);
1955 lang2 = msymbol_get (im2->language, Mlanguage);
1956 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1960 setup_input_methods (int with_xim)
1962 MInputMethod *im = NULL;
1963 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1967 num_input_methods = mplist_length (plist);
1971 MInputXIMArgIM arg_xim;
1973 arg_xim.display = display;
1975 arg_xim.res_name = arg_xim.res_class = NULL;
1976 arg_xim.locale = NULL;
1977 arg_xim.modifier_list = NULL;
1978 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1980 num_input_methods++;
1982 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
1985 input_method_table[i].available = 1;
1986 input_method_table[i].language = Mnil;
1987 input_method_table[i].name = im->name;
1988 input_method_table[i].im = im;
1992 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1994 MDatabase *mdb = mplist_value (pl);
1995 MSymbol *tag = mdatabase_tag (mdb);
1999 input_method_table[i].language = tag[1];
2000 input_method_table[i].name = tag[2];
2005 m17n_object_unref (plist);
2006 num_input_methods = i;
2007 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2008 compare_input_method);
2009 current_input_context = NULL;
2011 mplist_put (minput_driver->callback_list, Minput_status_start,
2012 (void *) input_status);
2013 mplist_put (minput_driver->callback_list, Minput_status_draw,
2014 (void *) input_status);
2015 mplist_put (minput_driver->callback_list, Minput_status_done,
2016 (void *) input_status);
2021 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2025 if (num && *num > 0)
2029 for (i = 0; i < *num; i++)
2030 bytes += strlen (str[i]) + 1;
2031 msg = alloca (bytes);
2032 strcpy (msg, str[0]);
2033 for (i = 1; i < *num; i++)
2034 strcat (msg, " "), strcat (msg, str[i]);
2036 else if (cursor.from < nchars)
2038 int c = mtext_ref_char (mt, cursor.from);
2039 char *name = mchar_get_prop (c, Mname);
2043 msg = alloca (10 + strlen (name));
2044 sprintf (msg, "U+%04X %s", c, name);
2050 XtSetArg (arg[0], XtNlabel, msg);
2051 XtSetValues (MessageWidget, arg, 1);
2057 char *name1, *name2;
2058 XtCallbackProc proc;
2059 XtPointer client_data;
2064 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2066 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2068 MenuRec FileMenu[] =
2069 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2070 { 0, "Save", NULL, SaveProc, NULL, -1 },
2071 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2073 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2074 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2076 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2077 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2079 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2082 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2084 MenuRec *rec = (MenuRec *) client_data;
2087 XtSetArg (arg[0], XtNvalue, "");
2088 XtSetArg (arg[1], XtNlabel, rec->name1);
2089 XtSetValues (FileDialogWidget, arg, 2);
2090 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2091 XtSetArg (arg[0], XtNx, x + 20);
2092 XtSetArg (arg[1], XtNy, y + 10);
2093 XtSetValues (FileShellWidget, arg, 2);
2094 XtPopup (FileShellWidget, XtGrabExclusive);
2098 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2103 XtPopdown (FileShellWidget);
2104 if ((int) client_data == 1)
2106 XtSetArg (arg[0], XtNlabel, &label);
2107 XtGetValues (FileDialogWidget, arg, 1);
2108 if (strcmp (label, FileMenu[0].name1) == 0)
2112 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2113 fp = fopen (filename, "r");
2115 m17n_object_unref (mt);
2118 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2126 nchars = mtext_len (mt);
2128 update_cursor (0, 1);
2129 redraw (0, win_height, 1, 1);
2131 else if (strcmp (label, FileMenu[2].name1) == 0)
2132 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2134 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2137 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2138 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2139 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2140 (MENU).status = (STATUS))
2144 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2145 char *menu_name, MenuRec *menus, int num_menus, char *help)
2147 Widget button, menu;
2148 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2149 <LeaveWindow>: reset() MenuHelp()\n\
2150 <BtnDown>: reset() PopupMenu()\n\
2151 <BtnUp>: highlight()";
2157 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2158 for (i = 0; i < num_menus; i++)
2169 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2171 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2173 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2175 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2179 XtSetArg (arg[0], XtNsensitive, False);
2180 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2186 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2191 trans = alloca (strlen (fmt) + strlen (help));
2192 sprintf (trans, fmt, help);
2193 XtSetArg (arg[0], XtNmenuName, menu_name);
2194 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2195 XtSetArg (arg[2], XtNinternalWidth, 2);
2196 XtSetArg (arg[3], XtNhighlightThickness, 1);
2197 XtSetArg (arg[4], XtNleft, XawChainLeft);
2198 XtSetArg (arg[5], XtNright, XawChainLeft);
2201 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2202 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2207 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2208 int *len = alloca (sizeof (int) * num_menus);
2211 XFontSetExtents *fontset_extents;
2213 XtSetArg (arg[0], XtNfontSet, &font_set);
2214 XtGetValues (button, arg, 1);
2216 fontset_extents = XExtentsOfFontSet (font_set);
2217 height = fontset_extents->max_logical_extent.height;
2218 ascent = - fontset_extents->max_logical_extent.y;
2220 for (i = 0; i < num_menus; i++)
2223 len[i] = strlen (menus[i].name2);
2224 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2225 if (max_width < width[i])
2226 max_width = width[i];
2228 for (i = 0; i < num_menus; i++)
2231 Pixmap pixmap = XCreatePixmap (display,
2232 RootWindow (display, screen),
2233 max_width, height, 1);
2234 XFillRectangle (display, pixmap, mono_gc_inv,
2235 0, 0, max_width, height);
2236 XmbDrawString (display, pixmap, font_set, mono_gc,
2237 max_width - width[i], ascent,
2238 menus[i].name2, len[i]);
2239 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2240 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2241 XtSetValues (menus[i].w, arg, 2);
2249 XtActionsRec actions[] = {
2250 {"Expose", ExposeProc},
2251 {"Configure", ConfigureProc},
2253 {"ButtonPress", ButtonProc},
2254 {"ButtonRelease", ButtonReleaseProc},
2255 {"ButtonMotion", ButtonMoveProc},
2256 {"Button2Press", Button2Proc},
2257 {"MenuHelp", MenuHelpProc}
2261 /* Print the usage of this program (the name is PROG), and exit with
2265 help_exit (char *prog, int exit_code)
2273 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2274 printf ("Display FILE on a window and allow users to edit it.\n");
2275 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2276 printf ("The following OPTIONs are available.\n");
2277 printf (" %-13s %s", "--version", "print version number\n");
2278 printf (" %-13s %s", "-h, --help", "print this message\n");
2283 main (int argc, char **argv)
2285 Widget form, BodyWidget, w;
2286 char *fontset_name = NULL;
2287 int col = 80, row = 32;
2288 /* Translation table for TextWidget. */
2289 String trans = "<Expose>: Expose()\n\
2290 <Configure>: Configure()\n\
2293 <Btn1Down>: ButtonPress()\n\
2294 <Btn1Up>: ButtonRelease()\n\
2295 <Btn1Motion>: ButtonMotion()\n\
2296 <Btn2Down>: Button2Press()";
2297 /* Translation table for the top form widget. */
2298 String trans2 = "<Key>: Key()\n\
2300 String pop_face_trans
2301 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2302 <LeaveWindow>: MenuHelp() reset()\n\
2303 <Btn1Down>: set()\n\
2304 <Btn1Up>: notify() unset()";
2305 String pop_lang_trans
2306 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2307 <LeaveWindow>: MenuHelp() reset()\n\
2308 <Btn1Down>: set()\n\
2309 <Btn1Up>: notify() unset()";
2310 int font_width, font_ascent, font_descent;
2314 setlocale (LC_ALL, "");
2315 /* Create the top shell. */
2316 XtSetLanguageProc (NULL, NULL, NULL);
2317 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2318 NULL, sessionShellWidgetClass, NULL, 0);
2319 display = XtDisplay (ShellWidget);
2320 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2322 /* Parse the remaining command line arguments. */
2323 for (i = 1; i < argc; i++)
2325 if (! strcmp (argv[i], "--help")
2326 || ! strcmp (argv[i], "-h"))
2327 help_exit (argv[0], 0);
2328 else if (! strcmp (argv[i], "--version"))
2330 printf ("medit (m17n library) %s\n", VERSION);
2331 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2334 else if (! strcmp (argv[i], "--geometry"))
2337 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2338 help_exit (argv[0], 1);
2340 else if (! strcmp (argv[i], "--fontset"))
2343 fontset_name = strdup (argv[i]);
2345 else if (! strcmp (argv[i], "--with-xim"))
2349 else if (argv[i][0] != '-')
2351 filename = strdup (argv[i]);
2355 fprintf (stderr, "Unknown option: %s", argv[i]);
2356 help_exit (argv[0], 1);
2360 help_exit (argv[0], 1);
2362 mdatabase_dir = ".";
2363 /* Initialize the m17n library. */
2365 if (merror_code != MERROR_NONE)
2366 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2368 mt = read_file (filename);
2371 nchars = mtext_len (mt);
2374 MFace *face = mface ();
2376 mface_put_prop (face, Mforeground, msymbol ("blue"));
2377 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2378 mface_put_prop (face, Mvideomode, Mreverse);
2379 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2380 m17n_object_unref (face);
2383 /* This tells ExposeProc to initialize everything. */
2386 XA_TEXT = XInternAtom (display, "TEXT", False);
2387 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2388 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2390 MPlist *plist = mplist ();
2394 mplist_put (plist, msymbol ("widget"), ShellWidget);
2397 MFontset *fontset = mfontset (fontset_name);
2400 mface_put_prop (face, Mfontset, fontset);
2401 m17n_object_unref (fontset);
2402 mplist_add (plist, Mface, face);
2403 m17n_object_unref (face);
2405 frame = mframe (plist);
2406 m17n_object_unref (plist);
2407 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2408 default_face_list = mplist ();
2409 mplist_add (default_face_list, Mt, face_default);
2410 face_default_fontset = mface ();
2411 mface_put_prop (face_default_fontset, Mfontset,
2412 mface_get_prop (face_default, Mfontset));
2414 font = (MFont *) mframe_get_prop (frame, Mfont);
2415 default_font_size = (int) mfont_get_prop (font, Msize);
2418 font_width = (int) mframe_get_prop (frame, Mfont_width);
2419 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2420 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2421 win_width = font_width * col;
2422 win_height = (font_ascent + font_descent) * row;
2428 prop.color_top = prop.color_left = msymbol ("magenta");
2429 prop.color_bottom = prop.color_right = msymbol ("red");
2430 prop.inner_hmargin = prop.inner_vmargin = 1;
2431 prop.outer_hmargin = prop.outer_vmargin = 2;
2433 face_box = mface ();
2434 mface_put_prop (face_box, Mbox, &prop);
2437 face_courier = mface ();
2438 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2439 face_helvetica = mface ();
2440 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2441 face_times = mface ();
2442 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2443 face_dv_ttyogesh = mface ();
2444 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2445 face_freesans = mface ();
2446 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2447 face_freemono = mface ();
2448 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2450 face_xxx_large = mface ();
2451 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2453 MFont *latin_font = mframe_get_prop (frame, Mfont);
2454 MFont *dev_font = mfont ();
2455 MFont *thai_font = mfont ();
2456 MFont *tib_font = mfont ();
2458 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2459 MSymbol no_ctl = msymbol ("no-ctl");
2461 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2462 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2463 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2464 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2465 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2466 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2468 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2469 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2470 latin_font, Mnil, 0);
2471 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2472 dev_font, no_ctl, 0);
2473 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2474 thai_font, no_ctl, 0);
2475 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2476 tib_font, no_ctl, 0);
2477 face_no_ctl_fontset = mface ();
2478 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2479 m17n_object_unref (fontset);
2486 setup_input_methods (with_xim);
2488 gc = DefaultGC (display, screen);
2490 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2491 XtSetArg (arg[1], XtNdefaultDistance, 2);
2492 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2494 XtSetArg (arg[0], XtNborderWidth, 0);
2495 XtSetArg (arg[1], XtNdefaultDistance, 2);
2496 XtSetArg (arg[2], XtNtop, XawChainTop);
2497 XtSetArg (arg[3], XtNbottom, XawChainTop);
2498 XtSetArg (arg[4], XtNleft, XawChainLeft);
2499 XtSetArg (arg[5], XtNright, XawChainRight);
2500 XtSetArg (arg[6], XtNresizable, True);
2501 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2502 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2503 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2504 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2505 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2506 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2507 XtSetArg (arg[7], XtNfromVert, LangWidget);
2508 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2509 XtSetArg (arg[2], XtNtop, XawChainBottom);
2510 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2511 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2513 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2514 HeadWidget, NULL, 0);
2515 XtSetArg (arg[0], XtNvalue, "");
2516 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2517 FileShellWidget, arg, 1);
2518 XawDialogAddButton (FileDialogWidget, "OK",
2519 FileDialogProc, (XtPointer) 0);
2520 XawDialogAddButton (FileDialogWidget, "CANCEL",
2521 FileDialogProc, (XtPointer) 1);
2523 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2524 (char *) check_bits,
2525 check_width, check_height);
2527 unsigned long valuemask = GCForeground;
2530 values.foreground = 1;
2531 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2532 values.foreground = 0;
2533 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2540 if (num_menus < num_input_methods + 2)
2541 num_menus = num_input_methods + 2;
2542 if (num_menus < num_faces + 1)
2543 num_menus = num_faces + 1;
2544 menus = alloca (sizeof (MenuRec) * num_menus);
2546 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2547 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2548 "File I/O, Serialization, Image, Quit");
2550 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2551 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2552 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2553 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2554 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2555 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2556 w = create_menu_button (ShellWidget, HeadWidget, w,
2557 "Cursor", "Cursor Menu",
2558 menus, 6, "Cursor Movement Mode, Cursor Shape");
2559 CursorMenus[0] = menus[0].w;
2560 CursorMenus[1] = menus[1].w;
2561 CursorMenus[2] = menus[3].w;
2562 CursorMenus[3] = menus[4].w;
2563 CursorMenus[4] = menus[5].w;
2565 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2566 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2567 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2568 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2569 menus, 3, "BIDI Processing Mode");
2570 for (i = 0; i < 3; i++)
2571 BidiMenus[i] = menus[i].w;
2573 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2574 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2575 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2576 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2578 menus, 3, "How to break lines");
2579 for (i = 0; i < 3; i++)
2580 LineBreakMenus[i] = menus[i].w;
2582 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2583 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2584 for (i = 0; i < num_input_methods; i++)
2586 InputMethodInfo *im = input_method_table + i;
2587 char *name1, *name2;
2589 if (im->language != Mnil && im->language != Mt)
2591 MSymbol sym = msymbol_get (im->language, Mlanguage);
2593 name1 = msymbol_name (im->language);
2595 name1 = msymbol_name (sym);
2596 name2 = msymbol_name (im->name);
2599 name1 = msymbol_name (im->name), name2 = NULL;
2601 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2603 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2604 "Input Method Menu", menus, i + 2,
2605 "Select input method");
2608 unsigned long valuemask = GCForeground;
2611 XtSetArg (arg[0], XtNbackground, &values.foreground);
2612 XtGetValues (w, arg, 1);
2613 gc_inv = XCreateGC (display, RootWindow (display, screen),
2614 valuemask, &values);
2617 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2618 for (i = 0; i < num_input_methods + 2; i++)
2619 InputMethodMenus[i] = menus[i].w;
2621 input_status_width = font_width * 8;
2622 input_status_height = (font_ascent + font_descent) * 2.4;
2623 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2625 input_status_height,
2626 DefaultDepth (display, screen));
2631 prop.color_top = prop.color_bottom
2632 = prop.color_left = prop.color_right = Mnil;
2633 prop.inner_hmargin = prop.inner_vmargin = 1;
2634 prop.outer_hmargin = prop.outer_vmargin = 0;
2635 face_input_status = mface_copy (face_default);
2636 mface_put_prop (face_input_status, Mbox, &prop);
2639 XFillRectangle (display, input_status_pixmap, gc_inv,
2640 0, 0, input_status_width, input_status_height);
2641 XtSetArg (arg[0], XtNfromHoriz, w);
2642 XtSetArg (arg[1], XtNleft, XawRubber);
2643 XtSetArg (arg[2], XtNright, XawChainRight);
2644 XtSetArg (arg[3], XtNborderWidth, 0);
2645 XtSetArg (arg[4], XtNlabel, " ");
2646 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2647 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2648 HeadWidget, arg, 6);
2649 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2650 XtSetArg (arg[1], XtNleft, XawChainRight);
2651 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2652 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2653 HeadWidget, arg, 5);
2655 XtSetArg (arg[0], XtNborderWidth, 0);
2656 XtSetArg (arg[1], XtNleft, XawChainLeft);
2657 XtSetArg (arg[2], XtNright, XawChainLeft);
2658 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2659 for (i = 0; i < num_faces;)
2661 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2662 char *label = label_menu + 5; /* "Xxxx" */
2664 for (j = i; j < num_faces && face_table[j].face; j++)
2665 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2667 w = create_menu_button (ShellWidget, FaceWidget, w,
2669 menus, j - i, "Push face property");
2673 XtSetArg (arg[0], XtNfromHoriz, w);
2674 XtSetArg (arg[1], XtNleft, XawChainLeft);
2675 XtSetArg (arg[2], XtNright, XawChainLeft);
2676 XtSetArg (arg[3], XtNhorizDistance, 10);
2677 XtSetArg (arg[4], XtNlabel, "Pop");
2678 XtSetArg (arg[5], XtNtranslations,
2679 XtParseTranslationTable (pop_face_trans));
2680 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2681 FaceWidget, arg, 6);
2682 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2684 XtSetArg (arg[0], XtNfromHoriz, w);
2685 XtSetArg (arg[1], XtNleft, XawChainLeft);
2686 XtSetArg (arg[2], XtNright, XawChainRight);
2687 XtSetArg (arg[3], XtNlabel, "");
2688 XtSetArg (arg[4], XtNborderWidth, 0);
2689 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2690 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2691 FaceWidget, arg, 6);
2693 XtSetArg (arg[0], XtNborderWidth, 0);
2694 XtSetArg (arg[1], XtNleft, XawChainLeft);
2695 XtSetArg (arg[2], XtNright, XawChainLeft);
2696 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2698 MPlist *plist[11], *pl;
2701 for (i = 0; i < 11; i++) plist[i] = NULL;
2703 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2704 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2706 MSymbol sym = msymbol_exist (langname);
2710 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2712 char *name = msymbol_name (fullname);
2715 if (c >= 'A' && c <= 'Z')
2717 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2721 pl = plist[idx] = mplist ();
2722 for (; mplist_next (pl); pl = mplist_next (pl))
2723 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2725 mplist_push (pl, sym, fullname);
2730 for (i = 0; i < 11; i++)
2733 char *name = alloca (9);
2735 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2738 for (j = 0, pl = plist[i]; mplist_next (pl);
2739 j++, pl = mplist_next (pl))
2740 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2741 msymbol_name (mplist_key (pl)),
2742 LangProc, mplist_key (pl), -1);
2743 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2744 menus, j, "Push language property");
2746 for (i = 0; i < 11; i++)
2748 m17n_object_unref (plist[i]);
2750 XtSetArg (arg[0], XtNfromHoriz, w);
2751 XtSetArg (arg[1], XtNleft, XawChainLeft);
2752 XtSetArg (arg[2], XtNright, XawChainLeft);
2753 XtSetArg (arg[3], XtNhorizDistance, 10);
2754 XtSetArg (arg[4], XtNlabel, "Pop");
2755 XtSetArg (arg[5], XtNtranslations,
2756 XtParseTranslationTable (pop_lang_trans));
2757 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2758 LangWidget, arg, 6);
2759 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2761 XtSetArg (arg[0], XtNfromHoriz, w);
2762 XtSetArg (arg[1], XtNleft, XawChainLeft);
2763 XtSetArg (arg[2], XtNright, XawChainRight);
2764 XtSetArg (arg[3], XtNlabel, "");
2765 XtSetArg (arg[4], XtNborderWidth, 0);
2766 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2767 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2768 LangWidget, arg, 6);
2771 XtSetArg (arg[0], XtNheight, win_height);
2772 XtSetArg (arg[1], XtNwidth, 10);
2773 XtSetArg (arg[2], XtNleft, XawChainLeft);
2774 XtSetArg (arg[3], XtNright, XawChainLeft);
2775 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2777 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2778 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2780 XtSetArg (arg[0], XtNheight, win_height);
2781 XtSetArg (arg[1], XtNwidth, win_width);
2782 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2783 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2784 XtSetArg (arg[4], XtNleft, XawChainLeft);
2785 XtSetArg (arg[5], XtNright, XawChainRight);
2786 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2789 XtSetArg (arg[0], XtNborderWidth, 0);
2790 XtSetArg (arg[1], XtNleft, XawChainLeft);
2791 XtSetArg (arg[2], XtNright, XawChainRight);
2792 XtSetArg (arg[3], XtNresizable, True);
2793 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2794 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2795 TailWidget, arg, 5);
2797 memset (&control, 0, sizeof control);
2798 control.two_dimensional = 1;
2799 control.enable_bidi = 1;
2800 control.anti_alias = 1;
2801 control.min_line_ascent = font_ascent;
2802 control.min_line_descent = font_descent;
2803 control.max_line_width = win_width;
2804 control.with_cursor = 1;
2805 control.cursor_width = 2;
2806 control.partial_update = 1;
2807 control.ignore_formatting_char = 1;
2809 memset (&input_status_control, 0, sizeof input_status_control);
2810 input_status_control.enable_bidi = 1;
2812 XtAppAddActions (context, actions, XtNumber (actions));
2813 XtRealizeWidget (ShellWidget);
2815 win = XtWindow (TextWidget);
2817 XtAppMainLoop (context);
2819 if (current_input_context)
2820 minput_destroy_ic (current_input_context);
2821 for (i = 0; i < num_input_methods; i++)
2822 if (input_method_table[i].im)
2823 minput_close_im (input_method_table[i].im);
2824 m17n_object_unref (frame);
2825 m17n_object_unref (mt);
2826 m17n_object_unref (face_xxx_large);
2827 m17n_object_unref (face_box);
2828 m17n_object_unref (face_courier);
2829 m17n_object_unref (face_helvetica);
2830 m17n_object_unref (face_times);
2831 m17n_object_unref (face_dv_ttyogesh);
2832 m17n_object_unref (face_freesans);
2833 m17n_object_unref (face_freemono);
2834 m17n_object_unref (face_default_fontset);
2835 m17n_object_unref (face_no_ctl_fontset);
2836 m17n_object_unref (face_input_status);
2837 m17n_object_unref (face_default);
2838 m17n_object_unref (default_face_list);
2839 m17n_object_unref (selection);
2843 free (fontset_name);
2845 free (input_method_table);
2846 free (InputMethodMenus);
2848 XFreeGC (display, mono_gc);
2849 XFreeGC (display, mono_gc_inv);
2850 XFreeGC (display, gc_inv);
2851 XtUninstallTranslations (form);
2852 XtUninstallTranslations (TextWidget);
2853 XtDestroyWidget (ShellWidget);
2854 XtDestroyApplicationContext (context);
2858 #endif /* not FOR_DOXYGEN */