1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004, 2005
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 @enpage m17n-edit edit multilingual text
26 @section m17n-edit-synopsis SYNOPSIS
28 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section m17n-edit-description DESCRIPTION
32 Display FILE on a window and allow users to edit it.
34 XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).
36 The following OPTIONs are available.
50 This program is to demonstrate how to use the m17n GUI API.
51 Although m17n-edit directly uses the GUI API, the API is mainly
52 for toolkit libraries or to implement XOM (X Outout Method), not
53 for direct use from application programs.
56 @japage m17n-edit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section m17n-edit-synopsis SYNOPSIS
60 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section m17n-edit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit
83 ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é
84 ¥ê¤äXOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
85 ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
100 #ifdef HAVE_X11_XAW_COMMAND_H
102 #include <X11/keysym.h>
103 #include <X11/Xatom.h>
104 #include <X11/Intrinsic.h>
105 #include <X11/StringDefs.h>
106 #include <X11/Shell.h>
108 #include <m17n-gui.h>
109 #include <m17n-misc.h>
112 #include <X11/Xaw/Command.h>
113 #include <X11/Xaw/Box.h>
114 #include <X11/Xaw/Form.h>
115 #include <X11/Xaw/Dialog.h>
116 #include <X11/Xaw/Scrollbar.h>
117 #include <X11/Xaw/Toggle.h>
118 #include <X11/Xaw/SimpleMenu.h>
119 #include <X11/Xaw/SmeBSB.h>
120 #include <X11/Xaw/SmeLine.h>
121 #include <X11/Xaw/MenuButton.h>
123 #define VERSION "1.2.0"
125 /* Global variables. */
130 /* For the X Window System. */
133 /* GCs for normal drawing, filling by background color, normal drawing
134 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
136 GC gc, gc_inv, mono_gc, mono_gc_inv;
138 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
139 XtAppContext context;
140 int default_font_size;
144 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
145 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
146 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
147 +- Body -- Sbar, Text
151 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
152 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
153 Widget SbarWidget, TextWidget;
154 Widget FileShellWidget, FileDialogWidget;
155 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
156 Widget CurIMLang, CurIMStatus;
158 int win_width, win_height; /* Size of TextWidget. */
161 Pixmap input_status_pixmap;
162 int input_status_width, input_status_height;
164 /* Bitmap for "check" glyph. */
165 #define check_width 9
166 #define check_height 8
167 static unsigned char check_bits[] = {
168 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
169 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
172 /* For the m17n library. */
175 int nchars; /* == mtext_len (mt) */
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,
869 msymbol_name (msymbol_get (sym, Mlanguage)));
870 XtSetValues (CurLangWidget, arg, 2);
872 XtSetValues (CurLangWidget, arg, 2);
874 if (auto_input_method)
877 select_input_method (-1);
882 for (i = 0; i < num_input_methods; i++)
883 if (input_method_table[i].language == sym
884 && input_method_table[i].available >= 0)
886 if (i < num_input_methods)
887 select_input_method (i);
889 select_input_method (-1);
894 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
900 /* Hide the cursor. */
904 control.with_cursor = 0;
906 XtAppAddWorkProc (context, show_cursor, NULL);
910 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
911 $Y1 and $NEW_Y1 assuming that the text in the other area is not
914 update_region (int y0, int old_y1, int new_y1)
920 if (old_y1 < win_height)
922 COPY_AREA (old_y1, win_height, new_y1);
923 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
926 redraw (new_y1, win_height, 1, 0);
928 else if (new_y1 > old_y1)
930 if (new_y1 < win_height)
931 COPY_AREA (old_y1, win_height, new_y1);
933 if (new_y1 > win_height)
935 redraw (y0, new_y1, 1, 1);
939 /* Delete the next $N characters. If $N is negative delete the
940 precious (- $N) characters. */
946 int y0, old_y1, new_y1;
948 int line_from = cursor.line_from;
951 from = cursor.from, to = from + n;
954 from = cursor.from + n;
956 if (cursor.from == cur.from)
958 /* We are at the beginning of line. */
959 int pos = cursor.prev_from;
961 if (cursor.from == top.from)
963 /* We are at the beginning of screen. We must scroll
965 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
966 reseat (info.line_from);
968 update_cursor (pos, 1);
972 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
973 old_y1 = cur.y0 + rect.height;
975 /* Now delete a character. */
976 mtext_del (mt, from, to);
978 if (from >= top.from && from < top.to)
979 update_top (top.from);
980 update_cursor (from, 1);
983 if (line_from != cursor.line_from)
986 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
987 new_y1 = cur.y0 + rect.height;
989 update_region (cur.y0, old_y1, new_y1);
993 /* Insert M-text $NEWTEXT at the current cursor position. */
995 insert_chars (MText *newtext)
997 int n = mtext_len (newtext);
999 int y0, old_y1, new_y1;
1004 int n = (mtext_property_end (selection)
1005 - mtext_property_start (selection));
1006 mtext_detach_property (selection);
1011 if (cursor.line_from > 0
1012 && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
1013 y0 -= control.min_line_descent;
1015 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1016 old_y1 = y0 + rect.height;
1018 line_from = cursor.line_from;
1020 /* Now insert chars. */
1021 mtext_ins (mt, cursor.from, newtext);
1023 if (cur.from == top.from)
1024 update_top (top.from);
1025 update_cursor (cursor.from + n, 1);
1027 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
1028 new_y1 = cur.y0 + rect.height;
1030 update_region (y0, old_y1, new_y1);
1031 update_selection ();
1036 word_constituent_p (int c)
1038 MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
1039 char *name = category != Mnil ? msymbol_name (category) : NULL;
1041 return (name && (name[0] == 'L' || name[0] == 'M'));
1048 int pos = cursor.from;
1050 while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
1054 MTextProperty *prop = mtext_get_property (mt, pos, Mword);
1057 pos = mtext_property_end (prop);
1059 while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
1062 update_cursor (pos, 0);
1068 int pos = cursor.from;
1070 while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
1074 MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
1077 pos = mtext_property_start (prop);
1079 while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
1082 update_cursor (pos, 0);
1086 /* Convert the currently selected text to UTF8-STRING or
1087 COMPOUND-TEXT. It is called when someone requests the current
1088 value of the selection. */
1090 covert_selection (Widget w, Atom *selection_atom,
1091 Atom *target, Atom *return_type,
1092 XtPointer *value, unsigned long *length, int *format)
1094 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1095 MText *this_mt = mtext ();
1096 int from = mtext_property_start (selection);
1097 int to = mtext_property_end (selection);
1101 mtext_copy (this_mt, 0, mt, from, to);
1102 if (*target == XA_TEXT)
1104 #ifdef X_HAVE_UTF8_STRING
1105 coding = Mcoding_utf_8;
1106 *return_type = XA_UTF8_STRING;
1108 coding = Mcoding_compound_text;
1109 *return_type = XA_COMPOUND_TEXT;
1112 else if (*target == XA_UTF8_STRING)
1114 coding = Mcoding_utf_8;
1115 *return_type = XA_UTF8_STRING;
1117 else if (*target == XA_STRING)
1122 for (i = 0; i < len; i++)
1123 if (mtext_ref_char (this_mt, i) >= 0x100)
1124 /* Can't encode in XA_STRING */
1126 coding = Mcoding_iso_8859_1;
1127 *return_type = XA_STRING;
1129 else if (*target == XA_COMPOUND_TEXT)
1131 coding = Mcoding_compound_text;
1132 *return_type = XA_COMPOUND_TEXT;
1137 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1138 m17n_object_unref (this_mt);
1142 *value = (XtPointer) buf;
1148 /* Unselect the text. It is called when we loose the selection. */
1150 lose_selection (Widget w, Atom *selection_atom)
1154 mtext_detach_property (selection);
1155 redraw (sel_start.y0, sel_end.y1, 1, 0);
1160 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1161 XtPointer value, unsigned long *length, int *format)
1166 if (*type == XT_CONVERT_FAIL || ! value)
1168 if (*type == XA_STRING)
1170 else if (*type == XA_COMPOUND_TEXT)
1171 coding = msymbol ("compound-text");
1172 #ifdef X_HAVE_UTF8_STRING
1173 else if (*type == XA_UTF8_STRING)
1174 coding = msymbol ("utf-8");
1179 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1180 if (! this_mt && *type != XA_UTF8_STRING)
1182 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1189 insert_chars (this_mt);
1190 m17n_object_unref (this_mt);
1199 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1201 XExposeEvent *expose = (XExposeEvent *) event;
1205 Dimension width_max, width;
1207 XtSetArg (arg[0], XtNwidth, &width);
1208 XtGetValues (XtParent (w), arg, 1);
1210 XtGetValues (HeadWidget, arg, 1);
1211 if (width_max < width)
1213 XtGetValues (FaceWidget, arg, 1);
1214 if (width_max < width)
1216 XtGetValues (LangWidget, arg, 1);
1217 if (width_max < width)
1219 XtSetArg (arg[0], XtNwidth, width_max);
1220 XtSetValues (HeadWidget, arg, 1);
1221 XtSetValues (FaceWidget, arg, 1);
1222 XtSetValues (LangWidget, arg, 1);
1223 XtSetValues (XtParent (w), arg, 1);
1224 XtSetValues (TailWidget, arg, 1);
1227 update_cursor (0, 1);
1228 redraw (0, win_height, 0, 1);
1229 if (current_input_method >= 0)
1231 int idx = current_input_method;
1233 current_input_method = -1;
1234 select_input_method (idx);
1240 redraw (expose->y, expose->y + expose->height, 0, 0);
1241 if (current_input_context
1242 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1243 set_input_method_spot ();
1248 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1250 XConfigureEvent *configure = (XConfigureEvent *) event;
1253 control.max_line_width = win_width = configure->width;
1254 win_height = configure->height;
1255 mdraw_clear_cache (mt);
1257 update_cursor (0, 1);
1258 redraw (0, win_height, 1, 1);
1259 if (current_input_context)
1260 set_input_method_spot ();
1264 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1267 int x = event->xbutton.x;
1268 int y = event->xbutton.y - top.ascent;
1270 if (control.orientation_reversed)
1272 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1275 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1276 mtext_detach_property (selection);
1277 redraw (sel_start.y0, sel_end.y1, 1, 0);
1280 if (current_input_context
1281 && minput_filter (current_input_context, Minput_focus_move, NULL) == 0)
1283 MText *produced = mtext ();
1285 minput_lookup (current_input_context, Mnil, NULL, produced);
1286 if (mtext_len (produced) > 0)
1288 insert_chars (produced);
1289 if (pos >= cursor.from)
1290 pos += mtext_len (produced);
1292 m17n_object_unref (produced);
1294 update_cursor (pos, 0);
1299 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1304 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1305 covert_selection, lose_selection, NULL);
1306 update_cursor (mtext_property_start (selection), 0);
1311 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1315 /* We don't have a local selection. */
1316 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1321 int from = mtext_property_start (selection);
1322 int to = mtext_property_end (selection);
1325 int x = event->xbutton.x;
1326 int y = event->xbutton.y - top.ascent;
1328 if (control.orientation_reversed)
1330 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1332 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1333 mtext_detach_property (selection);
1335 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1336 update_cursor (pos, 0);
1337 insert_chars (this_mt);
1338 m17n_object_unref (this_mt);
1343 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1346 int x = event->xbutton.x;
1347 int y = event->xbutton.y;
1349 if (control.orientation_reversed)
1352 pos = top.from, y -= top.ascent;
1354 pos = cur.from, y -= cur.y0 + cur.ascent;
1355 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1357 if (pos == cursor.from)
1363 /* Selection range changed. */
1364 int from = mtext_property_start (selection);
1365 int to = mtext_property_end (selection);
1366 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1367 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1369 if (cursor.from == from)
1371 /* Starting position changed. */
1374 /* Enlarged. We can simply overdraw. */
1375 select_region (pos, to);
1376 redraw (sel_start.y0, start_y1, 0, 0);
1380 /* Shrunken. Previous selection face must be cleared. */
1381 select_region (pos, to);
1382 redraw (start_y0, sel_start.y1, 1, 0);
1386 /* Shrunken to zero. */
1387 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1388 mtext_detach_property (selection);
1389 redraw (start_y0, end_y1, 1, 0);
1393 /* Full update is necessary. */
1394 select_region (to, pos);
1395 redraw (start_y0, sel_end.y1, 1, 0);
1400 /* Ending position changed. */
1403 /* Full update is necessary. */
1404 select_region (pos, from);
1405 redraw (sel_start.y0, end_y1, 1, 0);
1407 else if (pos == from)
1409 /* Shrunken to zero. */
1410 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1411 mtext_detach_property (selection);
1412 redraw (start_y0, end_y1, 1, 0);
1416 /* Shrunken. Previous selection face must be cleared. */
1417 select_region (from, pos);
1418 redraw (sel_end.y0, end_y1, 1, 0);
1422 /* Enlarged. We can simply overdraw. */
1423 select_region (from, pos);
1424 redraw (end_y0, sel_end.y1, 0, 0);
1430 /* Newly selected. */
1431 select_region (pos, cursor.from);
1432 redraw (sel_start.y0, sel_end.y1, 0, 0);
1434 update_cursor (pos, 1);
1438 FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num)
1440 if (current_input_context
1441 && minput_filter (current_input_context, Minput_focus_in, NULL) == 0)
1443 MText *produced = mtext ();
1445 minput_lookup (current_input_context, Mnil, NULL, produced);
1446 if (mtext_len (produced) > 0)
1449 insert_chars (produced);
1451 m17n_object_unref (produced);
1456 FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num)
1458 if (current_input_context
1459 && minput_filter (current_input_context, Minput_focus_out, NULL) == 0)
1461 MText *produced = mtext ();
1463 minput_lookup (current_input_context, Mnil, NULL, produced);
1464 if (mtext_len (produced) > 0)
1467 insert_chars (produced);
1469 m17n_object_unref (produced);
1474 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1477 MDrawGlyphInfo info;
1479 int cursor_pos = cursor.from;
1481 if (((int) position) < 0)
1487 height = top.y1 - top.y0;
1490 pos = bol (from - 1, 0);
1491 GLYPH_INFO (pos, from - 1, info);
1492 if (height + info.metrics.height > win_height)
1494 height += info.metrics.height;
1495 from = info.line_from;
1497 if (cursor_pos >= top.to)
1499 cursor_pos = top.from;
1501 while (cursor_pos < nchars)
1503 GLYPH_INFO (pos, pos, info);
1504 if (height + info.metrics.height > win_height)
1506 height += info.metrics.height;
1512 else if (cur.to < nchars)
1514 /* Scroll up, but leave at least one line. */
1517 while (from < nchars)
1519 GLYPH_INFO (from, from, info);
1520 if (height + info.metrics.height > win_height
1521 || info.line_to >= nchars)
1523 height += info.metrics.height;
1524 from = info.line_to;
1527 from = info.line_from;
1528 if (cursor_pos < from)
1532 /* Scroll up to make the cursor line top. */
1536 update_cursor (cursor_pos, 1);
1540 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1542 float persent = *(float *) persent_ptr;
1543 int pos1, pos2 = nchars * persent;
1544 MDrawGlyphInfo info;
1547 pos1 = bol (pos2, 0);
1548 GLYPH_INFO (pos1, pos2, info);
1549 pos1 = info.line_from;
1551 update_cursor (pos1, 1);
1556 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1558 XKeyEvent *key_event = (XKeyEvent *) event;
1560 KeySym keysym = NoSymbol;
1562 /* If set to 1, do not update target_x_position. */
1563 int keep_target_x_position = 0;
1565 int y0, old_y1, new_y1;
1572 if (current_input_context
1573 && minput_filter (current_input_context, Mnil, event))
1578 update_region (y0, old_y1, new_y1);
1582 if (event->type == KeyRelease)
1585 produced = mtext ();
1586 ret = minput_lookup (current_input_context, Mnil, event, produced);
1587 if (mtext_len (produced) > 0)
1588 insert_chars (produced);
1590 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1591 m17n_object_unref (produced);
1601 n = (mtext_property_end (selection)
1602 - mtext_property_start (selection));
1603 mtext_detach_property (selection);
1605 else if (cursor.from < nchars)
1607 /* Delete the following grapheme cluster. */
1608 n = cursor.to - cursor.from;
1621 /* Delete selected region. */
1622 n = (mtext_property_end (selection)
1623 - mtext_property_start (selection));
1624 mtext_detach_property (selection);
1626 else if (cursor.from > 0)
1628 /* Delete the preceding character. */
1639 mtext_detach_property (selection);
1640 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1644 if (cursor.prev_from >= 0)
1645 update_cursor (cursor.prev_from, 0);
1649 if (cursor.left_from >= 0)
1650 update_cursor (cursor.left_from, 0);
1657 mtext_detach_property (selection);
1658 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1662 if (cursor.next_to >= 0)
1663 update_cursor (cursor.to, 0);
1667 if (cursor.right_from >= 0)
1668 update_cursor (cursor.right_from, 0);
1675 mtext_detach_property (selection);
1676 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1678 if (cur.to <= nchars)
1680 MDrawGlyphInfo info;
1683 GLYPH_INFO (cur.from, cur.to, info);
1684 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1685 target_x_position, info.y);
1686 keep_target_x_position = 1;
1687 update_cursor (pos, 0);
1694 mtext_detach_property (selection);
1695 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1701 int pos = bol (cur.from - 1, 0);
1703 TEXT_EXTENTS (pos, cur.from - 1, rect);
1704 y = rect.height + rect.y - 1;
1705 pos = COORDINATES_POSITION (pos, nchars,
1706 target_x_position, y);
1707 keep_target_x_position = 1;
1708 update_cursor (pos, 0);
1715 mtext_detach_property (selection);
1716 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1718 if (top.from < nchars)
1719 ScrollProc (w, NULL, (XtPointer) 1);
1725 mtext_detach_property (selection);
1726 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1729 ScrollProc (w, NULL, (XtPointer) -1);
1733 if (key_event->state >= Mod1Mask)
1735 lose_selection (NULL, NULL);
1741 if (key_event->state >= Mod1Mask)
1743 lose_selection (NULL, NULL);
1751 if (buf[0] == 17) /* C-q */
1753 XtAppSetExitFlag (context);
1756 else if (buf[0] == 12) /* C-l */
1758 redraw (0, win_height, 1, 1);
1763 MText *temp = mtext ();
1765 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1766 : ((unsigned char *) buf)[0]);
1767 if (current_input_context)
1768 mtext_put_prop (temp, 0, 1, Mlanguage,
1769 current_input_context->im->language);
1770 insert_chars (temp);
1771 m17n_object_unref (temp);
1776 if (! keep_target_x_position)
1777 target_x_position = cursor.x;
1781 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1783 char *name = (char *) client_data;
1785 int from = -1, to = 0;
1790 filename = strdup (name);
1793 fp = fopen (filename, "w");
1796 fprintf (stderr, "Open for write fail: %s", filename);
1802 from = mtext_property_start (selection);
1803 to = mtext_property_end (selection);
1804 mtext_detach_property (selection);
1807 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1810 select_region (from, to);
1814 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1820 mtext_detach_property (selection);
1821 serialized = (int) client_data;
1823 new = mtext_deserialize (mt);
1826 MPlist *plist = mplist ();
1828 mplist_push (plist, Mt, Mface);
1829 mplist_push (plist, Mt, Mlanguage);
1830 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1831 m17n_object_unref (plist);
1835 m17n_object_unref (mt);
1837 serialized = ! serialized;
1838 nchars = mtext_len (mt);
1841 update_cursor (0, 1);
1842 redraw (0, win_height, 1, 1);
1846 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1848 XtAppSetExitFlag (context);
1854 FILE *fp = fopen (filename, "r");
1857 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1858 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1861 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1866 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1868 int data = (int) client_data;
1873 control.enable_bidi = 0;
1874 control.orientation_reversed = 0;
1878 control.enable_bidi = 1;
1879 control.orientation_reversed = data == 2;
1881 for (i = 0; i < 3; i++)
1884 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1886 XtSetArg (arg[0], XtNleftBitmap, None);
1887 XtSetValues (BidiMenus[i], arg, 1);
1890 update_cursor (cursor.from, 1);
1891 redraw (0, win_height, 1, 0);
1895 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1897 int data = (int) client_data;
1901 control.max_line_width = 0;
1904 control.max_line_width = win_width;
1905 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1907 for (i = 0; i < 3; i++)
1910 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1912 XtSetArg (arg[0], XtNleftBitmap, None);
1913 XtSetValues (LineBreakMenus[i], arg, 1);
1916 update_cursor (cursor.from, 1);
1917 redraw (0, win_height, 1, 0);
1921 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1923 char *filter_module = (char *) client_data;
1925 void (*func) (MText *, int, int);
1929 handle = dlopen (filter_module, RTLD_NOW);
1932 *(void **) (&func) = dlsym (handle, "filter");
1934 (*func) (mt, mtext_property_start (selection),
1935 mtext_property_end (selection));
1940 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1942 int data = (int) client_data;
1956 control.cursor_bidi = 0, control.cursor_width = -1;
1960 control.cursor_bidi = 0, control.cursor_width = 2;
1964 control.cursor_bidi = 1;
1969 for (i = from; i < to; i++)
1972 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1974 XtSetArg (arg[0], XtNleftBitmap, None);
1975 XtSetValues (CursorMenus[i], arg, 1);
1978 update_cursor (cursor.from, 0);
1979 redraw (0, win_height, 1, 0);
1983 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1985 int idx = (int) client_data;
1987 if (idx == -2 ? (! auto_input_method && current_input_method < 0)
1988 : idx == -1 ? auto_input_method
1989 : idx == current_input_method)
1992 if (auto_input_method)
1994 select_input_method (-1);
1995 XtSetArg (arg[0], XtNleftBitmap, None);
1996 XtSetValues (InputMethodMenus[1], arg, 1);
1997 auto_input_method = 0;
2002 select_input_method (-1);
2003 XtSetArg (arg[0], XtNleftBitmap, None);
2004 XtSetValues (InputMethodMenus[0], arg, 1);
2005 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
2006 XtSetValues (InputMethodMenus[1], arg, 1);
2007 auto_input_method = 1;
2012 select_input_method (idx);
2016 MPlist *default_face_list;
2019 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
2021 int idx = (int) client_data;
2032 MFace *face = mframe_get_prop (frame, Mface);
2034 for (plist = default_face_list; mplist_key (plist) != Mnil;
2035 plist = mplist_next (plist))
2036 mface_merge (face, mplist_value (plist));
2037 mplist_add (plist, Mt, *face_table[idx].face);
2038 mface_merge (face, *face_table[idx].face);
2040 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
2042 MFace *face = mframe_get_prop (frame, Mface);
2044 for (plist = default_face_list;
2045 mplist_key (mplist_next (plist)) != Mnil;
2046 plist = mplist_next (plist))
2047 mface_merge (face, mplist_value (plist));
2051 update_cursor (0, 1);
2052 redraw (0, win_height, 1, 1);
2057 XtAppAddWorkProc (context, show_cursor, NULL);
2058 from = mtext_property_start (selection);
2059 to = mtext_property_end (selection);
2060 old_y1 = sel_end.y1;
2062 mtext_detach_property (selection);
2065 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
2066 MTEXTPROP_REAR_STICKY);
2067 mtext_push_property (mt, from, to, prop);
2068 m17n_object_unref (prop);
2071 mtext_pop_prop (mt, from, to, Mface);
2073 update_top (top.from);
2074 update_cursor (cursor.from, 1);
2075 select_region (from, to);
2076 update_region (sel_start.y0, old_y1, sel_end.y1);
2077 if (cur.y1 > win_height)
2079 while (cur.y1 > win_height)
2082 update_cursor (cursor.from, 1);
2088 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2090 MSymbol sym = (MSymbol) client_data;
2097 XtAppAddWorkProc (context, show_cursor, NULL);
2098 from = mtext_property_start (selection);
2099 to = mtext_property_end (selection);
2100 old_y1 = sel_end.y1;
2102 mtext_detach_property (selection);
2104 mtext_put_prop (mt, from, to, Mlanguage, sym);
2106 mtext_pop_prop (mt, from, to, Mlanguage);
2109 update_top (top.from);
2110 update_cursor (cursor.from, 1);
2111 select_region (from, to);
2112 update_region (sel_start.y0, old_y1, sel_end.y1);
2113 if (cur.y1 > win_height)
2115 while (cur.y1 > win_height)
2118 update_cursor (cursor.from, 1);
2124 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2126 int narrowed = (int) client_data;
2129 MConverter *converter;
2135 from = mtext_property_start (selection);
2136 to = mtext_property_end (selection);
2145 mdump = popen ("mdump -q -p a4", "w");
2147 mdump = popen ("mdump -q", "w");
2150 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2151 mconv_encode_range (converter, mt, from, to);
2152 mconv_free_converter (converter);
2157 input_status (MInputContext *ic, MSymbol command)
2159 XFillRectangle (display, input_status_pixmap, gc_inv,
2160 0, 0, input_status_width, input_status_height);
2161 if (command == Minput_status_draw)
2165 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2166 Mface, face_input_status);
2167 if (ic->im->language != Mnil)
2168 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2169 Mlanguage, ic->im->language);
2170 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2171 &input_status_control, NULL, NULL, &rect);
2172 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2173 input_status_width - rect.width - 2, - rect.y,
2174 ic->status, 0, mtext_len (ic->status),
2175 &input_status_control);
2177 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2178 XtSetValues (CurIMStatus, arg, 1);
2182 surrounding_text_handler (MInputContext *ic, MSymbol command)
2184 if (command == Minput_get_surrounding_text)
2186 int len = (int) mplist_value (ic->plist);
2188 MText *surround = NULL;
2192 pos = cursor.from + len;
2195 surround = mtext_duplicate (mt, pos, cursor.from);
2199 pos = cursor.from + len;
2202 surround = mtext_duplicate (mt, cursor.from, pos);
2206 mplist_set (ic->plist, Mtext, surround);
2207 m17n_object_unref (surround);
2210 else if (command == Minput_delete_surrounding_text)
2212 int len = (int) mplist_value (ic->plist);
2216 if (cursor.from + len < 0)
2217 len = - cursor.from;
2218 mtext_del (mt, cursor.from + len, cursor.from);
2220 update_cursor (cursor.from + len, 1);
2224 if (cursor.from + len > nchars)
2225 len = nchars - cursor.from;
2226 mtext_del (mt, cursor.from, cursor.from + len);
2228 update_cursor (cursor.from, 1);
2236 compare_input_method (const void *elt1, const void *elt2)
2238 const InputMethodInfo *im1 = elt1;
2239 const InputMethodInfo *im2 = elt2;
2240 MSymbol lang1, lang2;
2242 if (im1->language == Mnil)
2244 if (im1->language == im2->language)
2245 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2246 if (im1->language == Mt)
2248 if (im2->language == Mt)
2250 lang1 = msymbol_get (im1->language, Mlanguage);
2251 lang2 = msymbol_get (im2->language, Mlanguage);
2252 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2256 setup_input_methods (int with_xim, char *initial_input_method)
2258 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2262 num_input_methods = plist ? mplist_length (plist) : 0;
2264 num_input_methods++;
2265 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2270 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
2272 MDatabase *mdb = mplist_value (pl);
2273 MSymbol *tag = mdatabase_tag (mdb);
2276 i--, num_input_methods--;
2279 input_method_table[i].language = tag[1];
2280 input_method_table[i].name = tag[2];
2283 m17n_object_unref (plist);
2287 input_method_table[i].language = Mnil;
2288 input_method_table[i].name = msymbol ("xim");
2292 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2293 compare_input_method);
2294 mplist_put (minput_driver->callback_list, Minput_status_start,
2295 (void *) input_status);
2296 mplist_put (minput_driver->callback_list, Minput_status_draw,
2297 (void *) input_status);
2298 mplist_put (minput_driver->callback_list, Minput_status_done,
2299 (void *) input_status);
2300 mplist_put (minput_driver->callback_list, Minput_get_surrounding_text,
2301 (void *) surrounding_text_handler);
2302 mplist_put (minput_driver->callback_list, Minput_delete_surrounding_text,
2303 (void *) surrounding_text_handler);
2305 current_input_context = NULL;
2306 current_input_method = -1;
2308 if (initial_input_method)
2310 char *lang_name, *method_name;
2311 char *p = strchr (initial_input_method, '-');
2314 lang_name = initial_input_method, *p = '\0', method_name = p + 1;
2316 lang_name = "t", method_name = initial_input_method;
2318 for (i = 0; i < num_input_methods; i++)
2319 if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
2321 && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
2323 current_input_method = i;
2331 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2335 if (num && *num > 0)
2339 for (i = 0; i < *num; i++)
2340 bytes += strlen (str[i]) + 1;
2341 msg = alloca (bytes);
2342 strcpy (msg, str[0]);
2343 for (i = 1; i < *num; i++)
2344 strcat (msg, " "), strcat (msg, str[i]);
2346 else if (cursor.from < nchars)
2348 int c = mtext_ref_char (mt, cursor.from);
2349 char *name = mchar_get_prop (c, Mname);
2353 msg = alloca (10 + strlen (name));
2354 sprintf (msg, "U+%04X %s", c, name);
2360 XtSetArg (arg[0], XtNlabel, msg);
2361 XtSetValues (MessageWidget, arg, 1);
2367 char *name1, *name2;
2368 XtCallbackProc proc;
2369 XtPointer client_data;
2374 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2376 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2378 MenuRec FileMenu[] =
2379 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2380 { 0, "Save", NULL, SaveProc, NULL, -1 },
2381 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2383 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2384 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2386 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2387 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2389 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2392 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2394 MenuRec *rec = (MenuRec *) client_data;
2397 XtSetArg (arg[0], XtNvalue, "");
2398 XtSetArg (arg[1], XtNlabel, rec->name1);
2399 XtSetValues (FileDialogWidget, arg, 2);
2400 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2401 XtSetArg (arg[0], XtNx, x + 20);
2402 XtSetArg (arg[1], XtNy, y + 10);
2403 XtSetValues (FileShellWidget, arg, 2);
2404 XtPopup (FileShellWidget, XtGrabExclusive);
2408 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2413 XtPopdown (FileShellWidget);
2414 if ((int) client_data == 1)
2416 XtSetArg (arg[0], XtNlabel, &label);
2417 XtGetValues (FileDialogWidget, arg, 1);
2418 if (strcmp (label, FileMenu[0].name1) == 0)
2422 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2423 fp = fopen (filename, "r");
2425 m17n_object_unref (mt);
2428 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2436 nchars = mtext_len (mt);
2438 update_cursor (0, 1);
2439 redraw (0, win_height, 1, 1);
2441 else if (strcmp (label, FileMenu[2].name1) == 0)
2442 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2444 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2447 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2448 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2449 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2450 (MENU).status = (STATUS))
2454 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2455 char *menu_name, MenuRec *menus, int num_menus, char *help)
2457 Widget button, menu;
2458 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2459 <LeaveWindow>: reset() MenuHelp()\n\
2460 <BtnDown>: reset() PopupMenu()\n\
2461 <BtnUp>: highlight()";
2467 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2468 for (i = 0; i < num_menus; i++)
2479 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2481 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2483 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2485 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2489 XtSetArg (arg[0], XtNsensitive, False);
2490 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2496 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2501 trans = alloca (strlen (fmt) + strlen (help));
2502 sprintf (trans, fmt, help);
2503 XtSetArg (arg[0], XtNmenuName, menu_name);
2504 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2505 XtSetArg (arg[2], XtNinternalWidth, 2);
2506 XtSetArg (arg[3], XtNhighlightThickness, 1);
2507 XtSetArg (arg[4], XtNleft, XawChainLeft);
2508 XtSetArg (arg[5], XtNright, XawChainLeft);
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 = msymbol_get (im->language, Mlanguage);
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 = msymbol_get (sym, Mlanguage)) != 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 */