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.logical_width;
479 CLEAR_AREA (x, cur.y0, cursor.logical_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 UTF8-STRING or
988 COMPOUND-TEXT. It is called when someone requests the current
989 value of the selection. */
991 covert_selection (Widget w, Atom *selection_atom,
992 Atom *target, Atom *return_type,
993 XtPointer *value, unsigned long *length, int *format)
995 unsigned char *buf = (unsigned char *) XtMalloc (4096);
996 MText *this_mt = mtext ();
997 int from = mtext_property_start (selection);
998 int to = mtext_property_end (selection);
1001 mtext_copy (this_mt, 0, mt, from, to);
1002 #ifdef X_HAVE_UTF8_STRING
1003 if (target != XA_COMPOUND_TEXT)
1005 coding = msymbol ("utf-8");
1006 *return_type = XA_UTF8_STRING;
1011 coding = msymbol ("compound-text");
1012 *return_type = XA_COMPOUND_TEXT;
1014 *length = mconv_encode_buffer (coding, this_mt, buf, 4096);
1015 m17n_object_unref (this_mt);
1018 *value = (XtPointer) buf;
1024 /* Unselect the text. It is called when we loose the selection. */
1026 lose_selection (Widget w, Atom *selection_atom)
1030 mtext_detach_property (selection);
1031 redraw (sel_start.y0, sel_end.y1, 1, 0);
1036 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1037 XtPointer value, unsigned long *length, int *format)
1042 if (*type == XT_CONVERT_FAIL || ! value)
1044 if (*type == XA_STRING)
1046 else if (*type == XA_COMPOUND_TEXT)
1047 coding = msymbol ("compound-text");
1048 #ifdef X_HAVE_UTF8_STRING
1049 else if (*type == XA_UTF8_STRING)
1050 coding = msymbol ("utf-8");
1055 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1059 insert_chars (this_mt);
1060 m17n_object_unref (this_mt);
1069 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1071 XExposeEvent *expose = (XExposeEvent *) event;
1075 Dimension width_max, width;
1077 XtSetArg (arg[0], XtNwidth, &width);
1078 XtGetValues (XtParent (w), arg, 1);
1080 XtGetValues (HeadWidget, arg, 1);
1081 if (width_max < width)
1083 XtGetValues (FaceWidget, arg, 1);
1084 if (width_max < width)
1086 XtGetValues (LangWidget, arg, 1);
1087 if (width_max < width)
1089 XtSetArg (arg[0], XtNwidth, width_max);
1090 XtSetValues (HeadWidget, arg, 1);
1091 XtSetValues (FaceWidget, arg, 1);
1092 XtSetValues (LangWidget, arg, 1);
1093 XtSetValues (XtParent (w), arg, 1);
1094 XtSetValues (TailWidget, arg, 1);
1097 update_cursor (0, 1);
1098 redraw (0, win_height, 0, 1);
1103 redraw (expose->y, expose->y + expose->height, 0, 0);
1104 if (current_input_context
1105 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1106 set_input_method_spot ();
1111 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1113 XConfigureEvent *configure = (XConfigureEvent *) event;
1116 control.max_line_width = win_width = configure->width;
1117 win_height = configure->height;
1118 mdraw_clear_cache (mt);
1120 update_cursor (0, 1);
1121 redraw (0, win_height, 1, 1);
1122 if (current_input_context)
1123 set_input_method_spot ();
1127 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1130 int x = event->xbutton.x;
1131 int y = event->xbutton.y - top.ascent;
1133 if (control.orientation_reversed)
1135 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1138 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1139 mtext_detach_property (selection);
1140 redraw (sel_start.y0, sel_end.y1, 1, 0);
1143 update_cursor (pos, 0);
1148 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1153 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1154 covert_selection, lose_selection, NULL);
1155 update_cursor (mtext_property_start (selection), 0);
1160 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1164 /* We don't have a local selection. */
1165 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1170 int from = mtext_property_start (selection);
1171 int to = mtext_property_end (selection);
1174 int x = event->xbutton.x;
1175 int y = event->xbutton.y - top.ascent;
1177 if (control.orientation_reversed)
1179 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1181 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1182 mtext_detach_property (selection);
1184 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1185 update_cursor (pos, 0);
1186 insert_chars (this_mt);
1187 m17n_object_unref (this_mt);
1192 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1195 int x = event->xbutton.x;
1196 int y = event->xbutton.y;
1198 if (control.orientation_reversed)
1201 pos = top.from, y -= top.ascent;
1203 pos = cur.from, y -= cur.y0 + cur.ascent;
1204 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1206 if (pos == cursor.from)
1212 /* Selection range changed. */
1213 int from = mtext_property_start (selection);
1214 int to = mtext_property_end (selection);
1215 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1216 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1218 if (cursor.from == from)
1220 /* Starting position changed. */
1223 /* Enlarged. We can simply overdraw. */
1224 select_region (pos, to);
1225 redraw (sel_start.y0, start_y1, 0, 0);
1229 /* Shrunken. Previous selection face must be cleared. */
1230 select_region (pos, to);
1231 redraw (start_y0, sel_start.y1, 1, 0);
1235 /* Shrunken to zero. */
1236 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1237 mtext_detach_property (selection);
1238 redraw (start_y0, end_y1, 1, 0);
1242 /* Full update is necessary. */
1243 select_region (to, pos);
1244 redraw (start_y0, sel_end.y1, 1, 0);
1249 /* Ending position changed. */
1252 /* Full update is necessary. */
1253 select_region (pos, from);
1254 redraw (sel_start.y0, end_y1, 1, 0);
1256 else if (pos == from)
1258 /* Shrunken to zero. */
1259 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1260 mtext_detach_property (selection);
1261 redraw (start_y0, end_y1, 1, 0);
1265 /* Shrunken. Previous selection face must be cleared. */
1266 select_region (from, pos);
1267 redraw (sel_end.y0, end_y1, 1, 0);
1271 /* Enlarged. We can simply overdraw. */
1272 select_region (from, pos);
1273 redraw (end_y0, sel_end.y1, 0, 0);
1279 /* Newly selected. */
1280 select_region (pos, cursor.from);
1281 redraw (sel_start.y0, sel_end.y1, 0, 0);
1283 update_cursor (pos, 1);
1287 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1290 MDrawGlyphInfo info;
1292 int cursor_pos = cursor.from;
1294 if (((int) position) < 0)
1300 height = top.y1 - top.y0;
1303 pos = bol (from - 1, 0);
1304 GLYPH_INFO (pos, from - 1, info);
1305 if (height + info.this.height > win_height)
1307 height += info.this.height;
1308 from = info.line_from;
1310 if (cursor_pos >= top.to)
1312 cursor_pos = top.from;
1314 while (cursor_pos < nchars)
1316 GLYPH_INFO (pos, pos, info);
1317 if (height + info.this.height > win_height)
1319 height += info.this.height;
1325 else if (cur.to < nchars)
1327 /* Scroll up, but leave at least one line. */
1330 while (from < nchars)
1332 GLYPH_INFO (from, from, info);
1333 if (height + info.this.height > win_height
1334 || info.line_to >= nchars)
1336 height += info.this.height;
1337 from = info.line_to;
1340 from = info.line_from;
1341 if (cursor_pos < from)
1345 /* Scroll up to make the cursor line top. */
1349 update_cursor (cursor_pos, 1);
1353 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1355 float persent = *(float *) persent_ptr;
1356 int pos1, pos2 = nchars * persent;
1357 MDrawGlyphInfo info;
1360 pos1 = bol (pos2, 0);
1361 GLYPH_INFO (pos1, pos2, info);
1362 pos1 = info.line_from;
1364 update_cursor (pos1, 1);
1369 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1371 XKeyEvent *key_event = (XKeyEvent *) event;
1373 KeySym keysym = NoSymbol;
1375 /* If set to 1, do not update target_x_position. */
1376 int keep_target_x_position = 0;
1379 if (current_input_context
1380 && minput_filter (current_input_context, Mnil, event))
1382 if (event->type == KeyRelease)
1387 produced = mtext ();
1388 ret = minput_lookup (current_input_context, Mnil, event, produced);
1389 if (mtext_len (produced) > 0)
1390 insert_chars (produced);
1392 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1393 m17n_object_unref (produced);
1403 n = (mtext_property_end (selection)
1404 - mtext_property_start (selection));
1405 mtext_detach_property (selection);
1407 else if (cursor.from < nchars)
1409 /* Delete the following grapheme cluster. */
1410 n = cursor.to - cursor.from;
1423 /* Delete selected region. */
1424 n = (mtext_property_end (selection)
1425 - mtext_property_start (selection));
1426 mtext_detach_property (selection);
1428 else if (cursor.from > 0)
1430 /* Delete the preceding character. */
1441 mtext_detach_property (selection);
1442 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1446 if (cursor.prev_from >= 0)
1447 update_cursor (cursor.prev_from, 0);
1451 if (cursor.left_from >= 0)
1452 update_cursor (cursor.left_from, 0);
1459 mtext_detach_property (selection);
1460 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1464 if (cursor.next_to >= 0)
1465 update_cursor (cursor.to, 0);
1469 if (cursor.right_from >= 0)
1470 update_cursor (cursor.right_from, 0);
1477 mtext_detach_property (selection);
1478 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1480 if (cur.to <= nchars)
1482 MDrawGlyphInfo info;
1485 GLYPH_INFO (cur.from, cur.to, info);
1486 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1487 target_x_position, info.y);
1488 keep_target_x_position = 1;
1489 update_cursor (pos, 0);
1496 mtext_detach_property (selection);
1497 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1503 int pos = bol (cur.from - 1, 0);
1505 TEXT_EXTENTS (pos, cur.from - 1, rect);
1506 y = rect.height + rect.y - 1;
1507 pos = COORDINATES_POSITION (pos, nchars,
1508 target_x_position, y);
1509 keep_target_x_position = 1;
1510 update_cursor (pos, 0);
1517 mtext_detach_property (selection);
1518 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1520 if (top.from < nchars)
1521 ScrollProc (w, NULL, (XtPointer) 1);
1527 mtext_detach_property (selection);
1528 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1531 ScrollProc (w, NULL, (XtPointer) -1);
1537 if (buf[0] == 17) /* C-q */
1539 XtAppSetExitFlag (context);
1542 else if (buf[0] == 12) /* C-l */
1544 redraw (0, win_height, 1, 1);
1549 MText *temp = mtext ();
1551 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1552 if (current_input_context)
1553 mtext_put_prop (temp, 0, 1, Mlanguage,
1554 current_input_context->im->language);
1555 insert_chars (temp);
1556 m17n_object_unref (temp);
1561 if (! keep_target_x_position)
1562 target_x_position = cursor.x;
1566 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1568 char *name = (char *) client_data;
1570 int from = -1, to = 0;
1575 filename = strdup (name);
1578 fp = fopen (filename, "w");
1581 fprintf (stderr, "Open for write fail: %s", filename);
1587 from = mtext_property_start (selection);
1588 to = mtext_property_end (selection);
1589 mtext_detach_property (selection);
1592 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1595 select_region (from, to);
1599 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1605 mtext_detach_property (selection);
1606 serialized = (int) client_data;
1608 new = mtext_deserialize (mt);
1611 MPlist *plist = mplist ();
1613 mplist_push (plist, Mt, Mface);
1614 mplist_push (plist, Mt, Mlanguage);
1615 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1616 m17n_object_unref (plist);
1620 m17n_object_unref (mt);
1622 serialized = ! serialized;
1623 nchars = mtext_len (mt);
1626 update_cursor (0, 1);
1627 redraw (0, win_height, 1, 1);
1631 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1633 XtAppSetExitFlag (context);
1639 FILE *fp = fopen (filename, "r");
1642 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1643 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1646 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1651 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1653 int data = (int) client_data;
1658 control.enable_bidi = 0;
1659 control.orientation_reversed = 0;
1663 control.enable_bidi = 1;
1664 control.orientation_reversed = data == 2;
1666 for (i = 0; i < 3; i++)
1669 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1671 XtSetArg (arg[0], XtNleftBitmap, None);
1672 XtSetValues (BidiMenus[i], arg, 1);
1675 update_cursor (cursor.from, 1);
1676 redraw (0, win_height, 1, 0);
1679 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1682 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1684 int data = (int) client_data;
1688 control.max_line_width = 0;
1691 control.max_line_width = win_width;
1692 control.line_break = (data == 1 ? NULL : line_break);
1694 for (i = 0; i < 3; i++)
1697 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1699 XtSetArg (arg[0], XtNleftBitmap, None);
1700 XtSetValues (LineBreakMenus[i], arg, 1);
1703 update_cursor (cursor.from, 1);
1704 redraw (0, win_height, 1, 0);
1708 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1710 int data = (int) client_data;
1724 control.cursor_bidi = 0, control.cursor_width = -1;
1728 control.cursor_bidi = 0, control.cursor_width = 2;
1732 control.cursor_bidi = 1;
1737 for (i = from; i < to; i++)
1740 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1742 XtSetArg (arg[0], XtNleftBitmap, None);
1743 XtSetValues (CursorMenus[i], arg, 1);
1746 redraw (0, win_height, 1, 0);
1750 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1752 int idx = (int) client_data;
1754 if (idx == -2 ? current_input_method < 0
1755 : idx == -1 ? auto_input_method
1756 : idx == current_input_method)
1759 XtSetArg (arg[0], XtNleftBitmap, None);
1760 if (auto_input_method)
1762 XtSetValues (InputMethodMenus[1], arg, 1);
1763 auto_input_method = 0;
1765 else if (current_input_method < 0)
1766 XtSetValues (InputMethodMenus[0], arg, 1);
1768 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1772 auto_input_method = 1;
1775 else if (input_method_table[idx].available >= 0)
1777 if (! input_method_table[idx].im)
1779 input_method_table[idx].im =
1780 minput_open_im (input_method_table[idx].language,
1781 input_method_table[idx].name, NULL);
1782 if (! input_method_table[idx].im)
1783 input_method_table[idx].available = -1;
1785 if (input_method_table[idx].im)
1786 select_input_method (idx);
1788 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1789 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1792 MPlist *default_face_list;
1795 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1797 int idx = (int) client_data;
1807 MFace *face = mframe_get_prop (frame, Mface);
1809 for (plist = default_face_list; mplist_key (plist) != Mnil;
1810 plist = mplist_next (plist))
1811 mface_merge (face, mplist_value (plist));
1812 mplist_add (plist, Mt, *face_table[idx].face);
1813 mface_merge (face, *face_table[idx].face);
1815 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1817 MFace *face = mframe_get_prop (frame, Mface);
1819 for (plist = default_face_list;
1820 mplist_key (mplist_next (plist)) != Mnil;
1821 plist = mplist_next (plist))
1822 mface_merge (face, mplist_value (plist));
1826 update_cursor (0, 1);
1827 redraw (0, win_height, 1, 1);
1832 XtAppAddWorkProc (context, show_cursor, NULL);
1833 from = mtext_property_start (selection);
1834 to = mtext_property_end (selection);
1835 old_y1 = sel_end.y1;
1837 mtext_detach_property (selection);
1840 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1841 MTEXTPROP_REAR_STICKY);
1842 mtext_push_property (mt, from, to, prop);
1843 m17n_object_unref (prop);
1846 mtext_pop_prop (mt, from, to, Mface);
1848 update_top (top.from);
1849 update_cursor (cursor.from, 1);
1850 select_region (from, to);
1851 update_region (sel_start.y0, old_y1, sel_end.y1);
1852 if (cur.y1 > win_height)
1854 while (cur.y1 > win_height)
1857 update_cursor (cursor.from, 1);
1863 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1865 MSymbol sym = (MSymbol) client_data;
1872 XtAppAddWorkProc (context, show_cursor, NULL);
1873 from = mtext_property_start (selection);
1874 to = mtext_property_end (selection);
1875 old_y1 = sel_end.y1;
1877 mtext_detach_property (selection);
1879 mtext_put_prop (mt, from, to, Mlanguage, sym);
1881 mtext_pop_prop (mt, from, to, Mlanguage);
1884 update_top (top.from);
1885 update_cursor (cursor.from, 1);
1886 select_region (from, to);
1887 update_region (sel_start.y0, old_y1, sel_end.y1);
1888 if (cur.y1 > win_height)
1890 while (cur.y1 > win_height)
1893 update_cursor (cursor.from, 1);
1899 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1901 int narrowed = (int) client_data;
1904 MConverter *converter;
1910 from = mtext_property_start (selection);
1911 to = mtext_property_end (selection);
1920 mdump = popen ("mdump -q -p a4", "w");
1922 mdump = popen ("mdump -q", "w");
1925 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1926 mconv_encode_range (converter, mt, from, to);
1927 mconv_free_converter (converter);
1932 input_status (MInputContext *ic, MSymbol command)
1934 XFillRectangle (display, input_status_pixmap, gc_inv,
1935 0, 0, input_status_width, input_status_height);
1936 if (command == Minput_status_draw)
1940 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1941 Mface, face_input_status);
1942 if (ic->im->language != Mnil)
1943 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1944 Mlanguage, ic->im->language);
1945 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1946 &input_status_control, NULL, NULL, &rect);
1947 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1948 input_status_width - rect.width - 2, - rect.y,
1949 ic->status, 0, mtext_len (ic->status),
1950 &input_status_control);
1952 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1953 XtSetValues (CurIMStatus, arg, 1);
1957 compare_input_method (const void *elt1, const void *elt2)
1959 const InputMethodInfo *im1 = elt1;
1960 const InputMethodInfo *im2 = elt2;
1961 MSymbol lang1, lang2;
1963 if (im1->language == Mnil)
1965 if (im1->language == im2->language)
1966 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1967 if (im1->language == Mt)
1969 if (im2->language == Mt)
1971 lang1 = msymbol_get (im1->language, Mlanguage);
1972 lang2 = msymbol_get (im2->language, Mlanguage);
1973 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1977 setup_input_methods (int with_xim)
1979 MInputMethod *im = NULL;
1980 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1984 num_input_methods = mplist_length (plist);
1988 MInputXIMArgIM arg_xim;
1990 arg_xim.display = display;
1992 arg_xim.res_name = arg_xim.res_class = NULL;
1993 arg_xim.locale = NULL;
1994 arg_xim.modifier_list = NULL;
1995 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1997 num_input_methods++;
1999 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2002 input_method_table[i].available = 1;
2003 input_method_table[i].language = Mnil;
2004 input_method_table[i].name = im->name;
2005 input_method_table[i].im = im;
2009 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2011 MDatabase *mdb = mplist_value (pl);
2012 MSymbol *tag = mdatabase_tag (mdb);
2016 input_method_table[i].language = tag[1];
2017 input_method_table[i].name = tag[2];
2022 m17n_object_unref (plist);
2023 num_input_methods = i;
2024 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2025 compare_input_method);
2026 current_input_context = NULL;
2028 mplist_put (minput_driver->callback_list, Minput_status_start,
2029 (void *) input_status);
2030 mplist_put (minput_driver->callback_list, Minput_status_draw,
2031 (void *) input_status);
2032 mplist_put (minput_driver->callback_list, Minput_status_done,
2033 (void *) input_status);
2038 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2042 if (num && *num > 0)
2046 for (i = 0; i < *num; i++)
2047 bytes += strlen (str[i]) + 1;
2048 msg = alloca (bytes);
2049 strcpy (msg, str[0]);
2050 for (i = 1; i < *num; i++)
2051 strcat (msg, " "), strcat (msg, str[i]);
2053 else if (cursor.from < nchars)
2055 int c = mtext_ref_char (mt, cursor.from);
2056 char *name = mchar_get_prop (c, Mname);
2060 msg = alloca (10 + strlen (name));
2061 sprintf (msg, "U+%04X %s", c, name);
2067 XtSetArg (arg[0], XtNlabel, msg);
2068 XtSetValues (MessageWidget, arg, 1);
2074 char *name1, *name2;
2075 XtCallbackProc proc;
2076 XtPointer client_data;
2081 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2083 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2085 MenuRec FileMenu[] =
2086 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2087 { 0, "Save", NULL, SaveProc, NULL, -1 },
2088 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2090 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2091 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2093 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2094 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2096 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2099 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2101 MenuRec *rec = (MenuRec *) client_data;
2104 XtSetArg (arg[0], XtNvalue, "");
2105 XtSetArg (arg[1], XtNlabel, rec->name1);
2106 XtSetValues (FileDialogWidget, arg, 2);
2107 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2108 XtSetArg (arg[0], XtNx, x + 20);
2109 XtSetArg (arg[1], XtNy, y + 10);
2110 XtSetValues (FileShellWidget, arg, 2);
2111 XtPopup (FileShellWidget, XtGrabExclusive);
2115 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2120 XtPopdown (FileShellWidget);
2121 if ((int) client_data == 1)
2123 XtSetArg (arg[0], XtNlabel, &label);
2124 XtGetValues (FileDialogWidget, arg, 1);
2125 if (strcmp (label, FileMenu[0].name1) == 0)
2129 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2130 fp = fopen (filename, "r");
2132 m17n_object_unref (mt);
2135 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2143 nchars = mtext_len (mt);
2145 update_cursor (0, 1);
2146 redraw (0, win_height, 1, 1);
2148 else if (strcmp (label, FileMenu[2].name1) == 0)
2149 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2151 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2154 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2155 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2156 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2157 (MENU).status = (STATUS))
2161 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2162 char *menu_name, MenuRec *menus, int num_menus, char *help)
2164 Widget button, menu;
2165 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2166 <LeaveWindow>: reset() MenuHelp()\n\
2167 <BtnDown>: reset() PopupMenu()\n\
2168 <BtnUp>: highlight()";
2174 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2175 for (i = 0; i < num_menus; i++)
2186 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2188 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2190 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2192 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2196 XtSetArg (arg[0], XtNsensitive, False);
2197 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2203 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2208 trans = alloca (strlen (fmt) + strlen (help));
2209 sprintf (trans, fmt, help);
2210 XtSetArg (arg[0], XtNmenuName, menu_name);
2211 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2212 XtSetArg (arg[2], XtNinternalWidth, 2);
2213 XtSetArg (arg[3], XtNhighlightThickness, 1);
2214 XtSetArg (arg[4], XtNleft, XawChainLeft);
2215 XtSetArg (arg[5], XtNright, XawChainLeft);
2218 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2219 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2224 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2225 int *len = alloca (sizeof (int) * num_menus);
2228 XFontSetExtents *fontset_extents;
2230 XtSetArg (arg[0], XtNfontSet, &font_set);
2231 XtGetValues (button, arg, 1);
2233 fontset_extents = XExtentsOfFontSet (font_set);
2234 height = fontset_extents->max_logical_extent.height;
2235 ascent = - fontset_extents->max_logical_extent.y;
2237 for (i = 0; i < num_menus; i++)
2240 len[i] = strlen (menus[i].name2);
2241 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2242 if (max_width < width[i])
2243 max_width = width[i];
2245 for (i = 0; i < num_menus; i++)
2248 Pixmap pixmap = XCreatePixmap (display,
2249 RootWindow (display, screen),
2250 max_width, height, 1);
2251 XFillRectangle (display, pixmap, mono_gc_inv,
2252 0, 0, max_width, height);
2253 XmbDrawString (display, pixmap, font_set, mono_gc,
2254 max_width - width[i], ascent,
2255 menus[i].name2, len[i]);
2256 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2257 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2258 XtSetValues (menus[i].w, arg, 2);
2266 XtActionsRec actions[] = {
2267 {"Expose", ExposeProc},
2268 {"Configure", ConfigureProc},
2270 {"ButtonPress", ButtonProc},
2271 {"ButtonRelease", ButtonReleaseProc},
2272 {"ButtonMotion", ButtonMoveProc},
2273 {"Button2Press", Button2Proc},
2274 {"MenuHelp", MenuHelpProc}
2278 /* Print the usage of this program (the name is PROG), and exit with
2282 help_exit (char *prog, int exit_code)
2290 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2291 printf ("Display FILE on a window and allow users to edit it.\n");
2292 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2293 printf ("The following OPTIONs are available.\n");
2294 printf (" %-13s %s", "--version", "print version number\n");
2295 printf (" %-13s %s", "-h, --help", "print this message\n");
2300 main (int argc, char **argv)
2302 Widget form, BodyWidget, w;
2303 char *fontset_name = NULL;
2304 int col = 80, row = 32;
2305 /* Translation table for TextWidget. */
2306 String trans = "<Expose>: Expose()\n\
2307 <Configure>: Configure()\n\
2310 <Btn1Down>: ButtonPress()\n\
2311 <Btn1Up>: ButtonRelease()\n\
2312 <Btn1Motion>: ButtonMotion()\n\
2313 <Btn2Down>: Button2Press()";
2314 /* Translation table for the top form widget. */
2315 String trans2 = "<Key>: Key()\n\
2317 String pop_face_trans
2318 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2319 <LeaveWindow>: MenuHelp() reset()\n\
2320 <Btn1Down>: set()\n\
2321 <Btn1Up>: notify() unset()";
2322 String pop_lang_trans
2323 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2324 <LeaveWindow>: MenuHelp() reset()\n\
2325 <Btn1Down>: set()\n\
2326 <Btn1Up>: notify() unset()";
2327 int font_width, font_ascent, font_descent;
2331 setlocale (LC_ALL, "");
2332 /* Create the top shell. */
2333 XtSetLanguageProc (NULL, NULL, NULL);
2334 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2335 NULL, sessionShellWidgetClass, NULL, 0);
2336 display = XtDisplay (ShellWidget);
2337 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2339 /* Parse the remaining command line arguments. */
2340 for (i = 1; i < argc; i++)
2342 if (! strcmp (argv[i], "--help")
2343 || ! strcmp (argv[i], "-h"))
2344 help_exit (argv[0], 0);
2345 else if (! strcmp (argv[i], "--version"))
2347 printf ("medit (m17n library) %s\n", VERSION);
2348 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2351 else if (! strcmp (argv[i], "--geometry"))
2354 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2355 help_exit (argv[0], 1);
2357 else if (! strcmp (argv[i], "--fontset"))
2360 fontset_name = strdup (argv[i]);
2362 else if (! strcmp (argv[i], "--with-xim"))
2366 else if (argv[i][0] != '-')
2368 filename = strdup (argv[i]);
2372 fprintf (stderr, "Unknown option: %s", argv[i]);
2373 help_exit (argv[0], 1);
2377 help_exit (argv[0], 1);
2379 mdatabase_dir = ".";
2380 /* Initialize the m17n library. */
2382 if (merror_code != MERROR_NONE)
2383 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2385 mt = read_file (filename);
2388 nchars = mtext_len (mt);
2391 MFace *face = mface ();
2393 mface_put_prop (face, Mforeground, msymbol ("blue"));
2394 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2395 mface_put_prop (face, Mvideomode, Mreverse);
2396 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2397 m17n_object_unref (face);
2400 /* This tells ExposeProc to initialize everything. */
2403 XA_TEXT = XInternAtom (display, "TEXT", False);
2404 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2405 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2407 MPlist *plist = mplist ();
2411 mplist_put (plist, msymbol ("widget"), ShellWidget);
2414 MFontset *fontset = mfontset (fontset_name);
2417 mface_put_prop (face, Mfontset, fontset);
2418 m17n_object_unref (fontset);
2419 mplist_add (plist, Mface, face);
2420 m17n_object_unref (face);
2422 frame = mframe (plist);
2423 m17n_object_unref (plist);
2424 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2425 default_face_list = mplist ();
2426 mplist_add (default_face_list, Mt, face_default);
2427 face_default_fontset = mface ();
2428 mface_put_prop (face_default_fontset, Mfontset,
2429 mface_get_prop (face_default, Mfontset));
2431 font = (MFont *) mframe_get_prop (frame, Mfont);
2432 default_font_size = (int) mfont_get_prop (font, Msize);
2435 font_width = (int) mframe_get_prop (frame, Mfont_width);
2436 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2437 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2438 win_width = font_width * col;
2439 win_height = (font_ascent + font_descent) * row;
2445 prop.color_top = prop.color_left = msymbol ("magenta");
2446 prop.color_bottom = prop.color_right = msymbol ("red");
2447 prop.inner_hmargin = prop.inner_vmargin = 1;
2448 prop.outer_hmargin = prop.outer_vmargin = 2;
2450 face_box = mface ();
2451 mface_put_prop (face_box, Mbox, &prop);
2454 face_courier = mface ();
2455 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2456 face_helvetica = mface ();
2457 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2458 face_times = mface ();
2459 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2460 face_dv_ttyogesh = mface ();
2461 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2462 face_freesans = mface ();
2463 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2464 face_freeserif = mface ();
2465 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2466 face_freemono = mface ();
2467 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2469 face_xxx_large = mface ();
2470 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2472 MFont *latin_font = mframe_get_prop (frame, Mfont);
2473 MFont *dev_font = mfont ();
2474 MFont *thai_font = mfont ();
2475 MFont *tib_font = mfont ();
2477 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2478 MSymbol no_ctl = msymbol ("no-ctl");
2480 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2481 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2482 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2483 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2484 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2485 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2487 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2488 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2489 latin_font, Mnil, 0);
2490 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2491 dev_font, no_ctl, 0);
2492 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2493 thai_font, no_ctl, 0);
2494 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2495 tib_font, no_ctl, 0);
2496 face_no_ctl_fontset = mface ();
2497 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2498 m17n_object_unref (fontset);
2505 setup_input_methods (with_xim);
2507 gc = DefaultGC (display, screen);
2509 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2510 XtSetArg (arg[1], XtNdefaultDistance, 2);
2511 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2513 XtSetArg (arg[0], XtNborderWidth, 0);
2514 XtSetArg (arg[1], XtNdefaultDistance, 2);
2515 XtSetArg (arg[2], XtNtop, XawChainTop);
2516 XtSetArg (arg[3], XtNbottom, XawChainTop);
2517 XtSetArg (arg[4], XtNleft, XawChainLeft);
2518 XtSetArg (arg[5], XtNright, XawChainRight);
2519 XtSetArg (arg[6], XtNresizable, True);
2520 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2521 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2522 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2523 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2524 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2525 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2526 XtSetArg (arg[7], XtNfromVert, LangWidget);
2527 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2528 XtSetArg (arg[2], XtNtop, XawChainBottom);
2529 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2530 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2532 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2533 HeadWidget, NULL, 0);
2534 XtSetArg (arg[0], XtNvalue, "");
2535 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2536 FileShellWidget, arg, 1);
2537 XawDialogAddButton (FileDialogWidget, "OK",
2538 FileDialogProc, (XtPointer) 0);
2539 XawDialogAddButton (FileDialogWidget, "CANCEL",
2540 FileDialogProc, (XtPointer) 1);
2542 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2543 (char *) check_bits,
2544 check_width, check_height);
2546 unsigned long valuemask = GCForeground;
2549 values.foreground = 1;
2550 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2551 values.foreground = 0;
2552 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2559 if (num_menus < num_input_methods + 2)
2560 num_menus = num_input_methods + 2;
2561 if (num_menus < num_faces + 1)
2562 num_menus = num_faces + 1;
2563 menus = alloca (sizeof (MenuRec) * num_menus);
2565 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2566 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2567 "File I/O, Serialization, Image, Quit");
2569 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2570 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2571 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2572 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2573 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2574 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2575 w = create_menu_button (ShellWidget, HeadWidget, w,
2576 "Cursor", "Cursor Menu",
2577 menus, 6, "Cursor Movement Mode, Cursor Shape");
2578 CursorMenus[0] = menus[0].w;
2579 CursorMenus[1] = menus[1].w;
2580 CursorMenus[2] = menus[3].w;
2581 CursorMenus[3] = menus[4].w;
2582 CursorMenus[4] = menus[5].w;
2584 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2585 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2586 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2587 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2588 menus, 3, "BIDI Processing Mode");
2589 for (i = 0; i < 3; i++)
2590 BidiMenus[i] = menus[i].w;
2592 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2593 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2594 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2595 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2597 menus, 3, "How to break lines");
2598 for (i = 0; i < 3; i++)
2599 LineBreakMenus[i] = menus[i].w;
2601 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2602 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2603 for (i = 0; i < num_input_methods; i++)
2605 InputMethodInfo *im = input_method_table + i;
2606 char *name1, *name2;
2608 if (im->language != Mnil && im->language != Mt)
2610 MSymbol sym = msymbol_get (im->language, Mlanguage);
2612 name1 = msymbol_name (im->language);
2614 name1 = msymbol_name (sym);
2615 name2 = msymbol_name (im->name);
2618 name1 = msymbol_name (im->name), name2 = NULL;
2620 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2622 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2623 "Input Method Menu", menus, i + 2,
2624 "Select input method");
2627 unsigned long valuemask = GCForeground;
2630 XtSetArg (arg[0], XtNbackground, &values.foreground);
2631 XtGetValues (w, arg, 1);
2632 gc_inv = XCreateGC (display, RootWindow (display, screen),
2633 valuemask, &values);
2636 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2637 for (i = 0; i < num_input_methods + 2; i++)
2638 InputMethodMenus[i] = menus[i].w;
2640 input_status_width = font_width * 8;
2641 input_status_height = (font_ascent + font_descent) * 2.4;
2642 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2644 input_status_height,
2645 DefaultDepth (display, screen));
2650 prop.color_top = prop.color_bottom
2651 = prop.color_left = prop.color_right = Mnil;
2652 prop.inner_hmargin = prop.inner_vmargin = 1;
2653 prop.outer_hmargin = prop.outer_vmargin = 0;
2654 face_input_status = mface_copy (face_default);
2655 mface_put_prop (face_input_status, Mbox, &prop);
2658 XFillRectangle (display, input_status_pixmap, gc_inv,
2659 0, 0, input_status_width, input_status_height);
2660 XtSetArg (arg[0], XtNfromHoriz, w);
2661 XtSetArg (arg[1], XtNleft, XawRubber);
2662 XtSetArg (arg[2], XtNright, XawChainRight);
2663 XtSetArg (arg[3], XtNborderWidth, 0);
2664 XtSetArg (arg[4], XtNlabel, " ");
2665 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2666 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2667 HeadWidget, arg, 6);
2668 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2669 XtSetArg (arg[1], XtNleft, XawChainRight);
2670 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2671 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2672 HeadWidget, arg, 5);
2674 XtSetArg (arg[0], XtNborderWidth, 0);
2675 XtSetArg (arg[1], XtNleft, XawChainLeft);
2676 XtSetArg (arg[2], XtNright, XawChainLeft);
2677 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2678 for (i = 0; i < num_faces;)
2680 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2681 char *label = label_menu + 5; /* "Xxxx" */
2683 for (j = i; j < num_faces && face_table[j].face; j++)
2684 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2686 w = create_menu_button (ShellWidget, FaceWidget, w,
2688 menus, j - i, "Push face property");
2692 XtSetArg (arg[0], XtNfromHoriz, w);
2693 XtSetArg (arg[1], XtNleft, XawChainLeft);
2694 XtSetArg (arg[2], XtNright, XawChainLeft);
2695 XtSetArg (arg[3], XtNhorizDistance, 10);
2696 XtSetArg (arg[4], XtNlabel, "Pop");
2697 XtSetArg (arg[5], XtNtranslations,
2698 XtParseTranslationTable (pop_face_trans));
2699 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2700 FaceWidget, arg, 6);
2701 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2703 XtSetArg (arg[0], XtNfromHoriz, w);
2704 XtSetArg (arg[1], XtNleft, XawChainLeft);
2705 XtSetArg (arg[2], XtNright, XawChainRight);
2706 XtSetArg (arg[3], XtNlabel, "");
2707 XtSetArg (arg[4], XtNborderWidth, 0);
2708 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2709 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2710 FaceWidget, arg, 6);
2712 XtSetArg (arg[0], XtNborderWidth, 0);
2713 XtSetArg (arg[1], XtNleft, XawChainLeft);
2714 XtSetArg (arg[2], XtNright, XawChainLeft);
2715 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2717 MPlist *plist[11], *pl;
2720 for (i = 0; i < 11; i++) plist[i] = NULL;
2722 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2723 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2725 MSymbol sym = msymbol_exist (langname);
2729 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2731 char *name = msymbol_name (fullname);
2734 if (c >= 'A' && c <= 'Z')
2736 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2740 pl = plist[idx] = mplist ();
2741 for (; mplist_next (pl); pl = mplist_next (pl))
2742 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2744 mplist_push (pl, sym, fullname);
2749 for (i = 0; i < 11; i++)
2752 char *name = alloca (9);
2754 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2757 for (j = 0, pl = plist[i]; mplist_next (pl);
2758 j++, pl = mplist_next (pl))
2759 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2760 msymbol_name (mplist_key (pl)),
2761 LangProc, mplist_key (pl), -1);
2762 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2763 menus, j, "Push language property");
2765 for (i = 0; i < 11; i++)
2767 m17n_object_unref (plist[i]);
2769 XtSetArg (arg[0], XtNfromHoriz, w);
2770 XtSetArg (arg[1], XtNleft, XawChainLeft);
2771 XtSetArg (arg[2], XtNright, XawChainLeft);
2772 XtSetArg (arg[3], XtNhorizDistance, 10);
2773 XtSetArg (arg[4], XtNlabel, "Pop");
2774 XtSetArg (arg[5], XtNtranslations,
2775 XtParseTranslationTable (pop_lang_trans));
2776 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2777 LangWidget, arg, 6);
2778 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2780 XtSetArg (arg[0], XtNfromHoriz, w);
2781 XtSetArg (arg[1], XtNleft, XawChainLeft);
2782 XtSetArg (arg[2], XtNright, XawChainRight);
2783 XtSetArg (arg[3], XtNlabel, "");
2784 XtSetArg (arg[4], XtNborderWidth, 0);
2785 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2786 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2787 LangWidget, arg, 6);
2790 XtSetArg (arg[0], XtNheight, win_height);
2791 XtSetArg (arg[1], XtNwidth, 10);
2792 XtSetArg (arg[2], XtNleft, XawChainLeft);
2793 XtSetArg (arg[3], XtNright, XawChainLeft);
2794 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2796 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2797 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2799 XtSetArg (arg[0], XtNheight, win_height);
2800 XtSetArg (arg[1], XtNwidth, win_width);
2801 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2802 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2803 XtSetArg (arg[4], XtNleft, XawChainLeft);
2804 XtSetArg (arg[5], XtNright, XawChainRight);
2805 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2808 XtSetArg (arg[0], XtNborderWidth, 0);
2809 XtSetArg (arg[1], XtNleft, XawChainLeft);
2810 XtSetArg (arg[2], XtNright, XawChainRight);
2811 XtSetArg (arg[3], XtNresizable, True);
2812 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2813 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2814 TailWidget, arg, 5);
2816 memset (&control, 0, sizeof control);
2817 control.two_dimensional = 1;
2818 control.enable_bidi = 1;
2819 control.anti_alias = 1;
2820 control.min_line_ascent = font_ascent;
2821 control.min_line_descent = font_descent;
2822 control.max_line_width = win_width;
2823 control.with_cursor = 1;
2824 control.cursor_width = 2;
2825 control.partial_update = 1;
2826 control.ignore_formatting_char = 1;
2828 memset (&input_status_control, 0, sizeof input_status_control);
2829 input_status_control.enable_bidi = 1;
2831 XtAppAddActions (context, actions, XtNumber (actions));
2832 XtRealizeWidget (ShellWidget);
2834 win = XtWindow (TextWidget);
2836 XtAppMainLoop (context);
2838 if (current_input_context)
2839 minput_destroy_ic (current_input_context);
2840 for (i = 0; i < num_input_methods; i++)
2841 if (input_method_table[i].im)
2842 minput_close_im (input_method_table[i].im);
2843 m17n_object_unref (frame);
2844 m17n_object_unref (mt);
2845 m17n_object_unref (face_xxx_large);
2846 m17n_object_unref (face_box);
2847 m17n_object_unref (face_courier);
2848 m17n_object_unref (face_helvetica);
2849 m17n_object_unref (face_times);
2850 m17n_object_unref (face_dv_ttyogesh);
2851 m17n_object_unref (face_freesans);
2852 m17n_object_unref (face_freeserif);
2853 m17n_object_unref (face_freemono);
2854 m17n_object_unref (face_default_fontset);
2855 m17n_object_unref (face_no_ctl_fontset);
2856 m17n_object_unref (face_input_status);
2857 m17n_object_unref (face_default);
2858 m17n_object_unref (default_face_list);
2859 m17n_object_unref (selection);
2863 free (fontset_name);
2865 free (input_method_table);
2866 free (InputMethodMenus);
2868 XFreeGC (display, mono_gc);
2869 XFreeGC (display, mono_gc_inv);
2870 XFreeGC (display, gc_inv);
2871 XtUninstallTranslations (form);
2872 XtUninstallTranslations (TextWidget);
2873 XtDestroyWidget (ShellWidget);
2874 XtDestroyApplicationContext (context);
2878 #endif /* not FOR_DOXYGEN */