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;
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 NULL, NULL, NULL, &rect);
1796 mdraw_text (frame, (MDrawWindow) input_status_pixmap,
1797 input_status_width - rect.width - 2, - rect.y,
1798 ic->status, 0, mtext_len (ic->status));
1800 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1801 XtSetValues (CurIMStatus, arg, 1);
1805 compare_input_method (const void *elt1, const void *elt2)
1807 const MInputMethod *im1 = *(MInputMethod **) elt1;
1808 const MInputMethod *im2 = *(MInputMethod **) elt2;
1809 MSymbol lang1, lang2;
1811 if (im1->language == Mnil)
1813 if (im1->language == im2->language)
1814 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1815 if (im1->language == Mt)
1817 if (im2->language == Mt)
1819 lang1 = msymbol_get (im1->language, Mlanguage);
1820 lang2 = msymbol_get (im2->language, Mlanguage);
1821 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1825 setup_input_methods (int with_xim)
1827 MInputMethod *im = NULL;
1828 MInputXIMArgIM arg_xim;
1829 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
1833 num_input_methods = mplist_length (plist);
1837 arg_xim.display = display;
1839 arg_xim.res_name = arg_xim.res_class = NULL;
1840 arg_xim.locale = NULL;
1841 arg_xim.modifier_list = NULL;
1842 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
1844 num_input_methods++;
1846 input_method_table = calloc (num_input_methods, sizeof (MInputMethod *));
1848 input_method_table[i++] = im;
1849 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
1851 MDatabase *mdb = mplist_value (pl);
1852 MSymbol *tag = mdatabase_tag (mdb);
1856 im = minput_open_im (tag[1], tag[2], NULL);
1858 input_method_table[i++] = im;
1862 m17n_object_unref (plist);
1863 num_input_methods = i;
1864 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
1865 compare_input_method);
1866 current_input_context = NULL;
1868 mplist_put (minput_driver->callback_list, Minput_status_start,
1869 (void *) input_status);
1870 mplist_put (minput_driver->callback_list, Minput_status_draw,
1871 (void *) input_status);
1872 mplist_put (minput_driver->callback_list, Minput_status_done,
1873 (void *) input_status);
1878 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
1882 if (num && *num > 0)
1886 for (i = 0; i < *num; i++)
1887 bytes += strlen (str[i]) + 1;
1888 msg = alloca (bytes);
1889 strcpy (msg, str[0]);
1890 for (i = 1; i < *num; i++)
1891 strcat (msg, " "), strcat (msg, str[i]);
1893 else if (cursor.from < nchars)
1895 int c = mtext_ref_char (mt, cursor.from);
1896 char *name = mchar_get_prop (c, Mname);
1900 msg = alloca (10 + strlen (name));
1901 sprintf (msg, "U+%04X %s", c, name);
1907 XtSetArg (arg[0], XtNlabel, msg);
1908 XtSetValues (MessageWidget, arg, 1);
1914 char *name1, *name2;
1915 XtCallbackProc proc;
1916 XtPointer client_data;
1921 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
1923 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
1925 MenuRec FileMenu[] =
1926 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
1927 { 0, "Save", NULL, SaveProc, NULL, -1 },
1928 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
1930 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
1931 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
1933 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
1934 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
1936 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
1939 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
1941 MenuRec *rec = (MenuRec *) client_data;
1944 XtSetArg (arg[0], XtNvalue, "");
1945 XtSetArg (arg[1], XtNlabel, rec->name1);
1946 XtSetValues (FileDialogWidget, arg, 2);
1947 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
1948 XtSetArg (arg[0], XtNx, x + 20);
1949 XtSetArg (arg[1], XtNy, y + 10);
1950 XtSetValues (FileShellWidget, arg, 2);
1951 XtPopup (FileShellWidget, XtGrabExclusive);
1955 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
1960 XtPopdown (FileShellWidget);
1961 if ((int) client_data == 1)
1963 XtSetArg (arg[0], XtNlabel, &label);
1964 XtGetValues (FileDialogWidget, arg, 1);
1965 if (strcmp (label, FileMenu[0].name1) == 0)
1969 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
1970 fp = fopen (filename, "r");
1972 m17n_object_unref (mt);
1975 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1983 nchars = mtext_len (mt);
1985 update_cursor (0, 1);
1986 redraw (0, win_height, 1, 1);
1988 else if (strcmp (label, FileMenu[2].name1) == 0)
1989 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
1991 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
1994 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
1995 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
1996 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
1997 (MENU).status = (STATUS))
2001 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2002 char *menu_name, MenuRec *menus, int num_menus, char *help)
2004 Widget button, menu;
2005 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2006 <LeaveWindow>: reset() MenuHelp()\n\
2007 <BtnDown>: reset() PopupMenu()\n\
2008 <BtnUp>: highlight()";
2014 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2015 for (i = 0; i < num_menus; i++)
2026 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2028 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2030 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2032 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2036 XtSetArg (arg[0], XtNsensitive, False);
2037 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2043 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2048 trans = alloca (strlen (fmt) + strlen (help));
2049 sprintf (trans, fmt, help);
2050 XtSetArg (arg[0], XtNmenuName, menu_name);
2051 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2052 XtSetArg (arg[2], XtNinternalWidth, 2);
2053 XtSetArg (arg[3], XtNhighlightThickness, 1);
2054 XtSetArg (arg[4], XtNleft, XawChainLeft);
2055 XtSetArg (arg[5], XtNright, XawChainLeft);
2058 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2059 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2064 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2065 int *len = alloca (sizeof (int) * num_menus);
2068 XFontSetExtents *fontset_extents;
2070 XtSetArg (arg[0], XtNfontSet, &font_set);
2071 XtGetValues (button, arg, 1);
2073 fontset_extents = XExtentsOfFontSet (font_set);
2074 height = fontset_extents->max_logical_extent.height;
2075 ascent = - fontset_extents->max_logical_extent.y;
2077 for (i = 0; i < num_menus; i++)
2080 len[i] = strlen (menus[i].name2);
2081 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2082 if (max_width < width[i])
2083 max_width = width[i];
2085 for (i = 0; i < num_menus; i++)
2088 Pixmap pixmap = XCreatePixmap (display,
2089 RootWindow (display, screen),
2090 max_width, height, 1);
2091 XFillRectangle (display, pixmap, mono_gc_inv,
2092 0, 0, max_width, height);
2093 XmbDrawString (display, pixmap, font_set, mono_gc,
2094 max_width - width[i], ascent,
2095 menus[i].name2, len[i]);
2096 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2097 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2098 XtSetValues (menus[i].w, arg, 2);
2106 XtActionsRec actions[] = {
2107 {"Expose", ExposeProc},
2108 {"Configure", ConfigureProc},
2110 {"ButtonPress", ButtonProc},
2111 {"ButtonRelease", ButtonReleaseProc},
2112 {"ButtonMotion", ButtonMoveProc},
2113 {"Button2Press", Button2Proc},
2114 {"MenuHelp", MenuHelpProc}
2118 /* Print the usage of this program (the name is PROG), and exit with
2122 help_exit (char *prog, int exit_code)
2130 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2131 printf ("Display FILE on a window and allow users to edit it.\n");
2132 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2133 printf ("The following OPTIONs are available.\n");
2134 printf (" %-13s %s", "--version", "print version number\n");
2135 printf (" %-13s %s", "-h, --help", "print this message\n");
2140 main (int argc, char **argv)
2142 Widget form, BodyWidget, w;
2143 char *fontset_name = NULL;
2144 int col = 80, row = 32;
2145 /* Translation table for TextWidget. */
2146 String trans = "<Expose>: Expose()\n\
2147 <Configure>: Configure()\n\
2150 <Btn1Down>: ButtonPress()\n\
2151 <Btn1Up>: ButtonRelease()\n\
2152 <Btn1Motion>: ButtonMotion()\n\
2153 <Btn2Down>: Button2Press()";
2154 /* Translation table for the top form widget. */
2155 String trans2 = "<Key>: Key()\n\
2157 String pop_face_trans
2158 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2159 <LeaveWindow>: MenuHelp() reset()\n\
2160 <Btn1Down>: set()\n\
2161 <Btn1Up>: notify() unset()";
2162 String pop_lang_trans
2163 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2164 <LeaveWindow>: MenuHelp() reset()\n\
2165 <Btn1Down>: set()\n\
2166 <Btn1Up>: notify() unset()";
2167 int font_width, font_ascent, font_descent;
2171 setlocale (LC_ALL, "");
2172 /* Create the top shell. */
2173 XtSetLanguageProc (NULL, NULL, NULL);
2174 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2175 NULL, sessionShellWidgetClass, NULL, 0);
2176 display = XtDisplay (ShellWidget);
2177 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2179 /* Parse the remaining command line arguments. */
2180 for (i = 1; i < argc; i++)
2182 if (! strcmp (argv[i], "--help")
2183 || ! strcmp (argv[i], "-h"))
2184 help_exit (argv[0], 0);
2185 else if (! strcmp (argv[i], "--version"))
2187 printf ("medit (m17n library) %s\n", VERSION);
2188 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2191 else if (! strcmp (argv[i], "--geometry"))
2194 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2195 help_exit (argv[0], 1);
2197 else if (! strcmp (argv[i], "--fontset"))
2200 fontset_name = strdup (argv[i]);
2202 else if (! strcmp (argv[i], "--with-xim"))
2206 else if (argv[i][0] != '-')
2208 filename = strdup (argv[i]);
2212 fprintf (stderr, "Unknown option: %s", argv[i]);
2213 help_exit (argv[0], 1);
2217 help_exit (argv[0], 1);
2219 mdatabase_dir = ".";
2220 /* Initialize the m17n library. */
2222 if (merror_code != MERROR_NONE)
2223 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2225 mt = read_file (filename);
2228 nchars = mtext_len (mt);
2231 MFace *face = mface ();
2233 mface_put_prop (face, Mbackground, msymbol ("blue"));
2234 mface_put_prop (face, Mforeground, msymbol ("yellow"));
2235 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2236 m17n_object_unref (face);
2239 /* This tells ExposeProc to initialize everything. */
2242 XA_TEXT = XInternAtom (display, "TEXT", False);
2243 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2244 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2246 MPlist *plist = mplist ();
2250 mplist_put (plist, msymbol ("widget"), ShellWidget);
2253 MFontset *fontset = mfontset (fontset_name);
2256 mface_put_prop (face, Mfontset, fontset);
2257 m17n_object_unref (fontset);
2258 mplist_add (plist, Mface, face);
2259 m17n_object_unref (face);
2261 frame = mframe (plist);
2262 m17n_object_unref (plist);
2263 face_default = (MFace *) mframe_get_prop (frame, Mface);
2264 face_default_fontset = mface ();
2265 mface_put_prop (face_default_fontset, Mfontset,
2266 mface_get_prop (face_default, Mfontset));
2268 font = (MFont *) mframe_get_prop (frame, Mfont);
2269 default_font_size = (int) mfont_get_prop (font, Msize);
2272 font_width = (int) mframe_get_prop (frame, Mfont_width);
2273 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2274 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2275 win_width = font_width * col;
2276 win_height = (font_ascent + font_descent) * row;
2282 prop.color_top = prop.color_left = msymbol ("magenta");
2283 prop.color_bottom = prop.color_right = msymbol ("red");
2284 prop.inner_hmargin = prop.inner_vmargin = 1;
2285 prop.outer_hmargin = prop.outer_vmargin = 2;
2287 face_box = mface ();
2288 mface_put_prop (face_box, Mbox, &prop);
2291 face_courier = mface ();
2292 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2293 face_helvetica = mface ();
2294 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2295 face_times = mface ();
2296 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2297 face_dv_ttyogesh = mface ();
2298 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2299 face_freesans = mface ();
2300 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2301 face_freemono = mface ();
2302 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2304 face_xxx_large = mface ();
2305 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2307 MFont *latin_font = mframe_get_prop (frame, Mfont);
2308 MFont *dev_font = mfont ();
2309 MFont *thai_font = mfont ();
2310 MFont *tib_font = mfont ();
2312 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2313 MSymbol no_ctl = msymbol ("no-ctl");
2315 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2316 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2317 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2318 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2319 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2320 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2322 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2323 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2324 latin_font, Mnil, 0);
2325 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2326 dev_font, no_ctl, 0);
2327 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2328 thai_font, no_ctl, 0);
2329 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2330 tib_font, no_ctl, 0);
2331 face_no_ctl_fontset = mface ();
2332 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2333 m17n_object_unref (fontset);
2340 setup_input_methods (with_xim);
2342 gc = DefaultGC (display, screen);
2344 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2345 XtSetArg (arg[1], XtNdefaultDistance, 2);
2346 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2348 XtSetArg (arg[0], XtNborderWidth, 0);
2349 XtSetArg (arg[1], XtNdefaultDistance, 2);
2350 XtSetArg (arg[2], XtNtop, XawChainTop);
2351 XtSetArg (arg[3], XtNbottom, XawChainTop);
2352 XtSetArg (arg[4], XtNleft, XawChainLeft);
2353 XtSetArg (arg[5], XtNright, XawChainRight);
2354 XtSetArg (arg[6], XtNresizable, True);
2355 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2356 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2357 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2358 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2359 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2360 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2361 XtSetArg (arg[7], XtNfromVert, LangWidget);
2362 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2363 XtSetArg (arg[2], XtNtop, XawChainBottom);
2364 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2365 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2367 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2368 HeadWidget, NULL, 0);
2369 XtSetArg (arg[0], XtNvalue, "");
2370 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2371 FileShellWidget, arg, 1);
2372 XawDialogAddButton (FileDialogWidget, "OK",
2373 FileDialogProc, (XtPointer) 0);
2374 XawDialogAddButton (FileDialogWidget, "CANCEL",
2375 FileDialogProc, (XtPointer) 1);
2377 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2378 (char *) check_bits,
2379 check_width, check_height);
2381 unsigned long valuemask = GCForeground;
2384 values.foreground = 1;
2385 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2386 values.foreground = 0;
2387 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2394 if (num_menus < num_input_methods + 2)
2395 num_menus = num_input_methods + 2;
2396 if (num_menus < num_faces + 1)
2397 num_menus = num_faces + 1;
2398 menus = alloca (sizeof (MenuRec) * num_menus);
2400 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2401 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2402 "File I/O, Serialization, Image, Quit");
2404 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2405 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2406 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2407 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2408 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2409 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2410 w = create_menu_button (ShellWidget, HeadWidget, w,
2411 "Cursor", "Cursor Menu",
2412 menus, 6, "Cursor Movement Mode, Cursor Shape");
2413 CursorMenus[0] = menus[0].w;
2414 CursorMenus[1] = menus[1].w;
2415 CursorMenus[2] = menus[3].w;
2416 CursorMenus[3] = menus[4].w;
2417 CursorMenus[4] = menus[5].w;
2419 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2420 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2421 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2422 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2423 menus, 3, "BIDI Processing Mode");
2424 for (i = 0; i < 3; i++)
2425 BidiMenus[i] = menus[i].w;
2427 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2428 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2429 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2430 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2432 menus, 3, "How to break lines");
2433 for (i = 0; i < 3; i++)
2434 LineBreakMenus[i] = menus[i].w;
2436 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2437 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2438 for (i = 0; i < num_input_methods; i++)
2440 MInputMethod *im = input_method_table[i];
2441 char *name1, *name2;
2443 if (im->language != Mnil && im->language != Mt)
2445 MSymbol sym = msymbol_get (im->language, Mlanguage);
2447 name1 = msymbol_name (im->language);
2449 name1 = msymbol_name (sym);
2450 name2 = msymbol_name (im->name);
2453 name1 = msymbol_name (im->name), name2 = NULL;
2455 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2457 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2458 "Input Method Menu", menus, i + 2,
2459 "Select input method");
2462 unsigned long valuemask = GCForeground;
2465 XtSetArg (arg[0], XtNbackground, &values.foreground);
2466 XtGetValues (w, arg, 1);
2467 gc_inv = XCreateGC (display, RootWindow (display, screen),
2468 valuemask, &values);
2471 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2472 for (i = 0; i < num_input_methods + 2; i++)
2473 InputMethodMenus[i] = menus[i].w;
2475 input_status_width = font_width * 8;
2476 input_status_height = (font_ascent + font_descent) * 2.4;
2477 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2479 input_status_height,
2480 DefaultDepth (display, screen));
2485 prop.color_top = prop.color_bottom
2486 = prop.color_left = prop.color_right = Mnil;
2487 prop.inner_hmargin = prop.inner_vmargin = 1;
2488 prop.outer_hmargin = prop.outer_vmargin = 0;
2489 face_input_status = mface ();
2490 mface_put_prop (face_input_status, Mbox, &prop);
2493 XFillRectangle (display, input_status_pixmap, gc_inv,
2494 0, 0, input_status_width, input_status_height);
2495 XtSetArg (arg[0], XtNfromHoriz, w);
2496 XtSetArg (arg[1], XtNleft, XawRubber);
2497 XtSetArg (arg[2], XtNright, XawChainRight);
2498 XtSetArg (arg[3], XtNborderWidth, 0);
2499 XtSetArg (arg[4], XtNlabel, " ");
2500 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2501 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2502 HeadWidget, arg, 6);
2503 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2504 XtSetArg (arg[1], XtNleft, XawChainRight);
2505 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2506 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2507 HeadWidget, arg, 5);
2509 XtSetArg (arg[0], XtNborderWidth, 0);
2510 XtSetArg (arg[1], XtNleft, XawChainLeft);
2511 XtSetArg (arg[2], XtNright, XawChainLeft);
2512 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2513 for (i = 0; i < num_faces;)
2515 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2516 char *label = label_menu + 5; /* "Xxxx" */
2518 for (j = i; j < num_faces && face_table[j].face; j++)
2519 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2521 w = create_menu_button (ShellWidget, FaceWidget, w,
2523 menus, j - i, "Push face property");
2527 XtSetArg (arg[0], XtNfromHoriz, w);
2528 XtSetArg (arg[1], XtNleft, XawChainLeft);
2529 XtSetArg (arg[2], XtNright, XawChainLeft);
2530 XtSetArg (arg[3], XtNhorizDistance, 10);
2531 XtSetArg (arg[4], XtNlabel, "Pop");
2532 XtSetArg (arg[5], XtNtranslations,
2533 XtParseTranslationTable (pop_face_trans));
2534 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2535 FaceWidget, arg, 6);
2536 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2538 XtSetArg (arg[0], XtNfromHoriz, w);
2539 XtSetArg (arg[1], XtNleft, XawChainLeft);
2540 XtSetArg (arg[2], XtNright, XawChainRight);
2541 XtSetArg (arg[3], XtNlabel, "");
2542 XtSetArg (arg[4], XtNborderWidth, 0);
2543 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2544 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2545 FaceWidget, arg, 6);
2547 XtSetArg (arg[0], XtNborderWidth, 0);
2548 XtSetArg (arg[1], XtNleft, XawChainLeft);
2549 XtSetArg (arg[2], XtNright, XawChainLeft);
2550 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2552 MPlist *plist[11], *pl;
2555 for (i = 0; i < 11; i++) plist[i] = NULL;
2557 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2558 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2560 MSymbol sym = msymbol_exist (langname);
2564 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2566 char *name = msymbol_name (fullname);
2569 if (c >= 'A' && c <= 'Z')
2571 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2575 pl = plist[idx] = mplist ();
2576 for (; mplist_next (pl); pl = mplist_next (pl))
2577 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2579 mplist_push (pl, sym, fullname);
2584 for (i = 0; i < 11; i++)
2587 char *name = malloc (9);
2589 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2592 for (j = 0, pl = plist[i]; mplist_next (pl);
2593 j++, pl = mplist_next (pl))
2594 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2595 msymbol_name (mplist_key (pl)),
2596 LangProc, mplist_key (pl), -1);
2597 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2598 menus, j, "Push language property");
2600 for (i = 0; i < 11; i++)
2602 m17n_object_unref (plist[i]);
2604 XtSetArg (arg[0], XtNfromHoriz, w);
2605 XtSetArg (arg[1], XtNleft, XawChainLeft);
2606 XtSetArg (arg[2], XtNright, XawChainLeft);
2607 XtSetArg (arg[3], XtNhorizDistance, 10);
2608 XtSetArg (arg[4], XtNlabel, "Pop");
2609 XtSetArg (arg[5], XtNtranslations,
2610 XtParseTranslationTable (pop_lang_trans));
2611 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2612 LangWidget, arg, 6);
2613 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2615 XtSetArg (arg[0], XtNfromHoriz, w);
2616 XtSetArg (arg[1], XtNleft, XawChainLeft);
2617 XtSetArg (arg[2], XtNright, XawChainRight);
2618 XtSetArg (arg[3], XtNlabel, "");
2619 XtSetArg (arg[4], XtNborderWidth, 0);
2620 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2621 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2622 LangWidget, arg, 6);
2625 XtSetArg (arg[0], XtNheight, win_height);
2626 XtSetArg (arg[1], XtNwidth, 10);
2627 XtSetArg (arg[2], XtNleft, XawChainLeft);
2628 XtSetArg (arg[3], XtNright, XawChainLeft);
2629 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2631 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2632 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2634 XtSetArg (arg[0], XtNheight, win_height);
2635 XtSetArg (arg[1], XtNwidth, win_width);
2636 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2637 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2638 XtSetArg (arg[4], XtNleft, XawChainLeft);
2639 XtSetArg (arg[5], XtNright, XawChainRight);
2640 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2643 XtSetArg (arg[0], XtNborderWidth, 0);
2644 XtSetArg (arg[1], XtNleft, XawChainLeft);
2645 XtSetArg (arg[2], XtNright, XawChainRight);
2646 XtSetArg (arg[3], XtNresizable, True);
2647 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2648 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2649 TailWidget, arg, 5);
2651 memset (&control, 0, sizeof control);
2652 control.two_dimensional = 1;
2653 control.enable_bidi = 1;
2654 control.min_line_ascent = font_ascent;
2655 control.min_line_descent = font_descent;
2656 control.max_line_width = win_width;
2657 control.with_cursor = 1;
2658 control.cursor_width = 2;
2659 control.partial_update = 1;
2660 control.ignore_formatting_char = 1;
2662 XtAppAddActions (context, actions, XtNumber (actions));
2663 XtRealizeWidget (ShellWidget);
2665 win = XtWindow (TextWidget);
2667 XtAppMainLoop (context);
2669 if (current_input_context)
2670 minput_destroy_ic (current_input_context);
2671 for (i = 0; i < num_input_methods; i++)
2672 minput_close_im (input_method_table[i]);
2673 m17n_object_unref (frame);
2675 m17n_object_unref (mt);
2676 m17n_object_unref (face_xxx_large);
2677 m17n_object_unref (face_box);
2678 m17n_object_unref (face_courier);
2679 m17n_object_unref (face_helvetica);
2680 m17n_object_unref (face_times);
2681 m17n_object_unref (face_dv_ttyogesh);
2682 m17n_object_unref (face_freesans);
2683 m17n_object_unref (face_freemono);
2684 m17n_object_unref (face_default_fontset);
2685 m17n_object_unref (face_no_ctl_fontset);
2686 m17n_object_unref (face_input_status);
2687 m17n_object_unref (selection);
2691 free (fontset_name);
2693 XtUninstallTranslations (form);
2694 XtUninstallTranslations (TextWidget);
2695 XtDestroyWidget (ShellWidget);
2696 XtDestroyApplicationContext (context);
2700 #endif /* not FOR_DOXYGEN */