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 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);
2215 i--, num_input_methods--;
2218 input_method_table[i].language = tag[1];
2219 input_method_table[i].name = tag[2];
2222 m17n_object_unref (plist);
2226 input_method_table[i].language = Mnil;
2227 input_method_table[i].name = msymbol ("xim");
2231 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2232 compare_input_method);
2233 mplist_put (minput_driver->callback_list, Minput_status_start,
2234 (void *) input_status);
2235 mplist_put (minput_driver->callback_list, Minput_status_draw,
2236 (void *) input_status);
2237 mplist_put (minput_driver->callback_list, Minput_status_done,
2238 (void *) input_status);
2240 current_input_context = NULL;
2241 current_input_method = -1;
2243 if (initial_input_method)
2245 char *lang_name, *method_name;
2246 char *p = strchr (initial_input_method, '-');
2249 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2251 lang_name = "t", method_name = initial_input_method;
2253 for (i = 0; i < num_input_methods; i++)
2254 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2256 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2258 current_input_method = i;
2266 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2270 if (num && *num > 0)
2274 for (i = 0; i < *num; i++)
2275 bytes += strlen (str[i]) + 1;
2276 msg = alloca (bytes);
2277 strcpy (msg, str[0]);
2278 for (i = 1; i < *num; i++)
2279 strcat (msg, " "), strcat (msg, str[i]);
2281 else if (cursor.from < nchars)
2283 int c = mtext_ref_char (mt, cursor.from);
2284 char *name = mchar_get_prop (c, Mname);
2288 msg = alloca (10 + strlen (name));
2289 sprintf (msg, "U+%04X %s", c, name);
2295 XtSetArg (arg[0], XtNlabel, msg);
2296 XtSetValues (MessageWidget, arg, 1);
2302 char *name1, *name2;
2303 XtCallbackProc proc;
2304 XtPointer client_data;
2309 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2311 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2313 MenuRec FileMenu[] =
2314 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2315 { 0, "Save", NULL, SaveProc, NULL, -1 },
2316 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2318 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2319 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2321 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2322 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2324 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2327 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2329 MenuRec *rec = (MenuRec *) client_data;
2332 XtSetArg (arg[0], XtNvalue, "");
2333 XtSetArg (arg[1], XtNlabel, rec->name1);
2334 XtSetValues (FileDialogWidget, arg, 2);
2335 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2336 XtSetArg (arg[0], XtNx, x + 20);
2337 XtSetArg (arg[1], XtNy, y + 10);
2338 XtSetValues (FileShellWidget, arg, 2);
2339 XtPopup (FileShellWidget, XtGrabExclusive);
2343 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2348 XtPopdown (FileShellWidget);
2349 if ((int) client_data == 1)
2351 XtSetArg (arg[0], XtNlabel, &label);
2352 XtGetValues (FileDialogWidget, arg, 1);
2353 if (strcmp (label, FileMenu[0].name1) == 0)
2357 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2358 fp = fopen (filename, "r");
2360 m17n_object_unref (mt);
2363 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2371 nchars = mtext_len (mt);
2373 update_cursor (0, 1);
2374 redraw (0, win_height, 1, 1);
2376 else if (strcmp (label, FileMenu[2].name1) == 0)
2377 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2379 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2382 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2383 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2384 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2385 (MENU).status = (STATUS))
2389 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2390 char *menu_name, MenuRec *menus, int num_menus, char *help)
2392 Widget button, menu;
2393 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2394 <LeaveWindow>: reset() MenuHelp()\n\
2395 <BtnDown>: reset() PopupMenu()\n\
2396 <BtnUp>: highlight()";
2402 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2403 for (i = 0; i < num_menus; i++)
2414 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2416 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2418 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2420 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2424 XtSetArg (arg[0], XtNsensitive, False);
2425 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2431 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2436 trans = alloca (strlen (fmt) + strlen (help));
2437 sprintf (trans, fmt, help);
2438 XtSetArg (arg[0], XtNmenuName, menu_name);
2439 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2440 XtSetArg (arg[2], XtNinternalWidth, 2);
2441 XtSetArg (arg[3], XtNhighlightThickness, 1);
2442 XtSetArg (arg[4], XtNleft, XawChainLeft);
2443 XtSetArg (arg[5], XtNright, XawChainLeft);
2446 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2447 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2452 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2453 int *len = alloca (sizeof (int) * num_menus);
2456 XFontSetExtents *fontset_extents;
2458 XtSetArg (arg[0], XtNfontSet, &font_set);
2459 XtGetValues (button, arg, 1);
2461 fontset_extents = XExtentsOfFontSet (font_set);
2462 height = fontset_extents->max_logical_extent.height;
2463 ascent = - fontset_extents->max_logical_extent.y;
2465 for (i = 0; i < num_menus; i++)
2468 len[i] = strlen (menus[i].name2);
2469 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2470 if (max_width < width[i])
2471 max_width = width[i];
2473 for (i = 0; i < num_menus; i++)
2476 Pixmap pixmap = XCreatePixmap (display,
2477 RootWindow (display, screen),
2478 max_width, height, 1);
2479 XFillRectangle (display, pixmap, mono_gc_inv,
2480 0, 0, max_width, height);
2481 XmbDrawString (display, pixmap, font_set, mono_gc,
2482 max_width - width[i], ascent,
2483 menus[i].name2, len[i]);
2484 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2485 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2486 XtSetValues (menus[i].w, arg, 2);
2494 XtActionsRec actions[] = {
2495 {"Expose", ExposeProc},
2496 {"Configure", ConfigureProc},
2498 {"ButtonPress", ButtonProc},
2499 {"ButtonRelease", ButtonReleaseProc},
2500 {"ButtonMotion", ButtonMoveProc},
2501 {"Button2Press", Button2Proc},
2502 {"MenuHelp", MenuHelpProc},
2503 {"FocusIn", FocusInProc},
2504 {"FocusOut", FocusOutProc}
2508 /* Print the usage of this program (the name is PROG), and exit with
2512 help_exit (char *prog, int exit_code)
2520 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2521 printf ("Display FILE on a window and allow users to edit it.\n");
2522 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2523 printf ("The following OPTIONs are available.\n");
2524 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2525 "Use the specified fontset\n");
2526 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2527 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2528 "Input method activated initially.\n");
2529 printf (" %-13s %s", "--version", "print version number\n");
2530 printf (" %-13s %s", "-h, --help", "print this message\n");
2536 main (int argc, char **argv)
2538 Widget form, BodyWidget, w;
2539 char *fontset_name = NULL;
2541 char *initial_input_method = NULL;
2542 int col = 80, row = 32;
2543 /* Translation table for TextWidget. */
2544 String trans = "<Expose>: Expose()\n\
2545 <Configure>: Configure()\n\
2548 <Btn1Down>: ButtonPress()\n\
2549 <Btn1Up>: ButtonRelease()\n\
2550 <Btn1Motion>: ButtonMotion()\n\
2551 <Btn2Down>: Button2Press()";
2552 /* Translation table for the top form widget. */
2553 String trans2 = "<Key>: Key()\n\
2555 <FocusIn>: FocusIn()\n\
2556 <FocusOut>: FocusOut()";
2557 String pop_face_trans
2558 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2559 <LeaveWindow>: MenuHelp() reset()\n\
2560 <Btn1Down>: set()\n\
2561 <Btn1Up>: notify() unset()";
2562 String pop_lang_trans
2563 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2564 <LeaveWindow>: MenuHelp() reset()\n\
2565 <Btn1Down>: set()\n\
2566 <Btn1Up>: notify() unset()";
2567 int font_width, font_ascent, font_descent;
2570 char *filter = NULL;
2572 setlocale (LC_ALL, "");
2573 /* Create the top shell. */
2574 XtSetLanguageProc (NULL, NULL, NULL);
2575 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2576 NULL, sessionShellWidgetClass, NULL, 0);
2577 display = XtDisplay (ShellWidget);
2578 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2580 /* Parse the remaining command line arguments. */
2581 for (i = 1; i < argc; i++)
2583 if (! strcmp (argv[i], "--help")
2584 || ! strcmp (argv[i], "-h"))
2585 help_exit (argv[0], 0);
2586 else if (! strcmp (argv[i], "--version"))
2588 printf ("m17n-edit (m17n library) %s\n", VERSION);
2589 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2592 else if (! strcmp (argv[i], "--geometry"))
2595 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2596 help_exit (argv[0], 1);
2598 else if (! strcmp (argv[i], "-s"))
2601 fontsize = atoi (argv[i]);
2605 else if (! strcmp (argv[i], "--fontset"))
2608 fontset_name = strdup (argv[i]);
2610 else if (! strcmp (argv[i], "--im"))
2613 initial_input_method = strdup (argv[i]);
2615 else if (! strcmp (argv[i], "--with-xim"))
2619 else if (! strcmp (argv[i], "--filter"))
2624 else if (argv[i][0] != '-')
2626 filename = strdup (argv[i]);
2630 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2631 help_exit (argv[0], 1);
2635 filename = strdup ("/dev/null");
2637 mdatabase_dir = ".";
2638 /* Initialize the m17n library. */
2640 if (merror_code != MERROR_NONE)
2641 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2642 minput_driver = &minput_gui_driver;
2644 mt = read_file (filename);
2647 nchars = mtext_len (mt);
2649 Mword = msymbol ("word");
2652 MFace *face = mface ();
2654 mface_put_prop (face, Mforeground, msymbol ("blue"));
2655 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2656 mface_put_prop (face, Mvideomode, Mreverse);
2657 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2658 m17n_object_unref (face);
2661 /* This tells ExposeProc to initialize everything. */
2664 XA_TEXT = XInternAtom (display, "TEXT", False);
2665 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2666 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2667 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2668 if (Mcoding_compound_text == Mnil)
2669 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2672 MPlist *plist = mplist ();
2676 mplist_put (plist, msymbol ("widget"), ShellWidget);
2677 if (fontset_name || fontsize > 0)
2679 MFontset *fontset = mfontset (fontset_name);
2682 mface_put_prop (face, Mfontset, fontset);
2683 mface_put_prop (face, Msize, (void *) fontsize);
2684 m17n_object_unref (fontset);
2685 mplist_add (plist, Mface, face);
2686 m17n_object_unref (face);
2688 frame = mframe (plist);
2690 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2691 m17n_object_unref (plist);
2692 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2693 default_face_list = mplist ();
2694 mplist_add (default_face_list, Mt, face_default);
2695 face_default_fontset = mface ();
2696 mface_put_prop (face_default_fontset, Mfontset,
2697 mface_get_prop (face_default, Mfontset));
2699 font = (MFont *) mframe_get_prop (frame, Mfont);
2700 default_font_size = (int) mfont_get_prop (font, Msize);
2703 font_width = (int) mframe_get_prop (frame, Mfont_width);
2704 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2705 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2706 win_width = font_width * col;
2707 win_height = (font_ascent + font_descent) * row;
2713 prop.color_top = prop.color_left = msymbol ("magenta");
2714 prop.color_bottom = prop.color_right = msymbol ("red");
2715 prop.inner_hmargin = prop.inner_vmargin = 1;
2716 prop.outer_hmargin = prop.outer_vmargin = 2;
2718 face_box = mface ();
2719 mface_put_prop (face_box, Mbox, &prop);
2722 face_courier = mface ();
2723 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2724 face_helvetica = mface ();
2725 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2726 face_times = mface ();
2727 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2728 face_dv_ttyogesh = mface ();
2729 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2730 face_freesans = mface ();
2731 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2732 face_freeserif = mface ();
2733 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2734 face_freemono = mface ();
2735 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2737 face_xxx_large = mface ();
2738 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2740 MFont *latin_font = mframe_get_prop (frame, Mfont);
2741 MFont *dev_font = mfont ();
2742 MFont *thai_font = mfont ();
2743 MFont *tib_font = mfont ();
2744 MFontset *fontset, *fontset_no_ctl;
2745 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2746 MSymbol no_ctl = msymbol ("no-ctl");
2748 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2749 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2750 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2751 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2752 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2753 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2755 fontset = mfontset (fontset_name);
2756 fontset_no_ctl = mfontset_copy (fontset, "no-ctl");
2757 m17n_object_unref (fontset);
2758 mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil,
2759 latin_font, Mnil, 0);
2760 mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil,
2761 dev_font, no_ctl, 0);
2762 mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil,
2763 thai_font, no_ctl, 0);
2764 mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil,
2765 tib_font, no_ctl, 0);
2766 face_no_ctl_fontset = mface ();
2767 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl);
2768 m17n_object_unref (fontset_no_ctl);
2775 setup_input_methods (with_xim, initial_input_method);
2777 gc = DefaultGC (display, screen);
2779 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2780 XtSetArg (arg[1], XtNdefaultDistance, 2);
2781 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2783 XtSetArg (arg[0], XtNborderWidth, 0);
2784 XtSetArg (arg[1], XtNdefaultDistance, 2);
2785 XtSetArg (arg[2], XtNtop, XawChainTop);
2786 XtSetArg (arg[3], XtNbottom, XawChainTop);
2787 XtSetArg (arg[4], XtNleft, XawChainLeft);
2788 XtSetArg (arg[5], XtNright, XawChainRight);
2789 XtSetArg (arg[6], XtNresizable, True);
2790 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2791 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2792 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2793 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2794 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2795 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2796 XtSetArg (arg[7], XtNfromVert, LangWidget);
2797 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2798 XtSetArg (arg[2], XtNtop, XawChainBottom);
2799 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2800 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2802 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2803 HeadWidget, NULL, 0);
2804 XtSetArg (arg[0], XtNvalue, "");
2805 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2806 FileShellWidget, arg, 1);
2807 XawDialogAddButton (FileDialogWidget, "OK",
2808 FileDialogProc, (XtPointer) 0);
2809 XawDialogAddButton (FileDialogWidget, "CANCEL",
2810 FileDialogProc, (XtPointer) 1);
2812 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2813 (char *) check_bits,
2814 check_width, check_height);
2816 unsigned long valuemask = GCForeground;
2819 values.foreground = 1;
2820 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2821 values.foreground = 0;
2822 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2829 if (num_menus < num_input_methods + 2)
2830 num_menus = num_input_methods + 2;
2831 if (num_menus < num_faces + 1)
2832 num_menus = num_faces + 1;
2833 menus = alloca (sizeof (MenuRec) * num_menus);
2835 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2836 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2837 "File I/O, Serialization, Image, Quit");
2839 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2840 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2841 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2842 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2843 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2844 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2845 w = create_menu_button (ShellWidget, HeadWidget, w,
2846 "Cursor", "Cursor Menu",
2847 menus, 6, "Cursor Movement Mode, Cursor Shape");
2848 CursorMenus[0] = menus[0].w;
2849 CursorMenus[1] = menus[1].w;
2850 CursorMenus[2] = menus[3].w;
2851 CursorMenus[3] = menus[4].w;
2852 CursorMenus[4] = menus[5].w;
2854 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2855 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2856 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2857 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2858 menus, 3, "BIDI Processing Mode");
2859 for (i = 0; i < 3; i++)
2860 BidiMenus[i] = menus[i].w;
2862 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2863 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2864 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2865 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2867 menus, 3, "How to break lines");
2868 for (i = 0; i < 3; i++)
2869 LineBreakMenus[i] = menus[i].w;
2871 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2872 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2873 for (i = 0; i < num_input_methods; i++)
2875 InputMethodInfo *im = input_method_table + i;
2876 char *name1, *name2;
2878 if (im->language != Mnil && im->language != Mt)
2880 MSymbol sym = msymbol_get (im->language, Mlanguage);
2882 name1 = msymbol_name (im->language);
2884 name1 = msymbol_name (sym);
2885 name2 = msymbol_name (im->name);
2888 name1 = msymbol_name (im->name), name2 = NULL;
2890 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2892 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2893 "Input Method Menu", menus, i + 2,
2894 "Select input method");
2897 unsigned long valuemask = GCForeground;
2900 XtSetArg (arg[0], XtNbackground, &values.foreground);
2901 XtGetValues (w, arg, 1);
2902 gc_inv = XCreateGC (display, RootWindow (display, screen),
2903 valuemask, &values);
2906 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2907 for (i = 0; i < num_input_methods + 2; i++)
2908 InputMethodMenus[i] = menus[i].w;
2912 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2913 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2914 "Filter Menu", menus, 1,
2915 "Select filter to run");
2918 input_status_width = font_width * 8;
2919 input_status_height = (font_ascent + font_descent) * 2.4;
2920 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2922 input_status_height,
2923 DefaultDepth (display, screen));
2928 prop.color_top = prop.color_bottom
2929 = prop.color_left = prop.color_right = Mnil;
2930 prop.inner_hmargin = prop.inner_vmargin = 1;
2931 prop.outer_hmargin = prop.outer_vmargin = 0;
2932 face_input_status = mface_copy (face_default);
2933 mface_put_prop (face_input_status, Mbox, &prop);
2936 XFillRectangle (display, input_status_pixmap, gc_inv,
2937 0, 0, input_status_width, input_status_height);
2938 XtSetArg (arg[0], XtNfromHoriz, w);
2939 XtSetArg (arg[1], XtNleft, XawRubber);
2940 XtSetArg (arg[2], XtNright, XawChainRight);
2941 XtSetArg (arg[3], XtNborderWidth, 0);
2942 XtSetArg (arg[4], XtNlabel, " ");
2943 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2944 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2945 HeadWidget, arg, 6);
2946 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2947 XtSetArg (arg[1], XtNleft, XawChainRight);
2948 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2949 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2950 HeadWidget, arg, 5);
2952 XtSetArg (arg[0], XtNborderWidth, 0);
2953 XtSetArg (arg[1], XtNleft, XawChainLeft);
2954 XtSetArg (arg[2], XtNright, XawChainLeft);
2955 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2956 for (i = 0; i < num_faces;)
2958 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2959 char *label = label_menu + 5; /* "Xxxx" */
2961 for (j = i; j < num_faces && face_table[j].face; j++)
2962 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2964 w = create_menu_button (ShellWidget, FaceWidget, w,
2966 menus, j - i, "Push face property");
2970 XtSetArg (arg[0], XtNfromHoriz, w);
2971 XtSetArg (arg[1], XtNleft, XawChainLeft);
2972 XtSetArg (arg[2], XtNright, XawChainLeft);
2973 XtSetArg (arg[3], XtNhorizDistance, 10);
2974 XtSetArg (arg[4], XtNlabel, "Pop");
2975 XtSetArg (arg[5], XtNtranslations,
2976 XtParseTranslationTable (pop_face_trans));
2977 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2978 FaceWidget, arg, 6);
2979 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2981 XtSetArg (arg[0], XtNfromHoriz, w);
2982 XtSetArg (arg[1], XtNleft, XawChainLeft);
2983 XtSetArg (arg[2], XtNright, XawChainRight);
2984 XtSetArg (arg[3], XtNlabel, "");
2985 XtSetArg (arg[4], XtNborderWidth, 0);
2986 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2987 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2988 FaceWidget, arg, 6);
2990 XtSetArg (arg[0], XtNborderWidth, 0);
2991 XtSetArg (arg[1], XtNleft, XawChainLeft);
2992 XtSetArg (arg[2], XtNright, XawChainLeft);
2993 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2995 MPlist *plist[11], *pl;
2998 for (i = 0; i < 11; i++) plist[i] = NULL;
3000 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
3001 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
3003 MSymbol sym = msymbol_exist (langname);
3007 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
3009 char *name = msymbol_name (fullname);
3012 if (c >= 'a' && c <= 'z')
3014 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
3018 pl = plist[idx] = mplist ();
3019 for (; mplist_next (pl); pl = mplist_next (pl))
3020 if (strcmp (name, (char *) mplist_value (pl)) < 0)
3022 mplist_push (pl, sym, fullname);
3027 for (i = 0; i < 11; i++)
3030 char *name = alloca (9);
3032 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
3035 for (j = 0, pl = plist[i]; mplist_next (pl);
3036 j++, pl = mplist_next (pl))
3037 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
3038 msymbol_name (mplist_key (pl)),
3039 LangProc, mplist_key (pl), -1);
3040 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
3041 menus, j, "Push language property");
3043 for (i = 0; i < 11; i++)
3045 m17n_object_unref (plist[i]);
3047 XtSetArg (arg[0], XtNfromHoriz, w);
3048 XtSetArg (arg[1], XtNleft, XawChainLeft);
3049 XtSetArg (arg[2], XtNright, XawChainLeft);
3050 XtSetArg (arg[3], XtNhorizDistance, 10);
3051 XtSetArg (arg[4], XtNlabel, "Pop");
3052 XtSetArg (arg[5], XtNtranslations,
3053 XtParseTranslationTable (pop_lang_trans));
3054 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3055 LangWidget, arg, 6);
3056 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3058 XtSetArg (arg[0], XtNfromHoriz, w);
3059 XtSetArg (arg[1], XtNleft, XawChainLeft);
3060 XtSetArg (arg[2], XtNright, XawChainRight);
3061 XtSetArg (arg[3], XtNlabel, "");
3062 XtSetArg (arg[4], XtNborderWidth, 0);
3063 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3064 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3065 LangWidget, arg, 6);
3068 XtSetArg (arg[0], XtNheight, win_height);
3069 XtSetArg (arg[1], XtNwidth, 10);
3070 XtSetArg (arg[2], XtNleft, XawChainLeft);
3071 XtSetArg (arg[3], XtNright, XawChainLeft);
3072 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3074 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3075 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3077 XtSetArg (arg[0], XtNheight, win_height);
3078 XtSetArg (arg[1], XtNwidth, win_width);
3079 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3080 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3081 XtSetArg (arg[4], XtNleft, XawChainLeft);
3082 XtSetArg (arg[5], XtNright, XawChainRight);
3083 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3086 XtSetArg (arg[0], XtNborderWidth, 0);
3087 XtSetArg (arg[1], XtNleft, XawChainLeft);
3088 XtSetArg (arg[2], XtNright, XawChainRight);
3089 XtSetArg (arg[3], XtNresizable, True);
3090 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3091 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3092 TailWidget, arg, 5);
3094 memset (&control, 0, sizeof control);
3095 control.two_dimensional = 1;
3096 control.enable_bidi = 1;
3097 control.anti_alias = 1;
3098 control.min_line_ascent = font_ascent;
3099 control.min_line_descent = font_descent;
3100 control.max_line_width = win_width;
3101 control.with_cursor = 1;
3102 control.cursor_width = 2;
3103 control.partial_update = 1;
3104 control.ignore_formatting_char = 1;
3106 memset (&input_status_control, 0, sizeof input_status_control);
3107 input_status_control.enable_bidi = 1;
3109 XtAppAddActions (context, actions, XtNumber (actions));
3110 XtRealizeWidget (ShellWidget);
3112 win = XtWindow (TextWidget);
3114 XtAppMainLoop (context);
3116 if (current_input_context)
3117 minput_destroy_ic (current_input_context);
3118 for (i = 0; i < num_input_methods; i++)
3119 if (input_method_table[i].im)
3120 minput_close_im (input_method_table[i].im);
3121 m17n_object_unref (frame);
3122 m17n_object_unref (mt);
3123 m17n_object_unref (face_xxx_large);
3124 m17n_object_unref (face_box);
3125 m17n_object_unref (face_courier);
3126 m17n_object_unref (face_helvetica);
3127 m17n_object_unref (face_times);
3128 m17n_object_unref (face_dv_ttyogesh);
3129 m17n_object_unref (face_freesans);
3130 m17n_object_unref (face_freeserif);
3131 m17n_object_unref (face_freemono);
3132 m17n_object_unref (face_default_fontset);
3133 m17n_object_unref (face_no_ctl_fontset);
3134 m17n_object_unref (face_input_status);
3135 m17n_object_unref (face_default);
3136 m17n_object_unref (default_face_list);
3137 m17n_object_unref (selection);
3139 XFreeGC (display, mono_gc);
3140 XFreeGC (display, mono_gc_inv);
3141 XFreeGC (display, gc_inv);
3142 XtUninstallTranslations (form);
3143 XtUninstallTranslations (TextWidget);
3144 XtDestroyWidget (ShellWidget);
3145 XtDestroyApplicationContext (context);
3149 free (fontset_name);
3151 free (input_method_table);
3152 free (InputMethodMenus);
3157 #else /* not HAVE_X11_XAW_COMMAND_H */
3160 main (int argc, char **argv)
3163 "Building of this program failed (lack of some header files)\n");
3167 #endif /* not HAVE_X11_XAW_COMMAND_H */
3169 #endif /* not FOR_DOXYGEN */