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.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;
429 int size = 0, ratio = 0, i;
432 n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
434 for (i = n - 1; i >= 0; i--)
437 size = (int) mface_get_prop (faces[i], Msize);
439 ratio = (int) mface_get_prop (faces[i], Mratio);
442 size = default_font_size;
444 size = size * ratio / 100;
445 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
446 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
451 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
454 redraw_cursor (int clear)
456 if (control.cursor_bidi)
458 /* We must update the whole line of the cursor. */
459 int beg = bol (cur.from, 0);
460 int end = bol (cur.to - 1, 1);
462 int y0 = cur.y0, y1 = cur.y1;
466 TEXT_EXTENTS (beg, cur.from, rect);
471 TEXT_EXTENTS (cur.to, end, rect);
474 redraw (y0, y1, clear, 0);
482 if (control.orientation_reversed)
483 x += win_width - cursor.logical_width;
484 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.this.height);
486 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
491 /* Update the information about the location of cursor to the position
492 $POS. If $FULL is nonzero, update the information fully only from
493 the information about the top line. Otherwise, truct the current
494 information in the structure $CUR. */
496 update_cursor (int pos, int full)
502 /* CUR is inaccurate. We can trust only TOP. */
503 GLYPH_INFO (top.from, pos, cursor);
504 cur.y0 = top.ascent + cursor.y + cursor.this.y;
506 else if (pos < cur.from)
508 int from = bol (pos, 0);
510 TEXT_EXTENTS (from, cur.from, rect);
511 GLYPH_INFO (from, pos, cursor);
512 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y);
514 else if (pos < cur.to)
516 GLYPH_INFO (cur.from, pos, cursor);
520 GLYPH_INFO (cur.from, pos, cursor);
521 cur.y0 += cur.ascent + cursor.y + cursor.this.y;
524 cur.from = cursor.line_from;
525 cur.to = cursor.line_to;
526 cur.y1 = cur.y0 + cursor.this.height;
527 cur.ascent = - cursor.this.y;
531 /* Update the information about the selected region. */
541 from = mtext_property_start (selection);
542 to = mtext_property_end (selection);
546 int pos = bol (from, 0);
548 TEXT_EXTENTS (pos, top.from, rect);
549 sel_start.y0 = top.y0 - rect.height;
550 sel_start.ascent = - rect.y;
551 GLYPH_INFO (pos, from, info);
552 if (pos < info.line_from)
553 sel_start.y0 += - rect.y + info.y + info.this.y;
557 GLYPH_INFO (top.from, from, info);
558 sel_start.y0 = top.ascent + info.y + info.this.y;
560 sel_start.ascent = -info.this.y;
561 sel_start.y1 = sel_start.y0 + info.this.height;
562 sel_start.from = info.line_from;
563 sel_start.to = info.line_to;
565 if (to <= sel_start.to)
568 if (to >= sel_end.to)
570 GLYPH_INFO (sel_start.from, to, info);
571 sel_end.y1 = sel_end.y0 + info.y + info.this.height;
572 sel_end.to = info.line_to;
577 GLYPH_INFO (sel_start.from, to, info);
578 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
579 sel_end.y1 = sel_end.y0 + info.this.height;
580 sel_end.ascent = - info.this.y;
581 sel_end.from = info.line_from;
582 sel_end.to = info.line_to;
587 /* Select the text in the region from $FROM to $TO. */
589 select_region (int from, int to)
594 pos = from, from = to, to = pos;
595 mtext_push_property (mt, from, to, selection);
600 /* Setup the window to display the character of $POS at the top left
606 /* Top and bottom Y positions to redraw. */
609 if (pos + 1000 < top.from)
610 y0 = 0, y1 = win_height;
611 else if (pos < top.from)
614 TEXT_EXTENTS (pos, top.from, rect);
615 if (rect.height >= win_height * 0.9)
620 COPY_AREA (0, win_height - y1, y1);
623 else if (pos < top.to)
625 /* No need of redrawing. */
628 else if (pos < top.from + 1000)
630 TEXT_EXTENTS (top.from, pos, rect);
631 if (rect.height >= win_height * 0.9)
635 y0 = win_height - rect.height;
636 COPY_AREA (rect.height, win_height, 0);
641 y0 = 0, y1 = win_height;
647 update_cursor (pos, 1);
649 update_cursor (cursor.from, 1);
651 redraw (y0, y1, 1, 1);
655 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
658 /* Select an input method accoding to $IDX. If $IDX is negative, turn
659 off the current input method, otherwide turn on the input method
660 input_method_table[$IDX]. */
662 select_input_method (idx)
664 if (idx == current_input_method)
666 if (current_input_context)
668 minput_destroy_ic (current_input_context);
669 current_input_context = NULL;
670 current_input_method = -1;
674 InputMethodInfo *im = input_method_table + idx;
676 if (im->language == Mnil)
678 MInputXIMArgIC arg_xic;
679 Window win = XtWindow (TextWidget);
681 arg_xic.input_style = 0;
682 arg_xic.client_win = arg_xic.focus_win = win;
683 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
684 current_input_context = minput_create_ic (im->im, &arg_xic);
688 MInputGUIArgIC arg_ic;
690 arg_ic.frame = frame;
691 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
692 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
693 current_input_context = minput_create_ic (im->im, &arg_ic);
696 if (current_input_context)
698 set_input_method_spot ();
699 current_input_method = idx;
702 if (current_input_method >= 0)
705 XtSetArg (arg[0], XtNlabel, &label);
706 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
707 XtSetArg (arg[0], XtNlabel, label);
710 XtSetArg (arg[0], XtNlabel, "");
711 XtSetValues (CurIMLang, arg, 1);
714 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
717 /* Display cursor according to the current information of #CUR.
718 $CLIENT_DATA is ignore. Most callback functions add this function
719 as a background processing procedure the current application (by
720 XtAppAddWorkProc) via the function hide_cursor. */
722 show_cursor (XtPointer client_data)
724 MFaceHLineProp *hline;
730 update_cursor (cursor.from, 1);
732 while (cur.y1 > win_height)
735 update_cursor (cursor.from, 1);
738 control.cursor_pos = cursor.from;
741 control.with_cursor = 1;
744 if (current_input_context)
745 set_input_method_spot ();
749 int pos = (SELECTEDP () ? mtext_property_start (selection)
750 : cursor.from > 0 ? cursor.from - 1
752 MFace *face = mface ();
753 MTextProperty *props[256];
754 int n = mtext_get_properties (mt, pos, Mface, props, 256);
756 char buf[256], *p = buf;
762 int size = (int) mfont_get_prop (cursor.font, Msize);
763 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
764 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
765 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
766 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
768 sprintf (p, "%dpt", size / 10), p += strlen (p);
770 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
772 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
774 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
776 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
780 mface_merge (face, face_default);
781 for (i = 0; i < n; i++)
782 if (props[i] != selection)
783 mface_merge (face, (MFace *) mtext_property_value (props[i]));
784 sym = (MSymbol) mface_get_prop (face, Mforeground);
786 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
787 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
788 strcat (p, ",rev"), p += strlen (p);
789 hline = mface_get_prop (face, Mhline);
790 if (hline && hline->width > 0)
791 strcat (p, ",ul"), p += strlen (p);
792 box = mface_get_prop (face, Mbox);
793 if (box && box->width > 0)
794 strcat (p, ",box"), p += strlen (p);
795 m17n_object_unref (face);
797 XtSetArg (arg[0], XtNborderWidth, 1);
798 XtSetArg (arg[1], XtNlabel, buf);
799 XtSetValues (CurFaceWidget, arg, 2);
802 if (control.cursor_pos < nchars)
806 if (control.cursor_pos > 0
807 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
808 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
810 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
814 XtSetArg (arg[0], XtNborderWidth, 0);
815 XtSetArg (arg[1], XtNlabel, "");
819 XtSetArg (arg[0], XtNborderWidth, 1);
820 XtSetArg (arg[1], XtNlabel,
821 msymbol_name (msymbol_get (sym, Mlanguage)));
822 XtSetValues (CurLangWidget, arg, 2);
824 XtSetValues (CurLangWidget, arg, 2);
826 if (auto_input_method)
829 select_input_method (-1);
834 for (i = 0; i < num_input_methods; i++)
835 if (input_method_table[i].language == sym)
837 if (i < num_input_methods
838 && input_method_table[i].available >= 0)
840 if (! input_method_table[i].im)
842 input_method_table[i].im =
843 minput_open_im (input_method_table[i].language,
844 input_method_table[i].name, NULL);
845 if (! input_method_table[i].im)
846 input_method_table[i].available = -1;
848 if (input_method_table[i].im)
849 select_input_method (i);
851 select_input_method (-1);
854 select_input_method (-1);
859 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
865 /* Hide the cursor. */
869 control.with_cursor = 0;
871 XtAppAddWorkProc (context, show_cursor, NULL);
875 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
876 $Y1 and $NEW_Y1 assuming that the text in the other area is not
879 update_region (int y0, int old_y1, int new_y1)
885 if (old_y1 < win_height)
887 COPY_AREA (old_y1, win_height, new_y1);
888 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
891 redraw (new_y1, win_height, 1, 0);
893 else if (new_y1 > old_y1)
895 if (new_y1 < win_height)
896 COPY_AREA (old_y1, win_height, new_y1);
898 if (new_y1 > win_height)
900 redraw (y0, new_y1, 1, 1);
904 /* Delete the next $N characters. If $N is negative delete the
905 precious (- $N) characters. */
915 from = cursor.from, to = from + n;
918 if (cursor.from == cur.from)
920 /* We are at the beginning of line. */
921 int pos = cursor.prev_from;
923 if (cursor.from == top.from)
925 /* We are at the beginning of screen. We must scroll
927 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
928 reseat (info.line_from);
930 update_cursor (pos, 1);
936 from = cursor.from - 1;
941 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
942 old_y1 = cur.y0 + rect.height;
944 /* Now delete a character. */
945 mtext_del (mt, from, to);
947 if (from >= top.from && from < top.to)
948 update_top (top.from);
949 update_cursor (from, 1);
951 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
952 new_y1 = cur.y0 + rect.height;
954 update_region (cur.y0, old_y1, new_y1);
958 /* Insert M-text $NEWTEXT at the current cursor position. */
960 insert_chars (MText *newtext)
962 int n = mtext_len (newtext);
964 int y0, old_y1, new_y1;
968 int n = (mtext_property_end (selection)
969 - mtext_property_start (selection));
970 mtext_detach_property (selection);
975 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
976 old_y1 = y0 + rect.height;
978 /* Now insert chars. */
979 mtext_ins (mt, cursor.from, newtext);
981 if (cur.from == top.from)
982 update_top (top.from);
983 update_cursor (cursor.from + n, 1);
985 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
986 new_y1 = cur.y0 + rect.height;
988 update_region (y0, old_y1, new_y1);
993 /* Convert the currently selected text to UTF8-STRING or
994 COMPOUND-TEXT. It is called when someone requests the current
995 value of the selection. */
997 covert_selection (Widget w, Atom *selection_atom,
998 Atom *target, Atom *return_type,
999 XtPointer *value, unsigned long *length, int *format)
1001 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1002 MText *this_mt = mtext ();
1003 int from = mtext_property_start (selection);
1004 int to = mtext_property_end (selection);
1008 mtext_copy (this_mt, 0, mt, from, to);
1009 if (*target == XA_TEXT)
1011 #ifdef X_HAVE_UTF8_STRING
1012 coding = Mcoding_utf_8;
1013 *return_type = XA_UTF8_STRING;
1015 coding = Mcoding_compound_text;
1016 *return_type = XA_COMPOUND_TEXT;
1019 else if (*target == XA_UTF8_STRING)
1021 coding = Mcoding_utf_8;
1022 *return_type = XA_UTF8_STRING;
1024 else if (*target == XA_STRING)
1029 for (i = 0; i < len; i++)
1030 if (mtext_ref_char (this_mt, i) >= 0x100)
1031 /* Can't encode in XA_STRING */
1033 coding = Mcoding_iso_8859_1;
1034 *return_type = XA_STRING;
1036 else if (*target == XA_COMPOUND_TEXT)
1038 coding = Mcoding_compound_text;
1039 *return_type = XA_COMPOUND_TEXT;
1044 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1045 m17n_object_unref (this_mt);
1049 *value = (XtPointer) buf;
1055 /* Unselect the text. It is called when we loose the selection. */
1057 lose_selection (Widget w, Atom *selection_atom)
1061 mtext_detach_property (selection);
1062 redraw (sel_start.y0, sel_end.y1, 1, 0);
1067 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1068 XtPointer value, unsigned long *length, int *format)
1073 if (*type == XT_CONVERT_FAIL || ! value)
1075 if (*type == XA_STRING)
1077 else if (*type == XA_COMPOUND_TEXT)
1078 coding = msymbol ("compound-text");
1079 #ifdef X_HAVE_UTF8_STRING
1080 else if (*type == XA_UTF8_STRING)
1081 coding = msymbol ("utf-8");
1086 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1087 if (! this_mt && *type != XA_UTF8_STRING)
1089 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1096 insert_chars (this_mt);
1097 m17n_object_unref (this_mt);
1106 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1108 XExposeEvent *expose = (XExposeEvent *) event;
1112 Dimension width_max, width;
1114 XtSetArg (arg[0], XtNwidth, &width);
1115 XtGetValues (XtParent (w), arg, 1);
1117 XtGetValues (HeadWidget, arg, 1);
1118 if (width_max < width)
1120 XtGetValues (FaceWidget, arg, 1);
1121 if (width_max < width)
1123 XtGetValues (LangWidget, arg, 1);
1124 if (width_max < width)
1126 XtSetArg (arg[0], XtNwidth, width_max);
1127 XtSetValues (HeadWidget, arg, 1);
1128 XtSetValues (FaceWidget, arg, 1);
1129 XtSetValues (LangWidget, arg, 1);
1130 XtSetValues (XtParent (w), arg, 1);
1131 XtSetValues (TailWidget, arg, 1);
1134 update_cursor (0, 1);
1135 redraw (0, win_height, 0, 1);
1137 int idx = current_input_method;
1139 current_input_method = -1;
1140 input_method_table[idx].im =
1141 minput_open_im (input_method_table[idx].language,
1142 input_method_table[idx].name, NULL);
1143 if (input_method_table[idx].im)
1144 select_input_method (idx);
1146 input_method_table[idx].available = -1;
1152 redraw (expose->y, expose->y + expose->height, 0, 0);
1153 if (current_input_context
1154 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1155 set_input_method_spot ();
1160 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1162 XConfigureEvent *configure = (XConfigureEvent *) event;
1165 control.max_line_width = win_width = configure->width;
1166 win_height = configure->height;
1167 mdraw_clear_cache (mt);
1169 update_cursor (0, 1);
1170 redraw (0, win_height, 1, 1);
1171 if (current_input_context)
1172 set_input_method_spot ();
1176 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1179 int x = event->xbutton.x;
1180 int y = event->xbutton.y - top.ascent;
1182 if (control.orientation_reversed)
1184 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1187 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1188 mtext_detach_property (selection);
1189 redraw (sel_start.y0, sel_end.y1, 1, 0);
1192 update_cursor (pos, 0);
1197 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1202 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1203 covert_selection, lose_selection, NULL);
1204 update_cursor (mtext_property_start (selection), 0);
1209 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1213 /* We don't have a local selection. */
1214 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1219 int from = mtext_property_start (selection);
1220 int to = mtext_property_end (selection);
1223 int x = event->xbutton.x;
1224 int y = event->xbutton.y - top.ascent;
1226 if (control.orientation_reversed)
1228 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1230 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1231 mtext_detach_property (selection);
1233 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1234 update_cursor (pos, 0);
1235 insert_chars (this_mt);
1236 m17n_object_unref (this_mt);
1241 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1244 int x = event->xbutton.x;
1245 int y = event->xbutton.y;
1247 if (control.orientation_reversed)
1250 pos = top.from, y -= top.ascent;
1252 pos = cur.from, y -= cur.y0 + cur.ascent;
1253 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1255 if (pos == cursor.from)
1261 /* Selection range changed. */
1262 int from = mtext_property_start (selection);
1263 int to = mtext_property_end (selection);
1264 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1265 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1267 if (cursor.from == from)
1269 /* Starting position changed. */
1272 /* Enlarged. We can simply overdraw. */
1273 select_region (pos, to);
1274 redraw (sel_start.y0, start_y1, 0, 0);
1278 /* Shrunken. Previous selection face must be cleared. */
1279 select_region (pos, to);
1280 redraw (start_y0, sel_start.y1, 1, 0);
1284 /* Shrunken to zero. */
1285 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1286 mtext_detach_property (selection);
1287 redraw (start_y0, end_y1, 1, 0);
1291 /* Full update is necessary. */
1292 select_region (to, pos);
1293 redraw (start_y0, sel_end.y1, 1, 0);
1298 /* Ending position changed. */
1301 /* Full update is necessary. */
1302 select_region (pos, from);
1303 redraw (sel_start.y0, end_y1, 1, 0);
1305 else if (pos == from)
1307 /* Shrunken to zero. */
1308 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1309 mtext_detach_property (selection);
1310 redraw (start_y0, end_y1, 1, 0);
1314 /* Shrunken. Previous selection face must be cleared. */
1315 select_region (from, pos);
1316 redraw (sel_end.y0, end_y1, 1, 0);
1320 /* Enlarged. We can simply overdraw. */
1321 select_region (from, pos);
1322 redraw (end_y0, sel_end.y1, 0, 0);
1328 /* Newly selected. */
1329 select_region (pos, cursor.from);
1330 redraw (sel_start.y0, sel_end.y1, 0, 0);
1332 update_cursor (pos, 1);
1336 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1339 MDrawGlyphInfo info;
1341 int cursor_pos = cursor.from;
1343 if (((int) position) < 0)
1349 height = top.y1 - top.y0;
1352 pos = bol (from - 1, 0);
1353 GLYPH_INFO (pos, from - 1, info);
1354 if (height + info.this.height > win_height)
1356 height += info.this.height;
1357 from = info.line_from;
1359 if (cursor_pos >= top.to)
1361 cursor_pos = top.from;
1363 while (cursor_pos < nchars)
1365 GLYPH_INFO (pos, pos, info);
1366 if (height + info.this.height > win_height)
1368 height += info.this.height;
1374 else if (cur.to < nchars)
1376 /* Scroll up, but leave at least one line. */
1379 while (from < nchars)
1381 GLYPH_INFO (from, from, info);
1382 if (height + info.this.height > win_height
1383 || info.line_to >= nchars)
1385 height += info.this.height;
1386 from = info.line_to;
1389 from = info.line_from;
1390 if (cursor_pos < from)
1394 /* Scroll up to make the cursor line top. */
1398 update_cursor (cursor_pos, 1);
1402 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1404 float persent = *(float *) persent_ptr;
1405 int pos1, pos2 = nchars * persent;
1406 MDrawGlyphInfo info;
1409 pos1 = bol (pos2, 0);
1410 GLYPH_INFO (pos1, pos2, info);
1411 pos1 = info.line_from;
1413 update_cursor (pos1, 1);
1418 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1420 XKeyEvent *key_event = (XKeyEvent *) event;
1422 KeySym keysym = NoSymbol;
1424 /* If set to 1, do not update target_x_position. */
1425 int keep_target_x_position = 0;
1428 if (current_input_context
1429 && minput_filter (current_input_context, Mnil, event))
1431 if (event->type == KeyRelease)
1436 produced = mtext ();
1437 ret = minput_lookup (current_input_context, Mnil, event, produced);
1438 if (mtext_len (produced) > 0)
1439 insert_chars (produced);
1441 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1442 m17n_object_unref (produced);
1452 n = (mtext_property_end (selection)
1453 - mtext_property_start (selection));
1454 mtext_detach_property (selection);
1456 else if (cursor.from < nchars)
1458 /* Delete the following grapheme cluster. */
1459 n = cursor.to - cursor.from;
1472 /* Delete selected region. */
1473 n = (mtext_property_end (selection)
1474 - mtext_property_start (selection));
1475 mtext_detach_property (selection);
1477 else if (cursor.from > 0)
1479 /* Delete the preceding character. */
1490 mtext_detach_property (selection);
1491 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1495 if (cursor.prev_from >= 0)
1496 update_cursor (cursor.prev_from, 0);
1500 if (cursor.left_from >= 0)
1501 update_cursor (cursor.left_from, 0);
1508 mtext_detach_property (selection);
1509 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1513 if (cursor.next_to >= 0)
1514 update_cursor (cursor.to, 0);
1518 if (cursor.right_from >= 0)
1519 update_cursor (cursor.right_from, 0);
1526 mtext_detach_property (selection);
1527 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1529 if (cur.to <= nchars)
1531 MDrawGlyphInfo info;
1534 GLYPH_INFO (cur.from, cur.to, info);
1535 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1536 target_x_position, info.y);
1537 keep_target_x_position = 1;
1538 update_cursor (pos, 0);
1545 mtext_detach_property (selection);
1546 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1552 int pos = bol (cur.from - 1, 0);
1554 TEXT_EXTENTS (pos, cur.from - 1, rect);
1555 y = rect.height + rect.y - 1;
1556 pos = COORDINATES_POSITION (pos, nchars,
1557 target_x_position, y);
1558 keep_target_x_position = 1;
1559 update_cursor (pos, 0);
1566 mtext_detach_property (selection);
1567 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1569 if (top.from < nchars)
1570 ScrollProc (w, NULL, (XtPointer) 1);
1576 mtext_detach_property (selection);
1577 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1580 ScrollProc (w, NULL, (XtPointer) -1);
1586 if (buf[0] == 17) /* C-q */
1588 XtAppSetExitFlag (context);
1591 else if (buf[0] == 12) /* C-l */
1593 redraw (0, win_height, 1, 1);
1598 MText *temp = mtext ();
1600 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1601 if (current_input_context)
1602 mtext_put_prop (temp, 0, 1, Mlanguage,
1603 current_input_context->im->language);
1604 insert_chars (temp);
1605 m17n_object_unref (temp);
1610 if (! keep_target_x_position)
1611 target_x_position = cursor.x;
1615 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1617 char *name = (char *) client_data;
1619 int from = -1, to = 0;
1624 filename = strdup (name);
1627 fp = fopen (filename, "w");
1630 fprintf (stderr, "Open for write fail: %s", filename);
1636 from = mtext_property_start (selection);
1637 to = mtext_property_end (selection);
1638 mtext_detach_property (selection);
1641 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1644 select_region (from, to);
1648 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1654 mtext_detach_property (selection);
1655 serialized = (int) client_data;
1657 new = mtext_deserialize (mt);
1660 MPlist *plist = mplist ();
1662 mplist_push (plist, Mt, Mface);
1663 mplist_push (plist, Mt, Mlanguage);
1664 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1665 m17n_object_unref (plist);
1669 m17n_object_unref (mt);
1671 serialized = ! serialized;
1672 nchars = mtext_len (mt);
1675 update_cursor (0, 1);
1676 redraw (0, win_height, 1, 1);
1680 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1682 XtAppSetExitFlag (context);
1688 FILE *fp = fopen (filename, "r");
1691 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1692 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1695 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1700 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1702 int data = (int) client_data;
1707 control.enable_bidi = 0;
1708 control.orientation_reversed = 0;
1712 control.enable_bidi = 1;
1713 control.orientation_reversed = data == 2;
1715 for (i = 0; i < 3; i++)
1718 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1720 XtSetArg (arg[0], XtNleftBitmap, None);
1721 XtSetValues (BidiMenus[i], arg, 1);
1724 update_cursor (cursor.from, 1);
1725 redraw (0, win_height, 1, 0);
1728 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1731 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1733 int data = (int) client_data;
1737 control.max_line_width = 0;
1740 control.max_line_width = win_width;
1741 control.line_break = (data == 1 ? NULL : line_break);
1743 for (i = 0; i < 3; i++)
1746 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1748 XtSetArg (arg[0], XtNleftBitmap, None);
1749 XtSetValues (LineBreakMenus[i], arg, 1);
1752 update_cursor (cursor.from, 1);
1753 redraw (0, win_height, 1, 0);
1757 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1759 int data = (int) client_data;
1773 control.cursor_bidi = 0, control.cursor_width = -1;
1777 control.cursor_bidi = 0, control.cursor_width = 2;
1781 control.cursor_bidi = 1;
1786 for (i = from; i < to; i++)
1789 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1791 XtSetArg (arg[0], XtNleftBitmap, None);
1792 XtSetValues (CursorMenus[i], arg, 1);
1795 update_cursor (cursor.from, 0);
1796 redraw (0, win_height, 1, 0);
1800 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1802 int idx = (int) client_data;
1804 if (idx == -2 ? current_input_method < 0
1805 : idx == -1 ? auto_input_method
1806 : idx == current_input_method)
1809 XtSetArg (arg[0], XtNleftBitmap, None);
1810 if (auto_input_method)
1812 XtSetValues (InputMethodMenus[1], arg, 1);
1813 auto_input_method = 0;
1815 else if (current_input_method < 0)
1816 XtSetValues (InputMethodMenus[0], arg, 1);
1818 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1822 auto_input_method = 1;
1825 else if (input_method_table[idx].available >= 0)
1827 if (! input_method_table[idx].im)
1829 input_method_table[idx].im =
1830 minput_open_im (input_method_table[idx].language,
1831 input_method_table[idx].name, NULL);
1832 if (! input_method_table[idx].im)
1833 input_method_table[idx].available = -1;
1835 if (input_method_table[idx].im)
1836 select_input_method (idx);
1838 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1839 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1842 MPlist *default_face_list;
1845 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1847 int idx = (int) client_data;
1857 MFace *face = mframe_get_prop (frame, Mface);
1859 for (plist = default_face_list; mplist_key (plist) != Mnil;
1860 plist = mplist_next (plist))
1861 mface_merge (face, mplist_value (plist));
1862 mplist_add (plist, Mt, *face_table[idx].face);
1863 mface_merge (face, *face_table[idx].face);
1865 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1867 MFace *face = mframe_get_prop (frame, Mface);
1869 for (plist = default_face_list;
1870 mplist_key (mplist_next (plist)) != Mnil;
1871 plist = mplist_next (plist))
1872 mface_merge (face, mplist_value (plist));
1876 update_cursor (0, 1);
1877 redraw (0, win_height, 1, 1);
1882 XtAppAddWorkProc (context, show_cursor, NULL);
1883 from = mtext_property_start (selection);
1884 to = mtext_property_end (selection);
1885 old_y1 = sel_end.y1;
1887 mtext_detach_property (selection);
1890 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1891 MTEXTPROP_REAR_STICKY);
1892 mtext_push_property (mt, from, to, prop);
1893 m17n_object_unref (prop);
1896 mtext_pop_prop (mt, from, to, Mface);
1898 update_top (top.from);
1899 update_cursor (cursor.from, 1);
1900 select_region (from, to);
1901 update_region (sel_start.y0, old_y1, sel_end.y1);
1902 if (cur.y1 > win_height)
1904 while (cur.y1 > win_height)
1907 update_cursor (cursor.from, 1);
1913 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1915 MSymbol sym = (MSymbol) client_data;
1922 XtAppAddWorkProc (context, show_cursor, NULL);
1923 from = mtext_property_start (selection);
1924 to = mtext_property_end (selection);
1925 old_y1 = sel_end.y1;
1927 mtext_detach_property (selection);
1929 mtext_put_prop (mt, from, to, Mlanguage, sym);
1931 mtext_pop_prop (mt, from, to, Mlanguage);
1934 update_top (top.from);
1935 update_cursor (cursor.from, 1);
1936 select_region (from, to);
1937 update_region (sel_start.y0, old_y1, sel_end.y1);
1938 if (cur.y1 > win_height)
1940 while (cur.y1 > win_height)
1943 update_cursor (cursor.from, 1);
1949 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1951 int narrowed = (int) client_data;
1954 MConverter *converter;
1960 from = mtext_property_start (selection);
1961 to = mtext_property_end (selection);
1970 mdump = popen ("mdump -q -p a4", "w");
1972 mdump = popen ("mdump -q", "w");
1975 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1976 mconv_encode_range (converter, mt, from, to);
1977 mconv_free_converter (converter);
1982 input_status (MInputContext *ic, MSymbol command)
1984 XFillRectangle (display, input_status_pixmap, gc_inv,
1985 0, 0, input_status_width, input_status_height);
1986 if (command == Minput_status_draw)
1990 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1991 Mface, face_input_status);
1992 if (ic->im->language != Mnil)
1993 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1994 Mlanguage, ic->im->language);
1995 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1996 &input_status_control, NULL, NULL, &rect);
1997 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1998 input_status_width - rect.width - 2, - rect.y,
1999 ic->status, 0, mtext_len (ic->status),
2000 &input_status_control);
2002 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2003 XtSetValues (CurIMStatus, arg, 1);
2007 compare_input_method (const void *elt1, const void *elt2)
2009 const InputMethodInfo *im1 = elt1;
2010 const InputMethodInfo *im2 = elt2;
2011 MSymbol lang1, lang2;
2013 if (im1->language == Mnil)
2015 if (im1->language == im2->language)
2016 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2017 if (im1->language == Mt)
2019 if (im2->language == Mt)
2021 lang1 = msymbol_get (im1->language, Mlanguage);
2022 lang2 = msymbol_get (im2->language, Mlanguage);
2023 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2027 setup_input_methods (int with_xim, char *initial_input_method)
2029 MInputMethod *im = NULL;
2030 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2033 char *lang_name = NULL, *method_name = NULL;
2035 if (initial_input_method)
2037 char *p = strchr (initial_input_method, '-');
2039 lang_name = initial_input_method, method_name = p + 1, *p = '\0';
2041 method_name = initial_input_method;
2044 num_input_methods = mplist_length (plist);
2048 MInputXIMArgIM arg_xim;
2050 arg_xim.display = display;
2052 arg_xim.res_name = arg_xim.res_class = NULL;
2053 arg_xim.locale = NULL;
2054 arg_xim.modifier_list = NULL;
2055 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2057 num_input_methods++;
2059 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2062 input_method_table[i].available = 1;
2063 input_method_table[i].language = Mnil;
2064 input_method_table[i].name = im->name;
2065 input_method_table[i].im = im;
2069 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2071 MDatabase *mdb = mplist_value (pl);
2072 MSymbol *tag = mdatabase_tag (mdb);
2076 input_method_table[i].language = tag[1];
2077 input_method_table[i].name = tag[2];
2082 m17n_object_unref (plist);
2083 num_input_methods = i;
2084 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2085 compare_input_method);
2086 current_input_context = NULL;
2088 mplist_put (minput_driver->callback_list, Minput_status_start,
2089 (void *) input_status);
2090 mplist_put (minput_driver->callback_list, Minput_status_draw,
2091 (void *) input_status);
2092 mplist_put (minput_driver->callback_list, Minput_status_done,
2093 (void *) input_status);
2096 for (i = 0; i < num_input_methods; i++)
2097 if (strcmp (method_name, msymbol_name (input_method_table[i].name)) == 0
2099 ? strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0
2100 : input_method_table[i].language == Mt))
2102 current_input_method = i;
2109 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2113 if (num && *num > 0)
2117 for (i = 0; i < *num; i++)
2118 bytes += strlen (str[i]) + 1;
2119 msg = alloca (bytes);
2120 strcpy (msg, str[0]);
2121 for (i = 1; i < *num; i++)
2122 strcat (msg, " "), strcat (msg, str[i]);
2124 else if (cursor.from < nchars)
2126 int c = mtext_ref_char (mt, cursor.from);
2127 char *name = mchar_get_prop (c, Mname);
2131 msg = alloca (10 + strlen (name));
2132 sprintf (msg, "U+%04X %s", c, name);
2138 XtSetArg (arg[0], XtNlabel, msg);
2139 XtSetValues (MessageWidget, arg, 1);
2145 char *name1, *name2;
2146 XtCallbackProc proc;
2147 XtPointer client_data;
2152 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2154 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2156 MenuRec FileMenu[] =
2157 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2158 { 0, "Save", NULL, SaveProc, NULL, -1 },
2159 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2161 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2162 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2164 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2165 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2167 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2170 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2172 MenuRec *rec = (MenuRec *) client_data;
2175 XtSetArg (arg[0], XtNvalue, "");
2176 XtSetArg (arg[1], XtNlabel, rec->name1);
2177 XtSetValues (FileDialogWidget, arg, 2);
2178 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2179 XtSetArg (arg[0], XtNx, x + 20);
2180 XtSetArg (arg[1], XtNy, y + 10);
2181 XtSetValues (FileShellWidget, arg, 2);
2182 XtPopup (FileShellWidget, XtGrabExclusive);
2186 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2191 XtPopdown (FileShellWidget);
2192 if ((int) client_data == 1)
2194 XtSetArg (arg[0], XtNlabel, &label);
2195 XtGetValues (FileDialogWidget, arg, 1);
2196 if (strcmp (label, FileMenu[0].name1) == 0)
2200 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2201 fp = fopen (filename, "r");
2203 m17n_object_unref (mt);
2206 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2214 nchars = mtext_len (mt);
2216 update_cursor (0, 1);
2217 redraw (0, win_height, 1, 1);
2219 else if (strcmp (label, FileMenu[2].name1) == 0)
2220 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2222 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2225 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2226 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2227 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2228 (MENU).status = (STATUS))
2232 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2233 char *menu_name, MenuRec *menus, int num_menus, char *help)
2235 Widget button, menu;
2236 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2237 <LeaveWindow>: reset() MenuHelp()\n\
2238 <BtnDown>: reset() PopupMenu()\n\
2239 <BtnUp>: highlight()";
2245 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2246 for (i = 0; i < num_menus; i++)
2257 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2259 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2261 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2263 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2267 XtSetArg (arg[0], XtNsensitive, False);
2268 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2274 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2279 trans = alloca (strlen (fmt) + strlen (help));
2280 sprintf (trans, fmt, help);
2281 XtSetArg (arg[0], XtNmenuName, menu_name);
2282 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2283 XtSetArg (arg[2], XtNinternalWidth, 2);
2284 XtSetArg (arg[3], XtNhighlightThickness, 1);
2285 XtSetArg (arg[4], XtNleft, XawChainLeft);
2286 XtSetArg (arg[5], XtNright, XawChainLeft);
2289 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2290 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2295 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2296 int *len = alloca (sizeof (int) * num_menus);
2299 XFontSetExtents *fontset_extents;
2301 XtSetArg (arg[0], XtNfontSet, &font_set);
2302 XtGetValues (button, arg, 1);
2304 fontset_extents = XExtentsOfFontSet (font_set);
2305 height = fontset_extents->max_logical_extent.height;
2306 ascent = - fontset_extents->max_logical_extent.y;
2308 for (i = 0; i < num_menus; i++)
2311 len[i] = strlen (menus[i].name2);
2312 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2313 if (max_width < width[i])
2314 max_width = width[i];
2316 for (i = 0; i < num_menus; i++)
2319 Pixmap pixmap = XCreatePixmap (display,
2320 RootWindow (display, screen),
2321 max_width, height, 1);
2322 XFillRectangle (display, pixmap, mono_gc_inv,
2323 0, 0, max_width, height);
2324 XmbDrawString (display, pixmap, font_set, mono_gc,
2325 max_width - width[i], ascent,
2326 menus[i].name2, len[i]);
2327 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2328 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2329 XtSetValues (menus[i].w, arg, 2);
2337 XtActionsRec actions[] = {
2338 {"Expose", ExposeProc},
2339 {"Configure", ConfigureProc},
2341 {"ButtonPress", ButtonProc},
2342 {"ButtonRelease", ButtonReleaseProc},
2343 {"ButtonMotion", ButtonMoveProc},
2344 {"Button2Press", Button2Proc},
2345 {"MenuHelp", MenuHelpProc}
2349 /* Print the usage of this program (the name is PROG), and exit with
2353 help_exit (char *prog, int exit_code)
2361 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2362 printf ("Display FILE on a window and allow users to edit it.\n");
2363 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2364 printf ("The following OPTIONs are available.\n");
2365 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2366 "Use the specified fontset\n");
2367 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2368 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2369 "Input method activated initially.\n");
2370 printf (" %-13s %s", "--version", "print version number\n");
2371 printf (" %-13s %s", "-h, --help", "print this message\n");
2377 main (int argc, char **argv)
2379 Widget form, BodyWidget, w;
2380 char *fontset_name = NULL;
2382 char *initial_input_method = NULL;
2383 int col = 80, row = 32;
2384 /* Translation table for TextWidget. */
2385 String trans = "<Expose>: Expose()\n\
2386 <Configure>: Configure()\n\
2389 <Btn1Down>: ButtonPress()\n\
2390 <Btn1Up>: ButtonRelease()\n\
2391 <Btn1Motion>: ButtonMotion()\n\
2392 <Btn2Down>: Button2Press()";
2393 /* Translation table for the top form widget. */
2394 String trans2 = "<Key>: Key()\n\
2396 String pop_face_trans
2397 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2398 <LeaveWindow>: MenuHelp() reset()\n\
2399 <Btn1Down>: set()\n\
2400 <Btn1Up>: notify() unset()";
2401 String pop_lang_trans
2402 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2403 <LeaveWindow>: MenuHelp() reset()\n\
2404 <Btn1Down>: set()\n\
2405 <Btn1Up>: notify() unset()";
2406 int font_width, font_ascent, font_descent;
2410 setlocale (LC_ALL, "");
2411 /* Create the top shell. */
2412 XtSetLanguageProc (NULL, NULL, NULL);
2413 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2414 NULL, sessionShellWidgetClass, NULL, 0);
2415 display = XtDisplay (ShellWidget);
2416 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2418 /* Parse the remaining command line arguments. */
2419 for (i = 1; i < argc; i++)
2421 if (! strcmp (argv[i], "--help")
2422 || ! strcmp (argv[i], "-h"))
2423 help_exit (argv[0], 0);
2424 else if (! strcmp (argv[i], "--version"))
2426 printf ("medit (m17n library) %s\n", VERSION);
2427 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2430 else if (! strcmp (argv[i], "--geometry"))
2433 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2434 help_exit (argv[0], 1);
2436 else if (! strcmp (argv[i], "-s"))
2439 fontsize = atoi (argv[i]);
2443 else if (! strcmp (argv[i], "--fontset"))
2446 fontset_name = strdup (argv[i]);
2448 else if (! strcmp (argv[i], "--im"))
2451 initial_input_method = strdup (argv[i]);
2453 else if (! strcmp (argv[i], "--with-xim"))
2457 else if (argv[i][0] != '-')
2459 filename = strdup (argv[i]);
2463 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2464 help_exit (argv[0], 1);
2468 help_exit (argv[0], 1);
2470 mdatabase_dir = ".";
2471 /* Initialize the m17n library. */
2473 if (merror_code != MERROR_NONE)
2474 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2476 mt = read_file (filename);
2479 nchars = mtext_len (mt);
2482 MFace *face = mface ();
2484 mface_put_prop (face, Mforeground, msymbol ("blue"));
2485 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2486 mface_put_prop (face, Mvideomode, Mreverse);
2487 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2488 m17n_object_unref (face);
2491 /* This tells ExposeProc to initialize everything. */
2494 XA_TEXT = XInternAtom (display, "TEXT", False);
2495 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2496 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2497 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2498 if (Mcoding_compound_text == Mnil)
2499 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2502 MPlist *plist = mplist ();
2506 mplist_put (plist, msymbol ("widget"), ShellWidget);
2507 if (fontset_name || fontsize != 120)
2509 MFontset *fontset = mfontset (fontset_name);
2512 mface_put_prop (face, Mfontset, fontset);
2513 mface_put_prop (face, Msize, (void *) fontsize);
2514 m17n_object_unref (fontset);
2515 mplist_add (plist, Mface, face);
2516 m17n_object_unref (face);
2518 frame = mframe (plist);
2520 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2521 m17n_object_unref (plist);
2522 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2523 default_face_list = mplist ();
2524 mplist_add (default_face_list, Mt, face_default);
2525 face_default_fontset = mface ();
2526 mface_put_prop (face_default_fontset, Mfontset,
2527 mface_get_prop (face_default, Mfontset));
2529 font = (MFont *) mframe_get_prop (frame, Mfont);
2530 default_font_size = (int) mfont_get_prop (font, Msize);
2533 font_width = (int) mframe_get_prop (frame, Mfont_width);
2534 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2535 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2536 win_width = font_width * col;
2537 win_height = (font_ascent + font_descent) * row;
2543 prop.color_top = prop.color_left = msymbol ("magenta");
2544 prop.color_bottom = prop.color_right = msymbol ("red");
2545 prop.inner_hmargin = prop.inner_vmargin = 1;
2546 prop.outer_hmargin = prop.outer_vmargin = 2;
2548 face_box = mface ();
2549 mface_put_prop (face_box, Mbox, &prop);
2552 face_courier = mface ();
2553 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2554 face_helvetica = mface ();
2555 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2556 face_times = mface ();
2557 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2558 face_dv_ttyogesh = mface ();
2559 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2560 face_freesans = mface ();
2561 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2562 face_freeserif = mface ();
2563 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2564 face_freemono = mface ();
2565 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2567 face_xxx_large = mface ();
2568 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2570 MFont *latin_font = mframe_get_prop (frame, Mfont);
2571 MFont *dev_font = mfont ();
2572 MFont *thai_font = mfont ();
2573 MFont *tib_font = mfont ();
2575 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2576 MSymbol no_ctl = msymbol ("no-ctl");
2578 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2579 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2580 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2581 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2582 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2583 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2585 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2586 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2587 latin_font, Mnil, 0);
2588 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2589 dev_font, no_ctl, 0);
2590 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2591 thai_font, no_ctl, 0);
2592 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2593 tib_font, no_ctl, 0);
2594 face_no_ctl_fontset = mface ();
2595 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2596 m17n_object_unref (fontset);
2603 setup_input_methods (with_xim, initial_input_method);
2605 gc = DefaultGC (display, screen);
2607 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2608 XtSetArg (arg[1], XtNdefaultDistance, 2);
2609 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2611 XtSetArg (arg[0], XtNborderWidth, 0);
2612 XtSetArg (arg[1], XtNdefaultDistance, 2);
2613 XtSetArg (arg[2], XtNtop, XawChainTop);
2614 XtSetArg (arg[3], XtNbottom, XawChainTop);
2615 XtSetArg (arg[4], XtNleft, XawChainLeft);
2616 XtSetArg (arg[5], XtNright, XawChainRight);
2617 XtSetArg (arg[6], XtNresizable, True);
2618 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2619 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2620 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2621 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2622 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2623 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2624 XtSetArg (arg[7], XtNfromVert, LangWidget);
2625 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2626 XtSetArg (arg[2], XtNtop, XawChainBottom);
2627 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2628 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2630 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2631 HeadWidget, NULL, 0);
2632 XtSetArg (arg[0], XtNvalue, "");
2633 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2634 FileShellWidget, arg, 1);
2635 XawDialogAddButton (FileDialogWidget, "OK",
2636 FileDialogProc, (XtPointer) 0);
2637 XawDialogAddButton (FileDialogWidget, "CANCEL",
2638 FileDialogProc, (XtPointer) 1);
2640 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2641 (char *) check_bits,
2642 check_width, check_height);
2644 unsigned long valuemask = GCForeground;
2647 values.foreground = 1;
2648 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2649 values.foreground = 0;
2650 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2657 if (num_menus < num_input_methods + 2)
2658 num_menus = num_input_methods + 2;
2659 if (num_menus < num_faces + 1)
2660 num_menus = num_faces + 1;
2661 menus = alloca (sizeof (MenuRec) * num_menus);
2663 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2664 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2665 "File I/O, Serialization, Image, Quit");
2667 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2668 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2669 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2670 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2671 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2672 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2673 w = create_menu_button (ShellWidget, HeadWidget, w,
2674 "Cursor", "Cursor Menu",
2675 menus, 6, "Cursor Movement Mode, Cursor Shape");
2676 CursorMenus[0] = menus[0].w;
2677 CursorMenus[1] = menus[1].w;
2678 CursorMenus[2] = menus[3].w;
2679 CursorMenus[3] = menus[4].w;
2680 CursorMenus[4] = menus[5].w;
2682 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2683 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2684 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2685 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2686 menus, 3, "BIDI Processing Mode");
2687 for (i = 0; i < 3; i++)
2688 BidiMenus[i] = menus[i].w;
2690 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2691 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2692 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2693 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2695 menus, 3, "How to break lines");
2696 for (i = 0; i < 3; i++)
2697 LineBreakMenus[i] = menus[i].w;
2699 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2700 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2701 for (i = 0; i < num_input_methods; i++)
2703 InputMethodInfo *im = input_method_table + i;
2704 char *name1, *name2;
2706 if (im->language != Mnil && im->language != Mt)
2708 MSymbol sym = msymbol_get (im->language, Mlanguage);
2710 name1 = msymbol_name (im->language);
2712 name1 = msymbol_name (sym);
2713 name2 = msymbol_name (im->name);
2716 name1 = msymbol_name (im->name), name2 = NULL;
2718 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2720 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2721 "Input Method Menu", menus, i + 2,
2722 "Select input method");
2725 unsigned long valuemask = GCForeground;
2728 XtSetArg (arg[0], XtNbackground, &values.foreground);
2729 XtGetValues (w, arg, 1);
2730 gc_inv = XCreateGC (display, RootWindow (display, screen),
2731 valuemask, &values);
2734 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2735 for (i = 0; i < num_input_methods + 2; i++)
2736 InputMethodMenus[i] = menus[i].w;
2738 input_status_width = font_width * 8;
2739 input_status_height = (font_ascent + font_descent) * 2.4;
2740 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2742 input_status_height,
2743 DefaultDepth (display, screen));
2748 prop.color_top = prop.color_bottom
2749 = prop.color_left = prop.color_right = Mnil;
2750 prop.inner_hmargin = prop.inner_vmargin = 1;
2751 prop.outer_hmargin = prop.outer_vmargin = 0;
2752 face_input_status = mface_copy (face_default);
2753 mface_put_prop (face_input_status, Mbox, &prop);
2756 XFillRectangle (display, input_status_pixmap, gc_inv,
2757 0, 0, input_status_width, input_status_height);
2758 XtSetArg (arg[0], XtNfromHoriz, w);
2759 XtSetArg (arg[1], XtNleft, XawRubber);
2760 XtSetArg (arg[2], XtNright, XawChainRight);
2761 XtSetArg (arg[3], XtNborderWidth, 0);
2762 XtSetArg (arg[4], XtNlabel, " ");
2763 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2764 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2765 HeadWidget, arg, 6);
2766 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2767 XtSetArg (arg[1], XtNleft, XawChainRight);
2768 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2769 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2770 HeadWidget, arg, 5);
2772 XtSetArg (arg[0], XtNborderWidth, 0);
2773 XtSetArg (arg[1], XtNleft, XawChainLeft);
2774 XtSetArg (arg[2], XtNright, XawChainLeft);
2775 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2776 for (i = 0; i < num_faces;)
2778 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2779 char *label = label_menu + 5; /* "Xxxx" */
2781 for (j = i; j < num_faces && face_table[j].face; j++)
2782 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2784 w = create_menu_button (ShellWidget, FaceWidget, w,
2786 menus, j - i, "Push face property");
2790 XtSetArg (arg[0], XtNfromHoriz, w);
2791 XtSetArg (arg[1], XtNleft, XawChainLeft);
2792 XtSetArg (arg[2], XtNright, XawChainLeft);
2793 XtSetArg (arg[3], XtNhorizDistance, 10);
2794 XtSetArg (arg[4], XtNlabel, "Pop");
2795 XtSetArg (arg[5], XtNtranslations,
2796 XtParseTranslationTable (pop_face_trans));
2797 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2798 FaceWidget, arg, 6);
2799 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2801 XtSetArg (arg[0], XtNfromHoriz, w);
2802 XtSetArg (arg[1], XtNleft, XawChainLeft);
2803 XtSetArg (arg[2], XtNright, XawChainRight);
2804 XtSetArg (arg[3], XtNlabel, "");
2805 XtSetArg (arg[4], XtNborderWidth, 0);
2806 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2807 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2808 FaceWidget, arg, 6);
2810 XtSetArg (arg[0], XtNborderWidth, 0);
2811 XtSetArg (arg[1], XtNleft, XawChainLeft);
2812 XtSetArg (arg[2], XtNright, XawChainLeft);
2813 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2815 MPlist *plist[11], *pl;
2818 for (i = 0; i < 11; i++) plist[i] = NULL;
2820 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2821 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2823 MSymbol sym = msymbol_exist (langname);
2827 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2829 char *name = msymbol_name (fullname);
2832 if (c >= 'A' && c <= 'Z')
2834 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2838 pl = plist[idx] = mplist ();
2839 for (; mplist_next (pl); pl = mplist_next (pl))
2840 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2842 mplist_push (pl, sym, fullname);
2847 for (i = 0; i < 11; i++)
2850 char *name = alloca (9);
2852 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2855 for (j = 0, pl = plist[i]; mplist_next (pl);
2856 j++, pl = mplist_next (pl))
2857 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2858 msymbol_name (mplist_key (pl)),
2859 LangProc, mplist_key (pl), -1);
2860 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2861 menus, j, "Push language property");
2863 for (i = 0; i < 11; i++)
2865 m17n_object_unref (plist[i]);
2867 XtSetArg (arg[0], XtNfromHoriz, w);
2868 XtSetArg (arg[1], XtNleft, XawChainLeft);
2869 XtSetArg (arg[2], XtNright, XawChainLeft);
2870 XtSetArg (arg[3], XtNhorizDistance, 10);
2871 XtSetArg (arg[4], XtNlabel, "Pop");
2872 XtSetArg (arg[5], XtNtranslations,
2873 XtParseTranslationTable (pop_lang_trans));
2874 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2875 LangWidget, arg, 6);
2876 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2878 XtSetArg (arg[0], XtNfromHoriz, w);
2879 XtSetArg (arg[1], XtNleft, XawChainLeft);
2880 XtSetArg (arg[2], XtNright, XawChainRight);
2881 XtSetArg (arg[3], XtNlabel, "");
2882 XtSetArg (arg[4], XtNborderWidth, 0);
2883 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2884 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2885 LangWidget, arg, 6);
2888 XtSetArg (arg[0], XtNheight, win_height);
2889 XtSetArg (arg[1], XtNwidth, 10);
2890 XtSetArg (arg[2], XtNleft, XawChainLeft);
2891 XtSetArg (arg[3], XtNright, XawChainLeft);
2892 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2894 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2895 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2897 XtSetArg (arg[0], XtNheight, win_height);
2898 XtSetArg (arg[1], XtNwidth, win_width);
2899 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2900 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2901 XtSetArg (arg[4], XtNleft, XawChainLeft);
2902 XtSetArg (arg[5], XtNright, XawChainRight);
2903 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2906 XtSetArg (arg[0], XtNborderWidth, 0);
2907 XtSetArg (arg[1], XtNleft, XawChainLeft);
2908 XtSetArg (arg[2], XtNright, XawChainRight);
2909 XtSetArg (arg[3], XtNresizable, True);
2910 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2911 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2912 TailWidget, arg, 5);
2914 memset (&control, 0, sizeof control);
2915 control.two_dimensional = 1;
2916 control.enable_bidi = 1;
2917 control.anti_alias = 1;
2918 control.min_line_ascent = font_ascent;
2919 control.min_line_descent = font_descent;
2920 control.max_line_width = win_width;
2921 control.with_cursor = 1;
2922 control.cursor_width = 2;
2923 control.partial_update = 1;
2924 control.ignore_formatting_char = 1;
2926 memset (&input_status_control, 0, sizeof input_status_control);
2927 input_status_control.enable_bidi = 1;
2929 XtAppAddActions (context, actions, XtNumber (actions));
2930 XtRealizeWidget (ShellWidget);
2932 win = XtWindow (TextWidget);
2934 XtAppMainLoop (context);
2936 if (current_input_context)
2937 minput_destroy_ic (current_input_context);
2938 for (i = 0; i < num_input_methods; i++)
2939 if (input_method_table[i].im)
2940 minput_close_im (input_method_table[i].im);
2941 m17n_object_unref (frame);
2942 m17n_object_unref (mt);
2943 m17n_object_unref (face_xxx_large);
2944 m17n_object_unref (face_box);
2945 m17n_object_unref (face_courier);
2946 m17n_object_unref (face_helvetica);
2947 m17n_object_unref (face_times);
2948 m17n_object_unref (face_dv_ttyogesh);
2949 m17n_object_unref (face_freesans);
2950 m17n_object_unref (face_freeserif);
2951 m17n_object_unref (face_freemono);
2952 m17n_object_unref (face_default_fontset);
2953 m17n_object_unref (face_no_ctl_fontset);
2954 m17n_object_unref (face_input_status);
2955 m17n_object_unref (face_default);
2956 m17n_object_unref (default_face_list);
2957 m17n_object_unref (selection);
2959 XFreeGC (display, mono_gc);
2960 XFreeGC (display, mono_gc_inv);
2961 XFreeGC (display, gc_inv);
2962 XtUninstallTranslations (form);
2963 XtUninstallTranslations (TextWidget);
2964 XtDestroyWidget (ShellWidget);
2965 XtDestroyApplicationContext (context);
2969 free (fontset_name);
2971 free (input_method_table);
2972 free (InputMethodMenus);
2976 #endif /* not FOR_DOXYGEN */