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.
60 #include <sys/types.h>
67 #include <X11/keysym.h>
68 #include <X11/Xatom.h>
69 #include <X11/Intrinsic.h>
70 #include <X11/StringDefs.h>
71 #include <X11/Shell.h>
72 #include <X11/Xaw/Command.h>
73 #include <X11/Xaw/Box.h>
74 #include <X11/Xaw/Form.h>
75 #include <X11/Xaw/Dialog.h>
76 #include <X11/Xaw/Scrollbar.h>
77 #include <X11/Xaw/Toggle.h>
78 #include <X11/Xaw/SimpleMenu.h>
79 #include <X11/Xaw/SmeBSB.h>
80 #include <X11/Xaw/SmeLine.h>
81 #include <X11/Xaw/MenuButton.h>
84 #include <m17n-misc.h>
87 #define VERSION "1.0.1"
89 /* Global variables. */
94 /* For the X Window System. */
97 /* GCs for normal drawing, filling by background color, normal drawing
98 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
100 GC gc, gc_inv, mono_gc, mono_gc_inv;
102 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
103 XtAppContext context;
104 int default_font_size;
108 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
109 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
110 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
111 +- Body -- Sbar, Text
115 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
116 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
117 Widget SbarWidget, TextWidget;
118 Widget FileShellWidget, FileDialogWidget;
119 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
120 Widget CurIMLang, CurIMStatus;
122 int win_width, win_height; /* Size of TextWidget. */
125 Pixmap input_status_pixmap;
126 int input_status_width, input_status_height;
128 /* Bitmap for "check" glyph. */
129 #define check_width 9
130 #define check_height 8
131 static unsigned char check_bits[] = {
132 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
133 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
136 /* For the m17n library. */
139 int nchars; /* == mtext_len (mt) */
140 MDrawControl control, input_status_control;
141 MTextProperty *selection;
144 MFace *face_xxx_large;
146 MFace *face_courier, *face_helvetica, *face_times;
147 MFace *face_dv_ttyogesh, *face_freesans, *face_freemono;
148 MFace *face_default_fontset, *face_no_ctl_fontset;
149 MFace *face_input_status;
151 int logical_move = 1; /* If 0, move cursor visually. */
153 MInputMethod **input_method_table;
154 int num_input_methods;
155 int current_input_method = -1; /* i.e. none */
156 int auto_input_method = 0;
157 MInputContext *current_input_context;
164 { {"Menu Size", NULL},
165 {"xx-small", &mface_xx_small},
166 {"x-small", &mface_x_small},
167 {"small", &mface_small},
168 {"normalsize", &mface_normalsize},
169 {"large", &mface_large},
170 {"x-large", &mface_x_large},
171 {"xx-large", &mface_xx_large},
172 {"xxx-large", &face_xxx_large},
174 {"Menu Family", NULL},
175 {"courier", &face_courier},
176 {"helvetica", &face_helvetica},
177 {"times", &face_times},
178 {"dv-ttyogesh", &face_dv_ttyogesh},
179 {"freesans", &face_freesans},
180 {"freemono", &face_freemono},
182 {"Menu Style", NULL},
183 {"medium", &mface_medium},
184 {"bold", &mface_bold},
185 {"italic", &mface_italic},
187 {"Menu Color", NULL},
188 {"black", &mface_black},
189 {"white", &mface_white},
191 {"green", &mface_green},
192 {"blue", &mface_blue},
193 {"cyan", &mface_cyan},
194 {"yello", &mface_yellow},
195 {"magenta", &mface_magenta},
198 {"normal", &mface_normal_video},
199 {"reverse", &mface_reverse_video},
200 {"underline", &mface_underline},
202 {"No CTL", &face_no_ctl_fontset} };
205 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
207 /* Information about a physical line metric. */
210 int from; /* BOL position of the line. */
211 int to; /* BOL position of the next line. */
212 int y0, y1; /* Top and bottom Y position of the line. */
213 int ascent; /* Height of the top Y position. */
216 struct LineInfo top; /* Topmost line. */
217 struct LineInfo cur; /* Line containing cursor. */
218 struct LineInfo sel_start; /* Line containing selection start. */
219 struct LineInfo sel_end; /* Line containing selection end. */
221 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
223 /* X position to keep on vertical (up and down) cursor motion. */
224 int target_x_position;
226 /* Interface macros for m17n-lib drawing routines. */
228 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
229 coordinate ($X, $Y) */
230 #define DRAW_TEXT(x, y, from, to) \
231 mdraw_text_with_control \
232 (frame, (MDrawWindow) win, \
233 control.orientation_reversed ? x + win_width : x, y, \
234 mt, from, to, &control)
236 /* Store the extents of a text in the range $FROM to $TO in the
237 structure $RECT (type MDrawMetric). */
238 #define TEXT_EXTENTS(from, to, rect) \
239 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
241 /* Store the glyph information of a character at the position $POS in
242 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
243 $FROM is written at the coordinate (0, 0). */
244 #define GLYPH_INFO(from, pos, info) \
245 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
247 /* Set $X and $Y to the coordinate of character at position $POS
248 assuming that the text from $FROM is written at the coordinate (0,
250 #define COORDINATES_POSITION(from, pos, x, y) \
251 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
253 /* Interface macros for X library. */
254 #define COPY_AREA(y0, y1, to) \
255 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
257 #define CLEAR_AREA(x, y, w, h) \
258 XClearArea (display, win, (x), (y), (w), (h), False)
260 #define SELECTEDP() \
261 mtext_property_mtext (selection)
263 /* Format MSG by FMT and print the result to the stderr, and exit. */
264 #define FATAL_ERROR(fmt, arg) \
266 fprintf (stderr, fmt, arg); \
271 /* If POS is greater than zero, move POS back to the beginning of line
272 (BOL) position. If FORWARD is nonzero, move POS forward instead.
273 Return the new position. */
275 bol (int pos, int forward)
277 int limit = forward ? nchars : 0;
279 pos = mtext_character (mt, pos, limit, '\n');
280 return (pos < 0 ? limit : pos + 1);
283 /* Update the structure #TOP (struct LineInfo) to make $POS the first
284 character position of the screen. */
288 int from = bol (pos, 0);
291 GLYPH_INFO (from, pos, info);
292 top.from = info.line_from;
293 top.to = info.line_to;
295 top.y1 = info.this.height;
296 top.ascent = - info.this.y;
300 /* Update the scroll bar so that the text of the range $FROM to $TO
301 are shown on the window. */
303 update_scroll_bar (int from, int to)
305 float top = (float) from / nchars;
306 float shown = (float) (to - from) / nchars;
307 XtArgVal *l_top = (XtArgVal *) ⊤
308 XtArgVal *l_shown = (XtArgVal *) &shown;
310 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
311 XtSetArg (arg[1], XtNshown, *l_shown);
312 XtSetValues (SbarWidget, arg, 2);
316 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
317 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
318 is nonzero, update the scoll bar. */
320 redraw (int y0, int y1, int clear, int scroll_bar)
325 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
326 struct LineInfo *line;
329 CLEAR_AREA (0, y0, win_width, y1 - y0);
331 /* Find a line closest to y0. It is a cursor line if the cursor is
332 Y0, otherwise the top line. */
337 /* If there exists a selected region, check it too. */
338 if (sel_y0 > line->y0 && y0 >= sel_y0)
343 info.this.height = line->y1 - y;
344 info.this.y = - line->ascent;
345 info.line_to = line->to;
346 while (from < nchars && y + info.this.height <= y0)
348 y += info.this.height;
350 GLYPH_INFO (from, from, info);
352 y0 = y - info.this.y;
354 while (to < nchars && y < y1)
356 GLYPH_INFO (to, to, info);
357 y += info.this.height;
363 DRAW_TEXT (0, y0, from, to);
368 GLYPH_INFO (to, to, info);
369 if (y + info.this.height >= win_height)
372 y += info.this.height;
374 update_scroll_bar (top.from, to);
379 /* Set the current input method spot to the correct position. */
381 set_input_method_spot ()
383 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
384 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
386 int n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
387 int size = 0, ratio = 0, i;
389 for (i = n - 1; i >= 0; i--)
392 size = (int) mface_get_prop (faces[i], Msize);
394 ratio = (int) mface_get_prop (faces[i], Mratio);
397 size = default_font_size;
399 size = size * ratio / 100;
400 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
401 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
406 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
409 redraw_cursor (int clear)
411 if (control.cursor_bidi)
413 /* We must update the whole line of the cursor. */
414 int beg = bol (cur.from, 0);
415 int end = bol (cur.to - 1, 1);
417 int y0 = cur.y0, y1 = cur.y1;
421 TEXT_EXTENTS (beg, cur.from, rect);
426 TEXT_EXTENTS (cur.to, end, rect);
429 redraw (y0, y1, clear, 0);
437 if (control.orientation_reversed)
438 x += win_width - cursor.this.width;
439 CLEAR_AREA (x, cur.y0, cursor.this.width, cursor.this.height);
441 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
446 /* Update the information about the location of cursor to the position
447 $POS. If $FULL is nonzero, update the information fully only from
448 the information about the top line. Otherwise, truct the current
449 information in the structure $CUR. */
451 update_cursor (int pos, int full)
457 /* CUR is inaccurate. We can trust only TOP. */
458 GLYPH_INFO (top.from, pos, cursor);
459 cur.y0 = top.ascent + cursor.y + cursor.this.y;
461 else if (pos < cur.from)
463 int from = bol (pos, 0);
465 TEXT_EXTENTS (from, cur.from, rect);
466 GLYPH_INFO (from, pos, cursor);
467 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y);
469 else if (pos < cur.to)
471 GLYPH_INFO (cur.from, pos, cursor);
475 GLYPH_INFO (cur.from, pos, cursor);
476 cur.y0 += cur.ascent + cursor.y + cursor.this.y;
479 cur.from = cursor.line_from;
480 cur.to = cursor.line_to;
481 cur.y1 = cur.y0 + cursor.this.height;
482 cur.ascent = - cursor.this.y;
486 /* Update the information about the selected region. */
496 from = mtext_property_start (selection);
497 to = mtext_property_end (selection);
501 int pos = bol (from, 0);
503 TEXT_EXTENTS (pos, top.from, rect);
504 sel_start.y0 = top.y0 - rect.height;
505 sel_start.ascent = - rect.y;
506 GLYPH_INFO (pos, from, info);
507 if (pos < info.line_from)
508 sel_start.y0 += - rect.y + info.y + info.this.y;
512 GLYPH_INFO (top.from, from, info);
513 sel_start.y0 = top.ascent + info.y + info.this.y;
515 sel_start.ascent = -info.this.y;
516 sel_start.y1 = sel_start.y0 + info.this.height;
517 sel_start.from = info.line_from;
518 sel_start.to = info.line_to;
520 if (to <= sel_start.to)
523 if (to >= sel_end.to)
525 GLYPH_INFO (sel_start.from, to, info);
526 sel_end.y1 = sel_end.y0 + info.y + info.this.height;
527 sel_end.to = info.line_to;
532 GLYPH_INFO (sel_start.from, to, info);
533 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
534 sel_end.y1 = sel_end.y0 + info.this.height;
535 sel_end.ascent = - info.this.y;
536 sel_end.from = info.line_from;
537 sel_end.to = info.line_to;
542 /* Select the text in the region from $FROM to $TO. */
544 select_region (int from, int to)
549 pos = from, from = to, to = pos;
550 mtext_push_property (mt, from, to, selection);
555 /* Setup the window to display the character of $POS at the top left
561 /* Top and bottom Y positions to redraw. */
564 if (pos + 1000 < top.from)
565 y0 = 0, y1 = win_height;
566 else if (pos < top.from)
569 TEXT_EXTENTS (pos, top.from, rect);
570 if (rect.height >= win_height * 0.9)
575 COPY_AREA (0, win_height - y1, y1);
578 else if (pos < top.to)
580 /* No need of redrawing. */
583 else if (pos < top.from + 1000)
585 TEXT_EXTENTS (top.from, pos, rect);
586 if (rect.height >= win_height * 0.9)
590 y0 = win_height - rect.height;
591 COPY_AREA (rect.height, win_height, 0);
596 y0 = 0, y1 = win_height;
602 update_cursor (pos, 1);
604 update_cursor (cursor.from, 1);
606 redraw (y0, y1, 1, 1);
610 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
613 /* Select an input method accoding to $IDX. If $IDX is negative, turn
614 off the current input method, otherwide turn on the input method
615 input_method_table[$IDX]. */
617 select_input_method (idx)
619 if (idx == current_input_method)
621 if (current_input_context)
623 minput_destroy_ic (current_input_context);
624 current_input_context = NULL;
625 current_input_method = -1;
629 MInputMethod *im = input_method_table[idx];
631 if (im->language == Mnil)
633 MInputXIMArgIC arg_xic;
634 Window win = XtWindow (TextWidget);
636 arg_xic.input_style = 0;
637 arg_xic.client_win = arg_xic.focus_win = win;
638 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
639 current_input_context = minput_create_ic (im, &arg_xic);
643 MInputGUIArgIC arg_ic;
645 arg_ic.frame = frame;
646 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
647 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
648 current_input_context = minput_create_ic (im, &arg_ic);
651 if (current_input_context)
653 set_input_method_spot ();
654 current_input_method = idx;
657 if (current_input_method >= 0)
660 XtSetArg (arg[0], XtNlabel, &label);
661 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
662 XtSetArg (arg[0], XtNlabel, label);
665 XtSetArg (arg[0], XtNlabel, "");
666 XtSetValues (CurIMLang, arg, 1);
669 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
672 /* Display cursor according to the current information of #CUR.
673 $CLIENT_DATA is ignore. Most callback functions add this function
674 as a background processing procedure the current application (by
675 XtAppAddWorkProc) via the function hide_cursor. */
677 show_cursor (XtPointer client_data)
682 update_cursor (cursor.from, 1);
684 while (cur.y1 > win_height)
687 update_cursor (cursor.from, 1);
690 control.cursor_pos = cursor.from;
693 control.with_cursor = 1;
696 if (current_input_context)
697 set_input_method_spot ();
700 int pos = (SELECTEDP () ? mtext_property_start (selection)
701 : cursor.from > 0 ? cursor.from - 1
703 MFace *face = mface ();
704 MTextProperty *props[256];
705 int n = mtext_get_properties (mt, pos, Mface, props, 256);
707 char buf[256], *p = buf;
713 int size = (int) mfont_get_prop (cursor.font, Msize);
714 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
715 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
716 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
717 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
719 sprintf (p, "%dpt", size / 10), p += strlen (p);
721 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
723 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
725 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
727 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
731 mface_merge (face, face_default);
732 for (i = 0; i < n; i++)
733 if (props[i] != selection)
734 mface_merge (face, (MFace *) mtext_property_value (props[i]));
735 sym = (MSymbol) mface_get_prop (face, Mforeground);
737 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
738 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
739 strcat (p, ",rev"), p += strlen (p);
740 if (mface_get_prop (face, Mhline))
741 strcat (p, ",ul"), p += strlen (p);
742 if (mface_get_prop (face, Mbox))
743 strcat (p, ",box"), p += strlen (p);
744 m17n_object_unref (face);
746 XtSetArg (arg[0], XtNborderWidth, 1);
747 XtSetArg (arg[1], XtNlabel, buf);
748 XtSetValues (CurFaceWidget, arg, 2);
751 if (control.cursor_pos < nchars)
755 if (control.cursor_pos > 0
756 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
757 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
759 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
763 XtSetArg (arg[0], XtNborderWidth, 0);
764 XtSetArg (arg[1], XtNlabel, "");
768 XtSetArg (arg[0], XtNborderWidth, 1);
769 XtSetArg (arg[1], XtNlabel,
770 msymbol_name (msymbol_get (sym, Mlanguage)));
771 XtSetValues (CurLangWidget, arg, 2);
773 XtSetValues (CurLangWidget, arg, 2);
775 if (auto_input_method)
778 select_input_method (-1);
783 for (i = 0; i < num_input_methods; i++)
784 if (input_method_table[i]->language == sym)
786 if (i < num_input_methods)
787 select_input_method (i);
789 select_input_method (-1);
794 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
800 /* Hide the cursor. */
804 control.with_cursor = 0;
806 XtAppAddWorkProc (context, show_cursor, NULL);
810 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
811 $Y1 and $NEW_Y1 assuming that the text in the other area is not
814 update_region (int y0, int old_y1, int new_y1)
820 if (old_y1 < win_height)
822 COPY_AREA (old_y1, win_height, new_y1);
823 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
826 redraw (new_y1, win_height, 1, 0);
828 else if (new_y1 > old_y1)
830 if (new_y1 < win_height)
831 COPY_AREA (old_y1, win_height, new_y1);
833 if (new_y1 > win_height)
835 redraw (y0, new_y1, 1, 1);
839 /* Delete the next $N characters. If $N is negative delete the
840 precious (- $N) characters. */
850 from = cursor.from, to = from + n;
853 if (cursor.from == cur.from)
855 /* We are at the beginning of line. */
856 int pos = cursor.prev_from;
858 if (cursor.from == top.from)
860 /* We are at the beginning of screen. We must scroll
862 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
863 reseat (info.line_from);
865 update_cursor (pos, 1);
871 from = cursor.from - 1;
876 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
877 old_y1 = cur.y0 + rect.height;
879 /* Now delete a character. */
880 mtext_del (mt, from, to);
882 if (from >= top.from && from < top.to)
883 update_top (top.from);
884 update_cursor (from, 1);
886 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
887 new_y1 = cur.y0 + rect.height;
889 update_region (cur.y0, old_y1, new_y1);
893 /* Insert M-text $NEWTEXT at the current cursor position. */
895 insert_chars (MText *newtext)
897 int n = mtext_len (newtext);
899 int y0, old_y1, new_y1;
903 int n = (mtext_property_end (selection)
904 - mtext_property_start (selection));
905 mtext_detach_property (selection);
910 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
911 old_y1 = y0 + rect.height;
913 /* Now insert chars. */
914 mtext_ins (mt, cursor.from, newtext);
916 if (cur.from == top.from)
917 update_top (top.from);
918 update_cursor (cursor.from + n, 1);
920 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
921 new_y1 = cur.y0 + rect.height;
923 update_region (y0, old_y1, new_y1);
928 /* Convert the currently selected text to COMPOUND-TEXT. It is called
929 when someone requests the current value of the selection. */
931 covert_selection (Widget w, Atom *selection_atom,
932 Atom *target, Atom *return_type,
933 XtPointer *value, unsigned long *length, int *format)
935 unsigned char *buf = (unsigned char *) XtMalloc (4096);
936 MText *this_mt = mtext ();
937 int from = mtext_property_start (selection);
938 int to = mtext_property_end (selection);
940 mtext_copy (this_mt, 0, mt, from, to);
941 *length = mconv_encode_buffer (msymbol ("compound-text"),
943 *return_type = XA_COMPOUND_TEXT;
944 *value = (XtPointer) buf;
946 m17n_object_unref (this_mt);
951 /* Unselect the text. It is called when we loose the selection. */
953 lose_selection (Widget w, Atom *selection_atom)
957 mtext_detach_property (selection);
958 redraw (sel_start.y0, sel_end.y1, 1, 0);
963 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
964 XtPointer value, unsigned long *length, int *format)
969 if (*type == XT_CONVERT_FAIL || ! value)
971 if (*type == XA_STRING)
973 else if (*type == XA_COMPOUND_TEXT)
974 coding = msymbol ("compound-text");
975 else if (*type == XA_UTF8_STRING)
976 coding = msymbol ("utf-8");
980 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
984 insert_chars (this_mt);
985 m17n_object_unref (this_mt);
994 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
996 XExposeEvent *expose = (XExposeEvent *) event;
1000 Dimension width_max, width;
1002 XtSetArg (arg[0], XtNwidth, &width);
1003 XtGetValues (XtParent (w), arg, 1);
1005 XtGetValues (HeadWidget, arg, 1);
1006 if (width_max < width)
1008 XtGetValues (FaceWidget, arg, 1);
1009 if (width_max < width)
1011 XtGetValues (LangWidget, arg, 1);
1012 if (width_max < width)
1014 XtSetArg (arg[0], XtNwidth, width_max);
1015 XtSetValues (HeadWidget, arg, 1);
1016 XtSetValues (FaceWidget, arg, 1);
1017 XtSetValues (LangWidget, arg, 1);
1018 XtSetValues (XtParent (w), arg, 1);
1019 XtSetValues (TailWidget, arg, 1);
1022 update_cursor (0, 1);
1023 redraw (0, win_height, 0, 1);
1028 redraw (expose->y, expose->y + expose->height, 0, 0);
1029 if (current_input_context
1030 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1031 set_input_method_spot ();
1036 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1038 XConfigureEvent *configure = (XConfigureEvent *) event;
1041 control.max_line_width = win_width = configure->width;
1042 win_height = configure->height;
1043 mdraw_clear_cache (mt);
1045 update_cursor (0, 1);
1046 redraw (0, win_height, 1, 1);
1047 if (current_input_context)
1048 set_input_method_spot ();
1052 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1055 int x = event->xbutton.x;
1056 int y = event->xbutton.y - top.ascent;
1058 if (control.orientation_reversed)
1060 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1063 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1064 mtext_detach_property (selection);
1065 redraw (sel_start.y0, sel_end.y1, 1, 0);
1068 update_cursor (pos, 0);
1073 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1078 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1079 covert_selection, lose_selection, NULL);
1080 update_cursor (mtext_property_start (selection), 0);
1085 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1089 /* We don't have a local selection. */
1090 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1095 int from = mtext_property_start (selection);
1096 int to = mtext_property_end (selection);
1099 int x = event->xbutton.x;
1100 int y = event->xbutton.y - top.ascent;
1102 if (control.orientation_reversed)
1104 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1106 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1107 mtext_detach_property (selection);
1109 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1110 update_cursor (pos, 0);
1111 insert_chars (this_mt);
1112 m17n_object_unref (this_mt);
1117 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1120 int x = event->xbutton.x;
1121 int y = event->xbutton.y;
1123 if (control.orientation_reversed)
1126 pos = top.from, y -= top.ascent;
1128 pos = cur.from, y -= cur.y0 + cur.ascent;
1129 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1131 if (pos == cursor.from)
1137 /* Selection range changed. */
1138 int from = mtext_property_start (selection);
1139 int to = mtext_property_end (selection);
1140 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1141 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1143 if (cursor.from == from)
1145 /* Starting position changed. */
1148 /* Enlarged. We can simply overdraw. */
1149 select_region (pos, to);
1150 redraw (sel_start.y0, start_y1, 0, 0);
1154 /* Shrunken. Previous selection face must be cleared. */
1155 select_region (pos, to);
1156 redraw (start_y0, sel_start.y1, 1, 0);
1160 /* Shrunken to zero. */
1161 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1162 mtext_detach_property (selection);
1163 redraw (start_y0, end_y1, 1, 0);
1167 /* Full update is necessary. */
1168 select_region (to, pos);
1169 redraw (start_y0, sel_end.y1, 1, 0);
1174 /* Ending position changed. */
1177 /* Full update is necessary. */
1178 select_region (pos, from);
1179 redraw (sel_start.y0, end_y1, 1, 0);
1181 else if (pos == from)
1183 /* Shrunken to zero. */
1184 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1185 mtext_detach_property (selection);
1186 redraw (start_y0, end_y1, 1, 0);
1190 /* Shrunken. Previous selection face must be cleared. */
1191 select_region (from, pos);
1192 redraw (sel_end.y0, end_y1, 1, 0);
1196 /* Enlarged. We can simply overdraw. */
1197 select_region (from, pos);
1198 redraw (end_y0, sel_end.y1, 0, 0);
1204 /* Newly selected. */
1205 select_region (pos, cursor.from);
1206 redraw (sel_start.y0, sel_end.y1, 0, 0);
1208 update_cursor (pos, 1);
1212 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1215 MDrawGlyphInfo info;
1217 int cursor_pos = cursor.from;
1219 if (((int) position) < 0)
1225 height = top.y1 - top.y0;
1228 pos = bol (from - 1, 0);
1229 GLYPH_INFO (pos, from - 1, info);
1230 if (height + info.this.height > win_height)
1232 height += info.this.height;
1233 from = info.line_from;
1235 if (cursor_pos >= top.to)
1237 cursor_pos = top.from;
1239 while (cursor_pos < nchars)
1241 GLYPH_INFO (pos, pos, info);
1242 if (height + info.this.height > win_height)
1244 height += info.this.height;
1250 else if (cur.to < nchars)
1252 /* Scroll up, but leave at least one line. */
1255 while (from < nchars)
1257 GLYPH_INFO (from, from, info);
1258 if (height + info.this.height > win_height
1259 || info.line_to >= nchars)
1261 height += info.this.height;
1262 from = info.line_to;
1265 from = info.line_from;
1266 if (cursor_pos < from)
1270 /* Scroll up to make the cursor line top. */
1274 update_cursor (cursor_pos, 1);
1278 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1280 float persent = *(float *) persent_ptr;
1281 int pos1, pos2 = nchars * persent;
1282 MDrawGlyphInfo info;
1285 pos1 = bol (pos2, 0);
1286 GLYPH_INFO (pos1, pos2, info);
1287 pos1 = info.line_from;
1289 update_cursor (pos1, 1);
1294 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1296 XKeyEvent *key_event = (XKeyEvent *) event;
1298 KeySym keysym = NoSymbol;
1300 /* If set to 1, do not update target_x_position. */
1301 int keep_target_x_position = 0;
1304 if (current_input_context
1305 && minput_filter (current_input_context, Mnil, event))
1307 if (event->type == KeyRelease)
1312 produced = mtext ();
1313 ret = minput_lookup (current_input_context, Mnil, event, produced);
1314 if (mtext_len (produced) > 0)
1315 insert_chars (produced);
1317 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1318 m17n_object_unref (produced);
1328 n = (mtext_property_end (selection)
1329 - mtext_property_start (selection));
1330 mtext_detach_property (selection);
1332 else if (cursor.from < nchars)
1334 /* Delete the following grapheme cluster. */
1335 n = cursor.to - cursor.from;
1348 /* Delete selected region. */
1349 n = (mtext_property_end (selection)
1350 - mtext_property_start (selection));
1351 mtext_detach_property (selection);
1353 else if (cursor.from > 0)
1355 /* Delete the preceding character. */
1366 mtext_detach_property (selection);
1367 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1371 if (cursor.prev_from >= 0)
1372 update_cursor (cursor.prev_from, 0);
1376 if (cursor.left_from >= 0)
1377 update_cursor (cursor.left_from, 0);
1384 mtext_detach_property (selection);
1385 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1389 if (cursor.next_to >= 0)
1390 update_cursor (cursor.to, 0);
1394 if (cursor.right_from >= 0)
1395 update_cursor (cursor.right_from, 0);
1402 mtext_detach_property (selection);
1403 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1405 if (cur.to <= nchars)
1407 MDrawGlyphInfo info;
1410 GLYPH_INFO (cur.from, cur.to, info);
1411 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1412 target_x_position, info.y);
1413 keep_target_x_position = 1;
1414 update_cursor (pos, 0);
1421 mtext_detach_property (selection);
1422 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1428 int pos = bol (cur.from - 1, 0);
1430 TEXT_EXTENTS (pos, cur.from - 1, rect);
1431 y = rect.height + rect.y - 1;
1432 pos = COORDINATES_POSITION (pos, nchars,
1433 target_x_position, y);
1434 keep_target_x_position = 1;
1435 update_cursor (pos, 0);
1442 mtext_detach_property (selection);
1443 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1445 if (top.from < nchars)
1446 ScrollProc (w, NULL, (XtPointer) 1);
1452 mtext_detach_property (selection);
1453 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1456 ScrollProc (w, NULL, (XtPointer) -1);
1462 if (buf[0] == 17) /* C-q */
1464 XtAppSetExitFlag (context);
1467 else if (buf[0] == 12) /* C-l */
1469 redraw (0, win_height, 1, 1);
1474 MText *temp = mtext ();
1476 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1477 if (current_input_context)
1478 mtext_put_prop (temp, 0, 1, Mlanguage,
1479 current_input_context->im->language);
1480 insert_chars (temp);
1481 m17n_object_unref (temp);
1486 if (! keep_target_x_position)
1487 target_x_position = cursor.x;
1491 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1493 char *name = (char *) client_data;
1495 int from = -1, to = 0;
1500 filename = strdup (name);
1503 fp = fopen (filename, "w");
1506 fprintf (stderr, "Open for write fail: %s", filename);
1512 from = mtext_property_start (selection);
1513 to = mtext_property_end (selection);
1514 mtext_detach_property (selection);
1517 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1520 select_region (from, to);
1524 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1530 mtext_detach_property (selection);
1531 serialized = (int) client_data;
1533 new = mtext_deserialize (mt);
1536 MPlist *plist = mplist ();
1538 mplist_push (plist, Mt, Mface);
1539 mplist_push (plist, Mt, Mlanguage);
1540 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1541 m17n_object_unref (plist);
1545 m17n_object_unref (mt);
1547 serialized = ! serialized;
1548 nchars = mtext_len (mt);
1551 update_cursor (0, 1);
1552 redraw (0, win_height, 1, 1);
1556 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1558 XtAppSetExitFlag (context);
1564 FILE *fp = fopen (filename, "r");
1567 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1568 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1571 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1576 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1578 int data = (int) client_data;
1583 control.enable_bidi = 0;
1584 control.orientation_reversed = 0;
1588 control.enable_bidi = 1;
1589 control.orientation_reversed = data == 2;
1591 for (i = 0; i < 3; i++)
1594 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1596 XtSetArg (arg[0], XtNleftBitmap, None);
1597 XtSetValues (BidiMenus[i], arg, 1);
1600 update_cursor (cursor.from, 1);
1601 redraw (0, win_height, 1, 0);
1604 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1607 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1609 int data = (int) client_data;
1613 control.max_line_width = 0;
1616 control.max_line_width = win_width;
1617 control.line_break = (data == 1 ? NULL : line_break);
1619 for (i = 0; i < 3; i++)
1622 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1624 XtSetArg (arg[0], XtNleftBitmap, None);
1625 XtSetValues (LineBreakMenus[i], arg, 1);
1628 update_cursor (cursor.from, 1);
1629 redraw (0, win_height, 1, 0);
1633 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1635 int data = (int) client_data;
1649 control.cursor_bidi = 0, control.cursor_width = -1;
1653 control.cursor_bidi = 0, control.cursor_width = 2;
1657 control.cursor_bidi = 1;
1662 for (i = from; i < to; i++)
1665 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1667 XtSetArg (arg[0], XtNleftBitmap, None);
1668 XtSetValues (CursorMenus[i], arg, 1);
1671 redraw (0, win_height, 1, 0);
1675 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1677 int idx = (int) client_data;
1679 if (idx == -2 ? current_input_method < 0
1680 : idx == -1 ? auto_input_method
1681 : idx == current_input_method)
1684 XtSetArg (arg[0], XtNleftBitmap, None);
1685 if (auto_input_method)
1687 XtSetValues (InputMethodMenus[1], arg, 1);
1688 auto_input_method = 0;
1690 else if (current_input_method < 0)
1691 XtSetValues (InputMethodMenus[0], arg, 1);
1693 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1697 auto_input_method = 1;
1701 select_input_method (idx);
1702 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1703 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1707 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1709 int idx = (int) client_data;
1716 XtAppAddWorkProc (context, show_cursor, NULL);
1717 from = mtext_property_start (selection);
1718 to = mtext_property_end (selection);
1719 old_y1 = sel_end.y1;
1721 mtext_detach_property (selection);
1724 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1725 MTEXTPROP_REAR_STICKY);
1726 mtext_push_property (mt, from, to, prop);
1727 m17n_object_unref (prop);
1730 mtext_pop_prop (mt, from, to, Mface);
1732 update_top (top.from);
1733 update_cursor (cursor.from, 1);
1734 select_region (from, to);
1735 update_region (sel_start.y0, old_y1, sel_end.y1);
1736 if (cur.y1 > win_height)
1738 while (cur.y1 > win_height)
1741 update_cursor (cursor.from, 1);
1747 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1749 MSymbol sym = (MSymbol) client_data;
1756 XtAppAddWorkProc (context, show_cursor, NULL);
1757 from = mtext_property_start (selection);
1758 to = mtext_property_end (selection);
1759 old_y1 = sel_end.y1;
1761 mtext_detach_property (selection);
1763 mtext_put_prop (mt, from, to, Mlanguage, sym);
1765 mtext_pop_prop (mt, from, to, Mlanguage);
1768 update_top (top.from);
1769 update_cursor (cursor.from, 1);
1770 select_region (from, to);
1771 update_region (sel_start.y0, old_y1, sel_end.y1);
1772 if (cur.y1 > win_height)
1774 while (cur.y1 > win_height)
1777 update_cursor (cursor.from, 1);
1783 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1785 int narrowed = (int) client_data;
1788 MConverter *converter;
1794 from = mtext_property_start (selection);
1795 to = mtext_property_end (selection);
1804 mdump = popen ("mdump -q -p a4", "w");
1806 mdump = popen ("mdump -q", "w");
1809 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1810 mconv_encode_range (converter, mt, from, to);
1811 mconv_free_converter (converter);
1816 input_status (MInputContext *ic, MSymbol command)
1818 XFillRectangle (display, input_status_pixmap, gc_inv,
1819 0, 0, input_status_width, input_status_height);
1820 if (command == Minput_status_draw)
1824 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1825 Mface, face_input_status);
1826 if (ic->im->language != Mnil)
1827 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1828 Mlanguage, ic->im->language);
1829 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1830 &input_status_control, NULL, NULL, &rect);
1831 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1832 input_status_width - rect.width - 2, - rect.y,
1833 ic->status, 0, mtext_len (ic->status),
1834 &input_status_control);
1836 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1837 XtSetValues (CurIMStatus, arg, 1);
1841 compare_input_method (const void *elt1, const void *elt2)
1843 const MInputMethod *im1 = *(MInputMethod **) elt1;
1844 const MInputMethod *im2 = *(MInputMethod **) elt2;
1845 MSymbol lang1, lang2;
1847 if (im1->language == Mnil)
1849 if (im1->language == im2->language)
1850 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1851 if (im1->language == Mt)
1853 if (im2->language == Mt)
1855 lang1 = msymbol_get (im1->language, Mlanguage);
1856 lang2 = msymbol_get (im2->language, Mlanguage);
1857 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1861 setup_input_methods (int with_xim)
1863 MInputMethod *im = NULL;
1864 MInputXIMArgIM arg_xim;
1865 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1869 num_input_methods = mplist_length (plist);
1873 arg_xim.display = display;
1875 arg_xim.res_name = arg_xim.res_class = NULL;
1876 arg_xim.locale = NULL;
1877 arg_xim.modifier_list = NULL;
1878 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1880 num_input_methods++;
1882 input_method_table = calloc (num_input_methods, sizeof (MInputMethod *));
1884 input_method_table[i++] = im;
1885 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1887 MDatabase *mdb = mplist_value (pl);
1888 MSymbol *tag = mdatabase_tag (mdb);
1892 im = minput_open_im (tag[1], tag[2], NULL);
1894 input_method_table[i++] = im;
1898 m17n_object_unref (plist);
1899 num_input_methods = i;
1900 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
1901 compare_input_method);
1902 current_input_context = NULL;
1904 mplist_put (minput_driver->callback_list, Minput_status_start,
1905 (void *) input_status);
1906 mplist_put (minput_driver->callback_list, Minput_status_draw,
1907 (void *) input_status);
1908 mplist_put (minput_driver->callback_list, Minput_status_done,
1909 (void *) input_status);
1914 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
1918 if (num && *num > 0)
1922 for (i = 0; i < *num; i++)
1923 bytes += strlen (str[i]) + 1;
1924 msg = alloca (bytes);
1925 strcpy (msg, str[0]);
1926 for (i = 1; i < *num; i++)
1927 strcat (msg, " "), strcat (msg, str[i]);
1929 else if (cursor.from < nchars)
1931 int c = mtext_ref_char (mt, cursor.from);
1932 char *name = mchar_get_prop (c, Mname);
1936 msg = alloca (10 + strlen (name));
1937 sprintf (msg, "U+%04X %s", c, name);
1943 XtSetArg (arg[0], XtNlabel, msg);
1944 XtSetValues (MessageWidget, arg, 1);
1950 char *name1, *name2;
1951 XtCallbackProc proc;
1952 XtPointer client_data;
1957 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
1959 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
1961 MenuRec FileMenu[] =
1962 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
1963 { 0, "Save", NULL, SaveProc, NULL, -1 },
1964 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
1966 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
1967 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
1969 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
1970 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
1972 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
1975 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
1977 MenuRec *rec = (MenuRec *) client_data;
1980 XtSetArg (arg[0], XtNvalue, "");
1981 XtSetArg (arg[1], XtNlabel, rec->name1);
1982 XtSetValues (FileDialogWidget, arg, 2);
1983 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
1984 XtSetArg (arg[0], XtNx, x + 20);
1985 XtSetArg (arg[1], XtNy, y + 10);
1986 XtSetValues (FileShellWidget, arg, 2);
1987 XtPopup (FileShellWidget, XtGrabExclusive);
1991 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
1996 XtPopdown (FileShellWidget);
1997 if ((int) client_data == 1)
1999 XtSetArg (arg[0], XtNlabel, &label);
2000 XtGetValues (FileDialogWidget, arg, 1);
2001 if (strcmp (label, FileMenu[0].name1) == 0)
2005 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2006 fp = fopen (filename, "r");
2008 m17n_object_unref (mt);
2011 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2019 nchars = mtext_len (mt);
2021 update_cursor (0, 1);
2022 redraw (0, win_height, 1, 1);
2024 else if (strcmp (label, FileMenu[2].name1) == 0)
2025 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2027 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2030 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2031 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2032 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2033 (MENU).status = (STATUS))
2037 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2038 char *menu_name, MenuRec *menus, int num_menus, char *help)
2040 Widget button, menu;
2041 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2042 <LeaveWindow>: reset() MenuHelp()\n\
2043 <BtnDown>: reset() PopupMenu()\n\
2044 <BtnUp>: highlight()";
2050 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2051 for (i = 0; i < num_menus; i++)
2062 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2064 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2066 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2068 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2072 XtSetArg (arg[0], XtNsensitive, False);
2073 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2079 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2084 trans = alloca (strlen (fmt) + strlen (help));
2085 sprintf (trans, fmt, help);
2086 XtSetArg (arg[0], XtNmenuName, menu_name);
2087 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2088 XtSetArg (arg[2], XtNinternalWidth, 2);
2089 XtSetArg (arg[3], XtNhighlightThickness, 1);
2090 XtSetArg (arg[4], XtNleft, XawChainLeft);
2091 XtSetArg (arg[5], XtNright, XawChainLeft);
2094 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2095 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2100 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2101 int *len = alloca (sizeof (int) * num_menus);
2104 XFontSetExtents *fontset_extents;
2106 XtSetArg (arg[0], XtNfontSet, &font_set);
2107 XtGetValues (button, arg, 1);
2109 fontset_extents = XExtentsOfFontSet (font_set);
2110 height = fontset_extents->max_logical_extent.height;
2111 ascent = - fontset_extents->max_logical_extent.y;
2113 for (i = 0; i < num_menus; i++)
2116 len[i] = strlen (menus[i].name2);
2117 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2118 if (max_width < width[i])
2119 max_width = width[i];
2121 for (i = 0; i < num_menus; i++)
2124 Pixmap pixmap = XCreatePixmap (display,
2125 RootWindow (display, screen),
2126 max_width, height, 1);
2127 XFillRectangle (display, pixmap, mono_gc_inv,
2128 0, 0, max_width, height);
2129 XmbDrawString (display, pixmap, font_set, mono_gc,
2130 max_width - width[i], ascent,
2131 menus[i].name2, len[i]);
2132 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2133 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2134 XtSetValues (menus[i].w, arg, 2);
2142 XtActionsRec actions[] = {
2143 {"Expose", ExposeProc},
2144 {"Configure", ConfigureProc},
2146 {"ButtonPress", ButtonProc},
2147 {"ButtonRelease", ButtonReleaseProc},
2148 {"ButtonMotion", ButtonMoveProc},
2149 {"Button2Press", Button2Proc},
2150 {"MenuHelp", MenuHelpProc}
2154 /* Print the usage of this program (the name is PROG), and exit with
2158 help_exit (char *prog, int exit_code)
2166 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2167 printf ("Display FILE on a window and allow users to edit it.\n");
2168 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2169 printf ("The following OPTIONs are available.\n");
2170 printf (" %-13s %s", "--version", "print version number\n");
2171 printf (" %-13s %s", "-h, --help", "print this message\n");
2176 main (int argc, char **argv)
2178 Widget form, BodyWidget, w;
2179 char *fontset_name = NULL;
2180 int col = 80, row = 32;
2181 /* Translation table for TextWidget. */
2182 String trans = "<Expose>: Expose()\n\
2183 <Configure>: Configure()\n\
2186 <Btn1Down>: ButtonPress()\n\
2187 <Btn1Up>: ButtonRelease()\n\
2188 <Btn1Motion>: ButtonMotion()\n\
2189 <Btn2Down>: Button2Press()";
2190 /* Translation table for the top form widget. */
2191 String trans2 = "<Key>: Key()\n\
2193 String pop_face_trans
2194 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2195 <LeaveWindow>: MenuHelp() reset()\n\
2196 <Btn1Down>: set()\n\
2197 <Btn1Up>: notify() unset()";
2198 String pop_lang_trans
2199 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2200 <LeaveWindow>: MenuHelp() reset()\n\
2201 <Btn1Down>: set()\n\
2202 <Btn1Up>: notify() unset()";
2203 int font_width, font_ascent, font_descent;
2207 setlocale (LC_ALL, "");
2208 /* Create the top shell. */
2209 XtSetLanguageProc (NULL, NULL, NULL);
2210 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2211 NULL, sessionShellWidgetClass, NULL, 0);
2212 display = XtDisplay (ShellWidget);
2213 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2215 /* Parse the remaining command line arguments. */
2216 for (i = 1; i < argc; i++)
2218 if (! strcmp (argv[i], "--help")
2219 || ! strcmp (argv[i], "-h"))
2220 help_exit (argv[0], 0);
2221 else if (! strcmp (argv[i], "--version"))
2223 printf ("medit (m17n library) %s\n", VERSION);
2224 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2227 else if (! strcmp (argv[i], "--geometry"))
2230 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2231 help_exit (argv[0], 1);
2233 else if (! strcmp (argv[i], "--fontset"))
2236 fontset_name = strdup (argv[i]);
2238 else if (! strcmp (argv[i], "--with-xim"))
2242 else if (argv[i][0] != '-')
2244 filename = strdup (argv[i]);
2248 fprintf (stderr, "Unknown option: %s", argv[i]);
2249 help_exit (argv[0], 1);
2253 help_exit (argv[0], 1);
2255 mdatabase_dir = ".";
2256 /* Initialize the m17n library. */
2258 if (merror_code != MERROR_NONE)
2259 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2261 mt = read_file (filename);
2264 nchars = mtext_len (mt);
2267 MFace *face = mface ();
2269 mface_put_prop (face, Mbackground, msymbol ("blue"));
2270 mface_put_prop (face, Mforeground, msymbol ("yellow"));
2271 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2272 m17n_object_unref (face);
2275 /* This tells ExposeProc to initialize everything. */
2278 XA_TEXT = XInternAtom (display, "TEXT", False);
2279 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2280 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2282 MPlist *plist = mplist ();
2286 mplist_put (plist, msymbol ("widget"), ShellWidget);
2289 MFontset *fontset = mfontset (fontset_name);
2292 mface_put_prop (face, Mfontset, fontset);
2293 m17n_object_unref (fontset);
2294 mplist_add (plist, Mface, face);
2295 m17n_object_unref (face);
2297 frame = mframe (plist);
2298 m17n_object_unref (plist);
2299 face_default = (MFace *) mframe_get_prop (frame, Mface);
2300 face_default_fontset = mface ();
2301 mface_put_prop (face_default_fontset, Mfontset,
2302 mface_get_prop (face_default, Mfontset));
2304 font = (MFont *) mframe_get_prop (frame, Mfont);
2305 default_font_size = (int) mfont_get_prop (font, Msize);
2308 font_width = (int) mframe_get_prop (frame, Mfont_width);
2309 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2310 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2311 win_width = font_width * col;
2312 win_height = (font_ascent + font_descent) * row;
2318 prop.color_top = prop.color_left = msymbol ("magenta");
2319 prop.color_bottom = prop.color_right = msymbol ("red");
2320 prop.inner_hmargin = prop.inner_vmargin = 1;
2321 prop.outer_hmargin = prop.outer_vmargin = 2;
2323 face_box = mface ();
2324 mface_put_prop (face_box, Mbox, &prop);
2327 face_courier = mface ();
2328 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2329 face_helvetica = mface ();
2330 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2331 face_times = mface ();
2332 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2333 face_dv_ttyogesh = mface ();
2334 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2335 face_freesans = mface ();
2336 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2337 face_freemono = mface ();
2338 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2340 face_xxx_large = mface ();
2341 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2343 MFont *latin_font = mframe_get_prop (frame, Mfont);
2344 MFont *dev_font = mfont ();
2345 MFont *thai_font = mfont ();
2346 MFont *tib_font = mfont ();
2348 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2349 MSymbol no_ctl = msymbol ("no-ctl");
2351 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2352 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2353 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2354 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2355 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2356 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2358 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2359 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2360 latin_font, Mnil, 0);
2361 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2362 dev_font, no_ctl, 0);
2363 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2364 thai_font, no_ctl, 0);
2365 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2366 tib_font, no_ctl, 0);
2367 face_no_ctl_fontset = mface ();
2368 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2369 m17n_object_unref (fontset);
2376 setup_input_methods (with_xim);
2378 gc = DefaultGC (display, screen);
2380 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2381 XtSetArg (arg[1], XtNdefaultDistance, 2);
2382 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2384 XtSetArg (arg[0], XtNborderWidth, 0);
2385 XtSetArg (arg[1], XtNdefaultDistance, 2);
2386 XtSetArg (arg[2], XtNtop, XawChainTop);
2387 XtSetArg (arg[3], XtNbottom, XawChainTop);
2388 XtSetArg (arg[4], XtNleft, XawChainLeft);
2389 XtSetArg (arg[5], XtNright, XawChainRight);
2390 XtSetArg (arg[6], XtNresizable, True);
2391 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2392 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2393 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2394 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2395 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2396 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2397 XtSetArg (arg[7], XtNfromVert, LangWidget);
2398 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2399 XtSetArg (arg[2], XtNtop, XawChainBottom);
2400 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2401 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2403 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2404 HeadWidget, NULL, 0);
2405 XtSetArg (arg[0], XtNvalue, "");
2406 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2407 FileShellWidget, arg, 1);
2408 XawDialogAddButton (FileDialogWidget, "OK",
2409 FileDialogProc, (XtPointer) 0);
2410 XawDialogAddButton (FileDialogWidget, "CANCEL",
2411 FileDialogProc, (XtPointer) 1);
2413 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2414 (char *) check_bits,
2415 check_width, check_height);
2417 unsigned long valuemask = GCForeground;
2420 values.foreground = 1;
2421 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2422 values.foreground = 0;
2423 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2430 if (num_menus < num_input_methods + 2)
2431 num_menus = num_input_methods + 2;
2432 if (num_menus < num_faces + 1)
2433 num_menus = num_faces + 1;
2434 menus = alloca (sizeof (MenuRec) * num_menus);
2436 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2437 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2438 "File I/O, Serialization, Image, Quit");
2440 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2441 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2442 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2443 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2444 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2445 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2446 w = create_menu_button (ShellWidget, HeadWidget, w,
2447 "Cursor", "Cursor Menu",
2448 menus, 6, "Cursor Movement Mode, Cursor Shape");
2449 CursorMenus[0] = menus[0].w;
2450 CursorMenus[1] = menus[1].w;
2451 CursorMenus[2] = menus[3].w;
2452 CursorMenus[3] = menus[4].w;
2453 CursorMenus[4] = menus[5].w;
2455 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2456 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2457 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2458 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2459 menus, 3, "BIDI Processing Mode");
2460 for (i = 0; i < 3; i++)
2461 BidiMenus[i] = menus[i].w;
2463 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2464 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2465 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2466 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2468 menus, 3, "How to break lines");
2469 for (i = 0; i < 3; i++)
2470 LineBreakMenus[i] = menus[i].w;
2472 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2473 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2474 for (i = 0; i < num_input_methods; i++)
2476 MInputMethod *im = input_method_table[i];
2477 char *name1, *name2;
2479 if (im->language != Mnil && im->language != Mt)
2481 MSymbol sym = msymbol_get (im->language, Mlanguage);
2483 name1 = msymbol_name (im->language);
2485 name1 = msymbol_name (sym);
2486 name2 = msymbol_name (im->name);
2489 name1 = msymbol_name (im->name), name2 = NULL;
2491 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2493 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2494 "Input Method Menu", menus, i + 2,
2495 "Select input method");
2498 unsigned long valuemask = GCForeground;
2501 XtSetArg (arg[0], XtNbackground, &values.foreground);
2502 XtGetValues (w, arg, 1);
2503 gc_inv = XCreateGC (display, RootWindow (display, screen),
2504 valuemask, &values);
2507 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2508 for (i = 0; i < num_input_methods + 2; i++)
2509 InputMethodMenus[i] = menus[i].w;
2511 input_status_width = font_width * 8;
2512 input_status_height = (font_ascent + font_descent) * 2.4;
2513 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2515 input_status_height,
2516 DefaultDepth (display, screen));
2521 prop.color_top = prop.color_bottom
2522 = prop.color_left = prop.color_right = Mnil;
2523 prop.inner_hmargin = prop.inner_vmargin = 1;
2524 prop.outer_hmargin = prop.outer_vmargin = 0;
2525 face_input_status = mface ();
2526 mface_put_prop (face_input_status, Mbox, &prop);
2529 XFillRectangle (display, input_status_pixmap, gc_inv,
2530 0, 0, input_status_width, input_status_height);
2531 XtSetArg (arg[0], XtNfromHoriz, w);
2532 XtSetArg (arg[1], XtNleft, XawRubber);
2533 XtSetArg (arg[2], XtNright, XawChainRight);
2534 XtSetArg (arg[3], XtNborderWidth, 0);
2535 XtSetArg (arg[4], XtNlabel, " ");
2536 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2537 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2538 HeadWidget, arg, 6);
2539 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2540 XtSetArg (arg[1], XtNleft, XawChainRight);
2541 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2542 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2543 HeadWidget, arg, 5);
2545 XtSetArg (arg[0], XtNborderWidth, 0);
2546 XtSetArg (arg[1], XtNleft, XawChainLeft);
2547 XtSetArg (arg[2], XtNright, XawChainLeft);
2548 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2549 for (i = 0; i < num_faces;)
2551 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2552 char *label = label_menu + 5; /* "Xxxx" */
2554 for (j = i; j < num_faces && face_table[j].face; j++)
2555 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2557 w = create_menu_button (ShellWidget, FaceWidget, w,
2559 menus, j - i, "Push face property");
2563 XtSetArg (arg[0], XtNfromHoriz, w);
2564 XtSetArg (arg[1], XtNleft, XawChainLeft);
2565 XtSetArg (arg[2], XtNright, XawChainLeft);
2566 XtSetArg (arg[3], XtNhorizDistance, 10);
2567 XtSetArg (arg[4], XtNlabel, "Pop");
2568 XtSetArg (arg[5], XtNtranslations,
2569 XtParseTranslationTable (pop_face_trans));
2570 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2571 FaceWidget, arg, 6);
2572 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2574 XtSetArg (arg[0], XtNfromHoriz, w);
2575 XtSetArg (arg[1], XtNleft, XawChainLeft);
2576 XtSetArg (arg[2], XtNright, XawChainRight);
2577 XtSetArg (arg[3], XtNlabel, "");
2578 XtSetArg (arg[4], XtNborderWidth, 0);
2579 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2580 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2581 FaceWidget, arg, 6);
2583 XtSetArg (arg[0], XtNborderWidth, 0);
2584 XtSetArg (arg[1], XtNleft, XawChainLeft);
2585 XtSetArg (arg[2], XtNright, XawChainLeft);
2586 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2588 MPlist *plist[11], *pl;
2591 for (i = 0; i < 11; i++) plist[i] = NULL;
2593 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2594 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2596 MSymbol sym = msymbol_exist (langname);
2600 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2602 char *name = msymbol_name (fullname);
2605 if (c >= 'A' && c <= 'Z')
2607 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2611 pl = plist[idx] = mplist ();
2612 for (; mplist_next (pl); pl = mplist_next (pl))
2613 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2615 mplist_push (pl, sym, fullname);
2620 for (i = 0; i < 11; i++)
2623 char *name = alloca (9);
2625 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2628 for (j = 0, pl = plist[i]; mplist_next (pl);
2629 j++, pl = mplist_next (pl))
2630 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2631 msymbol_name (mplist_key (pl)),
2632 LangProc, mplist_key (pl), -1);
2633 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2634 menus, j, "Push language property");
2636 for (i = 0; i < 11; i++)
2638 m17n_object_unref (plist[i]);
2640 XtSetArg (arg[0], XtNfromHoriz, w);
2641 XtSetArg (arg[1], XtNleft, XawChainLeft);
2642 XtSetArg (arg[2], XtNright, XawChainLeft);
2643 XtSetArg (arg[3], XtNhorizDistance, 10);
2644 XtSetArg (arg[4], XtNlabel, "Pop");
2645 XtSetArg (arg[5], XtNtranslations,
2646 XtParseTranslationTable (pop_lang_trans));
2647 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2648 LangWidget, arg, 6);
2649 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2651 XtSetArg (arg[0], XtNfromHoriz, w);
2652 XtSetArg (arg[1], XtNleft, XawChainLeft);
2653 XtSetArg (arg[2], XtNright, XawChainRight);
2654 XtSetArg (arg[3], XtNlabel, "");
2655 XtSetArg (arg[4], XtNborderWidth, 0);
2656 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2657 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2658 LangWidget, arg, 6);
2661 XtSetArg (arg[0], XtNheight, win_height);
2662 XtSetArg (arg[1], XtNwidth, 10);
2663 XtSetArg (arg[2], XtNleft, XawChainLeft);
2664 XtSetArg (arg[3], XtNright, XawChainLeft);
2665 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2667 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2668 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2670 XtSetArg (arg[0], XtNheight, win_height);
2671 XtSetArg (arg[1], XtNwidth, win_width);
2672 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2673 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2674 XtSetArg (arg[4], XtNleft, XawChainLeft);
2675 XtSetArg (arg[5], XtNright, XawChainRight);
2676 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2679 XtSetArg (arg[0], XtNborderWidth, 0);
2680 XtSetArg (arg[1], XtNleft, XawChainLeft);
2681 XtSetArg (arg[2], XtNright, XawChainRight);
2682 XtSetArg (arg[3], XtNresizable, True);
2683 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2684 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2685 TailWidget, arg, 5);
2687 memset (&control, 0, sizeof control);
2688 control.two_dimensional = 1;
2689 control.enable_bidi = 1;
2691 control.anti_alias = 1;
2693 control.min_line_ascent = font_ascent;
2694 control.min_line_descent = font_descent;
2695 control.max_line_width = win_width;
2696 control.with_cursor = 1;
2697 control.cursor_width = 2;
2698 control.partial_update = 1;
2699 control.ignore_formatting_char = 1;
2701 memset (&input_status_control, 0, sizeof input_status_control);
2702 input_status_control.enable_bidi = 1;
2704 XtAppAddActions (context, actions, XtNumber (actions));
2705 XtRealizeWidget (ShellWidget);
2707 win = XtWindow (TextWidget);
2709 XtAppMainLoop (context);
2711 if (current_input_context)
2712 minput_destroy_ic (current_input_context);
2713 for (i = 0; i < num_input_methods; i++)
2714 minput_close_im (input_method_table[i]);
2715 m17n_object_unref (frame);
2716 m17n_object_unref (mt);
2717 m17n_object_unref (face_xxx_large);
2718 m17n_object_unref (face_box);
2719 m17n_object_unref (face_courier);
2720 m17n_object_unref (face_helvetica);
2721 m17n_object_unref (face_times);
2722 m17n_object_unref (face_dv_ttyogesh);
2723 m17n_object_unref (face_freesans);
2724 m17n_object_unref (face_freemono);
2725 m17n_object_unref (face_default_fontset);
2726 m17n_object_unref (face_no_ctl_fontset);
2727 m17n_object_unref (face_input_status);
2728 m17n_object_unref (selection);
2732 free (fontset_name);
2734 free (input_method_table);
2735 free (InputMethodMenus);
2737 XFreeGC (display, mono_gc);
2738 XFreeGC (display, mono_gc_inv);
2739 XFreeGC (display, gc_inv);
2740 XtUninstallTranslations (form);
2741 XtUninstallTranslations (TextWidget);
2742 XtDestroyWidget (ShellWidget);
2743 XtDestroyApplicationContext (context);
2747 #endif /* not FOR_DOXYGEN */