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>
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. The lihe is a cursor line if the
332 cursor is at the position above 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 GLYPH_INFO (bol (from, 0), from, info);
502 sel_start.ascent = -info.this.y;
503 sel_start.from = info.line_from;
504 sel_start.to = info.line_to;
505 TEXT_EXTENTS (from, top.from, rect);
506 sel_start.y0 = - rect.height;
507 sel_start.y1 = sel_start.y0 + info.this.height;
511 GLYPH_INFO (top.from, from, info);
512 sel_start.y0 = top.ascent + info.y + info.this.y;
513 sel_start.y1 = sel_start.y0 + info.this.height;
514 sel_start.ascent = -info.this.y;
515 sel_start.from = info.line_from;
516 sel_start.to = info.line_to;
519 if (to <= sel_start.to)
522 to = bol (to - 1, 1) - 1;
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 to = bol (to - 1, 1) - 1;
533 GLYPH_INFO (sel_start.from, to, info);
534 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
535 sel_end.y1 = sel_end.y0 + info.this.height;
536 sel_end.ascent = - info.this.y;
537 sel_end.from = info.line_from;
538 sel_end.to = info.line_to;
543 /* Select the text in the region from $FROM to $TO. */
545 select_region (int from, int to)
550 pos = from, from = to, to = pos;
551 mtext_push_property (mt, from, to, selection);
556 /* Setup the window to display the character of $POS at the top left
562 /* Top and bottom Y positions to redraw. */
565 if (pos + 1000 < top.from)
566 y0 = 0, y1 = win_height;
567 else if (pos < top.from)
570 TEXT_EXTENTS (pos, top.from, rect);
571 if (rect.height >= win_height * 0.9)
576 COPY_AREA (0, win_height - y1, y1);
579 else if (pos < top.to)
581 /* No need of redrawing. */
584 else if (pos < top.from + 1000)
586 TEXT_EXTENTS (top.from, pos, rect);
587 if (rect.height >= win_height * 0.9)
591 y0 = win_height - rect.height;
592 COPY_AREA (rect.height, win_height, 0);
597 y0 = 0, y1 = win_height;
603 update_cursor (pos, 1);
605 update_cursor (cursor.from, 1);
607 redraw (y0, y1, 1, 1);
611 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
614 /* Select an input method accoding to $IDX. If $IDX is negative, turn
615 off the current input method, otherwide turn on the input method
616 input_method_table[$IDX]. */
618 select_input_method (idx)
620 if (idx == current_input_method)
622 if (current_input_context)
624 minput_destroy_ic (current_input_context);
625 current_input_context = NULL;
626 current_input_method = -1;
630 MInputMethod *im = input_method_table[idx];
632 if (im->language == Mnil)
634 MInputXIMArgIC arg_xic;
635 Window win = XtWindow (TextWidget);
637 arg_xic.input_style = 0;
638 arg_xic.client_win = arg_xic.focus_win = win;
639 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
640 current_input_context = minput_create_ic (im, &arg_xic);
644 MInputGUIArgIC arg_ic;
646 arg_ic.frame = frame;
647 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
648 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
649 current_input_context = minput_create_ic (im, &arg_ic);
652 if (current_input_context)
654 set_input_method_spot ();
655 current_input_method = idx;
658 if (current_input_method >= 0)
661 XtSetArg (arg[0], XtNlabel, &label);
662 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
663 XtSetArg (arg[0], XtNlabel, label);
666 XtSetArg (arg[0], XtNlabel, "");
667 XtSetValues (CurIMLang, arg, 1);
670 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
673 /* Display cursor according to the current information of #CUR.
674 $CLIENT_DATA is ignore. Most callback functions add this function
675 as a background processing procedure the current application (by
676 XtAppAddWorkProc) via the function hide_cursor. */
678 show_cursor (XtPointer client_data)
683 update_cursor (cursor.from, 1);
685 while (cur.y1 > win_height)
688 update_cursor (cursor.from, 1);
691 control.cursor_pos = cursor.from;
694 control.with_cursor = 1;
697 if (current_input_context)
698 set_input_method_spot ();
701 int pos = (SELECTEDP () ? mtext_property_start (selection)
702 : cursor.from > 0 ? cursor.from - 1
704 MFace *face = mface ();
705 MTextProperty *props[256];
706 int n = mtext_get_properties (mt, pos, Mface, props, 256);
708 char buf[256], *p = buf;
714 int size = (int) mfont_get_prop (cursor.font, Msize);
715 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
716 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
717 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
718 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
720 sprintf (p, "%dpt", size / 10), p += strlen (p);
722 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
724 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
726 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
728 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
732 mface_merge (face, face_default);
733 for (i = 0; i < n; i++)
734 if (props[i] != selection)
735 mface_merge (face, (MFace *) mtext_property_value (props[i]));
736 sym = (MSymbol) mface_get_prop (face, Mforeground);
738 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
739 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
740 strcat (p, ",rev"), p += strlen (p);
741 if (mface_get_prop (face, Mhline))
742 strcat (p, ",ul"), p += strlen (p);
743 if (mface_get_prop (face, Mbox))
744 strcat (p, ",box"), p += strlen (p);
745 m17n_object_unref (face);
747 XtSetArg (arg[0], XtNborderWidth, 1);
748 XtSetArg (arg[1], XtNlabel, buf);
749 XtSetValues (CurFaceWidget, arg, 2);
752 if (control.cursor_pos < nchars)
756 if (control.cursor_pos > 0
757 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
758 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
760 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
764 XtSetArg (arg[0], XtNborderWidth, 0);
765 XtSetArg (arg[1], XtNlabel, "");
769 XtSetArg (arg[0], XtNborderWidth, 1);
770 XtSetArg (arg[1], XtNlabel,
771 msymbol_name (msymbol_get (sym, Mlanguage)));
772 XtSetValues (CurLangWidget, arg, 2);
774 XtSetValues (CurLangWidget, arg, 2);
776 if (auto_input_method)
779 select_input_method (-1);
784 for (i = 0; i < num_input_methods; i++)
785 if (input_method_table[i]->language == sym)
787 if (i < num_input_methods)
788 select_input_method (i);
790 select_input_method (-1);
795 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
801 /* Hide the cursor. */
805 control.with_cursor = 0;
807 XtAppAddWorkProc (context, show_cursor, NULL);
811 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
812 $Y1 and $NEW_Y1 assuming that the text in the other area is not
815 update_region (int y0, int old_y1, int new_y1)
821 if (old_y1 < win_height)
823 COPY_AREA (old_y1, win_height, new_y1);
824 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
827 redraw (new_y1, win_height, 1, 0);
829 else if (new_y1 > old_y1)
831 if (new_y1 < win_height)
832 COPY_AREA (old_y1, win_height, new_y1);
834 if (new_y1 > win_height)
836 redraw (y0, new_y1, 1, 1);
840 /* Delete the next $N characters. If $N is negative delete the
841 precious (- $N) characters. */
851 from = cursor.from, to = from + n;
854 if (cursor.from == cur.from)
856 /* We are at the beginning of line. */
857 int pos = cursor.prev_from;
859 if (cursor.from == top.from)
861 /* We are at the beginning of screen. We must scroll
863 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
864 reseat (info.line_from);
866 update_cursor (pos, 1);
872 from = cursor.from - 1;
877 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
878 old_y1 = cur.y0 + rect.height;
880 /* Now delete a character. */
881 mtext_del (mt, from, to);
883 if (from >= top.from && from < top.to)
884 update_top (top.from);
885 update_cursor (from, 1);
887 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
888 new_y1 = cur.y0 + rect.height;
890 update_region (cur.y0, old_y1, new_y1);
894 /* Insert M-text $NEWTEXT at the current cursor position. */
896 insert_chars (MText *newtext)
898 int n = mtext_len (newtext);
900 int y0, old_y1, new_y1;
904 int n = (mtext_property_end (selection)
905 - mtext_property_start (selection));
906 mtext_detach_property (selection);
911 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
912 old_y1 = y0 + rect.height;
914 /* Now insert chars. */
915 mtext_ins (mt, cursor.from, newtext);
917 if (cur.from == top.from)
918 update_top (top.from);
919 update_cursor (cursor.from + n, 1);
921 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
922 new_y1 = cur.y0 + rect.height;
924 update_region (y0, old_y1, new_y1);
929 /* Convert the currently selected text to COMPOUND-TEXT. It is called
930 when someone requests the current value of the selection. */
932 covert_selection (Widget w, Atom *selection_atom,
933 Atom *target, Atom *return_type,
934 XtPointer *value, unsigned long *length, int *format)
936 unsigned char *buf = (unsigned char *) XtMalloc (4096);
937 MText *this_mt = mtext ();
938 int from = mtext_property_start (selection);
939 int to = mtext_property_end (selection);
941 mtext_copy (this_mt, 0, mt, from, to);
942 *length = mconv_encode_buffer (msymbol ("compound-text"),
944 *return_type = XA_COMPOUND_TEXT;
945 *value = (XtPointer) buf;
947 m17n_object_unref (this_mt);
952 /* Unselect the text. It is called when we loose the selection. */
954 lose_selection (Widget w, Atom *selection_atom)
958 mtext_detach_property (selection);
959 redraw (sel_start.y0, sel_end.y1, 1, 0);
964 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
965 XtPointer value, unsigned long *length, int *format)
970 if (*type == XT_CONVERT_FAIL || ! value)
972 if (*type == XA_STRING)
974 else if (*type == XA_COMPOUND_TEXT)
975 coding = msymbol ("compound-text");
976 else if (*type == XA_UTF8_STRING)
977 coding = msymbol ("utf-8");
981 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
985 insert_chars (this_mt);
986 m17n_object_unref (this_mt);
995 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
997 XExposeEvent *expose = (XExposeEvent *) event;
1001 Dimension width_max, width;
1003 XtSetArg (arg[0], XtNwidth, &width);
1004 XtGetValues (XtParent (w), arg, 1);
1006 XtGetValues (HeadWidget, arg, 1);
1007 if (width_max < width)
1009 XtGetValues (FaceWidget, arg, 1);
1010 if (width_max < width)
1012 XtGetValues (LangWidget, arg, 1);
1013 if (width_max < width)
1015 XtSetArg (arg[0], XtNwidth, width_max);
1016 XtSetValues (HeadWidget, arg, 1);
1017 XtSetValues (FaceWidget, arg, 1);
1018 XtSetValues (LangWidget, arg, 1);
1019 XtSetValues (XtParent (w), arg, 1);
1020 XtSetValues (TailWidget, arg, 1);
1023 update_cursor (0, 1);
1024 redraw (0, win_height, 0, 1);
1029 redraw (expose->y, expose->y + expose->height, 0, 0);
1030 if (current_input_context
1031 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1032 set_input_method_spot ();
1037 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1039 XConfigureEvent *configure = (XConfigureEvent *) event;
1042 control.max_line_width = win_width = configure->width;
1043 win_height = configure->height;
1044 mdraw_clear_cache (mt);
1046 update_cursor (0, 1);
1047 redraw (0, win_height, 1, 1);
1048 if (current_input_context)
1049 set_input_method_spot ();
1053 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1056 int x = event->xbutton.x;
1057 int y = event->xbutton.y - top.ascent;
1059 if (control.orientation_reversed)
1061 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1064 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1065 mtext_detach_property (selection);
1066 redraw (sel_start.y0, sel_end.y1, 1, 0);
1069 update_cursor (pos, 0);
1074 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1079 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1080 covert_selection, lose_selection, NULL);
1081 update_cursor (mtext_property_start (selection), 0);
1086 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1090 /* We don't have a local selection. */
1091 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1096 int from = mtext_property_start (selection);
1097 int to = mtext_property_end (selection);
1100 int x = event->xbutton.x;
1101 int y = event->xbutton.y - top.ascent;
1103 if (control.orientation_reversed)
1105 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1107 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1108 mtext_detach_property (selection);
1110 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1111 update_cursor (pos, 0);
1112 insert_chars (this_mt);
1113 m17n_object_unref (this_mt);
1118 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1121 int x = event->xbutton.x;
1122 int y = event->xbutton.y;
1124 if (control.orientation_reversed)
1127 pos = top.from, y -= top.ascent;
1129 pos = cur.from, y -= cur.y0 + cur.ascent;
1130 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1132 if (pos == cursor.from)
1138 /* Selection range changed. */
1139 int from = mtext_property_start (selection);
1140 int to = mtext_property_end (selection);
1141 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1142 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1144 if (cursor.from == from)
1146 /* Start position of selection changed. */
1147 select_region (pos, to);
1149 /* Shrunken. Previous selection face must be cleared. */
1150 redraw (start_y0, sel_start.y1, 1, 0);
1152 /* Enlarged. We can simply overdraw. */
1153 redraw (sel_start.y0, start_y1, 0, 0);
1157 /* End position of selection changed. */
1158 select_region (from, pos);
1160 /* Shrunken. Previous selection face must be cleared. */
1161 redraw (sel_end.y0, end_y1, 1, 0);
1163 /* Enlarged. We can simply overdraw. */
1164 redraw (end_y0, sel_end.y1, 0, 0);
1169 /* Newly selected. */
1170 select_region (pos, cursor.from);
1171 redraw (sel_start.y0, sel_end.y1, 0, 0);
1173 update_cursor (pos, 1);
1177 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1180 MDrawGlyphInfo info;
1182 int cursor_pos = cursor.from;
1184 if (((int) position) < 0)
1190 height = top.y1 - top.y0;
1193 pos = bol (from - 1, 0);
1194 GLYPH_INFO (pos, from - 1, info);
1195 if (height + info.this.height > win_height)
1197 height += info.this.height;
1198 from = info.line_from;
1200 if (cursor_pos >= top.to)
1202 cursor_pos = top.from;
1204 while (cursor_pos < nchars)
1206 GLYPH_INFO (pos, pos, info);
1207 if (height + info.this.height > win_height)
1209 height += info.this.height;
1215 else if (cur.to < nchars)
1217 /* Scroll up, but leave at least one line. */
1220 while (from < nchars)
1222 GLYPH_INFO (from, from, info);
1223 if (height + info.this.height > win_height
1224 || info.line_to >= nchars)
1226 height += info.this.height;
1227 from = info.line_to;
1230 from = info.line_from;
1231 if (cursor_pos < from)
1235 /* Scroll up to make the cursor line top. */
1239 update_cursor (cursor_pos, 1);
1243 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1245 float persent = *(float *) persent_ptr;
1246 int pos1, pos2 = nchars * persent;
1247 MDrawGlyphInfo info;
1250 pos1 = bol (pos2, 0);
1251 GLYPH_INFO (pos1, pos2, info);
1252 pos1 = info.line_from;
1254 update_cursor (pos1, 1);
1259 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1261 XKeyEvent *key_event = (XKeyEvent *) event;
1263 KeySym keysym = NoSymbol;
1265 /* If set to 1, do not update target_x_position. */
1266 int keep_target_x_position = 0;
1269 if (current_input_context
1270 && minput_filter (current_input_context, Mnil, event))
1272 if (event->type == KeyRelease)
1277 produced = mtext ();
1278 ret = minput_lookup (current_input_context, Mnil, event, produced);
1279 if (mtext_len (produced) > 0)
1280 insert_chars (produced);
1282 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1283 m17n_object_unref (produced);
1293 n = (mtext_property_end (selection)
1294 - mtext_property_start (selection));
1295 mtext_detach_property (selection);
1297 else if (cursor.from < nchars)
1299 /* Delete the following grapheme cluster. */
1300 n = cursor.to - cursor.from;
1313 /* Delete selected region. */
1314 n = (mtext_property_end (selection)
1315 - mtext_property_start (selection));
1316 mtext_detach_property (selection);
1318 else if (cursor.from > 0)
1320 /* Delete the preceding character. */
1331 mtext_detach_property (selection);
1332 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1336 if (cursor.prev_from >= 0)
1337 update_cursor (cursor.prev_from, 0);
1341 if (cursor.left_from >= 0)
1342 update_cursor (cursor.left_from, 0);
1349 mtext_detach_property (selection);
1350 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1354 if (cursor.next_to >= 0)
1355 update_cursor (cursor.to, 0);
1359 if (cursor.right_from >= 0)
1360 update_cursor (cursor.right_from, 0);
1367 mtext_detach_property (selection);
1368 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1370 if (cur.to <= nchars)
1372 MDrawGlyphInfo info;
1375 GLYPH_INFO (cur.from, cur.to, info);
1376 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1377 target_x_position, info.y);
1378 keep_target_x_position = 1;
1379 update_cursor (pos, 0);
1386 mtext_detach_property (selection);
1387 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1393 int pos = bol (cur.from - 1, 0);
1395 TEXT_EXTENTS (pos, cur.from - 1, rect);
1396 y = rect.height + rect.y - 1;
1397 pos = COORDINATES_POSITION (pos, nchars,
1398 target_x_position, y);
1399 keep_target_x_position = 1;
1400 update_cursor (pos, 0);
1407 mtext_detach_property (selection);
1408 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1410 if (top.from < nchars)
1411 ScrollProc (w, NULL, (XtPointer) 1);
1417 mtext_detach_property (selection);
1418 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1421 ScrollProc (w, NULL, (XtPointer) -1);
1427 if (buf[0] == 17) /* C-q */
1429 XtAppSetExitFlag (context);
1432 else if (buf[0] == 12) /* C-l */
1434 redraw (0, win_height, 1, 1);
1439 MText *temp = mtext ();
1441 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1442 if (current_input_context)
1443 mtext_put_prop (temp, 0, 1, Mlanguage,
1444 current_input_context->im->language);
1445 insert_chars (temp);
1446 m17n_object_unref (temp);
1451 if (! keep_target_x_position)
1452 target_x_position = cursor.x;
1456 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1458 char *name = (char *) client_data;
1460 int from = -1, to = 0;
1465 filename = strdup (name);
1468 fp = fopen (filename, "w");
1471 fprintf (stderr, "Open for write fail: %s", filename);
1477 from = mtext_property_start (selection);
1478 to = mtext_property_end (selection);
1479 mtext_detach_property (selection);
1482 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1485 select_region (from, to);
1489 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1495 mtext_detach_property (selection);
1496 serialized = (int) client_data;
1498 new = mtext_deserialize (mt);
1501 MPlist *plist = mplist ();
1503 mplist_push (plist, Mt, Mface);
1504 mplist_push (plist, Mt, Mlanguage);
1505 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1506 m17n_object_unref (plist);
1510 m17n_object_unref (mt);
1512 serialized = ! serialized;
1513 nchars = mtext_len (mt);
1516 update_cursor (0, 1);
1517 redraw (0, win_height, 1, 1);
1521 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1523 XtAppSetExitFlag (context);
1529 FILE *fp = fopen (filename, "r");
1532 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1533 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1536 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1541 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1543 int data = (int) client_data;
1548 control.enable_bidi = 0;
1549 control.orientation_reversed = 0;
1553 control.enable_bidi = 1;
1554 control.orientation_reversed = data == 2;
1556 for (i = 0; i < 3; i++)
1559 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1561 XtSetArg (arg[0], XtNleftBitmap, None);
1562 XtSetValues (BidiMenus[i], arg, 1);
1565 update_cursor (cursor.from, 1);
1566 redraw (0, win_height, 1, 0);
1569 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1572 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1574 int data = (int) client_data;
1578 control.max_line_width = 0;
1581 control.max_line_width = win_width;
1582 control.line_break = (data == 1 ? NULL : line_break);
1584 for (i = 0; i < 3; i++)
1587 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1589 XtSetArg (arg[0], XtNleftBitmap, None);
1590 XtSetValues (LineBreakMenus[i], arg, 1);
1593 update_cursor (cursor.from, 1);
1594 redraw (0, win_height, 1, 0);
1598 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1600 int data = (int) client_data;
1614 control.cursor_bidi = 0, control.cursor_width = -1;
1618 control.cursor_bidi = 0, control.cursor_width = 2;
1622 control.cursor_bidi = 1;
1627 for (i = from; i < to; i++)
1630 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1632 XtSetArg (arg[0], XtNleftBitmap, None);
1633 XtSetValues (CursorMenus[i], arg, 1);
1636 redraw (0, win_height, 1, 0);
1640 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1642 int idx = (int) client_data;
1644 if (idx == -2 ? current_input_method < 0
1645 : idx == -1 ? auto_input_method
1646 : idx == current_input_method)
1649 XtSetArg (arg[0], XtNleftBitmap, None);
1650 if (auto_input_method)
1652 XtSetValues (InputMethodMenus[1], arg, 1);
1653 auto_input_method = 0;
1655 else if (current_input_method < 0)
1656 XtSetValues (InputMethodMenus[0], arg, 1);
1658 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1662 auto_input_method = 1;
1666 select_input_method (idx);
1667 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1668 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1672 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1674 int idx = (int) client_data;
1681 XtAppAddWorkProc (context, show_cursor, NULL);
1682 from = mtext_property_start (selection);
1683 to = mtext_property_end (selection);
1684 old_y1 = sel_end.y1;
1686 mtext_detach_property (selection);
1689 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1690 MTEXTPROP_REAR_STICKY);
1691 mtext_push_property (mt, from, to, prop);
1692 m17n_object_unref (prop);
1695 mtext_pop_prop (mt, from, to, Mface);
1697 update_top (top.from);
1698 update_cursor (cursor.from, 1);
1699 select_region (from, to);
1700 update_region (sel_start.y0, old_y1, sel_end.y1);
1701 if (cur.y1 > win_height)
1703 while (cur.y1 > win_height)
1706 update_cursor (cursor.from, 1);
1712 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1714 MSymbol sym = (MSymbol) client_data;
1721 XtAppAddWorkProc (context, show_cursor, NULL);
1722 from = mtext_property_start (selection);
1723 to = mtext_property_end (selection);
1724 old_y1 = sel_end.y1;
1726 mtext_detach_property (selection);
1728 mtext_put_prop (mt, from, to, Mlanguage, sym);
1730 mtext_pop_prop (mt, from, to, Mlanguage);
1733 update_top (top.from);
1734 update_cursor (cursor.from, 1);
1735 select_region (from, to);
1736 update_region (sel_start.y0, old_y1, sel_end.y1);
1737 if (cur.y1 > win_height)
1739 while (cur.y1 > win_height)
1742 update_cursor (cursor.from, 1);
1748 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1750 int narrowed = (int) client_data;
1753 MConverter *converter;
1759 from = mtext_property_start (selection);
1760 to = mtext_property_end (selection);
1769 mdump = popen ("mdump -q -p a4", "w");
1771 mdump = popen ("mdump -q", "w");
1774 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1775 mconv_encode_range (converter, mt, from, to);
1776 mconv_free_converter (converter);
1781 input_status (MInputContext *ic, MSymbol command)
1783 XFillRectangle (display, input_status_pixmap, gc_inv,
1784 0, 0, input_status_width, input_status_height);
1785 if (command == Minput_status_draw)
1789 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1790 Mface, face_input_status);
1791 if (ic->im->language != Mnil)
1792 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1793 Mlanguage, ic->im->language);
1794 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1795 &input_status_control, NULL, NULL, &rect);
1796 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1797 input_status_width - rect.width - 2, - rect.y,
1798 ic->status, 0, mtext_len (ic->status),
1799 &input_status_control);
1801 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1802 XtSetValues (CurIMStatus, arg, 1);
1806 compare_input_method (const void *elt1, const void *elt2)
1808 const MInputMethod *im1 = *(MInputMethod **) elt1;
1809 const MInputMethod *im2 = *(MInputMethod **) elt2;
1810 MSymbol lang1, lang2;
1812 if (im1->language == Mnil)
1814 if (im1->language == im2->language)
1815 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1816 if (im1->language == Mt)
1818 if (im2->language == Mt)
1820 lang1 = msymbol_get (im1->language, Mlanguage);
1821 lang2 = msymbol_get (im2->language, Mlanguage);
1822 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1826 setup_input_methods (int with_xim)
1828 MInputMethod *im = NULL;
1829 MInputXIMArgIM arg_xim;
1830 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1834 num_input_methods = mplist_length (plist);
1838 arg_xim.display = display;
1840 arg_xim.res_name = arg_xim.res_class = NULL;
1841 arg_xim.locale = NULL;
1842 arg_xim.modifier_list = NULL;
1843 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1845 num_input_methods++;
1847 input_method_table = calloc (num_input_methods, sizeof (MInputMethod *));
1849 input_method_table[i++] = im;
1850 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1852 MDatabase *mdb = mplist_value (pl);
1853 MSymbol *tag = mdatabase_tag (mdb);
1857 im = minput_open_im (tag[1], tag[2], NULL);
1859 input_method_table[i++] = im;
1863 m17n_object_unref (plist);
1864 num_input_methods = i;
1865 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
1866 compare_input_method);
1867 current_input_context = NULL;
1869 mplist_put (minput_driver->callback_list, Minput_status_start,
1870 (void *) input_status);
1871 mplist_put (minput_driver->callback_list, Minput_status_draw,
1872 (void *) input_status);
1873 mplist_put (minput_driver->callback_list, Minput_status_done,
1874 (void *) input_status);
1879 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
1883 if (num && *num > 0)
1887 for (i = 0; i < *num; i++)
1888 bytes += strlen (str[i]) + 1;
1889 msg = alloca (bytes);
1890 strcpy (msg, str[0]);
1891 for (i = 1; i < *num; i++)
1892 strcat (msg, " "), strcat (msg, str[i]);
1894 else if (cursor.from < nchars)
1896 int c = mtext_ref_char (mt, cursor.from);
1897 char *name = mchar_get_prop (c, Mname);
1901 msg = alloca (10 + strlen (name));
1902 sprintf (msg, "U+%04X %s", c, name);
1908 XtSetArg (arg[0], XtNlabel, msg);
1909 XtSetValues (MessageWidget, arg, 1);
1915 char *name1, *name2;
1916 XtCallbackProc proc;
1917 XtPointer client_data;
1922 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
1924 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
1926 MenuRec FileMenu[] =
1927 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
1928 { 0, "Save", NULL, SaveProc, NULL, -1 },
1929 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
1931 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
1932 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
1934 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
1935 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
1937 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
1940 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
1942 MenuRec *rec = (MenuRec *) client_data;
1945 XtSetArg (arg[0], XtNvalue, "");
1946 XtSetArg (arg[1], XtNlabel, rec->name1);
1947 XtSetValues (FileDialogWidget, arg, 2);
1948 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
1949 XtSetArg (arg[0], XtNx, x + 20);
1950 XtSetArg (arg[1], XtNy, y + 10);
1951 XtSetValues (FileShellWidget, arg, 2);
1952 XtPopup (FileShellWidget, XtGrabExclusive);
1956 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
1961 XtPopdown (FileShellWidget);
1962 if ((int) client_data == 1)
1964 XtSetArg (arg[0], XtNlabel, &label);
1965 XtGetValues (FileDialogWidget, arg, 1);
1966 if (strcmp (label, FileMenu[0].name1) == 0)
1970 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
1971 fp = fopen (filename, "r");
1973 m17n_object_unref (mt);
1976 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1984 nchars = mtext_len (mt);
1986 update_cursor (0, 1);
1987 redraw (0, win_height, 1, 1);
1989 else if (strcmp (label, FileMenu[2].name1) == 0)
1990 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
1992 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
1995 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
1996 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
1997 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
1998 (MENU).status = (STATUS))
2002 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2003 char *menu_name, MenuRec *menus, int num_menus, char *help)
2005 Widget button, menu;
2006 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2007 <LeaveWindow>: reset() MenuHelp()\n\
2008 <BtnDown>: reset() PopupMenu()\n\
2009 <BtnUp>: highlight()";
2015 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2016 for (i = 0; i < num_menus; i++)
2027 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2029 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2031 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2033 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2037 XtSetArg (arg[0], XtNsensitive, False);
2038 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2044 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2049 trans = alloca (strlen (fmt) + strlen (help));
2050 sprintf (trans, fmt, help);
2051 XtSetArg (arg[0], XtNmenuName, menu_name);
2052 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2053 XtSetArg (arg[2], XtNinternalWidth, 2);
2054 XtSetArg (arg[3], XtNhighlightThickness, 1);
2055 XtSetArg (arg[4], XtNleft, XawChainLeft);
2056 XtSetArg (arg[5], XtNright, XawChainLeft);
2059 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2060 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2065 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2066 int *len = alloca (sizeof (int) * num_menus);
2069 XFontSetExtents *fontset_extents;
2071 XtSetArg (arg[0], XtNfontSet, &font_set);
2072 XtGetValues (button, arg, 1);
2074 fontset_extents = XExtentsOfFontSet (font_set);
2075 height = fontset_extents->max_logical_extent.height;
2076 ascent = - fontset_extents->max_logical_extent.y;
2078 for (i = 0; i < num_menus; i++)
2081 len[i] = strlen (menus[i].name2);
2082 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2083 if (max_width < width[i])
2084 max_width = width[i];
2086 for (i = 0; i < num_menus; i++)
2089 Pixmap pixmap = XCreatePixmap (display,
2090 RootWindow (display, screen),
2091 max_width, height, 1);
2092 XFillRectangle (display, pixmap, mono_gc_inv,
2093 0, 0, max_width, height);
2094 XmbDrawString (display, pixmap, font_set, mono_gc,
2095 max_width - width[i], ascent,
2096 menus[i].name2, len[i]);
2097 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2098 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2099 XtSetValues (menus[i].w, arg, 2);
2107 XtActionsRec actions[] = {
2108 {"Expose", ExposeProc},
2109 {"Configure", ConfigureProc},
2111 {"ButtonPress", ButtonProc},
2112 {"ButtonRelease", ButtonReleaseProc},
2113 {"ButtonMotion", ButtonMoveProc},
2114 {"Button2Press", Button2Proc},
2115 {"MenuHelp", MenuHelpProc}
2119 /* Print the usage of this program (the name is PROG), and exit with
2123 help_exit (char *prog, int exit_code)
2131 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2132 printf ("Display FILE on a window and allow users to edit it.\n");
2133 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2134 printf ("The following OPTIONs are available.\n");
2135 printf (" %-13s %s", "--version", "print version number\n");
2136 printf (" %-13s %s", "-h, --help", "print this message\n");
2141 main (int argc, char **argv)
2143 Widget form, BodyWidget, w;
2144 char *fontset_name = NULL;
2145 int col = 80, row = 32;
2146 /* Translation table for TextWidget. */
2147 String trans = "<Expose>: Expose()\n\
2148 <Configure>: Configure()\n\
2151 <Btn1Down>: ButtonPress()\n\
2152 <Btn1Up>: ButtonRelease()\n\
2153 <Btn1Motion>: ButtonMotion()\n\
2154 <Btn2Down>: Button2Press()";
2155 /* Translation table for the top form widget. */
2156 String trans2 = "<Key>: Key()\n\
2158 String pop_face_trans
2159 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2160 <LeaveWindow>: MenuHelp() reset()\n\
2161 <Btn1Down>: set()\n\
2162 <Btn1Up>: notify() unset()";
2163 String pop_lang_trans
2164 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2165 <LeaveWindow>: MenuHelp() reset()\n\
2166 <Btn1Down>: set()\n\
2167 <Btn1Up>: notify() unset()";
2168 int font_width, font_ascent, font_descent;
2172 setlocale (LC_ALL, "");
2173 /* Create the top shell. */
2174 XtSetLanguageProc (NULL, NULL, NULL);
2175 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2176 NULL, sessionShellWidgetClass, NULL, 0);
2177 display = XtDisplay (ShellWidget);
2178 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2180 /* Parse the remaining command line arguments. */
2181 for (i = 1; i < argc; i++)
2183 if (! strcmp (argv[i], "--help")
2184 || ! strcmp (argv[i], "-h"))
2185 help_exit (argv[0], 0);
2186 else if (! strcmp (argv[i], "--version"))
2188 printf ("medit (m17n library) %s\n", VERSION);
2189 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2192 else if (! strcmp (argv[i], "--geometry"))
2195 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2196 help_exit (argv[0], 1);
2198 else if (! strcmp (argv[i], "--fontset"))
2201 fontset_name = strdup (argv[i]);
2203 else if (! strcmp (argv[i], "--with-xim"))
2207 else if (argv[i][0] != '-')
2209 filename = strdup (argv[i]);
2213 fprintf (stderr, "Unknown option: %s", argv[i]);
2214 help_exit (argv[0], 1);
2218 help_exit (argv[0], 1);
2220 mdatabase_dir = ".";
2221 /* Initialize the m17n library. */
2223 if (merror_code != MERROR_NONE)
2224 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2226 mt = read_file (filename);
2229 nchars = mtext_len (mt);
2232 MFace *face = mface ();
2234 mface_put_prop (face, Mbackground, msymbol ("blue"));
2235 mface_put_prop (face, Mforeground, msymbol ("yellow"));
2236 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2237 m17n_object_unref (face);
2240 /* This tells ExposeProc to initialize everything. */
2243 XA_TEXT = XInternAtom (display, "TEXT", False);
2244 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2245 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2247 MPlist *plist = mplist ();
2251 mplist_put (plist, msymbol ("widget"), ShellWidget);
2254 MFontset *fontset = mfontset (fontset_name);
2257 mface_put_prop (face, Mfontset, fontset);
2258 m17n_object_unref (fontset);
2259 mplist_add (plist, Mface, face);
2260 m17n_object_unref (face);
2262 frame = mframe (plist);
2263 m17n_object_unref (plist);
2264 face_default = (MFace *) mframe_get_prop (frame, Mface);
2265 face_default_fontset = mface ();
2266 mface_put_prop (face_default_fontset, Mfontset,
2267 mface_get_prop (face_default, Mfontset));
2269 font = (MFont *) mframe_get_prop (frame, Mfont);
2270 default_font_size = (int) mfont_get_prop (font, Msize);
2273 font_width = (int) mframe_get_prop (frame, Mfont_width);
2274 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2275 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2276 win_width = font_width * col;
2277 win_height = (font_ascent + font_descent) * row;
2283 prop.color_top = prop.color_left = msymbol ("magenta");
2284 prop.color_bottom = prop.color_right = msymbol ("red");
2285 prop.inner_hmargin = prop.inner_vmargin = 1;
2286 prop.outer_hmargin = prop.outer_vmargin = 2;
2288 face_box = mface ();
2289 mface_put_prop (face_box, Mbox, &prop);
2292 face_courier = mface ();
2293 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2294 face_helvetica = mface ();
2295 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2296 face_times = mface ();
2297 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2298 face_dv_ttyogesh = mface ();
2299 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2300 face_freesans = mface ();
2301 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2302 face_freemono = mface ();
2303 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2305 face_xxx_large = mface ();
2306 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2308 MFont *latin_font = mframe_get_prop (frame, Mfont);
2309 MFont *dev_font = mfont ();
2310 MFont *thai_font = mfont ();
2311 MFont *tib_font = mfont ();
2313 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2314 MSymbol no_ctl = msymbol ("no-ctl");
2316 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2317 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2318 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2319 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2320 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2321 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2323 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2324 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2325 latin_font, Mnil, 0);
2326 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2327 dev_font, no_ctl, 0);
2328 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2329 thai_font, no_ctl, 0);
2330 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2331 tib_font, no_ctl, 0);
2332 face_no_ctl_fontset = mface ();
2333 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2334 m17n_object_unref (fontset);
2341 setup_input_methods (with_xim);
2343 gc = DefaultGC (display, screen);
2345 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2346 XtSetArg (arg[1], XtNdefaultDistance, 2);
2347 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2349 XtSetArg (arg[0], XtNborderWidth, 0);
2350 XtSetArg (arg[1], XtNdefaultDistance, 2);
2351 XtSetArg (arg[2], XtNtop, XawChainTop);
2352 XtSetArg (arg[3], XtNbottom, XawChainTop);
2353 XtSetArg (arg[4], XtNleft, XawChainLeft);
2354 XtSetArg (arg[5], XtNright, XawChainRight);
2355 XtSetArg (arg[6], XtNresizable, True);
2356 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2357 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2358 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2359 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2360 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2361 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2362 XtSetArg (arg[7], XtNfromVert, LangWidget);
2363 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2364 XtSetArg (arg[2], XtNtop, XawChainBottom);
2365 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2366 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2368 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2369 HeadWidget, NULL, 0);
2370 XtSetArg (arg[0], XtNvalue, "");
2371 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2372 FileShellWidget, arg, 1);
2373 XawDialogAddButton (FileDialogWidget, "OK",
2374 FileDialogProc, (XtPointer) 0);
2375 XawDialogAddButton (FileDialogWidget, "CANCEL",
2376 FileDialogProc, (XtPointer) 1);
2378 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2379 (char *) check_bits,
2380 check_width, check_height);
2382 unsigned long valuemask = GCForeground;
2385 values.foreground = 1;
2386 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2387 values.foreground = 0;
2388 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2395 if (num_menus < num_input_methods + 2)
2396 num_menus = num_input_methods + 2;
2397 if (num_menus < num_faces + 1)
2398 num_menus = num_faces + 1;
2399 menus = alloca (sizeof (MenuRec) * num_menus);
2401 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2402 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2403 "File I/O, Serialization, Image, Quit");
2405 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2406 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2407 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2408 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2409 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2410 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2411 w = create_menu_button (ShellWidget, HeadWidget, w,
2412 "Cursor", "Cursor Menu",
2413 menus, 6, "Cursor Movement Mode, Cursor Shape");
2414 CursorMenus[0] = menus[0].w;
2415 CursorMenus[1] = menus[1].w;
2416 CursorMenus[2] = menus[3].w;
2417 CursorMenus[3] = menus[4].w;
2418 CursorMenus[4] = menus[5].w;
2420 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2421 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2422 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2423 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2424 menus, 3, "BIDI Processing Mode");
2425 for (i = 0; i < 3; i++)
2426 BidiMenus[i] = menus[i].w;
2428 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2429 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2430 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2431 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2433 menus, 3, "How to break lines");
2434 for (i = 0; i < 3; i++)
2435 LineBreakMenus[i] = menus[i].w;
2437 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2438 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2439 for (i = 0; i < num_input_methods; i++)
2441 MInputMethod *im = input_method_table[i];
2442 char *name1, *name2;
2444 if (im->language != Mnil && im->language != Mt)
2446 MSymbol sym = msymbol_get (im->language, Mlanguage);
2448 name1 = msymbol_name (im->language);
2450 name1 = msymbol_name (sym);
2451 name2 = msymbol_name (im->name);
2454 name1 = msymbol_name (im->name), name2 = NULL;
2456 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2458 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2459 "Input Method Menu", menus, i + 2,
2460 "Select input method");
2463 unsigned long valuemask = GCForeground;
2466 XtSetArg (arg[0], XtNbackground, &values.foreground);
2467 XtGetValues (w, arg, 1);
2468 gc_inv = XCreateGC (display, RootWindow (display, screen),
2469 valuemask, &values);
2472 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2473 for (i = 0; i < num_input_methods + 2; i++)
2474 InputMethodMenus[i] = menus[i].w;
2476 input_status_width = font_width * 8;
2477 input_status_height = (font_ascent + font_descent) * 2.4;
2478 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2480 input_status_height,
2481 DefaultDepth (display, screen));
2486 prop.color_top = prop.color_bottom
2487 = prop.color_left = prop.color_right = Mnil;
2488 prop.inner_hmargin = prop.inner_vmargin = 1;
2489 prop.outer_hmargin = prop.outer_vmargin = 0;
2490 face_input_status = mface ();
2491 mface_put_prop (face_input_status, Mbox, &prop);
2494 XFillRectangle (display, input_status_pixmap, gc_inv,
2495 0, 0, input_status_width, input_status_height);
2496 XtSetArg (arg[0], XtNfromHoriz, w);
2497 XtSetArg (arg[1], XtNleft, XawRubber);
2498 XtSetArg (arg[2], XtNright, XawChainRight);
2499 XtSetArg (arg[3], XtNborderWidth, 0);
2500 XtSetArg (arg[4], XtNlabel, " ");
2501 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2502 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2503 HeadWidget, arg, 6);
2504 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2505 XtSetArg (arg[1], XtNleft, XawChainRight);
2506 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2507 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2508 HeadWidget, arg, 5);
2510 XtSetArg (arg[0], XtNborderWidth, 0);
2511 XtSetArg (arg[1], XtNleft, XawChainLeft);
2512 XtSetArg (arg[2], XtNright, XawChainLeft);
2513 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2514 for (i = 0; i < num_faces;)
2516 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2517 char *label = label_menu + 5; /* "Xxxx" */
2519 for (j = i; j < num_faces && face_table[j].face; j++)
2520 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2522 w = create_menu_button (ShellWidget, FaceWidget, w,
2524 menus, j - i, "Push face property");
2528 XtSetArg (arg[0], XtNfromHoriz, w);
2529 XtSetArg (arg[1], XtNleft, XawChainLeft);
2530 XtSetArg (arg[2], XtNright, XawChainLeft);
2531 XtSetArg (arg[3], XtNhorizDistance, 10);
2532 XtSetArg (arg[4], XtNlabel, "Pop");
2533 XtSetArg (arg[5], XtNtranslations,
2534 XtParseTranslationTable (pop_face_trans));
2535 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2536 FaceWidget, arg, 6);
2537 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2539 XtSetArg (arg[0], XtNfromHoriz, w);
2540 XtSetArg (arg[1], XtNleft, XawChainLeft);
2541 XtSetArg (arg[2], XtNright, XawChainRight);
2542 XtSetArg (arg[3], XtNlabel, "");
2543 XtSetArg (arg[4], XtNborderWidth, 0);
2544 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2545 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2546 FaceWidget, arg, 6);
2548 XtSetArg (arg[0], XtNborderWidth, 0);
2549 XtSetArg (arg[1], XtNleft, XawChainLeft);
2550 XtSetArg (arg[2], XtNright, XawChainLeft);
2551 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2553 MPlist *plist[11], *pl;
2556 for (i = 0; i < 11; i++) plist[i] = NULL;
2558 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2559 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2561 MSymbol sym = msymbol_exist (langname);
2565 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2567 char *name = msymbol_name (fullname);
2570 if (c >= 'A' && c <= 'Z')
2572 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2576 pl = plist[idx] = mplist ();
2577 for (; mplist_next (pl); pl = mplist_next (pl))
2578 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2580 mplist_push (pl, sym, fullname);
2585 for (i = 0; i < 11; i++)
2588 char *name = malloc (9);
2590 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2593 for (j = 0, pl = plist[i]; mplist_next (pl);
2594 j++, pl = mplist_next (pl))
2595 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2596 msymbol_name (mplist_key (pl)),
2597 LangProc, mplist_key (pl), -1);
2598 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2599 menus, j, "Push language property");
2601 for (i = 0; i < 11; i++)
2603 m17n_object_unref (plist[i]);
2605 XtSetArg (arg[0], XtNfromHoriz, w);
2606 XtSetArg (arg[1], XtNleft, XawChainLeft);
2607 XtSetArg (arg[2], XtNright, XawChainLeft);
2608 XtSetArg (arg[3], XtNhorizDistance, 10);
2609 XtSetArg (arg[4], XtNlabel, "Pop");
2610 XtSetArg (arg[5], XtNtranslations,
2611 XtParseTranslationTable (pop_lang_trans));
2612 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2613 LangWidget, arg, 6);
2614 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2616 XtSetArg (arg[0], XtNfromHoriz, w);
2617 XtSetArg (arg[1], XtNleft, XawChainLeft);
2618 XtSetArg (arg[2], XtNright, XawChainRight);
2619 XtSetArg (arg[3], XtNlabel, "");
2620 XtSetArg (arg[4], XtNborderWidth, 0);
2621 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2622 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2623 LangWidget, arg, 6);
2626 XtSetArg (arg[0], XtNheight, win_height);
2627 XtSetArg (arg[1], XtNwidth, 10);
2628 XtSetArg (arg[2], XtNleft, XawChainLeft);
2629 XtSetArg (arg[3], XtNright, XawChainLeft);
2630 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2632 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2633 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2635 XtSetArg (arg[0], XtNheight, win_height);
2636 XtSetArg (arg[1], XtNwidth, win_width);
2637 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2638 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2639 XtSetArg (arg[4], XtNleft, XawChainLeft);
2640 XtSetArg (arg[5], XtNright, XawChainRight);
2641 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2644 XtSetArg (arg[0], XtNborderWidth, 0);
2645 XtSetArg (arg[1], XtNleft, XawChainLeft);
2646 XtSetArg (arg[2], XtNright, XawChainRight);
2647 XtSetArg (arg[3], XtNresizable, True);
2648 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2649 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2650 TailWidget, arg, 5);
2652 memset (&control, 0, sizeof control);
2653 control.two_dimensional = 1;
2654 control.enable_bidi = 1;
2655 control.min_line_ascent = font_ascent;
2656 control.min_line_descent = font_descent;
2657 control.max_line_width = win_width;
2658 control.with_cursor = 1;
2659 control.cursor_width = 2;
2660 control.partial_update = 1;
2661 control.ignore_formatting_char = 1;
2663 memset (&input_status_control, 0, sizeof input_status_control);
2664 input_status_control.enable_bidi = 1;
2666 XtAppAddActions (context, actions, XtNumber (actions));
2667 XtRealizeWidget (ShellWidget);
2669 win = XtWindow (TextWidget);
2671 XtAppMainLoop (context);
2673 if (current_input_context)
2674 minput_destroy_ic (current_input_context);
2675 for (i = 0; i < num_input_methods; i++)
2676 minput_close_im (input_method_table[i]);
2677 m17n_object_unref (frame);
2679 m17n_object_unref (mt);
2680 m17n_object_unref (face_xxx_large);
2681 m17n_object_unref (face_box);
2682 m17n_object_unref (face_courier);
2683 m17n_object_unref (face_helvetica);
2684 m17n_object_unref (face_times);
2685 m17n_object_unref (face_dv_ttyogesh);
2686 m17n_object_unref (face_freesans);
2687 m17n_object_unref (face_freemono);
2688 m17n_object_unref (face_default_fontset);
2689 m17n_object_unref (face_no_ctl_fontset);
2690 m17n_object_unref (face_input_status);
2691 m17n_object_unref (selection);
2695 free (fontset_name);
2697 XtUninstallTranslations (form);
2698 XtUninstallTranslations (TextWidget);
2699 XtDestroyWidget (ShellWidget);
2700 XtDestroyApplicationContext (context);
2704 #endif /* not FOR_DOXYGEN */