1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 @enpage medit edit multilingual text
26 @section medit-synopsis SYNOPSIS
28 medit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section medit-description DESCRIPTION
32 Display FILE on a window and allow users to edit it.
34 XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).
36 The following OPTIONs are available.
50 This program is to demonstrate how to use the m17n GUI API.
51 Although medit directly uses the GUI API, the API is mainly for
52 toolkit libraries or to implement XOM (X Outout Method), not for
53 direct use from application programs.
56 @japage medit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section medit-synopsis SYNOPSIS
60 medit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section medit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£medit ¤Ïľ
83 ÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é¥ê¤ä
84 XOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é ¥à
85 ¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
99 #include <X11/keysym.h>
100 #include <X11/Xatom.h>
101 #include <X11/Intrinsic.h>
102 #include <X11/StringDefs.h>
103 #include <X11/Shell.h>
104 #include <X11/Xaw/Command.h>
105 #include <X11/Xaw/Box.h>
106 #include <X11/Xaw/Form.h>
107 #include <X11/Xaw/Dialog.h>
108 #include <X11/Xaw/Scrollbar.h>
109 #include <X11/Xaw/Toggle.h>
110 #include <X11/Xaw/SimpleMenu.h>
111 #include <X11/Xaw/SmeBSB.h>
112 #include <X11/Xaw/SmeLine.h>
113 #include <X11/Xaw/MenuButton.h>
115 #include <m17n-gui.h>
116 #include <m17n-misc.h>
119 #define VERSION "1.0.1"
121 /* Global variables. */
126 /* For the X Window System. */
129 /* GCs for normal drawing, filling by background color, normal drawing
130 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
132 GC gc, gc_inv, mono_gc, mono_gc_inv;
134 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
135 XtAppContext context;
136 int default_font_size;
140 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
141 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
142 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
143 +- Body -- Sbar, Text
147 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
148 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
149 Widget SbarWidget, TextWidget;
150 Widget FileShellWidget, FileDialogWidget;
151 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
152 Widget CurIMLang, CurIMStatus;
154 int win_width, win_height; /* Size of TextWidget. */
157 Pixmap input_status_pixmap;
158 int input_status_width, input_status_height;
160 /* Bitmap for "check" glyph. */
161 #define check_width 9
162 #define check_height 8
163 static unsigned char check_bits[] = {
164 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
165 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
168 /* For the m17n library. */
171 int nchars; /* == mtext_len (mt) */
172 MDrawControl control, input_status_control;
173 MTextProperty *selection;
176 MFace *face_xxx_large;
178 MFace *face_courier, *face_helvetica, *face_times;
179 MFace *face_dv_ttyogesh, *face_freesans, *face_freemono;
180 MFace *face_default_fontset, *face_no_ctl_fontset;
181 MFace *face_input_status;
183 int logical_move = 1; /* If 0, move cursor visually. */
185 MInputMethod **input_method_table;
186 int num_input_methods;
187 int current_input_method = -1; /* i.e. none */
188 int auto_input_method = 0;
189 MInputContext *current_input_context;
196 { {"Menu Size", NULL},
197 {"xx-small", &mface_xx_small},
198 {"x-small", &mface_x_small},
199 {"small", &mface_small},
200 {"normalsize", &mface_normalsize},
201 {"large", &mface_large},
202 {"x-large", &mface_x_large},
203 {"xx-large", &mface_xx_large},
204 {"xxx-large", &face_xxx_large},
206 {"Menu Family", NULL},
207 {"courier", &face_courier},
208 {"helvetica", &face_helvetica},
209 {"times", &face_times},
210 {"dv-ttyogesh", &face_dv_ttyogesh},
211 {"freesans", &face_freesans},
212 {"freemono", &face_freemono},
214 {"Menu Style", NULL},
215 {"medium", &mface_medium},
216 {"bold", &mface_bold},
217 {"italic", &mface_italic},
219 {"Menu Color", NULL},
220 {"black", &mface_black},
221 {"white", &mface_white},
223 {"green", &mface_green},
224 {"blue", &mface_blue},
225 {"cyan", &mface_cyan},
226 {"yello", &mface_yellow},
227 {"magenta", &mface_magenta},
230 {"normal", &mface_normal_video},
231 {"reverse", &mface_reverse_video},
232 {"underline", &mface_underline},
234 {"No CTL", &face_no_ctl_fontset} };
237 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
239 /* Information about a physical line metric. */
242 int from; /* BOL position of the line. */
243 int to; /* BOL position of the next line. */
244 int y0, y1; /* Top and bottom Y position of the line. */
245 int ascent; /* Height of the top Y position. */
248 struct LineInfo top; /* Topmost line. */
249 struct LineInfo cur; /* Line containing cursor. */
250 struct LineInfo sel_start; /* Line containing selection start. */
251 struct LineInfo sel_end; /* Line containing selection end. */
253 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
255 /* X position to keep on vertical (up and down) cursor motion. */
256 int target_x_position;
258 /* Interface macros for m17n-lib drawing routines. */
260 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
261 coordinate ($X, $Y) */
262 #define DRAW_TEXT(x, y, from, to) \
263 mdraw_text_with_control \
264 (frame, (MDrawWindow) win, \
265 control.orientation_reversed ? x + win_width : x, y, \
266 mt, from, to, &control)
268 /* Store the extents of a text in the range $FROM to $TO in the
269 structure $RECT (type MDrawMetric). */
270 #define TEXT_EXTENTS(from, to, rect) \
271 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
273 /* Store the glyph information of a character at the position $POS in
274 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
275 $FROM is written at the coordinate (0, 0). */
276 #define GLYPH_INFO(from, pos, info) \
277 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
279 /* Set $X and $Y to the coordinate of character at position $POS
280 assuming that the text from $FROM is written at the coordinate (0,
282 #define COORDINATES_POSITION(from, pos, x, y) \
283 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
285 /* Interface macros for X library. */
286 #define COPY_AREA(y0, y1, to) \
287 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
289 #define CLEAR_AREA(x, y, w, h) \
290 XClearArea (display, win, (x), (y), (w), (h), False)
292 #define SELECTEDP() \
293 mtext_property_mtext (selection)
295 /* Format MSG by FMT and print the result to the stderr, and exit. */
296 #define FATAL_ERROR(fmt, arg) \
298 fprintf (stderr, fmt, arg); \
303 /* If POS is greater than zero, move POS back to the beginning of line
304 (BOL) position. If FORWARD is nonzero, move POS forward instead.
305 Return the new position. */
307 bol (int pos, int forward)
309 int limit = forward ? nchars : 0;
311 pos = mtext_character (mt, pos, limit, '\n');
312 return (pos < 0 ? limit : pos + 1);
315 /* Update the structure #TOP (struct LineInfo) to make $POS the first
316 character position of the screen. */
320 int from = bol (pos, 0);
323 GLYPH_INFO (from, pos, info);
324 top.from = info.line_from;
325 top.to = info.line_to;
327 top.y1 = info.this.height;
328 top.ascent = - info.this.y;
332 /* Update the scroll bar so that the text of the range $FROM to $TO
333 are shown on the window. */
335 update_scroll_bar (int from, int to)
337 float top = (float) from / nchars;
338 float shown = (float) (to - from) / nchars;
339 XtArgVal *l_top = (XtArgVal *) ⊤
340 XtArgVal *l_shown = (XtArgVal *) &shown;
342 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
343 XtSetArg (arg[1], XtNshown, *l_shown);
344 XtSetValues (SbarWidget, arg, 2);
348 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
349 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
350 is nonzero, update the scoll bar. */
352 redraw (int y0, int y1, int clear, int scroll_bar)
357 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
358 struct LineInfo *line;
361 CLEAR_AREA (0, y0, win_width, y1 - y0);
363 /* Find a line closest to y0. It is a cursor line if the cursor is
364 Y0, otherwise the top line. */
369 /* If there exists a selected region, check it too. */
370 if (sel_y0 > line->y0 && y0 >= sel_y0)
375 info.this.height = line->y1 - y;
376 info.this.y = - line->ascent;
377 info.line_to = line->to;
378 while (from < nchars && y + info.this.height <= y0)
380 y += info.this.height;
382 GLYPH_INFO (from, from, info);
384 y0 = y - info.this.y;
386 while (to < nchars && y < y1)
388 GLYPH_INFO (to, to, info);
389 y += info.this.height;
395 DRAW_TEXT (0, y0, from, to);
400 GLYPH_INFO (to, to, info);
401 if (y + info.this.height >= win_height)
404 y += info.this.height;
406 update_scroll_bar (top.from, to);
411 /* Set the current input method spot to the correct position. */
413 set_input_method_spot ()
415 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
416 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
418 int n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
419 int size = 0, ratio = 0, i;
421 for (i = n - 1; i >= 0; i--)
424 size = (int) mface_get_prop (faces[i], Msize);
426 ratio = (int) mface_get_prop (faces[i], Mratio);
429 size = default_font_size;
431 size = size * ratio / 100;
432 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
433 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
438 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
441 redraw_cursor (int clear)
443 if (control.cursor_bidi)
445 /* We must update the whole line of the cursor. */
446 int beg = bol (cur.from, 0);
447 int end = bol (cur.to - 1, 1);
449 int y0 = cur.y0, y1 = cur.y1;
453 TEXT_EXTENTS (beg, cur.from, rect);
458 TEXT_EXTENTS (cur.to, end, rect);
461 redraw (y0, y1, clear, 0);
469 if (control.orientation_reversed)
470 x += win_width - cursor.this.width;
471 CLEAR_AREA (x, cur.y0, cursor.this.width, cursor.this.height);
473 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
478 /* Update the information about the location of cursor to the position
479 $POS. If $FULL is nonzero, update the information fully only from
480 the information about the top line. Otherwise, truct the current
481 information in the structure $CUR. */
483 update_cursor (int pos, int full)
489 /* CUR is inaccurate. We can trust only TOP. */
490 GLYPH_INFO (top.from, pos, cursor);
491 cur.y0 = top.ascent + cursor.y + cursor.this.y;
493 else if (pos < cur.from)
495 int from = bol (pos, 0);
497 TEXT_EXTENTS (from, cur.from, rect);
498 GLYPH_INFO (from, pos, cursor);
499 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y);
501 else if (pos < cur.to)
503 GLYPH_INFO (cur.from, pos, cursor);
507 GLYPH_INFO (cur.from, pos, cursor);
508 cur.y0 += cur.ascent + cursor.y + cursor.this.y;
511 cur.from = cursor.line_from;
512 cur.to = cursor.line_to;
513 cur.y1 = cur.y0 + cursor.this.height;
514 cur.ascent = - cursor.this.y;
518 /* Update the information about the selected region. */
528 from = mtext_property_start (selection);
529 to = mtext_property_end (selection);
533 int pos = bol (from, 0);
535 TEXT_EXTENTS (pos, top.from, rect);
536 sel_start.y0 = top.y0 - rect.height;
537 sel_start.ascent = - rect.y;
538 GLYPH_INFO (pos, from, info);
539 if (pos < info.line_from)
540 sel_start.y0 += - rect.y + info.y + info.this.y;
544 GLYPH_INFO (top.from, from, info);
545 sel_start.y0 = top.ascent + info.y + info.this.y;
547 sel_start.ascent = -info.this.y;
548 sel_start.y1 = sel_start.y0 + info.this.height;
549 sel_start.from = info.line_from;
550 sel_start.to = info.line_to;
552 if (to <= sel_start.to)
555 if (to >= sel_end.to)
557 GLYPH_INFO (sel_start.from, to, info);
558 sel_end.y1 = sel_end.y0 + info.y + info.this.height;
559 sel_end.to = info.line_to;
564 GLYPH_INFO (sel_start.from, to, info);
565 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
566 sel_end.y1 = sel_end.y0 + info.this.height;
567 sel_end.ascent = - info.this.y;
568 sel_end.from = info.line_from;
569 sel_end.to = info.line_to;
574 /* Select the text in the region from $FROM to $TO. */
576 select_region (int from, int to)
581 pos = from, from = to, to = pos;
582 mtext_push_property (mt, from, to, selection);
587 /* Setup the window to display the character of $POS at the top left
593 /* Top and bottom Y positions to redraw. */
596 if (pos + 1000 < top.from)
597 y0 = 0, y1 = win_height;
598 else if (pos < top.from)
601 TEXT_EXTENTS (pos, top.from, rect);
602 if (rect.height >= win_height * 0.9)
607 COPY_AREA (0, win_height - y1, y1);
610 else if (pos < top.to)
612 /* No need of redrawing. */
615 else if (pos < top.from + 1000)
617 TEXT_EXTENTS (top.from, pos, rect);
618 if (rect.height >= win_height * 0.9)
622 y0 = win_height - rect.height;
623 COPY_AREA (rect.height, win_height, 0);
628 y0 = 0, y1 = win_height;
634 update_cursor (pos, 1);
636 update_cursor (cursor.from, 1);
638 redraw (y0, y1, 1, 1);
642 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
645 /* Select an input method accoding to $IDX. If $IDX is negative, turn
646 off the current input method, otherwide turn on the input method
647 input_method_table[$IDX]. */
649 select_input_method (idx)
651 if (idx == current_input_method)
653 if (current_input_context)
655 minput_destroy_ic (current_input_context);
656 current_input_context = NULL;
657 current_input_method = -1;
661 MInputMethod *im = input_method_table[idx];
663 if (im->language == Mnil)
665 MInputXIMArgIC arg_xic;
666 Window win = XtWindow (TextWidget);
668 arg_xic.input_style = 0;
669 arg_xic.client_win = arg_xic.focus_win = win;
670 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
671 current_input_context = minput_create_ic (im, &arg_xic);
675 MInputGUIArgIC arg_ic;
677 arg_ic.frame = frame;
678 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
679 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
680 current_input_context = minput_create_ic (im, &arg_ic);
683 if (current_input_context)
685 set_input_method_spot ();
686 current_input_method = idx;
689 if (current_input_method >= 0)
692 XtSetArg (arg[0], XtNlabel, &label);
693 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
694 XtSetArg (arg[0], XtNlabel, label);
697 XtSetArg (arg[0], XtNlabel, "");
698 XtSetValues (CurIMLang, arg, 1);
701 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
704 /* Display cursor according to the current information of #CUR.
705 $CLIENT_DATA is ignore. Most callback functions add this function
706 as a background processing procedure the current application (by
707 XtAppAddWorkProc) via the function hide_cursor. */
709 show_cursor (XtPointer client_data)
714 update_cursor (cursor.from, 1);
716 while (cur.y1 > win_height)
719 update_cursor (cursor.from, 1);
722 control.cursor_pos = cursor.from;
725 control.with_cursor = 1;
728 if (current_input_context)
729 set_input_method_spot ();
732 int pos = (SELECTEDP () ? mtext_property_start (selection)
733 : cursor.from > 0 ? cursor.from - 1
735 MFace *face = mface ();
736 MTextProperty *props[256];
737 int n = mtext_get_properties (mt, pos, Mface, props, 256);
739 char buf[256], *p = buf;
745 int size = (int) mfont_get_prop (cursor.font, Msize);
746 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
747 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
748 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
749 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
751 sprintf (p, "%dpt", size / 10), p += strlen (p);
753 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
755 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
757 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
759 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
763 mface_merge (face, face_default);
764 for (i = 0; i < n; i++)
765 if (props[i] != selection)
766 mface_merge (face, (MFace *) mtext_property_value (props[i]));
767 sym = (MSymbol) mface_get_prop (face, Mforeground);
769 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
770 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
771 strcat (p, ",rev"), p += strlen (p);
772 if (mface_get_prop (face, Mhline))
773 strcat (p, ",ul"), p += strlen (p);
774 if (mface_get_prop (face, Mbox))
775 strcat (p, ",box"), p += strlen (p);
776 m17n_object_unref (face);
778 XtSetArg (arg[0], XtNborderWidth, 1);
779 XtSetArg (arg[1], XtNlabel, buf);
780 XtSetValues (CurFaceWidget, arg, 2);
783 if (control.cursor_pos < nchars)
787 if (control.cursor_pos > 0
788 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
789 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
791 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
795 XtSetArg (arg[0], XtNborderWidth, 0);
796 XtSetArg (arg[1], XtNlabel, "");
800 XtSetArg (arg[0], XtNborderWidth, 1);
801 XtSetArg (arg[1], XtNlabel,
802 msymbol_name (msymbol_get (sym, Mlanguage)));
803 XtSetValues (CurLangWidget, arg, 2);
805 XtSetValues (CurLangWidget, arg, 2);
807 if (auto_input_method)
810 select_input_method (-1);
815 for (i = 0; i < num_input_methods; i++)
816 if (input_method_table[i]->language == sym)
818 if (i < num_input_methods)
819 select_input_method (i);
821 select_input_method (-1);
826 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
832 /* Hide the cursor. */
836 control.with_cursor = 0;
838 XtAppAddWorkProc (context, show_cursor, NULL);
842 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
843 $Y1 and $NEW_Y1 assuming that the text in the other area is not
846 update_region (int y0, int old_y1, int new_y1)
852 if (old_y1 < win_height)
854 COPY_AREA (old_y1, win_height, new_y1);
855 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
858 redraw (new_y1, win_height, 1, 0);
860 else if (new_y1 > old_y1)
862 if (new_y1 < win_height)
863 COPY_AREA (old_y1, win_height, new_y1);
865 if (new_y1 > win_height)
867 redraw (y0, new_y1, 1, 1);
871 /* Delete the next $N characters. If $N is negative delete the
872 precious (- $N) characters. */
882 from = cursor.from, to = from + n;
885 if (cursor.from == cur.from)
887 /* We are at the beginning of line. */
888 int pos = cursor.prev_from;
890 if (cursor.from == top.from)
892 /* We are at the beginning of screen. We must scroll
894 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
895 reseat (info.line_from);
897 update_cursor (pos, 1);
903 from = cursor.from - 1;
908 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
909 old_y1 = cur.y0 + rect.height;
911 /* Now delete a character. */
912 mtext_del (mt, from, to);
914 if (from >= top.from && from < top.to)
915 update_top (top.from);
916 update_cursor (from, 1);
918 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
919 new_y1 = cur.y0 + rect.height;
921 update_region (cur.y0, old_y1, new_y1);
925 /* Insert M-text $NEWTEXT at the current cursor position. */
927 insert_chars (MText *newtext)
929 int n = mtext_len (newtext);
931 int y0, old_y1, new_y1;
935 int n = (mtext_property_end (selection)
936 - mtext_property_start (selection));
937 mtext_detach_property (selection);
942 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
943 old_y1 = y0 + rect.height;
945 /* Now insert chars. */
946 mtext_ins (mt, cursor.from, newtext);
948 if (cur.from == top.from)
949 update_top (top.from);
950 update_cursor (cursor.from + n, 1);
952 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
953 new_y1 = cur.y0 + rect.height;
955 update_region (y0, old_y1, new_y1);
960 /* Convert the currently selected text to COMPOUND-TEXT. It is called
961 when someone requests the current value of the selection. */
963 covert_selection (Widget w, Atom *selection_atom,
964 Atom *target, Atom *return_type,
965 XtPointer *value, unsigned long *length, int *format)
967 unsigned char *buf = (unsigned char *) XtMalloc (4096);
968 MText *this_mt = mtext ();
969 int from = mtext_property_start (selection);
970 int to = mtext_property_end (selection);
972 mtext_copy (this_mt, 0, mt, from, to);
973 *length = mconv_encode_buffer (msymbol ("compound-text"),
975 *return_type = XA_COMPOUND_TEXT;
976 *value = (XtPointer) buf;
978 m17n_object_unref (this_mt);
983 /* Unselect the text. It is called when we loose the selection. */
985 lose_selection (Widget w, Atom *selection_atom)
989 mtext_detach_property (selection);
990 redraw (sel_start.y0, sel_end.y1, 1, 0);
995 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
996 XtPointer value, unsigned long *length, int *format)
1001 if (*type == XT_CONVERT_FAIL || ! value)
1003 if (*type == XA_STRING)
1005 else if (*type == XA_COMPOUND_TEXT)
1006 coding = msymbol ("compound-text");
1007 else if (*type == XA_UTF8_STRING)
1008 coding = msymbol ("utf-8");
1012 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1016 insert_chars (this_mt);
1017 m17n_object_unref (this_mt);
1026 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1028 XExposeEvent *expose = (XExposeEvent *) event;
1032 Dimension width_max, width;
1034 XtSetArg (arg[0], XtNwidth, &width);
1035 XtGetValues (XtParent (w), arg, 1);
1037 XtGetValues (HeadWidget, arg, 1);
1038 if (width_max < width)
1040 XtGetValues (FaceWidget, arg, 1);
1041 if (width_max < width)
1043 XtGetValues (LangWidget, arg, 1);
1044 if (width_max < width)
1046 XtSetArg (arg[0], XtNwidth, width_max);
1047 XtSetValues (HeadWidget, arg, 1);
1048 XtSetValues (FaceWidget, arg, 1);
1049 XtSetValues (LangWidget, arg, 1);
1050 XtSetValues (XtParent (w), arg, 1);
1051 XtSetValues (TailWidget, arg, 1);
1054 update_cursor (0, 1);
1055 redraw (0, win_height, 0, 1);
1060 redraw (expose->y, expose->y + expose->height, 0, 0);
1061 if (current_input_context
1062 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1063 set_input_method_spot ();
1068 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1070 XConfigureEvent *configure = (XConfigureEvent *) event;
1073 control.max_line_width = win_width = configure->width;
1074 win_height = configure->height;
1075 mdraw_clear_cache (mt);
1077 update_cursor (0, 1);
1078 redraw (0, win_height, 1, 1);
1079 if (current_input_context)
1080 set_input_method_spot ();
1084 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1087 int x = event->xbutton.x;
1088 int y = event->xbutton.y - top.ascent;
1090 if (control.orientation_reversed)
1092 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1095 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1096 mtext_detach_property (selection);
1097 redraw (sel_start.y0, sel_end.y1, 1, 0);
1100 update_cursor (pos, 0);
1105 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1110 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1111 covert_selection, lose_selection, NULL);
1112 update_cursor (mtext_property_start (selection), 0);
1117 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1121 /* We don't have a local selection. */
1122 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1127 int from = mtext_property_start (selection);
1128 int to = mtext_property_end (selection);
1131 int x = event->xbutton.x;
1132 int y = event->xbutton.y - top.ascent;
1134 if (control.orientation_reversed)
1136 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1138 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1139 mtext_detach_property (selection);
1141 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1142 update_cursor (pos, 0);
1143 insert_chars (this_mt);
1144 m17n_object_unref (this_mt);
1149 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1152 int x = event->xbutton.x;
1153 int y = event->xbutton.y;
1155 if (control.orientation_reversed)
1158 pos = top.from, y -= top.ascent;
1160 pos = cur.from, y -= cur.y0 + cur.ascent;
1161 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1163 if (pos == cursor.from)
1169 /* Selection range changed. */
1170 int from = mtext_property_start (selection);
1171 int to = mtext_property_end (selection);
1172 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1173 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1175 if (cursor.from == from)
1177 /* Starting position changed. */
1180 /* Enlarged. We can simply overdraw if not using
1181 antialiased text. */
1182 select_region (pos, to);
1183 redraw (sel_start.y0, start_y1, control.anti_alias, 0);
1187 /* Shrunken. Previous selection face must be cleared. */
1188 select_region (pos, to);
1189 redraw (start_y0, sel_start.y1, 1, 0);
1193 /* Shrunken to zero. */
1194 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1195 mtext_detach_property (selection);
1196 redraw (start_y0, end_y1, 1, 0);
1200 /* Full update is necessary. */
1201 select_region (to, pos);
1202 redraw (start_y0, sel_end.y1, 1, 0);
1207 /* Ending position changed. */
1210 /* Full update is necessary. */
1211 select_region (pos, from);
1212 redraw (sel_start.y0, end_y1, 1, 0);
1214 else if (pos == from)
1216 /* Shrunken to zero. */
1217 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1218 mtext_detach_property (selection);
1219 redraw (start_y0, end_y1, 1, 0);
1223 /* Shrunken. Previous selection face must be cleared. */
1224 select_region (from, pos);
1225 redraw (sel_end.y0, end_y1, 1, 0);
1229 /* Enlarged. We can simply overdraw if not using
1230 antialiased text. */
1231 select_region (from, pos);
1232 redraw (end_y0, sel_end.y1, control.anti_alias, 0);
1238 /* Newly selected. */
1239 select_region (pos, cursor.from);
1240 redraw (sel_start.y0, sel_end.y1, 0, 0);
1242 update_cursor (pos, 1);
1246 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1249 MDrawGlyphInfo info;
1251 int cursor_pos = cursor.from;
1253 if (((int) position) < 0)
1259 height = top.y1 - top.y0;
1262 pos = bol (from - 1, 0);
1263 GLYPH_INFO (pos, from - 1, info);
1264 if (height + info.this.height > win_height)
1266 height += info.this.height;
1267 from = info.line_from;
1269 if (cursor_pos >= top.to)
1271 cursor_pos = top.from;
1273 while (cursor_pos < nchars)
1275 GLYPH_INFO (pos, pos, info);
1276 if (height + info.this.height > win_height)
1278 height += info.this.height;
1284 else if (cur.to < nchars)
1286 /* Scroll up, but leave at least one line. */
1289 while (from < nchars)
1291 GLYPH_INFO (from, from, info);
1292 if (height + info.this.height > win_height
1293 || info.line_to >= nchars)
1295 height += info.this.height;
1296 from = info.line_to;
1299 from = info.line_from;
1300 if (cursor_pos < from)
1304 /* Scroll up to make the cursor line top. */
1308 update_cursor (cursor_pos, 1);
1312 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1314 float persent = *(float *) persent_ptr;
1315 int pos1, pos2 = nchars * persent;
1316 MDrawGlyphInfo info;
1319 pos1 = bol (pos2, 0);
1320 GLYPH_INFO (pos1, pos2, info);
1321 pos1 = info.line_from;
1323 update_cursor (pos1, 1);
1328 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1330 XKeyEvent *key_event = (XKeyEvent *) event;
1332 KeySym keysym = NoSymbol;
1334 /* If set to 1, do not update target_x_position. */
1335 int keep_target_x_position = 0;
1338 if (current_input_context
1339 && minput_filter (current_input_context, Mnil, event))
1341 if (event->type == KeyRelease)
1346 produced = mtext ();
1347 ret = minput_lookup (current_input_context, Mnil, event, produced);
1348 if (mtext_len (produced) > 0)
1349 insert_chars (produced);
1351 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1352 m17n_object_unref (produced);
1362 n = (mtext_property_end (selection)
1363 - mtext_property_start (selection));
1364 mtext_detach_property (selection);
1366 else if (cursor.from < nchars)
1368 /* Delete the following grapheme cluster. */
1369 n = cursor.to - cursor.from;
1382 /* Delete selected region. */
1383 n = (mtext_property_end (selection)
1384 - mtext_property_start (selection));
1385 mtext_detach_property (selection);
1387 else if (cursor.from > 0)
1389 /* Delete the preceding character. */
1400 mtext_detach_property (selection);
1401 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1405 if (cursor.prev_from >= 0)
1406 update_cursor (cursor.prev_from, 0);
1410 if (cursor.left_from >= 0)
1411 update_cursor (cursor.left_from, 0);
1418 mtext_detach_property (selection);
1419 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1423 if (cursor.next_to >= 0)
1424 update_cursor (cursor.to, 0);
1428 if (cursor.right_from >= 0)
1429 update_cursor (cursor.right_from, 0);
1436 mtext_detach_property (selection);
1437 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1439 if (cur.to <= nchars)
1441 MDrawGlyphInfo info;
1444 GLYPH_INFO (cur.from, cur.to, info);
1445 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1446 target_x_position, info.y);
1447 keep_target_x_position = 1;
1448 update_cursor (pos, 0);
1455 mtext_detach_property (selection);
1456 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1462 int pos = bol (cur.from - 1, 0);
1464 TEXT_EXTENTS (pos, cur.from - 1, rect);
1465 y = rect.height + rect.y - 1;
1466 pos = COORDINATES_POSITION (pos, nchars,
1467 target_x_position, y);
1468 keep_target_x_position = 1;
1469 update_cursor (pos, 0);
1476 mtext_detach_property (selection);
1477 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1479 if (top.from < nchars)
1480 ScrollProc (w, NULL, (XtPointer) 1);
1486 mtext_detach_property (selection);
1487 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1490 ScrollProc (w, NULL, (XtPointer) -1);
1496 if (buf[0] == 17) /* C-q */
1498 XtAppSetExitFlag (context);
1501 else if (buf[0] == 12) /* C-l */
1503 redraw (0, win_height, 1, 1);
1508 MText *temp = mtext ();
1510 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1511 if (current_input_context)
1512 mtext_put_prop (temp, 0, 1, Mlanguage,
1513 current_input_context->im->language);
1514 insert_chars (temp);
1515 m17n_object_unref (temp);
1520 if (! keep_target_x_position)
1521 target_x_position = cursor.x;
1525 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1527 char *name = (char *) client_data;
1529 int from = -1, to = 0;
1534 filename = strdup (name);
1537 fp = fopen (filename, "w");
1540 fprintf (stderr, "Open for write fail: %s", filename);
1546 from = mtext_property_start (selection);
1547 to = mtext_property_end (selection);
1548 mtext_detach_property (selection);
1551 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1554 select_region (from, to);
1558 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1564 mtext_detach_property (selection);
1565 serialized = (int) client_data;
1567 new = mtext_deserialize (mt);
1570 MPlist *plist = mplist ();
1572 mplist_push (plist, Mt, Mface);
1573 mplist_push (plist, Mt, Mlanguage);
1574 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1575 m17n_object_unref (plist);
1579 m17n_object_unref (mt);
1581 serialized = ! serialized;
1582 nchars = mtext_len (mt);
1585 update_cursor (0, 1);
1586 redraw (0, win_height, 1, 1);
1590 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1592 XtAppSetExitFlag (context);
1598 FILE *fp = fopen (filename, "r");
1601 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1602 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1605 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1610 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1612 int data = (int) client_data;
1617 control.enable_bidi = 0;
1618 control.orientation_reversed = 0;
1622 control.enable_bidi = 1;
1623 control.orientation_reversed = data == 2;
1625 for (i = 0; i < 3; i++)
1628 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1630 XtSetArg (arg[0], XtNleftBitmap, None);
1631 XtSetValues (BidiMenus[i], arg, 1);
1634 update_cursor (cursor.from, 1);
1635 redraw (0, win_height, 1, 0);
1638 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1641 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1643 int data = (int) client_data;
1647 control.max_line_width = 0;
1650 control.max_line_width = win_width;
1651 control.line_break = (data == 1 ? NULL : line_break);
1653 for (i = 0; i < 3; i++)
1656 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1658 XtSetArg (arg[0], XtNleftBitmap, None);
1659 XtSetValues (LineBreakMenus[i], arg, 1);
1662 update_cursor (cursor.from, 1);
1663 redraw (0, win_height, 1, 0);
1667 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1669 int data = (int) client_data;
1683 control.cursor_bidi = 0, control.cursor_width = -1;
1687 control.cursor_bidi = 0, control.cursor_width = 2;
1691 control.cursor_bidi = 1;
1696 for (i = from; i < to; i++)
1699 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1701 XtSetArg (arg[0], XtNleftBitmap, None);
1702 XtSetValues (CursorMenus[i], arg, 1);
1705 redraw (0, win_height, 1, 0);
1709 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1711 int idx = (int) client_data;
1713 if (idx == -2 ? current_input_method < 0
1714 : idx == -1 ? auto_input_method
1715 : idx == current_input_method)
1718 XtSetArg (arg[0], XtNleftBitmap, None);
1719 if (auto_input_method)
1721 XtSetValues (InputMethodMenus[1], arg, 1);
1722 auto_input_method = 0;
1724 else if (current_input_method < 0)
1725 XtSetValues (InputMethodMenus[0], arg, 1);
1727 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1731 auto_input_method = 1;
1735 select_input_method (idx);
1736 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1737 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1741 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1743 int idx = (int) client_data;
1750 XtAppAddWorkProc (context, show_cursor, NULL);
1751 from = mtext_property_start (selection);
1752 to = mtext_property_end (selection);
1753 old_y1 = sel_end.y1;
1755 mtext_detach_property (selection);
1758 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1759 MTEXTPROP_REAR_STICKY);
1760 mtext_push_property (mt, from, to, prop);
1761 m17n_object_unref (prop);
1764 mtext_pop_prop (mt, from, to, Mface);
1766 update_top (top.from);
1767 update_cursor (cursor.from, 1);
1768 select_region (from, to);
1769 update_region (sel_start.y0, old_y1, sel_end.y1);
1770 if (cur.y1 > win_height)
1772 while (cur.y1 > win_height)
1775 update_cursor (cursor.from, 1);
1781 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1783 MSymbol sym = (MSymbol) client_data;
1790 XtAppAddWorkProc (context, show_cursor, NULL);
1791 from = mtext_property_start (selection);
1792 to = mtext_property_end (selection);
1793 old_y1 = sel_end.y1;
1795 mtext_detach_property (selection);
1797 mtext_put_prop (mt, from, to, Mlanguage, sym);
1799 mtext_pop_prop (mt, from, to, Mlanguage);
1802 update_top (top.from);
1803 update_cursor (cursor.from, 1);
1804 select_region (from, to);
1805 update_region (sel_start.y0, old_y1, sel_end.y1);
1806 if (cur.y1 > win_height)
1808 while (cur.y1 > win_height)
1811 update_cursor (cursor.from, 1);
1817 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1819 int narrowed = (int) client_data;
1822 MConverter *converter;
1828 from = mtext_property_start (selection);
1829 to = mtext_property_end (selection);
1838 mdump = popen ("mdump -q -p a4", "w");
1840 mdump = popen ("mdump -q", "w");
1843 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1844 mconv_encode_range (converter, mt, from, to);
1845 mconv_free_converter (converter);
1850 input_status (MInputContext *ic, MSymbol command)
1852 XFillRectangle (display, input_status_pixmap, gc_inv,
1853 0, 0, input_status_width, input_status_height);
1854 if (command == Minput_status_draw)
1858 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1859 Mface, face_input_status);
1860 if (ic->im->language != Mnil)
1861 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1862 Mlanguage, ic->im->language);
1863 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1864 &input_status_control, NULL, NULL, &rect);
1865 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1866 input_status_width - rect.width - 2, - rect.y,
1867 ic->status, 0, mtext_len (ic->status),
1868 &input_status_control);
1870 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1871 XtSetValues (CurIMStatus, arg, 1);
1875 compare_input_method (const void *elt1, const void *elt2)
1877 const MInputMethod *im1 = *(MInputMethod **) elt1;
1878 const MInputMethod *im2 = *(MInputMethod **) elt2;
1879 MSymbol lang1, lang2;
1881 if (im1->language == Mnil)
1883 if (im1->language == im2->language)
1884 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1885 if (im1->language == Mt)
1887 if (im2->language == Mt)
1889 lang1 = msymbol_get (im1->language, Mlanguage);
1890 lang2 = msymbol_get (im2->language, Mlanguage);
1891 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1895 setup_input_methods (int with_xim)
1897 MInputMethod *im = NULL;
1898 MInputXIMArgIM arg_xim;
1899 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1903 num_input_methods = mplist_length (plist);
1907 arg_xim.display = display;
1909 arg_xim.res_name = arg_xim.res_class = NULL;
1910 arg_xim.locale = NULL;
1911 arg_xim.modifier_list = NULL;
1912 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1914 num_input_methods++;
1916 input_method_table = calloc (num_input_methods, sizeof (MInputMethod *));
1918 input_method_table[i++] = im;
1919 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1921 MDatabase *mdb = mplist_value (pl);
1922 MSymbol *tag = mdatabase_tag (mdb);
1926 im = minput_open_im (tag[1], tag[2], NULL);
1928 input_method_table[i++] = im;
1932 m17n_object_unref (plist);
1933 num_input_methods = i;
1934 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
1935 compare_input_method);
1936 current_input_context = NULL;
1938 mplist_put (minput_driver->callback_list, Minput_status_start,
1939 (void *) input_status);
1940 mplist_put (minput_driver->callback_list, Minput_status_draw,
1941 (void *) input_status);
1942 mplist_put (minput_driver->callback_list, Minput_status_done,
1943 (void *) input_status);
1948 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
1952 if (num && *num > 0)
1956 for (i = 0; i < *num; i++)
1957 bytes += strlen (str[i]) + 1;
1958 msg = alloca (bytes);
1959 strcpy (msg, str[0]);
1960 for (i = 1; i < *num; i++)
1961 strcat (msg, " "), strcat (msg, str[i]);
1963 else if (cursor.from < nchars)
1965 int c = mtext_ref_char (mt, cursor.from);
1966 char *name = mchar_get_prop (c, Mname);
1970 msg = alloca (10 + strlen (name));
1971 sprintf (msg, "U+%04X %s", c, name);
1977 XtSetArg (arg[0], XtNlabel, msg);
1978 XtSetValues (MessageWidget, arg, 1);
1984 char *name1, *name2;
1985 XtCallbackProc proc;
1986 XtPointer client_data;
1991 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
1993 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
1995 MenuRec FileMenu[] =
1996 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
1997 { 0, "Save", NULL, SaveProc, NULL, -1 },
1998 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2000 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2001 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2003 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2004 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2006 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2009 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2011 MenuRec *rec = (MenuRec *) client_data;
2014 XtSetArg (arg[0], XtNvalue, "");
2015 XtSetArg (arg[1], XtNlabel, rec->name1);
2016 XtSetValues (FileDialogWidget, arg, 2);
2017 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2018 XtSetArg (arg[0], XtNx, x + 20);
2019 XtSetArg (arg[1], XtNy, y + 10);
2020 XtSetValues (FileShellWidget, arg, 2);
2021 XtPopup (FileShellWidget, XtGrabExclusive);
2025 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2030 XtPopdown (FileShellWidget);
2031 if ((int) client_data == 1)
2033 XtSetArg (arg[0], XtNlabel, &label);
2034 XtGetValues (FileDialogWidget, arg, 1);
2035 if (strcmp (label, FileMenu[0].name1) == 0)
2039 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2040 fp = fopen (filename, "r");
2042 m17n_object_unref (mt);
2045 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2053 nchars = mtext_len (mt);
2055 update_cursor (0, 1);
2056 redraw (0, win_height, 1, 1);
2058 else if (strcmp (label, FileMenu[2].name1) == 0)
2059 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2061 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2064 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2065 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2066 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2067 (MENU).status = (STATUS))
2071 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2072 char *menu_name, MenuRec *menus, int num_menus, char *help)
2074 Widget button, menu;
2075 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2076 <LeaveWindow>: reset() MenuHelp()\n\
2077 <BtnDown>: reset() PopupMenu()\n\
2078 <BtnUp>: highlight()";
2084 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2085 for (i = 0; i < num_menus; i++)
2096 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2098 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2100 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2102 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2106 XtSetArg (arg[0], XtNsensitive, False);
2107 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2113 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2118 trans = alloca (strlen (fmt) + strlen (help));
2119 sprintf (trans, fmt, help);
2120 XtSetArg (arg[0], XtNmenuName, menu_name);
2121 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2122 XtSetArg (arg[2], XtNinternalWidth, 2);
2123 XtSetArg (arg[3], XtNhighlightThickness, 1);
2124 XtSetArg (arg[4], XtNleft, XawChainLeft);
2125 XtSetArg (arg[5], XtNright, XawChainLeft);
2128 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2129 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2134 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2135 int *len = alloca (sizeof (int) * num_menus);
2138 XFontSetExtents *fontset_extents;
2140 XtSetArg (arg[0], XtNfontSet, &font_set);
2141 XtGetValues (button, arg, 1);
2143 fontset_extents = XExtentsOfFontSet (font_set);
2144 height = fontset_extents->max_logical_extent.height;
2145 ascent = - fontset_extents->max_logical_extent.y;
2147 for (i = 0; i < num_menus; i++)
2150 len[i] = strlen (menus[i].name2);
2151 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2152 if (max_width < width[i])
2153 max_width = width[i];
2155 for (i = 0; i < num_menus; i++)
2158 Pixmap pixmap = XCreatePixmap (display,
2159 RootWindow (display, screen),
2160 max_width, height, 1);
2161 XFillRectangle (display, pixmap, mono_gc_inv,
2162 0, 0, max_width, height);
2163 XmbDrawString (display, pixmap, font_set, mono_gc,
2164 max_width - width[i], ascent,
2165 menus[i].name2, len[i]);
2166 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2167 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2168 XtSetValues (menus[i].w, arg, 2);
2176 XtActionsRec actions[] = {
2177 {"Expose", ExposeProc},
2178 {"Configure", ConfigureProc},
2180 {"ButtonPress", ButtonProc},
2181 {"ButtonRelease", ButtonReleaseProc},
2182 {"ButtonMotion", ButtonMoveProc},
2183 {"Button2Press", Button2Proc},
2184 {"MenuHelp", MenuHelpProc}
2188 /* Print the usage of this program (the name is PROG), and exit with
2192 help_exit (char *prog, int exit_code)
2200 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2201 printf ("Display FILE on a window and allow users to edit it.\n");
2202 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2203 printf ("The following OPTIONs are available.\n");
2204 printf (" %-13s %s", "--version", "print version number\n");
2205 printf (" %-13s %s", "-h, --help", "print this message\n");
2210 main (int argc, char **argv)
2212 Widget form, BodyWidget, w;
2213 char *fontset_name = NULL;
2214 int col = 80, row = 32;
2215 /* Translation table for TextWidget. */
2216 String trans = "<Expose>: Expose()\n\
2217 <Configure>: Configure()\n\
2220 <Btn1Down>: ButtonPress()\n\
2221 <Btn1Up>: ButtonRelease()\n\
2222 <Btn1Motion>: ButtonMotion()\n\
2223 <Btn2Down>: Button2Press()";
2224 /* Translation table for the top form widget. */
2225 String trans2 = "<Key>: Key()\n\
2227 String pop_face_trans
2228 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2229 <LeaveWindow>: MenuHelp() reset()\n\
2230 <Btn1Down>: set()\n\
2231 <Btn1Up>: notify() unset()";
2232 String pop_lang_trans
2233 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2234 <LeaveWindow>: MenuHelp() reset()\n\
2235 <Btn1Down>: set()\n\
2236 <Btn1Up>: notify() unset()";
2237 int font_width, font_ascent, font_descent;
2241 setlocale (LC_ALL, "");
2242 /* Create the top shell. */
2243 XtSetLanguageProc (NULL, NULL, NULL);
2244 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2245 NULL, sessionShellWidgetClass, NULL, 0);
2246 display = XtDisplay (ShellWidget);
2247 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2249 /* Parse the remaining command line arguments. */
2250 for (i = 1; i < argc; i++)
2252 if (! strcmp (argv[i], "--help")
2253 || ! strcmp (argv[i], "-h"))
2254 help_exit (argv[0], 0);
2255 else if (! strcmp (argv[i], "--version"))
2257 printf ("medit (m17n library) %s\n", VERSION);
2258 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2261 else if (! strcmp (argv[i], "--geometry"))
2264 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2265 help_exit (argv[0], 1);
2267 else if (! strcmp (argv[i], "--fontset"))
2270 fontset_name = strdup (argv[i]);
2272 else if (! strcmp (argv[i], "--with-xim"))
2276 else if (argv[i][0] != '-')
2278 filename = strdup (argv[i]);
2282 fprintf (stderr, "Unknown option: %s", argv[i]);
2283 help_exit (argv[0], 1);
2287 help_exit (argv[0], 1);
2289 mdatabase_dir = ".";
2290 /* Initialize the m17n library. */
2292 if (merror_code != MERROR_NONE)
2293 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2295 mt = read_file (filename);
2298 nchars = mtext_len (mt);
2301 MFace *face = mface ();
2303 mface_put_prop (face, Mbackground, msymbol ("blue"));
2304 mface_put_prop (face, Mforeground, msymbol ("yellow"));
2305 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2306 m17n_object_unref (face);
2309 /* This tells ExposeProc to initialize everything. */
2312 XA_TEXT = XInternAtom (display, "TEXT", False);
2313 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2314 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2316 MPlist *plist = mplist ();
2320 mplist_put (plist, msymbol ("widget"), ShellWidget);
2323 MFontset *fontset = mfontset (fontset_name);
2326 mface_put_prop (face, Mfontset, fontset);
2327 m17n_object_unref (fontset);
2328 mplist_add (plist, Mface, face);
2329 m17n_object_unref (face);
2331 frame = mframe (plist);
2332 m17n_object_unref (plist);
2333 face_default = (MFace *) mframe_get_prop (frame, Mface);
2334 face_default_fontset = mface ();
2335 mface_put_prop (face_default_fontset, Mfontset,
2336 mface_get_prop (face_default, Mfontset));
2338 font = (MFont *) mframe_get_prop (frame, Mfont);
2339 default_font_size = (int) mfont_get_prop (font, Msize);
2342 font_width = (int) mframe_get_prop (frame, Mfont_width);
2343 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2344 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2345 win_width = font_width * col;
2346 win_height = (font_ascent + font_descent) * row;
2352 prop.color_top = prop.color_left = msymbol ("magenta");
2353 prop.color_bottom = prop.color_right = msymbol ("red");
2354 prop.inner_hmargin = prop.inner_vmargin = 1;
2355 prop.outer_hmargin = prop.outer_vmargin = 2;
2357 face_box = mface ();
2358 mface_put_prop (face_box, Mbox, &prop);
2361 face_courier = mface ();
2362 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2363 face_helvetica = mface ();
2364 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2365 face_times = mface ();
2366 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2367 face_dv_ttyogesh = mface ();
2368 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2369 face_freesans = mface ();
2370 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2371 face_freemono = mface ();
2372 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2374 face_xxx_large = mface ();
2375 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2377 MFont *latin_font = mframe_get_prop (frame, Mfont);
2378 MFont *dev_font = mfont ();
2379 MFont *thai_font = mfont ();
2380 MFont *tib_font = mfont ();
2382 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2383 MSymbol no_ctl = msymbol ("no-ctl");
2385 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2386 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2387 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2388 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2389 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2390 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2392 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2393 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2394 latin_font, Mnil, 0);
2395 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2396 dev_font, no_ctl, 0);
2397 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2398 thai_font, no_ctl, 0);
2399 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2400 tib_font, no_ctl, 0);
2401 face_no_ctl_fontset = mface ();
2402 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2403 m17n_object_unref (fontset);
2410 setup_input_methods (with_xim);
2412 gc = DefaultGC (display, screen);
2414 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2415 XtSetArg (arg[1], XtNdefaultDistance, 2);
2416 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2418 XtSetArg (arg[0], XtNborderWidth, 0);
2419 XtSetArg (arg[1], XtNdefaultDistance, 2);
2420 XtSetArg (arg[2], XtNtop, XawChainTop);
2421 XtSetArg (arg[3], XtNbottom, XawChainTop);
2422 XtSetArg (arg[4], XtNleft, XawChainLeft);
2423 XtSetArg (arg[5], XtNright, XawChainRight);
2424 XtSetArg (arg[6], XtNresizable, True);
2425 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2426 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2427 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2428 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2429 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2430 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2431 XtSetArg (arg[7], XtNfromVert, LangWidget);
2432 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2433 XtSetArg (arg[2], XtNtop, XawChainBottom);
2434 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2435 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2437 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2438 HeadWidget, NULL, 0);
2439 XtSetArg (arg[0], XtNvalue, "");
2440 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2441 FileShellWidget, arg, 1);
2442 XawDialogAddButton (FileDialogWidget, "OK",
2443 FileDialogProc, (XtPointer) 0);
2444 XawDialogAddButton (FileDialogWidget, "CANCEL",
2445 FileDialogProc, (XtPointer) 1);
2447 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2448 (char *) check_bits,
2449 check_width, check_height);
2451 unsigned long valuemask = GCForeground;
2454 values.foreground = 1;
2455 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2456 values.foreground = 0;
2457 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2464 if (num_menus < num_input_methods + 2)
2465 num_menus = num_input_methods + 2;
2466 if (num_menus < num_faces + 1)
2467 num_menus = num_faces + 1;
2468 menus = alloca (sizeof (MenuRec) * num_menus);
2470 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2471 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2472 "File I/O, Serialization, Image, Quit");
2474 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2475 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2476 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2477 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2478 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2479 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2480 w = create_menu_button (ShellWidget, HeadWidget, w,
2481 "Cursor", "Cursor Menu",
2482 menus, 6, "Cursor Movement Mode, Cursor Shape");
2483 CursorMenus[0] = menus[0].w;
2484 CursorMenus[1] = menus[1].w;
2485 CursorMenus[2] = menus[3].w;
2486 CursorMenus[3] = menus[4].w;
2487 CursorMenus[4] = menus[5].w;
2489 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2490 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2491 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2492 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2493 menus, 3, "BIDI Processing Mode");
2494 for (i = 0; i < 3; i++)
2495 BidiMenus[i] = menus[i].w;
2497 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2498 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2499 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2500 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2502 menus, 3, "How to break lines");
2503 for (i = 0; i < 3; i++)
2504 LineBreakMenus[i] = menus[i].w;
2506 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2507 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2508 for (i = 0; i < num_input_methods; i++)
2510 MInputMethod *im = input_method_table[i];
2511 char *name1, *name2;
2513 if (im->language != Mnil && im->language != Mt)
2515 MSymbol sym = msymbol_get (im->language, Mlanguage);
2517 name1 = msymbol_name (im->language);
2519 name1 = msymbol_name (sym);
2520 name2 = msymbol_name (im->name);
2523 name1 = msymbol_name (im->name), name2 = NULL;
2525 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2527 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2528 "Input Method Menu", menus, i + 2,
2529 "Select input method");
2532 unsigned long valuemask = GCForeground;
2535 XtSetArg (arg[0], XtNbackground, &values.foreground);
2536 XtGetValues (w, arg, 1);
2537 gc_inv = XCreateGC (display, RootWindow (display, screen),
2538 valuemask, &values);
2541 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2542 for (i = 0; i < num_input_methods + 2; i++)
2543 InputMethodMenus[i] = menus[i].w;
2545 input_status_width = font_width * 8;
2546 input_status_height = (font_ascent + font_descent) * 2.4;
2547 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2549 input_status_height,
2550 DefaultDepth (display, screen));
2555 prop.color_top = prop.color_bottom
2556 = prop.color_left = prop.color_right = Mnil;
2557 prop.inner_hmargin = prop.inner_vmargin = 1;
2558 prop.outer_hmargin = prop.outer_vmargin = 0;
2559 face_input_status = mface ();
2560 mface_put_prop (face_input_status, Mbox, &prop);
2563 XFillRectangle (display, input_status_pixmap, gc_inv,
2564 0, 0, input_status_width, input_status_height);
2565 XtSetArg (arg[0], XtNfromHoriz, w);
2566 XtSetArg (arg[1], XtNleft, XawRubber);
2567 XtSetArg (arg[2], XtNright, XawChainRight);
2568 XtSetArg (arg[3], XtNborderWidth, 0);
2569 XtSetArg (arg[4], XtNlabel, " ");
2570 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2571 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2572 HeadWidget, arg, 6);
2573 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2574 XtSetArg (arg[1], XtNleft, XawChainRight);
2575 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2576 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2577 HeadWidget, arg, 5);
2579 XtSetArg (arg[0], XtNborderWidth, 0);
2580 XtSetArg (arg[1], XtNleft, XawChainLeft);
2581 XtSetArg (arg[2], XtNright, XawChainLeft);
2582 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2583 for (i = 0; i < num_faces;)
2585 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2586 char *label = label_menu + 5; /* "Xxxx" */
2588 for (j = i; j < num_faces && face_table[j].face; j++)
2589 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2591 w = create_menu_button (ShellWidget, FaceWidget, w,
2593 menus, j - i, "Push face property");
2597 XtSetArg (arg[0], XtNfromHoriz, w);
2598 XtSetArg (arg[1], XtNleft, XawChainLeft);
2599 XtSetArg (arg[2], XtNright, XawChainLeft);
2600 XtSetArg (arg[3], XtNhorizDistance, 10);
2601 XtSetArg (arg[4], XtNlabel, "Pop");
2602 XtSetArg (arg[5], XtNtranslations,
2603 XtParseTranslationTable (pop_face_trans));
2604 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2605 FaceWidget, arg, 6);
2606 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2608 XtSetArg (arg[0], XtNfromHoriz, w);
2609 XtSetArg (arg[1], XtNleft, XawChainLeft);
2610 XtSetArg (arg[2], XtNright, XawChainRight);
2611 XtSetArg (arg[3], XtNlabel, "");
2612 XtSetArg (arg[4], XtNborderWidth, 0);
2613 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2614 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2615 FaceWidget, arg, 6);
2617 XtSetArg (arg[0], XtNborderWidth, 0);
2618 XtSetArg (arg[1], XtNleft, XawChainLeft);
2619 XtSetArg (arg[2], XtNright, XawChainLeft);
2620 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2622 MPlist *plist[11], *pl;
2625 for (i = 0; i < 11; i++) plist[i] = NULL;
2627 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2628 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2630 MSymbol sym = msymbol_exist (langname);
2634 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2636 char *name = msymbol_name (fullname);
2639 if (c >= 'A' && c <= 'Z')
2641 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2645 pl = plist[idx] = mplist ();
2646 for (; mplist_next (pl); pl = mplist_next (pl))
2647 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2649 mplist_push (pl, sym, fullname);
2654 for (i = 0; i < 11; i++)
2657 char *name = alloca (9);
2659 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2662 for (j = 0, pl = plist[i]; mplist_next (pl);
2663 j++, pl = mplist_next (pl))
2664 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2665 msymbol_name (mplist_key (pl)),
2666 LangProc, mplist_key (pl), -1);
2667 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2668 menus, j, "Push language property");
2670 for (i = 0; i < 11; i++)
2672 m17n_object_unref (plist[i]);
2674 XtSetArg (arg[0], XtNfromHoriz, w);
2675 XtSetArg (arg[1], XtNleft, XawChainLeft);
2676 XtSetArg (arg[2], XtNright, XawChainLeft);
2677 XtSetArg (arg[3], XtNhorizDistance, 10);
2678 XtSetArg (arg[4], XtNlabel, "Pop");
2679 XtSetArg (arg[5], XtNtranslations,
2680 XtParseTranslationTable (pop_lang_trans));
2681 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2682 LangWidget, arg, 6);
2683 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2685 XtSetArg (arg[0], XtNfromHoriz, w);
2686 XtSetArg (arg[1], XtNleft, XawChainLeft);
2687 XtSetArg (arg[2], XtNright, XawChainRight);
2688 XtSetArg (arg[3], XtNlabel, "");
2689 XtSetArg (arg[4], XtNborderWidth, 0);
2690 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2691 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2692 LangWidget, arg, 6);
2695 XtSetArg (arg[0], XtNheight, win_height);
2696 XtSetArg (arg[1], XtNwidth, 10);
2697 XtSetArg (arg[2], XtNleft, XawChainLeft);
2698 XtSetArg (arg[3], XtNright, XawChainLeft);
2699 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2701 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2702 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2704 XtSetArg (arg[0], XtNheight, win_height);
2705 XtSetArg (arg[1], XtNwidth, win_width);
2706 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2707 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2708 XtSetArg (arg[4], XtNleft, XawChainLeft);
2709 XtSetArg (arg[5], XtNright, XawChainRight);
2710 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2713 XtSetArg (arg[0], XtNborderWidth, 0);
2714 XtSetArg (arg[1], XtNleft, XawChainLeft);
2715 XtSetArg (arg[2], XtNright, XawChainRight);
2716 XtSetArg (arg[3], XtNresizable, True);
2717 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2718 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2719 TailWidget, arg, 5);
2721 memset (&control, 0, sizeof control);
2722 control.two_dimensional = 1;
2723 control.enable_bidi = 1;
2724 control.anti_alias = 1;
2725 control.min_line_ascent = font_ascent;
2726 control.min_line_descent = font_descent;
2727 control.max_line_width = win_width;
2728 control.with_cursor = 1;
2729 control.cursor_width = 2;
2730 control.partial_update = 1;
2731 control.ignore_formatting_char = 1;
2733 memset (&input_status_control, 0, sizeof input_status_control);
2734 input_status_control.enable_bidi = 1;
2736 XtAppAddActions (context, actions, XtNumber (actions));
2737 XtRealizeWidget (ShellWidget);
2739 win = XtWindow (TextWidget);
2741 XtAppMainLoop (context);
2743 if (current_input_context)
2744 minput_destroy_ic (current_input_context);
2745 for (i = 0; i < num_input_methods; i++)
2746 minput_close_im (input_method_table[i]);
2747 m17n_object_unref (frame);
2748 m17n_object_unref (mt);
2749 m17n_object_unref (face_xxx_large);
2750 m17n_object_unref (face_box);
2751 m17n_object_unref (face_courier);
2752 m17n_object_unref (face_helvetica);
2753 m17n_object_unref (face_times);
2754 m17n_object_unref (face_dv_ttyogesh);
2755 m17n_object_unref (face_freesans);
2756 m17n_object_unref (face_freemono);
2757 m17n_object_unref (face_default_fontset);
2758 m17n_object_unref (face_no_ctl_fontset);
2759 m17n_object_unref (face_input_status);
2760 m17n_object_unref (selection);
2764 free (fontset_name);
2766 free (input_method_table);
2767 free (InputMethodMenus);
2769 XFreeGC (display, mono_gc);
2770 XFreeGC (display, mono_gc_inv);
2771 XFreeGC (display, gc_inv);
2772 XtUninstallTranslations (form);
2773 XtUninstallTranslations (TextWidget);
2774 XtDestroyWidget (ShellWidget);
2775 XtDestroyApplicationContext (context);
2779 #endif /* not FOR_DOXYGEN */