1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 @enpage medit edit multilingual text
26 @section medit-synopsis SYNOPSIS
28 medit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section medit-description DESCRIPTION
32 Display FILE on a window and allow users to edit it.
34 XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).
36 The following OPTIONs are available.
50 This program is to demonstrate how to use the m17n GUI API.
51 Although medit directly uses the GUI API, the API is mainly for
52 toolkit libraries or to implement XOM (X Outout Method), not for
53 direct use from application programs.
56 @japage medit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section medit-synopsis SYNOPSIS
60 medit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section medit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£medit ¤Ïľ
83 ÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é¥ê¤ä
84 XOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é ¥à
85 ¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
99 #include <X11/keysym.h>
100 #include <X11/Xatom.h>
101 #include <X11/Intrinsic.h>
102 #include <X11/StringDefs.h>
103 #include <X11/Shell.h>
104 #include <X11/Xaw/Command.h>
105 #include <X11/Xaw/Box.h>
106 #include <X11/Xaw/Form.h>
107 #include <X11/Xaw/Dialog.h>
108 #include <X11/Xaw/Scrollbar.h>
109 #include <X11/Xaw/Toggle.h>
110 #include <X11/Xaw/SimpleMenu.h>
111 #include <X11/Xaw/SmeBSB.h>
112 #include <X11/Xaw/SmeLine.h>
113 #include <X11/Xaw/MenuButton.h>
115 #include <m17n-gui.h>
116 #include <m17n-misc.h>
119 #define VERSION "1.0.1"
121 /* Global variables. */
126 /* For the X Window System. */
129 /* GCs for normal drawing, filling by background color, normal drawing
130 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
132 GC gc, gc_inv, mono_gc, mono_gc_inv;
134 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
135 XtAppContext context;
136 int default_font_size;
140 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
141 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
142 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
143 +- Body -- Sbar, Text
147 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
148 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
149 Widget SbarWidget, TextWidget;
150 Widget FileShellWidget, FileDialogWidget;
151 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
152 Widget CurIMLang, CurIMStatus;
154 int win_width, win_height; /* Size of TextWidget. */
157 Pixmap input_status_pixmap;
158 int input_status_width, input_status_height;
160 /* Bitmap for "check" glyph. */
161 #define check_width 9
162 #define check_height 8
163 static unsigned char check_bits[] = {
164 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
165 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
168 /* For the m17n library. */
171 int nchars; /* == mtext_len (mt) */
172 MDrawControl control, input_status_control;
173 MTextProperty *selection;
176 MFace *face_xxx_large;
178 MFace *face_courier, *face_helvetica, *face_times;
179 MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
180 MFace *face_default_fontset, *face_no_ctl_fontset;
181 MFace *face_input_status;
183 MSymbol Mcoding_compound_text;
185 int logical_move = 1; /* If 0, move cursor visually. */
189 MSymbol language, name;
193 InputMethodInfo *input_method_table;
195 int num_input_methods;
196 int current_input_method = -1; /* i.e. none */
197 int auto_input_method = 0;
198 MInputContext *current_input_context;
205 { {"Menu Size", NULL},
206 {"xx-small", &mface_xx_small},
207 {"x-small", &mface_x_small},
208 {"small", &mface_small},
209 {"normalsize", &mface_normalsize},
210 {"large", &mface_large},
211 {"x-large", &mface_x_large},
212 {"xx-large", &mface_xx_large},
213 {"xxx-large", &face_xxx_large},
215 {"Menu Family", NULL},
216 {"courier", &face_courier},
217 {"helvetica", &face_helvetica},
218 {"times", &face_times},
219 {"dv-ttyogesh", &face_dv_ttyogesh},
220 {"freesans", &face_freesans},
221 {"freeserif", &face_freeserif},
222 {"freemono", &face_freemono},
224 {"Menu Style", NULL},
225 {"medium", &mface_medium},
226 {"bold", &mface_bold},
227 {"italic", &mface_italic},
229 {"Menu Color", NULL},
230 {"black", &mface_black},
231 {"white", &mface_white},
233 {"green", &mface_green},
234 {"blue", &mface_blue},
235 {"cyan", &mface_cyan},
236 {"yello", &mface_yellow},
237 {"magenta", &mface_magenta},
240 {"normal", &mface_normal_video},
241 {"reverse", &mface_reverse_video},
242 {"underline", &mface_underline},
244 {"No CTL", &face_no_ctl_fontset} };
247 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
249 /* Information about a physical line metric. */
252 int from; /* BOL position of the line. */
253 int to; /* BOL position of the next line. */
254 int y0, y1; /* Top and bottom Y position of the line. */
255 int ascent; /* Height of the top Y position. */
258 struct LineInfo top; /* Topmost line. */
259 struct LineInfo cur; /* Line containing cursor. */
260 struct LineInfo sel_start; /* Line containing selection start. */
261 struct LineInfo sel_end; /* Line containing selection end. */
263 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
265 /* X position to keep on vertical (up and down) cursor motion. */
266 int target_x_position;
268 /* Interface macros for m17n-lib drawing routines. */
270 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
271 coordinate ($X, $Y) */
272 #define DRAW_TEXT(x, y, from, to) \
273 mdraw_text_with_control \
274 (frame, (MDrawWindow) win, \
275 control.orientation_reversed ? x + win_width : x, y, \
276 mt, from, to, &control)
278 /* Store the extents of a text in the range $FROM to $TO in the
279 structure $RECT (type MDrawMetric). */
280 #define TEXT_EXTENTS(from, to, rect) \
281 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
283 /* Store the glyph information of a character at the position $POS in
284 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
285 $FROM is written at the coordinate (0, 0). */
286 #define GLYPH_INFO(from, pos, info) \
287 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
289 /* Set $X and $Y to the coordinate of character at position $POS
290 assuming that the text from $FROM is written at the coordinate (0,
292 #define COORDINATES_POSITION(from, pos, x, y) \
293 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
295 /* Interface macros for X library. */
296 #define COPY_AREA(y0, y1, to) \
297 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
299 #define CLEAR_AREA(x, y, w, h) \
300 XClearArea (display, win, (x), (y), (w), (h), False)
302 #define SELECTEDP() \
303 mtext_property_mtext (selection)
305 /* Format MSG by FMT and print the result to the stderr, and exit. */
306 #define FATAL_ERROR(fmt, arg) \
308 fprintf (stderr, fmt, arg); \
313 /* If POS is greater than zero, move POS back to the beginning of line
314 (BOL) position. If FORWARD is nonzero, move POS forward instead.
315 Return the new position. */
317 bol (int pos, int forward)
319 int limit = forward ? nchars : 0;
321 pos = mtext_character (mt, pos, limit, '\n');
322 return (pos < 0 ? limit : pos + 1);
325 /* Update the structure #TOP (struct LineInfo) to make $POS the first
326 character position of the screen. */
330 int from = bol (pos, 0);
333 GLYPH_INFO (from, pos, info);
334 top.from = info.line_from;
335 top.to = info.line_to;
337 top.y1 = info.this.height;
338 top.ascent = - info.this.y;
342 /* Update the scroll bar so that the text of the range $FROM to $TO
343 are shown on the window. */
345 update_scroll_bar (int from, int to)
347 float top = (float) from / nchars;
348 float shown = (float) (to - from) / nchars;
349 XtArgVal *l_top = (XtArgVal *) ⊤
350 XtArgVal *l_shown = (XtArgVal *) &shown;
352 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
353 XtSetArg (arg[1], XtNshown, *l_shown);
354 XtSetValues (SbarWidget, arg, 2);
358 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
359 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
360 is nonzero, update the scoll bar. */
362 redraw (int y0, int y1, int clear, int scroll_bar)
367 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
368 struct LineInfo *line;
370 if (clear || control.anti_alias)
371 CLEAR_AREA (0, y0, win_width, y1 - y0);
373 /* Find a line closest to y0. It is a cursor line if the cursor is
374 Y0, otherwise the top line. */
379 /* If there exists a selected region, check it too. */
380 if (sel_y0 > line->y0 && y0 >= sel_y0)
385 info.this.height = line->y1 - y;
386 info.this.y = - line->ascent;
387 info.line_to = line->to;
388 while (from < nchars && y + info.this.height <= y0)
390 y += info.this.height;
392 GLYPH_INFO (from, from, info);
394 y0 = y - info.this.y;
396 while (to < nchars && y < y1)
398 GLYPH_INFO (to, to, info);
399 y += info.this.height;
405 DRAW_TEXT (0, y0, from, to);
410 GLYPH_INFO (to, to, info);
411 if (y + info.this.height >= win_height)
414 y += info.this.height;
416 update_scroll_bar (top.from, to);
421 /* Set the current input method spot to the correct position. */
423 set_input_method_spot ()
425 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
426 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
428 int n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
429 int size = 0, ratio = 0, i;
431 for (i = n - 1; i >= 0; i--)
434 size = (int) mface_get_prop (faces[i], Msize);
436 ratio = (int) mface_get_prop (faces[i], Mratio);
439 size = default_font_size;
441 size = size * ratio / 100;
442 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
443 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
448 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
451 redraw_cursor (int clear)
453 if (control.cursor_bidi)
455 /* We must update the whole line of the cursor. */
456 int beg = bol (cur.from, 0);
457 int end = bol (cur.to - 1, 1);
459 int y0 = cur.y0, y1 = cur.y1;
463 TEXT_EXTENTS (beg, cur.from, rect);
468 TEXT_EXTENTS (cur.to, end, rect);
471 redraw (y0, y1, clear, 0);
479 if (control.orientation_reversed)
480 x += win_width - cursor.logical_width;
481 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.this.height);
483 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
488 /* Update the information about the location of cursor to the position
489 $POS. If $FULL is nonzero, update the information fully only from
490 the information about the top line. Otherwise, truct the current
491 information in the structure $CUR. */
493 update_cursor (int pos, int full)
499 /* CUR is inaccurate. We can trust only TOP. */
500 GLYPH_INFO (top.from, pos, cursor);
501 cur.y0 = top.ascent + cursor.y + cursor.this.y;
503 else if (pos < cur.from)
505 int from = bol (pos, 0);
507 TEXT_EXTENTS (from, cur.from, rect);
508 GLYPH_INFO (from, pos, cursor);
509 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y);
511 else if (pos < cur.to)
513 GLYPH_INFO (cur.from, pos, cursor);
517 GLYPH_INFO (cur.from, pos, cursor);
518 cur.y0 += cur.ascent + cursor.y + cursor.this.y;
521 cur.from = cursor.line_from;
522 cur.to = cursor.line_to;
523 cur.y1 = cur.y0 + cursor.this.height;
524 cur.ascent = - cursor.this.y;
528 /* Update the information about the selected region. */
538 from = mtext_property_start (selection);
539 to = mtext_property_end (selection);
543 int pos = bol (from, 0);
545 TEXT_EXTENTS (pos, top.from, rect);
546 sel_start.y0 = top.y0 - rect.height;
547 sel_start.ascent = - rect.y;
548 GLYPH_INFO (pos, from, info);
549 if (pos < info.line_from)
550 sel_start.y0 += - rect.y + info.y + info.this.y;
554 GLYPH_INFO (top.from, from, info);
555 sel_start.y0 = top.ascent + info.y + info.this.y;
557 sel_start.ascent = -info.this.y;
558 sel_start.y1 = sel_start.y0 + info.this.height;
559 sel_start.from = info.line_from;
560 sel_start.to = info.line_to;
562 if (to <= sel_start.to)
565 if (to >= sel_end.to)
567 GLYPH_INFO (sel_start.from, to, info);
568 sel_end.y1 = sel_end.y0 + info.y + info.this.height;
569 sel_end.to = info.line_to;
574 GLYPH_INFO (sel_start.from, to, info);
575 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
576 sel_end.y1 = sel_end.y0 + info.this.height;
577 sel_end.ascent = - info.this.y;
578 sel_end.from = info.line_from;
579 sel_end.to = info.line_to;
584 /* Select the text in the region from $FROM to $TO. */
586 select_region (int from, int to)
591 pos = from, from = to, to = pos;
592 mtext_push_property (mt, from, to, selection);
597 /* Setup the window to display the character of $POS at the top left
603 /* Top and bottom Y positions to redraw. */
606 if (pos + 1000 < top.from)
607 y0 = 0, y1 = win_height;
608 else if (pos < top.from)
611 TEXT_EXTENTS (pos, top.from, rect);
612 if (rect.height >= win_height * 0.9)
617 COPY_AREA (0, win_height - y1, y1);
620 else if (pos < top.to)
622 /* No need of redrawing. */
625 else if (pos < top.from + 1000)
627 TEXT_EXTENTS (top.from, pos, rect);
628 if (rect.height >= win_height * 0.9)
632 y0 = win_height - rect.height;
633 COPY_AREA (rect.height, win_height, 0);
638 y0 = 0, y1 = win_height;
644 update_cursor (pos, 1);
646 update_cursor (cursor.from, 1);
648 redraw (y0, y1, 1, 1);
652 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
655 /* Select an input method accoding to $IDX. If $IDX is negative, turn
656 off the current input method, otherwide turn on the input method
657 input_method_table[$IDX]. */
659 select_input_method (idx)
661 if (idx == current_input_method)
663 if (current_input_context)
665 minput_destroy_ic (current_input_context);
666 current_input_context = NULL;
667 current_input_method = -1;
671 InputMethodInfo *im = input_method_table + idx;
673 if (im->language == Mnil)
675 MInputXIMArgIC arg_xic;
676 Window win = XtWindow (TextWidget);
678 arg_xic.input_style = 0;
679 arg_xic.client_win = arg_xic.focus_win = win;
680 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
681 current_input_context = minput_create_ic (im->im, &arg_xic);
685 MInputGUIArgIC arg_ic;
687 arg_ic.frame = frame;
688 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
689 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
690 current_input_context = minput_create_ic (im->im, &arg_ic);
693 if (current_input_context)
695 set_input_method_spot ();
696 current_input_method = idx;
699 if (current_input_method >= 0)
702 XtSetArg (arg[0], XtNlabel, &label);
703 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
704 XtSetArg (arg[0], XtNlabel, label);
707 XtSetArg (arg[0], XtNlabel, "");
708 XtSetValues (CurIMLang, arg, 1);
711 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
714 /* Display cursor according to the current information of #CUR.
715 $CLIENT_DATA is ignore. Most callback functions add this function
716 as a background processing procedure the current application (by
717 XtAppAddWorkProc) via the function hide_cursor. */
719 show_cursor (XtPointer client_data)
721 MFaceHLineProp *hline;
727 update_cursor (cursor.from, 1);
729 while (cur.y1 > win_height)
732 update_cursor (cursor.from, 1);
735 control.cursor_pos = cursor.from;
738 control.with_cursor = 1;
741 if (current_input_context)
742 set_input_method_spot ();
745 int pos = (SELECTEDP () ? mtext_property_start (selection)
746 : cursor.from > 0 ? cursor.from - 1
748 MFace *face = mface ();
749 MTextProperty *props[256];
750 int n = mtext_get_properties (mt, pos, Mface, props, 256);
752 char buf[256], *p = buf;
758 int size = (int) mfont_get_prop (cursor.font, Msize);
759 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
760 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
761 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
762 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
764 sprintf (p, "%dpt", size / 10), p += strlen (p);
766 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
768 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
770 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
772 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
776 mface_merge (face, face_default);
777 for (i = 0; i < n; i++)
778 if (props[i] != selection)
779 mface_merge (face, (MFace *) mtext_property_value (props[i]));
780 sym = (MSymbol) mface_get_prop (face, Mforeground);
782 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
783 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
784 strcat (p, ",rev"), p += strlen (p);
785 hline = mface_get_prop (face, Mhline);
786 if (hline && hline->width > 0)
787 strcat (p, ",ul"), p += strlen (p);
788 box = mface_get_prop (face, Mbox);
789 if (box && box->width > 0)
790 strcat (p, ",box"), p += strlen (p);
791 m17n_object_unref (face);
793 XtSetArg (arg[0], XtNborderWidth, 1);
794 XtSetArg (arg[1], XtNlabel, buf);
795 XtSetValues (CurFaceWidget, arg, 2);
798 if (control.cursor_pos < nchars)
802 if (control.cursor_pos > 0
803 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
804 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
806 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
810 XtSetArg (arg[0], XtNborderWidth, 0);
811 XtSetArg (arg[1], XtNlabel, "");
815 XtSetArg (arg[0], XtNborderWidth, 1);
816 XtSetArg (arg[1], XtNlabel,
817 msymbol_name (msymbol_get (sym, Mlanguage)));
818 XtSetValues (CurLangWidget, arg, 2);
820 XtSetValues (CurLangWidget, arg, 2);
822 if (auto_input_method)
825 select_input_method (-1);
830 for (i = 0; i < num_input_methods; i++)
831 if (input_method_table[i].language == sym)
833 if (i < num_input_methods
834 && input_method_table[i].available >= 0)
836 if (! input_method_table[i].im)
838 input_method_table[i].im =
839 minput_open_im (input_method_table[i].language,
840 input_method_table[i].name, NULL);
841 if (! input_method_table[i].im)
842 input_method_table[i].available = -1;
844 if (input_method_table[i].im)
845 select_input_method (i);
847 select_input_method (-1);
850 select_input_method (-1);
855 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
861 /* Hide the cursor. */
865 control.with_cursor = 0;
867 XtAppAddWorkProc (context, show_cursor, NULL);
871 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
872 $Y1 and $NEW_Y1 assuming that the text in the other area is not
875 update_region (int y0, int old_y1, int new_y1)
881 if (old_y1 < win_height)
883 COPY_AREA (old_y1, win_height, new_y1);
884 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
887 redraw (new_y1, win_height, 1, 0);
889 else if (new_y1 > old_y1)
891 if (new_y1 < win_height)
892 COPY_AREA (old_y1, win_height, new_y1);
894 if (new_y1 > win_height)
896 redraw (y0, new_y1, 1, 1);
900 /* Delete the next $N characters. If $N is negative delete the
901 precious (- $N) characters. */
911 from = cursor.from, to = from + n;
914 if (cursor.from == cur.from)
916 /* We are at the beginning of line. */
917 int pos = cursor.prev_from;
919 if (cursor.from == top.from)
921 /* We are at the beginning of screen. We must scroll
923 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
924 reseat (info.line_from);
926 update_cursor (pos, 1);
932 from = cursor.from - 1;
937 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
938 old_y1 = cur.y0 + rect.height;
940 /* Now delete a character. */
941 mtext_del (mt, from, to);
943 if (from >= top.from && from < top.to)
944 update_top (top.from);
945 update_cursor (from, 1);
947 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
948 new_y1 = cur.y0 + rect.height;
950 update_region (cur.y0, old_y1, new_y1);
954 /* Insert M-text $NEWTEXT at the current cursor position. */
956 insert_chars (MText *newtext)
958 int n = mtext_len (newtext);
960 int y0, old_y1, new_y1;
964 int n = (mtext_property_end (selection)
965 - mtext_property_start (selection));
966 mtext_detach_property (selection);
971 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
972 old_y1 = y0 + rect.height;
974 /* Now insert chars. */
975 mtext_ins (mt, cursor.from, newtext);
977 if (cur.from == top.from)
978 update_top (top.from);
979 update_cursor (cursor.from + n, 1);
981 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
982 new_y1 = cur.y0 + rect.height;
984 update_region (y0, old_y1, new_y1);
989 /* Convert the currently selected text to UTF8-STRING or
990 COMPOUND-TEXT. It is called when someone requests the current
991 value of the selection. */
993 covert_selection (Widget w, Atom *selection_atom,
994 Atom *target, Atom *return_type,
995 XtPointer *value, unsigned long *length, int *format)
997 unsigned char *buf = (unsigned char *) XtMalloc (4096);
998 MText *this_mt = mtext ();
999 int from = mtext_property_start (selection);
1000 int to = mtext_property_end (selection);
1003 mtext_copy (this_mt, 0, mt, from, to);
1004 if (*target == XA_TEXT)
1006 #ifdef X_HAVE_UTF8_STRING
1007 coding = Mcoding_utf_8;
1008 *return_type = XA_UTF8_STRING;
1010 coding = Mcoding_compound_text;
1011 *return_type = XA_COMPOUND_TEXT;
1014 else if (*target == XA_STRING)
1016 int len = to - from;
1019 for (i = 0; i < len; i++)
1020 if (mtext_ref_char (this_mt, i) >= 0x100)
1021 /* Can't encode in XA_STRING */
1023 coding = Mcoding_iso_8859_1;
1024 *return_type = XA_STRING;
1026 else if (*target == XA_COMPOUND_TEXT)
1028 coding = Mcoding_compound_text;
1029 *return_type = XA_COMPOUND_TEXT;
1031 *length = mconv_encode_buffer (coding, this_mt, buf, 4096);
1032 m17n_object_unref (this_mt);
1035 *value = (XtPointer) buf;
1041 /* Unselect the text. It is called when we loose the selection. */
1043 lose_selection (Widget w, Atom *selection_atom)
1047 mtext_detach_property (selection);
1048 redraw (sel_start.y0, sel_end.y1, 1, 0);
1053 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1054 XtPointer value, unsigned long *length, int *format)
1059 if (*type == XT_CONVERT_FAIL || ! value)
1061 if (*type == XA_STRING)
1063 else if (*type == XA_COMPOUND_TEXT)
1064 coding = msymbol ("compound-text");
1065 #ifdef X_HAVE_UTF8_STRING
1066 else if (*type == XA_UTF8_STRING)
1067 coding = msymbol ("utf-8");
1072 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1076 insert_chars (this_mt);
1077 m17n_object_unref (this_mt);
1086 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1088 XExposeEvent *expose = (XExposeEvent *) event;
1092 Dimension width_max, width;
1094 XtSetArg (arg[0], XtNwidth, &width);
1095 XtGetValues (XtParent (w), arg, 1);
1097 XtGetValues (HeadWidget, arg, 1);
1098 if (width_max < width)
1100 XtGetValues (FaceWidget, arg, 1);
1101 if (width_max < width)
1103 XtGetValues (LangWidget, arg, 1);
1104 if (width_max < width)
1106 XtSetArg (arg[0], XtNwidth, width_max);
1107 XtSetValues (HeadWidget, arg, 1);
1108 XtSetValues (FaceWidget, arg, 1);
1109 XtSetValues (LangWidget, arg, 1);
1110 XtSetValues (XtParent (w), arg, 1);
1111 XtSetValues (TailWidget, arg, 1);
1114 update_cursor (0, 1);
1115 redraw (0, win_height, 0, 1);
1120 redraw (expose->y, expose->y + expose->height, 0, 0);
1121 if (current_input_context
1122 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1123 set_input_method_spot ();
1128 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1130 XConfigureEvent *configure = (XConfigureEvent *) event;
1133 control.max_line_width = win_width = configure->width;
1134 win_height = configure->height;
1135 mdraw_clear_cache (mt);
1137 update_cursor (0, 1);
1138 redraw (0, win_height, 1, 1);
1139 if (current_input_context)
1140 set_input_method_spot ();
1144 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1147 int x = event->xbutton.x;
1148 int y = event->xbutton.y - top.ascent;
1150 if (control.orientation_reversed)
1152 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1155 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1156 mtext_detach_property (selection);
1157 redraw (sel_start.y0, sel_end.y1, 1, 0);
1160 update_cursor (pos, 0);
1165 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1170 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1171 covert_selection, lose_selection, NULL);
1172 update_cursor (mtext_property_start (selection), 0);
1177 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1181 /* We don't have a local selection. */
1182 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1187 int from = mtext_property_start (selection);
1188 int to = mtext_property_end (selection);
1191 int x = event->xbutton.x;
1192 int y = event->xbutton.y - top.ascent;
1194 if (control.orientation_reversed)
1196 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1198 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1199 mtext_detach_property (selection);
1201 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1202 update_cursor (pos, 0);
1203 insert_chars (this_mt);
1204 m17n_object_unref (this_mt);
1209 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1212 int x = event->xbutton.x;
1213 int y = event->xbutton.y;
1215 if (control.orientation_reversed)
1218 pos = top.from, y -= top.ascent;
1220 pos = cur.from, y -= cur.y0 + cur.ascent;
1221 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1223 if (pos == cursor.from)
1229 /* Selection range changed. */
1230 int from = mtext_property_start (selection);
1231 int to = mtext_property_end (selection);
1232 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1233 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1235 if (cursor.from == from)
1237 /* Starting position changed. */
1240 /* Enlarged. We can simply overdraw. */
1241 select_region (pos, to);
1242 redraw (sel_start.y0, start_y1, 0, 0);
1246 /* Shrunken. Previous selection face must be cleared. */
1247 select_region (pos, to);
1248 redraw (start_y0, sel_start.y1, 1, 0);
1252 /* Shrunken to zero. */
1253 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1254 mtext_detach_property (selection);
1255 redraw (start_y0, end_y1, 1, 0);
1259 /* Full update is necessary. */
1260 select_region (to, pos);
1261 redraw (start_y0, sel_end.y1, 1, 0);
1266 /* Ending position changed. */
1269 /* Full update is necessary. */
1270 select_region (pos, from);
1271 redraw (sel_start.y0, end_y1, 1, 0);
1273 else if (pos == from)
1275 /* Shrunken to zero. */
1276 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1277 mtext_detach_property (selection);
1278 redraw (start_y0, end_y1, 1, 0);
1282 /* Shrunken. Previous selection face must be cleared. */
1283 select_region (from, pos);
1284 redraw (sel_end.y0, end_y1, 1, 0);
1288 /* Enlarged. We can simply overdraw. */
1289 select_region (from, pos);
1290 redraw (end_y0, sel_end.y1, 0, 0);
1296 /* Newly selected. */
1297 select_region (pos, cursor.from);
1298 redraw (sel_start.y0, sel_end.y1, 0, 0);
1300 update_cursor (pos, 1);
1304 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1307 MDrawGlyphInfo info;
1309 int cursor_pos = cursor.from;
1311 if (((int) position) < 0)
1317 height = top.y1 - top.y0;
1320 pos = bol (from - 1, 0);
1321 GLYPH_INFO (pos, from - 1, info);
1322 if (height + info.this.height > win_height)
1324 height += info.this.height;
1325 from = info.line_from;
1327 if (cursor_pos >= top.to)
1329 cursor_pos = top.from;
1331 while (cursor_pos < nchars)
1333 GLYPH_INFO (pos, pos, info);
1334 if (height + info.this.height > win_height)
1336 height += info.this.height;
1342 else if (cur.to < nchars)
1344 /* Scroll up, but leave at least one line. */
1347 while (from < nchars)
1349 GLYPH_INFO (from, from, info);
1350 if (height + info.this.height > win_height
1351 || info.line_to >= nchars)
1353 height += info.this.height;
1354 from = info.line_to;
1357 from = info.line_from;
1358 if (cursor_pos < from)
1362 /* Scroll up to make the cursor line top. */
1366 update_cursor (cursor_pos, 1);
1370 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1372 float persent = *(float *) persent_ptr;
1373 int pos1, pos2 = nchars * persent;
1374 MDrawGlyphInfo info;
1377 pos1 = bol (pos2, 0);
1378 GLYPH_INFO (pos1, pos2, info);
1379 pos1 = info.line_from;
1381 update_cursor (pos1, 1);
1386 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1388 XKeyEvent *key_event = (XKeyEvent *) event;
1390 KeySym keysym = NoSymbol;
1392 /* If set to 1, do not update target_x_position. */
1393 int keep_target_x_position = 0;
1396 if (current_input_context
1397 && minput_filter (current_input_context, Mnil, event))
1399 if (event->type == KeyRelease)
1404 produced = mtext ();
1405 ret = minput_lookup (current_input_context, Mnil, event, produced);
1406 if (mtext_len (produced) > 0)
1407 insert_chars (produced);
1409 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1410 m17n_object_unref (produced);
1420 n = (mtext_property_end (selection)
1421 - mtext_property_start (selection));
1422 mtext_detach_property (selection);
1424 else if (cursor.from < nchars)
1426 /* Delete the following grapheme cluster. */
1427 n = cursor.to - cursor.from;
1440 /* Delete selected region. */
1441 n = (mtext_property_end (selection)
1442 - mtext_property_start (selection));
1443 mtext_detach_property (selection);
1445 else if (cursor.from > 0)
1447 /* Delete the preceding character. */
1458 mtext_detach_property (selection);
1459 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1463 if (cursor.prev_from >= 0)
1464 update_cursor (cursor.prev_from, 0);
1468 if (cursor.left_from >= 0)
1469 update_cursor (cursor.left_from, 0);
1476 mtext_detach_property (selection);
1477 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1481 if (cursor.next_to >= 0)
1482 update_cursor (cursor.to, 0);
1486 if (cursor.right_from >= 0)
1487 update_cursor (cursor.right_from, 0);
1494 mtext_detach_property (selection);
1495 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1497 if (cur.to <= nchars)
1499 MDrawGlyphInfo info;
1502 GLYPH_INFO (cur.from, cur.to, info);
1503 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1504 target_x_position, info.y);
1505 keep_target_x_position = 1;
1506 update_cursor (pos, 0);
1513 mtext_detach_property (selection);
1514 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1520 int pos = bol (cur.from - 1, 0);
1522 TEXT_EXTENTS (pos, cur.from - 1, rect);
1523 y = rect.height + rect.y - 1;
1524 pos = COORDINATES_POSITION (pos, nchars,
1525 target_x_position, y);
1526 keep_target_x_position = 1;
1527 update_cursor (pos, 0);
1534 mtext_detach_property (selection);
1535 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1537 if (top.from < nchars)
1538 ScrollProc (w, NULL, (XtPointer) 1);
1544 mtext_detach_property (selection);
1545 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1548 ScrollProc (w, NULL, (XtPointer) -1);
1554 if (buf[0] == 17) /* C-q */
1556 XtAppSetExitFlag (context);
1559 else if (buf[0] == 12) /* C-l */
1561 redraw (0, win_height, 1, 1);
1566 MText *temp = mtext ();
1568 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1569 if (current_input_context)
1570 mtext_put_prop (temp, 0, 1, Mlanguage,
1571 current_input_context->im->language);
1572 insert_chars (temp);
1573 m17n_object_unref (temp);
1578 if (! keep_target_x_position)
1579 target_x_position = cursor.x;
1583 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1585 char *name = (char *) client_data;
1587 int from = -1, to = 0;
1592 filename = strdup (name);
1595 fp = fopen (filename, "w");
1598 fprintf (stderr, "Open for write fail: %s", filename);
1604 from = mtext_property_start (selection);
1605 to = mtext_property_end (selection);
1606 mtext_detach_property (selection);
1609 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1612 select_region (from, to);
1616 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1622 mtext_detach_property (selection);
1623 serialized = (int) client_data;
1625 new = mtext_deserialize (mt);
1628 MPlist *plist = mplist ();
1630 mplist_push (plist, Mt, Mface);
1631 mplist_push (plist, Mt, Mlanguage);
1632 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1633 m17n_object_unref (plist);
1637 m17n_object_unref (mt);
1639 serialized = ! serialized;
1640 nchars = mtext_len (mt);
1643 update_cursor (0, 1);
1644 redraw (0, win_height, 1, 1);
1648 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1650 XtAppSetExitFlag (context);
1656 FILE *fp = fopen (filename, "r");
1659 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1660 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1663 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1668 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1670 int data = (int) client_data;
1675 control.enable_bidi = 0;
1676 control.orientation_reversed = 0;
1680 control.enable_bidi = 1;
1681 control.orientation_reversed = data == 2;
1683 for (i = 0; i < 3; i++)
1686 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1688 XtSetArg (arg[0], XtNleftBitmap, None);
1689 XtSetValues (BidiMenus[i], arg, 1);
1692 update_cursor (cursor.from, 1);
1693 redraw (0, win_height, 1, 0);
1696 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1699 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1701 int data = (int) client_data;
1705 control.max_line_width = 0;
1708 control.max_line_width = win_width;
1709 control.line_break = (data == 1 ? NULL : line_break);
1711 for (i = 0; i < 3; i++)
1714 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1716 XtSetArg (arg[0], XtNleftBitmap, None);
1717 XtSetValues (LineBreakMenus[i], arg, 1);
1720 update_cursor (cursor.from, 1);
1721 redraw (0, win_height, 1, 0);
1725 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1727 int data = (int) client_data;
1741 control.cursor_bidi = 0, control.cursor_width = -1;
1745 control.cursor_bidi = 0, control.cursor_width = 2;
1749 control.cursor_bidi = 1;
1754 for (i = from; i < to; i++)
1757 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1759 XtSetArg (arg[0], XtNleftBitmap, None);
1760 XtSetValues (CursorMenus[i], arg, 1);
1763 redraw (0, win_height, 1, 0);
1767 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1769 int idx = (int) client_data;
1771 if (idx == -2 ? current_input_method < 0
1772 : idx == -1 ? auto_input_method
1773 : idx == current_input_method)
1776 XtSetArg (arg[0], XtNleftBitmap, None);
1777 if (auto_input_method)
1779 XtSetValues (InputMethodMenus[1], arg, 1);
1780 auto_input_method = 0;
1782 else if (current_input_method < 0)
1783 XtSetValues (InputMethodMenus[0], arg, 1);
1785 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1789 auto_input_method = 1;
1792 else if (input_method_table[idx].available >= 0)
1794 if (! input_method_table[idx].im)
1796 input_method_table[idx].im =
1797 minput_open_im (input_method_table[idx].language,
1798 input_method_table[idx].name, NULL);
1799 if (! input_method_table[idx].im)
1800 input_method_table[idx].available = -1;
1802 if (input_method_table[idx].im)
1803 select_input_method (idx);
1805 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1806 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1809 MPlist *default_face_list;
1812 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1814 int idx = (int) client_data;
1824 MFace *face = mframe_get_prop (frame, Mface);
1826 for (plist = default_face_list; mplist_key (plist) != Mnil;
1827 plist = mplist_next (plist))
1828 mface_merge (face, mplist_value (plist));
1829 mplist_add (plist, Mt, *face_table[idx].face);
1830 mface_merge (face, *face_table[idx].face);
1832 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1834 MFace *face = mframe_get_prop (frame, Mface);
1836 for (plist = default_face_list;
1837 mplist_key (mplist_next (plist)) != Mnil;
1838 plist = mplist_next (plist))
1839 mface_merge (face, mplist_value (plist));
1843 update_cursor (0, 1);
1844 redraw (0, win_height, 1, 1);
1849 XtAppAddWorkProc (context, show_cursor, NULL);
1850 from = mtext_property_start (selection);
1851 to = mtext_property_end (selection);
1852 old_y1 = sel_end.y1;
1854 mtext_detach_property (selection);
1857 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1858 MTEXTPROP_REAR_STICKY);
1859 mtext_push_property (mt, from, to, prop);
1860 m17n_object_unref (prop);
1863 mtext_pop_prop (mt, from, to, Mface);
1865 update_top (top.from);
1866 update_cursor (cursor.from, 1);
1867 select_region (from, to);
1868 update_region (sel_start.y0, old_y1, sel_end.y1);
1869 if (cur.y1 > win_height)
1871 while (cur.y1 > win_height)
1874 update_cursor (cursor.from, 1);
1880 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1882 MSymbol sym = (MSymbol) client_data;
1889 XtAppAddWorkProc (context, show_cursor, NULL);
1890 from = mtext_property_start (selection);
1891 to = mtext_property_end (selection);
1892 old_y1 = sel_end.y1;
1894 mtext_detach_property (selection);
1896 mtext_put_prop (mt, from, to, Mlanguage, sym);
1898 mtext_pop_prop (mt, from, to, Mlanguage);
1901 update_top (top.from);
1902 update_cursor (cursor.from, 1);
1903 select_region (from, to);
1904 update_region (sel_start.y0, old_y1, sel_end.y1);
1905 if (cur.y1 > win_height)
1907 while (cur.y1 > win_height)
1910 update_cursor (cursor.from, 1);
1916 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1918 int narrowed = (int) client_data;
1921 MConverter *converter;
1927 from = mtext_property_start (selection);
1928 to = mtext_property_end (selection);
1937 mdump = popen ("mdump -q -p a4", "w");
1939 mdump = popen ("mdump -q", "w");
1942 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1943 mconv_encode_range (converter, mt, from, to);
1944 mconv_free_converter (converter);
1949 input_status (MInputContext *ic, MSymbol command)
1951 XFillRectangle (display, input_status_pixmap, gc_inv,
1952 0, 0, input_status_width, input_status_height);
1953 if (command == Minput_status_draw)
1957 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1958 Mface, face_input_status);
1959 if (ic->im->language != Mnil)
1960 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1961 Mlanguage, ic->im->language);
1962 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1963 &input_status_control, NULL, NULL, &rect);
1964 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1965 input_status_width - rect.width - 2, - rect.y,
1966 ic->status, 0, mtext_len (ic->status),
1967 &input_status_control);
1969 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1970 XtSetValues (CurIMStatus, arg, 1);
1974 compare_input_method (const void *elt1, const void *elt2)
1976 const InputMethodInfo *im1 = elt1;
1977 const InputMethodInfo *im2 = elt2;
1978 MSymbol lang1, lang2;
1980 if (im1->language == Mnil)
1982 if (im1->language == im2->language)
1983 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1984 if (im1->language == Mt)
1986 if (im2->language == Mt)
1988 lang1 = msymbol_get (im1->language, Mlanguage);
1989 lang2 = msymbol_get (im2->language, Mlanguage);
1990 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
1994 setup_input_methods (int with_xim)
1996 MInputMethod *im = NULL;
1997 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2001 num_input_methods = mplist_length (plist);
2005 MInputXIMArgIM arg_xim;
2007 arg_xim.display = display;
2009 arg_xim.res_name = arg_xim.res_class = NULL;
2010 arg_xim.locale = NULL;
2011 arg_xim.modifier_list = NULL;
2012 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2014 num_input_methods++;
2016 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2019 input_method_table[i].available = 1;
2020 input_method_table[i].language = Mnil;
2021 input_method_table[i].name = im->name;
2022 input_method_table[i].im = im;
2026 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2028 MDatabase *mdb = mplist_value (pl);
2029 MSymbol *tag = mdatabase_tag (mdb);
2033 input_method_table[i].language = tag[1];
2034 input_method_table[i].name = tag[2];
2039 m17n_object_unref (plist);
2040 num_input_methods = i;
2041 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2042 compare_input_method);
2043 current_input_context = NULL;
2045 mplist_put (minput_driver->callback_list, Minput_status_start,
2046 (void *) input_status);
2047 mplist_put (minput_driver->callback_list, Minput_status_draw,
2048 (void *) input_status);
2049 mplist_put (minput_driver->callback_list, Minput_status_done,
2050 (void *) input_status);
2055 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2059 if (num && *num > 0)
2063 for (i = 0; i < *num; i++)
2064 bytes += strlen (str[i]) + 1;
2065 msg = alloca (bytes);
2066 strcpy (msg, str[0]);
2067 for (i = 1; i < *num; i++)
2068 strcat (msg, " "), strcat (msg, str[i]);
2070 else if (cursor.from < nchars)
2072 int c = mtext_ref_char (mt, cursor.from);
2073 char *name = mchar_get_prop (c, Mname);
2077 msg = alloca (10 + strlen (name));
2078 sprintf (msg, "U+%04X %s", c, name);
2084 XtSetArg (arg[0], XtNlabel, msg);
2085 XtSetValues (MessageWidget, arg, 1);
2091 char *name1, *name2;
2092 XtCallbackProc proc;
2093 XtPointer client_data;
2098 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2100 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2102 MenuRec FileMenu[] =
2103 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2104 { 0, "Save", NULL, SaveProc, NULL, -1 },
2105 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2107 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2108 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2110 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2111 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2113 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2116 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2118 MenuRec *rec = (MenuRec *) client_data;
2121 XtSetArg (arg[0], XtNvalue, "");
2122 XtSetArg (arg[1], XtNlabel, rec->name1);
2123 XtSetValues (FileDialogWidget, arg, 2);
2124 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2125 XtSetArg (arg[0], XtNx, x + 20);
2126 XtSetArg (arg[1], XtNy, y + 10);
2127 XtSetValues (FileShellWidget, arg, 2);
2128 XtPopup (FileShellWidget, XtGrabExclusive);
2132 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2137 XtPopdown (FileShellWidget);
2138 if ((int) client_data == 1)
2140 XtSetArg (arg[0], XtNlabel, &label);
2141 XtGetValues (FileDialogWidget, arg, 1);
2142 if (strcmp (label, FileMenu[0].name1) == 0)
2146 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2147 fp = fopen (filename, "r");
2149 m17n_object_unref (mt);
2152 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2160 nchars = mtext_len (mt);
2162 update_cursor (0, 1);
2163 redraw (0, win_height, 1, 1);
2165 else if (strcmp (label, FileMenu[2].name1) == 0)
2166 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2168 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2171 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2172 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2173 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2174 (MENU).status = (STATUS))
2178 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2179 char *menu_name, MenuRec *menus, int num_menus, char *help)
2181 Widget button, menu;
2182 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2183 <LeaveWindow>: reset() MenuHelp()\n\
2184 <BtnDown>: reset() PopupMenu()\n\
2185 <BtnUp>: highlight()";
2191 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2192 for (i = 0; i < num_menus; i++)
2203 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2205 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2207 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2209 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2213 XtSetArg (arg[0], XtNsensitive, False);
2214 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2220 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2225 trans = alloca (strlen (fmt) + strlen (help));
2226 sprintf (trans, fmt, help);
2227 XtSetArg (arg[0], XtNmenuName, menu_name);
2228 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2229 XtSetArg (arg[2], XtNinternalWidth, 2);
2230 XtSetArg (arg[3], XtNhighlightThickness, 1);
2231 XtSetArg (arg[4], XtNleft, XawChainLeft);
2232 XtSetArg (arg[5], XtNright, XawChainLeft);
2235 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2236 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2241 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2242 int *len = alloca (sizeof (int) * num_menus);
2245 XFontSetExtents *fontset_extents;
2247 XtSetArg (arg[0], XtNfontSet, &font_set);
2248 XtGetValues (button, arg, 1);
2250 fontset_extents = XExtentsOfFontSet (font_set);
2251 height = fontset_extents->max_logical_extent.height;
2252 ascent = - fontset_extents->max_logical_extent.y;
2254 for (i = 0; i < num_menus; i++)
2257 len[i] = strlen (menus[i].name2);
2258 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2259 if (max_width < width[i])
2260 max_width = width[i];
2262 for (i = 0; i < num_menus; i++)
2265 Pixmap pixmap = XCreatePixmap (display,
2266 RootWindow (display, screen),
2267 max_width, height, 1);
2268 XFillRectangle (display, pixmap, mono_gc_inv,
2269 0, 0, max_width, height);
2270 XmbDrawString (display, pixmap, font_set, mono_gc,
2271 max_width - width[i], ascent,
2272 menus[i].name2, len[i]);
2273 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2274 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2275 XtSetValues (menus[i].w, arg, 2);
2283 XtActionsRec actions[] = {
2284 {"Expose", ExposeProc},
2285 {"Configure", ConfigureProc},
2287 {"ButtonPress", ButtonProc},
2288 {"ButtonRelease", ButtonReleaseProc},
2289 {"ButtonMotion", ButtonMoveProc},
2290 {"Button2Press", Button2Proc},
2291 {"MenuHelp", MenuHelpProc}
2295 /* Print the usage of this program (the name is PROG), and exit with
2299 help_exit (char *prog, int exit_code)
2307 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2308 printf ("Display FILE on a window and allow users to edit it.\n");
2309 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2310 printf ("The following OPTIONs are available.\n");
2311 printf (" %-13s %s", "--version", "print version number\n");
2312 printf (" %-13s %s", "-h, --help", "print this message\n");
2317 main (int argc, char **argv)
2319 Widget form, BodyWidget, w;
2320 char *fontset_name = NULL;
2321 int col = 80, row = 32;
2322 /* Translation table for TextWidget. */
2323 String trans = "<Expose>: Expose()\n\
2324 <Configure>: Configure()\n\
2327 <Btn1Down>: ButtonPress()\n\
2328 <Btn1Up>: ButtonRelease()\n\
2329 <Btn1Motion>: ButtonMotion()\n\
2330 <Btn2Down>: Button2Press()";
2331 /* Translation table for the top form widget. */
2332 String trans2 = "<Key>: Key()\n\
2334 String pop_face_trans
2335 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2336 <LeaveWindow>: MenuHelp() reset()\n\
2337 <Btn1Down>: set()\n\
2338 <Btn1Up>: notify() unset()";
2339 String pop_lang_trans
2340 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2341 <LeaveWindow>: MenuHelp() reset()\n\
2342 <Btn1Down>: set()\n\
2343 <Btn1Up>: notify() unset()";
2344 int font_width, font_ascent, font_descent;
2348 setlocale (LC_ALL, "");
2349 /* Create the top shell. */
2350 XtSetLanguageProc (NULL, NULL, NULL);
2351 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2352 NULL, sessionShellWidgetClass, NULL, 0);
2353 display = XtDisplay (ShellWidget);
2354 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2356 /* Parse the remaining command line arguments. */
2357 for (i = 1; i < argc; i++)
2359 if (! strcmp (argv[i], "--help")
2360 || ! strcmp (argv[i], "-h"))
2361 help_exit (argv[0], 0);
2362 else if (! strcmp (argv[i], "--version"))
2364 printf ("medit (m17n library) %s\n", VERSION);
2365 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2368 else if (! strcmp (argv[i], "--geometry"))
2371 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2372 help_exit (argv[0], 1);
2374 else if (! strcmp (argv[i], "--fontset"))
2377 fontset_name = strdup (argv[i]);
2379 else if (! strcmp (argv[i], "--with-xim"))
2383 else if (argv[i][0] != '-')
2385 filename = strdup (argv[i]);
2389 fprintf (stderr, "Unknown option: %s", argv[i]);
2390 help_exit (argv[0], 1);
2394 help_exit (argv[0], 1);
2396 mdatabase_dir = ".";
2397 /* Initialize the m17n library. */
2399 if (merror_code != MERROR_NONE)
2400 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2402 mt = read_file (filename);
2405 nchars = mtext_len (mt);
2408 MFace *face = mface ();
2410 mface_put_prop (face, Mforeground, msymbol ("blue"));
2411 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2412 mface_put_prop (face, Mvideomode, Mreverse);
2413 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2414 m17n_object_unref (face);
2417 /* This tells ExposeProc to initialize everything. */
2420 XA_TEXT = XInternAtom (display, "TEXT", False);
2421 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2422 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2423 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2424 if (Mcoding_compound_text == Mnil)
2425 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2428 MPlist *plist = mplist ();
2432 mplist_put (plist, msymbol ("widget"), ShellWidget);
2435 MFontset *fontset = mfontset (fontset_name);
2438 mface_put_prop (face, Mfontset, fontset);
2439 m17n_object_unref (fontset);
2440 mplist_add (plist, Mface, face);
2441 m17n_object_unref (face);
2443 frame = mframe (plist);
2445 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2446 m17n_object_unref (plist);
2447 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2448 default_face_list = mplist ();
2449 mplist_add (default_face_list, Mt, face_default);
2450 face_default_fontset = mface ();
2451 mface_put_prop (face_default_fontset, Mfontset,
2452 mface_get_prop (face_default, Mfontset));
2454 font = (MFont *) mframe_get_prop (frame, Mfont);
2455 default_font_size = (int) mfont_get_prop (font, Msize);
2458 font_width = (int) mframe_get_prop (frame, Mfont_width);
2459 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2460 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2461 win_width = font_width * col;
2462 win_height = (font_ascent + font_descent) * row;
2468 prop.color_top = prop.color_left = msymbol ("magenta");
2469 prop.color_bottom = prop.color_right = msymbol ("red");
2470 prop.inner_hmargin = prop.inner_vmargin = 1;
2471 prop.outer_hmargin = prop.outer_vmargin = 2;
2473 face_box = mface ();
2474 mface_put_prop (face_box, Mbox, &prop);
2477 face_courier = mface ();
2478 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2479 face_helvetica = mface ();
2480 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2481 face_times = mface ();
2482 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2483 face_dv_ttyogesh = mface ();
2484 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2485 face_freesans = mface ();
2486 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2487 face_freeserif = mface ();
2488 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2489 face_freemono = mface ();
2490 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2492 face_xxx_large = mface ();
2493 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2495 MFont *latin_font = mframe_get_prop (frame, Mfont);
2496 MFont *dev_font = mfont ();
2497 MFont *thai_font = mfont ();
2498 MFont *tib_font = mfont ();
2500 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2501 MSymbol no_ctl = msymbol ("no-ctl");
2503 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2504 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2505 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2506 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2507 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2508 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2510 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2511 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2512 latin_font, Mnil, 0);
2513 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2514 dev_font, no_ctl, 0);
2515 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2516 thai_font, no_ctl, 0);
2517 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2518 tib_font, no_ctl, 0);
2519 face_no_ctl_fontset = mface ();
2520 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2521 m17n_object_unref (fontset);
2528 setup_input_methods (with_xim);
2530 gc = DefaultGC (display, screen);
2532 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2533 XtSetArg (arg[1], XtNdefaultDistance, 2);
2534 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2536 XtSetArg (arg[0], XtNborderWidth, 0);
2537 XtSetArg (arg[1], XtNdefaultDistance, 2);
2538 XtSetArg (arg[2], XtNtop, XawChainTop);
2539 XtSetArg (arg[3], XtNbottom, XawChainTop);
2540 XtSetArg (arg[4], XtNleft, XawChainLeft);
2541 XtSetArg (arg[5], XtNright, XawChainRight);
2542 XtSetArg (arg[6], XtNresizable, True);
2543 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2544 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2545 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2546 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2547 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2548 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2549 XtSetArg (arg[7], XtNfromVert, LangWidget);
2550 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2551 XtSetArg (arg[2], XtNtop, XawChainBottom);
2552 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2553 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2555 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2556 HeadWidget, NULL, 0);
2557 XtSetArg (arg[0], XtNvalue, "");
2558 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2559 FileShellWidget, arg, 1);
2560 XawDialogAddButton (FileDialogWidget, "OK",
2561 FileDialogProc, (XtPointer) 0);
2562 XawDialogAddButton (FileDialogWidget, "CANCEL",
2563 FileDialogProc, (XtPointer) 1);
2565 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2566 (char *) check_bits,
2567 check_width, check_height);
2569 unsigned long valuemask = GCForeground;
2572 values.foreground = 1;
2573 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2574 values.foreground = 0;
2575 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2582 if (num_menus < num_input_methods + 2)
2583 num_menus = num_input_methods + 2;
2584 if (num_menus < num_faces + 1)
2585 num_menus = num_faces + 1;
2586 menus = alloca (sizeof (MenuRec) * num_menus);
2588 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2589 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2590 "File I/O, Serialization, Image, Quit");
2592 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2593 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2594 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2595 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2596 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2597 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2598 w = create_menu_button (ShellWidget, HeadWidget, w,
2599 "Cursor", "Cursor Menu",
2600 menus, 6, "Cursor Movement Mode, Cursor Shape");
2601 CursorMenus[0] = menus[0].w;
2602 CursorMenus[1] = menus[1].w;
2603 CursorMenus[2] = menus[3].w;
2604 CursorMenus[3] = menus[4].w;
2605 CursorMenus[4] = menus[5].w;
2607 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2608 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2609 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2610 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2611 menus, 3, "BIDI Processing Mode");
2612 for (i = 0; i < 3; i++)
2613 BidiMenus[i] = menus[i].w;
2615 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2616 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2617 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2618 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2620 menus, 3, "How to break lines");
2621 for (i = 0; i < 3; i++)
2622 LineBreakMenus[i] = menus[i].w;
2624 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2625 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2626 for (i = 0; i < num_input_methods; i++)
2628 InputMethodInfo *im = input_method_table + i;
2629 char *name1, *name2;
2631 if (im->language != Mnil && im->language != Mt)
2633 MSymbol sym = msymbol_get (im->language, Mlanguage);
2635 name1 = msymbol_name (im->language);
2637 name1 = msymbol_name (sym);
2638 name2 = msymbol_name (im->name);
2641 name1 = msymbol_name (im->name), name2 = NULL;
2643 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2645 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2646 "Input Method Menu", menus, i + 2,
2647 "Select input method");
2650 unsigned long valuemask = GCForeground;
2653 XtSetArg (arg[0], XtNbackground, &values.foreground);
2654 XtGetValues (w, arg, 1);
2655 gc_inv = XCreateGC (display, RootWindow (display, screen),
2656 valuemask, &values);
2659 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2660 for (i = 0; i < num_input_methods + 2; i++)
2661 InputMethodMenus[i] = menus[i].w;
2663 input_status_width = font_width * 8;
2664 input_status_height = (font_ascent + font_descent) * 2.4;
2665 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2667 input_status_height,
2668 DefaultDepth (display, screen));
2673 prop.color_top = prop.color_bottom
2674 = prop.color_left = prop.color_right = Mnil;
2675 prop.inner_hmargin = prop.inner_vmargin = 1;
2676 prop.outer_hmargin = prop.outer_vmargin = 0;
2677 face_input_status = mface_copy (face_default);
2678 mface_put_prop (face_input_status, Mbox, &prop);
2681 XFillRectangle (display, input_status_pixmap, gc_inv,
2682 0, 0, input_status_width, input_status_height);
2683 XtSetArg (arg[0], XtNfromHoriz, w);
2684 XtSetArg (arg[1], XtNleft, XawRubber);
2685 XtSetArg (arg[2], XtNright, XawChainRight);
2686 XtSetArg (arg[3], XtNborderWidth, 0);
2687 XtSetArg (arg[4], XtNlabel, " ");
2688 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2689 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2690 HeadWidget, arg, 6);
2691 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2692 XtSetArg (arg[1], XtNleft, XawChainRight);
2693 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2694 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2695 HeadWidget, arg, 5);
2697 XtSetArg (arg[0], XtNborderWidth, 0);
2698 XtSetArg (arg[1], XtNleft, XawChainLeft);
2699 XtSetArg (arg[2], XtNright, XawChainLeft);
2700 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2701 for (i = 0; i < num_faces;)
2703 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2704 char *label = label_menu + 5; /* "Xxxx" */
2706 for (j = i; j < num_faces && face_table[j].face; j++)
2707 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2709 w = create_menu_button (ShellWidget, FaceWidget, w,
2711 menus, j - i, "Push face property");
2715 XtSetArg (arg[0], XtNfromHoriz, w);
2716 XtSetArg (arg[1], XtNleft, XawChainLeft);
2717 XtSetArg (arg[2], XtNright, XawChainLeft);
2718 XtSetArg (arg[3], XtNhorizDistance, 10);
2719 XtSetArg (arg[4], XtNlabel, "Pop");
2720 XtSetArg (arg[5], XtNtranslations,
2721 XtParseTranslationTable (pop_face_trans));
2722 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2723 FaceWidget, arg, 6);
2724 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2726 XtSetArg (arg[0], XtNfromHoriz, w);
2727 XtSetArg (arg[1], XtNleft, XawChainLeft);
2728 XtSetArg (arg[2], XtNright, XawChainRight);
2729 XtSetArg (arg[3], XtNlabel, "");
2730 XtSetArg (arg[4], XtNborderWidth, 0);
2731 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2732 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2733 FaceWidget, arg, 6);
2735 XtSetArg (arg[0], XtNborderWidth, 0);
2736 XtSetArg (arg[1], XtNleft, XawChainLeft);
2737 XtSetArg (arg[2], XtNright, XawChainLeft);
2738 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2740 MPlist *plist[11], *pl;
2743 for (i = 0; i < 11; i++) plist[i] = NULL;
2745 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2746 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2748 MSymbol sym = msymbol_exist (langname);
2752 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2754 char *name = msymbol_name (fullname);
2757 if (c >= 'A' && c <= 'Z')
2759 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2763 pl = plist[idx] = mplist ();
2764 for (; mplist_next (pl); pl = mplist_next (pl))
2765 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2767 mplist_push (pl, sym, fullname);
2772 for (i = 0; i < 11; i++)
2775 char *name = alloca (9);
2777 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2780 for (j = 0, pl = plist[i]; mplist_next (pl);
2781 j++, pl = mplist_next (pl))
2782 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2783 msymbol_name (mplist_key (pl)),
2784 LangProc, mplist_key (pl), -1);
2785 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2786 menus, j, "Push language property");
2788 for (i = 0; i < 11; i++)
2790 m17n_object_unref (plist[i]);
2792 XtSetArg (arg[0], XtNfromHoriz, w);
2793 XtSetArg (arg[1], XtNleft, XawChainLeft);
2794 XtSetArg (arg[2], XtNright, XawChainLeft);
2795 XtSetArg (arg[3], XtNhorizDistance, 10);
2796 XtSetArg (arg[4], XtNlabel, "Pop");
2797 XtSetArg (arg[5], XtNtranslations,
2798 XtParseTranslationTable (pop_lang_trans));
2799 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2800 LangWidget, arg, 6);
2801 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2803 XtSetArg (arg[0], XtNfromHoriz, w);
2804 XtSetArg (arg[1], XtNleft, XawChainLeft);
2805 XtSetArg (arg[2], XtNright, XawChainRight);
2806 XtSetArg (arg[3], XtNlabel, "");
2807 XtSetArg (arg[4], XtNborderWidth, 0);
2808 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2809 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2810 LangWidget, arg, 6);
2813 XtSetArg (arg[0], XtNheight, win_height);
2814 XtSetArg (arg[1], XtNwidth, 10);
2815 XtSetArg (arg[2], XtNleft, XawChainLeft);
2816 XtSetArg (arg[3], XtNright, XawChainLeft);
2817 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2819 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2820 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2822 XtSetArg (arg[0], XtNheight, win_height);
2823 XtSetArg (arg[1], XtNwidth, win_width);
2824 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2825 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2826 XtSetArg (arg[4], XtNleft, XawChainLeft);
2827 XtSetArg (arg[5], XtNright, XawChainRight);
2828 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2831 XtSetArg (arg[0], XtNborderWidth, 0);
2832 XtSetArg (arg[1], XtNleft, XawChainLeft);
2833 XtSetArg (arg[2], XtNright, XawChainRight);
2834 XtSetArg (arg[3], XtNresizable, True);
2835 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2836 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2837 TailWidget, arg, 5);
2839 memset (&control, 0, sizeof control);
2840 control.two_dimensional = 1;
2841 control.enable_bidi = 1;
2842 control.anti_alias = 1;
2843 control.min_line_ascent = font_ascent;
2844 control.min_line_descent = font_descent;
2845 control.max_line_width = win_width;
2846 control.with_cursor = 1;
2847 control.cursor_width = 2;
2848 control.partial_update = 1;
2849 control.ignore_formatting_char = 1;
2851 memset (&input_status_control, 0, sizeof input_status_control);
2852 input_status_control.enable_bidi = 1;
2854 XtAppAddActions (context, actions, XtNumber (actions));
2855 XtRealizeWidget (ShellWidget);
2857 win = XtWindow (TextWidget);
2859 XtAppMainLoop (context);
2861 if (current_input_context)
2862 minput_destroy_ic (current_input_context);
2863 for (i = 0; i < num_input_methods; i++)
2864 if (input_method_table[i].im)
2865 minput_close_im (input_method_table[i].im);
2866 m17n_object_unref (frame);
2867 m17n_object_unref (mt);
2868 m17n_object_unref (face_xxx_large);
2869 m17n_object_unref (face_box);
2870 m17n_object_unref (face_courier);
2871 m17n_object_unref (face_helvetica);
2872 m17n_object_unref (face_times);
2873 m17n_object_unref (face_dv_ttyogesh);
2874 m17n_object_unref (face_freesans);
2875 m17n_object_unref (face_freeserif);
2876 m17n_object_unref (face_freemono);
2877 m17n_object_unref (face_default_fontset);
2878 m17n_object_unref (face_no_ctl_fontset);
2879 m17n_object_unref (face_input_status);
2880 m17n_object_unref (face_default);
2881 m17n_object_unref (default_face_list);
2882 m17n_object_unref (selection);
2884 XFreeGC (display, mono_gc);
2885 XFreeGC (display, mono_gc_inv);
2886 XFreeGC (display, gc_inv);
2887 XtUninstallTranslations (form);
2888 XtUninstallTranslations (TextWidget);
2889 XtDestroyWidget (ShellWidget);
2890 XtDestroyApplicationContext (context);
2894 free (fontset_name);
2896 free (input_method_table);
2897 free (InputMethodMenus);
2901 #endif /* not FOR_DOXYGEN */