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 Output 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 Output 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) */
177 MDrawControl control, input_status_control;
178 MTextProperty *selection;
183 MFace *face_xxx_large;
185 MFace *face_courier, *face_helvetica, *face_times;
186 MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
187 MFace *face_default_fontset, *face_no_ctl_fontset;
188 MFace *face_input_status;
190 MSymbol Mcoding_compound_text;
192 int logical_move = 1; /* If 0, move cursor visually. */
196 MSymbol language, name;
200 InputMethodInfo *input_method_table;
202 int num_input_methods;
203 int current_input_method = -1; /* i.e. none */
204 int auto_input_method = 0;
205 MInputContext *current_input_context;
212 { {"Menu Size", NULL},
213 {"xx-small", &mface_xx_small},
214 {"x-small", &mface_x_small},
215 {"small", &mface_small},
216 {"normalsize", &mface_normalsize},
217 {"large", &mface_large},
218 {"x-large", &mface_x_large},
219 {"xx-large", &mface_xx_large},
220 {"xxx-large", &face_xxx_large},
222 {"Menu Family", NULL},
223 {"courier", &face_courier},
224 {"helvetica", &face_helvetica},
225 {"times", &face_times},
226 {"dv-ttyogesh", &face_dv_ttyogesh},
227 {"freesans", &face_freesans},
228 {"freeserif", &face_freeserif},
229 {"freemono", &face_freemono},
231 {"Menu Style", NULL},
232 {"medium", &mface_medium},
233 {"bold", &mface_bold},
234 {"italic", &mface_italic},
236 {"Menu Color", NULL},
237 {"black", &mface_black},
238 {"white", &mface_white},
240 {"green", &mface_green},
241 {"blue", &mface_blue},
242 {"cyan", &mface_cyan},
243 {"yello", &mface_yellow},
244 {"magenta", &mface_magenta},
247 {"normal", &mface_normal_video},
248 {"reverse", &mface_reverse_video},
249 {"underline", &mface_underline},
251 {"No CTL", &face_no_ctl_fontset} };
254 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
256 /* Information about a physical line metric. */
259 int from; /* BOL position of the line. */
260 int to; /* BOL position of the next line. */
261 int y0, y1; /* Top and bottom Y position of the line. */
262 int ascent; /* Height of the top Y position. */
265 struct LineInfo top; /* Topmost line. */
266 struct LineInfo cur; /* Line containing cursor. */
267 struct LineInfo sel_start; /* Line containing selection start. */
268 struct LineInfo sel_end; /* Line containing selection end. */
270 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
272 /* X position to keep on vertical (up and down) cursor motion. */
273 int target_x_position;
275 /* Interface macros for m17n-lib drawing routines. */
277 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
278 coordinate ($X, $Y) */
279 #define DRAW_TEXT(x, y, from, to) \
280 mdraw_text_with_control \
281 (frame, (MDrawWindow) win, \
282 control.orientation_reversed ? x + win_width : x, y, \
283 mt, from, to, &control)
285 /* Store the extents of a text in the range $FROM to $TO in the
286 structure $RECT (type MDrawMetric). */
287 #define TEXT_EXTENTS(from, to, rect) \
288 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
290 /* Store the glyph information of a character at the position $POS in
291 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
292 $FROM is written at the coordinate (0, 0). */
293 #define GLYPH_INFO(from, pos, info) \
294 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
296 /* Set $X and $Y to the coordinate of character at position $POS
297 assuming that the text from $FROM is written at the coordinate (0,
299 #define COORDINATES_POSITION(from, pos, x, y) \
300 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
302 /* Interface macros for X library. */
303 #define COPY_AREA(y0, y1, to) \
304 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
306 #define CLEAR_AREA(x, y, w, h) \
307 XClearArea (display, win, (x), (y), (w), (h), False)
309 #define SELECTEDP() \
310 mtext_property_mtext (selection)
312 /* Format MSG by FMT and print the result to the stderr, and exit. */
313 #define FATAL_ERROR(fmt, arg) \
315 fprintf (stderr, fmt, arg); \
320 /* If POS is greater than zero, move POS back to the beginning of line
321 (BOL) position. If FORWARD is nonzero, move POS forward instead.
322 Return the new position. */
324 bol (int pos, int forward)
326 int limit = forward ? nchars : 0;
328 pos = mtext_character (mt, pos, limit, '\n');
329 return (pos < 0 ? limit : pos + 1);
332 /* Update the structure #TOP (struct LineInfo) to make $POS the first
333 character position of the screen. */
337 int from = bol (pos, 0);
340 GLYPH_INFO (from, pos, info);
341 top.from = info.line_from;
342 top.to = info.line_to;
344 top.y1 = info.metrics.height;
345 top.ascent = - info.metrics.y;
349 /* Update the scroll bar so that the text of the range $FROM to $TO
350 are shown on the window. */
352 update_scroll_bar (int from, int to)
354 float top = (float) from / nchars;
355 float shown = (float) (to - from) / nchars;
356 XtArgVal *l_top = (XtArgVal *) ⊤
357 XtArgVal *l_shown = (XtArgVal *) &shown;
359 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
360 XtSetArg (arg[1], XtNshown, *l_shown);
361 XtSetValues (SbarWidget, arg, 2);
365 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
366 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
367 is nonzero, update the scoll bar. */
369 redraw (int y0, int y1, int clear, int scroll_bar)
374 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
375 struct LineInfo *line;
377 if (clear || control.anti_alias)
378 CLEAR_AREA (0, y0, win_width, y1 - y0);
380 /* Find a line closest to y0. It is a cursor line if the cursor is
381 Y0, otherwise the top line. */
386 /* If there exists a selected region, check it too. */
387 if (sel_y0 > line->y0 && y0 >= sel_y0)
392 info.metrics.height = line->y1 - y;
393 info.metrics.y = - line->ascent;
394 info.line_to = line->to;
395 while (y + info.metrics.height <= y0)
397 y += info.metrics.height;
401 GLYPH_INFO (from, from, info);
403 if (y + info.metrics.height <= y0)
406 y0 = y - info.metrics.y;
408 while (to < nchars && y < y1)
410 GLYPH_INFO (to, to, info);
411 y += info.metrics.height;
417 DRAW_TEXT (0, y0, from, to);
422 GLYPH_INFO (to, to, info);
423 if (y + info.metrics.height >= win_height)
426 y += info.metrics.height;
428 update_scroll_bar (top.from, to);
433 /* Set the current input method spot to the correct position. */
435 set_input_method_spot ()
437 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
438 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
441 int size = 0, ratio = 0, i;
444 n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
446 for (i = n - 1; i >= 0; i--)
449 size = (int) mface_get_prop (faces[i], Msize);
451 ratio = (int) mface_get_prop (faces[i], Mratio);
454 size = default_font_size;
456 size = size * ratio / 100;
457 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
458 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
463 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
466 redraw_cursor (int clear)
468 if (control.cursor_bidi)
470 /* We must update the whole line of the cursor. */
471 int beg = bol (cur.from, 0);
472 int end = bol (cur.to - 1, 1);
474 int y0 = cur.y0, y1 = cur.y1;
478 TEXT_EXTENTS (beg, cur.from, rect);
483 TEXT_EXTENTS (cur.to, end, rect);
486 redraw (y0, y1, clear, 0);
494 if (control.orientation_reversed)
495 x += win_width - cursor.logical_width;
496 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
498 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
503 /* Update the information about the location of cursor to the position
504 $POS. If $FULL is nonzero, update the information fully only from
505 the information about the top line. Otherwise, trust the current
506 information in the structure $CUR. */
508 update_cursor (int pos, int full)
514 /* CUR is inaccurate. We can trust only TOP. */
515 GLYPH_INFO (top.from, pos, cursor);
516 cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
518 else if (pos < cur.from)
520 int from = bol (pos, 0);
522 TEXT_EXTENTS (from, cur.from, rect);
523 GLYPH_INFO (from, pos, cursor);
524 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
526 else if (pos < cur.to)
528 GLYPH_INFO (cur.from, pos, cursor);
532 GLYPH_INFO (cur.from, pos, cursor);
533 cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
536 cur.from = cursor.line_from;
537 cur.to = cursor.line_to;
538 cur.y1 = cur.y0 + cursor.metrics.height;
539 cur.ascent = - cursor.metrics.y;
543 /* Update the information about the selected region. */
553 from = mtext_property_start (selection);
554 to = mtext_property_end (selection);
558 int pos = bol (from, 0);
560 TEXT_EXTENTS (pos, top.from, rect);
561 sel_start.y0 = top.y0 - rect.height;
562 sel_start.ascent = - rect.y;
563 GLYPH_INFO (pos, from, info);
564 if (pos < info.line_from)
565 sel_start.y0 += - rect.y + info.y + info.metrics.y;
569 GLYPH_INFO (top.from, from, info);
570 sel_start.y0 = top.ascent + info.y + info.metrics.y;
572 sel_start.ascent = -info.metrics.y;
573 sel_start.y1 = sel_start.y0 + info.metrics.height;
574 sel_start.from = info.line_from;
575 sel_start.to = info.line_to;
577 if (to <= sel_start.to)
583 GLYPH_INFO (sel_start.from, to, info);
584 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
585 sel_end.y1 = sel_end.y0 + info.metrics.height;
586 sel_end.ascent = - info.metrics.y;
587 sel_end.from = info.line_from;
588 sel_end.to = info.line_to;
593 /* Select the text in the region from $FROM to $TO. */
595 select_region (int from, int to)
600 pos = from, from = to, to = pos;
601 mtext_push_property (mt, from, to, selection);
606 /* Setup the window to display the character of $POS at the top left
612 /* Top and bottom Y positions to redraw. */
615 if (pos + 1000 < top.from)
616 y0 = 0, y1 = win_height;
617 else if (pos < top.from)
620 TEXT_EXTENTS (pos, top.from, rect);
621 if (rect.height >= win_height * 0.9)
626 COPY_AREA (0, win_height - y1, y1);
629 else if (pos < top.to)
631 /* No need of redrawing. */
634 else if (pos < top.from + 1000)
636 TEXT_EXTENTS (top.from, pos, rect);
637 if (rect.height >= win_height * 0.9)
641 y0 = win_height - rect.height;
642 COPY_AREA (rect.height, win_height, 0);
647 y0 = 0, y1 = win_height;
653 update_cursor (pos, 1);
655 update_cursor (cursor.from, 1);
657 redraw (y0, y1, 1, 1);
661 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
664 /* Select an input method accoding to $IDX. If $IDX is negative, turn
665 off the current input method, otherwide turn on the input method
666 input_method_table[$IDX]. */
668 select_input_method (idx)
670 int previous_input_method = current_input_method;
672 if (idx == current_input_method)
674 if (current_input_method >= 0)
676 minput_destroy_ic (current_input_context);
677 current_input_context = NULL;
678 current_input_method = -1;
682 && input_method_table[idx].available >= 0)
684 InputMethodInfo *im = input_method_table + idx;
686 if (im->available == 0)
689 im->im = minput_open_im (im->language, im->name, NULL);
692 MInputXIMArgIM arg_xim;
694 arg_xim.display = display;
696 arg_xim.res_name = arg_xim.res_class = NULL;
697 arg_xim.locale = NULL;
698 arg_xim.modifier_list = NULL;
699 im->im = minput_open_im (Mnil, im->name, &arg_xim);
701 im->available = im->im ? 1 : -1;
705 if (im->language == Mnil)
707 MInputXIMArgIC arg_xic;
708 Window win = XtWindow (TextWidget);
710 arg_xic.input_style = 0;
711 arg_xic.client_win = arg_xic.focus_win = win;
712 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
713 current_input_context = minput_create_ic (im->im, &arg_xic);
717 MInputGUIArgIC arg_ic;
719 arg_ic.frame = frame;
720 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
721 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
722 current_input_context = minput_create_ic (im->im, &arg_ic);
725 if (current_input_context)
727 current_input_method = idx;
728 set_input_method_spot ();
732 minput_close_im (im->im);
735 current_input_method = -1;
739 if (! auto_input_method)
741 XtSetArg (arg[0], XtNleftBitmap, None);
742 if (previous_input_method >= 0)
743 XtSetValues (InputMethodMenus[previous_input_method + 2], arg, 1);
745 XtSetValues (InputMethodMenus[0], arg, 1);
746 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
747 if (current_input_method >= 0)
748 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
750 XtSetValues (InputMethodMenus[0], arg, 1);
753 if (current_input_method >= 0)
757 XtSetArg (arg[0], XtNlabel, &label);
758 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
759 XtSetArg (arg[0], XtNlabel, label);
763 XtSetArg (arg[0], XtNlabel, "");
765 XtSetValues (CurIMLang, arg, 1);
768 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
771 /* Display cursor according to the current information of #CUR.
772 $CLIENT_DATA is ignore. Most callback functions add this function
773 as a background processing procedure the current application (by
774 XtAppAddWorkProc) via the function hide_cursor. */
776 show_cursor (XtPointer client_data)
778 MFaceHLineProp *hline;
784 update_cursor (cursor.from, 1);
786 while (cur.y1 > win_height)
789 update_cursor (cursor.from, 1);
792 control.cursor_pos = cursor.from;
795 control.with_cursor = 1;
798 if (current_input_context)
799 set_input_method_spot ();
803 int pos = (SELECTEDP () ? mtext_property_start (selection)
804 : cursor.from > 0 ? cursor.from - 1
806 MFace *face = mface ();
807 MTextProperty *props[256];
808 int n = mtext_get_properties (mt, pos, Mface, props, 256);
810 char buf[256], *p = buf;
816 int size = (int) mfont_get_prop (cursor.font, Msize);
817 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
818 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
819 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
820 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
822 sprintf (p, "%dpt", size / 10), p += strlen (p);
824 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
826 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
828 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
830 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
834 mface_merge (face, face_default);
835 for (i = 0; i < n; i++)
836 if (props[i] != selection)
837 mface_merge (face, (MFace *) mtext_property_value (props[i]));
838 sym = (MSymbol) mface_get_prop (face, Mforeground);
840 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
841 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
842 strcat (p, ",rev"), p += strlen (p);
843 hline = mface_get_prop (face, Mhline);
844 if (hline && hline->width > 0)
845 strcat (p, ",ul"), p += strlen (p);
846 box = mface_get_prop (face, Mbox);
847 if (box && box->width > 0)
848 strcat (p, ",box"), p += strlen (p);
849 m17n_object_unref (face);
851 XtSetArg (arg[0], XtNborderWidth, 1);
852 XtSetArg (arg[1], XtNlabel, buf);
853 XtSetValues (CurFaceWidget, arg, 2);
856 if (control.cursor_pos < nchars)
858 MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
862 XtSetArg (arg[0], XtNborderWidth, 0);
863 XtSetArg (arg[1], XtNlabel, "");
867 XtSetArg (arg[0], XtNborderWidth, 1);
868 XtSetArg (arg[1], XtNlabel, mlanguage_name (sym));
869 XtSetValues (CurLangWidget, arg, 2);
871 XtSetValues (CurLangWidget, arg, 2);
873 if (auto_input_method)
876 select_input_method (-1);
881 for (i = 0; i < num_input_methods; i++)
882 if (input_method_table[i].language == sym
883 && input_method_table[i].available >= 0)
885 if (i < num_input_methods)
886 select_input_method (i);
888 select_input_method (-1);
893 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
899 /* Hide the cursor. */
903 control.with_cursor = 0;
905 XtAppAddWorkProc (context, show_cursor, NULL);
909 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
910 $Y1 and $NEW_Y1 assuming that the text in the other area is not
913 update_region (int y0, int old_y1, int new_y1)
919 if (old_y1 < win_height)
921 COPY_AREA (old_y1, win_height, new_y1);
922 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
925 redraw (new_y1, win_height, 1, 0);
927 else if (new_y1 > old_y1)
929 if (new_y1 < win_height)
930 COPY_AREA (old_y1, win_height, new_y1);
932 if (new_y1 > win_height)
934 redraw (y0, new_y1, 1, 1);
938 /* Delete the next $N characters. If $N is negative delete the
939 precious (- $N) characters. */
945 int y0, old_y1, new_y1;
947 int line_from = cursor.line_from;
950 from = cursor.from, to = from + n;
953 from = cursor.from + n;
955 if (cursor.from == cur.from)
957 /* We are at the beginning of line. */
958 int pos = cursor.prev_from;
960 if (cursor.from == top.from)
962 /* We are at the beginning of screen. We must scroll
964 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
965 reseat (info.line_from);
967 update_cursor (pos, 1);
971 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
972 old_y1 = cur.y0 + rect.height;
974 /* Now delete a character. */
975 mtext_del (mt, from, to);
977 if (from >= top.from && from < top.to)
978 update_top (top.from);
979 update_cursor (from, 1);
982 if (line_from != cursor.line_from)
985 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
986 new_y1 = cur.y0 + rect.height;
988 update_region (cur.y0, old_y1, new_y1);
992 /* Insert M-text $NEWTEXT at the current cursor position. */
994 insert_chars (MText *newtext)
996 int n = mtext_len (newtext);
998 int y0, old_y1, new_y1;
1003 int n = (mtext_property_end (selection)
1004 - mtext_property_start (selection));
1005 mtext_detach_property (selection);
1010 if (cursor.line_from > 0
1011 && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
1012 y0 -= control.min_line_descent;
1014 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1015 old_y1 = y0 + rect.height;
1017 line_from = cursor.line_from;
1019 /* Now insert chars. */
1020 mtext_ins (mt, cursor.from, newtext);
1022 if (cur.from == top.from)
1023 update_top (top.from);
1024 update_cursor (cursor.from + n, 1);
1026 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1027 new_y1 = cur.y0 + rect.height;
1029 update_region (y0, old_y1, new_y1);
1030 update_selection ();
1035 word_constituent_p (int c)
1037 MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
1038 char *name = category != Mnil ? msymbol_name (category) : NULL;
1040 return (name && (name[0] == 'L' || name[0] == 'M'));
1047 int pos = cursor.from;
1049 while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
1053 MTextProperty *prop = mtext_get_property (mt, pos, Mword);
1056 pos = mtext_property_end (prop);
1058 while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
1061 update_cursor (pos, 0);
1067 int pos = cursor.from;
1069 while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
1073 MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
1076 pos = mtext_property_start (prop);
1078 while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
1081 update_cursor (pos, 0);
1085 /* Convert the currently selected text to UTF8-STRING or
1086 COMPOUND-TEXT. It is called when someone requests the current
1087 value of the selection. */
1089 covert_selection (Widget w, Atom *selection_atom,
1090 Atom *target, Atom *return_type,
1091 XtPointer *value, unsigned long *length, int *format)
1093 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1094 MText *this_mt = mtext ();
1095 int from = mtext_property_start (selection);
1096 int to = mtext_property_end (selection);
1100 mtext_copy (this_mt, 0, mt, from, to);
1101 if (*target == XA_TEXT)
1103 #ifdef X_HAVE_UTF8_STRING
1104 coding = Mcoding_utf_8;
1105 *return_type = XA_UTF8_STRING;
1107 coding = Mcoding_compound_text;
1108 *return_type = XA_COMPOUND_TEXT;
1111 else if (*target == XA_UTF8_STRING)
1113 coding = Mcoding_utf_8;
1114 *return_type = XA_UTF8_STRING;
1116 else if (*target == XA_STRING)
1121 for (i = 0; i < len; i++)
1122 if (mtext_ref_char (this_mt, i) >= 0x100)
1123 /* Can't encode in XA_STRING */
1125 coding = Mcoding_iso_8859_1;
1126 *return_type = XA_STRING;
1128 else if (*target == XA_COMPOUND_TEXT)
1130 coding = Mcoding_compound_text;
1131 *return_type = XA_COMPOUND_TEXT;
1136 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1137 m17n_object_unref (this_mt);
1141 *value = (XtPointer) buf;
1147 /* Unselect the text. It is called when we loose the selection. */
1149 lose_selection (Widget w, Atom *selection_atom)
1153 mtext_detach_property (selection);
1154 redraw (sel_start.y0, sel_end.y1, 1, 0);
1159 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1160 XtPointer value, unsigned long *length, int *format)
1165 if (*type == XT_CONVERT_FAIL || ! value)
1167 if (*type == XA_STRING)
1169 else if (*type == XA_COMPOUND_TEXT)
1170 coding = msymbol ("compound-text");
1171 #ifdef X_HAVE_UTF8_STRING
1172 else if (*type == XA_UTF8_STRING)
1173 coding = msymbol ("utf-8");
1178 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1179 if (! this_mt && *type != XA_UTF8_STRING)
1181 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1188 insert_chars (this_mt);
1189 m17n_object_unref (this_mt);
1198 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1200 XExposeEvent *expose = (XExposeEvent *) event;
1204 Dimension width_max, width;
1206 XtSetArg (arg[0], XtNwidth, &width);
1207 XtGetValues (XtParent (w), arg, 1);
1209 XtGetValues (HeadWidget, arg, 1);
1210 if (width_max < width)
1212 XtGetValues (FaceWidget, arg, 1);
1213 if (width_max < width)
1215 XtGetValues (LangWidget, arg, 1);
1216 if (width_max < width)
1218 XtSetArg (arg[0], XtNwidth, width_max);
1219 XtSetValues (HeadWidget, arg, 1);
1220 XtSetValues (FaceWidget, arg, 1);
1221 XtSetValues (LangWidget, arg, 1);
1222 XtSetValues (XtParent (w), arg, 1);
1223 XtSetValues (TailWidget, arg, 1);
1226 update_cursor (0, 1);
1227 redraw (0, win_height, 0, 1);
1228 if (current_input_method >= 0)
1230 int idx = current_input_method;
1232 current_input_method = -1;
1233 select_input_method (idx);
1239 redraw (expose->y, expose->y + expose->height, 0, 0);
1240 if (current_input_context
1241 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1242 set_input_method_spot ();
1247 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1249 XConfigureEvent *configure = (XConfigureEvent *) event;
1252 control.max_line_width = win_width = configure->width;
1253 win_height = configure->height;
1254 mdraw_clear_cache (mt);
1256 update_cursor (0, 1);
1257 redraw (0, win_height, 1, 1);
1258 if (current_input_context)
1259 set_input_method_spot ();
1263 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1266 int x = event->xbutton.x;
1267 int y = event->xbutton.y - top.ascent;
1269 if (control.orientation_reversed)
1271 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1274 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1275 mtext_detach_property (selection);
1276 redraw (sel_start.y0, sel_end.y1, 1, 0);
1279 if (current_input_context
1280 && minput_filter (current_input_context, Minput_focus_move, NULL) == 0)
1282 MText *produced = mtext ();
1284 minput_lookup (current_input_context, Mnil, NULL, produced);
1285 if (mtext_len (produced) > 0)
1287 insert_chars (produced);
1288 if (pos >= cursor.from)
1289 pos += mtext_len (produced);
1291 m17n_object_unref (produced);
1293 update_cursor (pos, 0);
1298 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1303 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1304 covert_selection, lose_selection, NULL);
1305 update_cursor (mtext_property_start (selection), 0);
1310 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1314 /* We don't have a local selection. */
1315 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1320 int from = mtext_property_start (selection);
1321 int to = mtext_property_end (selection);
1324 int x = event->xbutton.x;
1325 int y = event->xbutton.y - top.ascent;
1327 if (control.orientation_reversed)
1329 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1331 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1332 mtext_detach_property (selection);
1334 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1335 update_cursor (pos, 0);
1336 insert_chars (this_mt);
1337 m17n_object_unref (this_mt);
1342 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1345 int x = event->xbutton.x;
1346 int y = event->xbutton.y;
1348 if (control.orientation_reversed)
1351 pos = top.from, y -= top.ascent;
1353 pos = cur.from, y -= cur.y0 + cur.ascent;
1354 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1356 if (pos == cursor.from)
1362 /* Selection range changed. */
1363 int from = mtext_property_start (selection);
1364 int to = mtext_property_end (selection);
1365 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1366 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1368 if (cursor.from == from)
1370 /* Starting position changed. */
1373 /* Enlarged. We can simply overdraw. */
1374 select_region (pos, to);
1375 redraw (sel_start.y0, start_y1, 0, 0);
1379 /* Shrunken. Previous selection face must be cleared. */
1380 select_region (pos, to);
1381 redraw (start_y0, sel_start.y1, 1, 0);
1385 /* Shrunken to zero. */
1386 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1387 mtext_detach_property (selection);
1388 redraw (start_y0, end_y1, 1, 0);
1392 /* Full update is necessary. */
1393 select_region (to, pos);
1394 redraw (start_y0, sel_end.y1, 1, 0);
1399 /* Ending position changed. */
1402 /* Full update is necessary. */
1403 select_region (pos, from);
1404 redraw (sel_start.y0, end_y1, 1, 0);
1406 else if (pos == from)
1408 /* Shrunken to zero. */
1409 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1410 mtext_detach_property (selection);
1411 redraw (start_y0, end_y1, 1, 0);
1415 /* Shrunken. Previous selection face must be cleared. */
1416 select_region (from, pos);
1417 redraw (sel_end.y0, end_y1, 1, 0);
1421 /* Enlarged. We can simply overdraw. */
1422 select_region (from, pos);
1423 redraw (end_y0, sel_end.y1, 0, 0);
1429 /* Newly selected. */
1430 select_region (pos, cursor.from);
1431 redraw (sel_start.y0, sel_end.y1, 0, 0);
1433 update_cursor (pos, 1);
1437 FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num)
1439 if (current_input_context
1440 && minput_filter (current_input_context, Minput_focus_in, NULL) == 0)
1442 MText *produced = mtext ();
1444 minput_lookup (current_input_context, Mnil, NULL, produced);
1445 if (mtext_len (produced) > 0)
1448 insert_chars (produced);
1450 m17n_object_unref (produced);
1455 FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num)
1457 if (current_input_context
1458 && minput_filter (current_input_context, Minput_focus_out, NULL) == 0)
1460 MText *produced = mtext ();
1462 minput_lookup (current_input_context, Mnil, NULL, produced);
1463 if (mtext_len (produced) > 0)
1466 insert_chars (produced);
1468 m17n_object_unref (produced);
1473 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1476 MDrawGlyphInfo info;
1478 int cursor_pos = cursor.from;
1480 if (((int) position) < 0)
1486 height = top.y1 - top.y0;
1489 pos = bol (from - 1, 0);
1490 GLYPH_INFO (pos, from - 1, info);
1491 if (height + info.metrics.height > win_height)
1493 height += info.metrics.height;
1494 from = info.line_from;
1496 if (cursor_pos >= top.to)
1498 cursor_pos = top.from;
1500 while (cursor_pos < nchars)
1502 GLYPH_INFO (pos, pos, info);
1503 if (height + info.metrics.height > win_height)
1505 height += info.metrics.height;
1511 else if (cur.to < nchars)
1513 /* Scroll up, but leave at least one line. */
1516 while (from < nchars)
1518 GLYPH_INFO (from, from, info);
1519 if (height + info.metrics.height > win_height
1520 || info.line_to >= nchars)
1522 height += info.metrics.height;
1523 from = info.line_to;
1526 from = info.line_from;
1527 if (cursor_pos < from)
1531 /* Scroll up to make the cursor line top. */
1535 update_cursor (cursor_pos, 1);
1539 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1541 float persent = *(float *) persent_ptr;
1542 int pos1, pos2 = nchars * persent;
1543 MDrawGlyphInfo info;
1546 pos1 = bol (pos2, 0);
1547 GLYPH_INFO (pos1, pos2, info);
1548 pos1 = info.line_from;
1550 update_cursor (pos1, 1);
1555 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1557 XKeyEvent *key_event = (XKeyEvent *) event;
1559 KeySym keysym = NoSymbol;
1561 /* If set to 1, do not update target_x_position. */
1562 int keep_target_x_position = 0;
1564 int y0, old_y1, new_y1;
1571 if (current_input_context
1572 && minput_filter (current_input_context, Mnil, event))
1577 update_region (y0, old_y1, new_y1);
1581 if (event->type == KeyRelease)
1584 produced = mtext ();
1585 ret = minput_lookup (current_input_context, Mnil, event, produced);
1586 if (mtext_len (produced) > 0)
1587 insert_chars (produced);
1589 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1590 m17n_object_unref (produced);
1600 n = (mtext_property_end (selection)
1601 - mtext_property_start (selection));
1602 mtext_detach_property (selection);
1604 else if (cursor.from < nchars)
1606 /* Delete the following grapheme cluster. */
1607 n = cursor.to - cursor.from;
1620 /* Delete selected region. */
1621 n = (mtext_property_end (selection)
1622 - mtext_property_start (selection));
1623 mtext_detach_property (selection);
1625 else if (cursor.from > 0)
1627 /* Delete the preceding character. */
1638 mtext_detach_property (selection);
1639 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1643 if (cursor.prev_from >= 0)
1644 update_cursor (cursor.prev_from, 0);
1648 if (cursor.left_from >= 0)
1649 update_cursor (cursor.left_from, 0);
1656 mtext_detach_property (selection);
1657 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1661 if (cursor.next_to >= 0)
1662 update_cursor (cursor.to, 0);
1666 if (cursor.right_from >= 0)
1667 update_cursor (cursor.right_from, 0);
1674 mtext_detach_property (selection);
1675 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1677 if (cur.to <= nchars)
1679 MDrawGlyphInfo info;
1682 GLYPH_INFO (cur.from, cur.to, info);
1683 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1684 target_x_position, info.y);
1685 keep_target_x_position = 1;
1686 update_cursor (pos, 0);
1693 mtext_detach_property (selection);
1694 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1700 int pos = bol (cur.from - 1, 0);
1702 TEXT_EXTENTS (pos, cur.from - 1, rect);
1703 y = rect.height + rect.y - 1;
1704 pos = COORDINATES_POSITION (pos, nchars,
1705 target_x_position, y);
1706 keep_target_x_position = 1;
1707 update_cursor (pos, 0);
1714 mtext_detach_property (selection);
1715 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1717 if (top.from < nchars)
1718 ScrollProc (w, NULL, (XtPointer) 1);
1724 mtext_detach_property (selection);
1725 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1728 ScrollProc (w, NULL, (XtPointer) -1);
1732 if (key_event->state >= Mod1Mask)
1734 lose_selection (NULL, NULL);
1740 if (key_event->state >= Mod1Mask)
1742 lose_selection (NULL, NULL);
1750 if (buf[0] == 17) /* C-q */
1752 XtAppSetExitFlag (context);
1755 else if (buf[0] == 12) /* C-l */
1757 redraw (0, win_height, 1, 1);
1762 MText *temp = mtext ();
1764 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1765 : ((unsigned char *) buf)[0]);
1766 if (current_input_context)
1767 mtext_put_prop (temp, 0, 1, Mlanguage,
1768 current_input_context->im->language);
1769 insert_chars (temp);
1770 m17n_object_unref (temp);
1775 if (! keep_target_x_position)
1776 target_x_position = cursor.x;
1780 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1782 char *name = (char *) client_data;
1784 int from = -1, to = 0;
1789 filename = strdup (name);
1792 fp = fopen (filename, "w");
1795 fprintf (stderr, "Open for write fail: %s", filename);
1801 from = mtext_property_start (selection);
1802 to = mtext_property_end (selection);
1803 mtext_detach_property (selection);
1806 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1809 select_region (from, to);
1813 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1819 mtext_detach_property (selection);
1820 serialized = (int) client_data;
1822 new = mtext_deserialize (mt);
1825 MPlist *plist = mplist ();
1827 mplist_push (plist, Mt, Mface);
1828 mplist_push (plist, Mt, Mlanguage);
1829 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1830 m17n_object_unref (plist);
1834 m17n_object_unref (mt);
1836 serialized = ! serialized;
1837 nchars = mtext_len (mt);
1840 update_cursor (0, 1);
1841 redraw (0, win_height, 1, 1);
1845 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1847 XtAppSetExitFlag (context);
1853 FILE *fp = fopen (filename, "r");
1856 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1857 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1860 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1865 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1867 int data = (int) client_data;
1872 control.enable_bidi = 0;
1873 control.orientation_reversed = 0;
1877 control.enable_bidi = 1;
1878 control.orientation_reversed = data == 2;
1880 for (i = 0; i < 3; i++)
1883 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1885 XtSetArg (arg[0], XtNleftBitmap, None);
1886 XtSetValues (BidiMenus[i], arg, 1);
1889 update_cursor (cursor.from, 1);
1890 redraw (0, win_height, 1, 0);
1894 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1896 int data = (int) client_data;
1900 control.max_line_width = 0;
1903 control.max_line_width = win_width;
1904 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1906 for (i = 0; i < 3; i++)
1909 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1911 XtSetArg (arg[0], XtNleftBitmap, None);
1912 XtSetValues (LineBreakMenus[i], arg, 1);
1915 update_cursor (cursor.from, 1);
1916 redraw (0, win_height, 1, 0);
1920 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1922 char *filter_module = (char *) client_data;
1924 void (*func) (MText *, int, int);
1928 handle = dlopen (filter_module, RTLD_NOW);
1931 *(void **) (&func) = dlsym (handle, "filter");
1933 (*func) (mt, mtext_property_start (selection),
1934 mtext_property_end (selection));
1939 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1941 int data = (int) client_data;
1955 control.cursor_bidi = 0, control.cursor_width = -1;
1959 control.cursor_bidi = 0, control.cursor_width = 2;
1963 control.cursor_bidi = 1;
1968 for (i = from; i < to; i++)
1971 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1973 XtSetArg (arg[0], XtNleftBitmap, None);
1974 XtSetValues (CursorMenus[i], arg, 1);
1977 update_cursor (cursor.from, 0);
1978 redraw (0, win_height, 1, 0);
1982 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1984 int idx = (int) client_data;
1986 if (idx == -2 ? (! auto_input_method && current_input_method < 0)
1987 : idx == -1 ? auto_input_method
1988 : idx == current_input_method)
1991 if (auto_input_method)
1993 select_input_method (-1);
1994 XtSetArg (arg[0], XtNleftBitmap, None);
1995 XtSetValues (InputMethodMenus[1], arg, 1);
1996 auto_input_method = 0;
2001 select_input_method (-1);
2002 XtSetArg (arg[0], XtNleftBitmap, None);
2003 XtSetValues (InputMethodMenus[0], arg, 1);
2004 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
2005 XtSetValues (InputMethodMenus[1], arg, 1);
2006 auto_input_method = 1;
2011 select_input_method (idx);
2015 MPlist *default_face_list;
2018 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
2020 int idx = (int) client_data;
2031 MFace *face = mframe_get_prop (frame, Mface);
2033 for (plist = default_face_list; mplist_key (plist) != Mnil;
2034 plist = mplist_next (plist))
2035 mface_merge (face, mplist_value (plist));
2036 mplist_add (plist, Mt, *face_table[idx].face);
2037 mface_merge (face, *face_table[idx].face);
2039 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
2041 MFace *face = mframe_get_prop (frame, Mface);
2043 for (plist = default_face_list;
2044 mplist_key (mplist_next (plist)) != Mnil;
2045 plist = mplist_next (plist))
2046 mface_merge (face, mplist_value (plist));
2050 update_cursor (0, 1);
2051 redraw (0, win_height, 1, 1);
2056 XtAppAddWorkProc (context, show_cursor, NULL);
2057 from = mtext_property_start (selection);
2058 to = mtext_property_end (selection);
2059 old_y1 = sel_end.y1;
2061 mtext_detach_property (selection);
2064 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
2065 MTEXTPROP_REAR_STICKY);
2066 mtext_push_property (mt, from, to, prop);
2067 m17n_object_unref (prop);
2070 mtext_pop_prop (mt, from, to, Mface);
2072 update_top (top.from);
2073 update_cursor (cursor.from, 1);
2074 select_region (from, to);
2075 update_region (sel_start.y0, old_y1, sel_end.y1);
2076 if (cur.y1 > win_height)
2078 while (cur.y1 > win_height)
2081 update_cursor (cursor.from, 1);
2087 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2089 MSymbol sym = (MSymbol) client_data;
2096 XtAppAddWorkProc (context, show_cursor, NULL);
2097 from = mtext_property_start (selection);
2098 to = mtext_property_end (selection);
2099 old_y1 = sel_end.y1;
2101 mtext_detach_property (selection);
2103 mtext_put_prop (mt, from, to, Mlanguage, sym);
2105 mtext_pop_prop (mt, from, to, Mlanguage);
2108 update_top (top.from);
2109 update_cursor (cursor.from, 1);
2110 select_region (from, to);
2111 update_region (sel_start.y0, old_y1, sel_end.y1);
2112 if (cur.y1 > win_height)
2114 while (cur.y1 > win_height)
2117 update_cursor (cursor.from, 1);
2123 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2125 int narrowed = (int) client_data;
2128 MConverter *converter;
2134 from = mtext_property_start (selection);
2135 to = mtext_property_end (selection);
2144 mdump = popen ("mdump -q -p a4", "w");
2146 mdump = popen ("mdump -q", "w");
2149 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2150 mconv_encode_range (converter, mt, from, to);
2151 mconv_free_converter (converter);
2156 input_status (MInputContext *ic, MSymbol command)
2158 XFillRectangle (display, input_status_pixmap, gc_inv,
2159 0, 0, input_status_width, input_status_height);
2160 if (command == Minput_status_draw)
2164 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2165 Mface, face_input_status);
2166 if (ic->im->language != Mnil)
2167 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2168 Mlanguage, ic->im->language);
2169 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2170 &input_status_control, NULL, NULL, &rect);
2171 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2172 input_status_width - rect.width - 2, - rect.y,
2173 ic->status, 0, mtext_len (ic->status),
2174 &input_status_control);
2176 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2177 XtSetValues (CurIMStatus, arg, 1);
2181 surrounding_text_handler (MInputContext *ic, MSymbol command)
2183 if (command == Minput_get_surrounding_text)
2185 int len = (int) mplist_value (ic->plist);
2187 MText *surround = NULL;
2191 pos = cursor.from + len;
2194 surround = mtext_duplicate (mt, pos, cursor.from);
2198 pos = cursor.from + len;
2201 surround = mtext_duplicate (mt, cursor.from, pos);
2205 mplist_set (ic->plist, Mtext, surround);
2206 m17n_object_unref (surround);
2209 else if (command == Minput_delete_surrounding_text)
2211 int len = (int) mplist_value (ic->plist);
2215 if (cursor.from + len < 0)
2216 len = - cursor.from;
2217 mtext_del (mt, cursor.from + len, cursor.from);
2219 update_cursor (cursor.from + len, 1);
2223 if (cursor.from + len > nchars)
2224 len = nchars - cursor.from;
2225 mtext_del (mt, cursor.from, cursor.from + len);
2227 update_cursor (cursor.from, 1);
2235 compare_input_method (const void *elt1, const void *elt2)
2237 const InputMethodInfo *im1 = elt1;
2238 const InputMethodInfo *im2 = elt2;
2239 MSymbol lang1, lang2;
2241 if (im1->language == Mnil)
2243 if (im1->language == im2->language)
2244 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2245 if (im1->language == Mt)
2247 if (im2->language == Mt)
2249 lang1 = mlanguage_name (im1->language);
2250 lang2 = mlanguage_name (im2->language);
2251 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2255 setup_input_methods (int with_xim, char *initial_input_method)
2257 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2261 num_input_methods = plist ? mplist_length (plist) : 0;
2263 num_input_methods++;
2264 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2269 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
2271 MDatabase *mdb = mplist_value (pl);
2272 MSymbol *tag = mdatabase_tag (mdb);
2275 i--, num_input_methods--;
2278 input_method_table[i].language = tag[1];
2279 input_method_table[i].name = tag[2];
2282 m17n_object_unref (plist);
2286 input_method_table[i].language = Mnil;
2287 input_method_table[i].name = msymbol ("xim");
2291 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2292 compare_input_method);
2293 mplist_put (minput_driver->callback_list, Minput_status_start,
2294 (void *) input_status);
2295 mplist_put (minput_driver->callback_list, Minput_status_draw,
2296 (void *) input_status);
2297 mplist_put (minput_driver->callback_list, Minput_status_done,
2298 (void *) input_status);
2299 mplist_put (minput_driver->callback_list, Minput_get_surrounding_text,
2300 (void *) surrounding_text_handler);
2301 mplist_put (minput_driver->callback_list, Minput_delete_surrounding_text,
2302 (void *) surrounding_text_handler);
2304 current_input_context = NULL;
2305 current_input_method = -1;
2307 if (initial_input_method)
2309 char *lang_name, *method_name;
2310 char *p = strchr (initial_input_method, '-');
2313 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2315 lang_name = "t", method_name = initial_input_method;
2317 for (i = 0; i < num_input_methods; i++)
2318 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2320 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2322 current_input_method = i;
2330 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2334 if (num && *num > 0)
2338 for (i = 0; i < *num; i++)
2339 bytes += strlen (str[i]) + 1;
2340 msg = alloca (bytes);
2341 strcpy (msg, str[0]);
2342 for (i = 1; i < *num; i++)
2343 strcat (msg, " "), strcat (msg, str[i]);
2345 else if (cursor.from < nchars)
2347 int c = mtext_ref_char (mt, cursor.from);
2348 char *name = mchar_get_prop (c, Mname);
2352 msg = alloca (10 + strlen (name));
2353 sprintf (msg, "U+%04X %s", c, name);
2359 XtSetArg (arg[0], XtNlabel, msg);
2360 XtSetValues (MessageWidget, arg, 1);
2366 char *name1, *name2;
2367 XtCallbackProc proc;
2368 XtPointer client_data;
2373 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2375 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2377 MenuRec FileMenu[] =
2378 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2379 { 0, "Save", NULL, SaveProc, NULL, -1 },
2380 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2382 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2383 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2385 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2386 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2388 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2391 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2393 MenuRec *rec = (MenuRec *) client_data;
2396 XtSetArg (arg[0], XtNvalue, "");
2397 XtSetArg (arg[1], XtNlabel, rec->name1);
2398 XtSetValues (FileDialogWidget, arg, 2);
2399 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2400 XtSetArg (arg[0], XtNx, x + 20);
2401 XtSetArg (arg[1], XtNy, y + 10);
2402 XtSetValues (FileShellWidget, arg, 2);
2403 XtPopup (FileShellWidget, XtGrabExclusive);
2407 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2412 XtPopdown (FileShellWidget);
2413 if ((int) client_data == 1)
2415 XtSetArg (arg[0], XtNlabel, &label);
2416 XtGetValues (FileDialogWidget, arg, 1);
2417 if (strcmp (label, FileMenu[0].name1) == 0)
2421 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2422 fp = fopen (filename, "r");
2424 m17n_object_unref (mt);
2427 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2435 nchars = mtext_len (mt);
2437 update_cursor (0, 1);
2438 redraw (0, win_height, 1, 1);
2440 else if (strcmp (label, FileMenu[2].name1) == 0)
2441 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2443 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2446 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2447 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2448 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2449 (MENU).status = (STATUS))
2453 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2454 char *menu_name, MenuRec *menus, int num_menus, char *help)
2456 Widget button, menu;
2457 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2458 <LeaveWindow>: reset() MenuHelp()\n\
2459 <BtnDown>: reset() PopupMenu()\n\
2460 <BtnUp>: highlight()";
2466 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2467 for (i = 0; i < num_menus; i++)
2478 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2480 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2482 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2484 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2488 XtSetArg (arg[0], XtNsensitive, False);
2489 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2495 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2500 trans = alloca (strlen (fmt) + strlen (help));
2501 sprintf (trans, fmt, help);
2502 XtSetArg (arg[0], XtNmenuName, menu_name);
2503 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2504 XtSetArg (arg[2], XtNinternalWidth, 2);
2505 XtSetArg (arg[3], XtNhighlightThickness, 1);
2506 XtSetArg (arg[4], XtNleft, XawChainLeft);
2507 XtSetArg (arg[5], XtNright, XawChainLeft);
2508 XtSetArg (arg[6], XtNinternational, True);
2511 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2512 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2517 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2518 int *len = alloca (sizeof (int) * num_menus);
2521 XFontSetExtents *fontset_extents;
2523 XtSetArg (arg[0], XtNfontSet, &font_set);
2524 XtGetValues (button, arg, 1);
2526 fontset_extents = XExtentsOfFontSet (font_set);
2527 height = fontset_extents->max_logical_extent.height;
2528 ascent = - fontset_extents->max_logical_extent.y;
2530 for (i = 0; i < num_menus; i++)
2533 len[i] = strlen (menus[i].name2);
2534 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2535 if (max_width < width[i])
2536 max_width = width[i];
2538 for (i = 0; i < num_menus; i++)
2541 Pixmap pixmap = XCreatePixmap (display,
2542 RootWindow (display, screen),
2543 max_width, height, 1);
2544 XFillRectangle (display, pixmap, mono_gc_inv,
2545 0, 0, max_width, height);
2546 XmbDrawString (display, pixmap, font_set, mono_gc,
2547 max_width - width[i], ascent,
2548 menus[i].name2, len[i]);
2549 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2550 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2551 XtSetValues (menus[i].w, arg, 2);
2559 XtActionsRec actions[] = {
2560 {"Expose", ExposeProc},
2561 {"Configure", ConfigureProc},
2563 {"ButtonPress", ButtonProc},
2564 {"ButtonRelease", ButtonReleaseProc},
2565 {"ButtonMotion", ButtonMoveProc},
2566 {"Button2Press", Button2Proc},
2567 {"MenuHelp", MenuHelpProc},
2568 {"FocusIn", FocusInProc},
2569 {"FocusOut", FocusOutProc}
2573 /* Print the usage of this program (the name is PROG), and exit with
2577 help_exit (char *prog, int exit_code)
2585 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2586 printf ("Display FILE on a window and allow users to edit it.\n");
2587 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2588 printf ("The following OPTIONs are available.\n");
2589 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2590 "Use the specified fontset\n");
2591 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2592 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2593 "Input method activated initially.\n");
2594 printf (" %-13s %s", "--version", "print version number\n");
2595 printf (" %-13s %s", "-h, --help", "print this message\n");
2601 main (int argc, char **argv)
2603 Widget form, BodyWidget, w;
2604 char *fontset_name = NULL;
2605 char *font_name = NULL;
2607 char *initial_input_method = NULL;
2608 int col = 80, row = 32;
2609 /* Translation table for TextWidget. */
2610 String trans = "<Expose>: Expose()\n\
2611 <Configure>: Configure()\n\
2614 <Btn1Down>: ButtonPress()\n\
2615 <Btn1Up>: ButtonRelease()\n\
2616 <Btn1Motion>: ButtonMotion()\n\
2617 <Btn2Down>: Button2Press()";
2618 /* Translation table for the top form widget. */
2619 String trans2 = "<Key>: Key()\n\
2621 <FocusIn>: FocusIn()\n\
2622 <FocusOut>: FocusOut()";
2623 String pop_face_trans
2624 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2625 <LeaveWindow>: MenuHelp() reset()\n\
2626 <Btn1Down>: set()\n\
2627 <Btn1Up>: notify() unset()";
2628 String pop_lang_trans
2629 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2630 <LeaveWindow>: MenuHelp() reset()\n\
2631 <Btn1Down>: set()\n\
2632 <Btn1Up>: notify() unset()";
2633 int font_width, font_ascent, font_descent;
2636 char *filter = NULL;
2639 setlocale (LC_ALL, "");
2640 /* Create the top shell. */
2641 XtSetLanguageProc (NULL, NULL, NULL);
2642 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2643 NULL, sessionShellWidgetClass, NULL, 0);
2644 display = XtDisplay (ShellWidget);
2645 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2647 /* Parse the remaining command line arguments. */
2648 for (i = 1; i < argc; i++)
2650 if (! strcmp (argv[i], "--help")
2651 || ! strcmp (argv[i], "-h"))
2652 help_exit (argv[0], 0);
2653 else if (! strcmp (argv[i], "--version"))
2655 printf ("m17n-edit (m17n library) %s\n", VERSION);
2656 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2659 else if (! strcmp (argv[i], "--geometry"))
2662 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2663 help_exit (argv[0], 1);
2665 else if (! strcmp (argv[i], "-s"))
2668 fontsize = atoi (argv[i]);
2672 else if (! strcmp (argv[i], "--fontset"))
2675 fontset_name = strdup (argv[i]);
2677 else if (! strcmp (argv[i], "--font"))
2680 font_name = strdup (argv[i]);
2682 else if (! strcmp (argv[i], "--im"))
2685 initial_input_method = strdup (argv[i]);
2687 else if (! strcmp (argv[i], "--with-xim"))
2691 else if (! strcmp (argv[i], "--filter"))
2696 else if (argv[i][0] != '-')
2698 filename = strdup (argv[i]);
2702 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2703 help_exit (argv[0], 1);
2707 filename = strdup ("/dev/null");
2709 mdatabase_dir = ".";
2710 /* Initialize the m17n library. */
2712 if (merror_code != MERROR_NONE)
2713 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2714 minput_driver = &minput_gui_driver;
2716 mt = read_file (filename);
2719 nchars = mtext_len (mt);
2721 Mword = msymbol ("word");
2724 MFace *face = mface ();
2726 mface_put_prop (face, Mforeground, msymbol ("blue"));
2727 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2728 mface_put_prop (face, Mvideomode, Mreverse);
2729 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2730 m17n_object_unref (face);
2733 /* This tells ExposeProc to initialize everything. */
2736 XA_TEXT = XInternAtom (display, "TEXT", False);
2737 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2738 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2739 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2740 if (Mcoding_compound_text == Mnil)
2741 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2744 MPlist *plist = mplist ();
2747 mplist_put (plist, msymbol ("widget"), ShellWidget);
2748 if (fontset_name || font_name || fontsize > 0)
2754 font = mfont_parse_name (font_name, Mnil);
2756 face = mface_from_font (font);
2764 MFontset *fontset = mfontset (fontset_name);
2766 mface_put_prop (face, Mfontset, fontset);
2767 m17n_object_unref (fontset);
2770 mface_put_prop (face, Msize, (void *) fontsize);
2771 mplist_add (plist, Mface, face);
2772 m17n_object_unref (face);
2774 frame = mframe (plist);
2776 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2777 m17n_object_unref (plist);
2778 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2779 default_face_list = mplist ();
2780 mplist_add (default_face_list, Mt, face_default);
2781 face_default_fontset = mface ();
2782 mface_put_prop (face_default_fontset, Mfontset,
2783 mface_get_prop (face_default, Mfontset));
2785 font = (MFont *) mframe_get_prop (frame, Mfont);
2786 default_font_size = (int) mfont_get_prop (font, Msize);
2789 font_width = (int) mframe_get_prop (frame, Mfont_width);
2790 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2791 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2792 win_width = font_width * col;
2793 win_height = (font_ascent + font_descent) * row;
2799 prop.color_top = prop.color_left = msymbol ("magenta");
2800 prop.color_bottom = prop.color_right = msymbol ("red");
2801 prop.inner_hmargin = prop.inner_vmargin = 1;
2802 prop.outer_hmargin = prop.outer_vmargin = 2;
2804 face_box = mface ();
2805 mface_put_prop (face_box, Mbox, &prop);
2808 face_courier = mface ();
2809 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2810 face_helvetica = mface ();
2811 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2812 face_times = mface ();
2813 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2814 face_dv_ttyogesh = mface ();
2815 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2816 face_freesans = mface ();
2817 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2818 face_freeserif = mface ();
2819 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2820 face_freemono = mface ();
2821 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2823 face_xxx_large = mface ();
2824 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2826 MFont *latin_font = mframe_get_prop (frame, Mfont);
2827 MFont *dev_font = mfont ();
2828 MFont *thai_font = mfont ();
2829 MFont *tib_font = mfont ();
2830 MFontset *fontset, *fontset_no_ctl;
2831 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2832 MSymbol no_ctl = msymbol ("no-ctl");
2834 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2835 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2836 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2837 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2838 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2839 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2841 fontset = mfontset (fontset_name);
2842 fontset_no_ctl = mfontset_copy (fontset, "no-ctl");
2843 m17n_object_unref (fontset);
2844 mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil,
2845 latin_font, Mnil, 0);
2846 mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil,
2847 dev_font, no_ctl, 0);
2848 mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil,
2849 thai_font, no_ctl, 0);
2850 mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil,
2851 tib_font, no_ctl, 0);
2852 face_no_ctl_fontset = mface ();
2853 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl);
2854 m17n_object_unref (fontset_no_ctl);
2861 setup_input_methods (with_xim, initial_input_method);
2863 gc = DefaultGC (display, screen);
2865 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2866 XtSetArg (arg[1], XtNdefaultDistance, 2);
2867 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2869 XtSetArg (arg[0], XtNborderWidth, 0);
2870 XtSetArg (arg[1], XtNdefaultDistance, 2);
2871 XtSetArg (arg[2], XtNtop, XawChainTop);
2872 XtSetArg (arg[3], XtNbottom, XawChainTop);
2873 XtSetArg (arg[4], XtNleft, XawChainLeft);
2874 XtSetArg (arg[5], XtNright, XawChainRight);
2875 XtSetArg (arg[6], XtNresizable, True);
2876 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2877 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2878 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2879 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2880 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2881 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2882 XtSetArg (arg[7], XtNfromVert, LangWidget);
2883 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2884 XtSetArg (arg[2], XtNtop, XawChainBottom);
2885 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2886 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2888 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2889 HeadWidget, NULL, 0);
2890 XtSetArg (arg[0], XtNvalue, "");
2891 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2892 FileShellWidget, arg, 1);
2893 XawDialogAddButton (FileDialogWidget, "OK",
2894 FileDialogProc, (XtPointer) 0);
2895 XawDialogAddButton (FileDialogWidget, "CANCEL",
2896 FileDialogProc, (XtPointer) 1);
2898 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2899 (char *) check_bits,
2900 check_width, check_height);
2902 unsigned long valuemask = GCForeground;
2905 values.foreground = 1;
2906 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2907 values.foreground = 0;
2908 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2915 if (num_menus < num_input_methods + 2)
2916 num_menus = num_input_methods + 2;
2917 if (num_menus < num_faces + 1)
2918 num_menus = num_faces + 1;
2919 menus = alloca (sizeof (MenuRec) * num_menus);
2921 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2922 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2923 "File I/O, Serialization, Image, Quit");
2925 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2926 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2927 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2928 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2929 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2930 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2931 w = create_menu_button (ShellWidget, HeadWidget, w,
2932 "Cursor", "Cursor Menu",
2933 menus, 6, "Cursor Movement Mode, Cursor Shape");
2934 CursorMenus[0] = menus[0].w;
2935 CursorMenus[1] = menus[1].w;
2936 CursorMenus[2] = menus[3].w;
2937 CursorMenus[3] = menus[4].w;
2938 CursorMenus[4] = menus[5].w;
2940 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2941 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2942 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2943 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2944 menus, 3, "BIDI Processing Mode");
2945 for (i = 0; i < 3; i++)
2946 BidiMenus[i] = menus[i].w;
2948 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2949 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2950 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2951 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2953 menus, 3, "How to break lines");
2954 for (i = 0; i < 3; i++)
2955 LineBreakMenus[i] = menus[i].w;
2957 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2958 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2959 for (i = 0; i < num_input_methods; i++)
2961 InputMethodInfo *im = input_method_table + i;
2962 char *name1, *name2;
2964 if (im->language != Mnil && im->language != Mt)
2966 MSymbol sym = mlanguage_name (im->language);
2968 name1 = msymbol_name (im->language);
2970 name1 = msymbol_name (sym);
2971 name2 = msymbol_name (im->name);
2974 name1 = msymbol_name (im->name), name2 = NULL;
2976 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2978 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2979 "Input Method Menu", menus, i + 2,
2980 "Select input method");
2983 unsigned long valuemask = GCForeground;
2986 XtSetArg (arg[0], XtNbackground, &values.foreground);
2987 XtGetValues (w, arg, 1);
2988 gc_inv = XCreateGC (display, RootWindow (display, screen),
2989 valuemask, &values);
2992 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2993 for (i = 0; i < num_input_methods + 2; i++)
2994 InputMethodMenus[i] = menus[i].w;
2998 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2999 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
3000 "Filter Menu", menus, 1,
3001 "Select filter to run");
3004 input_status_width = font_width * 8;
3005 input_status_height = (font_ascent + font_descent) * 2.4;
3006 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
3008 input_status_height,
3009 DefaultDepth (display, screen));
3014 prop.color_top = prop.color_bottom
3015 = prop.color_left = prop.color_right = Mnil;
3016 prop.inner_hmargin = prop.inner_vmargin = 1;
3017 prop.outer_hmargin = prop.outer_vmargin = 0;
3018 face_input_status = mface_copy (face_default);
3019 mface_put_prop (face_input_status, Mbox, &prop);
3022 XFillRectangle (display, input_status_pixmap, gc_inv,
3023 0, 0, input_status_width, input_status_height);
3024 XtSetArg (arg[0], XtNfromHoriz, w);
3025 XtSetArg (arg[1], XtNleft, XawRubber);
3026 XtSetArg (arg[2], XtNright, XawChainRight);
3027 XtSetArg (arg[3], XtNborderWidth, 0);
3028 XtSetArg (arg[4], XtNlabel, " ");
3029 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3030 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
3031 HeadWidget, arg, 6);
3032 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
3033 XtSetArg (arg[1], XtNleft, XawChainRight);
3034 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
3035 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
3036 HeadWidget, arg, 5);
3038 XtSetArg (arg[0], XtNborderWidth, 0);
3039 XtSetArg (arg[1], XtNleft, XawChainLeft);
3040 XtSetArg (arg[2], XtNright, XawChainLeft);
3041 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
3042 for (i = 0; i < num_faces;)
3044 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
3045 char *label = label_menu + 5; /* "Xxxx" */
3047 for (j = i; j < num_faces && face_table[j].face; j++)
3048 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
3050 w = create_menu_button (ShellWidget, FaceWidget, w,
3052 menus, j - i, "Push face property");
3056 XtSetArg (arg[0], XtNfromHoriz, w);
3057 XtSetArg (arg[1], XtNleft, XawChainLeft);
3058 XtSetArg (arg[2], XtNright, XawChainLeft);
3059 XtSetArg (arg[3], XtNhorizDistance, 10);
3060 XtSetArg (arg[4], XtNlabel, "Pop");
3061 XtSetArg (arg[5], XtNtranslations,
3062 XtParseTranslationTable (pop_face_trans));
3063 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
3064 FaceWidget, arg, 6);
3065 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
3067 XtSetArg (arg[0], XtNfromHoriz, w);
3068 XtSetArg (arg[1], XtNleft, XawChainLeft);
3069 XtSetArg (arg[2], XtNright, XawChainRight);
3070 XtSetArg (arg[3], XtNlabel, "");
3071 XtSetArg (arg[4], XtNborderWidth, 0);
3072 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3073 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
3074 FaceWidget, arg, 6);
3076 XtSetArg (arg[0], XtNborderWidth, 0);
3077 XtSetArg (arg[1], XtNleft, XawChainLeft);
3078 XtSetArg (arg[2], XtNright, XawChainLeft);
3079 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
3081 MPlist *plist[11], *pl;
3084 for (i = 0; i < 11; i++) plist[i] = NULL;
3086 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
3087 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
3089 MSymbol sym = msymbol_exist (langname);
3093 && ((fullname = mlanguage_name (sym)) != Mnil))
3095 char *name = msymbol_name (fullname);
3098 if (c >= 'a' && c <= 'z')
3100 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
3104 pl = plist[idx] = mplist ();
3105 for (; mplist_next (pl); pl = mplist_next (pl))
3106 if (strcmp (name, (char *) mplist_value (pl)) < 0)
3108 mplist_push (pl, sym, fullname);
3113 for (i = 0; i < 11; i++)
3116 char *name = alloca (9);
3118 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
3121 for (j = 0, pl = plist[i]; mplist_next (pl);
3122 j++, pl = mplist_next (pl))
3123 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
3124 msymbol_name (mplist_key (pl)),
3125 LangProc, mplist_key (pl), -1);
3126 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
3127 menus, j, "Push language property");
3129 for (i = 0; i < 11; i++)
3131 m17n_object_unref (plist[i]);
3133 XtSetArg (arg[0], XtNfromHoriz, w);
3134 XtSetArg (arg[1], XtNleft, XawChainLeft);
3135 XtSetArg (arg[2], XtNright, XawChainLeft);
3136 XtSetArg (arg[3], XtNhorizDistance, 10);
3137 XtSetArg (arg[4], XtNlabel, "Pop");
3138 XtSetArg (arg[5], XtNtranslations,
3139 XtParseTranslationTable (pop_lang_trans));
3140 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3141 LangWidget, arg, 6);
3142 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3144 XtSetArg (arg[0], XtNfromHoriz, w);
3145 XtSetArg (arg[1], XtNleft, XawChainLeft);
3146 XtSetArg (arg[2], XtNright, XawChainRight);
3147 XtSetArg (arg[3], XtNlabel, "");
3148 XtSetArg (arg[4], XtNborderWidth, 0);
3149 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3150 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3151 LangWidget, arg, 6);
3154 XtSetArg (arg[0], XtNheight, win_height);
3155 XtSetArg (arg[1], XtNwidth, 10);
3156 XtSetArg (arg[2], XtNleft, XawChainLeft);
3157 XtSetArg (arg[3], XtNright, XawChainLeft);
3158 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3160 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3161 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3163 XtSetArg (arg[0], XtNheight, win_height);
3164 XtSetArg (arg[1], XtNwidth, win_width);
3165 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3166 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3167 XtSetArg (arg[4], XtNleft, XawChainLeft);
3168 XtSetArg (arg[5], XtNright, XawChainRight);
3169 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3172 XtSetArg (arg[0], XtNborderWidth, 0);
3173 XtSetArg (arg[1], XtNleft, XawChainLeft);
3174 XtSetArg (arg[2], XtNright, XawChainRight);
3175 XtSetArg (arg[3], XtNresizable, True);
3176 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3177 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3178 TailWidget, arg, 5);
3180 memset (&control, 0, sizeof control);
3181 control.two_dimensional = 1;
3182 control.enable_bidi = 1;
3183 control.anti_alias = 1;
3184 control.min_line_ascent = font_ascent;
3185 control.min_line_descent = font_descent;
3186 control.max_line_width = win_width;
3187 control.with_cursor = 1;
3188 control.cursor_width = 2;
3189 control.partial_update = 1;
3190 control.ignore_formatting_char = 1;
3192 memset (&input_status_control, 0, sizeof input_status_control);
3193 input_status_control.enable_bidi = 1;
3195 XtAppAddActions (context, actions, XtNumber (actions));
3196 XtRealizeWidget (ShellWidget);
3198 win = XtWindow (TextWidget);
3200 XtAppMainLoop (context);
3202 if (current_input_context)
3203 minput_destroy_ic (current_input_context);
3204 for (i = 0; i < num_input_methods; i++)
3205 if (input_method_table[i].im)
3206 minput_close_im (input_method_table[i].im);
3207 m17n_object_unref (frame);
3208 m17n_object_unref (mt);
3209 m17n_object_unref (face_xxx_large);
3210 m17n_object_unref (face_box);
3211 m17n_object_unref (face_courier);
3212 m17n_object_unref (face_helvetica);
3213 m17n_object_unref (face_times);
3214 m17n_object_unref (face_dv_ttyogesh);
3215 m17n_object_unref (face_freesans);
3216 m17n_object_unref (face_freeserif);
3217 m17n_object_unref (face_freemono);
3218 m17n_object_unref (face_default_fontset);
3219 m17n_object_unref (face_no_ctl_fontset);
3220 m17n_object_unref (face_input_status);
3221 m17n_object_unref (face_default);
3222 m17n_object_unref (default_face_list);
3223 m17n_object_unref (selection);
3227 XFreeGC (display, mono_gc);
3228 XFreeGC (display, mono_gc_inv);
3229 XFreeGC (display, gc_inv);
3230 XtUninstallTranslations (form);
3231 XtUninstallTranslations (TextWidget);
3232 XtDestroyWidget (ShellWidget);
3233 XtDestroyApplicationContext (context);
3238 free (fontset_name);
3240 free (input_method_table);
3241 free (InputMethodMenus);
3246 #else /* not HAVE_X11_XAW_COMMAND_H */
3249 main (int argc, char **argv)
3252 "Building of this program failed (lack of some header files)\n");
3256 #endif /* not HAVE_X11_XAW_COMMAND_H */
3258 #endif /* not FOR_DOXYGEN */