1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004, 2005
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 m17n-edit edit multilingual text
26 @section m17n-edit-synopsis SYNOPSIS
28 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section m17n-edit-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 m17n-edit directly uses the GUI API, the API is mainly
52 for toolkit libraries or to implement XOM (X Outout Method), not
53 for direct use from application programs.
56 @japage m17n-edit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section m17n-edit-synopsis SYNOPSIS
60 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section m17n-edit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit
83 ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é
84 ¥ê¤äXOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
85 ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
100 #ifdef HAVE_X11_XAW_COMMAND_H
102 #include <X11/keysym.h>
103 #include <X11/Xatom.h>
104 #include <X11/Intrinsic.h>
105 #include <X11/StringDefs.h>
106 #include <X11/Shell.h>
108 #include <m17n-gui.h>
109 #include <m17n-misc.h>
112 #include <X11/Xaw/Command.h>
113 #include <X11/Xaw/Box.h>
114 #include <X11/Xaw/Form.h>
115 #include <X11/Xaw/Dialog.h>
116 #include <X11/Xaw/Scrollbar.h>
117 #include <X11/Xaw/Toggle.h>
118 #include <X11/Xaw/SimpleMenu.h>
119 #include <X11/Xaw/SmeBSB.h>
120 #include <X11/Xaw/SmeLine.h>
121 #include <X11/Xaw/MenuButton.h>
123 #define VERSION "1.2.0"
125 /* Global variables. */
130 /* For the X Window System. */
133 /* GCs for normal drawing, filling by background color, normal drawing
134 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
136 GC gc, gc_inv, mono_gc, mono_gc_inv;
138 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
139 XtAppContext context;
140 int default_font_size;
144 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
145 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
146 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
147 +- Body -- Sbar, Text
151 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
152 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
153 Widget SbarWidget, TextWidget;
154 Widget FileShellWidget, FileDialogWidget;
155 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
156 Widget CurIMLang, CurIMStatus;
158 int win_width, win_height; /* Size of TextWidget. */
161 Pixmap input_status_pixmap;
162 int input_status_width, input_status_height;
164 /* Bitmap for "check" glyph. */
165 #define check_width 9
166 #define check_height 8
167 static unsigned char check_bits[] = {
168 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
169 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
172 /* For the m17n library. */
175 int nchars; /* == mtext_len (mt) */
176 MDrawControl control, input_status_control;
177 MTextProperty *selection;
182 MFace *face_xxx_large;
184 MFace *face_courier, *face_helvetica, *face_times;
185 MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
186 MFace *face_default_fontset, *face_no_ctl_fontset;
187 MFace *face_input_status;
189 MSymbol Mcoding_compound_text;
191 int logical_move = 1; /* If 0, move cursor visually. */
195 MSymbol language, name;
199 InputMethodInfo *input_method_table;
201 int num_input_methods;
202 int current_input_method = -1; /* i.e. none */
203 int auto_input_method = 0;
204 MInputContext *current_input_context;
211 { {"Menu Size", NULL},
212 {"xx-small", &mface_xx_small},
213 {"x-small", &mface_x_small},
214 {"small", &mface_small},
215 {"normalsize", &mface_normalsize},
216 {"large", &mface_large},
217 {"x-large", &mface_x_large},
218 {"xx-large", &mface_xx_large},
219 {"xxx-large", &face_xxx_large},
221 {"Menu Family", NULL},
222 {"courier", &face_courier},
223 {"helvetica", &face_helvetica},
224 {"times", &face_times},
225 {"dv-ttyogesh", &face_dv_ttyogesh},
226 {"freesans", &face_freesans},
227 {"freeserif", &face_freeserif},
228 {"freemono", &face_freemono},
230 {"Menu Style", NULL},
231 {"medium", &mface_medium},
232 {"bold", &mface_bold},
233 {"italic", &mface_italic},
235 {"Menu Color", NULL},
236 {"black", &mface_black},
237 {"white", &mface_white},
239 {"green", &mface_green},
240 {"blue", &mface_blue},
241 {"cyan", &mface_cyan},
242 {"yello", &mface_yellow},
243 {"magenta", &mface_magenta},
246 {"normal", &mface_normal_video},
247 {"reverse", &mface_reverse_video},
248 {"underline", &mface_underline},
250 {"No CTL", &face_no_ctl_fontset} };
253 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
255 /* Information about a physical line metric. */
258 int from; /* BOL position of the line. */
259 int to; /* BOL position of the next line. */
260 int y0, y1; /* Top and bottom Y position of the line. */
261 int ascent; /* Height of the top Y position. */
264 struct LineInfo top; /* Topmost line. */
265 struct LineInfo cur; /* Line containing cursor. */
266 struct LineInfo sel_start; /* Line containing selection start. */
267 struct LineInfo sel_end; /* Line containing selection end. */
269 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
271 /* X position to keep on vertical (up and down) cursor motion. */
272 int target_x_position;
274 /* Interface macros for m17n-lib drawing routines. */
276 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
277 coordinate ($X, $Y) */
278 #define DRAW_TEXT(x, y, from, to) \
279 mdraw_text_with_control \
280 (frame, (MDrawWindow) win, \
281 control.orientation_reversed ? x + win_width : x, y, \
282 mt, from, to, &control)
284 /* Store the extents of a text in the range $FROM to $TO in the
285 structure $RECT (type MDrawMetric). */
286 #define TEXT_EXTENTS(from, to, rect) \
287 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
289 /* Store the glyph information of a character at the position $POS in
290 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
291 $FROM is written at the coordinate (0, 0). */
292 #define GLYPH_INFO(from, pos, info) \
293 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
295 /* Set $X and $Y to the coordinate of character at position $POS
296 assuming that the text from $FROM is written at the coordinate (0,
298 #define COORDINATES_POSITION(from, pos, x, y) \
299 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
301 /* Interface macros for X library. */
302 #define COPY_AREA(y0, y1, to) \
303 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
305 #define CLEAR_AREA(x, y, w, h) \
306 XClearArea (display, win, (x), (y), (w), (h), False)
308 #define SELECTEDP() \
309 mtext_property_mtext (selection)
311 /* Format MSG by FMT and print the result to the stderr, and exit. */
312 #define FATAL_ERROR(fmt, arg) \
314 fprintf (stderr, fmt, arg); \
319 /* If POS is greater than zero, move POS back to the beginning of line
320 (BOL) position. If FORWARD is nonzero, move POS forward instead.
321 Return the new position. */
323 bol (int pos, int forward)
325 int limit = forward ? nchars : 0;
327 pos = mtext_character (mt, pos, limit, '\n');
328 return (pos < 0 ? limit : pos + 1);
331 /* Update the structure #TOP (struct LineInfo) to make $POS the first
332 character position of the screen. */
336 int from = bol (pos, 0);
339 GLYPH_INFO (from, pos, info);
340 top.from = info.line_from;
341 top.to = info.line_to;
343 top.y1 = info.metrics.height;
344 top.ascent = - info.metrics.y;
348 /* Update the scroll bar so that the text of the range $FROM to $TO
349 are shown on the window. */
351 update_scroll_bar (int from, int to)
353 float top = (float) from / nchars;
354 float shown = (float) (to - from) / nchars;
355 XtArgVal *l_top = (XtArgVal *) ⊤
356 XtArgVal *l_shown = (XtArgVal *) &shown;
358 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
359 XtSetArg (arg[1], XtNshown, *l_shown);
360 XtSetValues (SbarWidget, arg, 2);
364 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
365 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
366 is nonzero, update the scoll bar. */
368 redraw (int y0, int y1, int clear, int scroll_bar)
373 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
374 struct LineInfo *line;
376 if (clear || control.anti_alias)
377 CLEAR_AREA (0, y0, win_width, y1 - y0);
379 /* Find a line closest to y0. It is a cursor line if the cursor is
380 Y0, otherwise the top line. */
385 /* If there exists a selected region, check it too. */
386 if (sel_y0 > line->y0 && y0 >= sel_y0)
391 info.metrics.height = line->y1 - y;
392 info.metrics.y = - line->ascent;
393 info.line_to = line->to;
394 while (y + info.metrics.height <= y0)
396 y += info.metrics.height;
400 GLYPH_INFO (from, from, info);
402 if (y + info.metrics.height <= y0)
405 y0 = y - info.metrics.y;
407 while (to < nchars && y < y1)
409 GLYPH_INFO (to, to, info);
410 y += info.metrics.height;
416 DRAW_TEXT (0, y0, from, to);
421 GLYPH_INFO (to, to, info);
422 if (y + info.metrics.height >= win_height)
425 y += info.metrics.height;
427 update_scroll_bar (top.from, to);
432 /* Set the current input method spot to the correct position. */
434 set_input_method_spot ()
436 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
437 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
440 int size = 0, ratio = 0, i;
443 n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
445 for (i = n - 1; i >= 0; i--)
448 size = (int) mface_get_prop (faces[i], Msize);
450 ratio = (int) mface_get_prop (faces[i], Mratio);
453 size = default_font_size;
455 size = size * ratio / 100;
456 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
457 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
462 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
465 redraw_cursor (int clear)
467 if (control.cursor_bidi)
469 /* We must update the whole line of the cursor. */
470 int beg = bol (cur.from, 0);
471 int end = bol (cur.to - 1, 1);
473 int y0 = cur.y0, y1 = cur.y1;
477 TEXT_EXTENTS (beg, cur.from, rect);
482 TEXT_EXTENTS (cur.to, end, rect);
485 redraw (y0, y1, clear, 0);
493 if (control.orientation_reversed)
494 x += win_width - cursor.logical_width;
495 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
497 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
502 /* Update the information about the location of cursor to the position
503 $POS. If $FULL is nonzero, update the information fully only from
504 the information about the top line. Otherwise, trust the current
505 information in the structure $CUR. */
507 update_cursor (int pos, int full)
513 /* CUR is inaccurate. We can trust only TOP. */
514 GLYPH_INFO (top.from, pos, cursor);
515 cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
517 else if (pos < cur.from)
519 int from = bol (pos, 0);
521 TEXT_EXTENTS (from, cur.from, rect);
522 GLYPH_INFO (from, pos, cursor);
523 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
525 else if (pos < cur.to)
527 GLYPH_INFO (cur.from, pos, cursor);
531 GLYPH_INFO (cur.from, pos, cursor);
532 cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
535 cur.from = cursor.line_from;
536 cur.to = cursor.line_to;
537 cur.y1 = cur.y0 + cursor.metrics.height;
538 cur.ascent = - cursor.metrics.y;
542 /* Update the information about the selected region. */
552 from = mtext_property_start (selection);
553 to = mtext_property_end (selection);
557 int pos = bol (from, 0);
559 TEXT_EXTENTS (pos, top.from, rect);
560 sel_start.y0 = top.y0 - rect.height;
561 sel_start.ascent = - rect.y;
562 GLYPH_INFO (pos, from, info);
563 if (pos < info.line_from)
564 sel_start.y0 += - rect.y + info.y + info.metrics.y;
568 GLYPH_INFO (top.from, from, info);
569 sel_start.y0 = top.ascent + info.y + info.metrics.y;
571 sel_start.ascent = -info.metrics.y;
572 sel_start.y1 = sel_start.y0 + info.metrics.height;
573 sel_start.from = info.line_from;
574 sel_start.to = info.line_to;
576 if (to <= sel_start.to)
582 GLYPH_INFO (sel_start.from, to, info);
583 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
584 sel_end.y1 = sel_end.y0 + info.metrics.height;
585 sel_end.ascent = - info.metrics.y;
586 sel_end.from = info.line_from;
587 sel_end.to = info.line_to;
592 /* Select the text in the region from $FROM to $TO. */
594 select_region (int from, int to)
599 pos = from, from = to, to = pos;
600 mtext_push_property (mt, from, to, selection);
605 /* Setup the window to display the character of $POS at the top left
611 /* Top and bottom Y positions to redraw. */
614 if (pos + 1000 < top.from)
615 y0 = 0, y1 = win_height;
616 else if (pos < top.from)
619 TEXT_EXTENTS (pos, top.from, rect);
620 if (rect.height >= win_height * 0.9)
625 COPY_AREA (0, win_height - y1, y1);
628 else if (pos < top.to)
630 /* No need of redrawing. */
633 else if (pos < top.from + 1000)
635 TEXT_EXTENTS (top.from, pos, rect);
636 if (rect.height >= win_height * 0.9)
640 y0 = win_height - rect.height;
641 COPY_AREA (rect.height, win_height, 0);
646 y0 = 0, y1 = win_height;
652 update_cursor (pos, 1);
654 update_cursor (cursor.from, 1);
656 redraw (y0, y1, 1, 1);
660 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
663 /* Select an input method accoding to $IDX. If $IDX is negative, turn
664 off the current input method, otherwide turn on the input method
665 input_method_table[$IDX]. */
667 select_input_method (idx)
669 int previous_input_method = current_input_method;
671 if (idx == current_input_method)
673 if (current_input_method >= 0)
675 minput_destroy_ic (current_input_context);
676 current_input_context = NULL;
677 current_input_method = -1;
681 && input_method_table[idx].available >= 0)
683 InputMethodInfo *im = input_method_table + idx;
685 if (im->available == 0)
688 im->im = minput_open_im (im->language, im->name, NULL);
691 MInputXIMArgIM arg_xim;
693 arg_xim.display = display;
695 arg_xim.res_name = arg_xim.res_class = NULL;
696 arg_xim.locale = NULL;
697 arg_xim.modifier_list = NULL;
698 im->im = minput_open_im (Mnil, im->name, &arg_xim);
700 im->available = im->im ? 1 : -1;
704 if (im->language == Mnil)
706 MInputXIMArgIC arg_xic;
707 Window win = XtWindow (TextWidget);
709 arg_xic.input_style = 0;
710 arg_xic.client_win = arg_xic.focus_win = win;
711 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
712 current_input_context = minput_create_ic (im->im, &arg_xic);
716 MInputGUIArgIC arg_ic;
718 arg_ic.frame = frame;
719 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
720 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
721 current_input_context = minput_create_ic (im->im, &arg_ic);
724 if (current_input_context)
726 current_input_method = idx;
727 set_input_method_spot ();
731 minput_close_im (im->im);
734 current_input_method = -1;
738 if (! auto_input_method)
740 XtSetArg (arg[0], XtNleftBitmap, None);
741 if (previous_input_method >= 0)
742 XtSetValues (InputMethodMenus[previous_input_method + 2], arg, 1);
744 XtSetValues (InputMethodMenus[0], arg, 1);
745 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
746 if (current_input_method >= 0)
747 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
749 XtSetValues (InputMethodMenus[0], arg, 1);
752 if (current_input_method >= 0)
756 XtSetArg (arg[0], XtNlabel, &label);
757 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
758 XtSetArg (arg[0], XtNlabel, label);
762 XtSetArg (arg[0], XtNlabel, "");
764 XtSetValues (CurIMLang, arg, 1);
767 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
770 /* Display cursor according to the current information of #CUR.
771 $CLIENT_DATA is ignore. Most callback functions add this function
772 as a background processing procedure the current application (by
773 XtAppAddWorkProc) via the function hide_cursor. */
775 show_cursor (XtPointer client_data)
777 MFaceHLineProp *hline;
783 update_cursor (cursor.from, 1);
785 while (cur.y1 > win_height)
788 update_cursor (cursor.from, 1);
791 control.cursor_pos = cursor.from;
794 control.with_cursor = 1;
797 if (current_input_context)
798 set_input_method_spot ();
802 int pos = (SELECTEDP () ? mtext_property_start (selection)
803 : cursor.from > 0 ? cursor.from - 1
805 MFace *face = mface ();
806 MTextProperty *props[256];
807 int n = mtext_get_properties (mt, pos, Mface, props, 256);
809 char buf[256], *p = buf;
815 int size = (int) mfont_get_prop (cursor.font, Msize);
816 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
817 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
818 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
819 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
821 sprintf (p, "%dpt", size / 10), p += strlen (p);
823 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
825 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
827 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
829 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
833 mface_merge (face, face_default);
834 for (i = 0; i < n; i++)
835 if (props[i] != selection)
836 mface_merge (face, (MFace *) mtext_property_value (props[i]));
837 sym = (MSymbol) mface_get_prop (face, Mforeground);
839 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
840 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
841 strcat (p, ",rev"), p += strlen (p);
842 hline = mface_get_prop (face, Mhline);
843 if (hline && hline->width > 0)
844 strcat (p, ",ul"), p += strlen (p);
845 box = mface_get_prop (face, Mbox);
846 if (box && box->width > 0)
847 strcat (p, ",box"), p += strlen (p);
848 m17n_object_unref (face);
850 XtSetArg (arg[0], XtNborderWidth, 1);
851 XtSetArg (arg[1], XtNlabel, buf);
852 XtSetValues (CurFaceWidget, arg, 2);
855 if (control.cursor_pos < nchars)
857 MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
861 XtSetArg (arg[0], XtNborderWidth, 0);
862 XtSetArg (arg[1], XtNlabel, "");
866 XtSetArg (arg[0], XtNborderWidth, 1);
867 XtSetArg (arg[1], XtNlabel,
868 msymbol_name (msymbol_get (sym, Mlanguage)));
869 XtSetValues (CurLangWidget, arg, 2);
871 XtSetValues (CurLangWidget, arg, 2);
873 if (auto_input_method)
876 select_input_method (-1);
881 for (i = 0; i < num_input_methods; i++)
882 if (input_method_table[i].language == sym
883 && input_method_table[i].available >= 0)
885 if (i < num_input_methods)
886 select_input_method (i);
888 select_input_method (-1);
893 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
899 /* Hide the cursor. */
903 control.with_cursor = 0;
905 XtAppAddWorkProc (context, show_cursor, NULL);
909 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
910 $Y1 and $NEW_Y1 assuming that the text in the other area is not
913 update_region (int y0, int old_y1, int new_y1)
919 if (old_y1 < win_height)
921 COPY_AREA (old_y1, win_height, new_y1);
922 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
925 redraw (new_y1, win_height, 1, 0);
927 else if (new_y1 > old_y1)
929 if (new_y1 < win_height)
930 COPY_AREA (old_y1, win_height, new_y1);
932 if (new_y1 > win_height)
934 redraw (y0, new_y1, 1, 1);
938 /* Delete the next $N characters. If $N is negative delete the
939 precious (- $N) characters. */
945 int y0, old_y1, new_y1;
947 int line_from = cursor.line_from;
950 from = cursor.from, to = from + n;
953 from = cursor.from + n;
955 if (cursor.from == cur.from)
957 /* We are at the beginning of line. */
958 int pos = cursor.prev_from;
960 if (cursor.from == top.from)
962 /* We are at the beginning of screen. We must scroll
964 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
965 reseat (info.line_from);
967 update_cursor (pos, 1);
971 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
972 old_y1 = cur.y0 + rect.height;
974 /* Now delete a character. */
975 mtext_del (mt, from, to);
977 if (from >= top.from && from < top.to)
978 update_top (top.from);
979 update_cursor (from, 1);
982 if (line_from != cursor.line_from)
985 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
986 new_y1 = cur.y0 + rect.height;
988 update_region (cur.y0, old_y1, new_y1);
992 /* Insert M-text $NEWTEXT at the current cursor position. */
994 insert_chars (MText *newtext)
996 int n = mtext_len (newtext);
998 int y0, old_y1, new_y1;
1003 int n = (mtext_property_end (selection)
1004 - mtext_property_start (selection));
1005 mtext_detach_property (selection);
1010 if (cursor.line_from > 0
1011 && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
1012 y0 -= control.min_line_descent;
1014 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1015 old_y1 = y0 + rect.height;
1017 line_from = cursor.line_from;
1019 /* Now insert chars. */
1020 mtext_ins (mt, cursor.from, newtext);
1022 if (cur.from == top.from)
1023 update_top (top.from);
1024 update_cursor (cursor.from + n, 1);
1026 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1027 new_y1 = cur.y0 + rect.height;
1029 update_region (y0, old_y1, new_y1);
1030 update_selection ();
1035 word_constituent_p (int c)
1037 MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
1038 char *name = category != Mnil ? msymbol_name (category) : NULL;
1040 return (name && (name[0] == 'L' || name[0] == 'M'));
1047 int pos = cursor.from;
1049 while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
1053 MTextProperty *prop = mtext_get_property (mt, pos, Mword);
1056 pos = mtext_property_end (prop);
1058 while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
1061 update_cursor (pos, 0);
1067 int pos = cursor.from;
1069 while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
1073 MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
1076 pos = mtext_property_start (prop);
1078 while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
1081 update_cursor (pos, 0);
1085 /* Convert the currently selected text to UTF8-STRING or
1086 COMPOUND-TEXT. It is called when someone requests the current
1087 value of the selection. */
1089 covert_selection (Widget w, Atom *selection_atom,
1090 Atom *target, Atom *return_type,
1091 XtPointer *value, unsigned long *length, int *format)
1093 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1094 MText *this_mt = mtext ();
1095 int from = mtext_property_start (selection);
1096 int to = mtext_property_end (selection);
1100 mtext_copy (this_mt, 0, mt, from, to);
1101 if (*target == XA_TEXT)
1103 #ifdef X_HAVE_UTF8_STRING
1104 coding = Mcoding_utf_8;
1105 *return_type = XA_UTF8_STRING;
1107 coding = Mcoding_compound_text;
1108 *return_type = XA_COMPOUND_TEXT;
1111 else if (*target == XA_UTF8_STRING)
1113 coding = Mcoding_utf_8;
1114 *return_type = XA_UTF8_STRING;
1116 else if (*target == XA_STRING)
1121 for (i = 0; i < len; i++)
1122 if (mtext_ref_char (this_mt, i) >= 0x100)
1123 /* Can't encode in XA_STRING */
1125 coding = Mcoding_iso_8859_1;
1126 *return_type = XA_STRING;
1128 else if (*target == XA_COMPOUND_TEXT)
1130 coding = Mcoding_compound_text;
1131 *return_type = XA_COMPOUND_TEXT;
1136 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1137 m17n_object_unref (this_mt);
1141 *value = (XtPointer) buf;
1147 /* Unselect the text. It is called when we loose the selection. */
1149 lose_selection (Widget w, Atom *selection_atom)
1153 mtext_detach_property (selection);
1154 redraw (sel_start.y0, sel_end.y1, 1, 0);
1159 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1160 XtPointer value, unsigned long *length, int *format)
1165 if (*type == XT_CONVERT_FAIL || ! value)
1167 if (*type == XA_STRING)
1169 else if (*type == XA_COMPOUND_TEXT)
1170 coding = msymbol ("compound-text");
1171 #ifdef X_HAVE_UTF8_STRING
1172 else if (*type == XA_UTF8_STRING)
1173 coding = msymbol ("utf-8");
1178 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1179 if (! this_mt && *type != XA_UTF8_STRING)
1181 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1188 insert_chars (this_mt);
1189 m17n_object_unref (this_mt);
1198 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1200 XExposeEvent *expose = (XExposeEvent *) event;
1204 Dimension width_max, width;
1206 XtSetArg (arg[0], XtNwidth, &width);
1207 XtGetValues (XtParent (w), arg, 1);
1209 XtGetValues (HeadWidget, arg, 1);
1210 if (width_max < width)
1212 XtGetValues (FaceWidget, arg, 1);
1213 if (width_max < width)
1215 XtGetValues (LangWidget, arg, 1);
1216 if (width_max < width)
1218 XtSetArg (arg[0], XtNwidth, width_max);
1219 XtSetValues (HeadWidget, arg, 1);
1220 XtSetValues (FaceWidget, arg, 1);
1221 XtSetValues (LangWidget, arg, 1);
1222 XtSetValues (XtParent (w), arg, 1);
1223 XtSetValues (TailWidget, arg, 1);
1226 update_cursor (0, 1);
1227 redraw (0, win_height, 0, 1);
1228 if (current_input_method >= 0)
1230 int idx = current_input_method;
1232 current_input_method = -1;
1233 select_input_method (idx);
1239 redraw (expose->y, expose->y + expose->height, 0, 0);
1240 if (current_input_context
1241 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1242 set_input_method_spot ();
1247 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1249 XConfigureEvent *configure = (XConfigureEvent *) event;
1252 control.max_line_width = win_width = configure->width;
1253 win_height = configure->height;
1254 mdraw_clear_cache (mt);
1256 update_cursor (0, 1);
1257 redraw (0, win_height, 1, 1);
1258 if (current_input_context)
1259 set_input_method_spot ();
1263 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1266 int x = event->xbutton.x;
1267 int y = event->xbutton.y - top.ascent;
1269 if (control.orientation_reversed)
1271 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1274 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1275 mtext_detach_property (selection);
1276 redraw (sel_start.y0, sel_end.y1, 1, 0);
1279 if (current_input_context
1280 && minput_filter (current_input_context, Minput_focus_move, NULL) == 0)
1282 MText *produced = mtext ();
1284 minput_lookup (current_input_context, Mnil, NULL, produced);
1285 if (mtext_len (produced) > 0)
1287 insert_chars (produced);
1288 if (pos >= cursor.from)
1289 pos += mtext_len (produced);
1291 m17n_object_unref (produced);
1293 update_cursor (pos, 0);
1298 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1303 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1304 covert_selection, lose_selection, NULL);
1305 update_cursor (mtext_property_start (selection), 0);
1310 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1314 /* We don't have a local selection. */
1315 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1320 int from = mtext_property_start (selection);
1321 int to = mtext_property_end (selection);
1324 int x = event->xbutton.x;
1325 int y = event->xbutton.y - top.ascent;
1327 if (control.orientation_reversed)
1329 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1331 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1332 mtext_detach_property (selection);
1334 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1335 update_cursor (pos, 0);
1336 insert_chars (this_mt);
1337 m17n_object_unref (this_mt);
1342 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1345 int x = event->xbutton.x;
1346 int y = event->xbutton.y;
1348 if (control.orientation_reversed)
1351 pos = top.from, y -= top.ascent;
1353 pos = cur.from, y -= cur.y0 + cur.ascent;
1354 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1356 if (pos == cursor.from)
1362 /* Selection range changed. */
1363 int from = mtext_property_start (selection);
1364 int to = mtext_property_end (selection);
1365 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1366 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1368 if (cursor.from == from)
1370 /* Starting position changed. */
1373 /* Enlarged. We can simply overdraw. */
1374 select_region (pos, to);
1375 redraw (sel_start.y0, start_y1, 0, 0);
1379 /* Shrunken. Previous selection face must be cleared. */
1380 select_region (pos, to);
1381 redraw (start_y0, sel_start.y1, 1, 0);
1385 /* Shrunken to zero. */
1386 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1387 mtext_detach_property (selection);
1388 redraw (start_y0, end_y1, 1, 0);
1392 /* Full update is necessary. */
1393 select_region (to, pos);
1394 redraw (start_y0, sel_end.y1, 1, 0);
1399 /* Ending position changed. */
1402 /* Full update is necessary. */
1403 select_region (pos, from);
1404 redraw (sel_start.y0, end_y1, 1, 0);
1406 else if (pos == from)
1408 /* Shrunken to zero. */
1409 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1410 mtext_detach_property (selection);
1411 redraw (start_y0, end_y1, 1, 0);
1415 /* Shrunken. Previous selection face must be cleared. */
1416 select_region (from, pos);
1417 redraw (sel_end.y0, end_y1, 1, 0);
1421 /* Enlarged. We can simply overdraw. */
1422 select_region (from, pos);
1423 redraw (end_y0, sel_end.y1, 0, 0);
1429 /* Newly selected. */
1430 select_region (pos, cursor.from);
1431 redraw (sel_start.y0, sel_end.y1, 0, 0);
1433 update_cursor (pos, 1);
1437 FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num)
1439 if (current_input_context
1440 && minput_filter (current_input_context, Minput_focus_in, NULL) == 0)
1442 MText *produced = mtext ();
1444 minput_lookup (current_input_context, Mnil, NULL, produced);
1445 if (mtext_len (produced) > 0)
1448 insert_chars (produced);
1450 m17n_object_unref (produced);
1455 FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num)
1457 if (current_input_context
1458 && minput_filter (current_input_context, Minput_focus_out, NULL) == 0)
1460 MText *produced = mtext ();
1462 minput_lookup (current_input_context, Mnil, NULL, produced);
1463 if (mtext_len (produced) > 0)
1466 insert_chars (produced);
1468 m17n_object_unref (produced);
1473 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1476 MDrawGlyphInfo info;
1478 int cursor_pos = cursor.from;
1480 if (((int) position) < 0)
1486 height = top.y1 - top.y0;
1489 pos = bol (from - 1, 0);
1490 GLYPH_INFO (pos, from - 1, info);
1491 if (height + info.metrics.height > win_height)
1493 height += info.metrics.height;
1494 from = info.line_from;
1496 if (cursor_pos >= top.to)
1498 cursor_pos = top.from;
1500 while (cursor_pos < nchars)
1502 GLYPH_INFO (pos, pos, info);
1503 if (height + info.metrics.height > win_height)
1505 height += info.metrics.height;
1511 else if (cur.to < nchars)
1513 /* Scroll up, but leave at least one line. */
1516 while (from < nchars)
1518 GLYPH_INFO (from, from, info);
1519 if (height + info.metrics.height > win_height
1520 || info.line_to >= nchars)
1522 height += info.metrics.height;
1523 from = info.line_to;
1526 from = info.line_from;
1527 if (cursor_pos < from)
1531 /* Scroll up to make the cursor line top. */
1535 update_cursor (cursor_pos, 1);
1539 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1541 float persent = *(float *) persent_ptr;
1542 int pos1, pos2 = nchars * persent;
1543 MDrawGlyphInfo info;
1546 pos1 = bol (pos2, 0);
1547 GLYPH_INFO (pos1, pos2, info);
1548 pos1 = info.line_from;
1550 update_cursor (pos1, 1);
1555 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1557 XKeyEvent *key_event = (XKeyEvent *) event;
1559 KeySym keysym = NoSymbol;
1561 /* If set to 1, do not update target_x_position. */
1562 int keep_target_x_position = 0;
1565 if (current_input_context
1566 && minput_filter (current_input_context, Mnil, event))
1568 if (event->type == KeyRelease)
1573 produced = mtext ();
1574 ret = minput_lookup (current_input_context, Mnil, event, produced);
1575 if (mtext_len (produced) > 0)
1576 insert_chars (produced);
1578 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1579 m17n_object_unref (produced);
1589 n = (mtext_property_end (selection)
1590 - mtext_property_start (selection));
1591 mtext_detach_property (selection);
1593 else if (cursor.from < nchars)
1595 /* Delete the following grapheme cluster. */
1596 n = cursor.to - cursor.from;
1609 /* Delete selected region. */
1610 n = (mtext_property_end (selection)
1611 - mtext_property_start (selection));
1612 mtext_detach_property (selection);
1614 else if (cursor.from > 0)
1616 /* Delete the preceding character. */
1627 mtext_detach_property (selection);
1628 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1632 if (cursor.prev_from >= 0)
1633 update_cursor (cursor.prev_from, 0);
1637 if (cursor.left_from >= 0)
1638 update_cursor (cursor.left_from, 0);
1645 mtext_detach_property (selection);
1646 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1650 if (cursor.next_to >= 0)
1651 update_cursor (cursor.to, 0);
1655 if (cursor.right_from >= 0)
1656 update_cursor (cursor.right_from, 0);
1663 mtext_detach_property (selection);
1664 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1666 if (cur.to <= nchars)
1668 MDrawGlyphInfo info;
1671 GLYPH_INFO (cur.from, cur.to, info);
1672 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1673 target_x_position, info.y);
1674 keep_target_x_position = 1;
1675 update_cursor (pos, 0);
1682 mtext_detach_property (selection);
1683 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1689 int pos = bol (cur.from - 1, 0);
1691 TEXT_EXTENTS (pos, cur.from - 1, rect);
1692 y = rect.height + rect.y - 1;
1693 pos = COORDINATES_POSITION (pos, nchars,
1694 target_x_position, y);
1695 keep_target_x_position = 1;
1696 update_cursor (pos, 0);
1703 mtext_detach_property (selection);
1704 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1706 if (top.from < nchars)
1707 ScrollProc (w, NULL, (XtPointer) 1);
1713 mtext_detach_property (selection);
1714 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1717 ScrollProc (w, NULL, (XtPointer) -1);
1721 if (key_event->state >= Mod1Mask)
1723 lose_selection (NULL, NULL);
1729 if (key_event->state >= Mod1Mask)
1731 lose_selection (NULL, NULL);
1739 if (buf[0] == 17) /* C-q */
1741 XtAppSetExitFlag (context);
1744 else if (buf[0] == 12) /* C-l */
1746 redraw (0, win_height, 1, 1);
1751 MText *temp = mtext ();
1753 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1754 : ((unsigned char *) buf)[0]);
1755 if (current_input_context)
1756 mtext_put_prop (temp, 0, 1, Mlanguage,
1757 current_input_context->im->language);
1758 insert_chars (temp);
1759 m17n_object_unref (temp);
1764 if (! keep_target_x_position)
1765 target_x_position = cursor.x;
1769 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1771 char *name = (char *) client_data;
1773 int from = -1, to = 0;
1778 filename = strdup (name);
1781 fp = fopen (filename, "w");
1784 fprintf (stderr, "Open for write fail: %s", filename);
1790 from = mtext_property_start (selection);
1791 to = mtext_property_end (selection);
1792 mtext_detach_property (selection);
1795 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1798 select_region (from, to);
1802 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1808 mtext_detach_property (selection);
1809 serialized = (int) client_data;
1811 new = mtext_deserialize (mt);
1814 MPlist *plist = mplist ();
1816 mplist_push (plist, Mt, Mface);
1817 mplist_push (plist, Mt, Mlanguage);
1818 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1819 m17n_object_unref (plist);
1823 m17n_object_unref (mt);
1825 serialized = ! serialized;
1826 nchars = mtext_len (mt);
1829 update_cursor (0, 1);
1830 redraw (0, win_height, 1, 1);
1834 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1836 XtAppSetExitFlag (context);
1842 FILE *fp = fopen (filename, "r");
1845 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1846 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1849 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1854 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1856 int data = (int) client_data;
1861 control.enable_bidi = 0;
1862 control.orientation_reversed = 0;
1866 control.enable_bidi = 1;
1867 control.orientation_reversed = data == 2;
1869 for (i = 0; i < 3; i++)
1872 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1874 XtSetArg (arg[0], XtNleftBitmap, None);
1875 XtSetValues (BidiMenus[i], arg, 1);
1878 update_cursor (cursor.from, 1);
1879 redraw (0, win_height, 1, 0);
1883 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1885 int data = (int) client_data;
1889 control.max_line_width = 0;
1892 control.max_line_width = win_width;
1893 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1895 for (i = 0; i < 3; i++)
1898 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1900 XtSetArg (arg[0], XtNleftBitmap, None);
1901 XtSetValues (LineBreakMenus[i], arg, 1);
1904 update_cursor (cursor.from, 1);
1905 redraw (0, win_height, 1, 0);
1909 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1911 char *filter_module = (char *) client_data;
1913 void (*func) (MText *, int, int);
1917 handle = dlopen (filter_module, RTLD_NOW);
1920 *(void **) (&func) = dlsym (handle, "filter");
1922 (*func) (mt, mtext_property_start (selection),
1923 mtext_property_end (selection));
1928 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1930 int data = (int) client_data;
1944 control.cursor_bidi = 0, control.cursor_width = -1;
1948 control.cursor_bidi = 0, control.cursor_width = 2;
1952 control.cursor_bidi = 1;
1957 for (i = from; i < to; i++)
1960 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1962 XtSetArg (arg[0], XtNleftBitmap, None);
1963 XtSetValues (CursorMenus[i], arg, 1);
1966 update_cursor (cursor.from, 0);
1967 redraw (0, win_height, 1, 0);
1971 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1973 int idx = (int) client_data;
1975 if (idx == -2 ? (! auto_input_method && current_input_method < 0)
1976 : idx == -1 ? auto_input_method
1977 : idx == current_input_method)
1980 if (auto_input_method)
1982 select_input_method (-1);
1983 XtSetArg (arg[0], XtNleftBitmap, None);
1984 XtSetValues (InputMethodMenus[1], arg, 1);
1985 auto_input_method = 0;
1990 select_input_method (-1);
1991 XtSetArg (arg[0], XtNleftBitmap, None);
1992 XtSetValues (InputMethodMenus[0], arg, 1);
1993 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1994 XtSetValues (InputMethodMenus[1], arg, 1);
1995 auto_input_method = 1;
2000 select_input_method (idx);
2004 MPlist *default_face_list;
2007 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
2009 int idx = (int) client_data;
2020 MFace *face = mframe_get_prop (frame, Mface);
2022 for (plist = default_face_list; mplist_key (plist) != Mnil;
2023 plist = mplist_next (plist))
2024 mface_merge (face, mplist_value (plist));
2025 mplist_add (plist, Mt, *face_table[idx].face);
2026 mface_merge (face, *face_table[idx].face);
2028 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
2030 MFace *face = mframe_get_prop (frame, Mface);
2032 for (plist = default_face_list;
2033 mplist_key (mplist_next (plist)) != Mnil;
2034 plist = mplist_next (plist))
2035 mface_merge (face, mplist_value (plist));
2039 update_cursor (0, 1);
2040 redraw (0, win_height, 1, 1);
2045 XtAppAddWorkProc (context, show_cursor, NULL);
2046 from = mtext_property_start (selection);
2047 to = mtext_property_end (selection);
2048 old_y1 = sel_end.y1;
2050 mtext_detach_property (selection);
2053 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
2054 MTEXTPROP_REAR_STICKY);
2055 mtext_push_property (mt, from, to, prop);
2056 m17n_object_unref (prop);
2059 mtext_pop_prop (mt, from, to, Mface);
2061 update_top (top.from);
2062 update_cursor (cursor.from, 1);
2063 select_region (from, to);
2064 update_region (sel_start.y0, old_y1, sel_end.y1);
2065 if (cur.y1 > win_height)
2067 while (cur.y1 > win_height)
2070 update_cursor (cursor.from, 1);
2076 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2078 MSymbol sym = (MSymbol) client_data;
2085 XtAppAddWorkProc (context, show_cursor, NULL);
2086 from = mtext_property_start (selection);
2087 to = mtext_property_end (selection);
2088 old_y1 = sel_end.y1;
2090 mtext_detach_property (selection);
2092 mtext_put_prop (mt, from, to, Mlanguage, sym);
2094 mtext_pop_prop (mt, from, to, Mlanguage);
2097 update_top (top.from);
2098 update_cursor (cursor.from, 1);
2099 select_region (from, to);
2100 update_region (sel_start.y0, old_y1, sel_end.y1);
2101 if (cur.y1 > win_height)
2103 while (cur.y1 > win_height)
2106 update_cursor (cursor.from, 1);
2112 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2114 int narrowed = (int) client_data;
2117 MConverter *converter;
2123 from = mtext_property_start (selection);
2124 to = mtext_property_end (selection);
2133 mdump = popen ("mdump -q -p a4", "w");
2135 mdump = popen ("mdump -q", "w");
2138 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2139 mconv_encode_range (converter, mt, from, to);
2140 mconv_free_converter (converter);
2145 input_status (MInputContext *ic, MSymbol command)
2147 XFillRectangle (display, input_status_pixmap, gc_inv,
2148 0, 0, input_status_width, input_status_height);
2149 if (command == Minput_status_draw)
2153 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2154 Mface, face_input_status);
2155 if (ic->im->language != Mnil)
2156 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2157 Mlanguage, ic->im->language);
2158 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2159 &input_status_control, NULL, NULL, &rect);
2160 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2161 input_status_width - rect.width - 2, - rect.y,
2162 ic->status, 0, mtext_len (ic->status),
2163 &input_status_control);
2165 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2166 XtSetValues (CurIMStatus, arg, 1);
2170 surrounding_text_handler (MInputContext *ic, MSymbol command)
2172 if (command == Minput_get_surrounding_text)
2174 int len = (int) mplist_value (ic->plist);
2176 MText *surround = NULL;
2180 pos = cursor.from + len;
2183 surround = mtext_duplicate (mt, pos, cursor.from);
2187 pos = cursor.from + len;
2190 surround = mtext_duplicate (mt, cursor.from, pos);
2194 mplist_set (ic->plist, Mtext, surround);
2195 m17n_object_unref (surround);
2198 else if (command == Minput_delete_surrounding_text)
2200 int len = (int) mplist_value (ic->plist);
2204 if (cursor.from + len < 0)
2205 len = - cursor.from;
2206 mtext_del (mt, cursor.from + len, cursor.from);
2211 if (cursor.from + len > nchars)
2212 len = nchars - cursor.from;
2213 mtext_del (mt, cursor.from, cursor.from + len);
2219 compare_input_method (const void *elt1, const void *elt2)
2221 const InputMethodInfo *im1 = elt1;
2222 const InputMethodInfo *im2 = elt2;
2223 MSymbol lang1, lang2;
2225 if (im1->language == Mnil)
2227 if (im1->language == im2->language)
2228 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2229 if (im1->language == Mt)
2231 if (im2->language == Mt)
2233 lang1 = msymbol_get (im1->language, Mlanguage);
2234 lang2 = msymbol_get (im2->language, Mlanguage);
2235 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2239 setup_input_methods (int with_xim, char *initial_input_method)
2241 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2245 num_input_methods = plist ? mplist_length (plist) : 0;
2247 num_input_methods++;
2248 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2253 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
2255 MDatabase *mdb = mplist_value (pl);
2256 MSymbol *tag = mdatabase_tag (mdb);
2259 i--, num_input_methods--;
2262 input_method_table[i].language = tag[1];
2263 input_method_table[i].name = tag[2];
2266 m17n_object_unref (plist);
2270 input_method_table[i].language = Mnil;
2271 input_method_table[i].name = msymbol ("xim");
2275 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2276 compare_input_method);
2277 mplist_put (minput_driver->callback_list, Minput_status_start,
2278 (void *) input_status);
2279 mplist_put (minput_driver->callback_list, Minput_status_draw,
2280 (void *) input_status);
2281 mplist_put (minput_driver->callback_list, Minput_status_done,
2282 (void *) input_status);
2283 mplist_put (minput_driver->callback_list, Minput_get_surrounding_text,
2284 (void *) surrounding_text_handler);
2285 mplist_put (minput_driver->callback_list, Minput_delete_surrounding_text,
2286 (void *) surrounding_text_handler);
2288 current_input_context = NULL;
2289 current_input_method = -1;
2291 if (initial_input_method)
2293 char *lang_name, *method_name;
2294 char *p = strchr (initial_input_method, '-');
2297 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2299 lang_name = "t", method_name = initial_input_method;
2301 for (i = 0; i < num_input_methods; i++)
2302 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2304 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2306 current_input_method = i;
2314 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2318 if (num && *num > 0)
2322 for (i = 0; i < *num; i++)
2323 bytes += strlen (str[i]) + 1;
2324 msg = alloca (bytes);
2325 strcpy (msg, str[0]);
2326 for (i = 1; i < *num; i++)
2327 strcat (msg, " "), strcat (msg, str[i]);
2329 else if (cursor.from < nchars)
2331 int c = mtext_ref_char (mt, cursor.from);
2332 char *name = mchar_get_prop (c, Mname);
2336 msg = alloca (10 + strlen (name));
2337 sprintf (msg, "U+%04X %s", c, name);
2343 XtSetArg (arg[0], XtNlabel, msg);
2344 XtSetValues (MessageWidget, arg, 1);
2350 char *name1, *name2;
2351 XtCallbackProc proc;
2352 XtPointer client_data;
2357 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2359 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2361 MenuRec FileMenu[] =
2362 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2363 { 0, "Save", NULL, SaveProc, NULL, -1 },
2364 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2366 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2367 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2369 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2370 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2372 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2375 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2377 MenuRec *rec = (MenuRec *) client_data;
2380 XtSetArg (arg[0], XtNvalue, "");
2381 XtSetArg (arg[1], XtNlabel, rec->name1);
2382 XtSetValues (FileDialogWidget, arg, 2);
2383 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2384 XtSetArg (arg[0], XtNx, x + 20);
2385 XtSetArg (arg[1], XtNy, y + 10);
2386 XtSetValues (FileShellWidget, arg, 2);
2387 XtPopup (FileShellWidget, XtGrabExclusive);
2391 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2396 XtPopdown (FileShellWidget);
2397 if ((int) client_data == 1)
2399 XtSetArg (arg[0], XtNlabel, &label);
2400 XtGetValues (FileDialogWidget, arg, 1);
2401 if (strcmp (label, FileMenu[0].name1) == 0)
2405 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2406 fp = fopen (filename, "r");
2408 m17n_object_unref (mt);
2411 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2419 nchars = mtext_len (mt);
2421 update_cursor (0, 1);
2422 redraw (0, win_height, 1, 1);
2424 else if (strcmp (label, FileMenu[2].name1) == 0)
2425 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2427 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2430 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2431 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2432 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2433 (MENU).status = (STATUS))
2437 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2438 char *menu_name, MenuRec *menus, int num_menus, char *help)
2440 Widget button, menu;
2441 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2442 <LeaveWindow>: reset() MenuHelp()\n\
2443 <BtnDown>: reset() PopupMenu()\n\
2444 <BtnUp>: highlight()";
2450 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2451 for (i = 0; i < num_menus; i++)
2462 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2464 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2466 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2468 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2472 XtSetArg (arg[0], XtNsensitive, False);
2473 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2479 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2484 trans = alloca (strlen (fmt) + strlen (help));
2485 sprintf (trans, fmt, help);
2486 XtSetArg (arg[0], XtNmenuName, menu_name);
2487 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2488 XtSetArg (arg[2], XtNinternalWidth, 2);
2489 XtSetArg (arg[3], XtNhighlightThickness, 1);
2490 XtSetArg (arg[4], XtNleft, XawChainLeft);
2491 XtSetArg (arg[5], XtNright, XawChainLeft);
2494 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2495 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2500 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2501 int *len = alloca (sizeof (int) * num_menus);
2504 XFontSetExtents *fontset_extents;
2506 XtSetArg (arg[0], XtNfontSet, &font_set);
2507 XtGetValues (button, arg, 1);
2509 fontset_extents = XExtentsOfFontSet (font_set);
2510 height = fontset_extents->max_logical_extent.height;
2511 ascent = - fontset_extents->max_logical_extent.y;
2513 for (i = 0; i < num_menus; i++)
2516 len[i] = strlen (menus[i].name2);
2517 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2518 if (max_width < width[i])
2519 max_width = width[i];
2521 for (i = 0; i < num_menus; i++)
2524 Pixmap pixmap = XCreatePixmap (display,
2525 RootWindow (display, screen),
2526 max_width, height, 1);
2527 XFillRectangle (display, pixmap, mono_gc_inv,
2528 0, 0, max_width, height);
2529 XmbDrawString (display, pixmap, font_set, mono_gc,
2530 max_width - width[i], ascent,
2531 menus[i].name2, len[i]);
2532 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2533 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2534 XtSetValues (menus[i].w, arg, 2);
2542 XtActionsRec actions[] = {
2543 {"Expose", ExposeProc},
2544 {"Configure", ConfigureProc},
2546 {"ButtonPress", ButtonProc},
2547 {"ButtonRelease", ButtonReleaseProc},
2548 {"ButtonMotion", ButtonMoveProc},
2549 {"Button2Press", Button2Proc},
2550 {"MenuHelp", MenuHelpProc},
2551 {"FocusIn", FocusInProc},
2552 {"FocusOut", FocusOutProc}
2556 /* Print the usage of this program (the name is PROG), and exit with
2560 help_exit (char *prog, int exit_code)
2568 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2569 printf ("Display FILE on a window and allow users to edit it.\n");
2570 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2571 printf ("The following OPTIONs are available.\n");
2572 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2573 "Use the specified fontset\n");
2574 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2575 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2576 "Input method activated initially.\n");
2577 printf (" %-13s %s", "--version", "print version number\n");
2578 printf (" %-13s %s", "-h, --help", "print this message\n");
2584 main (int argc, char **argv)
2586 Widget form, BodyWidget, w;
2587 char *fontset_name = NULL;
2589 char *initial_input_method = NULL;
2590 int col = 80, row = 32;
2591 /* Translation table for TextWidget. */
2592 String trans = "<Expose>: Expose()\n\
2593 <Configure>: Configure()\n\
2596 <Btn1Down>: ButtonPress()\n\
2597 <Btn1Up>: ButtonRelease()\n\
2598 <Btn1Motion>: ButtonMotion()\n\
2599 <Btn2Down>: Button2Press()";
2600 /* Translation table for the top form widget. */
2601 String trans2 = "<Key>: Key()\n\
2603 <FocusIn>: FocusIn()\n\
2604 <FocusOut>: FocusOut()";
2605 String pop_face_trans
2606 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2607 <LeaveWindow>: MenuHelp() reset()\n\
2608 <Btn1Down>: set()\n\
2609 <Btn1Up>: notify() unset()";
2610 String pop_lang_trans
2611 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2612 <LeaveWindow>: MenuHelp() reset()\n\
2613 <Btn1Down>: set()\n\
2614 <Btn1Up>: notify() unset()";
2615 int font_width, font_ascent, font_descent;
2618 char *filter = NULL;
2620 setlocale (LC_ALL, "");
2621 /* Create the top shell. */
2622 XtSetLanguageProc (NULL, NULL, NULL);
2623 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2624 NULL, sessionShellWidgetClass, NULL, 0);
2625 display = XtDisplay (ShellWidget);
2626 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2628 /* Parse the remaining command line arguments. */
2629 for (i = 1; i < argc; i++)
2631 if (! strcmp (argv[i], "--help")
2632 || ! strcmp (argv[i], "-h"))
2633 help_exit (argv[0], 0);
2634 else if (! strcmp (argv[i], "--version"))
2636 printf ("m17n-edit (m17n library) %s\n", VERSION);
2637 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2640 else if (! strcmp (argv[i], "--geometry"))
2643 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2644 help_exit (argv[0], 1);
2646 else if (! strcmp (argv[i], "-s"))
2649 fontsize = atoi (argv[i]);
2653 else if (! strcmp (argv[i], "--fontset"))
2656 fontset_name = strdup (argv[i]);
2658 else if (! strcmp (argv[i], "--im"))
2661 initial_input_method = strdup (argv[i]);
2663 else if (! strcmp (argv[i], "--with-xim"))
2667 else if (! strcmp (argv[i], "--filter"))
2672 else if (argv[i][0] != '-')
2674 filename = strdup (argv[i]);
2678 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2679 help_exit (argv[0], 1);
2683 filename = strdup ("/dev/null");
2685 mdatabase_dir = ".";
2686 /* Initialize the m17n library. */
2688 if (merror_code != MERROR_NONE)
2689 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2690 minput_driver = &minput_gui_driver;
2692 mt = read_file (filename);
2695 nchars = mtext_len (mt);
2697 Mword = msymbol ("word");
2700 MFace *face = mface ();
2702 mface_put_prop (face, Mforeground, msymbol ("blue"));
2703 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2704 mface_put_prop (face, Mvideomode, Mreverse);
2705 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2706 m17n_object_unref (face);
2709 /* This tells ExposeProc to initialize everything. */
2712 XA_TEXT = XInternAtom (display, "TEXT", False);
2713 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2714 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2715 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2716 if (Mcoding_compound_text == Mnil)
2717 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2720 MPlist *plist = mplist ();
2724 mplist_put (plist, msymbol ("widget"), ShellWidget);
2725 if (fontset_name || fontsize > 0)
2727 MFontset *fontset = mfontset (fontset_name);
2730 mface_put_prop (face, Mfontset, fontset);
2731 mface_put_prop (face, Msize, (void *) fontsize);
2732 m17n_object_unref (fontset);
2733 mplist_add (plist, Mface, face);
2734 m17n_object_unref (face);
2736 frame = mframe (plist);
2738 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2739 m17n_object_unref (plist);
2740 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2741 default_face_list = mplist ();
2742 mplist_add (default_face_list, Mt, face_default);
2743 face_default_fontset = mface ();
2744 mface_put_prop (face_default_fontset, Mfontset,
2745 mface_get_prop (face_default, Mfontset));
2747 font = (MFont *) mframe_get_prop (frame, Mfont);
2748 default_font_size = (int) mfont_get_prop (font, Msize);
2751 font_width = (int) mframe_get_prop (frame, Mfont_width);
2752 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2753 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2754 win_width = font_width * col;
2755 win_height = (font_ascent + font_descent) * row;
2761 prop.color_top = prop.color_left = msymbol ("magenta");
2762 prop.color_bottom = prop.color_right = msymbol ("red");
2763 prop.inner_hmargin = prop.inner_vmargin = 1;
2764 prop.outer_hmargin = prop.outer_vmargin = 2;
2766 face_box = mface ();
2767 mface_put_prop (face_box, Mbox, &prop);
2770 face_courier = mface ();
2771 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2772 face_helvetica = mface ();
2773 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2774 face_times = mface ();
2775 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2776 face_dv_ttyogesh = mface ();
2777 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2778 face_freesans = mface ();
2779 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2780 face_freeserif = mface ();
2781 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2782 face_freemono = mface ();
2783 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2785 face_xxx_large = mface ();
2786 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2788 MFont *latin_font = mframe_get_prop (frame, Mfont);
2789 MFont *dev_font = mfont ();
2790 MFont *thai_font = mfont ();
2791 MFont *tib_font = mfont ();
2792 MFontset *fontset, *fontset_no_ctl;
2793 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2794 MSymbol no_ctl = msymbol ("no-ctl");
2796 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2797 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2798 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2799 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2800 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2801 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2803 fontset = mfontset (fontset_name);
2804 fontset_no_ctl = mfontset_copy (fontset, "no-ctl");
2805 m17n_object_unref (fontset);
2806 mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil,
2807 latin_font, Mnil, 0);
2808 mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil,
2809 dev_font, no_ctl, 0);
2810 mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil,
2811 thai_font, no_ctl, 0);
2812 mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil,
2813 tib_font, no_ctl, 0);
2814 face_no_ctl_fontset = mface ();
2815 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl);
2816 m17n_object_unref (fontset_no_ctl);
2823 setup_input_methods (with_xim, initial_input_method);
2825 gc = DefaultGC (display, screen);
2827 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2828 XtSetArg (arg[1], XtNdefaultDistance, 2);
2829 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2831 XtSetArg (arg[0], XtNborderWidth, 0);
2832 XtSetArg (arg[1], XtNdefaultDistance, 2);
2833 XtSetArg (arg[2], XtNtop, XawChainTop);
2834 XtSetArg (arg[3], XtNbottom, XawChainTop);
2835 XtSetArg (arg[4], XtNleft, XawChainLeft);
2836 XtSetArg (arg[5], XtNright, XawChainRight);
2837 XtSetArg (arg[6], XtNresizable, True);
2838 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2839 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2840 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2841 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2842 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2843 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2844 XtSetArg (arg[7], XtNfromVert, LangWidget);
2845 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2846 XtSetArg (arg[2], XtNtop, XawChainBottom);
2847 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2848 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2850 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2851 HeadWidget, NULL, 0);
2852 XtSetArg (arg[0], XtNvalue, "");
2853 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2854 FileShellWidget, arg, 1);
2855 XawDialogAddButton (FileDialogWidget, "OK",
2856 FileDialogProc, (XtPointer) 0);
2857 XawDialogAddButton (FileDialogWidget, "CANCEL",
2858 FileDialogProc, (XtPointer) 1);
2860 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2861 (char *) check_bits,
2862 check_width, check_height);
2864 unsigned long valuemask = GCForeground;
2867 values.foreground = 1;
2868 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2869 values.foreground = 0;
2870 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2877 if (num_menus < num_input_methods + 2)
2878 num_menus = num_input_methods + 2;
2879 if (num_menus < num_faces + 1)
2880 num_menus = num_faces + 1;
2881 menus = alloca (sizeof (MenuRec) * num_menus);
2883 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2884 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2885 "File I/O, Serialization, Image, Quit");
2887 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2888 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2889 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2890 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2891 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2892 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2893 w = create_menu_button (ShellWidget, HeadWidget, w,
2894 "Cursor", "Cursor Menu",
2895 menus, 6, "Cursor Movement Mode, Cursor Shape");
2896 CursorMenus[0] = menus[0].w;
2897 CursorMenus[1] = menus[1].w;
2898 CursorMenus[2] = menus[3].w;
2899 CursorMenus[3] = menus[4].w;
2900 CursorMenus[4] = menus[5].w;
2902 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2903 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2904 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2905 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2906 menus, 3, "BIDI Processing Mode");
2907 for (i = 0; i < 3; i++)
2908 BidiMenus[i] = menus[i].w;
2910 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2911 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2912 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2913 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2915 menus, 3, "How to break lines");
2916 for (i = 0; i < 3; i++)
2917 LineBreakMenus[i] = menus[i].w;
2919 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2920 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2921 for (i = 0; i < num_input_methods; i++)
2923 InputMethodInfo *im = input_method_table + i;
2924 char *name1, *name2;
2926 if (im->language != Mnil && im->language != Mt)
2928 MSymbol sym = msymbol_get (im->language, Mlanguage);
2930 name1 = msymbol_name (im->language);
2932 name1 = msymbol_name (sym);
2933 name2 = msymbol_name (im->name);
2936 name1 = msymbol_name (im->name), name2 = NULL;
2938 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2940 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2941 "Input Method Menu", menus, i + 2,
2942 "Select input method");
2945 unsigned long valuemask = GCForeground;
2948 XtSetArg (arg[0], XtNbackground, &values.foreground);
2949 XtGetValues (w, arg, 1);
2950 gc_inv = XCreateGC (display, RootWindow (display, screen),
2951 valuemask, &values);
2954 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2955 for (i = 0; i < num_input_methods + 2; i++)
2956 InputMethodMenus[i] = menus[i].w;
2960 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2961 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2962 "Filter Menu", menus, 1,
2963 "Select filter to run");
2966 input_status_width = font_width * 8;
2967 input_status_height = (font_ascent + font_descent) * 2.4;
2968 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2970 input_status_height,
2971 DefaultDepth (display, screen));
2976 prop.color_top = prop.color_bottom
2977 = prop.color_left = prop.color_right = Mnil;
2978 prop.inner_hmargin = prop.inner_vmargin = 1;
2979 prop.outer_hmargin = prop.outer_vmargin = 0;
2980 face_input_status = mface_copy (face_default);
2981 mface_put_prop (face_input_status, Mbox, &prop);
2984 XFillRectangle (display, input_status_pixmap, gc_inv,
2985 0, 0, input_status_width, input_status_height);
2986 XtSetArg (arg[0], XtNfromHoriz, w);
2987 XtSetArg (arg[1], XtNleft, XawRubber);
2988 XtSetArg (arg[2], XtNright, XawChainRight);
2989 XtSetArg (arg[3], XtNborderWidth, 0);
2990 XtSetArg (arg[4], XtNlabel, " ");
2991 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2992 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2993 HeadWidget, arg, 6);
2994 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2995 XtSetArg (arg[1], XtNleft, XawChainRight);
2996 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2997 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2998 HeadWidget, arg, 5);
3000 XtSetArg (arg[0], XtNborderWidth, 0);
3001 XtSetArg (arg[1], XtNleft, XawChainLeft);
3002 XtSetArg (arg[2], XtNright, XawChainLeft);
3003 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
3004 for (i = 0; i < num_faces;)
3006 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
3007 char *label = label_menu + 5; /* "Xxxx" */
3009 for (j = i; j < num_faces && face_table[j].face; j++)
3010 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
3012 w = create_menu_button (ShellWidget, FaceWidget, w,
3014 menus, j - i, "Push face property");
3018 XtSetArg (arg[0], XtNfromHoriz, w);
3019 XtSetArg (arg[1], XtNleft, XawChainLeft);
3020 XtSetArg (arg[2], XtNright, XawChainLeft);
3021 XtSetArg (arg[3], XtNhorizDistance, 10);
3022 XtSetArg (arg[4], XtNlabel, "Pop");
3023 XtSetArg (arg[5], XtNtranslations,
3024 XtParseTranslationTable (pop_face_trans));
3025 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
3026 FaceWidget, arg, 6);
3027 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
3029 XtSetArg (arg[0], XtNfromHoriz, w);
3030 XtSetArg (arg[1], XtNleft, XawChainLeft);
3031 XtSetArg (arg[2], XtNright, XawChainRight);
3032 XtSetArg (arg[3], XtNlabel, "");
3033 XtSetArg (arg[4], XtNborderWidth, 0);
3034 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3035 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
3036 FaceWidget, arg, 6);
3038 XtSetArg (arg[0], XtNborderWidth, 0);
3039 XtSetArg (arg[1], XtNleft, XawChainLeft);
3040 XtSetArg (arg[2], XtNright, XawChainLeft);
3041 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
3043 MPlist *plist[11], *pl;
3046 for (i = 0; i < 11; i++) plist[i] = NULL;
3048 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
3049 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
3051 MSymbol sym = msymbol_exist (langname);
3055 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
3057 char *name = msymbol_name (fullname);
3060 if (c >= 'a' && c <= 'z')
3062 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
3066 pl = plist[idx] = mplist ();
3067 for (; mplist_next (pl); pl = mplist_next (pl))
3068 if (strcmp (name, (char *) mplist_value (pl)) < 0)
3070 mplist_push (pl, sym, fullname);
3075 for (i = 0; i < 11; i++)
3078 char *name = alloca (9);
3080 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
3083 for (j = 0, pl = plist[i]; mplist_next (pl);
3084 j++, pl = mplist_next (pl))
3085 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
3086 msymbol_name (mplist_key (pl)),
3087 LangProc, mplist_key (pl), -1);
3088 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
3089 menus, j, "Push language property");
3091 for (i = 0; i < 11; i++)
3093 m17n_object_unref (plist[i]);
3095 XtSetArg (arg[0], XtNfromHoriz, w);
3096 XtSetArg (arg[1], XtNleft, XawChainLeft);
3097 XtSetArg (arg[2], XtNright, XawChainLeft);
3098 XtSetArg (arg[3], XtNhorizDistance, 10);
3099 XtSetArg (arg[4], XtNlabel, "Pop");
3100 XtSetArg (arg[5], XtNtranslations,
3101 XtParseTranslationTable (pop_lang_trans));
3102 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3103 LangWidget, arg, 6);
3104 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3106 XtSetArg (arg[0], XtNfromHoriz, w);
3107 XtSetArg (arg[1], XtNleft, XawChainLeft);
3108 XtSetArg (arg[2], XtNright, XawChainRight);
3109 XtSetArg (arg[3], XtNlabel, "");
3110 XtSetArg (arg[4], XtNborderWidth, 0);
3111 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3112 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3113 LangWidget, arg, 6);
3116 XtSetArg (arg[0], XtNheight, win_height);
3117 XtSetArg (arg[1], XtNwidth, 10);
3118 XtSetArg (arg[2], XtNleft, XawChainLeft);
3119 XtSetArg (arg[3], XtNright, XawChainLeft);
3120 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3122 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3123 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3125 XtSetArg (arg[0], XtNheight, win_height);
3126 XtSetArg (arg[1], XtNwidth, win_width);
3127 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3128 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3129 XtSetArg (arg[4], XtNleft, XawChainLeft);
3130 XtSetArg (arg[5], XtNright, XawChainRight);
3131 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3134 XtSetArg (arg[0], XtNborderWidth, 0);
3135 XtSetArg (arg[1], XtNleft, XawChainLeft);
3136 XtSetArg (arg[2], XtNright, XawChainRight);
3137 XtSetArg (arg[3], XtNresizable, True);
3138 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3139 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3140 TailWidget, arg, 5);
3142 memset (&control, 0, sizeof control);
3143 control.two_dimensional = 1;
3144 control.enable_bidi = 1;
3145 control.anti_alias = 1;
3146 control.min_line_ascent = font_ascent;
3147 control.min_line_descent = font_descent;
3148 control.max_line_width = win_width;
3149 control.with_cursor = 1;
3150 control.cursor_width = 2;
3151 control.partial_update = 1;
3152 control.ignore_formatting_char = 1;
3154 memset (&input_status_control, 0, sizeof input_status_control);
3155 input_status_control.enable_bidi = 1;
3157 XtAppAddActions (context, actions, XtNumber (actions));
3158 XtRealizeWidget (ShellWidget);
3160 win = XtWindow (TextWidget);
3162 XtAppMainLoop (context);
3164 if (current_input_context)
3165 minput_destroy_ic (current_input_context);
3166 for (i = 0; i < num_input_methods; i++)
3167 if (input_method_table[i].im)
3168 minput_close_im (input_method_table[i].im);
3169 m17n_object_unref (frame);
3170 m17n_object_unref (mt);
3171 m17n_object_unref (face_xxx_large);
3172 m17n_object_unref (face_box);
3173 m17n_object_unref (face_courier);
3174 m17n_object_unref (face_helvetica);
3175 m17n_object_unref (face_times);
3176 m17n_object_unref (face_dv_ttyogesh);
3177 m17n_object_unref (face_freesans);
3178 m17n_object_unref (face_freeserif);
3179 m17n_object_unref (face_freemono);
3180 m17n_object_unref (face_default_fontset);
3181 m17n_object_unref (face_no_ctl_fontset);
3182 m17n_object_unref (face_input_status);
3183 m17n_object_unref (face_default);
3184 m17n_object_unref (default_face_list);
3185 m17n_object_unref (selection);
3187 XFreeGC (display, mono_gc);
3188 XFreeGC (display, mono_gc_inv);
3189 XFreeGC (display, gc_inv);
3190 XtUninstallTranslations (form);
3191 XtUninstallTranslations (TextWidget);
3192 XtDestroyWidget (ShellWidget);
3193 XtDestroyApplicationContext (context);
3197 free (fontset_name);
3199 free (input_method_table);
3200 free (InputMethodMenus);
3205 #else /* not HAVE_X11_XAW_COMMAND_H */
3208 main (int argc, char **argv)
3211 "Building of this program failed (lack of some header files)\n");
3215 #endif /* not HAVE_X11_XAW_COMMAND_H */
3217 #endif /* not FOR_DOXYGEN */