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;
360 if (clear || control.anti_alias)
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)
711 MFaceHLineProp *hline;
717 update_cursor (cursor.from, 1);
719 while (cur.y1 > win_height)
722 update_cursor (cursor.from, 1);
725 control.cursor_pos = cursor.from;
728 control.with_cursor = 1;
731 if (current_input_context)
732 set_input_method_spot ();
735 int pos = (SELECTEDP () ? mtext_property_start (selection)
736 : cursor.from > 0 ? cursor.from - 1
738 MFace *face = mface ();
739 MTextProperty *props[256];
740 int n = mtext_get_properties (mt, pos, Mface, props, 256);
742 char buf[256], *p = buf;
748 int size = (int) mfont_get_prop (cursor.font, Msize);
749 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
750 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
751 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
752 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
754 sprintf (p, "%dpt", size / 10), p += strlen (p);
756 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
758 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
760 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
762 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
766 mface_merge (face, face_default);
767 for (i = 0; i < n; i++)
768 if (props[i] != selection)
769 mface_merge (face, (MFace *) mtext_property_value (props[i]));
770 sym = (MSymbol) mface_get_prop (face, Mforeground);
772 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
773 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
774 strcat (p, ",rev"), p += strlen (p);
775 hline = mface_get_prop (face, Mhline);
776 if (hline && hline->width > 0)
777 strcat (p, ",ul"), p += strlen (p);
778 box = mface_get_prop (face, Mbox);
779 if (box && box->width > 0)
780 strcat (p, ",box"), p += strlen (p);
781 m17n_object_unref (face);
783 XtSetArg (arg[0], XtNborderWidth, 1);
784 XtSetArg (arg[1], XtNlabel, buf);
785 XtSetValues (CurFaceWidget, arg, 2);
788 if (control.cursor_pos < nchars)
792 if (control.cursor_pos > 0
793 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
794 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
796 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
800 XtSetArg (arg[0], XtNborderWidth, 0);
801 XtSetArg (arg[1], XtNlabel, "");
805 XtSetArg (arg[0], XtNborderWidth, 1);
806 XtSetArg (arg[1], XtNlabel,
807 msymbol_name (msymbol_get (sym, Mlanguage)));
808 XtSetValues (CurLangWidget, arg, 2);
810 XtSetValues (CurLangWidget, arg, 2);
812 if (auto_input_method)
815 select_input_method (-1);
820 for (i = 0; i < num_input_methods; i++)
821 if (input_method_table[i]->language == sym)
823 if (i < num_input_methods)
824 select_input_method (i);
826 select_input_method (-1);
831 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
837 /* Hide the cursor. */
841 control.with_cursor = 0;
843 XtAppAddWorkProc (context, show_cursor, NULL);
847 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
848 $Y1 and $NEW_Y1 assuming that the text in the other area is not
851 update_region (int y0, int old_y1, int new_y1)
857 if (old_y1 < win_height)
859 COPY_AREA (old_y1, win_height, new_y1);
860 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
863 redraw (new_y1, win_height, 1, 0);
865 else if (new_y1 > old_y1)
867 if (new_y1 < win_height)
868 COPY_AREA (old_y1, win_height, new_y1);
870 if (new_y1 > win_height)
872 redraw (y0, new_y1, 1, 1);
876 /* Delete the next $N characters. If $N is negative delete the
877 precious (- $N) characters. */
887 from = cursor.from, to = from + n;
890 if (cursor.from == cur.from)
892 /* We are at the beginning of line. */
893 int pos = cursor.prev_from;
895 if (cursor.from == top.from)
897 /* We are at the beginning of screen. We must scroll
899 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
900 reseat (info.line_from);
902 update_cursor (pos, 1);
908 from = cursor.from - 1;
913 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
914 old_y1 = cur.y0 + rect.height;
916 /* Now delete a character. */
917 mtext_del (mt, from, to);
919 if (from >= top.from && from < top.to)
920 update_top (top.from);
921 update_cursor (from, 1);
923 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
924 new_y1 = cur.y0 + rect.height;
926 update_region (cur.y0, old_y1, new_y1);
930 /* Insert M-text $NEWTEXT at the current cursor position. */
932 insert_chars (MText *newtext)
934 int n = mtext_len (newtext);
936 int y0, old_y1, new_y1;
940 int n = (mtext_property_end (selection)
941 - mtext_property_start (selection));
942 mtext_detach_property (selection);
947 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
948 old_y1 = y0 + rect.height;
950 /* Now insert chars. */
951 mtext_ins (mt, cursor.from, newtext);
953 if (cur.from == top.from)
954 update_top (top.from);
955 update_cursor (cursor.from + n, 1);
957 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
958 new_y1 = cur.y0 + rect.height;
960 update_region (y0, old_y1, new_y1);
965 /* Convert the currently selected text to COMPOUND-TEXT. It is called
966 when someone requests the current value of the selection. */
968 covert_selection (Widget w, Atom *selection_atom,
969 Atom *target, Atom *return_type,
970 XtPointer *value, unsigned long *length, int *format)
972 unsigned char *buf = (unsigned char *) XtMalloc (4096);
973 MText *this_mt = mtext ();
974 int from = mtext_property_start (selection);
975 int to = mtext_property_end (selection);
977 mtext_copy (this_mt, 0, mt, from, to);
978 *length = mconv_encode_buffer (msymbol ("compound-text"),
980 *return_type = XA_COMPOUND_TEXT;
981 *value = (XtPointer) buf;
983 m17n_object_unref (this_mt);
988 /* Unselect the text. It is called when we loose the selection. */
990 lose_selection (Widget w, Atom *selection_atom)
994 mtext_detach_property (selection);
995 redraw (sel_start.y0, sel_end.y1, 1, 0);
1000 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1001 XtPointer value, unsigned long *length, int *format)
1006 if (*type == XT_CONVERT_FAIL || ! value)
1008 if (*type == XA_STRING)
1010 else if (*type == XA_COMPOUND_TEXT)
1011 coding = msymbol ("compound-text");
1012 else if (*type == XA_UTF8_STRING)
1013 coding = msymbol ("utf-8");
1017 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1021 insert_chars (this_mt);
1022 m17n_object_unref (this_mt);
1031 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1033 XExposeEvent *expose = (XExposeEvent *) event;
1037 Dimension width_max, width;
1039 XtSetArg (arg[0], XtNwidth, &width);
1040 XtGetValues (XtParent (w), arg, 1);
1042 XtGetValues (HeadWidget, arg, 1);
1043 if (width_max < width)
1045 XtGetValues (FaceWidget, arg, 1);
1046 if (width_max < width)
1048 XtGetValues (LangWidget, arg, 1);
1049 if (width_max < width)
1051 XtSetArg (arg[0], XtNwidth, width_max);
1052 XtSetValues (HeadWidget, arg, 1);
1053 XtSetValues (FaceWidget, arg, 1);
1054 XtSetValues (LangWidget, arg, 1);
1055 XtSetValues (XtParent (w), arg, 1);
1056 XtSetValues (TailWidget, arg, 1);
1059 update_cursor (0, 1);
1060 redraw (0, win_height, 0, 1);
1065 redraw (expose->y, expose->y + expose->height, 0, 0);
1066 if (current_input_context
1067 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1068 set_input_method_spot ();
1073 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1075 XConfigureEvent *configure = (XConfigureEvent *) event;
1078 control.max_line_width = win_width = configure->width;
1079 win_height = configure->height;
1080 mdraw_clear_cache (mt);
1082 update_cursor (0, 1);
1083 redraw (0, win_height, 1, 1);
1084 if (current_input_context)
1085 set_input_method_spot ();
1089 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1092 int x = event->xbutton.x;
1093 int y = event->xbutton.y - top.ascent;
1095 if (control.orientation_reversed)
1097 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1100 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1101 mtext_detach_property (selection);
1102 redraw (sel_start.y0, sel_end.y1, 1, 0);
1105 update_cursor (pos, 0);
1110 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1115 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1116 covert_selection, lose_selection, NULL);
1117 update_cursor (mtext_property_start (selection), 0);
1122 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1126 /* We don't have a local selection. */
1127 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1132 int from = mtext_property_start (selection);
1133 int to = mtext_property_end (selection);
1136 int x = event->xbutton.x;
1137 int y = event->xbutton.y - top.ascent;
1139 if (control.orientation_reversed)
1141 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1143 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1144 mtext_detach_property (selection);
1146 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1147 update_cursor (pos, 0);
1148 insert_chars (this_mt);
1149 m17n_object_unref (this_mt);
1154 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1157 int x = event->xbutton.x;
1158 int y = event->xbutton.y;
1160 if (control.orientation_reversed)
1163 pos = top.from, y -= top.ascent;
1165 pos = cur.from, y -= cur.y0 + cur.ascent;
1166 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1168 if (pos == cursor.from)
1174 /* Selection range changed. */
1175 int from = mtext_property_start (selection);
1176 int to = mtext_property_end (selection);
1177 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1178 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1180 if (cursor.from == from)
1182 /* Starting position changed. */
1185 /* Enlarged. We can simply overdraw. */
1186 select_region (pos, to);
1187 redraw (sel_start.y0, start_y1, 0, 0);
1191 /* Shrunken. Previous selection face must be cleared. */
1192 select_region (pos, to);
1193 redraw (start_y0, sel_start.y1, 1, 0);
1197 /* Shrunken to zero. */
1198 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1199 mtext_detach_property (selection);
1200 redraw (start_y0, end_y1, 1, 0);
1204 /* Full update is necessary. */
1205 select_region (to, pos);
1206 redraw (start_y0, sel_end.y1, 1, 0);
1211 /* Ending position changed. */
1214 /* Full update is necessary. */
1215 select_region (pos, from);
1216 redraw (sel_start.y0, end_y1, 1, 0);
1218 else if (pos == from)
1220 /* Shrunken to zero. */
1221 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1222 mtext_detach_property (selection);
1223 redraw (start_y0, end_y1, 1, 0);
1227 /* Shrunken. Previous selection face must be cleared. */
1228 select_region (from, pos);
1229 redraw (sel_end.y0, end_y1, 1, 0);
1233 /* Enlarged. We can simply overdraw. */
1234 select_region (from, pos);
1235 redraw (end_y0, sel_end.y1, 0, 0);
1241 /* Newly selected. */
1242 select_region (pos, cursor.from);
1243 redraw (sel_start.y0, sel_end.y1, 0, 0);
1245 update_cursor (pos, 1);
1249 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1252 MDrawGlyphInfo info;
1254 int cursor_pos = cursor.from;
1256 if (((int) position) < 0)
1262 height = top.y1 - top.y0;
1265 pos = bol (from - 1, 0);
1266 GLYPH_INFO (pos, from - 1, info);
1267 if (height + info.this.height > win_height)
1269 height += info.this.height;
1270 from = info.line_from;
1272 if (cursor_pos >= top.to)
1274 cursor_pos = top.from;
1276 while (cursor_pos < nchars)
1278 GLYPH_INFO (pos, pos, info);
1279 if (height + info.this.height > win_height)
1281 height += info.this.height;
1287 else if (cur.to < nchars)
1289 /* Scroll up, but leave at least one line. */
1292 while (from < nchars)
1294 GLYPH_INFO (from, from, info);
1295 if (height + info.this.height > win_height
1296 || info.line_to >= nchars)
1298 height += info.this.height;
1299 from = info.line_to;
1302 from = info.line_from;
1303 if (cursor_pos < from)
1307 /* Scroll up to make the cursor line top. */
1311 update_cursor (cursor_pos, 1);
1315 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1317 float persent = *(float *) persent_ptr;
1318 int pos1, pos2 = nchars * persent;
1319 MDrawGlyphInfo info;
1322 pos1 = bol (pos2, 0);
1323 GLYPH_INFO (pos1, pos2, info);
1324 pos1 = info.line_from;
1326 update_cursor (pos1, 1);
1331 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1333 XKeyEvent *key_event = (XKeyEvent *) event;
1335 KeySym keysym = NoSymbol;
1337 /* If set to 1, do not update target_x_position. */
1338 int keep_target_x_position = 0;
1341 if (current_input_context
1342 && minput_filter (current_input_context, Mnil, event))
1344 if (event->type == KeyRelease)
1349 produced = mtext ();
1350 ret = minput_lookup (current_input_context, Mnil, event, produced);
1351 if (mtext_len (produced) > 0)
1352 insert_chars (produced);
1354 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1355 m17n_object_unref (produced);
1365 n = (mtext_property_end (selection)
1366 - mtext_property_start (selection));
1367 mtext_detach_property (selection);
1369 else if (cursor.from < nchars)
1371 /* Delete the following grapheme cluster. */
1372 n = cursor.to - cursor.from;
1385 /* Delete selected region. */
1386 n = (mtext_property_end (selection)
1387 - mtext_property_start (selection));
1388 mtext_detach_property (selection);
1390 else if (cursor.from > 0)
1392 /* Delete the preceding character. */
1403 mtext_detach_property (selection);
1404 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1408 if (cursor.prev_from >= 0)
1409 update_cursor (cursor.prev_from, 0);
1413 if (cursor.left_from >= 0)
1414 update_cursor (cursor.left_from, 0);
1421 mtext_detach_property (selection);
1422 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1426 if (cursor.next_to >= 0)
1427 update_cursor (cursor.to, 0);
1431 if (cursor.right_from >= 0)
1432 update_cursor (cursor.right_from, 0);
1439 mtext_detach_property (selection);
1440 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1442 if (cur.to <= nchars)
1444 MDrawGlyphInfo info;
1447 GLYPH_INFO (cur.from, cur.to, info);
1448 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1449 target_x_position, info.y);
1450 keep_target_x_position = 1;
1451 update_cursor (pos, 0);
1458 mtext_detach_property (selection);
1459 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1465 int pos = bol (cur.from - 1, 0);
1467 TEXT_EXTENTS (pos, cur.from - 1, rect);
1468 y = rect.height + rect.y - 1;
1469 pos = COORDINATES_POSITION (pos, nchars,
1470 target_x_position, y);
1471 keep_target_x_position = 1;
1472 update_cursor (pos, 0);
1479 mtext_detach_property (selection);
1480 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1482 if (top.from < nchars)
1483 ScrollProc (w, NULL, (XtPointer) 1);
1489 mtext_detach_property (selection);
1490 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1493 ScrollProc (w, NULL, (XtPointer) -1);
1499 if (buf[0] == 17) /* C-q */
1501 XtAppSetExitFlag (context);
1504 else if (buf[0] == 12) /* C-l */
1506 redraw (0, win_height, 1, 1);
1511 MText *temp = mtext ();
1513 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1514 if (current_input_context)
1515 mtext_put_prop (temp, 0, 1, Mlanguage,
1516 current_input_context->im->language);
1517 insert_chars (temp);
1518 m17n_object_unref (temp);
1523 if (! keep_target_x_position)
1524 target_x_position = cursor.x;
1528 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1530 char *name = (char *) client_data;
1532 int from = -1, to = 0;
1537 filename = strdup (name);
1540 fp = fopen (filename, "w");
1543 fprintf (stderr, "Open for write fail: %s", filename);
1549 from = mtext_property_start (selection);
1550 to = mtext_property_end (selection);
1551 mtext_detach_property (selection);
1554 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1557 select_region (from, to);
1561 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1567 mtext_detach_property (selection);
1568 serialized = (int) client_data;
1570 new = mtext_deserialize (mt);
1573 MPlist *plist = mplist ();
1575 mplist_push (plist, Mt, Mface);
1576 mplist_push (plist, Mt, Mlanguage);
1577 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1578 m17n_object_unref (plist);
1582 m17n_object_unref (mt);
1584 serialized = ! serialized;
1585 nchars = mtext_len (mt);
1588 update_cursor (0, 1);
1589 redraw (0, win_height, 1, 1);
1593 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1595 XtAppSetExitFlag (context);
1601 FILE *fp = fopen (filename, "r");
1604 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1605 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1608 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1613 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1615 int data = (int) client_data;
1620 control.enable_bidi = 0;
1621 control.orientation_reversed = 0;
1625 control.enable_bidi = 1;
1626 control.orientation_reversed = data == 2;
1628 for (i = 0; i < 3; i++)
1631 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1633 XtSetArg (arg[0], XtNleftBitmap, None);
1634 XtSetValues (BidiMenus[i], arg, 1);
1637 update_cursor (cursor.from, 1);
1638 redraw (0, win_height, 1, 0);
1641 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1644 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1646 int data = (int) client_data;
1650 control.max_line_width = 0;
1653 control.max_line_width = win_width;
1654 control.line_break = (data == 1 ? NULL : line_break);
1656 for (i = 0; i < 3; i++)
1659 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1661 XtSetArg (arg[0], XtNleftBitmap, None);
1662 XtSetValues (LineBreakMenus[i], arg, 1);
1665 update_cursor (cursor.from, 1);
1666 redraw (0, win_height, 1, 0);
1670 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1672 int data = (int) client_data;
1686 control.cursor_bidi = 0, control.cursor_width = -1;
1690 control.cursor_bidi = 0, control.cursor_width = 2;
1694 control.cursor_bidi = 1;
1699 for (i = from; i < to; i++)
1702 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1704 XtSetArg (arg[0], XtNleftBitmap, None);
1705 XtSetValues (CursorMenus[i], arg, 1);
1708 redraw (0, win_height, 1, 0);
1712 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1714 int idx = (int) client_data;
1716 if (idx == -2 ? current_input_method < 0
1717 : idx == -1 ? auto_input_method
1718 : idx == current_input_method)
1721 XtSetArg (arg[0], XtNleftBitmap, None);
1722 if (auto_input_method)
1724 XtSetValues (InputMethodMenus[1], arg, 1);
1725 auto_input_method = 0;
1727 else if (current_input_method < 0)
1728 XtSetValues (InputMethodMenus[0], arg, 1);
1730 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1734 auto_input_method = 1;
1738 select_input_method (idx);
1739 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1740 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1743 MPlist *default_face_list;
1746 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1748 int idx = (int) client_data;
1758 MFace *face = mframe_get_prop (frame, Mface);
1760 for (plist = default_face_list; mplist_key (plist) != Mnil;
1761 plist = mplist_next (plist))
1762 mface_merge (face, mplist_value (plist));
1763 mplist_add (plist, Mt, *face_table[idx].face);
1764 mface_merge (face, *face_table[idx].face);
1766 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1768 MFace *face = mframe_get_prop (frame, Mface);
1770 for (plist = default_face_list;
1771 mplist_key (mplist_next (plist)) != Mnil;
1772 plist = mplist_next (plist))
1773 mface_merge (face, mplist_value (plist));
1777 update_cursor (0, 1);
1778 redraw (0, win_height, 1, 1);
1783 XtAppAddWorkProc (context, show_cursor, NULL);
1784 from = mtext_property_start (selection);
1785 to = mtext_property_end (selection);
1786 old_y1 = sel_end.y1;
1788 mtext_detach_property (selection);
1791 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1792 MTEXTPROP_REAR_STICKY);
1793 mtext_push_property (mt, from, to, prop);
1794 m17n_object_unref (prop);
1797 mtext_pop_prop (mt, from, to, Mface);
1799 update_top (top.from);
1800 update_cursor (cursor.from, 1);
1801 select_region (from, to);
1802 update_region (sel_start.y0, old_y1, sel_end.y1);
1803 if (cur.y1 > win_height)
1805 while (cur.y1 > win_height)
1808 update_cursor (cursor.from, 1);
1814 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1816 MSymbol sym = (MSymbol) client_data;
1823 XtAppAddWorkProc (context, show_cursor, NULL);
1824 from = mtext_property_start (selection);
1825 to = mtext_property_end (selection);
1826 old_y1 = sel_end.y1;
1828 mtext_detach_property (selection);
1830 mtext_put_prop (mt, from, to, Mlanguage, sym);
1832 mtext_pop_prop (mt, from, to, Mlanguage);
1835 update_top (top.from);
1836 update_cursor (cursor.from, 1);
1837 select_region (from, to);
1838 update_region (sel_start.y0, old_y1, sel_end.y1);
1839 if (cur.y1 > win_height)
1841 while (cur.y1 > win_height)
1844 update_cursor (cursor.from, 1);
1850 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1852 int narrowed = (int) client_data;
1855 MConverter *converter;
1861 from = mtext_property_start (selection);
1862 to = mtext_property_end (selection);
1871 mdump = popen ("mdump -q -p a4", "w");
1873 mdump = popen ("mdump -q", "w");
1876 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1877 mconv_encode_range (converter, mt, from, to);
1878 mconv_free_converter (converter);
1883 input_status (MInputContext *ic, MSymbol command)
1885 XFillRectangle (display, input_status_pixmap, gc_inv,
1886 0, 0, input_status_width, input_status_height);
1887 if (command == Minput_status_draw)
1891 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1892 Mface, face_input_status);
1893 if (ic->im->language != Mnil)
1894 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1895 Mlanguage, ic->im->language);
1896 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1897 &input_status_control, NULL, NULL, &rect);
1898 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1899 input_status_width - rect.width - 2, - rect.y,
1900 ic->status, 0, mtext_len (ic->status),
1901 &input_status_control);
1903 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1904 XtSetValues (CurIMStatus, arg, 1);
1908 compare_input_method (const void *elt1, const void *elt2)
1910 const MInputMethod *im1 = *(MInputMethod **) elt1;
1911 const MInputMethod *im2 = *(MInputMethod **) elt2;
1912 MSymbol lang1, lang2;
1914 if (im1->language == Mnil)
1916 if (im1->language == im2->language)
1917 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1918 if (im1->language == Mt)
1920 if (im2->language == Mt)
1922 lang1 = msymbol_get (im1->language, Mlanguage);
1923 lang2 = msymbol_get (im2->language, Mlanguage);
1924 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1928 setup_input_methods (int with_xim)
1930 MInputMethod *im = NULL;
1931 MInputXIMArgIM arg_xim;
1932 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1936 num_input_methods = mplist_length (plist);
1940 arg_xim.display = display;
1942 arg_xim.res_name = arg_xim.res_class = NULL;
1943 arg_xim.locale = NULL;
1944 arg_xim.modifier_list = NULL;
1945 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1947 num_input_methods++;
1949 input_method_table = calloc (num_input_methods, sizeof (MInputMethod *));
1951 input_method_table[i++] = im;
1952 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1954 MDatabase *mdb = mplist_value (pl);
1955 MSymbol *tag = mdatabase_tag (mdb);
1959 im = minput_open_im (tag[1], tag[2], NULL);
1961 input_method_table[i++] = im;
1965 m17n_object_unref (plist);
1966 num_input_methods = i;
1967 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
1968 compare_input_method);
1969 current_input_context = NULL;
1971 mplist_put (minput_driver->callback_list, Minput_status_start,
1972 (void *) input_status);
1973 mplist_put (minput_driver->callback_list, Minput_status_draw,
1974 (void *) input_status);
1975 mplist_put (minput_driver->callback_list, Minput_status_done,
1976 (void *) input_status);
1981 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
1985 if (num && *num > 0)
1989 for (i = 0; i < *num; i++)
1990 bytes += strlen (str[i]) + 1;
1991 msg = alloca (bytes);
1992 strcpy (msg, str[0]);
1993 for (i = 1; i < *num; i++)
1994 strcat (msg, " "), strcat (msg, str[i]);
1996 else if (cursor.from < nchars)
1998 int c = mtext_ref_char (mt, cursor.from);
1999 char *name = mchar_get_prop (c, Mname);
2003 msg = alloca (10 + strlen (name));
2004 sprintf (msg, "U+%04X %s", c, name);
2010 XtSetArg (arg[0], XtNlabel, msg);
2011 XtSetValues (MessageWidget, arg, 1);
2017 char *name1, *name2;
2018 XtCallbackProc proc;
2019 XtPointer client_data;
2024 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2026 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2028 MenuRec FileMenu[] =
2029 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2030 { 0, "Save", NULL, SaveProc, NULL, -1 },
2031 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2033 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2034 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2036 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2037 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2039 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2042 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2044 MenuRec *rec = (MenuRec *) client_data;
2047 XtSetArg (arg[0], XtNvalue, "");
2048 XtSetArg (arg[1], XtNlabel, rec->name1);
2049 XtSetValues (FileDialogWidget, arg, 2);
2050 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2051 XtSetArg (arg[0], XtNx, x + 20);
2052 XtSetArg (arg[1], XtNy, y + 10);
2053 XtSetValues (FileShellWidget, arg, 2);
2054 XtPopup (FileShellWidget, XtGrabExclusive);
2058 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2063 XtPopdown (FileShellWidget);
2064 if ((int) client_data == 1)
2066 XtSetArg (arg[0], XtNlabel, &label);
2067 XtGetValues (FileDialogWidget, arg, 1);
2068 if (strcmp (label, FileMenu[0].name1) == 0)
2072 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2073 fp = fopen (filename, "r");
2075 m17n_object_unref (mt);
2078 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2086 nchars = mtext_len (mt);
2088 update_cursor (0, 1);
2089 redraw (0, win_height, 1, 1);
2091 else if (strcmp (label, FileMenu[2].name1) == 0)
2092 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2094 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2097 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2098 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2099 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2100 (MENU).status = (STATUS))
2104 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2105 char *menu_name, MenuRec *menus, int num_menus, char *help)
2107 Widget button, menu;
2108 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2109 <LeaveWindow>: reset() MenuHelp()\n\
2110 <BtnDown>: reset() PopupMenu()\n\
2111 <BtnUp>: highlight()";
2117 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2118 for (i = 0; i < num_menus; i++)
2129 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2131 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2133 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2135 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2139 XtSetArg (arg[0], XtNsensitive, False);
2140 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2146 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2151 trans = alloca (strlen (fmt) + strlen (help));
2152 sprintf (trans, fmt, help);
2153 XtSetArg (arg[0], XtNmenuName, menu_name);
2154 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2155 XtSetArg (arg[2], XtNinternalWidth, 2);
2156 XtSetArg (arg[3], XtNhighlightThickness, 1);
2157 XtSetArg (arg[4], XtNleft, XawChainLeft);
2158 XtSetArg (arg[5], XtNright, XawChainLeft);
2161 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2162 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2167 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2168 int *len = alloca (sizeof (int) * num_menus);
2171 XFontSetExtents *fontset_extents;
2173 XtSetArg (arg[0], XtNfontSet, &font_set);
2174 XtGetValues (button, arg, 1);
2176 fontset_extents = XExtentsOfFontSet (font_set);
2177 height = fontset_extents->max_logical_extent.height;
2178 ascent = - fontset_extents->max_logical_extent.y;
2180 for (i = 0; i < num_menus; i++)
2183 len[i] = strlen (menus[i].name2);
2184 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2185 if (max_width < width[i])
2186 max_width = width[i];
2188 for (i = 0; i < num_menus; i++)
2191 Pixmap pixmap = XCreatePixmap (display,
2192 RootWindow (display, screen),
2193 max_width, height, 1);
2194 XFillRectangle (display, pixmap, mono_gc_inv,
2195 0, 0, max_width, height);
2196 XmbDrawString (display, pixmap, font_set, mono_gc,
2197 max_width - width[i], ascent,
2198 menus[i].name2, len[i]);
2199 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2200 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2201 XtSetValues (menus[i].w, arg, 2);
2209 XtActionsRec actions[] = {
2210 {"Expose", ExposeProc},
2211 {"Configure", ConfigureProc},
2213 {"ButtonPress", ButtonProc},
2214 {"ButtonRelease", ButtonReleaseProc},
2215 {"ButtonMotion", ButtonMoveProc},
2216 {"Button2Press", Button2Proc},
2217 {"MenuHelp", MenuHelpProc}
2221 /* Print the usage of this program (the name is PROG), and exit with
2225 help_exit (char *prog, int exit_code)
2233 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2234 printf ("Display FILE on a window and allow users to edit it.\n");
2235 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2236 printf ("The following OPTIONs are available.\n");
2237 printf (" %-13s %s", "--version", "print version number\n");
2238 printf (" %-13s %s", "-h, --help", "print this message\n");
2243 main (int argc, char **argv)
2245 Widget form, BodyWidget, w;
2246 char *fontset_name = NULL;
2247 int col = 80, row = 32;
2248 /* Translation table for TextWidget. */
2249 String trans = "<Expose>: Expose()\n\
2250 <Configure>: Configure()\n\
2253 <Btn1Down>: ButtonPress()\n\
2254 <Btn1Up>: ButtonRelease()\n\
2255 <Btn1Motion>: ButtonMotion()\n\
2256 <Btn2Down>: Button2Press()";
2257 /* Translation table for the top form widget. */
2258 String trans2 = "<Key>: Key()\n\
2260 String pop_face_trans
2261 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2262 <LeaveWindow>: MenuHelp() reset()\n\
2263 <Btn1Down>: set()\n\
2264 <Btn1Up>: notify() unset()";
2265 String pop_lang_trans
2266 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2267 <LeaveWindow>: MenuHelp() reset()\n\
2268 <Btn1Down>: set()\n\
2269 <Btn1Up>: notify() unset()";
2270 int font_width, font_ascent, font_descent;
2274 setlocale (LC_ALL, "");
2275 /* Create the top shell. */
2276 XtSetLanguageProc (NULL, NULL, NULL);
2277 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2278 NULL, sessionShellWidgetClass, NULL, 0);
2279 display = XtDisplay (ShellWidget);
2280 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2282 /* Parse the remaining command line arguments. */
2283 for (i = 1; i < argc; i++)
2285 if (! strcmp (argv[i], "--help")
2286 || ! strcmp (argv[i], "-h"))
2287 help_exit (argv[0], 0);
2288 else if (! strcmp (argv[i], "--version"))
2290 printf ("medit (m17n library) %s\n", VERSION);
2291 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2294 else if (! strcmp (argv[i], "--geometry"))
2297 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2298 help_exit (argv[0], 1);
2300 else if (! strcmp (argv[i], "--fontset"))
2303 fontset_name = strdup (argv[i]);
2305 else if (! strcmp (argv[i], "--with-xim"))
2309 else if (argv[i][0] != '-')
2311 filename = strdup (argv[i]);
2315 fprintf (stderr, "Unknown option: %s", argv[i]);
2316 help_exit (argv[0], 1);
2320 help_exit (argv[0], 1);
2322 mdatabase_dir = ".";
2323 /* Initialize the m17n library. */
2325 if (merror_code != MERROR_NONE)
2326 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2328 mt = read_file (filename);
2331 nchars = mtext_len (mt);
2334 MFace *face = mface ();
2336 mface_put_prop (face, Mforeground, msymbol ("blue"));
2337 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2338 mface_put_prop (face, Mvideomode, Mreverse);
2339 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2340 m17n_object_unref (face);
2343 /* This tells ExposeProc to initialize everything. */
2346 XA_TEXT = XInternAtom (display, "TEXT", False);
2347 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2348 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2350 MPlist *plist = mplist ();
2354 mplist_put (plist, msymbol ("widget"), ShellWidget);
2357 MFontset *fontset = mfontset (fontset_name);
2360 mface_put_prop (face, Mfontset, fontset);
2361 m17n_object_unref (fontset);
2362 mplist_add (plist, Mface, face);
2363 m17n_object_unref (face);
2365 frame = mframe (plist);
2366 m17n_object_unref (plist);
2367 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2368 default_face_list = mplist ();
2369 mplist_add (default_face_list, Mt, face_default);
2370 face_default_fontset = mface ();
2371 mface_put_prop (face_default_fontset, Mfontset,
2372 mface_get_prop (face_default, Mfontset));
2374 font = (MFont *) mframe_get_prop (frame, Mfont);
2375 default_font_size = (int) mfont_get_prop (font, Msize);
2378 font_width = (int) mframe_get_prop (frame, Mfont_width);
2379 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2380 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2381 win_width = font_width * col;
2382 win_height = (font_ascent + font_descent) * row;
2388 prop.color_top = prop.color_left = msymbol ("magenta");
2389 prop.color_bottom = prop.color_right = msymbol ("red");
2390 prop.inner_hmargin = prop.inner_vmargin = 1;
2391 prop.outer_hmargin = prop.outer_vmargin = 2;
2393 face_box = mface ();
2394 mface_put_prop (face_box, Mbox, &prop);
2397 face_courier = mface ();
2398 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2399 face_helvetica = mface ();
2400 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2401 face_times = mface ();
2402 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2403 face_dv_ttyogesh = mface ();
2404 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2405 face_freesans = mface ();
2406 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2407 face_freemono = mface ();
2408 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2410 face_xxx_large = mface ();
2411 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2413 MFont *latin_font = mframe_get_prop (frame, Mfont);
2414 MFont *dev_font = mfont ();
2415 MFont *thai_font = mfont ();
2416 MFont *tib_font = mfont ();
2418 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2419 MSymbol no_ctl = msymbol ("no-ctl");
2421 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2422 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2423 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2424 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2425 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2426 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2428 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2429 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2430 latin_font, Mnil, 0);
2431 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2432 dev_font, no_ctl, 0);
2433 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2434 thai_font, no_ctl, 0);
2435 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2436 tib_font, no_ctl, 0);
2437 face_no_ctl_fontset = mface ();
2438 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2439 m17n_object_unref (fontset);
2446 setup_input_methods (with_xim);
2448 gc = DefaultGC (display, screen);
2450 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2451 XtSetArg (arg[1], XtNdefaultDistance, 2);
2452 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2454 XtSetArg (arg[0], XtNborderWidth, 0);
2455 XtSetArg (arg[1], XtNdefaultDistance, 2);
2456 XtSetArg (arg[2], XtNtop, XawChainTop);
2457 XtSetArg (arg[3], XtNbottom, XawChainTop);
2458 XtSetArg (arg[4], XtNleft, XawChainLeft);
2459 XtSetArg (arg[5], XtNright, XawChainRight);
2460 XtSetArg (arg[6], XtNresizable, True);
2461 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2462 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2463 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2464 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2465 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2466 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2467 XtSetArg (arg[7], XtNfromVert, LangWidget);
2468 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2469 XtSetArg (arg[2], XtNtop, XawChainBottom);
2470 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2471 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2473 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2474 HeadWidget, NULL, 0);
2475 XtSetArg (arg[0], XtNvalue, "");
2476 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2477 FileShellWidget, arg, 1);
2478 XawDialogAddButton (FileDialogWidget, "OK",
2479 FileDialogProc, (XtPointer) 0);
2480 XawDialogAddButton (FileDialogWidget, "CANCEL",
2481 FileDialogProc, (XtPointer) 1);
2483 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2484 (char *) check_bits,
2485 check_width, check_height);
2487 unsigned long valuemask = GCForeground;
2490 values.foreground = 1;
2491 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2492 values.foreground = 0;
2493 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2500 if (num_menus < num_input_methods + 2)
2501 num_menus = num_input_methods + 2;
2502 if (num_menus < num_faces + 1)
2503 num_menus = num_faces + 1;
2504 menus = alloca (sizeof (MenuRec) * num_menus);
2506 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2507 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2508 "File I/O, Serialization, Image, Quit");
2510 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2511 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2512 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2513 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2514 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2515 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2516 w = create_menu_button (ShellWidget, HeadWidget, w,
2517 "Cursor", "Cursor Menu",
2518 menus, 6, "Cursor Movement Mode, Cursor Shape");
2519 CursorMenus[0] = menus[0].w;
2520 CursorMenus[1] = menus[1].w;
2521 CursorMenus[2] = menus[3].w;
2522 CursorMenus[3] = menus[4].w;
2523 CursorMenus[4] = menus[5].w;
2525 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2526 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2527 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2528 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2529 menus, 3, "BIDI Processing Mode");
2530 for (i = 0; i < 3; i++)
2531 BidiMenus[i] = menus[i].w;
2533 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2534 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2535 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2536 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2538 menus, 3, "How to break lines");
2539 for (i = 0; i < 3; i++)
2540 LineBreakMenus[i] = menus[i].w;
2542 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2543 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2544 for (i = 0; i < num_input_methods; i++)
2546 MInputMethod *im = input_method_table[i];
2547 char *name1, *name2;
2549 if (im->language != Mnil && im->language != Mt)
2551 MSymbol sym = msymbol_get (im->language, Mlanguage);
2553 name1 = msymbol_name (im->language);
2555 name1 = msymbol_name (sym);
2556 name2 = msymbol_name (im->name);
2559 name1 = msymbol_name (im->name), name2 = NULL;
2561 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2563 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2564 "Input Method Menu", menus, i + 2,
2565 "Select input method");
2568 unsigned long valuemask = GCForeground;
2571 XtSetArg (arg[0], XtNbackground, &values.foreground);
2572 XtGetValues (w, arg, 1);
2573 gc_inv = XCreateGC (display, RootWindow (display, screen),
2574 valuemask, &values);
2577 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2578 for (i = 0; i < num_input_methods + 2; i++)
2579 InputMethodMenus[i] = menus[i].w;
2581 input_status_width = font_width * 8;
2582 input_status_height = (font_ascent + font_descent) * 2.4;
2583 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2585 input_status_height,
2586 DefaultDepth (display, screen));
2591 prop.color_top = prop.color_bottom
2592 = prop.color_left = prop.color_right = Mnil;
2593 prop.inner_hmargin = prop.inner_vmargin = 1;
2594 prop.outer_hmargin = prop.outer_vmargin = 0;
2595 face_input_status = mface ();
2596 mface_put_prop (face_input_status, Mbox, &prop);
2599 XFillRectangle (display, input_status_pixmap, gc_inv,
2600 0, 0, input_status_width, input_status_height);
2601 XtSetArg (arg[0], XtNfromHoriz, w);
2602 XtSetArg (arg[1], XtNleft, XawRubber);
2603 XtSetArg (arg[2], XtNright, XawChainRight);
2604 XtSetArg (arg[3], XtNborderWidth, 0);
2605 XtSetArg (arg[4], XtNlabel, " ");
2606 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2607 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2608 HeadWidget, arg, 6);
2609 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2610 XtSetArg (arg[1], XtNleft, XawChainRight);
2611 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2612 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2613 HeadWidget, arg, 5);
2615 XtSetArg (arg[0], XtNborderWidth, 0);
2616 XtSetArg (arg[1], XtNleft, XawChainLeft);
2617 XtSetArg (arg[2], XtNright, XawChainLeft);
2618 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2619 for (i = 0; i < num_faces;)
2621 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2622 char *label = label_menu + 5; /* "Xxxx" */
2624 for (j = i; j < num_faces && face_table[j].face; j++)
2625 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2627 w = create_menu_button (ShellWidget, FaceWidget, w,
2629 menus, j - i, "Push face property");
2633 XtSetArg (arg[0], XtNfromHoriz, w);
2634 XtSetArg (arg[1], XtNleft, XawChainLeft);
2635 XtSetArg (arg[2], XtNright, XawChainLeft);
2636 XtSetArg (arg[3], XtNhorizDistance, 10);
2637 XtSetArg (arg[4], XtNlabel, "Pop");
2638 XtSetArg (arg[5], XtNtranslations,
2639 XtParseTranslationTable (pop_face_trans));
2640 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2641 FaceWidget, arg, 6);
2642 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2644 XtSetArg (arg[0], XtNfromHoriz, w);
2645 XtSetArg (arg[1], XtNleft, XawChainLeft);
2646 XtSetArg (arg[2], XtNright, XawChainRight);
2647 XtSetArg (arg[3], XtNlabel, "");
2648 XtSetArg (arg[4], XtNborderWidth, 0);
2649 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2650 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2651 FaceWidget, arg, 6);
2653 XtSetArg (arg[0], XtNborderWidth, 0);
2654 XtSetArg (arg[1], XtNleft, XawChainLeft);
2655 XtSetArg (arg[2], XtNright, XawChainLeft);
2656 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2658 MPlist *plist[11], *pl;
2661 for (i = 0; i < 11; i++) plist[i] = NULL;
2663 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2664 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2666 MSymbol sym = msymbol_exist (langname);
2670 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2672 char *name = msymbol_name (fullname);
2675 if (c >= 'A' && c <= 'Z')
2677 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2681 pl = plist[idx] = mplist ();
2682 for (; mplist_next (pl); pl = mplist_next (pl))
2683 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2685 mplist_push (pl, sym, fullname);
2690 for (i = 0; i < 11; i++)
2693 char *name = alloca (9);
2695 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2698 for (j = 0, pl = plist[i]; mplist_next (pl);
2699 j++, pl = mplist_next (pl))
2700 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2701 msymbol_name (mplist_key (pl)),
2702 LangProc, mplist_key (pl), -1);
2703 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2704 menus, j, "Push language property");
2706 for (i = 0; i < 11; i++)
2708 m17n_object_unref (plist[i]);
2710 XtSetArg (arg[0], XtNfromHoriz, w);
2711 XtSetArg (arg[1], XtNleft, XawChainLeft);
2712 XtSetArg (arg[2], XtNright, XawChainLeft);
2713 XtSetArg (arg[3], XtNhorizDistance, 10);
2714 XtSetArg (arg[4], XtNlabel, "Pop");
2715 XtSetArg (arg[5], XtNtranslations,
2716 XtParseTranslationTable (pop_lang_trans));
2717 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2718 LangWidget, arg, 6);
2719 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2721 XtSetArg (arg[0], XtNfromHoriz, w);
2722 XtSetArg (arg[1], XtNleft, XawChainLeft);
2723 XtSetArg (arg[2], XtNright, XawChainRight);
2724 XtSetArg (arg[3], XtNlabel, "");
2725 XtSetArg (arg[4], XtNborderWidth, 0);
2726 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2727 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2728 LangWidget, arg, 6);
2731 XtSetArg (arg[0], XtNheight, win_height);
2732 XtSetArg (arg[1], XtNwidth, 10);
2733 XtSetArg (arg[2], XtNleft, XawChainLeft);
2734 XtSetArg (arg[3], XtNright, XawChainLeft);
2735 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2737 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2738 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2740 XtSetArg (arg[0], XtNheight, win_height);
2741 XtSetArg (arg[1], XtNwidth, win_width);
2742 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2743 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2744 XtSetArg (arg[4], XtNleft, XawChainLeft);
2745 XtSetArg (arg[5], XtNright, XawChainRight);
2746 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2749 XtSetArg (arg[0], XtNborderWidth, 0);
2750 XtSetArg (arg[1], XtNleft, XawChainLeft);
2751 XtSetArg (arg[2], XtNright, XawChainRight);
2752 XtSetArg (arg[3], XtNresizable, True);
2753 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2754 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2755 TailWidget, arg, 5);
2757 memset (&control, 0, sizeof control);
2758 control.two_dimensional = 1;
2759 control.enable_bidi = 1;
2760 control.anti_alias = 1;
2761 control.min_line_ascent = font_ascent;
2762 control.min_line_descent = font_descent;
2763 control.max_line_width = win_width;
2764 control.with_cursor = 1;
2765 control.cursor_width = 2;
2766 control.partial_update = 1;
2767 control.ignore_formatting_char = 1;
2769 memset (&input_status_control, 0, sizeof input_status_control);
2770 input_status_control.enable_bidi = 1;
2772 XtAppAddActions (context, actions, XtNumber (actions));
2773 XtRealizeWidget (ShellWidget);
2775 win = XtWindow (TextWidget);
2777 XtAppMainLoop (context);
2779 if (current_input_context)
2780 minput_destroy_ic (current_input_context);
2781 for (i = 0; i < num_input_methods; i++)
2782 minput_close_im (input_method_table[i]);
2783 m17n_object_unref (frame);
2784 m17n_object_unref (mt);
2785 m17n_object_unref (face_xxx_large);
2786 m17n_object_unref (face_box);
2787 m17n_object_unref (face_courier);
2788 m17n_object_unref (face_helvetica);
2789 m17n_object_unref (face_times);
2790 m17n_object_unref (face_dv_ttyogesh);
2791 m17n_object_unref (face_freesans);
2792 m17n_object_unref (face_freemono);
2793 m17n_object_unref (face_default_fontset);
2794 m17n_object_unref (face_no_ctl_fontset);
2795 m17n_object_unref (face_input_status);
2796 m17n_object_unref (face_default);
2797 m17n_object_unref (default_face_list);
2798 m17n_object_unref (selection);
2802 free (fontset_name);
2804 free (input_method_table);
2805 free (InputMethodMenus);
2807 XFreeGC (display, mono_gc);
2808 XFreeGC (display, mono_gc_inv);
2809 XFreeGC (display, gc_inv);
2810 XtUninstallTranslations (form);
2811 XtUninstallTranslations (TextWidget);
2812 XtDestroyWidget (ShellWidget);
2813 XtDestroyApplicationContext (context);
2817 #endif /* not FOR_DOXYGEN */