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.3.4"
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);
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);
2204 surround = mtext ();
2205 mplist_set (ic->plist, Mtext, surround);
2206 m17n_object_unref (surround);
2208 else if (command == Minput_delete_surrounding_text)
2210 int len = (int) mplist_value (ic->plist);
2214 if (cursor.from + len < 0)
2215 len = - cursor.from;
2216 mtext_del (mt, cursor.from + len, cursor.from);
2218 update_cursor (cursor.from + len, 1);
2222 if (cursor.from + len > nchars)
2223 len = nchars - cursor.from;
2224 mtext_del (mt, cursor.from, cursor.from + len);
2226 update_cursor (cursor.from, 1);
2234 compare_input_method (const void *elt1, const void *elt2)
2236 const InputMethodInfo *im1 = elt1;
2237 const InputMethodInfo *im2 = elt2;
2238 MSymbol lang1, lang2;
2240 if (im1->language == Mnil)
2242 if (im1->language == im2->language)
2243 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2244 if (im1->language == Mt)
2246 if (im2->language == Mt)
2248 lang1 = mlanguage_name (im1->language);
2249 lang2 = mlanguage_name (im2->language);
2250 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2254 setup_input_methods (int with_xim, char *initial_input_method)
2256 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2260 num_input_methods = plist ? mplist_length (plist) : 0;
2262 num_input_methods++;
2263 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2268 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
2270 MDatabase *mdb = mplist_value (pl);
2271 MSymbol *tag = mdatabase_tag (mdb);
2274 i--, num_input_methods--;
2277 input_method_table[i].language = tag[1];
2278 input_method_table[i].name = tag[2];
2281 m17n_object_unref (plist);
2285 input_method_table[i].language = Mnil;
2286 input_method_table[i].name = msymbol ("xim");
2290 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2291 compare_input_method);
2292 mplist_put (minput_driver->callback_list, Minput_status_start,
2293 (void *) input_status);
2294 mplist_put (minput_driver->callback_list, Minput_status_draw,
2295 (void *) input_status);
2296 mplist_put (minput_driver->callback_list, Minput_status_done,
2297 (void *) input_status);
2298 mplist_put (minput_driver->callback_list, Minput_get_surrounding_text,
2299 (void *) surrounding_text_handler);
2300 mplist_put (minput_driver->callback_list, Minput_delete_surrounding_text,
2301 (void *) surrounding_text_handler);
2303 current_input_context = NULL;
2304 current_input_method = -1;
2306 if (initial_input_method)
2308 char *lang_name, *method_name;
2309 char *p = strchr (initial_input_method, '-');
2312 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2314 lang_name = "t", method_name = initial_input_method;
2316 for (i = 0; i < num_input_methods; i++)
2317 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2319 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2321 current_input_method = i;
2329 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2333 if (num && *num > 0)
2337 for (i = 0; i < *num; i++)
2338 bytes += strlen (str[i]) + 1;
2339 msg = alloca (bytes);
2340 strcpy (msg, str[0]);
2341 for (i = 1; i < *num; i++)
2342 strcat (msg, " "), strcat (msg, str[i]);
2344 else if (cursor.from < nchars)
2346 int c = mtext_ref_char (mt, cursor.from);
2347 char *name = mchar_get_prop (c, Mname);
2351 msg = alloca (10 + strlen (name));
2352 sprintf (msg, "U+%04X %s", c, name);
2358 XtSetArg (arg[0], XtNlabel, msg);
2359 XtSetValues (MessageWidget, arg, 1);
2365 char *name1, *name2;
2366 XtCallbackProc proc;
2367 XtPointer client_data;
2372 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2374 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2376 MenuRec FileMenu[] =
2377 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2378 { 0, "Save", NULL, SaveProc, NULL, -1 },
2379 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2381 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2382 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2384 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2385 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2387 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2390 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2392 MenuRec *rec = (MenuRec *) client_data;
2395 XtSetArg (arg[0], XtNvalue, "");
2396 XtSetArg (arg[1], XtNlabel, rec->name1);
2397 XtSetValues (FileDialogWidget, arg, 2);
2398 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2399 XtSetArg (arg[0], XtNx, x + 20);
2400 XtSetArg (arg[1], XtNy, y + 10);
2401 XtSetValues (FileShellWidget, arg, 2);
2402 XtPopup (FileShellWidget, XtGrabExclusive);
2406 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2411 XtPopdown (FileShellWidget);
2412 if ((int) client_data == 1)
2414 XtSetArg (arg[0], XtNlabel, &label);
2415 XtGetValues (FileDialogWidget, arg, 1);
2416 if (strcmp (label, FileMenu[0].name1) == 0)
2420 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2421 fp = fopen (filename, "r");
2423 m17n_object_unref (mt);
2426 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2434 nchars = mtext_len (mt);
2436 update_cursor (0, 1);
2437 redraw (0, win_height, 1, 1);
2439 else if (strcmp (label, FileMenu[2].name1) == 0)
2440 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2442 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2445 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2446 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2447 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2448 (MENU).status = (STATUS))
2452 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2453 char *menu_name, MenuRec *menus, int num_menus, char *help)
2455 Widget button, menu;
2456 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2457 <LeaveWindow>: reset() MenuHelp()\n\
2458 <BtnDown>: reset() PopupMenu()\n\
2459 <BtnUp>: highlight()";
2465 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2466 for (i = 0; i < num_menus; i++)
2477 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2479 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2481 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2483 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2487 XtSetArg (arg[0], XtNsensitive, False);
2488 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2494 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2499 trans = alloca (strlen (fmt) + strlen (help));
2500 sprintf (trans, fmt, help);
2501 XtSetArg (arg[0], XtNmenuName, menu_name);
2502 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2503 XtSetArg (arg[2], XtNinternalWidth, 2);
2504 XtSetArg (arg[3], XtNhighlightThickness, 1);
2505 XtSetArg (arg[4], XtNleft, XawChainLeft);
2506 XtSetArg (arg[5], XtNright, XawChainLeft);
2507 XtSetArg (arg[6], XtNinternational, True);
2510 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2511 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2516 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2517 int *len = alloca (sizeof (int) * num_menus);
2520 XFontSetExtents *fontset_extents;
2522 XtSetArg (arg[0], XtNfontSet, &font_set);
2523 XtGetValues (button, arg, 1);
2525 fontset_extents = XExtentsOfFontSet (font_set);
2526 height = fontset_extents->max_logical_extent.height;
2527 ascent = - fontset_extents->max_logical_extent.y;
2529 for (i = 0; i < num_menus; i++)
2532 len[i] = strlen (menus[i].name2);
2533 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2534 if (max_width < width[i])
2535 max_width = width[i];
2537 for (i = 0; i < num_menus; i++)
2540 Pixmap pixmap = XCreatePixmap (display,
2541 RootWindow (display, screen),
2542 max_width, height, 1);
2543 XFillRectangle (display, pixmap, mono_gc_inv,
2544 0, 0, max_width, height);
2545 XmbDrawString (display, pixmap, font_set, mono_gc,
2546 max_width - width[i], ascent,
2547 menus[i].name2, len[i]);
2548 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2549 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2550 XtSetValues (menus[i].w, arg, 2);
2558 XtActionsRec actions[] = {
2559 {"Expose", ExposeProc},
2560 {"Configure", ConfigureProc},
2562 {"ButtonPress", ButtonProc},
2563 {"ButtonRelease", ButtonReleaseProc},
2564 {"ButtonMotion", ButtonMoveProc},
2565 {"Button2Press", Button2Proc},
2566 {"MenuHelp", MenuHelpProc},
2567 {"FocusIn", FocusInProc},
2568 {"FocusOut", FocusOutProc}
2572 /* Print the usage of this program (the name is PROG), and exit with
2576 help_exit (char *prog, int exit_code)
2584 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2585 printf ("Display FILE on a window and allow users to edit it.\n");
2586 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2587 printf ("The following OPTIONs are available.\n");
2588 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2589 "Use the specified fontset\n");
2590 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2591 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2592 "Input method activated initially.\n");
2593 printf (" %-13s %s", "--version", "print version number\n");
2594 printf (" %-13s %s", "-h, --help", "print this message\n");
2600 main (int argc, char **argv)
2602 Widget form, BodyWidget, w;
2603 char *fontset_name = NULL;
2604 char *font_name = NULL;
2606 char *initial_input_method = NULL;
2607 int col = 80, row = 32;
2608 /* Translation table for TextWidget. */
2609 String trans = "<Expose>: Expose()\n\
2610 <Configure>: Configure()\n\
2613 <Btn1Down>: ButtonPress()\n\
2614 <Btn1Up>: ButtonRelease()\n\
2615 <Btn1Motion>: ButtonMotion()\n\
2616 <Btn2Down>: Button2Press()";
2617 /* Translation table for the top form widget. */
2618 String trans2 = "<Key>: Key()\n\
2620 <FocusIn>: FocusIn()\n\
2621 <FocusOut>: FocusOut()";
2622 String pop_face_trans
2623 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2624 <LeaveWindow>: MenuHelp() reset()\n\
2625 <Btn1Down>: set()\n\
2626 <Btn1Up>: notify() unset()";
2627 String pop_lang_trans
2628 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2629 <LeaveWindow>: MenuHelp() reset()\n\
2630 <Btn1Down>: set()\n\
2631 <Btn1Up>: notify() unset()";
2632 int font_width, font_ascent, font_descent;
2635 char *filter = NULL;
2638 setlocale (LC_ALL, "");
2639 /* Create the top shell. */
2640 XtSetLanguageProc (NULL, NULL, NULL);
2641 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2642 NULL, sessionShellWidgetClass, NULL, 0);
2643 display = XtDisplay (ShellWidget);
2644 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2646 /* Parse the remaining command line arguments. */
2647 for (i = 1; i < argc; i++)
2649 if (! strcmp (argv[i], "--help")
2650 || ! strcmp (argv[i], "-h"))
2651 help_exit (argv[0], 0);
2652 else if (! strcmp (argv[i], "--version"))
2654 printf ("m17n-edit (m17n library) %s\n", VERSION);
2655 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2658 else if (! strcmp (argv[i], "--geometry"))
2661 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2662 help_exit (argv[0], 1);
2664 else if (! strcmp (argv[i], "-s"))
2667 fontsize = atoi (argv[i]);
2671 else if (! strcmp (argv[i], "--fontset"))
2674 fontset_name = strdup (argv[i]);
2676 else if (! strcmp (argv[i], "--font"))
2679 font_name = strdup (argv[i]);
2681 else if (! strcmp (argv[i], "--im"))
2684 initial_input_method = strdup (argv[i]);
2686 else if (! strcmp (argv[i], "--with-xim"))
2690 else if (! strcmp (argv[i], "--filter"))
2695 else if (argv[i][0] != '-')
2697 filename = strdup (argv[i]);
2701 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2702 help_exit (argv[0], 1);
2706 filename = strdup ("/dev/null");
2708 mdatabase_dir = ".";
2709 /* Initialize the m17n library. */
2711 if (merror_code != MERROR_NONE)
2712 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2713 minput_driver = &minput_gui_driver;
2715 mt = read_file (filename);
2718 nchars = mtext_len (mt);
2720 Mword = msymbol ("word");
2723 MFace *face = mface ();
2725 mface_put_prop (face, Mforeground, msymbol ("blue"));
2726 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2727 mface_put_prop (face, Mvideomode, Mreverse);
2728 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2729 m17n_object_unref (face);
2732 /* This tells ExposeProc to initialize everything. */
2735 XA_TEXT = XInternAtom (display, "TEXT", False);
2736 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2737 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2738 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2739 if (Mcoding_compound_text == Mnil)
2740 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2743 MPlist *plist = mplist ();
2746 mplist_put (plist, msymbol ("widget"), ShellWidget);
2747 if (fontset_name || font_name || fontsize > 0)
2753 font = mfont_parse_name (font_name, Mnil);
2755 face = mface_from_font (font);
2763 MFontset *fontset = mfontset (fontset_name);
2765 mface_put_prop (face, Mfontset, fontset);
2766 m17n_object_unref (fontset);
2769 mface_put_prop (face, Msize, (void *) fontsize);
2770 mplist_add (plist, Mface, face);
2771 m17n_object_unref (face);
2773 frame = mframe (plist);
2775 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2776 m17n_object_unref (plist);
2777 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2778 default_face_list = mplist ();
2779 mplist_add (default_face_list, Mt, face_default);
2780 face_default_fontset = mface ();
2781 mface_put_prop (face_default_fontset, Mfontset,
2782 mface_get_prop (face_default, Mfontset));
2784 font = (MFont *) mframe_get_prop (frame, Mfont);
2785 default_font_size = (int) mfont_get_prop (font, Msize);
2788 font_width = (int) mframe_get_prop (frame, Mfont_width);
2789 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2790 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2791 win_width = font_width * col;
2792 win_height = (font_ascent + font_descent) * row;
2798 prop.color_top = prop.color_left = msymbol ("magenta");
2799 prop.color_bottom = prop.color_right = msymbol ("red");
2800 prop.inner_hmargin = prop.inner_vmargin = 1;
2801 prop.outer_hmargin = prop.outer_vmargin = 2;
2803 face_box = mface ();
2804 mface_put_prop (face_box, Mbox, &prop);
2807 face_courier = mface ();
2808 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2809 face_helvetica = mface ();
2810 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2811 face_times = mface ();
2812 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2813 face_dv_ttyogesh = mface ();
2814 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2815 face_freesans = mface ();
2816 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2817 face_freeserif = mface ();
2818 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2819 face_freemono = mface ();
2820 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2822 face_xxx_large = mface ();
2823 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2825 MFont *latin_font = mframe_get_prop (frame, Mfont);
2826 MFont *dev_font = mfont ();
2827 MFont *thai_font = mfont ();
2828 MFont *tib_font = mfont ();
2829 MFontset *fontset, *fontset_no_ctl;
2830 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2831 MSymbol no_ctl = msymbol ("no-ctl");
2833 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2834 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2835 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2836 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2837 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2838 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2840 fontset = mfontset (fontset_name);
2841 fontset_no_ctl = mfontset_copy (fontset, "no-ctl");
2842 m17n_object_unref (fontset);
2843 mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil,
2844 latin_font, Mnil, 0);
2845 mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil,
2846 dev_font, no_ctl, 0);
2847 mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil,
2848 thai_font, no_ctl, 0);
2849 mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil,
2850 tib_font, no_ctl, 0);
2851 face_no_ctl_fontset = mface ();
2852 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl);
2853 m17n_object_unref (fontset_no_ctl);
2860 setup_input_methods (with_xim, initial_input_method);
2862 gc = DefaultGC (display, screen);
2864 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2865 XtSetArg (arg[1], XtNdefaultDistance, 2);
2866 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2868 XtSetArg (arg[0], XtNborderWidth, 0);
2869 XtSetArg (arg[1], XtNdefaultDistance, 2);
2870 XtSetArg (arg[2], XtNtop, XawChainTop);
2871 XtSetArg (arg[3], XtNbottom, XawChainTop);
2872 XtSetArg (arg[4], XtNleft, XawChainLeft);
2873 XtSetArg (arg[5], XtNright, XawChainRight);
2874 XtSetArg (arg[6], XtNresizable, True);
2875 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2876 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2877 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2878 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2879 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2880 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2881 XtSetArg (arg[7], XtNfromVert, LangWidget);
2882 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2883 XtSetArg (arg[2], XtNtop, XawChainBottom);
2884 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2885 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2887 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2888 HeadWidget, NULL, 0);
2889 XtSetArg (arg[0], XtNvalue, "");
2890 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2891 FileShellWidget, arg, 1);
2892 XawDialogAddButton (FileDialogWidget, "OK",
2893 FileDialogProc, (XtPointer) 0);
2894 XawDialogAddButton (FileDialogWidget, "CANCEL",
2895 FileDialogProc, (XtPointer) 1);
2897 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2898 (char *) check_bits,
2899 check_width, check_height);
2901 unsigned long valuemask = GCForeground;
2904 values.foreground = 1;
2905 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2906 values.foreground = 0;
2907 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2914 if (num_menus < num_input_methods + 2)
2915 num_menus = num_input_methods + 2;
2916 if (num_menus < num_faces + 1)
2917 num_menus = num_faces + 1;
2918 menus = alloca (sizeof (MenuRec) * num_menus);
2920 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2921 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2922 "File I/O, Serialization, Image, Quit");
2924 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2925 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2926 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2927 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2928 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2929 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2930 w = create_menu_button (ShellWidget, HeadWidget, w,
2931 "Cursor", "Cursor Menu",
2932 menus, 6, "Cursor Movement Mode, Cursor Shape");
2933 CursorMenus[0] = menus[0].w;
2934 CursorMenus[1] = menus[1].w;
2935 CursorMenus[2] = menus[3].w;
2936 CursorMenus[3] = menus[4].w;
2937 CursorMenus[4] = menus[5].w;
2939 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2940 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2941 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2942 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2943 menus, 3, "BIDI Processing Mode");
2944 for (i = 0; i < 3; i++)
2945 BidiMenus[i] = menus[i].w;
2947 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2948 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2949 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2950 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2952 menus, 3, "How to break lines");
2953 for (i = 0; i < 3; i++)
2954 LineBreakMenus[i] = menus[i].w;
2956 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2957 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2958 for (i = 0; i < num_input_methods; i++)
2960 InputMethodInfo *im = input_method_table + i;
2961 char *name1, *name2;
2963 if (im->language != Mnil && im->language != Mt)
2965 MSymbol sym = mlanguage_name (im->language);
2967 name1 = msymbol_name (im->language);
2969 name1 = msymbol_name (sym);
2970 name2 = msymbol_name (im->name);
2973 name1 = msymbol_name (im->name), name2 = NULL;
2975 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2977 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2978 "Input Method Menu", menus, i + 2,
2979 "Select input method");
2982 unsigned long valuemask = GCForeground;
2985 XtSetArg (arg[0], XtNbackground, &values.foreground);
2986 XtGetValues (w, arg, 1);
2987 gc_inv = XCreateGC (display, RootWindow (display, screen),
2988 valuemask, &values);
2991 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2992 for (i = 0; i < num_input_methods + 2; i++)
2993 InputMethodMenus[i] = menus[i].w;
2997 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2998 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2999 "Filter Menu", menus, 1,
3000 "Select filter to run");
3003 input_status_width = font_width * 8;
3004 input_status_height = (font_ascent + font_descent) * 2.4;
3005 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
3007 input_status_height,
3008 DefaultDepth (display, screen));
3013 prop.color_top = prop.color_bottom
3014 = prop.color_left = prop.color_right = Mnil;
3015 prop.inner_hmargin = prop.inner_vmargin = 1;
3016 prop.outer_hmargin = prop.outer_vmargin = 0;
3017 face_input_status = mface_copy (face_default);
3018 mface_put_prop (face_input_status, Mbox, &prop);
3021 XFillRectangle (display, input_status_pixmap, gc_inv,
3022 0, 0, input_status_width, input_status_height);
3023 XtSetArg (arg[0], XtNfromHoriz, w);
3024 XtSetArg (arg[1], XtNleft, XawRubber);
3025 XtSetArg (arg[2], XtNright, XawChainRight);
3026 XtSetArg (arg[3], XtNborderWidth, 0);
3027 XtSetArg (arg[4], XtNlabel, " ");
3028 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3029 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
3030 HeadWidget, arg, 6);
3031 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
3032 XtSetArg (arg[1], XtNleft, XawChainRight);
3033 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
3034 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
3035 HeadWidget, arg, 5);
3037 XtSetArg (arg[0], XtNborderWidth, 0);
3038 XtSetArg (arg[1], XtNleft, XawChainLeft);
3039 XtSetArg (arg[2], XtNright, XawChainLeft);
3040 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
3041 for (i = 0; i < num_faces;)
3043 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
3044 char *label = label_menu + 5; /* "Xxxx" */
3046 for (j = i; j < num_faces && face_table[j].face; j++)
3047 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
3049 w = create_menu_button (ShellWidget, FaceWidget, w,
3051 menus, j - i, "Push face property");
3055 XtSetArg (arg[0], XtNfromHoriz, w);
3056 XtSetArg (arg[1], XtNleft, XawChainLeft);
3057 XtSetArg (arg[2], XtNright, XawChainLeft);
3058 XtSetArg (arg[3], XtNhorizDistance, 10);
3059 XtSetArg (arg[4], XtNlabel, "Pop");
3060 XtSetArg (arg[5], XtNtranslations,
3061 XtParseTranslationTable (pop_face_trans));
3062 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
3063 FaceWidget, arg, 6);
3064 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
3066 XtSetArg (arg[0], XtNfromHoriz, w);
3067 XtSetArg (arg[1], XtNleft, XawChainLeft);
3068 XtSetArg (arg[2], XtNright, XawChainRight);
3069 XtSetArg (arg[3], XtNlabel, "");
3070 XtSetArg (arg[4], XtNborderWidth, 0);
3071 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3072 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
3073 FaceWidget, arg, 6);
3075 XtSetArg (arg[0], XtNborderWidth, 0);
3076 XtSetArg (arg[1], XtNleft, XawChainLeft);
3077 XtSetArg (arg[2], XtNright, XawChainLeft);
3078 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
3080 MPlist *plist[11], *pl;
3083 for (i = 0; i < 11; i++) plist[i] = NULL;
3085 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
3086 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
3088 MSymbol sym = msymbol_exist (langname);
3092 && ((fullname = mlanguage_name (sym)) != Mnil))
3094 char *name = msymbol_name (fullname);
3097 if (c >= 'a' && c <= 'z')
3099 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
3103 pl = plist[idx] = mplist ();
3104 for (; mplist_next (pl); pl = mplist_next (pl))
3105 if (strcmp (name, (char *) mplist_value (pl)) < 0)
3107 mplist_push (pl, sym, fullname);
3112 for (i = 0; i < 11; i++)
3115 char *name = alloca (9);
3117 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
3120 for (j = 0, pl = plist[i]; mplist_next (pl);
3121 j++, pl = mplist_next (pl))
3122 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
3123 msymbol_name (mplist_key (pl)),
3124 LangProc, mplist_key (pl), -1);
3125 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
3126 menus, j, "Push language property");
3128 for (i = 0; i < 11; i++)
3130 m17n_object_unref (plist[i]);
3132 XtSetArg (arg[0], XtNfromHoriz, w);
3133 XtSetArg (arg[1], XtNleft, XawChainLeft);
3134 XtSetArg (arg[2], XtNright, XawChainLeft);
3135 XtSetArg (arg[3], XtNhorizDistance, 10);
3136 XtSetArg (arg[4], XtNlabel, "Pop");
3137 XtSetArg (arg[5], XtNtranslations,
3138 XtParseTranslationTable (pop_lang_trans));
3139 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3140 LangWidget, arg, 6);
3141 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3143 XtSetArg (arg[0], XtNfromHoriz, w);
3144 XtSetArg (arg[1], XtNleft, XawChainLeft);
3145 XtSetArg (arg[2], XtNright, XawChainRight);
3146 XtSetArg (arg[3], XtNlabel, "");
3147 XtSetArg (arg[4], XtNborderWidth, 0);
3148 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3149 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3150 LangWidget, arg, 6);
3153 XtSetArg (arg[0], XtNheight, win_height);
3154 XtSetArg (arg[1], XtNwidth, 10);
3155 XtSetArg (arg[2], XtNleft, XawChainLeft);
3156 XtSetArg (arg[3], XtNright, XawChainLeft);
3157 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3159 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3160 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3162 XtSetArg (arg[0], XtNheight, win_height);
3163 XtSetArg (arg[1], XtNwidth, win_width);
3164 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3165 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3166 XtSetArg (arg[4], XtNleft, XawChainLeft);
3167 XtSetArg (arg[5], XtNright, XawChainRight);
3168 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3171 XtSetArg (arg[0], XtNborderWidth, 0);
3172 XtSetArg (arg[1], XtNleft, XawChainLeft);
3173 XtSetArg (arg[2], XtNright, XawChainRight);
3174 XtSetArg (arg[3], XtNresizable, True);
3175 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3176 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3177 TailWidget, arg, 5);
3179 memset (&control, 0, sizeof control);
3180 control.two_dimensional = 1;
3181 control.enable_bidi = 1;
3182 control.anti_alias = 1;
3183 control.min_line_ascent = font_ascent;
3184 control.min_line_descent = font_descent;
3185 control.max_line_width = win_width;
3186 control.with_cursor = 1;
3187 control.cursor_width = 2;
3188 control.partial_update = 1;
3189 control.ignore_formatting_char = 1;
3191 memset (&input_status_control, 0, sizeof input_status_control);
3192 input_status_control.enable_bidi = 1;
3194 XtAppAddActions (context, actions, XtNumber (actions));
3195 XtRealizeWidget (ShellWidget);
3197 win = XtWindow (TextWidget);
3199 XtAppMainLoop (context);
3201 if (current_input_context)
3202 minput_destroy_ic (current_input_context);
3203 for (i = 0; i < num_input_methods; i++)
3204 if (input_method_table[i].im)
3205 minput_close_im (input_method_table[i].im);
3206 m17n_object_unref (frame);
3207 m17n_object_unref (mt);
3208 m17n_object_unref (face_xxx_large);
3209 m17n_object_unref (face_box);
3210 m17n_object_unref (face_courier);
3211 m17n_object_unref (face_helvetica);
3212 m17n_object_unref (face_times);
3213 m17n_object_unref (face_dv_ttyogesh);
3214 m17n_object_unref (face_freesans);
3215 m17n_object_unref (face_freeserif);
3216 m17n_object_unref (face_freemono);
3217 m17n_object_unref (face_default_fontset);
3218 m17n_object_unref (face_no_ctl_fontset);
3219 m17n_object_unref (face_input_status);
3220 m17n_object_unref (face_default);
3221 m17n_object_unref (default_face_list);
3222 m17n_object_unref (selection);
3226 XFreeGC (display, mono_gc);
3227 XFreeGC (display, mono_gc_inv);
3228 XFreeGC (display, gc_inv);
3229 XtUninstallTranslations (form);
3230 XtUninstallTranslations (TextWidget);
3231 XtDestroyWidget (ShellWidget);
3232 XtDestroyApplicationContext (context);
3237 free (fontset_name);
3239 free (input_method_table);
3240 free (InputMethodMenus);
3245 #else /* not HAVE_X11_XAW_COMMAND_H */
3248 main (int argc, char **argv)
3251 "Building of this program failed (lack of some header files)\n");
3255 #endif /* not HAVE_X11_XAW_COMMAND_H */
3257 #endif /* not FOR_DOXYGEN */