1 /* medit.c -- simple multilingual editor.
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 @page 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 @page 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. */
1181 select_region (pos, to);
1182 redraw (sel_start.y0, start_y1, 0, 0);
1186 /* Shrunken. Previous selection face must be cleared. */
1187 select_region (pos, to);
1188 redraw (start_y0, sel_start.y1, 1, 0);
1192 /* Shrunken to zero. */
1193 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1194 mtext_detach_property (selection);
1195 redraw (start_y0, end_y1, 1, 0);
1199 /* Full update is necessary. */
1200 select_region (to, pos);
1201 redraw (start_y0, sel_end.y1, 1, 0);
1206 /* Ending position changed. */
1209 /* Full update is necessary. */
1210 select_region (pos, from);
1211 redraw (sel_start.y0, end_y1, 1, 0);
1213 else if (pos == from)
1215 /* Shrunken to zero. */
1216 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1217 mtext_detach_property (selection);
1218 redraw (start_y0, end_y1, 1, 0);
1222 /* Shrunken. Previous selection face must be cleared. */
1223 select_region (from, pos);
1224 redraw (sel_end.y0, end_y1, 1, 0);
1228 /* Enlarged. We can simply overdraw. */
1229 select_region (from, pos);
1230 redraw (end_y0, sel_end.y1, 0, 0);
1236 /* Newly selected. */
1237 select_region (pos, cursor.from);
1238 redraw (sel_start.y0, sel_end.y1, 0, 0);
1240 update_cursor (pos, 1);
1244 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1247 MDrawGlyphInfo info;
1249 int cursor_pos = cursor.from;
1251 if (((int) position) < 0)
1257 height = top.y1 - top.y0;
1260 pos = bol (from - 1, 0);
1261 GLYPH_INFO (pos, from - 1, info);
1262 if (height + info.this.height > win_height)
1264 height += info.this.height;
1265 from = info.line_from;
1267 if (cursor_pos >= top.to)
1269 cursor_pos = top.from;
1271 while (cursor_pos < nchars)
1273 GLYPH_INFO (pos, pos, info);
1274 if (height + info.this.height > win_height)
1276 height += info.this.height;
1282 else if (cur.to < nchars)
1284 /* Scroll up, but leave at least one line. */
1287 while (from < nchars)
1289 GLYPH_INFO (from, from, info);
1290 if (height + info.this.height > win_height
1291 || info.line_to >= nchars)
1293 height += info.this.height;
1294 from = info.line_to;
1297 from = info.line_from;
1298 if (cursor_pos < from)
1302 /* Scroll up to make the cursor line top. */
1306 update_cursor (cursor_pos, 1);
1310 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1312 float persent = *(float *) persent_ptr;
1313 int pos1, pos2 = nchars * persent;
1314 MDrawGlyphInfo info;
1317 pos1 = bol (pos2, 0);
1318 GLYPH_INFO (pos1, pos2, info);
1319 pos1 = info.line_from;
1321 update_cursor (pos1, 1);
1326 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1328 XKeyEvent *key_event = (XKeyEvent *) event;
1330 KeySym keysym = NoSymbol;
1332 /* If set to 1, do not update target_x_position. */
1333 int keep_target_x_position = 0;
1336 if (current_input_context
1337 && minput_filter (current_input_context, Mnil, event))
1339 if (event->type == KeyRelease)
1344 produced = mtext ();
1345 ret = minput_lookup (current_input_context, Mnil, event, produced);
1346 if (mtext_len (produced) > 0)
1347 insert_chars (produced);
1349 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1350 m17n_object_unref (produced);
1360 n = (mtext_property_end (selection)
1361 - mtext_property_start (selection));
1362 mtext_detach_property (selection);
1364 else if (cursor.from < nchars)
1366 /* Delete the following grapheme cluster. */
1367 n = cursor.to - cursor.from;
1380 /* Delete selected region. */
1381 n = (mtext_property_end (selection)
1382 - mtext_property_start (selection));
1383 mtext_detach_property (selection);
1385 else if (cursor.from > 0)
1387 /* Delete the preceding character. */
1398 mtext_detach_property (selection);
1399 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1403 if (cursor.prev_from >= 0)
1404 update_cursor (cursor.prev_from, 0);
1408 if (cursor.left_from >= 0)
1409 update_cursor (cursor.left_from, 0);
1416 mtext_detach_property (selection);
1417 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1421 if (cursor.next_to >= 0)
1422 update_cursor (cursor.to, 0);
1426 if (cursor.right_from >= 0)
1427 update_cursor (cursor.right_from, 0);
1434 mtext_detach_property (selection);
1435 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1437 if (cur.to <= nchars)
1439 MDrawGlyphInfo info;
1442 GLYPH_INFO (cur.from, cur.to, info);
1443 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1444 target_x_position, info.y);
1445 keep_target_x_position = 1;
1446 update_cursor (pos, 0);
1453 mtext_detach_property (selection);
1454 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1460 int pos = bol (cur.from - 1, 0);
1462 TEXT_EXTENTS (pos, cur.from - 1, rect);
1463 y = rect.height + rect.y - 1;
1464 pos = COORDINATES_POSITION (pos, nchars,
1465 target_x_position, y);
1466 keep_target_x_position = 1;
1467 update_cursor (pos, 0);
1474 mtext_detach_property (selection);
1475 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1477 if (top.from < nchars)
1478 ScrollProc (w, NULL, (XtPointer) 1);
1484 mtext_detach_property (selection);
1485 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1488 ScrollProc (w, NULL, (XtPointer) -1);
1494 if (buf[0] == 17) /* C-q */
1496 XtAppSetExitFlag (context);
1499 else if (buf[0] == 12) /* C-l */
1501 redraw (0, win_height, 1, 1);
1506 MText *temp = mtext ();
1508 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1509 if (current_input_context)
1510 mtext_put_prop (temp, 0, 1, Mlanguage,
1511 current_input_context->im->language);
1512 insert_chars (temp);
1513 m17n_object_unref (temp);
1518 if (! keep_target_x_position)
1519 target_x_position = cursor.x;
1523 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1525 char *name = (char *) client_data;
1527 int from = -1, to = 0;
1532 filename = strdup (name);
1535 fp = fopen (filename, "w");
1538 fprintf (stderr, "Open for write fail: %s", filename);
1544 from = mtext_property_start (selection);
1545 to = mtext_property_end (selection);
1546 mtext_detach_property (selection);
1549 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1552 select_region (from, to);
1556 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1562 mtext_detach_property (selection);
1563 serialized = (int) client_data;
1565 new = mtext_deserialize (mt);
1568 MPlist *plist = mplist ();
1570 mplist_push (plist, Mt, Mface);
1571 mplist_push (plist, Mt, Mlanguage);
1572 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1573 m17n_object_unref (plist);
1577 m17n_object_unref (mt);
1579 serialized = ! serialized;
1580 nchars = mtext_len (mt);
1583 update_cursor (0, 1);
1584 redraw (0, win_height, 1, 1);
1588 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1590 XtAppSetExitFlag (context);
1596 FILE *fp = fopen (filename, "r");
1599 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1600 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1603 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1608 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1610 int data = (int) client_data;
1615 control.enable_bidi = 0;
1616 control.orientation_reversed = 0;
1620 control.enable_bidi = 1;
1621 control.orientation_reversed = data == 2;
1623 for (i = 0; i < 3; i++)
1626 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1628 XtSetArg (arg[0], XtNleftBitmap, None);
1629 XtSetValues (BidiMenus[i], arg, 1);
1632 update_cursor (cursor.from, 1);
1633 redraw (0, win_height, 1, 0);
1636 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1639 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1641 int data = (int) client_data;
1645 control.max_line_width = 0;
1648 control.max_line_width = win_width;
1649 control.line_break = (data == 1 ? NULL : line_break);
1651 for (i = 0; i < 3; i++)
1654 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1656 XtSetArg (arg[0], XtNleftBitmap, None);
1657 XtSetValues (LineBreakMenus[i], arg, 1);
1660 update_cursor (cursor.from, 1);
1661 redraw (0, win_height, 1, 0);
1665 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1667 int data = (int) client_data;
1681 control.cursor_bidi = 0, control.cursor_width = -1;
1685 control.cursor_bidi = 0, control.cursor_width = 2;
1689 control.cursor_bidi = 1;
1694 for (i = from; i < to; i++)
1697 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1699 XtSetArg (arg[0], XtNleftBitmap, None);
1700 XtSetValues (CursorMenus[i], arg, 1);
1703 redraw (0, win_height, 1, 0);
1707 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1709 int idx = (int) client_data;
1711 if (idx == -2 ? current_input_method < 0
1712 : idx == -1 ? auto_input_method
1713 : idx == current_input_method)
1716 XtSetArg (arg[0], XtNleftBitmap, None);
1717 if (auto_input_method)
1719 XtSetValues (InputMethodMenus[1], arg, 1);
1720 auto_input_method = 0;
1722 else if (current_input_method < 0)
1723 XtSetValues (InputMethodMenus[0], arg, 1);
1725 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1729 auto_input_method = 1;
1733 select_input_method (idx);
1734 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1735 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1739 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1741 int idx = (int) client_data;
1748 XtAppAddWorkProc (context, show_cursor, NULL);
1749 from = mtext_property_start (selection);
1750 to = mtext_property_end (selection);
1751 old_y1 = sel_end.y1;
1753 mtext_detach_property (selection);
1756 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1757 MTEXTPROP_REAR_STICKY);
1758 mtext_push_property (mt, from, to, prop);
1759 m17n_object_unref (prop);
1762 mtext_pop_prop (mt, from, to, Mface);
1764 update_top (top.from);
1765 update_cursor (cursor.from, 1);
1766 select_region (from, to);
1767 update_region (sel_start.y0, old_y1, sel_end.y1);
1768 if (cur.y1 > win_height)
1770 while (cur.y1 > win_height)
1773 update_cursor (cursor.from, 1);
1779 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1781 MSymbol sym = (MSymbol) client_data;
1788 XtAppAddWorkProc (context, show_cursor, NULL);
1789 from = mtext_property_start (selection);
1790 to = mtext_property_end (selection);
1791 old_y1 = sel_end.y1;
1793 mtext_detach_property (selection);
1795 mtext_put_prop (mt, from, to, Mlanguage, sym);
1797 mtext_pop_prop (mt, from, to, Mlanguage);
1800 update_top (top.from);
1801 update_cursor (cursor.from, 1);
1802 select_region (from, to);
1803 update_region (sel_start.y0, old_y1, sel_end.y1);
1804 if (cur.y1 > win_height)
1806 while (cur.y1 > win_height)
1809 update_cursor (cursor.from, 1);
1815 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1817 int narrowed = (int) client_data;
1820 MConverter *converter;
1826 from = mtext_property_start (selection);
1827 to = mtext_property_end (selection);
1836 mdump = popen ("mdump -q -p a4", "w");
1838 mdump = popen ("mdump -q", "w");
1841 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1842 mconv_encode_range (converter, mt, from, to);
1843 mconv_free_converter (converter);
1848 input_status (MInputContext *ic, MSymbol command)
1850 XFillRectangle (display, input_status_pixmap, gc_inv,
1851 0, 0, input_status_width, input_status_height);
1852 if (command == Minput_status_draw)
1856 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1857 Mface, face_input_status);
1858 if (ic->im->language != Mnil)
1859 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1860 Mlanguage, ic->im->language);
1861 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1862 &input_status_control, NULL, NULL, &rect);
1863 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1864 input_status_width - rect.width - 2, - rect.y,
1865 ic->status, 0, mtext_len (ic->status),
1866 &input_status_control);
1868 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1869 XtSetValues (CurIMStatus, arg, 1);
1873 compare_input_method (const void *elt1, const void *elt2)
1875 const MInputMethod *im1 = *(MInputMethod **) elt1;
1876 const MInputMethod *im2 = *(MInputMethod **) elt2;
1877 MSymbol lang1, lang2;
1879 if (im1->language == Mnil)
1881 if (im1->language == im2->language)
1882 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1883 if (im1->language == Mt)
1885 if (im2->language == Mt)
1887 lang1 = msymbol_get (im1->language, Mlanguage);
1888 lang2 = msymbol_get (im2->language, Mlanguage);
1889 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1893 setup_input_methods (int with_xim)
1895 MInputMethod *im = NULL;
1896 MInputXIMArgIM arg_xim;
1897 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1901 num_input_methods = mplist_length (plist);
1905 arg_xim.display = display;
1907 arg_xim.res_name = arg_xim.res_class = NULL;
1908 arg_xim.locale = NULL;
1909 arg_xim.modifier_list = NULL;
1910 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1912 num_input_methods++;
1914 input_method_table = calloc (num_input_methods, sizeof (MInputMethod *));
1916 input_method_table[i++] = im;
1917 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1919 MDatabase *mdb = mplist_value (pl);
1920 MSymbol *tag = mdatabase_tag (mdb);
1924 im = minput_open_im (tag[1], tag[2], NULL);
1926 input_method_table[i++] = im;
1930 m17n_object_unref (plist);
1931 num_input_methods = i;
1932 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
1933 compare_input_method);
1934 current_input_context = NULL;
1936 mplist_put (minput_driver->callback_list, Minput_status_start,
1937 (void *) input_status);
1938 mplist_put (minput_driver->callback_list, Minput_status_draw,
1939 (void *) input_status);
1940 mplist_put (minput_driver->callback_list, Minput_status_done,
1941 (void *) input_status);
1946 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
1950 if (num && *num > 0)
1954 for (i = 0; i < *num; i++)
1955 bytes += strlen (str[i]) + 1;
1956 msg = alloca (bytes);
1957 strcpy (msg, str[0]);
1958 for (i = 1; i < *num; i++)
1959 strcat (msg, " "), strcat (msg, str[i]);
1961 else if (cursor.from < nchars)
1963 int c = mtext_ref_char (mt, cursor.from);
1964 char *name = mchar_get_prop (c, Mname);
1968 msg = alloca (10 + strlen (name));
1969 sprintf (msg, "U+%04X %s", c, name);
1975 XtSetArg (arg[0], XtNlabel, msg);
1976 XtSetValues (MessageWidget, arg, 1);
1982 char *name1, *name2;
1983 XtCallbackProc proc;
1984 XtPointer client_data;
1989 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
1991 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
1993 MenuRec FileMenu[] =
1994 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
1995 { 0, "Save", NULL, SaveProc, NULL, -1 },
1996 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
1998 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
1999 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2001 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2002 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2004 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2007 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2009 MenuRec *rec = (MenuRec *) client_data;
2012 XtSetArg (arg[0], XtNvalue, "");
2013 XtSetArg (arg[1], XtNlabel, rec->name1);
2014 XtSetValues (FileDialogWidget, arg, 2);
2015 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2016 XtSetArg (arg[0], XtNx, x + 20);
2017 XtSetArg (arg[1], XtNy, y + 10);
2018 XtSetValues (FileShellWidget, arg, 2);
2019 XtPopup (FileShellWidget, XtGrabExclusive);
2023 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2028 XtPopdown (FileShellWidget);
2029 if ((int) client_data == 1)
2031 XtSetArg (arg[0], XtNlabel, &label);
2032 XtGetValues (FileDialogWidget, arg, 1);
2033 if (strcmp (label, FileMenu[0].name1) == 0)
2037 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2038 fp = fopen (filename, "r");
2040 m17n_object_unref (mt);
2043 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2051 nchars = mtext_len (mt);
2053 update_cursor (0, 1);
2054 redraw (0, win_height, 1, 1);
2056 else if (strcmp (label, FileMenu[2].name1) == 0)
2057 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2059 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2062 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2063 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2064 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2065 (MENU).status = (STATUS))
2069 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2070 char *menu_name, MenuRec *menus, int num_menus, char *help)
2072 Widget button, menu;
2073 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2074 <LeaveWindow>: reset() MenuHelp()\n\
2075 <BtnDown>: reset() PopupMenu()\n\
2076 <BtnUp>: highlight()";
2082 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2083 for (i = 0; i < num_menus; i++)
2094 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2096 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2098 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2100 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2104 XtSetArg (arg[0], XtNsensitive, False);
2105 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2111 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2116 trans = alloca (strlen (fmt) + strlen (help));
2117 sprintf (trans, fmt, help);
2118 XtSetArg (arg[0], XtNmenuName, menu_name);
2119 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2120 XtSetArg (arg[2], XtNinternalWidth, 2);
2121 XtSetArg (arg[3], XtNhighlightThickness, 1);
2122 XtSetArg (arg[4], XtNleft, XawChainLeft);
2123 XtSetArg (arg[5], XtNright, XawChainLeft);
2126 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2127 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2132 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2133 int *len = alloca (sizeof (int) * num_menus);
2136 XFontSetExtents *fontset_extents;
2138 XtSetArg (arg[0], XtNfontSet, &font_set);
2139 XtGetValues (button, arg, 1);
2141 fontset_extents = XExtentsOfFontSet (font_set);
2142 height = fontset_extents->max_logical_extent.height;
2143 ascent = - fontset_extents->max_logical_extent.y;
2145 for (i = 0; i < num_menus; i++)
2148 len[i] = strlen (menus[i].name2);
2149 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2150 if (max_width < width[i])
2151 max_width = width[i];
2153 for (i = 0; i < num_menus; i++)
2156 Pixmap pixmap = XCreatePixmap (display,
2157 RootWindow (display, screen),
2158 max_width, height, 1);
2159 XFillRectangle (display, pixmap, mono_gc_inv,
2160 0, 0, max_width, height);
2161 XmbDrawString (display, pixmap, font_set, mono_gc,
2162 max_width - width[i], ascent,
2163 menus[i].name2, len[i]);
2164 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2165 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2166 XtSetValues (menus[i].w, arg, 2);
2174 XtActionsRec actions[] = {
2175 {"Expose", ExposeProc},
2176 {"Configure", ConfigureProc},
2178 {"ButtonPress", ButtonProc},
2179 {"ButtonRelease", ButtonReleaseProc},
2180 {"ButtonMotion", ButtonMoveProc},
2181 {"Button2Press", Button2Proc},
2182 {"MenuHelp", MenuHelpProc}
2186 /* Print the usage of this program (the name is PROG), and exit with
2190 help_exit (char *prog, int exit_code)
2198 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2199 printf ("Display FILE on a window and allow users to edit it.\n");
2200 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2201 printf ("The following OPTIONs are available.\n");
2202 printf (" %-13s %s", "--version", "print version number\n");
2203 printf (" %-13s %s", "-h, --help", "print this message\n");
2208 main (int argc, char **argv)
2210 Widget form, BodyWidget, w;
2211 char *fontset_name = NULL;
2212 int col = 80, row = 32;
2213 /* Translation table for TextWidget. */
2214 String trans = "<Expose>: Expose()\n\
2215 <Configure>: Configure()\n\
2218 <Btn1Down>: ButtonPress()\n\
2219 <Btn1Up>: ButtonRelease()\n\
2220 <Btn1Motion>: ButtonMotion()\n\
2221 <Btn2Down>: Button2Press()";
2222 /* Translation table for the top form widget. */
2223 String trans2 = "<Key>: Key()\n\
2225 String pop_face_trans
2226 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2227 <LeaveWindow>: MenuHelp() reset()\n\
2228 <Btn1Down>: set()\n\
2229 <Btn1Up>: notify() unset()";
2230 String pop_lang_trans
2231 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2232 <LeaveWindow>: MenuHelp() reset()\n\
2233 <Btn1Down>: set()\n\
2234 <Btn1Up>: notify() unset()";
2235 int font_width, font_ascent, font_descent;
2239 setlocale (LC_ALL, "");
2240 /* Create the top shell. */
2241 XtSetLanguageProc (NULL, NULL, NULL);
2242 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2243 NULL, sessionShellWidgetClass, NULL, 0);
2244 display = XtDisplay (ShellWidget);
2245 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2247 /* Parse the remaining command line arguments. */
2248 for (i = 1; i < argc; i++)
2250 if (! strcmp (argv[i], "--help")
2251 || ! strcmp (argv[i], "-h"))
2252 help_exit (argv[0], 0);
2253 else if (! strcmp (argv[i], "--version"))
2255 printf ("medit (m17n library) %s\n", VERSION);
2256 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2259 else if (! strcmp (argv[i], "--geometry"))
2262 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2263 help_exit (argv[0], 1);
2265 else if (! strcmp (argv[i], "--fontset"))
2268 fontset_name = strdup (argv[i]);
2270 else if (! strcmp (argv[i], "--with-xim"))
2274 else if (argv[i][0] != '-')
2276 filename = strdup (argv[i]);
2280 fprintf (stderr, "Unknown option: %s", argv[i]);
2281 help_exit (argv[0], 1);
2285 help_exit (argv[0], 1);
2287 mdatabase_dir = ".";
2288 /* Initialize the m17n library. */
2290 if (merror_code != MERROR_NONE)
2291 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2293 mt = read_file (filename);
2296 nchars = mtext_len (mt);
2299 MFace *face = mface ();
2301 mface_put_prop (face, Mbackground, msymbol ("blue"));
2302 mface_put_prop (face, Mforeground, msymbol ("yellow"));
2303 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2304 m17n_object_unref (face);
2307 /* This tells ExposeProc to initialize everything. */
2310 XA_TEXT = XInternAtom (display, "TEXT", False);
2311 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2312 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2314 MPlist *plist = mplist ();
2318 mplist_put (plist, msymbol ("widget"), ShellWidget);
2321 MFontset *fontset = mfontset (fontset_name);
2324 mface_put_prop (face, Mfontset, fontset);
2325 m17n_object_unref (fontset);
2326 mplist_add (plist, Mface, face);
2327 m17n_object_unref (face);
2329 frame = mframe (plist);
2330 m17n_object_unref (plist);
2331 face_default = (MFace *) mframe_get_prop (frame, Mface);
2332 face_default_fontset = mface ();
2333 mface_put_prop (face_default_fontset, Mfontset,
2334 mface_get_prop (face_default, Mfontset));
2336 font = (MFont *) mframe_get_prop (frame, Mfont);
2337 default_font_size = (int) mfont_get_prop (font, Msize);
2340 font_width = (int) mframe_get_prop (frame, Mfont_width);
2341 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2342 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2343 win_width = font_width * col;
2344 win_height = (font_ascent + font_descent) * row;
2350 prop.color_top = prop.color_left = msymbol ("magenta");
2351 prop.color_bottom = prop.color_right = msymbol ("red");
2352 prop.inner_hmargin = prop.inner_vmargin = 1;
2353 prop.outer_hmargin = prop.outer_vmargin = 2;
2355 face_box = mface ();
2356 mface_put_prop (face_box, Mbox, &prop);
2359 face_courier = mface ();
2360 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2361 face_helvetica = mface ();
2362 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2363 face_times = mface ();
2364 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2365 face_dv_ttyogesh = mface ();
2366 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2367 face_freesans = mface ();
2368 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2369 face_freemono = mface ();
2370 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2372 face_xxx_large = mface ();
2373 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2375 MFont *latin_font = mframe_get_prop (frame, Mfont);
2376 MFont *dev_font = mfont ();
2377 MFont *thai_font = mfont ();
2378 MFont *tib_font = mfont ();
2380 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2381 MSymbol no_ctl = msymbol ("no-ctl");
2383 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2384 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2385 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2386 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2387 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2388 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2390 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2391 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2392 latin_font, Mnil, 0);
2393 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2394 dev_font, no_ctl, 0);
2395 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2396 thai_font, no_ctl, 0);
2397 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2398 tib_font, no_ctl, 0);
2399 face_no_ctl_fontset = mface ();
2400 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2401 m17n_object_unref (fontset);
2408 setup_input_methods (with_xim);
2410 gc = DefaultGC (display, screen);
2412 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2413 XtSetArg (arg[1], XtNdefaultDistance, 2);
2414 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2416 XtSetArg (arg[0], XtNborderWidth, 0);
2417 XtSetArg (arg[1], XtNdefaultDistance, 2);
2418 XtSetArg (arg[2], XtNtop, XawChainTop);
2419 XtSetArg (arg[3], XtNbottom, XawChainTop);
2420 XtSetArg (arg[4], XtNleft, XawChainLeft);
2421 XtSetArg (arg[5], XtNright, XawChainRight);
2422 XtSetArg (arg[6], XtNresizable, True);
2423 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2424 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2425 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2426 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2427 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2428 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2429 XtSetArg (arg[7], XtNfromVert, LangWidget);
2430 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2431 XtSetArg (arg[2], XtNtop, XawChainBottom);
2432 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2433 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2435 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2436 HeadWidget, NULL, 0);
2437 XtSetArg (arg[0], XtNvalue, "");
2438 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2439 FileShellWidget, arg, 1);
2440 XawDialogAddButton (FileDialogWidget, "OK",
2441 FileDialogProc, (XtPointer) 0);
2442 XawDialogAddButton (FileDialogWidget, "CANCEL",
2443 FileDialogProc, (XtPointer) 1);
2445 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2446 (char *) check_bits,
2447 check_width, check_height);
2449 unsigned long valuemask = GCForeground;
2452 values.foreground = 1;
2453 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2454 values.foreground = 0;
2455 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2462 if (num_menus < num_input_methods + 2)
2463 num_menus = num_input_methods + 2;
2464 if (num_menus < num_faces + 1)
2465 num_menus = num_faces + 1;
2466 menus = alloca (sizeof (MenuRec) * num_menus);
2468 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2469 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2470 "File I/O, Serialization, Image, Quit");
2472 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2473 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2474 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2475 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2476 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2477 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2478 w = create_menu_button (ShellWidget, HeadWidget, w,
2479 "Cursor", "Cursor Menu",
2480 menus, 6, "Cursor Movement Mode, Cursor Shape");
2481 CursorMenus[0] = menus[0].w;
2482 CursorMenus[1] = menus[1].w;
2483 CursorMenus[2] = menus[3].w;
2484 CursorMenus[3] = menus[4].w;
2485 CursorMenus[4] = menus[5].w;
2487 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2488 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2489 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2490 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2491 menus, 3, "BIDI Processing Mode");
2492 for (i = 0; i < 3; i++)
2493 BidiMenus[i] = menus[i].w;
2495 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2496 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2497 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2498 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2500 menus, 3, "How to break lines");
2501 for (i = 0; i < 3; i++)
2502 LineBreakMenus[i] = menus[i].w;
2504 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2505 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2506 for (i = 0; i < num_input_methods; i++)
2508 MInputMethod *im = input_method_table[i];
2509 char *name1, *name2;
2511 if (im->language != Mnil && im->language != Mt)
2513 MSymbol sym = msymbol_get (im->language, Mlanguage);
2515 name1 = msymbol_name (im->language);
2517 name1 = msymbol_name (sym);
2518 name2 = msymbol_name (im->name);
2521 name1 = msymbol_name (im->name), name2 = NULL;
2523 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2525 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2526 "Input Method Menu", menus, i + 2,
2527 "Select input method");
2530 unsigned long valuemask = GCForeground;
2533 XtSetArg (arg[0], XtNbackground, &values.foreground);
2534 XtGetValues (w, arg, 1);
2535 gc_inv = XCreateGC (display, RootWindow (display, screen),
2536 valuemask, &values);
2539 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2540 for (i = 0; i < num_input_methods + 2; i++)
2541 InputMethodMenus[i] = menus[i].w;
2543 input_status_width = font_width * 8;
2544 input_status_height = (font_ascent + font_descent) * 2.4;
2545 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2547 input_status_height,
2548 DefaultDepth (display, screen));
2553 prop.color_top = prop.color_bottom
2554 = prop.color_left = prop.color_right = Mnil;
2555 prop.inner_hmargin = prop.inner_vmargin = 1;
2556 prop.outer_hmargin = prop.outer_vmargin = 0;
2557 face_input_status = mface ();
2558 mface_put_prop (face_input_status, Mbox, &prop);
2561 XFillRectangle (display, input_status_pixmap, gc_inv,
2562 0, 0, input_status_width, input_status_height);
2563 XtSetArg (arg[0], XtNfromHoriz, w);
2564 XtSetArg (arg[1], XtNleft, XawRubber);
2565 XtSetArg (arg[2], XtNright, XawChainRight);
2566 XtSetArg (arg[3], XtNborderWidth, 0);
2567 XtSetArg (arg[4], XtNlabel, " ");
2568 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2569 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2570 HeadWidget, arg, 6);
2571 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2572 XtSetArg (arg[1], XtNleft, XawChainRight);
2573 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2574 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2575 HeadWidget, arg, 5);
2577 XtSetArg (arg[0], XtNborderWidth, 0);
2578 XtSetArg (arg[1], XtNleft, XawChainLeft);
2579 XtSetArg (arg[2], XtNright, XawChainLeft);
2580 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2581 for (i = 0; i < num_faces;)
2583 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2584 char *label = label_menu + 5; /* "Xxxx" */
2586 for (j = i; j < num_faces && face_table[j].face; j++)
2587 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2589 w = create_menu_button (ShellWidget, FaceWidget, w,
2591 menus, j - i, "Push face property");
2595 XtSetArg (arg[0], XtNfromHoriz, w);
2596 XtSetArg (arg[1], XtNleft, XawChainLeft);
2597 XtSetArg (arg[2], XtNright, XawChainLeft);
2598 XtSetArg (arg[3], XtNhorizDistance, 10);
2599 XtSetArg (arg[4], XtNlabel, "Pop");
2600 XtSetArg (arg[5], XtNtranslations,
2601 XtParseTranslationTable (pop_face_trans));
2602 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2603 FaceWidget, arg, 6);
2604 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2606 XtSetArg (arg[0], XtNfromHoriz, w);
2607 XtSetArg (arg[1], XtNleft, XawChainLeft);
2608 XtSetArg (arg[2], XtNright, XawChainRight);
2609 XtSetArg (arg[3], XtNlabel, "");
2610 XtSetArg (arg[4], XtNborderWidth, 0);
2611 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2612 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2613 FaceWidget, arg, 6);
2615 XtSetArg (arg[0], XtNborderWidth, 0);
2616 XtSetArg (arg[1], XtNleft, XawChainLeft);
2617 XtSetArg (arg[2], XtNright, XawChainLeft);
2618 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2620 MPlist *plist[11], *pl;
2623 for (i = 0; i < 11; i++) plist[i] = NULL;
2625 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2626 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2628 MSymbol sym = msymbol_exist (langname);
2632 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2634 char *name = msymbol_name (fullname);
2637 if (c >= 'A' && c <= 'Z')
2639 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2643 pl = plist[idx] = mplist ();
2644 for (; mplist_next (pl); pl = mplist_next (pl))
2645 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2647 mplist_push (pl, sym, fullname);
2652 for (i = 0; i < 11; i++)
2655 char *name = alloca (9);
2657 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2660 for (j = 0, pl = plist[i]; mplist_next (pl);
2661 j++, pl = mplist_next (pl))
2662 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2663 msymbol_name (mplist_key (pl)),
2664 LangProc, mplist_key (pl), -1);
2665 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2666 menus, j, "Push language property");
2668 for (i = 0; i < 11; i++)
2670 m17n_object_unref (plist[i]);
2672 XtSetArg (arg[0], XtNfromHoriz, w);
2673 XtSetArg (arg[1], XtNleft, XawChainLeft);
2674 XtSetArg (arg[2], XtNright, XawChainLeft);
2675 XtSetArg (arg[3], XtNhorizDistance, 10);
2676 XtSetArg (arg[4], XtNlabel, "Pop");
2677 XtSetArg (arg[5], XtNtranslations,
2678 XtParseTranslationTable (pop_lang_trans));
2679 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2680 LangWidget, arg, 6);
2681 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2683 XtSetArg (arg[0], XtNfromHoriz, w);
2684 XtSetArg (arg[1], XtNleft, XawChainLeft);
2685 XtSetArg (arg[2], XtNright, XawChainRight);
2686 XtSetArg (arg[3], XtNlabel, "");
2687 XtSetArg (arg[4], XtNborderWidth, 0);
2688 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2689 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2690 LangWidget, arg, 6);
2693 XtSetArg (arg[0], XtNheight, win_height);
2694 XtSetArg (arg[1], XtNwidth, 10);
2695 XtSetArg (arg[2], XtNleft, XawChainLeft);
2696 XtSetArg (arg[3], XtNright, XawChainLeft);
2697 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2699 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2700 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2702 XtSetArg (arg[0], XtNheight, win_height);
2703 XtSetArg (arg[1], XtNwidth, win_width);
2704 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2705 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2706 XtSetArg (arg[4], XtNleft, XawChainLeft);
2707 XtSetArg (arg[5], XtNright, XawChainRight);
2708 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2711 XtSetArg (arg[0], XtNborderWidth, 0);
2712 XtSetArg (arg[1], XtNleft, XawChainLeft);
2713 XtSetArg (arg[2], XtNright, XawChainRight);
2714 XtSetArg (arg[3], XtNresizable, True);
2715 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2716 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2717 TailWidget, arg, 5);
2719 memset (&control, 0, sizeof control);
2720 control.two_dimensional = 1;
2721 control.enable_bidi = 1;
2723 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 */