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);
1073 if (! this_mt && *type != XA_UTF8_STRING)
1075 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1082 insert_chars (this_mt);
1083 m17n_object_unref (this_mt);
1092 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1094 XExposeEvent *expose = (XExposeEvent *) event;
1098 Dimension width_max, width;
1100 XtSetArg (arg[0], XtNwidth, &width);
1101 XtGetValues (XtParent (w), arg, 1);
1103 XtGetValues (HeadWidget, arg, 1);
1104 if (width_max < width)
1106 XtGetValues (FaceWidget, arg, 1);
1107 if (width_max < width)
1109 XtGetValues (LangWidget, arg, 1);
1110 if (width_max < width)
1112 XtSetArg (arg[0], XtNwidth, width_max);
1113 XtSetValues (HeadWidget, arg, 1);
1114 XtSetValues (FaceWidget, arg, 1);
1115 XtSetValues (LangWidget, arg, 1);
1116 XtSetValues (XtParent (w), arg, 1);
1117 XtSetValues (TailWidget, arg, 1);
1120 update_cursor (0, 1);
1121 redraw (0, win_height, 0, 1);
1126 redraw (expose->y, expose->y + expose->height, 0, 0);
1127 if (current_input_context
1128 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1129 set_input_method_spot ();
1134 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1136 XConfigureEvent *configure = (XConfigureEvent *) event;
1139 control.max_line_width = win_width = configure->width;
1140 win_height = configure->height;
1141 mdraw_clear_cache (mt);
1143 update_cursor (0, 1);
1144 redraw (0, win_height, 1, 1);
1145 if (current_input_context)
1146 set_input_method_spot ();
1150 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1153 int x = event->xbutton.x;
1154 int y = event->xbutton.y - top.ascent;
1156 if (control.orientation_reversed)
1158 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1161 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1162 mtext_detach_property (selection);
1163 redraw (sel_start.y0, sel_end.y1, 1, 0);
1166 update_cursor (pos, 0);
1171 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1176 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1177 covert_selection, lose_selection, NULL);
1178 update_cursor (mtext_property_start (selection), 0);
1183 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1187 /* We don't have a local selection. */
1188 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1193 int from = mtext_property_start (selection);
1194 int to = mtext_property_end (selection);
1197 int x = event->xbutton.x;
1198 int y = event->xbutton.y - top.ascent;
1200 if (control.orientation_reversed)
1202 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1204 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1205 mtext_detach_property (selection);
1207 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1208 update_cursor (pos, 0);
1209 insert_chars (this_mt);
1210 m17n_object_unref (this_mt);
1215 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1218 int x = event->xbutton.x;
1219 int y = event->xbutton.y;
1221 if (control.orientation_reversed)
1224 pos = top.from, y -= top.ascent;
1226 pos = cur.from, y -= cur.y0 + cur.ascent;
1227 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1229 if (pos == cursor.from)
1235 /* Selection range changed. */
1236 int from = mtext_property_start (selection);
1237 int to = mtext_property_end (selection);
1238 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1239 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1241 if (cursor.from == from)
1243 /* Starting position changed. */
1246 /* Enlarged. We can simply overdraw. */
1247 select_region (pos, to);
1248 redraw (sel_start.y0, start_y1, 0, 0);
1252 /* Shrunken. Previous selection face must be cleared. */
1253 select_region (pos, to);
1254 redraw (start_y0, sel_start.y1, 1, 0);
1258 /* Shrunken to zero. */
1259 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1260 mtext_detach_property (selection);
1261 redraw (start_y0, end_y1, 1, 0);
1265 /* Full update is necessary. */
1266 select_region (to, pos);
1267 redraw (start_y0, sel_end.y1, 1, 0);
1272 /* Ending position changed. */
1275 /* Full update is necessary. */
1276 select_region (pos, from);
1277 redraw (sel_start.y0, end_y1, 1, 0);
1279 else if (pos == from)
1281 /* Shrunken to zero. */
1282 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1283 mtext_detach_property (selection);
1284 redraw (start_y0, end_y1, 1, 0);
1288 /* Shrunken. Previous selection face must be cleared. */
1289 select_region (from, pos);
1290 redraw (sel_end.y0, end_y1, 1, 0);
1294 /* Enlarged. We can simply overdraw. */
1295 select_region (from, pos);
1296 redraw (end_y0, sel_end.y1, 0, 0);
1302 /* Newly selected. */
1303 select_region (pos, cursor.from);
1304 redraw (sel_start.y0, sel_end.y1, 0, 0);
1306 update_cursor (pos, 1);
1310 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1313 MDrawGlyphInfo info;
1315 int cursor_pos = cursor.from;
1317 if (((int) position) < 0)
1323 height = top.y1 - top.y0;
1326 pos = bol (from - 1, 0);
1327 GLYPH_INFO (pos, from - 1, info);
1328 if (height + info.this.height > win_height)
1330 height += info.this.height;
1331 from = info.line_from;
1333 if (cursor_pos >= top.to)
1335 cursor_pos = top.from;
1337 while (cursor_pos < nchars)
1339 GLYPH_INFO (pos, pos, info);
1340 if (height + info.this.height > win_height)
1342 height += info.this.height;
1348 else if (cur.to < nchars)
1350 /* Scroll up, but leave at least one line. */
1353 while (from < nchars)
1355 GLYPH_INFO (from, from, info);
1356 if (height + info.this.height > win_height
1357 || info.line_to >= nchars)
1359 height += info.this.height;
1360 from = info.line_to;
1363 from = info.line_from;
1364 if (cursor_pos < from)
1368 /* Scroll up to make the cursor line top. */
1372 update_cursor (cursor_pos, 1);
1376 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1378 float persent = *(float *) persent_ptr;
1379 int pos1, pos2 = nchars * persent;
1380 MDrawGlyphInfo info;
1383 pos1 = bol (pos2, 0);
1384 GLYPH_INFO (pos1, pos2, info);
1385 pos1 = info.line_from;
1387 update_cursor (pos1, 1);
1392 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1394 XKeyEvent *key_event = (XKeyEvent *) event;
1396 KeySym keysym = NoSymbol;
1398 /* If set to 1, do not update target_x_position. */
1399 int keep_target_x_position = 0;
1402 if (current_input_context
1403 && minput_filter (current_input_context, Mnil, event))
1405 if (event->type == KeyRelease)
1410 produced = mtext ();
1411 ret = minput_lookup (current_input_context, Mnil, event, produced);
1412 if (mtext_len (produced) > 0)
1413 insert_chars (produced);
1415 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1416 m17n_object_unref (produced);
1426 n = (mtext_property_end (selection)
1427 - mtext_property_start (selection));
1428 mtext_detach_property (selection);
1430 else if (cursor.from < nchars)
1432 /* Delete the following grapheme cluster. */
1433 n = cursor.to - cursor.from;
1446 /* Delete selected region. */
1447 n = (mtext_property_end (selection)
1448 - mtext_property_start (selection));
1449 mtext_detach_property (selection);
1451 else if (cursor.from > 0)
1453 /* Delete the preceding character. */
1464 mtext_detach_property (selection);
1465 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1469 if (cursor.prev_from >= 0)
1470 update_cursor (cursor.prev_from, 0);
1474 if (cursor.left_from >= 0)
1475 update_cursor (cursor.left_from, 0);
1482 mtext_detach_property (selection);
1483 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1487 if (cursor.next_to >= 0)
1488 update_cursor (cursor.to, 0);
1492 if (cursor.right_from >= 0)
1493 update_cursor (cursor.right_from, 0);
1500 mtext_detach_property (selection);
1501 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1503 if (cur.to <= nchars)
1505 MDrawGlyphInfo info;
1508 GLYPH_INFO (cur.from, cur.to, info);
1509 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1510 target_x_position, info.y);
1511 keep_target_x_position = 1;
1512 update_cursor (pos, 0);
1519 mtext_detach_property (selection);
1520 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1526 int pos = bol (cur.from - 1, 0);
1528 TEXT_EXTENTS (pos, cur.from - 1, rect);
1529 y = rect.height + rect.y - 1;
1530 pos = COORDINATES_POSITION (pos, nchars,
1531 target_x_position, y);
1532 keep_target_x_position = 1;
1533 update_cursor (pos, 0);
1540 mtext_detach_property (selection);
1541 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1543 if (top.from < nchars)
1544 ScrollProc (w, NULL, (XtPointer) 1);
1550 mtext_detach_property (selection);
1551 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1554 ScrollProc (w, NULL, (XtPointer) -1);
1560 if (buf[0] == 17) /* C-q */
1562 XtAppSetExitFlag (context);
1565 else if (buf[0] == 12) /* C-l */
1567 redraw (0, win_height, 1, 1);
1572 MText *temp = mtext ();
1574 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1575 if (current_input_context)
1576 mtext_put_prop (temp, 0, 1, Mlanguage,
1577 current_input_context->im->language);
1578 insert_chars (temp);
1579 m17n_object_unref (temp);
1584 if (! keep_target_x_position)
1585 target_x_position = cursor.x;
1589 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1591 char *name = (char *) client_data;
1593 int from = -1, to = 0;
1598 filename = strdup (name);
1601 fp = fopen (filename, "w");
1604 fprintf (stderr, "Open for write fail: %s", filename);
1610 from = mtext_property_start (selection);
1611 to = mtext_property_end (selection);
1612 mtext_detach_property (selection);
1615 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1618 select_region (from, to);
1622 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1628 mtext_detach_property (selection);
1629 serialized = (int) client_data;
1631 new = mtext_deserialize (mt);
1634 MPlist *plist = mplist ();
1636 mplist_push (plist, Mt, Mface);
1637 mplist_push (plist, Mt, Mlanguage);
1638 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1639 m17n_object_unref (plist);
1643 m17n_object_unref (mt);
1645 serialized = ! serialized;
1646 nchars = mtext_len (mt);
1649 update_cursor (0, 1);
1650 redraw (0, win_height, 1, 1);
1654 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1656 XtAppSetExitFlag (context);
1662 FILE *fp = fopen (filename, "r");
1665 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1666 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1669 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1674 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1676 int data = (int) client_data;
1681 control.enable_bidi = 0;
1682 control.orientation_reversed = 0;
1686 control.enable_bidi = 1;
1687 control.orientation_reversed = data == 2;
1689 for (i = 0; i < 3; i++)
1692 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1694 XtSetArg (arg[0], XtNleftBitmap, None);
1695 XtSetValues (BidiMenus[i], arg, 1);
1698 update_cursor (cursor.from, 1);
1699 redraw (0, win_height, 1, 0);
1702 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1705 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1707 int data = (int) client_data;
1711 control.max_line_width = 0;
1714 control.max_line_width = win_width;
1715 control.line_break = (data == 1 ? NULL : line_break);
1717 for (i = 0; i < 3; i++)
1720 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1722 XtSetArg (arg[0], XtNleftBitmap, None);
1723 XtSetValues (LineBreakMenus[i], arg, 1);
1726 update_cursor (cursor.from, 1);
1727 redraw (0, win_height, 1, 0);
1731 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1733 int data = (int) client_data;
1747 control.cursor_bidi = 0, control.cursor_width = -1;
1751 control.cursor_bidi = 0, control.cursor_width = 2;
1755 control.cursor_bidi = 1;
1760 for (i = from; i < to; i++)
1763 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1765 XtSetArg (arg[0], XtNleftBitmap, None);
1766 XtSetValues (CursorMenus[i], arg, 1);
1769 redraw (0, win_height, 1, 0);
1773 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1775 int idx = (int) client_data;
1777 if (idx == -2 ? current_input_method < 0
1778 : idx == -1 ? auto_input_method
1779 : idx == current_input_method)
1782 XtSetArg (arg[0], XtNleftBitmap, None);
1783 if (auto_input_method)
1785 XtSetValues (InputMethodMenus[1], arg, 1);
1786 auto_input_method = 0;
1788 else if (current_input_method < 0)
1789 XtSetValues (InputMethodMenus[0], arg, 1);
1791 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1795 auto_input_method = 1;
1798 else if (input_method_table[idx].available >= 0)
1800 if (! input_method_table[idx].im)
1802 input_method_table[idx].im =
1803 minput_open_im (input_method_table[idx].language,
1804 input_method_table[idx].name, NULL);
1805 if (! input_method_table[idx].im)
1806 input_method_table[idx].available = -1;
1808 if (input_method_table[idx].im)
1809 select_input_method (idx);
1811 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1812 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1815 MPlist *default_face_list;
1818 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1820 int idx = (int) client_data;
1830 MFace *face = mframe_get_prop (frame, Mface);
1832 for (plist = default_face_list; mplist_key (plist) != Mnil;
1833 plist = mplist_next (plist))
1834 mface_merge (face, mplist_value (plist));
1835 mplist_add (plist, Mt, *face_table[idx].face);
1836 mface_merge (face, *face_table[idx].face);
1838 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1840 MFace *face = mframe_get_prop (frame, Mface);
1842 for (plist = default_face_list;
1843 mplist_key (mplist_next (plist)) != Mnil;
1844 plist = mplist_next (plist))
1845 mface_merge (face, mplist_value (plist));
1849 update_cursor (0, 1);
1850 redraw (0, win_height, 1, 1);
1855 XtAppAddWorkProc (context, show_cursor, NULL);
1856 from = mtext_property_start (selection);
1857 to = mtext_property_end (selection);
1858 old_y1 = sel_end.y1;
1860 mtext_detach_property (selection);
1863 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1864 MTEXTPROP_REAR_STICKY);
1865 mtext_push_property (mt, from, to, prop);
1866 m17n_object_unref (prop);
1869 mtext_pop_prop (mt, from, to, Mface);
1871 update_top (top.from);
1872 update_cursor (cursor.from, 1);
1873 select_region (from, to);
1874 update_region (sel_start.y0, old_y1, sel_end.y1);
1875 if (cur.y1 > win_height)
1877 while (cur.y1 > win_height)
1880 update_cursor (cursor.from, 1);
1886 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1888 MSymbol sym = (MSymbol) client_data;
1895 XtAppAddWorkProc (context, show_cursor, NULL);
1896 from = mtext_property_start (selection);
1897 to = mtext_property_end (selection);
1898 old_y1 = sel_end.y1;
1900 mtext_detach_property (selection);
1902 mtext_put_prop (mt, from, to, Mlanguage, sym);
1904 mtext_pop_prop (mt, from, to, Mlanguage);
1907 update_top (top.from);
1908 update_cursor (cursor.from, 1);
1909 select_region (from, to);
1910 update_region (sel_start.y0, old_y1, sel_end.y1);
1911 if (cur.y1 > win_height)
1913 while (cur.y1 > win_height)
1916 update_cursor (cursor.from, 1);
1922 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1924 int narrowed = (int) client_data;
1927 MConverter *converter;
1933 from = mtext_property_start (selection);
1934 to = mtext_property_end (selection);
1943 mdump = popen ("mdump -q -p a4", "w");
1945 mdump = popen ("mdump -q", "w");
1948 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1949 mconv_encode_range (converter, mt, from, to);
1950 mconv_free_converter (converter);
1955 input_status (MInputContext *ic, MSymbol command)
1957 XFillRectangle (display, input_status_pixmap, gc_inv,
1958 0, 0, input_status_width, input_status_height);
1959 if (command == Minput_status_draw)
1963 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1964 Mface, face_input_status);
1965 if (ic->im->language != Mnil)
1966 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1967 Mlanguage, ic->im->language);
1968 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1969 &input_status_control, NULL, NULL, &rect);
1970 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1971 input_status_width - rect.width - 2, - rect.y,
1972 ic->status, 0, mtext_len (ic->status),
1973 &input_status_control);
1975 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1976 XtSetValues (CurIMStatus, arg, 1);
1980 compare_input_method (const void *elt1, const void *elt2)
1982 const InputMethodInfo *im1 = elt1;
1983 const InputMethodInfo *im2 = elt2;
1984 MSymbol lang1, lang2;
1986 if (im1->language == Mnil)
1988 if (im1->language == im2->language)
1989 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1990 if (im1->language == Mt)
1992 if (im2->language == Mt)
1994 lang1 = msymbol_get (im1->language, Mlanguage);
1995 lang2 = msymbol_get (im2->language, Mlanguage);
1996 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2000 setup_input_methods (int with_xim)
2002 MInputMethod *im = NULL;
2003 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2007 num_input_methods = mplist_length (plist);
2011 MInputXIMArgIM arg_xim;
2013 arg_xim.display = display;
2015 arg_xim.res_name = arg_xim.res_class = NULL;
2016 arg_xim.locale = NULL;
2017 arg_xim.modifier_list = NULL;
2018 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2020 num_input_methods++;
2022 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2025 input_method_table[i].available = 1;
2026 input_method_table[i].language = Mnil;
2027 input_method_table[i].name = im->name;
2028 input_method_table[i].im = im;
2032 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2034 MDatabase *mdb = mplist_value (pl);
2035 MSymbol *tag = mdatabase_tag (mdb);
2039 input_method_table[i].language = tag[1];
2040 input_method_table[i].name = tag[2];
2045 m17n_object_unref (plist);
2046 num_input_methods = i;
2047 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2048 compare_input_method);
2049 current_input_context = NULL;
2051 mplist_put (minput_driver->callback_list, Minput_status_start,
2052 (void *) input_status);
2053 mplist_put (minput_driver->callback_list, Minput_status_draw,
2054 (void *) input_status);
2055 mplist_put (minput_driver->callback_list, Minput_status_done,
2056 (void *) input_status);
2061 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2065 if (num && *num > 0)
2069 for (i = 0; i < *num; i++)
2070 bytes += strlen (str[i]) + 1;
2071 msg = alloca (bytes);
2072 strcpy (msg, str[0]);
2073 for (i = 1; i < *num; i++)
2074 strcat (msg, " "), strcat (msg, str[i]);
2076 else if (cursor.from < nchars)
2078 int c = mtext_ref_char (mt, cursor.from);
2079 char *name = mchar_get_prop (c, Mname);
2083 msg = alloca (10 + strlen (name));
2084 sprintf (msg, "U+%04X %s", c, name);
2090 XtSetArg (arg[0], XtNlabel, msg);
2091 XtSetValues (MessageWidget, arg, 1);
2097 char *name1, *name2;
2098 XtCallbackProc proc;
2099 XtPointer client_data;
2104 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2106 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2108 MenuRec FileMenu[] =
2109 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2110 { 0, "Save", NULL, SaveProc, NULL, -1 },
2111 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2113 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2114 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2116 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2117 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2119 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2122 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2124 MenuRec *rec = (MenuRec *) client_data;
2127 XtSetArg (arg[0], XtNvalue, "");
2128 XtSetArg (arg[1], XtNlabel, rec->name1);
2129 XtSetValues (FileDialogWidget, arg, 2);
2130 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2131 XtSetArg (arg[0], XtNx, x + 20);
2132 XtSetArg (arg[1], XtNy, y + 10);
2133 XtSetValues (FileShellWidget, arg, 2);
2134 XtPopup (FileShellWidget, XtGrabExclusive);
2138 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2143 XtPopdown (FileShellWidget);
2144 if ((int) client_data == 1)
2146 XtSetArg (arg[0], XtNlabel, &label);
2147 XtGetValues (FileDialogWidget, arg, 1);
2148 if (strcmp (label, FileMenu[0].name1) == 0)
2152 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2153 fp = fopen (filename, "r");
2155 m17n_object_unref (mt);
2158 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2166 nchars = mtext_len (mt);
2168 update_cursor (0, 1);
2169 redraw (0, win_height, 1, 1);
2171 else if (strcmp (label, FileMenu[2].name1) == 0)
2172 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2174 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2177 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2178 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2179 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2180 (MENU).status = (STATUS))
2184 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2185 char *menu_name, MenuRec *menus, int num_menus, char *help)
2187 Widget button, menu;
2188 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2189 <LeaveWindow>: reset() MenuHelp()\n\
2190 <BtnDown>: reset() PopupMenu()\n\
2191 <BtnUp>: highlight()";
2197 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2198 for (i = 0; i < num_menus; i++)
2209 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2211 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2213 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2215 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2219 XtSetArg (arg[0], XtNsensitive, False);
2220 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2226 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2231 trans = alloca (strlen (fmt) + strlen (help));
2232 sprintf (trans, fmt, help);
2233 XtSetArg (arg[0], XtNmenuName, menu_name);
2234 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2235 XtSetArg (arg[2], XtNinternalWidth, 2);
2236 XtSetArg (arg[3], XtNhighlightThickness, 1);
2237 XtSetArg (arg[4], XtNleft, XawChainLeft);
2238 XtSetArg (arg[5], XtNright, XawChainLeft);
2241 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2242 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2247 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2248 int *len = alloca (sizeof (int) * num_menus);
2251 XFontSetExtents *fontset_extents;
2253 XtSetArg (arg[0], XtNfontSet, &font_set);
2254 XtGetValues (button, arg, 1);
2256 fontset_extents = XExtentsOfFontSet (font_set);
2257 height = fontset_extents->max_logical_extent.height;
2258 ascent = - fontset_extents->max_logical_extent.y;
2260 for (i = 0; i < num_menus; i++)
2263 len[i] = strlen (menus[i].name2);
2264 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2265 if (max_width < width[i])
2266 max_width = width[i];
2268 for (i = 0; i < num_menus; i++)
2271 Pixmap pixmap = XCreatePixmap (display,
2272 RootWindow (display, screen),
2273 max_width, height, 1);
2274 XFillRectangle (display, pixmap, mono_gc_inv,
2275 0, 0, max_width, height);
2276 XmbDrawString (display, pixmap, font_set, mono_gc,
2277 max_width - width[i], ascent,
2278 menus[i].name2, len[i]);
2279 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2280 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2281 XtSetValues (menus[i].w, arg, 2);
2289 XtActionsRec actions[] = {
2290 {"Expose", ExposeProc},
2291 {"Configure", ConfigureProc},
2293 {"ButtonPress", ButtonProc},
2294 {"ButtonRelease", ButtonReleaseProc},
2295 {"ButtonMotion", ButtonMoveProc},
2296 {"Button2Press", Button2Proc},
2297 {"MenuHelp", MenuHelpProc}
2301 /* Print the usage of this program (the name is PROG), and exit with
2305 help_exit (char *prog, int exit_code)
2313 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2314 printf ("Display FILE on a window and allow users to edit it.\n");
2315 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2316 printf ("The following OPTIONs are available.\n");
2317 printf (" %-13s %s", "--version", "print version number\n");
2318 printf (" %-13s %s", "-h, --help", "print this message\n");
2323 main (int argc, char **argv)
2325 Widget form, BodyWidget, w;
2326 char *fontset_name = NULL;
2327 int col = 80, row = 32;
2328 /* Translation table for TextWidget. */
2329 String trans = "<Expose>: Expose()\n\
2330 <Configure>: Configure()\n\
2333 <Btn1Down>: ButtonPress()\n\
2334 <Btn1Up>: ButtonRelease()\n\
2335 <Btn1Motion>: ButtonMotion()\n\
2336 <Btn2Down>: Button2Press()";
2337 /* Translation table for the top form widget. */
2338 String trans2 = "<Key>: Key()\n\
2340 String pop_face_trans
2341 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2342 <LeaveWindow>: MenuHelp() reset()\n\
2343 <Btn1Down>: set()\n\
2344 <Btn1Up>: notify() unset()";
2345 String pop_lang_trans
2346 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2347 <LeaveWindow>: MenuHelp() reset()\n\
2348 <Btn1Down>: set()\n\
2349 <Btn1Up>: notify() unset()";
2350 int font_width, font_ascent, font_descent;
2354 setlocale (LC_ALL, "");
2355 /* Create the top shell. */
2356 XtSetLanguageProc (NULL, NULL, NULL);
2357 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2358 NULL, sessionShellWidgetClass, NULL, 0);
2359 display = XtDisplay (ShellWidget);
2360 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2362 /* Parse the remaining command line arguments. */
2363 for (i = 1; i < argc; i++)
2365 if (! strcmp (argv[i], "--help")
2366 || ! strcmp (argv[i], "-h"))
2367 help_exit (argv[0], 0);
2368 else if (! strcmp (argv[i], "--version"))
2370 printf ("medit (m17n library) %s\n", VERSION);
2371 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2374 else if (! strcmp (argv[i], "--geometry"))
2377 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2378 help_exit (argv[0], 1);
2380 else if (! strcmp (argv[i], "--fontset"))
2383 fontset_name = strdup (argv[i]);
2385 else if (! strcmp (argv[i], "--with-xim"))
2389 else if (argv[i][0] != '-')
2391 filename = strdup (argv[i]);
2395 fprintf (stderr, "Unknown option: %s", argv[i]);
2396 help_exit (argv[0], 1);
2400 help_exit (argv[0], 1);
2402 mdatabase_dir = ".";
2403 /* Initialize the m17n library. */
2405 if (merror_code != MERROR_NONE)
2406 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2408 mt = read_file (filename);
2411 nchars = mtext_len (mt);
2414 MFace *face = mface ();
2416 mface_put_prop (face, Mforeground, msymbol ("blue"));
2417 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2418 mface_put_prop (face, Mvideomode, Mreverse);
2419 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2420 m17n_object_unref (face);
2423 /* This tells ExposeProc to initialize everything. */
2426 XA_TEXT = XInternAtom (display, "TEXT", False);
2427 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2428 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2429 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2430 if (Mcoding_compound_text == Mnil)
2431 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2434 MPlist *plist = mplist ();
2438 mplist_put (plist, msymbol ("widget"), ShellWidget);
2441 MFontset *fontset = mfontset (fontset_name);
2444 mface_put_prop (face, Mfontset, fontset);
2445 m17n_object_unref (fontset);
2446 mplist_add (plist, Mface, face);
2447 m17n_object_unref (face);
2449 frame = mframe (plist);
2451 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2452 m17n_object_unref (plist);
2453 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2454 default_face_list = mplist ();
2455 mplist_add (default_face_list, Mt, face_default);
2456 face_default_fontset = mface ();
2457 mface_put_prop (face_default_fontset, Mfontset,
2458 mface_get_prop (face_default, Mfontset));
2460 font = (MFont *) mframe_get_prop (frame, Mfont);
2461 default_font_size = (int) mfont_get_prop (font, Msize);
2464 font_width = (int) mframe_get_prop (frame, Mfont_width);
2465 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2466 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2467 win_width = font_width * col;
2468 win_height = (font_ascent + font_descent) * row;
2474 prop.color_top = prop.color_left = msymbol ("magenta");
2475 prop.color_bottom = prop.color_right = msymbol ("red");
2476 prop.inner_hmargin = prop.inner_vmargin = 1;
2477 prop.outer_hmargin = prop.outer_vmargin = 2;
2479 face_box = mface ();
2480 mface_put_prop (face_box, Mbox, &prop);
2483 face_courier = mface ();
2484 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2485 face_helvetica = mface ();
2486 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2487 face_times = mface ();
2488 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2489 face_dv_ttyogesh = mface ();
2490 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2491 face_freesans = mface ();
2492 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2493 face_freeserif = mface ();
2494 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2495 face_freemono = mface ();
2496 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2498 face_xxx_large = mface ();
2499 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2501 MFont *latin_font = mframe_get_prop (frame, Mfont);
2502 MFont *dev_font = mfont ();
2503 MFont *thai_font = mfont ();
2504 MFont *tib_font = mfont ();
2506 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2507 MSymbol no_ctl = msymbol ("no-ctl");
2509 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2510 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2511 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2512 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2513 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2514 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2516 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2517 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2518 latin_font, Mnil, 0);
2519 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2520 dev_font, no_ctl, 0);
2521 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2522 thai_font, no_ctl, 0);
2523 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2524 tib_font, no_ctl, 0);
2525 face_no_ctl_fontset = mface ();
2526 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2527 m17n_object_unref (fontset);
2534 setup_input_methods (with_xim);
2536 gc = DefaultGC (display, screen);
2538 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2539 XtSetArg (arg[1], XtNdefaultDistance, 2);
2540 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2542 XtSetArg (arg[0], XtNborderWidth, 0);
2543 XtSetArg (arg[1], XtNdefaultDistance, 2);
2544 XtSetArg (arg[2], XtNtop, XawChainTop);
2545 XtSetArg (arg[3], XtNbottom, XawChainTop);
2546 XtSetArg (arg[4], XtNleft, XawChainLeft);
2547 XtSetArg (arg[5], XtNright, XawChainRight);
2548 XtSetArg (arg[6], XtNresizable, True);
2549 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2550 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2551 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2552 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2553 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2554 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2555 XtSetArg (arg[7], XtNfromVert, LangWidget);
2556 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2557 XtSetArg (arg[2], XtNtop, XawChainBottom);
2558 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2559 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2561 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2562 HeadWidget, NULL, 0);
2563 XtSetArg (arg[0], XtNvalue, "");
2564 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2565 FileShellWidget, arg, 1);
2566 XawDialogAddButton (FileDialogWidget, "OK",
2567 FileDialogProc, (XtPointer) 0);
2568 XawDialogAddButton (FileDialogWidget, "CANCEL",
2569 FileDialogProc, (XtPointer) 1);
2571 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2572 (char *) check_bits,
2573 check_width, check_height);
2575 unsigned long valuemask = GCForeground;
2578 values.foreground = 1;
2579 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2580 values.foreground = 0;
2581 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2588 if (num_menus < num_input_methods + 2)
2589 num_menus = num_input_methods + 2;
2590 if (num_menus < num_faces + 1)
2591 num_menus = num_faces + 1;
2592 menus = alloca (sizeof (MenuRec) * num_menus);
2594 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2595 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2596 "File I/O, Serialization, Image, Quit");
2598 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2599 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2600 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2601 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2602 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2603 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2604 w = create_menu_button (ShellWidget, HeadWidget, w,
2605 "Cursor", "Cursor Menu",
2606 menus, 6, "Cursor Movement Mode, Cursor Shape");
2607 CursorMenus[0] = menus[0].w;
2608 CursorMenus[1] = menus[1].w;
2609 CursorMenus[2] = menus[3].w;
2610 CursorMenus[3] = menus[4].w;
2611 CursorMenus[4] = menus[5].w;
2613 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2614 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2615 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2616 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2617 menus, 3, "BIDI Processing Mode");
2618 for (i = 0; i < 3; i++)
2619 BidiMenus[i] = menus[i].w;
2621 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2622 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2623 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2624 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2626 menus, 3, "How to break lines");
2627 for (i = 0; i < 3; i++)
2628 LineBreakMenus[i] = menus[i].w;
2630 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2631 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2632 for (i = 0; i < num_input_methods; i++)
2634 InputMethodInfo *im = input_method_table + i;
2635 char *name1, *name2;
2637 if (im->language != Mnil && im->language != Mt)
2639 MSymbol sym = msymbol_get (im->language, Mlanguage);
2641 name1 = msymbol_name (im->language);
2643 name1 = msymbol_name (sym);
2644 name2 = msymbol_name (im->name);
2647 name1 = msymbol_name (im->name), name2 = NULL;
2649 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2651 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2652 "Input Method Menu", menus, i + 2,
2653 "Select input method");
2656 unsigned long valuemask = GCForeground;
2659 XtSetArg (arg[0], XtNbackground, &values.foreground);
2660 XtGetValues (w, arg, 1);
2661 gc_inv = XCreateGC (display, RootWindow (display, screen),
2662 valuemask, &values);
2665 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2666 for (i = 0; i < num_input_methods + 2; i++)
2667 InputMethodMenus[i] = menus[i].w;
2669 input_status_width = font_width * 8;
2670 input_status_height = (font_ascent + font_descent) * 2.4;
2671 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2673 input_status_height,
2674 DefaultDepth (display, screen));
2679 prop.color_top = prop.color_bottom
2680 = prop.color_left = prop.color_right = Mnil;
2681 prop.inner_hmargin = prop.inner_vmargin = 1;
2682 prop.outer_hmargin = prop.outer_vmargin = 0;
2683 face_input_status = mface_copy (face_default);
2684 mface_put_prop (face_input_status, Mbox, &prop);
2687 XFillRectangle (display, input_status_pixmap, gc_inv,
2688 0, 0, input_status_width, input_status_height);
2689 XtSetArg (arg[0], XtNfromHoriz, w);
2690 XtSetArg (arg[1], XtNleft, XawRubber);
2691 XtSetArg (arg[2], XtNright, XawChainRight);
2692 XtSetArg (arg[3], XtNborderWidth, 0);
2693 XtSetArg (arg[4], XtNlabel, " ");
2694 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2695 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2696 HeadWidget, arg, 6);
2697 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2698 XtSetArg (arg[1], XtNleft, XawChainRight);
2699 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2700 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2701 HeadWidget, arg, 5);
2703 XtSetArg (arg[0], XtNborderWidth, 0);
2704 XtSetArg (arg[1], XtNleft, XawChainLeft);
2705 XtSetArg (arg[2], XtNright, XawChainLeft);
2706 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2707 for (i = 0; i < num_faces;)
2709 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2710 char *label = label_menu + 5; /* "Xxxx" */
2712 for (j = i; j < num_faces && face_table[j].face; j++)
2713 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2715 w = create_menu_button (ShellWidget, FaceWidget, w,
2717 menus, j - i, "Push face property");
2721 XtSetArg (arg[0], XtNfromHoriz, w);
2722 XtSetArg (arg[1], XtNleft, XawChainLeft);
2723 XtSetArg (arg[2], XtNright, XawChainLeft);
2724 XtSetArg (arg[3], XtNhorizDistance, 10);
2725 XtSetArg (arg[4], XtNlabel, "Pop");
2726 XtSetArg (arg[5], XtNtranslations,
2727 XtParseTranslationTable (pop_face_trans));
2728 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2729 FaceWidget, arg, 6);
2730 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2732 XtSetArg (arg[0], XtNfromHoriz, w);
2733 XtSetArg (arg[1], XtNleft, XawChainLeft);
2734 XtSetArg (arg[2], XtNright, XawChainRight);
2735 XtSetArg (arg[3], XtNlabel, "");
2736 XtSetArg (arg[4], XtNborderWidth, 0);
2737 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2738 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2739 FaceWidget, arg, 6);
2741 XtSetArg (arg[0], XtNborderWidth, 0);
2742 XtSetArg (arg[1], XtNleft, XawChainLeft);
2743 XtSetArg (arg[2], XtNright, XawChainLeft);
2744 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2746 MPlist *plist[11], *pl;
2749 for (i = 0; i < 11; i++) plist[i] = NULL;
2751 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2752 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2754 MSymbol sym = msymbol_exist (langname);
2758 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2760 char *name = msymbol_name (fullname);
2763 if (c >= 'A' && c <= 'Z')
2765 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2769 pl = plist[idx] = mplist ();
2770 for (; mplist_next (pl); pl = mplist_next (pl))
2771 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2773 mplist_push (pl, sym, fullname);
2778 for (i = 0; i < 11; i++)
2781 char *name = alloca (9);
2783 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2786 for (j = 0, pl = plist[i]; mplist_next (pl);
2787 j++, pl = mplist_next (pl))
2788 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2789 msymbol_name (mplist_key (pl)),
2790 LangProc, mplist_key (pl), -1);
2791 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2792 menus, j, "Push language property");
2794 for (i = 0; i < 11; i++)
2796 m17n_object_unref (plist[i]);
2798 XtSetArg (arg[0], XtNfromHoriz, w);
2799 XtSetArg (arg[1], XtNleft, XawChainLeft);
2800 XtSetArg (arg[2], XtNright, XawChainLeft);
2801 XtSetArg (arg[3], XtNhorizDistance, 10);
2802 XtSetArg (arg[4], XtNlabel, "Pop");
2803 XtSetArg (arg[5], XtNtranslations,
2804 XtParseTranslationTable (pop_lang_trans));
2805 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2806 LangWidget, arg, 6);
2807 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2809 XtSetArg (arg[0], XtNfromHoriz, w);
2810 XtSetArg (arg[1], XtNleft, XawChainLeft);
2811 XtSetArg (arg[2], XtNright, XawChainRight);
2812 XtSetArg (arg[3], XtNlabel, "");
2813 XtSetArg (arg[4], XtNborderWidth, 0);
2814 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2815 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2816 LangWidget, arg, 6);
2819 XtSetArg (arg[0], XtNheight, win_height);
2820 XtSetArg (arg[1], XtNwidth, 10);
2821 XtSetArg (arg[2], XtNleft, XawChainLeft);
2822 XtSetArg (arg[3], XtNright, XawChainLeft);
2823 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2825 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2826 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2828 XtSetArg (arg[0], XtNheight, win_height);
2829 XtSetArg (arg[1], XtNwidth, win_width);
2830 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2831 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2832 XtSetArg (arg[4], XtNleft, XawChainLeft);
2833 XtSetArg (arg[5], XtNright, XawChainRight);
2834 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2837 XtSetArg (arg[0], XtNborderWidth, 0);
2838 XtSetArg (arg[1], XtNleft, XawChainLeft);
2839 XtSetArg (arg[2], XtNright, XawChainRight);
2840 XtSetArg (arg[3], XtNresizable, True);
2841 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2842 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2843 TailWidget, arg, 5);
2845 memset (&control, 0, sizeof control);
2846 control.two_dimensional = 1;
2847 control.enable_bidi = 1;
2848 control.anti_alias = 1;
2849 control.min_line_ascent = font_ascent;
2850 control.min_line_descent = font_descent;
2851 control.max_line_width = win_width;
2852 control.with_cursor = 1;
2853 control.cursor_width = 2;
2854 control.partial_update = 1;
2855 control.ignore_formatting_char = 1;
2857 memset (&input_status_control, 0, sizeof input_status_control);
2858 input_status_control.enable_bidi = 1;
2860 XtAppAddActions (context, actions, XtNumber (actions));
2861 XtRealizeWidget (ShellWidget);
2863 win = XtWindow (TextWidget);
2865 XtAppMainLoop (context);
2867 if (current_input_context)
2868 minput_destroy_ic (current_input_context);
2869 for (i = 0; i < num_input_methods; i++)
2870 if (input_method_table[i].im)
2871 minput_close_im (input_method_table[i].im);
2872 m17n_object_unref (frame);
2873 m17n_object_unref (mt);
2874 m17n_object_unref (face_xxx_large);
2875 m17n_object_unref (face_box);
2876 m17n_object_unref (face_courier);
2877 m17n_object_unref (face_helvetica);
2878 m17n_object_unref (face_times);
2879 m17n_object_unref (face_dv_ttyogesh);
2880 m17n_object_unref (face_freesans);
2881 m17n_object_unref (face_freeserif);
2882 m17n_object_unref (face_freemono);
2883 m17n_object_unref (face_default_fontset);
2884 m17n_object_unref (face_no_ctl_fontset);
2885 m17n_object_unref (face_input_status);
2886 m17n_object_unref (face_default);
2887 m17n_object_unref (default_face_list);
2888 m17n_object_unref (selection);
2890 XFreeGC (display, mono_gc);
2891 XFreeGC (display, mono_gc_inv);
2892 XFreeGC (display, gc_inv);
2893 XtUninstallTranslations (form);
2894 XtUninstallTranslations (TextWidget);
2895 XtDestroyWidget (ShellWidget);
2896 XtDestroyApplicationContext (context);
2900 free (fontset_name);
2902 free (input_method_table);
2903 free (InputMethodMenus);
2907 #endif /* not FOR_DOXYGEN */