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 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 if (cursor.from == cur.from)
955 /* We are at the beginning of line. */
956 int pos = cursor.prev_from;
958 if (cursor.from == top.from)
960 /* We are at the beginning of screen. We must scroll
962 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
963 reseat (info.line_from);
965 update_cursor (pos, 1);
971 from = cursor.from - 1;
976 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
977 old_y1 = cur.y0 + rect.height;
979 /* Now delete a character. */
980 mtext_del (mt, from, to);
982 if (from >= top.from && from < top.to)
983 update_top (top.from);
984 update_cursor (from, 1);
987 if (line_from != cursor.line_from)
990 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
991 new_y1 = cur.y0 + rect.height;
993 update_region (cur.y0, old_y1, new_y1);
997 /* Insert M-text $NEWTEXT at the current cursor position. */
999 insert_chars (MText *newtext)
1001 int n = mtext_len (newtext);
1003 int y0, old_y1, new_y1;
1008 int n = (mtext_property_end (selection)
1009 - mtext_property_start (selection));
1010 mtext_detach_property (selection);
1015 if (cursor.line_from > 0
1016 && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
1017 y0 -= control.min_line_descent;
1019 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1020 old_y1 = y0 + rect.height;
1022 line_from = cursor.line_from;
1024 /* Now insert chars. */
1025 mtext_ins (mt, cursor.from, newtext);
1027 if (cur.from == top.from)
1028 update_top (top.from);
1029 update_cursor (cursor.from + n, 1);
1031 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1032 new_y1 = cur.y0 + rect.height;
1034 update_region (y0, old_y1, new_y1);
1035 update_selection ();
1040 word_constituent_p (int c)
1042 MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
1043 char *name = category != Mnil ? msymbol_name (category) : NULL;
1045 return (name && (name[0] == 'L' || name[0] == 'M'));
1052 int pos = cursor.from;
1054 while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
1058 MTextProperty *prop = mtext_get_property (mt, pos, Mword);
1061 pos = mtext_property_end (prop);
1063 while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
1066 update_cursor (pos, 0);
1072 int pos = cursor.from;
1074 while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
1078 MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
1081 pos = mtext_property_start (prop);
1083 while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
1086 update_cursor (pos, 0);
1090 /* Convert the currently selected text to UTF8-STRING or
1091 COMPOUND-TEXT. It is called when someone requests the current
1092 value of the selection. */
1094 covert_selection (Widget w, Atom *selection_atom,
1095 Atom *target, Atom *return_type,
1096 XtPointer *value, unsigned long *length, int *format)
1098 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1099 MText *this_mt = mtext ();
1100 int from = mtext_property_start (selection);
1101 int to = mtext_property_end (selection);
1105 mtext_copy (this_mt, 0, mt, from, to);
1106 if (*target == XA_TEXT)
1108 #ifdef X_HAVE_UTF8_STRING
1109 coding = Mcoding_utf_8;
1110 *return_type = XA_UTF8_STRING;
1112 coding = Mcoding_compound_text;
1113 *return_type = XA_COMPOUND_TEXT;
1116 else if (*target == XA_UTF8_STRING)
1118 coding = Mcoding_utf_8;
1119 *return_type = XA_UTF8_STRING;
1121 else if (*target == XA_STRING)
1126 for (i = 0; i < len; i++)
1127 if (mtext_ref_char (this_mt, i) >= 0x100)
1128 /* Can't encode in XA_STRING */
1130 coding = Mcoding_iso_8859_1;
1131 *return_type = XA_STRING;
1133 else if (*target == XA_COMPOUND_TEXT)
1135 coding = Mcoding_compound_text;
1136 *return_type = XA_COMPOUND_TEXT;
1141 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1142 m17n_object_unref (this_mt);
1146 *value = (XtPointer) buf;
1152 /* Unselect the text. It is called when we loose the selection. */
1154 lose_selection (Widget w, Atom *selection_atom)
1158 mtext_detach_property (selection);
1159 redraw (sel_start.y0, sel_end.y1, 1, 0);
1164 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1165 XtPointer value, unsigned long *length, int *format)
1170 if (*type == XT_CONVERT_FAIL || ! value)
1172 if (*type == XA_STRING)
1174 else if (*type == XA_COMPOUND_TEXT)
1175 coding = msymbol ("compound-text");
1176 #ifdef X_HAVE_UTF8_STRING
1177 else if (*type == XA_UTF8_STRING)
1178 coding = msymbol ("utf-8");
1183 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1184 if (! this_mt && *type != XA_UTF8_STRING)
1186 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1193 insert_chars (this_mt);
1194 m17n_object_unref (this_mt);
1203 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1205 XExposeEvent *expose = (XExposeEvent *) event;
1209 Dimension width_max, width;
1211 XtSetArg (arg[0], XtNwidth, &width);
1212 XtGetValues (XtParent (w), arg, 1);
1214 XtGetValues (HeadWidget, arg, 1);
1215 if (width_max < width)
1217 XtGetValues (FaceWidget, arg, 1);
1218 if (width_max < width)
1220 XtGetValues (LangWidget, arg, 1);
1221 if (width_max < width)
1223 XtSetArg (arg[0], XtNwidth, width_max);
1224 XtSetValues (HeadWidget, arg, 1);
1225 XtSetValues (FaceWidget, arg, 1);
1226 XtSetValues (LangWidget, arg, 1);
1227 XtSetValues (XtParent (w), arg, 1);
1228 XtSetValues (TailWidget, arg, 1);
1231 update_cursor (0, 1);
1232 redraw (0, win_height, 0, 1);
1233 if (current_input_method >= 0)
1235 int idx = current_input_method;
1237 current_input_method = -1;
1238 select_input_method (idx);
1244 redraw (expose->y, expose->y + expose->height, 0, 0);
1245 if (current_input_context
1246 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1247 set_input_method_spot ();
1252 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1254 XConfigureEvent *configure = (XConfigureEvent *) event;
1257 control.max_line_width = win_width = configure->width;
1258 win_height = configure->height;
1259 mdraw_clear_cache (mt);
1261 update_cursor (0, 1);
1262 redraw (0, win_height, 1, 1);
1263 if (current_input_context)
1264 set_input_method_spot ();
1268 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1271 int x = event->xbutton.x;
1272 int y = event->xbutton.y - top.ascent;
1274 if (control.orientation_reversed)
1276 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1279 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1280 mtext_detach_property (selection);
1281 redraw (sel_start.y0, sel_end.y1, 1, 0);
1284 if (current_input_context
1285 && minput_filter (current_input_context, Minput_focus_move, NULL) == 0)
1287 MText *produced = mtext ();
1289 minput_lookup (current_input_context, Mnil, NULL, produced);
1290 if (mtext_len (produced) > 0)
1292 insert_chars (produced);
1293 if (pos >= cursor.from)
1294 pos += mtext_len (produced);
1296 m17n_object_unref (produced);
1298 update_cursor (pos, 0);
1303 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1308 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1309 covert_selection, lose_selection, NULL);
1310 update_cursor (mtext_property_start (selection), 0);
1315 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1319 /* We don't have a local selection. */
1320 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1325 int from = mtext_property_start (selection);
1326 int to = mtext_property_end (selection);
1329 int x = event->xbutton.x;
1330 int y = event->xbutton.y - top.ascent;
1332 if (control.orientation_reversed)
1334 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1336 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1337 mtext_detach_property (selection);
1339 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1340 update_cursor (pos, 0);
1341 insert_chars (this_mt);
1342 m17n_object_unref (this_mt);
1347 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1350 int x = event->xbutton.x;
1351 int y = event->xbutton.y;
1353 if (control.orientation_reversed)
1356 pos = top.from, y -= top.ascent;
1358 pos = cur.from, y -= cur.y0 + cur.ascent;
1359 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1361 if (pos == cursor.from)
1367 /* Selection range changed. */
1368 int from = mtext_property_start (selection);
1369 int to = mtext_property_end (selection);
1370 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1371 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1373 if (cursor.from == from)
1375 /* Starting position changed. */
1378 /* Enlarged. We can simply overdraw. */
1379 select_region (pos, to);
1380 redraw (sel_start.y0, start_y1, 0, 0);
1384 /* Shrunken. Previous selection face must be cleared. */
1385 select_region (pos, to);
1386 redraw (start_y0, sel_start.y1, 1, 0);
1390 /* Shrunken to zero. */
1391 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1392 mtext_detach_property (selection);
1393 redraw (start_y0, end_y1, 1, 0);
1397 /* Full update is necessary. */
1398 select_region (to, pos);
1399 redraw (start_y0, sel_end.y1, 1, 0);
1404 /* Ending position changed. */
1407 /* Full update is necessary. */
1408 select_region (pos, from);
1409 redraw (sel_start.y0, end_y1, 1, 0);
1411 else if (pos == from)
1413 /* Shrunken to zero. */
1414 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1415 mtext_detach_property (selection);
1416 redraw (start_y0, end_y1, 1, 0);
1420 /* Shrunken. Previous selection face must be cleared. */
1421 select_region (from, pos);
1422 redraw (sel_end.y0, end_y1, 1, 0);
1426 /* Enlarged. We can simply overdraw. */
1427 select_region (from, pos);
1428 redraw (end_y0, sel_end.y1, 0, 0);
1434 /* Newly selected. */
1435 select_region (pos, cursor.from);
1436 redraw (sel_start.y0, sel_end.y1, 0, 0);
1438 update_cursor (pos, 1);
1442 FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num)
1444 if (current_input_context
1445 && minput_filter (current_input_context, Minput_focus_in, NULL) == 0)
1447 MText *produced = mtext ();
1449 minput_lookup (current_input_context, Mnil, NULL, produced);
1450 if (mtext_len (produced) > 0)
1453 insert_chars (produced);
1455 m17n_object_unref (produced);
1460 FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num)
1462 if (current_input_context
1463 && minput_filter (current_input_context, Minput_focus_out, NULL) == 0)
1465 MText *produced = mtext ();
1467 minput_lookup (current_input_context, Mnil, NULL, produced);
1468 if (mtext_len (produced) > 0)
1471 insert_chars (produced);
1473 m17n_object_unref (produced);
1478 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1481 MDrawGlyphInfo info;
1483 int cursor_pos = cursor.from;
1485 if (((int) position) < 0)
1491 height = top.y1 - top.y0;
1494 pos = bol (from - 1, 0);
1495 GLYPH_INFO (pos, from - 1, info);
1496 if (height + info.metrics.height > win_height)
1498 height += info.metrics.height;
1499 from = info.line_from;
1501 if (cursor_pos >= top.to)
1503 cursor_pos = top.from;
1505 while (cursor_pos < nchars)
1507 GLYPH_INFO (pos, pos, info);
1508 if (height + info.metrics.height > win_height)
1510 height += info.metrics.height;
1516 else if (cur.to < nchars)
1518 /* Scroll up, but leave at least one line. */
1521 while (from < nchars)
1523 GLYPH_INFO (from, from, info);
1524 if (height + info.metrics.height > win_height
1525 || info.line_to >= nchars)
1527 height += info.metrics.height;
1528 from = info.line_to;
1531 from = info.line_from;
1532 if (cursor_pos < from)
1536 /* Scroll up to make the cursor line top. */
1540 update_cursor (cursor_pos, 1);
1544 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1546 float persent = *(float *) persent_ptr;
1547 int pos1, pos2 = nchars * persent;
1548 MDrawGlyphInfo info;
1551 pos1 = bol (pos2, 0);
1552 GLYPH_INFO (pos1, pos2, info);
1553 pos1 = info.line_from;
1555 update_cursor (pos1, 1);
1560 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1562 XKeyEvent *key_event = (XKeyEvent *) event;
1564 KeySym keysym = NoSymbol;
1566 /* If set to 1, do not update target_x_position. */
1567 int keep_target_x_position = 0;
1570 if (current_input_context
1571 && minput_filter (current_input_context, Mnil, event))
1573 if (event->type == KeyRelease)
1578 produced = mtext ();
1579 ret = minput_lookup (current_input_context, Mnil, event, produced);
1580 if (mtext_len (produced) > 0)
1581 insert_chars (produced);
1583 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1584 m17n_object_unref (produced);
1594 n = (mtext_property_end (selection)
1595 - mtext_property_start (selection));
1596 mtext_detach_property (selection);
1598 else if (cursor.from < nchars)
1600 /* Delete the following grapheme cluster. */
1601 n = cursor.to - cursor.from;
1614 /* Delete selected region. */
1615 n = (mtext_property_end (selection)
1616 - mtext_property_start (selection));
1617 mtext_detach_property (selection);
1619 else if (cursor.from > 0)
1621 /* Delete the preceding character. */
1632 mtext_detach_property (selection);
1633 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1637 if (cursor.prev_from >= 0)
1638 update_cursor (cursor.prev_from, 0);
1642 if (cursor.left_from >= 0)
1643 update_cursor (cursor.left_from, 0);
1650 mtext_detach_property (selection);
1651 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1655 if (cursor.next_to >= 0)
1656 update_cursor (cursor.to, 0);
1660 if (cursor.right_from >= 0)
1661 update_cursor (cursor.right_from, 0);
1668 mtext_detach_property (selection);
1669 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1671 if (cur.to <= nchars)
1673 MDrawGlyphInfo info;
1676 GLYPH_INFO (cur.from, cur.to, info);
1677 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1678 target_x_position, info.y);
1679 keep_target_x_position = 1;
1680 update_cursor (pos, 0);
1687 mtext_detach_property (selection);
1688 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1694 int pos = bol (cur.from - 1, 0);
1696 TEXT_EXTENTS (pos, cur.from - 1, rect);
1697 y = rect.height + rect.y - 1;
1698 pos = COORDINATES_POSITION (pos, nchars,
1699 target_x_position, y);
1700 keep_target_x_position = 1;
1701 update_cursor (pos, 0);
1708 mtext_detach_property (selection);
1709 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1711 if (top.from < nchars)
1712 ScrollProc (w, NULL, (XtPointer) 1);
1718 mtext_detach_property (selection);
1719 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1722 ScrollProc (w, NULL, (XtPointer) -1);
1726 if (key_event->state >= Mod1Mask)
1728 lose_selection (NULL, NULL);
1734 if (key_event->state >= Mod1Mask)
1736 lose_selection (NULL, NULL);
1744 if (buf[0] == 17) /* C-q */
1746 XtAppSetExitFlag (context);
1749 else if (buf[0] == 12) /* C-l */
1751 redraw (0, win_height, 1, 1);
1756 MText *temp = mtext ();
1758 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1759 : ((unsigned char *) buf)[0]);
1760 if (current_input_context)
1761 mtext_put_prop (temp, 0, 1, Mlanguage,
1762 current_input_context->im->language);
1763 insert_chars (temp);
1764 m17n_object_unref (temp);
1769 if (! keep_target_x_position)
1770 target_x_position = cursor.x;
1774 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1776 char *name = (char *) client_data;
1778 int from = -1, to = 0;
1783 filename = strdup (name);
1786 fp = fopen (filename, "w");
1789 fprintf (stderr, "Open for write fail: %s", filename);
1795 from = mtext_property_start (selection);
1796 to = mtext_property_end (selection);
1797 mtext_detach_property (selection);
1800 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1803 select_region (from, to);
1807 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1813 mtext_detach_property (selection);
1814 serialized = (int) client_data;
1816 new = mtext_deserialize (mt);
1819 MPlist *plist = mplist ();
1821 mplist_push (plist, Mt, Mface);
1822 mplist_push (plist, Mt, Mlanguage);
1823 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1824 m17n_object_unref (plist);
1828 m17n_object_unref (mt);
1830 serialized = ! serialized;
1831 nchars = mtext_len (mt);
1834 update_cursor (0, 1);
1835 redraw (0, win_height, 1, 1);
1839 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1841 XtAppSetExitFlag (context);
1847 FILE *fp = fopen (filename, "r");
1850 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1851 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1854 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1859 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1861 int data = (int) client_data;
1866 control.enable_bidi = 0;
1867 control.orientation_reversed = 0;
1871 control.enable_bidi = 1;
1872 control.orientation_reversed = data == 2;
1874 for (i = 0; i < 3; i++)
1877 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1879 XtSetArg (arg[0], XtNleftBitmap, None);
1880 XtSetValues (BidiMenus[i], arg, 1);
1883 update_cursor (cursor.from, 1);
1884 redraw (0, win_height, 1, 0);
1888 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1890 int data = (int) client_data;
1894 control.max_line_width = 0;
1897 control.max_line_width = win_width;
1898 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1900 for (i = 0; i < 3; i++)
1903 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1905 XtSetArg (arg[0], XtNleftBitmap, None);
1906 XtSetValues (LineBreakMenus[i], arg, 1);
1909 update_cursor (cursor.from, 1);
1910 redraw (0, win_height, 1, 0);
1914 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1916 char *filter_module = (char *) client_data;
1918 void (*func) (MText *, int, int);
1922 handle = dlopen (filter_module, RTLD_NOW);
1925 *(void **) (&func) = dlsym (handle, "filter");
1927 (*func) (mt, mtext_property_start (selection),
1928 mtext_property_end (selection));
1933 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1935 int data = (int) client_data;
1949 control.cursor_bidi = 0, control.cursor_width = -1;
1953 control.cursor_bidi = 0, control.cursor_width = 2;
1957 control.cursor_bidi = 1;
1962 for (i = from; i < to; i++)
1965 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1967 XtSetArg (arg[0], XtNleftBitmap, None);
1968 XtSetValues (CursorMenus[i], arg, 1);
1971 update_cursor (cursor.from, 0);
1972 redraw (0, win_height, 1, 0);
1976 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1978 int idx = (int) client_data;
1980 if (idx == -2 ? (! auto_input_method && current_input_method < 0)
1981 : idx == -1 ? auto_input_method
1982 : idx == current_input_method)
1985 if (auto_input_method)
1987 select_input_method (-1);
1988 XtSetArg (arg[0], XtNleftBitmap, None);
1989 XtSetValues (InputMethodMenus[1], arg, 1);
1990 auto_input_method = 0;
1995 select_input_method (-1);
1996 XtSetArg (arg[0], XtNleftBitmap, None);
1997 XtSetValues (InputMethodMenus[0], arg, 1);
1998 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1999 XtSetValues (InputMethodMenus[1], arg, 1);
2000 auto_input_method = 1;
2005 select_input_method (idx);
2009 MPlist *default_face_list;
2012 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
2014 int idx = (int) client_data;
2025 MFace *face = mframe_get_prop (frame, Mface);
2027 for (plist = default_face_list; mplist_key (plist) != Mnil;
2028 plist = mplist_next (plist))
2029 mface_merge (face, mplist_value (plist));
2030 mplist_add (plist, Mt, *face_table[idx].face);
2031 mface_merge (face, *face_table[idx].face);
2033 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
2035 MFace *face = mframe_get_prop (frame, Mface);
2037 for (plist = default_face_list;
2038 mplist_key (mplist_next (plist)) != Mnil;
2039 plist = mplist_next (plist))
2040 mface_merge (face, mplist_value (plist));
2044 update_cursor (0, 1);
2045 redraw (0, win_height, 1, 1);
2050 XtAppAddWorkProc (context, show_cursor, NULL);
2051 from = mtext_property_start (selection);
2052 to = mtext_property_end (selection);
2053 old_y1 = sel_end.y1;
2055 mtext_detach_property (selection);
2058 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
2059 MTEXTPROP_REAR_STICKY);
2060 mtext_push_property (mt, from, to, prop);
2061 m17n_object_unref (prop);
2064 mtext_pop_prop (mt, from, to, Mface);
2066 update_top (top.from);
2067 update_cursor (cursor.from, 1);
2068 select_region (from, to);
2069 update_region (sel_start.y0, old_y1, sel_end.y1);
2070 if (cur.y1 > win_height)
2072 while (cur.y1 > win_height)
2075 update_cursor (cursor.from, 1);
2081 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2083 MSymbol sym = (MSymbol) client_data;
2090 XtAppAddWorkProc (context, show_cursor, NULL);
2091 from = mtext_property_start (selection);
2092 to = mtext_property_end (selection);
2093 old_y1 = sel_end.y1;
2095 mtext_detach_property (selection);
2097 mtext_put_prop (mt, from, to, Mlanguage, sym);
2099 mtext_pop_prop (mt, from, to, Mlanguage);
2102 update_top (top.from);
2103 update_cursor (cursor.from, 1);
2104 select_region (from, to);
2105 update_region (sel_start.y0, old_y1, sel_end.y1);
2106 if (cur.y1 > win_height)
2108 while (cur.y1 > win_height)
2111 update_cursor (cursor.from, 1);
2117 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2119 int narrowed = (int) client_data;
2122 MConverter *converter;
2128 from = mtext_property_start (selection);
2129 to = mtext_property_end (selection);
2138 mdump = popen ("mdump -q -p a4", "w");
2140 mdump = popen ("mdump -q", "w");
2143 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2144 mconv_encode_range (converter, mt, from, to);
2145 mconv_free_converter (converter);
2150 input_status (MInputContext *ic, MSymbol command)
2152 XFillRectangle (display, input_status_pixmap, gc_inv,
2153 0, 0, input_status_width, input_status_height);
2154 if (command == Minput_status_draw)
2158 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2159 Mface, face_input_status);
2160 if (ic->im->language != Mnil)
2161 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2162 Mlanguage, ic->im->language);
2163 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2164 &input_status_control, NULL, NULL, &rect);
2165 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2166 input_status_width - rect.width - 2, - rect.y,
2167 ic->status, 0, mtext_len (ic->status),
2168 &input_status_control);
2170 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2171 XtSetValues (CurIMStatus, arg, 1);
2175 compare_input_method (const void *elt1, const void *elt2)
2177 const InputMethodInfo *im1 = elt1;
2178 const InputMethodInfo *im2 = elt2;
2179 MSymbol lang1, lang2;
2181 if (im1->language == Mnil)
2183 if (im1->language == im2->language)
2184 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2185 if (im1->language == Mt)
2187 if (im2->language == Mt)
2189 lang1 = msymbol_get (im1->language, Mlanguage);
2190 lang2 = msymbol_get (im2->language, Mlanguage);
2191 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2195 setup_input_methods (int with_xim, char *initial_input_method)
2197 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2201 num_input_methods = plist ? mplist_length (plist) : 0;
2203 num_input_methods++;
2204 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2209 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
2211 MDatabase *mdb = mplist_value (pl);
2212 MSymbol *tag = mdatabase_tag (mdb);
2214 input_method_table[i].language = tag[1];
2215 input_method_table[i].name = tag[2];
2217 m17n_object_unref (plist);
2221 input_method_table[i].language = Mnil;
2222 input_method_table[i].name = msymbol ("xim");
2226 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2227 compare_input_method);
2228 mplist_put (minput_driver->callback_list, Minput_status_start,
2229 (void *) input_status);
2230 mplist_put (minput_driver->callback_list, Minput_status_draw,
2231 (void *) input_status);
2232 mplist_put (minput_driver->callback_list, Minput_status_done,
2233 (void *) input_status);
2235 current_input_context = NULL;
2236 current_input_method = -1;
2238 if (initial_input_method)
2240 char *lang_name, *method_name;
2241 char *p = strchr (initial_input_method, '-');
2244 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2246 lang_name = "t", method_name = initial_input_method;
2248 for (i = 0; i < num_input_methods; i++)
2249 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2251 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2253 current_input_method = i;
2261 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2265 if (num && *num > 0)
2269 for (i = 0; i < *num; i++)
2270 bytes += strlen (str[i]) + 1;
2271 msg = alloca (bytes);
2272 strcpy (msg, str[0]);
2273 for (i = 1; i < *num; i++)
2274 strcat (msg, " "), strcat (msg, str[i]);
2276 else if (cursor.from < nchars)
2278 int c = mtext_ref_char (mt, cursor.from);
2279 char *name = mchar_get_prop (c, Mname);
2283 msg = alloca (10 + strlen (name));
2284 sprintf (msg, "U+%04X %s", c, name);
2290 XtSetArg (arg[0], XtNlabel, msg);
2291 XtSetValues (MessageWidget, arg, 1);
2297 char *name1, *name2;
2298 XtCallbackProc proc;
2299 XtPointer client_data;
2304 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2306 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2308 MenuRec FileMenu[] =
2309 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2310 { 0, "Save", NULL, SaveProc, NULL, -1 },
2311 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2313 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2314 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2316 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2317 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2319 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2322 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2324 MenuRec *rec = (MenuRec *) client_data;
2327 XtSetArg (arg[0], XtNvalue, "");
2328 XtSetArg (arg[1], XtNlabel, rec->name1);
2329 XtSetValues (FileDialogWidget, arg, 2);
2330 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2331 XtSetArg (arg[0], XtNx, x + 20);
2332 XtSetArg (arg[1], XtNy, y + 10);
2333 XtSetValues (FileShellWidget, arg, 2);
2334 XtPopup (FileShellWidget, XtGrabExclusive);
2338 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2343 XtPopdown (FileShellWidget);
2344 if ((int) client_data == 1)
2346 XtSetArg (arg[0], XtNlabel, &label);
2347 XtGetValues (FileDialogWidget, arg, 1);
2348 if (strcmp (label, FileMenu[0].name1) == 0)
2352 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2353 fp = fopen (filename, "r");
2355 m17n_object_unref (mt);
2358 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2366 nchars = mtext_len (mt);
2368 update_cursor (0, 1);
2369 redraw (0, win_height, 1, 1);
2371 else if (strcmp (label, FileMenu[2].name1) == 0)
2372 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2374 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2377 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2378 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2379 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2380 (MENU).status = (STATUS))
2384 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2385 char *menu_name, MenuRec *menus, int num_menus, char *help)
2387 Widget button, menu;
2388 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2389 <LeaveWindow>: reset() MenuHelp()\n\
2390 <BtnDown>: reset() PopupMenu()\n\
2391 <BtnUp>: highlight()";
2397 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2398 for (i = 0; i < num_menus; i++)
2409 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2411 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2413 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2415 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2419 XtSetArg (arg[0], XtNsensitive, False);
2420 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2426 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2431 trans = alloca (strlen (fmt) + strlen (help));
2432 sprintf (trans, fmt, help);
2433 XtSetArg (arg[0], XtNmenuName, menu_name);
2434 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2435 XtSetArg (arg[2], XtNinternalWidth, 2);
2436 XtSetArg (arg[3], XtNhighlightThickness, 1);
2437 XtSetArg (arg[4], XtNleft, XawChainLeft);
2438 XtSetArg (arg[5], XtNright, XawChainLeft);
2441 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2442 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2447 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2448 int *len = alloca (sizeof (int) * num_menus);
2451 XFontSetExtents *fontset_extents;
2453 XtSetArg (arg[0], XtNfontSet, &font_set);
2454 XtGetValues (button, arg, 1);
2456 fontset_extents = XExtentsOfFontSet (font_set);
2457 height = fontset_extents->max_logical_extent.height;
2458 ascent = - fontset_extents->max_logical_extent.y;
2460 for (i = 0; i < num_menus; i++)
2463 len[i] = strlen (menus[i].name2);
2464 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2465 if (max_width < width[i])
2466 max_width = width[i];
2468 for (i = 0; i < num_menus; i++)
2471 Pixmap pixmap = XCreatePixmap (display,
2472 RootWindow (display, screen),
2473 max_width, height, 1);
2474 XFillRectangle (display, pixmap, mono_gc_inv,
2475 0, 0, max_width, height);
2476 XmbDrawString (display, pixmap, font_set, mono_gc,
2477 max_width - width[i], ascent,
2478 menus[i].name2, len[i]);
2479 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2480 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2481 XtSetValues (menus[i].w, arg, 2);
2489 XtActionsRec actions[] = {
2490 {"Expose", ExposeProc},
2491 {"Configure", ConfigureProc},
2493 {"ButtonPress", ButtonProc},
2494 {"ButtonRelease", ButtonReleaseProc},
2495 {"ButtonMotion", ButtonMoveProc},
2496 {"Button2Press", Button2Proc},
2497 {"MenuHelp", MenuHelpProc},
2498 {"FocusIn", FocusInProc},
2499 {"FocusOut", FocusOutProc}
2503 /* Print the usage of this program (the name is PROG), and exit with
2507 help_exit (char *prog, int exit_code)
2515 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2516 printf ("Display FILE on a window and allow users to edit it.\n");
2517 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2518 printf ("The following OPTIONs are available.\n");
2519 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2520 "Use the specified fontset\n");
2521 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2522 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2523 "Input method activated initially.\n");
2524 printf (" %-13s %s", "--version", "print version number\n");
2525 printf (" %-13s %s", "-h, --help", "print this message\n");
2531 main (int argc, char **argv)
2533 Widget form, BodyWidget, w;
2534 char *fontset_name = NULL;
2536 char *initial_input_method = NULL;
2537 int col = 80, row = 32;
2538 /* Translation table for TextWidget. */
2539 String trans = "<Expose>: Expose()\n\
2540 <Configure>: Configure()\n\
2543 <Btn1Down>: ButtonPress()\n\
2544 <Btn1Up>: ButtonRelease()\n\
2545 <Btn1Motion>: ButtonMotion()\n\
2546 <Btn2Down>: Button2Press()";
2547 /* Translation table for the top form widget. */
2548 String trans2 = "<Key>: Key()\n\
2550 <FocusIn>: FocusIn()\n\
2551 <FocusOut>: FocusOut()";
2552 String pop_face_trans
2553 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2554 <LeaveWindow>: MenuHelp() reset()\n\
2555 <Btn1Down>: set()\n\
2556 <Btn1Up>: notify() unset()";
2557 String pop_lang_trans
2558 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2559 <LeaveWindow>: MenuHelp() reset()\n\
2560 <Btn1Down>: set()\n\
2561 <Btn1Up>: notify() unset()";
2562 int font_width, font_ascent, font_descent;
2565 char *filter = NULL;
2567 setlocale (LC_ALL, "");
2568 /* Create the top shell. */
2569 XtSetLanguageProc (NULL, NULL, NULL);
2570 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2571 NULL, sessionShellWidgetClass, NULL, 0);
2572 display = XtDisplay (ShellWidget);
2573 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2575 /* Parse the remaining command line arguments. */
2576 for (i = 1; i < argc; i++)
2578 if (! strcmp (argv[i], "--help")
2579 || ! strcmp (argv[i], "-h"))
2580 help_exit (argv[0], 0);
2581 else if (! strcmp (argv[i], "--version"))
2583 printf ("m17n-edit (m17n library) %s\n", VERSION);
2584 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2587 else if (! strcmp (argv[i], "--geometry"))
2590 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2591 help_exit (argv[0], 1);
2593 else if (! strcmp (argv[i], "-s"))
2596 fontsize = atoi (argv[i]);
2600 else if (! strcmp (argv[i], "--fontset"))
2603 fontset_name = strdup (argv[i]);
2605 else if (! strcmp (argv[i], "--im"))
2608 initial_input_method = strdup (argv[i]);
2610 else if (! strcmp (argv[i], "--with-xim"))
2614 else if (! strcmp (argv[i], "--filter"))
2619 else if (argv[i][0] != '-')
2621 filename = strdup (argv[i]);
2625 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2626 help_exit (argv[0], 1);
2630 filename = strdup ("/dev/null");
2632 mdatabase_dir = ".";
2633 /* Initialize the m17n library. */
2635 if (merror_code != MERROR_NONE)
2636 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2637 minput_driver = &minput_gui_driver;
2639 mt = read_file (filename);
2642 nchars = mtext_len (mt);
2644 Mword = msymbol ("word");
2647 MFace *face = mface ();
2649 mface_put_prop (face, Mforeground, msymbol ("blue"));
2650 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2651 mface_put_prop (face, Mvideomode, Mreverse);
2652 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2653 m17n_object_unref (face);
2656 /* This tells ExposeProc to initialize everything. */
2659 XA_TEXT = XInternAtom (display, "TEXT", False);
2660 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2661 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2662 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2663 if (Mcoding_compound_text == Mnil)
2664 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2667 MPlist *plist = mplist ();
2671 mplist_put (plist, msymbol ("widget"), ShellWidget);
2672 if (fontset_name || fontsize > 0)
2674 MFontset *fontset = mfontset (fontset_name);
2677 mface_put_prop (face, Mfontset, fontset);
2678 mface_put_prop (face, Msize, (void *) fontsize);
2679 m17n_object_unref (fontset);
2680 mplist_add (plist, Mface, face);
2681 m17n_object_unref (face);
2683 frame = mframe (plist);
2685 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2686 m17n_object_unref (plist);
2687 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2688 default_face_list = mplist ();
2689 mplist_add (default_face_list, Mt, face_default);
2690 face_default_fontset = mface ();
2691 mface_put_prop (face_default_fontset, Mfontset,
2692 mface_get_prop (face_default, Mfontset));
2694 font = (MFont *) mframe_get_prop (frame, Mfont);
2695 default_font_size = (int) mfont_get_prop (font, Msize);
2698 font_width = (int) mframe_get_prop (frame, Mfont_width);
2699 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2700 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2701 win_width = font_width * col;
2702 win_height = (font_ascent + font_descent) * row;
2708 prop.color_top = prop.color_left = msymbol ("magenta");
2709 prop.color_bottom = prop.color_right = msymbol ("red");
2710 prop.inner_hmargin = prop.inner_vmargin = 1;
2711 prop.outer_hmargin = prop.outer_vmargin = 2;
2713 face_box = mface ();
2714 mface_put_prop (face_box, Mbox, &prop);
2717 face_courier = mface ();
2718 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2719 face_helvetica = mface ();
2720 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2721 face_times = mface ();
2722 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2723 face_dv_ttyogesh = mface ();
2724 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2725 face_freesans = mface ();
2726 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2727 face_freeserif = mface ();
2728 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2729 face_freemono = mface ();
2730 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2732 face_xxx_large = mface ();
2733 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2735 MFont *latin_font = mframe_get_prop (frame, Mfont);
2736 MFont *dev_font = mfont ();
2737 MFont *thai_font = mfont ();
2738 MFont *tib_font = mfont ();
2740 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2741 MSymbol no_ctl = msymbol ("no-ctl");
2743 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2744 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2745 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2746 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2747 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2748 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2750 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2751 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2752 latin_font, Mnil, 0);
2753 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2754 dev_font, no_ctl, 0);
2755 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2756 thai_font, no_ctl, 0);
2757 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2758 tib_font, no_ctl, 0);
2759 face_no_ctl_fontset = mface ();
2760 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2761 m17n_object_unref (fontset);
2768 setup_input_methods (with_xim, initial_input_method);
2770 gc = DefaultGC (display, screen);
2772 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2773 XtSetArg (arg[1], XtNdefaultDistance, 2);
2774 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2776 XtSetArg (arg[0], XtNborderWidth, 0);
2777 XtSetArg (arg[1], XtNdefaultDistance, 2);
2778 XtSetArg (arg[2], XtNtop, XawChainTop);
2779 XtSetArg (arg[3], XtNbottom, XawChainTop);
2780 XtSetArg (arg[4], XtNleft, XawChainLeft);
2781 XtSetArg (arg[5], XtNright, XawChainRight);
2782 XtSetArg (arg[6], XtNresizable, True);
2783 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2784 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2785 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2786 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2787 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2788 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2789 XtSetArg (arg[7], XtNfromVert, LangWidget);
2790 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2791 XtSetArg (arg[2], XtNtop, XawChainBottom);
2792 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2793 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2795 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2796 HeadWidget, NULL, 0);
2797 XtSetArg (arg[0], XtNvalue, "");
2798 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2799 FileShellWidget, arg, 1);
2800 XawDialogAddButton (FileDialogWidget, "OK",
2801 FileDialogProc, (XtPointer) 0);
2802 XawDialogAddButton (FileDialogWidget, "CANCEL",
2803 FileDialogProc, (XtPointer) 1);
2805 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2806 (char *) check_bits,
2807 check_width, check_height);
2809 unsigned long valuemask = GCForeground;
2812 values.foreground = 1;
2813 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2814 values.foreground = 0;
2815 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2822 if (num_menus < num_input_methods + 2)
2823 num_menus = num_input_methods + 2;
2824 if (num_menus < num_faces + 1)
2825 num_menus = num_faces + 1;
2826 menus = alloca (sizeof (MenuRec) * num_menus);
2828 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2829 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2830 "File I/O, Serialization, Image, Quit");
2832 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2833 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2834 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2835 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2836 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2837 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2838 w = create_menu_button (ShellWidget, HeadWidget, w,
2839 "Cursor", "Cursor Menu",
2840 menus, 6, "Cursor Movement Mode, Cursor Shape");
2841 CursorMenus[0] = menus[0].w;
2842 CursorMenus[1] = menus[1].w;
2843 CursorMenus[2] = menus[3].w;
2844 CursorMenus[3] = menus[4].w;
2845 CursorMenus[4] = menus[5].w;
2847 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2848 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2849 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2850 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2851 menus, 3, "BIDI Processing Mode");
2852 for (i = 0; i < 3; i++)
2853 BidiMenus[i] = menus[i].w;
2855 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2856 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2857 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2858 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2860 menus, 3, "How to break lines");
2861 for (i = 0; i < 3; i++)
2862 LineBreakMenus[i] = menus[i].w;
2864 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2865 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2866 for (i = 0; i < num_input_methods; i++)
2868 InputMethodInfo *im = input_method_table + i;
2869 char *name1, *name2;
2871 if (im->language != Mnil && im->language != Mt)
2873 MSymbol sym = msymbol_get (im->language, Mlanguage);
2875 name1 = msymbol_name (im->language);
2877 name1 = msymbol_name (sym);
2878 name2 = msymbol_name (im->name);
2881 name1 = msymbol_name (im->name), name2 = NULL;
2883 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2885 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2886 "Input Method Menu", menus, i + 2,
2887 "Select input method");
2890 unsigned long valuemask = GCForeground;
2893 XtSetArg (arg[0], XtNbackground, &values.foreground);
2894 XtGetValues (w, arg, 1);
2895 gc_inv = XCreateGC (display, RootWindow (display, screen),
2896 valuemask, &values);
2899 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2900 for (i = 0; i < num_input_methods + 2; i++)
2901 InputMethodMenus[i] = menus[i].w;
2905 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2906 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2907 "Filter Menu", menus, 1,
2908 "Select filter to run");
2911 input_status_width = font_width * 8;
2912 input_status_height = (font_ascent + font_descent) * 2.4;
2913 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2915 input_status_height,
2916 DefaultDepth (display, screen));
2921 prop.color_top = prop.color_bottom
2922 = prop.color_left = prop.color_right = Mnil;
2923 prop.inner_hmargin = prop.inner_vmargin = 1;
2924 prop.outer_hmargin = prop.outer_vmargin = 0;
2925 face_input_status = mface_copy (face_default);
2926 mface_put_prop (face_input_status, Mbox, &prop);
2929 XFillRectangle (display, input_status_pixmap, gc_inv,
2930 0, 0, input_status_width, input_status_height);
2931 XtSetArg (arg[0], XtNfromHoriz, w);
2932 XtSetArg (arg[1], XtNleft, XawRubber);
2933 XtSetArg (arg[2], XtNright, XawChainRight);
2934 XtSetArg (arg[3], XtNborderWidth, 0);
2935 XtSetArg (arg[4], XtNlabel, " ");
2936 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2937 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2938 HeadWidget, arg, 6);
2939 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2940 XtSetArg (arg[1], XtNleft, XawChainRight);
2941 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2942 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2943 HeadWidget, arg, 5);
2945 XtSetArg (arg[0], XtNborderWidth, 0);
2946 XtSetArg (arg[1], XtNleft, XawChainLeft);
2947 XtSetArg (arg[2], XtNright, XawChainLeft);
2948 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2949 for (i = 0; i < num_faces;)
2951 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2952 char *label = label_menu + 5; /* "Xxxx" */
2954 for (j = i; j < num_faces && face_table[j].face; j++)
2955 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2957 w = create_menu_button (ShellWidget, FaceWidget, w,
2959 menus, j - i, "Push face property");
2963 XtSetArg (arg[0], XtNfromHoriz, w);
2964 XtSetArg (arg[1], XtNleft, XawChainLeft);
2965 XtSetArg (arg[2], XtNright, XawChainLeft);
2966 XtSetArg (arg[3], XtNhorizDistance, 10);
2967 XtSetArg (arg[4], XtNlabel, "Pop");
2968 XtSetArg (arg[5], XtNtranslations,
2969 XtParseTranslationTable (pop_face_trans));
2970 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2971 FaceWidget, arg, 6);
2972 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2974 XtSetArg (arg[0], XtNfromHoriz, w);
2975 XtSetArg (arg[1], XtNleft, XawChainLeft);
2976 XtSetArg (arg[2], XtNright, XawChainRight);
2977 XtSetArg (arg[3], XtNlabel, "");
2978 XtSetArg (arg[4], XtNborderWidth, 0);
2979 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2980 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2981 FaceWidget, arg, 6);
2983 XtSetArg (arg[0], XtNborderWidth, 0);
2984 XtSetArg (arg[1], XtNleft, XawChainLeft);
2985 XtSetArg (arg[2], XtNright, XawChainLeft);
2986 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2988 MPlist *plist[11], *pl;
2991 for (i = 0; i < 11; i++) plist[i] = NULL;
2993 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2994 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2996 MSymbol sym = msymbol_exist (langname);
3000 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
3002 char *name = msymbol_name (fullname);
3005 if (c >= 'a' && c <= 'z')
3007 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
3011 pl = plist[idx] = mplist ();
3012 for (; mplist_next (pl); pl = mplist_next (pl))
3013 if (strcmp (name, (char *) mplist_value (pl)) < 0)
3015 mplist_push (pl, sym, fullname);
3020 for (i = 0; i < 11; i++)
3023 char *name = alloca (9);
3025 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
3028 for (j = 0, pl = plist[i]; mplist_next (pl);
3029 j++, pl = mplist_next (pl))
3030 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
3031 msymbol_name (mplist_key (pl)),
3032 LangProc, mplist_key (pl), -1);
3033 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
3034 menus, j, "Push language property");
3036 for (i = 0; i < 11; i++)
3038 m17n_object_unref (plist[i]);
3040 XtSetArg (arg[0], XtNfromHoriz, w);
3041 XtSetArg (arg[1], XtNleft, XawChainLeft);
3042 XtSetArg (arg[2], XtNright, XawChainLeft);
3043 XtSetArg (arg[3], XtNhorizDistance, 10);
3044 XtSetArg (arg[4], XtNlabel, "Pop");
3045 XtSetArg (arg[5], XtNtranslations,
3046 XtParseTranslationTable (pop_lang_trans));
3047 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3048 LangWidget, arg, 6);
3049 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3051 XtSetArg (arg[0], XtNfromHoriz, w);
3052 XtSetArg (arg[1], XtNleft, XawChainLeft);
3053 XtSetArg (arg[2], XtNright, XawChainRight);
3054 XtSetArg (arg[3], XtNlabel, "");
3055 XtSetArg (arg[4], XtNborderWidth, 0);
3056 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3057 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3058 LangWidget, arg, 6);
3061 XtSetArg (arg[0], XtNheight, win_height);
3062 XtSetArg (arg[1], XtNwidth, 10);
3063 XtSetArg (arg[2], XtNleft, XawChainLeft);
3064 XtSetArg (arg[3], XtNright, XawChainLeft);
3065 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3067 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3068 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3070 XtSetArg (arg[0], XtNheight, win_height);
3071 XtSetArg (arg[1], XtNwidth, win_width);
3072 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3073 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3074 XtSetArg (arg[4], XtNleft, XawChainLeft);
3075 XtSetArg (arg[5], XtNright, XawChainRight);
3076 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3079 XtSetArg (arg[0], XtNborderWidth, 0);
3080 XtSetArg (arg[1], XtNleft, XawChainLeft);
3081 XtSetArg (arg[2], XtNright, XawChainRight);
3082 XtSetArg (arg[3], XtNresizable, True);
3083 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3084 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3085 TailWidget, arg, 5);
3087 memset (&control, 0, sizeof control);
3088 control.two_dimensional = 1;
3089 control.enable_bidi = 1;
3090 control.anti_alias = 1;
3091 control.min_line_ascent = font_ascent;
3092 control.min_line_descent = font_descent;
3093 control.max_line_width = win_width;
3094 control.with_cursor = 1;
3095 control.cursor_width = 2;
3096 control.partial_update = 1;
3097 control.ignore_formatting_char = 1;
3099 memset (&input_status_control, 0, sizeof input_status_control);
3100 input_status_control.enable_bidi = 1;
3102 XtAppAddActions (context, actions, XtNumber (actions));
3103 XtRealizeWidget (ShellWidget);
3105 win = XtWindow (TextWidget);
3107 XtAppMainLoop (context);
3109 if (current_input_context)
3110 minput_destroy_ic (current_input_context);
3111 for (i = 0; i < num_input_methods; i++)
3112 if (input_method_table[i].im)
3113 minput_close_im (input_method_table[i].im);
3114 m17n_object_unref (frame);
3115 m17n_object_unref (mt);
3116 m17n_object_unref (face_xxx_large);
3117 m17n_object_unref (face_box);
3118 m17n_object_unref (face_courier);
3119 m17n_object_unref (face_helvetica);
3120 m17n_object_unref (face_times);
3121 m17n_object_unref (face_dv_ttyogesh);
3122 m17n_object_unref (face_freesans);
3123 m17n_object_unref (face_freeserif);
3124 m17n_object_unref (face_freemono);
3125 m17n_object_unref (face_default_fontset);
3126 m17n_object_unref (face_no_ctl_fontset);
3127 m17n_object_unref (face_input_status);
3128 m17n_object_unref (face_default);
3129 m17n_object_unref (default_face_list);
3130 m17n_object_unref (selection);
3132 XFreeGC (display, mono_gc);
3133 XFreeGC (display, mono_gc_inv);
3134 XFreeGC (display, gc_inv);
3135 XtUninstallTranslations (form);
3136 XtUninstallTranslations (TextWidget);
3137 XtDestroyWidget (ShellWidget);
3138 XtDestroyApplicationContext (context);
3142 free (fontset_name);
3144 free (input_method_table);
3145 free (InputMethodMenus);
3150 #else /* not HAVE_X11_XAW_COMMAND_H */
3153 main (int argc, char **argv)
3156 "Building of this program failed (lack of some header files)\n");
3160 #endif /* not HAVE_X11_XAW_COMMAND_H */
3162 #endif /* not FOR_DOXYGEN */