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_freeserif, *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 {"freeserif", &face_freeserif},
220 {"freemono", &face_freemono},
222 {"Menu Style", NULL},
223 {"medium", &mface_medium},
224 {"bold", &mface_bold},
225 {"italic", &mface_italic},
227 {"Menu Color", NULL},
228 {"black", &mface_black},
229 {"white", &mface_white},
231 {"green", &mface_green},
232 {"blue", &mface_blue},
233 {"cyan", &mface_cyan},
234 {"yello", &mface_yellow},
235 {"magenta", &mface_magenta},
238 {"normal", &mface_normal_video},
239 {"reverse", &mface_reverse_video},
240 {"underline", &mface_underline},
242 {"No CTL", &face_no_ctl_fontset} };
245 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
247 /* Information about a physical line metric. */
250 int from; /* BOL position of the line. */
251 int to; /* BOL position of the next line. */
252 int y0, y1; /* Top and bottom Y position of the line. */
253 int ascent; /* Height of the top Y position. */
256 struct LineInfo top; /* Topmost line. */
257 struct LineInfo cur; /* Line containing cursor. */
258 struct LineInfo sel_start; /* Line containing selection start. */
259 struct LineInfo sel_end; /* Line containing selection end. */
261 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
263 /* X position to keep on vertical (up and down) cursor motion. */
264 int target_x_position;
266 /* Interface macros for m17n-lib drawing routines. */
268 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
269 coordinate ($X, $Y) */
270 #define DRAW_TEXT(x, y, from, to) \
271 mdraw_text_with_control \
272 (frame, (MDrawWindow) win, \
273 control.orientation_reversed ? x + win_width : x, y, \
274 mt, from, to, &control)
276 /* Store the extents of a text in the range $FROM to $TO in the
277 structure $RECT (type MDrawMetric). */
278 #define TEXT_EXTENTS(from, to, rect) \
279 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
281 /* Store the glyph information of a character at the position $POS in
282 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
283 $FROM is written at the coordinate (0, 0). */
284 #define GLYPH_INFO(from, pos, info) \
285 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
287 /* Set $X and $Y to the coordinate of character at position $POS
288 assuming that the text from $FROM is written at the coordinate (0,
290 #define COORDINATES_POSITION(from, pos, x, y) \
291 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
293 /* Interface macros for X library. */
294 #define COPY_AREA(y0, y1, to) \
295 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
297 #define CLEAR_AREA(x, y, w, h) \
298 XClearArea (display, win, (x), (y), (w), (h), False)
300 #define SELECTEDP() \
301 mtext_property_mtext (selection)
303 /* Format MSG by FMT and print the result to the stderr, and exit. */
304 #define FATAL_ERROR(fmt, arg) \
306 fprintf (stderr, fmt, arg); \
311 /* If POS is greater than zero, move POS back to the beginning of line
312 (BOL) position. If FORWARD is nonzero, move POS forward instead.
313 Return the new position. */
315 bol (int pos, int forward)
317 int limit = forward ? nchars : 0;
319 pos = mtext_character (mt, pos, limit, '\n');
320 return (pos < 0 ? limit : pos + 1);
323 /* Update the structure #TOP (struct LineInfo) to make $POS the first
324 character position of the screen. */
328 int from = bol (pos, 0);
331 GLYPH_INFO (from, pos, info);
332 top.from = info.line_from;
333 top.to = info.line_to;
335 top.y1 = info.this.height;
336 top.ascent = - info.this.y;
340 /* Update the scroll bar so that the text of the range $FROM to $TO
341 are shown on the window. */
343 update_scroll_bar (int from, int to)
345 float top = (float) from / nchars;
346 float shown = (float) (to - from) / nchars;
347 XtArgVal *l_top = (XtArgVal *) ⊤
348 XtArgVal *l_shown = (XtArgVal *) &shown;
350 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
351 XtSetArg (arg[1], XtNshown, *l_shown);
352 XtSetValues (SbarWidget, arg, 2);
356 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
357 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
358 is nonzero, update the scoll bar. */
360 redraw (int y0, int y1, int clear, int scroll_bar)
365 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
366 struct LineInfo *line;
368 if (clear || control.anti_alias)
369 CLEAR_AREA (0, y0, win_width, y1 - y0);
371 /* Find a line closest to y0. It is a cursor line if the cursor is
372 Y0, otherwise the top line. */
377 /* If there exists a selected region, check it too. */
378 if (sel_y0 > line->y0 && y0 >= sel_y0)
383 info.this.height = line->y1 - y;
384 info.this.y = - line->ascent;
385 info.line_to = line->to;
386 while (from < nchars && y + info.this.height <= y0)
388 y += info.this.height;
390 GLYPH_INFO (from, from, info);
392 y0 = y - info.this.y;
394 while (to < nchars && y < y1)
396 GLYPH_INFO (to, to, info);
397 y += info.this.height;
403 DRAW_TEXT (0, y0, from, to);
408 GLYPH_INFO (to, to, info);
409 if (y + info.this.height >= win_height)
412 y += info.this.height;
414 update_scroll_bar (top.from, to);
419 /* Set the current input method spot to the correct position. */
421 set_input_method_spot ()
423 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
424 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
426 int n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
427 int size = 0, ratio = 0, i;
429 for (i = n - 1; i >= 0; i--)
432 size = (int) mface_get_prop (faces[i], Msize);
434 ratio = (int) mface_get_prop (faces[i], Mratio);
437 size = default_font_size;
439 size = size * ratio / 100;
440 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
441 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
446 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
449 redraw_cursor (int clear)
451 if (control.cursor_bidi)
453 /* We must update the whole line of the cursor. */
454 int beg = bol (cur.from, 0);
455 int end = bol (cur.to - 1, 1);
457 int y0 = cur.y0, y1 = cur.y1;
461 TEXT_EXTENTS (beg, cur.from, rect);
466 TEXT_EXTENTS (cur.to, end, rect);
469 redraw (y0, y1, clear, 0);
477 if (control.orientation_reversed)
478 x += win_width - cursor.this.width;
479 CLEAR_AREA (x, cur.y0, cursor.this.width, cursor.this.height);
481 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
486 /* Update the information about the location of cursor to the position
487 $POS. If $FULL is nonzero, update the information fully only from
488 the information about the top line. Otherwise, truct the current
489 information in the structure $CUR. */
491 update_cursor (int pos, int full)
497 /* CUR is inaccurate. We can trust only TOP. */
498 GLYPH_INFO (top.from, pos, cursor);
499 cur.y0 = top.ascent + cursor.y + cursor.this.y;
501 else if (pos < cur.from)
503 int from = bol (pos, 0);
505 TEXT_EXTENTS (from, cur.from, rect);
506 GLYPH_INFO (from, pos, cursor);
507 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y);
509 else if (pos < cur.to)
511 GLYPH_INFO (cur.from, pos, cursor);
515 GLYPH_INFO (cur.from, pos, cursor);
516 cur.y0 += cur.ascent + cursor.y + cursor.this.y;
519 cur.from = cursor.line_from;
520 cur.to = cursor.line_to;
521 cur.y1 = cur.y0 + cursor.this.height;
522 cur.ascent = - cursor.this.y;
526 /* Update the information about the selected region. */
536 from = mtext_property_start (selection);
537 to = mtext_property_end (selection);
541 int pos = bol (from, 0);
543 TEXT_EXTENTS (pos, top.from, rect);
544 sel_start.y0 = top.y0 - rect.height;
545 sel_start.ascent = - rect.y;
546 GLYPH_INFO (pos, from, info);
547 if (pos < info.line_from)
548 sel_start.y0 += - rect.y + info.y + info.this.y;
552 GLYPH_INFO (top.from, from, info);
553 sel_start.y0 = top.ascent + info.y + info.this.y;
555 sel_start.ascent = -info.this.y;
556 sel_start.y1 = sel_start.y0 + info.this.height;
557 sel_start.from = info.line_from;
558 sel_start.to = info.line_to;
560 if (to <= sel_start.to)
563 if (to >= sel_end.to)
565 GLYPH_INFO (sel_start.from, to, info);
566 sel_end.y1 = sel_end.y0 + info.y + info.this.height;
567 sel_end.to = info.line_to;
572 GLYPH_INFO (sel_start.from, to, info);
573 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
574 sel_end.y1 = sel_end.y0 + info.this.height;
575 sel_end.ascent = - info.this.y;
576 sel_end.from = info.line_from;
577 sel_end.to = info.line_to;
582 /* Select the text in the region from $FROM to $TO. */
584 select_region (int from, int to)
589 pos = from, from = to, to = pos;
590 mtext_push_property (mt, from, to, selection);
595 /* Setup the window to display the character of $POS at the top left
601 /* Top and bottom Y positions to redraw. */
604 if (pos + 1000 < top.from)
605 y0 = 0, y1 = win_height;
606 else if (pos < top.from)
609 TEXT_EXTENTS (pos, top.from, rect);
610 if (rect.height >= win_height * 0.9)
615 COPY_AREA (0, win_height - y1, y1);
618 else if (pos < top.to)
620 /* No need of redrawing. */
623 else if (pos < top.from + 1000)
625 TEXT_EXTENTS (top.from, pos, rect);
626 if (rect.height >= win_height * 0.9)
630 y0 = win_height - rect.height;
631 COPY_AREA (rect.height, win_height, 0);
636 y0 = 0, y1 = win_height;
642 update_cursor (pos, 1);
644 update_cursor (cursor.from, 1);
646 redraw (y0, y1, 1, 1);
650 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
653 /* Select an input method accoding to $IDX. If $IDX is negative, turn
654 off the current input method, otherwide turn on the input method
655 input_method_table[$IDX]. */
657 select_input_method (idx)
659 if (idx == current_input_method)
661 if (current_input_context)
663 minput_destroy_ic (current_input_context);
664 current_input_context = NULL;
665 current_input_method = -1;
669 InputMethodInfo *im = input_method_table + idx;
671 if (im->language == Mnil)
673 MInputXIMArgIC arg_xic;
674 Window win = XtWindow (TextWidget);
676 arg_xic.input_style = 0;
677 arg_xic.client_win = arg_xic.focus_win = win;
678 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
679 current_input_context = minput_create_ic (im->im, &arg_xic);
683 MInputGUIArgIC arg_ic;
685 arg_ic.frame = frame;
686 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
687 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
688 current_input_context = minput_create_ic (im->im, &arg_ic);
691 if (current_input_context)
693 set_input_method_spot ();
694 current_input_method = idx;
697 if (current_input_method >= 0)
700 XtSetArg (arg[0], XtNlabel, &label);
701 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
702 XtSetArg (arg[0], XtNlabel, label);
705 XtSetArg (arg[0], XtNlabel, "");
706 XtSetValues (CurIMLang, arg, 1);
709 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
712 /* Display cursor according to the current information of #CUR.
713 $CLIENT_DATA is ignore. Most callback functions add this function
714 as a background processing procedure the current application (by
715 XtAppAddWorkProc) via the function hide_cursor. */
717 show_cursor (XtPointer client_data)
719 MFaceHLineProp *hline;
725 update_cursor (cursor.from, 1);
727 while (cur.y1 > win_height)
730 update_cursor (cursor.from, 1);
733 control.cursor_pos = cursor.from;
736 control.with_cursor = 1;
739 if (current_input_context)
740 set_input_method_spot ();
743 int pos = (SELECTEDP () ? mtext_property_start (selection)
744 : cursor.from > 0 ? cursor.from - 1
746 MFace *face = mface ();
747 MTextProperty *props[256];
748 int n = mtext_get_properties (mt, pos, Mface, props, 256);
750 char buf[256], *p = buf;
756 int size = (int) mfont_get_prop (cursor.font, Msize);
757 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
758 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
759 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
760 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
762 sprintf (p, "%dpt", size / 10), p += strlen (p);
764 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
766 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
768 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
770 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
774 mface_merge (face, face_default);
775 for (i = 0; i < n; i++)
776 if (props[i] != selection)
777 mface_merge (face, (MFace *) mtext_property_value (props[i]));
778 sym = (MSymbol) mface_get_prop (face, Mforeground);
780 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
781 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
782 strcat (p, ",rev"), p += strlen (p);
783 hline = mface_get_prop (face, Mhline);
784 if (hline && hline->width > 0)
785 strcat (p, ",ul"), p += strlen (p);
786 box = mface_get_prop (face, Mbox);
787 if (box && box->width > 0)
788 strcat (p, ",box"), p += strlen (p);
789 m17n_object_unref (face);
791 XtSetArg (arg[0], XtNborderWidth, 1);
792 XtSetArg (arg[1], XtNlabel, buf);
793 XtSetValues (CurFaceWidget, arg, 2);
796 if (control.cursor_pos < nchars)
800 if (control.cursor_pos > 0
801 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
802 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
804 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
808 XtSetArg (arg[0], XtNborderWidth, 0);
809 XtSetArg (arg[1], XtNlabel, "");
813 XtSetArg (arg[0], XtNborderWidth, 1);
814 XtSetArg (arg[1], XtNlabel,
815 msymbol_name (msymbol_get (sym, Mlanguage)));
816 XtSetValues (CurLangWidget, arg, 2);
818 XtSetValues (CurLangWidget, arg, 2);
820 if (auto_input_method)
823 select_input_method (-1);
828 for (i = 0; i < num_input_methods; i++)
829 if (input_method_table[i].language == sym)
831 if (i < num_input_methods
832 && input_method_table[i].available >= 0)
834 if (! input_method_table[i].im)
836 input_method_table[i].im =
837 minput_open_im (input_method_table[i].language,
838 input_method_table[i].name, NULL);
839 if (! input_method_table[i].im)
840 input_method_table[i].available = -1;
842 if (input_method_table[i].im)
843 select_input_method (i);
845 select_input_method (-1);
848 select_input_method (-1);
853 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
859 /* Hide the cursor. */
863 control.with_cursor = 0;
865 XtAppAddWorkProc (context, show_cursor, NULL);
869 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
870 $Y1 and $NEW_Y1 assuming that the text in the other area is not
873 update_region (int y0, int old_y1, int new_y1)
879 if (old_y1 < win_height)
881 COPY_AREA (old_y1, win_height, new_y1);
882 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
885 redraw (new_y1, win_height, 1, 0);
887 else if (new_y1 > old_y1)
889 if (new_y1 < win_height)
890 COPY_AREA (old_y1, win_height, new_y1);
892 if (new_y1 > win_height)
894 redraw (y0, new_y1, 1, 1);
898 /* Delete the next $N characters. If $N is negative delete the
899 precious (- $N) characters. */
909 from = cursor.from, to = from + n;
912 if (cursor.from == cur.from)
914 /* We are at the beginning of line. */
915 int pos = cursor.prev_from;
917 if (cursor.from == top.from)
919 /* We are at the beginning of screen. We must scroll
921 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
922 reseat (info.line_from);
924 update_cursor (pos, 1);
930 from = cursor.from - 1;
935 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
936 old_y1 = cur.y0 + rect.height;
938 /* Now delete a character. */
939 mtext_del (mt, from, to);
941 if (from >= top.from && from < top.to)
942 update_top (top.from);
943 update_cursor (from, 1);
945 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
946 new_y1 = cur.y0 + rect.height;
948 update_region (cur.y0, old_y1, new_y1);
952 /* Insert M-text $NEWTEXT at the current cursor position. */
954 insert_chars (MText *newtext)
956 int n = mtext_len (newtext);
958 int y0, old_y1, new_y1;
962 int n = (mtext_property_end (selection)
963 - mtext_property_start (selection));
964 mtext_detach_property (selection);
969 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
970 old_y1 = y0 + rect.height;
972 /* Now insert chars. */
973 mtext_ins (mt, cursor.from, newtext);
975 if (cur.from == top.from)
976 update_top (top.from);
977 update_cursor (cursor.from + n, 1);
979 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
980 new_y1 = cur.y0 + rect.height;
982 update_region (y0, old_y1, new_y1);
987 /* Convert the currently selected text to COMPOUND-TEXT. It is called
988 when someone requests the current value of the selection. */
990 covert_selection (Widget w, Atom *selection_atom,
991 Atom *target, Atom *return_type,
992 XtPointer *value, unsigned long *length, int *format)
994 unsigned char *buf = (unsigned char *) XtMalloc (4096);
995 MText *this_mt = mtext ();
996 int from = mtext_property_start (selection);
997 int to = mtext_property_end (selection);
999 mtext_copy (this_mt, 0, mt, from, to);
1000 *length = mconv_encode_buffer (msymbol ("compound-text"),
1001 this_mt, buf, 4096);
1002 *return_type = XA_COMPOUND_TEXT;
1003 *value = (XtPointer) buf;
1005 m17n_object_unref (this_mt);
1010 /* Unselect the text. It is called when we loose the selection. */
1012 lose_selection (Widget w, Atom *selection_atom)
1016 mtext_detach_property (selection);
1017 redraw (sel_start.y0, sel_end.y1, 1, 0);
1022 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1023 XtPointer value, unsigned long *length, int *format)
1028 if (*type == XT_CONVERT_FAIL || ! value)
1030 if (*type == XA_STRING)
1032 else if (*type == XA_COMPOUND_TEXT)
1033 coding = msymbol ("compound-text");
1034 else if (*type == XA_UTF8_STRING)
1035 coding = msymbol ("utf-8");
1039 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1043 insert_chars (this_mt);
1044 m17n_object_unref (this_mt);
1053 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1055 XExposeEvent *expose = (XExposeEvent *) event;
1059 Dimension width_max, width;
1061 XtSetArg (arg[0], XtNwidth, &width);
1062 XtGetValues (XtParent (w), arg, 1);
1064 XtGetValues (HeadWidget, arg, 1);
1065 if (width_max < width)
1067 XtGetValues (FaceWidget, arg, 1);
1068 if (width_max < width)
1070 XtGetValues (LangWidget, arg, 1);
1071 if (width_max < width)
1073 XtSetArg (arg[0], XtNwidth, width_max);
1074 XtSetValues (HeadWidget, arg, 1);
1075 XtSetValues (FaceWidget, arg, 1);
1076 XtSetValues (LangWidget, arg, 1);
1077 XtSetValues (XtParent (w), arg, 1);
1078 XtSetValues (TailWidget, arg, 1);
1081 update_cursor (0, 1);
1082 redraw (0, win_height, 0, 1);
1087 redraw (expose->y, expose->y + expose->height, 0, 0);
1088 if (current_input_context
1089 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1090 set_input_method_spot ();
1095 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1097 XConfigureEvent *configure = (XConfigureEvent *) event;
1100 control.max_line_width = win_width = configure->width;
1101 win_height = configure->height;
1102 mdraw_clear_cache (mt);
1104 update_cursor (0, 1);
1105 redraw (0, win_height, 1, 1);
1106 if (current_input_context)
1107 set_input_method_spot ();
1111 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1114 int x = event->xbutton.x;
1115 int y = event->xbutton.y - top.ascent;
1117 if (control.orientation_reversed)
1119 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1122 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1123 mtext_detach_property (selection);
1124 redraw (sel_start.y0, sel_end.y1, 1, 0);
1127 update_cursor (pos, 0);
1132 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1137 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1138 covert_selection, lose_selection, NULL);
1139 update_cursor (mtext_property_start (selection), 0);
1144 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1148 /* We don't have a local selection. */
1149 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1154 int from = mtext_property_start (selection);
1155 int to = mtext_property_end (selection);
1158 int x = event->xbutton.x;
1159 int y = event->xbutton.y - top.ascent;
1161 if (control.orientation_reversed)
1163 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1165 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1166 mtext_detach_property (selection);
1168 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1169 update_cursor (pos, 0);
1170 insert_chars (this_mt);
1171 m17n_object_unref (this_mt);
1176 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1179 int x = event->xbutton.x;
1180 int y = event->xbutton.y;
1182 if (control.orientation_reversed)
1185 pos = top.from, y -= top.ascent;
1187 pos = cur.from, y -= cur.y0 + cur.ascent;
1188 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1190 if (pos == cursor.from)
1196 /* Selection range changed. */
1197 int from = mtext_property_start (selection);
1198 int to = mtext_property_end (selection);
1199 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1200 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1202 if (cursor.from == from)
1204 /* Starting position changed. */
1207 /* Enlarged. We can simply overdraw. */
1208 select_region (pos, to);
1209 redraw (sel_start.y0, start_y1, 0, 0);
1213 /* Shrunken. Previous selection face must be cleared. */
1214 select_region (pos, to);
1215 redraw (start_y0, sel_start.y1, 1, 0);
1219 /* Shrunken to zero. */
1220 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1221 mtext_detach_property (selection);
1222 redraw (start_y0, end_y1, 1, 0);
1226 /* Full update is necessary. */
1227 select_region (to, pos);
1228 redraw (start_y0, sel_end.y1, 1, 0);
1233 /* Ending position changed. */
1236 /* Full update is necessary. */
1237 select_region (pos, from);
1238 redraw (sel_start.y0, end_y1, 1, 0);
1240 else if (pos == from)
1242 /* Shrunken to zero. */
1243 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1244 mtext_detach_property (selection);
1245 redraw (start_y0, end_y1, 1, 0);
1249 /* Shrunken. Previous selection face must be cleared. */
1250 select_region (from, pos);
1251 redraw (sel_end.y0, end_y1, 1, 0);
1255 /* Enlarged. We can simply overdraw. */
1256 select_region (from, pos);
1257 redraw (end_y0, sel_end.y1, 0, 0);
1263 /* Newly selected. */
1264 select_region (pos, cursor.from);
1265 redraw (sel_start.y0, sel_end.y1, 0, 0);
1267 update_cursor (pos, 1);
1271 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1274 MDrawGlyphInfo info;
1276 int cursor_pos = cursor.from;
1278 if (((int) position) < 0)
1284 height = top.y1 - top.y0;
1287 pos = bol (from - 1, 0);
1288 GLYPH_INFO (pos, from - 1, info);
1289 if (height + info.this.height > win_height)
1291 height += info.this.height;
1292 from = info.line_from;
1294 if (cursor_pos >= top.to)
1296 cursor_pos = top.from;
1298 while (cursor_pos < nchars)
1300 GLYPH_INFO (pos, pos, info);
1301 if (height + info.this.height > win_height)
1303 height += info.this.height;
1309 else if (cur.to < nchars)
1311 /* Scroll up, but leave at least one line. */
1314 while (from < nchars)
1316 GLYPH_INFO (from, from, info);
1317 if (height + info.this.height > win_height
1318 || info.line_to >= nchars)
1320 height += info.this.height;
1321 from = info.line_to;
1324 from = info.line_from;
1325 if (cursor_pos < from)
1329 /* Scroll up to make the cursor line top. */
1333 update_cursor (cursor_pos, 1);
1337 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1339 float persent = *(float *) persent_ptr;
1340 int pos1, pos2 = nchars * persent;
1341 MDrawGlyphInfo info;
1344 pos1 = bol (pos2, 0);
1345 GLYPH_INFO (pos1, pos2, info);
1346 pos1 = info.line_from;
1348 update_cursor (pos1, 1);
1353 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1355 XKeyEvent *key_event = (XKeyEvent *) event;
1357 KeySym keysym = NoSymbol;
1359 /* If set to 1, do not update target_x_position. */
1360 int keep_target_x_position = 0;
1363 if (current_input_context
1364 && minput_filter (current_input_context, Mnil, event))
1366 if (event->type == KeyRelease)
1371 produced = mtext ();
1372 ret = minput_lookup (current_input_context, Mnil, event, produced);
1373 if (mtext_len (produced) > 0)
1374 insert_chars (produced);
1376 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1377 m17n_object_unref (produced);
1387 n = (mtext_property_end (selection)
1388 - mtext_property_start (selection));
1389 mtext_detach_property (selection);
1391 else if (cursor.from < nchars)
1393 /* Delete the following grapheme cluster. */
1394 n = cursor.to - cursor.from;
1407 /* Delete selected region. */
1408 n = (mtext_property_end (selection)
1409 - mtext_property_start (selection));
1410 mtext_detach_property (selection);
1412 else if (cursor.from > 0)
1414 /* Delete the preceding character. */
1425 mtext_detach_property (selection);
1426 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1430 if (cursor.prev_from >= 0)
1431 update_cursor (cursor.prev_from, 0);
1435 if (cursor.left_from >= 0)
1436 update_cursor (cursor.left_from, 0);
1443 mtext_detach_property (selection);
1444 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1448 if (cursor.next_to >= 0)
1449 update_cursor (cursor.to, 0);
1453 if (cursor.right_from >= 0)
1454 update_cursor (cursor.right_from, 0);
1461 mtext_detach_property (selection);
1462 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1464 if (cur.to <= nchars)
1466 MDrawGlyphInfo info;
1469 GLYPH_INFO (cur.from, cur.to, info);
1470 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1471 target_x_position, info.y);
1472 keep_target_x_position = 1;
1473 update_cursor (pos, 0);
1480 mtext_detach_property (selection);
1481 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1487 int pos = bol (cur.from - 1, 0);
1489 TEXT_EXTENTS (pos, cur.from - 1, rect);
1490 y = rect.height + rect.y - 1;
1491 pos = COORDINATES_POSITION (pos, nchars,
1492 target_x_position, y);
1493 keep_target_x_position = 1;
1494 update_cursor (pos, 0);
1501 mtext_detach_property (selection);
1502 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1504 if (top.from < nchars)
1505 ScrollProc (w, NULL, (XtPointer) 1);
1511 mtext_detach_property (selection);
1512 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1515 ScrollProc (w, NULL, (XtPointer) -1);
1521 if (buf[0] == 17) /* C-q */
1523 XtAppSetExitFlag (context);
1526 else if (buf[0] == 12) /* C-l */
1528 redraw (0, win_height, 1, 1);
1533 MText *temp = mtext ();
1535 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1536 if (current_input_context)
1537 mtext_put_prop (temp, 0, 1, Mlanguage,
1538 current_input_context->im->language);
1539 insert_chars (temp);
1540 m17n_object_unref (temp);
1545 if (! keep_target_x_position)
1546 target_x_position = cursor.x;
1550 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1552 char *name = (char *) client_data;
1554 int from = -1, to = 0;
1559 filename = strdup (name);
1562 fp = fopen (filename, "w");
1565 fprintf (stderr, "Open for write fail: %s", filename);
1571 from = mtext_property_start (selection);
1572 to = mtext_property_end (selection);
1573 mtext_detach_property (selection);
1576 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1579 select_region (from, to);
1583 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1589 mtext_detach_property (selection);
1590 serialized = (int) client_data;
1592 new = mtext_deserialize (mt);
1595 MPlist *plist = mplist ();
1597 mplist_push (plist, Mt, Mface);
1598 mplist_push (plist, Mt, Mlanguage);
1599 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1600 m17n_object_unref (plist);
1604 m17n_object_unref (mt);
1606 serialized = ! serialized;
1607 nchars = mtext_len (mt);
1610 update_cursor (0, 1);
1611 redraw (0, win_height, 1, 1);
1615 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1617 XtAppSetExitFlag (context);
1623 FILE *fp = fopen (filename, "r");
1626 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1627 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1630 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1635 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1637 int data = (int) client_data;
1642 control.enable_bidi = 0;
1643 control.orientation_reversed = 0;
1647 control.enable_bidi = 1;
1648 control.orientation_reversed = data == 2;
1650 for (i = 0; i < 3; i++)
1653 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1655 XtSetArg (arg[0], XtNleftBitmap, None);
1656 XtSetValues (BidiMenus[i], arg, 1);
1659 update_cursor (cursor.from, 1);
1660 redraw (0, win_height, 1, 0);
1663 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1666 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1668 int data = (int) client_data;
1672 control.max_line_width = 0;
1675 control.max_line_width = win_width;
1676 control.line_break = (data == 1 ? NULL : line_break);
1678 for (i = 0; i < 3; i++)
1681 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1683 XtSetArg (arg[0], XtNleftBitmap, None);
1684 XtSetValues (LineBreakMenus[i], arg, 1);
1687 update_cursor (cursor.from, 1);
1688 redraw (0, win_height, 1, 0);
1692 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1694 int data = (int) client_data;
1708 control.cursor_bidi = 0, control.cursor_width = -1;
1712 control.cursor_bidi = 0, control.cursor_width = 2;
1716 control.cursor_bidi = 1;
1721 for (i = from; i < to; i++)
1724 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1726 XtSetArg (arg[0], XtNleftBitmap, None);
1727 XtSetValues (CursorMenus[i], arg, 1);
1730 redraw (0, win_height, 1, 0);
1734 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1736 int idx = (int) client_data;
1738 if (idx == -2 ? current_input_method < 0
1739 : idx == -1 ? auto_input_method
1740 : idx == current_input_method)
1743 XtSetArg (arg[0], XtNleftBitmap, None);
1744 if (auto_input_method)
1746 XtSetValues (InputMethodMenus[1], arg, 1);
1747 auto_input_method = 0;
1749 else if (current_input_method < 0)
1750 XtSetValues (InputMethodMenus[0], arg, 1);
1752 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1756 auto_input_method = 1;
1759 else if (input_method_table[idx].available >= 0)
1761 if (! input_method_table[idx].im)
1763 input_method_table[idx].im =
1764 minput_open_im (input_method_table[idx].language,
1765 input_method_table[idx].name, NULL);
1766 if (! input_method_table[idx].im)
1767 input_method_table[idx].available = -1;
1769 if (input_method_table[idx].im)
1770 select_input_method (idx);
1772 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1773 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1776 MPlist *default_face_list;
1779 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1781 int idx = (int) client_data;
1791 MFace *face = mframe_get_prop (frame, Mface);
1793 for (plist = default_face_list; mplist_key (plist) != Mnil;
1794 plist = mplist_next (plist))
1795 mface_merge (face, mplist_value (plist));
1796 mplist_add (plist, Mt, *face_table[idx].face);
1797 mface_merge (face, *face_table[idx].face);
1799 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1801 MFace *face = mframe_get_prop (frame, Mface);
1803 for (plist = default_face_list;
1804 mplist_key (mplist_next (plist)) != Mnil;
1805 plist = mplist_next (plist))
1806 mface_merge (face, mplist_value (plist));
1810 update_cursor (0, 1);
1811 redraw (0, win_height, 1, 1);
1816 XtAppAddWorkProc (context, show_cursor, NULL);
1817 from = mtext_property_start (selection);
1818 to = mtext_property_end (selection);
1819 old_y1 = sel_end.y1;
1821 mtext_detach_property (selection);
1824 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1825 MTEXTPROP_REAR_STICKY);
1826 mtext_push_property (mt, from, to, prop);
1827 m17n_object_unref (prop);
1830 mtext_pop_prop (mt, from, to, Mface);
1832 update_top (top.from);
1833 update_cursor (cursor.from, 1);
1834 select_region (from, to);
1835 update_region (sel_start.y0, old_y1, sel_end.y1);
1836 if (cur.y1 > win_height)
1838 while (cur.y1 > win_height)
1841 update_cursor (cursor.from, 1);
1847 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1849 MSymbol sym = (MSymbol) client_data;
1856 XtAppAddWorkProc (context, show_cursor, NULL);
1857 from = mtext_property_start (selection);
1858 to = mtext_property_end (selection);
1859 old_y1 = sel_end.y1;
1861 mtext_detach_property (selection);
1863 mtext_put_prop (mt, from, to, Mlanguage, sym);
1865 mtext_pop_prop (mt, from, to, Mlanguage);
1868 update_top (top.from);
1869 update_cursor (cursor.from, 1);
1870 select_region (from, to);
1871 update_region (sel_start.y0, old_y1, sel_end.y1);
1872 if (cur.y1 > win_height)
1874 while (cur.y1 > win_height)
1877 update_cursor (cursor.from, 1);
1883 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1885 int narrowed = (int) client_data;
1888 MConverter *converter;
1894 from = mtext_property_start (selection);
1895 to = mtext_property_end (selection);
1904 mdump = popen ("mdump -q -p a4", "w");
1906 mdump = popen ("mdump -q", "w");
1909 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1910 mconv_encode_range (converter, mt, from, to);
1911 mconv_free_converter (converter);
1916 input_status (MInputContext *ic, MSymbol command)
1918 XFillRectangle (display, input_status_pixmap, gc_inv,
1919 0, 0, input_status_width, input_status_height);
1920 if (command == Minput_status_draw)
1924 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1925 Mface, face_input_status);
1926 if (ic->im->language != Mnil)
1927 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1928 Mlanguage, ic->im->language);
1929 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1930 &input_status_control, NULL, NULL, &rect);
1931 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1932 input_status_width - rect.width - 2, - rect.y,
1933 ic->status, 0, mtext_len (ic->status),
1934 &input_status_control);
1936 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1937 XtSetValues (CurIMStatus, arg, 1);
1941 compare_input_method (const void *elt1, const void *elt2)
1943 const InputMethodInfo *im1 = elt1;
1944 const InputMethodInfo *im2 = elt2;
1945 MSymbol lang1, lang2;
1947 if (im1->language == Mnil)
1949 if (im1->language == im2->language)
1950 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1951 if (im1->language == Mt)
1953 if (im2->language == Mt)
1955 lang1 = msymbol_get (im1->language, Mlanguage);
1956 lang2 = msymbol_get (im2->language, Mlanguage);
1957 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1961 setup_input_methods (int with_xim)
1963 MInputMethod *im = NULL;
1964 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1968 num_input_methods = mplist_length (plist);
1972 MInputXIMArgIM arg_xim;
1974 arg_xim.display = display;
1976 arg_xim.res_name = arg_xim.res_class = NULL;
1977 arg_xim.locale = NULL;
1978 arg_xim.modifier_list = NULL;
1979 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1981 num_input_methods++;
1983 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
1986 input_method_table[i].available = 1;
1987 input_method_table[i].language = Mnil;
1988 input_method_table[i].name = im->name;
1989 input_method_table[i].im = im;
1993 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1995 MDatabase *mdb = mplist_value (pl);
1996 MSymbol *tag = mdatabase_tag (mdb);
2000 input_method_table[i].language = tag[1];
2001 input_method_table[i].name = tag[2];
2006 m17n_object_unref (plist);
2007 num_input_methods = i;
2008 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2009 compare_input_method);
2010 current_input_context = NULL;
2012 mplist_put (minput_driver->callback_list, Minput_status_start,
2013 (void *) input_status);
2014 mplist_put (minput_driver->callback_list, Minput_status_draw,
2015 (void *) input_status);
2016 mplist_put (minput_driver->callback_list, Minput_status_done,
2017 (void *) input_status);
2022 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2026 if (num && *num > 0)
2030 for (i = 0; i < *num; i++)
2031 bytes += strlen (str[i]) + 1;
2032 msg = alloca (bytes);
2033 strcpy (msg, str[0]);
2034 for (i = 1; i < *num; i++)
2035 strcat (msg, " "), strcat (msg, str[i]);
2037 else if (cursor.from < nchars)
2039 int c = mtext_ref_char (mt, cursor.from);
2040 char *name = mchar_get_prop (c, Mname);
2044 msg = alloca (10 + strlen (name));
2045 sprintf (msg, "U+%04X %s", c, name);
2051 XtSetArg (arg[0], XtNlabel, msg);
2052 XtSetValues (MessageWidget, arg, 1);
2058 char *name1, *name2;
2059 XtCallbackProc proc;
2060 XtPointer client_data;
2065 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2067 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2069 MenuRec FileMenu[] =
2070 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2071 { 0, "Save", NULL, SaveProc, NULL, -1 },
2072 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2074 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2075 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2077 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2078 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2080 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2083 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2085 MenuRec *rec = (MenuRec *) client_data;
2088 XtSetArg (arg[0], XtNvalue, "");
2089 XtSetArg (arg[1], XtNlabel, rec->name1);
2090 XtSetValues (FileDialogWidget, arg, 2);
2091 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2092 XtSetArg (arg[0], XtNx, x + 20);
2093 XtSetArg (arg[1], XtNy, y + 10);
2094 XtSetValues (FileShellWidget, arg, 2);
2095 XtPopup (FileShellWidget, XtGrabExclusive);
2099 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2104 XtPopdown (FileShellWidget);
2105 if ((int) client_data == 1)
2107 XtSetArg (arg[0], XtNlabel, &label);
2108 XtGetValues (FileDialogWidget, arg, 1);
2109 if (strcmp (label, FileMenu[0].name1) == 0)
2113 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2114 fp = fopen (filename, "r");
2116 m17n_object_unref (mt);
2119 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2127 nchars = mtext_len (mt);
2129 update_cursor (0, 1);
2130 redraw (0, win_height, 1, 1);
2132 else if (strcmp (label, FileMenu[2].name1) == 0)
2133 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2135 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2138 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2139 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2140 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2141 (MENU).status = (STATUS))
2145 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2146 char *menu_name, MenuRec *menus, int num_menus, char *help)
2148 Widget button, menu;
2149 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2150 <LeaveWindow>: reset() MenuHelp()\n\
2151 <BtnDown>: reset() PopupMenu()\n\
2152 <BtnUp>: highlight()";
2158 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2159 for (i = 0; i < num_menus; i++)
2170 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2172 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2174 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2176 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2180 XtSetArg (arg[0], XtNsensitive, False);
2181 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2187 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2192 trans = alloca (strlen (fmt) + strlen (help));
2193 sprintf (trans, fmt, help);
2194 XtSetArg (arg[0], XtNmenuName, menu_name);
2195 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2196 XtSetArg (arg[2], XtNinternalWidth, 2);
2197 XtSetArg (arg[3], XtNhighlightThickness, 1);
2198 XtSetArg (arg[4], XtNleft, XawChainLeft);
2199 XtSetArg (arg[5], XtNright, XawChainLeft);
2202 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2203 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2208 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2209 int *len = alloca (sizeof (int) * num_menus);
2212 XFontSetExtents *fontset_extents;
2214 XtSetArg (arg[0], XtNfontSet, &font_set);
2215 XtGetValues (button, arg, 1);
2217 fontset_extents = XExtentsOfFontSet (font_set);
2218 height = fontset_extents->max_logical_extent.height;
2219 ascent = - fontset_extents->max_logical_extent.y;
2221 for (i = 0; i < num_menus; i++)
2224 len[i] = strlen (menus[i].name2);
2225 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2226 if (max_width < width[i])
2227 max_width = width[i];
2229 for (i = 0; i < num_menus; i++)
2232 Pixmap pixmap = XCreatePixmap (display,
2233 RootWindow (display, screen),
2234 max_width, height, 1);
2235 XFillRectangle (display, pixmap, mono_gc_inv,
2236 0, 0, max_width, height);
2237 XmbDrawString (display, pixmap, font_set, mono_gc,
2238 max_width - width[i], ascent,
2239 menus[i].name2, len[i]);
2240 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2241 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2242 XtSetValues (menus[i].w, arg, 2);
2250 XtActionsRec actions[] = {
2251 {"Expose", ExposeProc},
2252 {"Configure", ConfigureProc},
2254 {"ButtonPress", ButtonProc},
2255 {"ButtonRelease", ButtonReleaseProc},
2256 {"ButtonMotion", ButtonMoveProc},
2257 {"Button2Press", Button2Proc},
2258 {"MenuHelp", MenuHelpProc}
2262 /* Print the usage of this program (the name is PROG), and exit with
2266 help_exit (char *prog, int exit_code)
2274 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2275 printf ("Display FILE on a window and allow users to edit it.\n");
2276 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2277 printf ("The following OPTIONs are available.\n");
2278 printf (" %-13s %s", "--version", "print version number\n");
2279 printf (" %-13s %s", "-h, --help", "print this message\n");
2284 main (int argc, char **argv)
2286 Widget form, BodyWidget, w;
2287 char *fontset_name = NULL;
2288 int col = 80, row = 32;
2289 /* Translation table for TextWidget. */
2290 String trans = "<Expose>: Expose()\n\
2291 <Configure>: Configure()\n\
2294 <Btn1Down>: ButtonPress()\n\
2295 <Btn1Up>: ButtonRelease()\n\
2296 <Btn1Motion>: ButtonMotion()\n\
2297 <Btn2Down>: Button2Press()";
2298 /* Translation table for the top form widget. */
2299 String trans2 = "<Key>: Key()\n\
2301 String pop_face_trans
2302 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2303 <LeaveWindow>: MenuHelp() reset()\n\
2304 <Btn1Down>: set()\n\
2305 <Btn1Up>: notify() unset()";
2306 String pop_lang_trans
2307 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2308 <LeaveWindow>: MenuHelp() reset()\n\
2309 <Btn1Down>: set()\n\
2310 <Btn1Up>: notify() unset()";
2311 int font_width, font_ascent, font_descent;
2315 setlocale (LC_ALL, "");
2316 /* Create the top shell. */
2317 XtSetLanguageProc (NULL, NULL, NULL);
2318 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2319 NULL, sessionShellWidgetClass, NULL, 0);
2320 display = XtDisplay (ShellWidget);
2321 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2323 /* Parse the remaining command line arguments. */
2324 for (i = 1; i < argc; i++)
2326 if (! strcmp (argv[i], "--help")
2327 || ! strcmp (argv[i], "-h"))
2328 help_exit (argv[0], 0);
2329 else if (! strcmp (argv[i], "--version"))
2331 printf ("medit (m17n library) %s\n", VERSION);
2332 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2335 else if (! strcmp (argv[i], "--geometry"))
2338 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2339 help_exit (argv[0], 1);
2341 else if (! strcmp (argv[i], "--fontset"))
2344 fontset_name = strdup (argv[i]);
2346 else if (! strcmp (argv[i], "--with-xim"))
2350 else if (argv[i][0] != '-')
2352 filename = strdup (argv[i]);
2356 fprintf (stderr, "Unknown option: %s", argv[i]);
2357 help_exit (argv[0], 1);
2361 help_exit (argv[0], 1);
2363 mdatabase_dir = ".";
2364 /* Initialize the m17n library. */
2366 if (merror_code != MERROR_NONE)
2367 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2369 mt = read_file (filename);
2372 nchars = mtext_len (mt);
2375 MFace *face = mface ();
2377 mface_put_prop (face, Mforeground, msymbol ("blue"));
2378 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2379 mface_put_prop (face, Mvideomode, Mreverse);
2380 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2381 m17n_object_unref (face);
2384 /* This tells ExposeProc to initialize everything. */
2387 XA_TEXT = XInternAtom (display, "TEXT", False);
2388 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2389 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2391 MPlist *plist = mplist ();
2395 mplist_put (plist, msymbol ("widget"), ShellWidget);
2398 MFontset *fontset = mfontset (fontset_name);
2401 mface_put_prop (face, Mfontset, fontset);
2402 m17n_object_unref (fontset);
2403 mplist_add (plist, Mface, face);
2404 m17n_object_unref (face);
2406 frame = mframe (plist);
2407 m17n_object_unref (plist);
2408 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2409 default_face_list = mplist ();
2410 mplist_add (default_face_list, Mt, face_default);
2411 face_default_fontset = mface ();
2412 mface_put_prop (face_default_fontset, Mfontset,
2413 mface_get_prop (face_default, Mfontset));
2415 font = (MFont *) mframe_get_prop (frame, Mfont);
2416 default_font_size = (int) mfont_get_prop (font, Msize);
2419 font_width = (int) mframe_get_prop (frame, Mfont_width);
2420 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2421 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2422 win_width = font_width * col;
2423 win_height = (font_ascent + font_descent) * row;
2429 prop.color_top = prop.color_left = msymbol ("magenta");
2430 prop.color_bottom = prop.color_right = msymbol ("red");
2431 prop.inner_hmargin = prop.inner_vmargin = 1;
2432 prop.outer_hmargin = prop.outer_vmargin = 2;
2434 face_box = mface ();
2435 mface_put_prop (face_box, Mbox, &prop);
2438 face_courier = mface ();
2439 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2440 face_helvetica = mface ();
2441 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2442 face_times = mface ();
2443 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2444 face_dv_ttyogesh = mface ();
2445 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2446 face_freesans = mface ();
2447 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2448 face_freeserif = mface ();
2449 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2450 face_freemono = mface ();
2451 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2453 face_xxx_large = mface ();
2454 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2456 MFont *latin_font = mframe_get_prop (frame, Mfont);
2457 MFont *dev_font = mfont ();
2458 MFont *thai_font = mfont ();
2459 MFont *tib_font = mfont ();
2461 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2462 MSymbol no_ctl = msymbol ("no-ctl");
2464 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2465 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2466 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2467 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2468 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2469 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2471 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2472 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2473 latin_font, Mnil, 0);
2474 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2475 dev_font, no_ctl, 0);
2476 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2477 thai_font, no_ctl, 0);
2478 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2479 tib_font, no_ctl, 0);
2480 face_no_ctl_fontset = mface ();
2481 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2482 m17n_object_unref (fontset);
2489 setup_input_methods (with_xim);
2491 gc = DefaultGC (display, screen);
2493 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2494 XtSetArg (arg[1], XtNdefaultDistance, 2);
2495 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2497 XtSetArg (arg[0], XtNborderWidth, 0);
2498 XtSetArg (arg[1], XtNdefaultDistance, 2);
2499 XtSetArg (arg[2], XtNtop, XawChainTop);
2500 XtSetArg (arg[3], XtNbottom, XawChainTop);
2501 XtSetArg (arg[4], XtNleft, XawChainLeft);
2502 XtSetArg (arg[5], XtNright, XawChainRight);
2503 XtSetArg (arg[6], XtNresizable, True);
2504 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2505 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2506 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2507 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2508 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2509 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2510 XtSetArg (arg[7], XtNfromVert, LangWidget);
2511 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2512 XtSetArg (arg[2], XtNtop, XawChainBottom);
2513 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2514 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2516 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2517 HeadWidget, NULL, 0);
2518 XtSetArg (arg[0], XtNvalue, "");
2519 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2520 FileShellWidget, arg, 1);
2521 XawDialogAddButton (FileDialogWidget, "OK",
2522 FileDialogProc, (XtPointer) 0);
2523 XawDialogAddButton (FileDialogWidget, "CANCEL",
2524 FileDialogProc, (XtPointer) 1);
2526 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2527 (char *) check_bits,
2528 check_width, check_height);
2530 unsigned long valuemask = GCForeground;
2533 values.foreground = 1;
2534 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2535 values.foreground = 0;
2536 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2543 if (num_menus < num_input_methods + 2)
2544 num_menus = num_input_methods + 2;
2545 if (num_menus < num_faces + 1)
2546 num_menus = num_faces + 1;
2547 menus = alloca (sizeof (MenuRec) * num_menus);
2549 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2550 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2551 "File I/O, Serialization, Image, Quit");
2553 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2554 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2555 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2556 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2557 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2558 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2559 w = create_menu_button (ShellWidget, HeadWidget, w,
2560 "Cursor", "Cursor Menu",
2561 menus, 6, "Cursor Movement Mode, Cursor Shape");
2562 CursorMenus[0] = menus[0].w;
2563 CursorMenus[1] = menus[1].w;
2564 CursorMenus[2] = menus[3].w;
2565 CursorMenus[3] = menus[4].w;
2566 CursorMenus[4] = menus[5].w;
2568 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2569 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2570 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2571 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2572 menus, 3, "BIDI Processing Mode");
2573 for (i = 0; i < 3; i++)
2574 BidiMenus[i] = menus[i].w;
2576 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2577 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2578 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2579 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2581 menus, 3, "How to break lines");
2582 for (i = 0; i < 3; i++)
2583 LineBreakMenus[i] = menus[i].w;
2585 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2586 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2587 for (i = 0; i < num_input_methods; i++)
2589 InputMethodInfo *im = input_method_table + i;
2590 char *name1, *name2;
2592 if (im->language != Mnil && im->language != Mt)
2594 MSymbol sym = msymbol_get (im->language, Mlanguage);
2596 name1 = msymbol_name (im->language);
2598 name1 = msymbol_name (sym);
2599 name2 = msymbol_name (im->name);
2602 name1 = msymbol_name (im->name), name2 = NULL;
2604 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2606 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2607 "Input Method Menu", menus, i + 2,
2608 "Select input method");
2611 unsigned long valuemask = GCForeground;
2614 XtSetArg (arg[0], XtNbackground, &values.foreground);
2615 XtGetValues (w, arg, 1);
2616 gc_inv = XCreateGC (display, RootWindow (display, screen),
2617 valuemask, &values);
2620 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2621 for (i = 0; i < num_input_methods + 2; i++)
2622 InputMethodMenus[i] = menus[i].w;
2624 input_status_width = font_width * 8;
2625 input_status_height = (font_ascent + font_descent) * 2.4;
2626 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2628 input_status_height,
2629 DefaultDepth (display, screen));
2634 prop.color_top = prop.color_bottom
2635 = prop.color_left = prop.color_right = Mnil;
2636 prop.inner_hmargin = prop.inner_vmargin = 1;
2637 prop.outer_hmargin = prop.outer_vmargin = 0;
2638 face_input_status = mface_copy (face_default);
2639 mface_put_prop (face_input_status, Mbox, &prop);
2642 XFillRectangle (display, input_status_pixmap, gc_inv,
2643 0, 0, input_status_width, input_status_height);
2644 XtSetArg (arg[0], XtNfromHoriz, w);
2645 XtSetArg (arg[1], XtNleft, XawRubber);
2646 XtSetArg (arg[2], XtNright, XawChainRight);
2647 XtSetArg (arg[3], XtNborderWidth, 0);
2648 XtSetArg (arg[4], XtNlabel, " ");
2649 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2650 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2651 HeadWidget, arg, 6);
2652 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2653 XtSetArg (arg[1], XtNleft, XawChainRight);
2654 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2655 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2656 HeadWidget, arg, 5);
2658 XtSetArg (arg[0], XtNborderWidth, 0);
2659 XtSetArg (arg[1], XtNleft, XawChainLeft);
2660 XtSetArg (arg[2], XtNright, XawChainLeft);
2661 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2662 for (i = 0; i < num_faces;)
2664 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2665 char *label = label_menu + 5; /* "Xxxx" */
2667 for (j = i; j < num_faces && face_table[j].face; j++)
2668 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2670 w = create_menu_button (ShellWidget, FaceWidget, w,
2672 menus, j - i, "Push face property");
2676 XtSetArg (arg[0], XtNfromHoriz, w);
2677 XtSetArg (arg[1], XtNleft, XawChainLeft);
2678 XtSetArg (arg[2], XtNright, XawChainLeft);
2679 XtSetArg (arg[3], XtNhorizDistance, 10);
2680 XtSetArg (arg[4], XtNlabel, "Pop");
2681 XtSetArg (arg[5], XtNtranslations,
2682 XtParseTranslationTable (pop_face_trans));
2683 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2684 FaceWidget, arg, 6);
2685 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2687 XtSetArg (arg[0], XtNfromHoriz, w);
2688 XtSetArg (arg[1], XtNleft, XawChainLeft);
2689 XtSetArg (arg[2], XtNright, XawChainRight);
2690 XtSetArg (arg[3], XtNlabel, "");
2691 XtSetArg (arg[4], XtNborderWidth, 0);
2692 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2693 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2694 FaceWidget, arg, 6);
2696 XtSetArg (arg[0], XtNborderWidth, 0);
2697 XtSetArg (arg[1], XtNleft, XawChainLeft);
2698 XtSetArg (arg[2], XtNright, XawChainLeft);
2699 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2701 MPlist *plist[11], *pl;
2704 for (i = 0; i < 11; i++) plist[i] = NULL;
2706 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2707 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2709 MSymbol sym = msymbol_exist (langname);
2713 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2715 char *name = msymbol_name (fullname);
2718 if (c >= 'A' && c <= 'Z')
2720 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2724 pl = plist[idx] = mplist ();
2725 for (; mplist_next (pl); pl = mplist_next (pl))
2726 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2728 mplist_push (pl, sym, fullname);
2733 for (i = 0; i < 11; i++)
2736 char *name = alloca (9);
2738 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2741 for (j = 0, pl = plist[i]; mplist_next (pl);
2742 j++, pl = mplist_next (pl))
2743 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2744 msymbol_name (mplist_key (pl)),
2745 LangProc, mplist_key (pl), -1);
2746 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2747 menus, j, "Push language property");
2749 for (i = 0; i < 11; i++)
2751 m17n_object_unref (plist[i]);
2753 XtSetArg (arg[0], XtNfromHoriz, w);
2754 XtSetArg (arg[1], XtNleft, XawChainLeft);
2755 XtSetArg (arg[2], XtNright, XawChainLeft);
2756 XtSetArg (arg[3], XtNhorizDistance, 10);
2757 XtSetArg (arg[4], XtNlabel, "Pop");
2758 XtSetArg (arg[5], XtNtranslations,
2759 XtParseTranslationTable (pop_lang_trans));
2760 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2761 LangWidget, arg, 6);
2762 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2764 XtSetArg (arg[0], XtNfromHoriz, w);
2765 XtSetArg (arg[1], XtNleft, XawChainLeft);
2766 XtSetArg (arg[2], XtNright, XawChainRight);
2767 XtSetArg (arg[3], XtNlabel, "");
2768 XtSetArg (arg[4], XtNborderWidth, 0);
2769 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2770 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2771 LangWidget, arg, 6);
2774 XtSetArg (arg[0], XtNheight, win_height);
2775 XtSetArg (arg[1], XtNwidth, 10);
2776 XtSetArg (arg[2], XtNleft, XawChainLeft);
2777 XtSetArg (arg[3], XtNright, XawChainLeft);
2778 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2780 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2781 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2783 XtSetArg (arg[0], XtNheight, win_height);
2784 XtSetArg (arg[1], XtNwidth, win_width);
2785 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2786 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2787 XtSetArg (arg[4], XtNleft, XawChainLeft);
2788 XtSetArg (arg[5], XtNright, XawChainRight);
2789 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2792 XtSetArg (arg[0], XtNborderWidth, 0);
2793 XtSetArg (arg[1], XtNleft, XawChainLeft);
2794 XtSetArg (arg[2], XtNright, XawChainRight);
2795 XtSetArg (arg[3], XtNresizable, True);
2796 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2797 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2798 TailWidget, arg, 5);
2800 memset (&control, 0, sizeof control);
2801 control.two_dimensional = 1;
2802 control.enable_bidi = 1;
2803 control.anti_alias = 1;
2804 control.min_line_ascent = font_ascent;
2805 control.min_line_descent = font_descent;
2806 control.max_line_width = win_width;
2807 control.with_cursor = 1;
2808 control.cursor_width = 2;
2809 control.partial_update = 1;
2810 control.ignore_formatting_char = 1;
2812 memset (&input_status_control, 0, sizeof input_status_control);
2813 input_status_control.enable_bidi = 1;
2815 XtAppAddActions (context, actions, XtNumber (actions));
2816 XtRealizeWidget (ShellWidget);
2818 win = XtWindow (TextWidget);
2820 XtAppMainLoop (context);
2822 if (current_input_context)
2823 minput_destroy_ic (current_input_context);
2824 for (i = 0; i < num_input_methods; i++)
2825 if (input_method_table[i].im)
2826 minput_close_im (input_method_table[i].im);
2827 m17n_object_unref (frame);
2828 m17n_object_unref (mt);
2829 m17n_object_unref (face_xxx_large);
2830 m17n_object_unref (face_box);
2831 m17n_object_unref (face_courier);
2832 m17n_object_unref (face_helvetica);
2833 m17n_object_unref (face_times);
2834 m17n_object_unref (face_dv_ttyogesh);
2835 m17n_object_unref (face_freesans);
2836 m17n_object_unref (face_freeserif);
2837 m17n_object_unref (face_freemono);
2838 m17n_object_unref (face_default_fontset);
2839 m17n_object_unref (face_no_ctl_fontset);
2840 m17n_object_unref (face_input_status);
2841 m17n_object_unref (face_default);
2842 m17n_object_unref (default_face_list);
2843 m17n_object_unref (selection);
2847 free (fontset_name);
2849 free (input_method_table);
2850 free (InputMethodMenus);
2852 XFreeGC (display, mono_gc);
2853 XFreeGC (display, mono_gc_inv);
2854 XFreeGC (display, gc_inv);
2855 XtUninstallTranslations (form);
2856 XtUninstallTranslations (TextWidget);
2857 XtDestroyWidget (ShellWidget);
2858 XtDestroyApplicationContext (context);
2862 #endif /* not FOR_DOXYGEN */