1 /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*-
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 @enpage m17n-edit edit multilingual text
26 @section m17n-edit-synopsis SYNOPSIS
28 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section m17n-edit-description DESCRIPTION
32 Display FILE on a window and allow users to edit it.
34 XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).
36 The following OPTIONs are available.
50 This program is to demonstrate how to use the m17n GUI API.
51 Although m17n-edit directly uses the GUI API, the API is mainly
52 for toolkit libraries or to implement XOM (X Outout Method), not
53 for direct use from application programs.
56 @japage m17n-edit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section m17n-edit-synopsis SYNOPSIS
60 m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section m17n-edit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit
83 ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é
84 ¥ê¤äXOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
85 ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
100 #ifdef HAVE_X11_XAW_COMMAND_H
102 #include <X11/keysym.h>
103 #include <X11/Xatom.h>
104 #include <X11/Intrinsic.h>
105 #include <X11/StringDefs.h>
106 #include <X11/Shell.h>
108 #include <m17n-gui.h>
109 #include <m17n-misc.h>
112 #include <X11/Xaw/Command.h>
113 #include <X11/Xaw/Box.h>
114 #include <X11/Xaw/Form.h>
115 #include <X11/Xaw/Dialog.h>
116 #include <X11/Xaw/Scrollbar.h>
117 #include <X11/Xaw/Toggle.h>
118 #include <X11/Xaw/SimpleMenu.h>
119 #include <X11/Xaw/SmeBSB.h>
120 #include <X11/Xaw/SmeLine.h>
121 #include <X11/Xaw/MenuButton.h>
123 #define VERSION "1.2.0"
125 /* Global variables. */
130 /* For the X Window System. */
133 /* GCs for normal drawing, filling by background color, normal drawing
134 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
136 GC gc, gc_inv, mono_gc, mono_gc_inv;
138 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
139 XtAppContext context;
140 int default_font_size;
144 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
145 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
146 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
147 +- Body -- Sbar, Text
151 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
152 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
153 Widget SbarWidget, TextWidget;
154 Widget FileShellWidget, FileDialogWidget;
155 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
156 Widget CurIMLang, CurIMStatus;
158 int win_width, win_height; /* Size of TextWidget. */
161 Pixmap input_status_pixmap;
162 int input_status_width, input_status_height;
164 /* Bitmap for "check" glyph. */
165 #define check_width 9
166 #define check_height 8
167 static unsigned char check_bits[] = {
168 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
169 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
172 /* For the m17n library. */
175 int nchars; /* == mtext_len (mt) */
176 MDrawControl control, input_status_control;
177 MTextProperty *selection;
182 MFace *face_xxx_large;
184 MFace *face_courier, *face_helvetica, *face_times;
185 MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
186 MFace *face_default_fontset, *face_no_ctl_fontset;
187 MFace *face_input_status;
189 MSymbol Mcoding_compound_text;
191 int logical_move = 1; /* If 0, move cursor visually. */
195 MSymbol language, name;
199 InputMethodInfo *input_method_table;
201 int num_input_methods;
202 int current_input_method = -1; /* i.e. none */
203 int auto_input_method = 0;
204 MInputContext *current_input_context;
211 { {"Menu Size", NULL},
212 {"xx-small", &mface_xx_small},
213 {"x-small", &mface_x_small},
214 {"small", &mface_small},
215 {"normalsize", &mface_normalsize},
216 {"large", &mface_large},
217 {"x-large", &mface_x_large},
218 {"xx-large", &mface_xx_large},
219 {"xxx-large", &face_xxx_large},
221 {"Menu Family", NULL},
222 {"courier", &face_courier},
223 {"helvetica", &face_helvetica},
224 {"times", &face_times},
225 {"dv-ttyogesh", &face_dv_ttyogesh},
226 {"freesans", &face_freesans},
227 {"freeserif", &face_freeserif},
228 {"freemono", &face_freemono},
230 {"Menu Style", NULL},
231 {"medium", &mface_medium},
232 {"bold", &mface_bold},
233 {"italic", &mface_italic},
235 {"Menu Color", NULL},
236 {"black", &mface_black},
237 {"white", &mface_white},
239 {"green", &mface_green},
240 {"blue", &mface_blue},
241 {"cyan", &mface_cyan},
242 {"yello", &mface_yellow},
243 {"magenta", &mface_magenta},
246 {"normal", &mface_normal_video},
247 {"reverse", &mface_reverse_video},
248 {"underline", &mface_underline},
250 {"No CTL", &face_no_ctl_fontset} };
253 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
255 /* Information about a physical line metric. */
258 int from; /* BOL position of the line. */
259 int to; /* BOL position of the next line. */
260 int y0, y1; /* Top and bottom Y position of the line. */
261 int ascent; /* Height of the top Y position. */
264 struct LineInfo top; /* Topmost line. */
265 struct LineInfo cur; /* Line containing cursor. */
266 struct LineInfo sel_start; /* Line containing selection start. */
267 struct LineInfo sel_end; /* Line containing selection end. */
269 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
271 /* X position to keep on vertical (up and down) cursor motion. */
272 int target_x_position;
274 /* Interface macros for m17n-lib drawing routines. */
276 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
277 coordinate ($X, $Y) */
278 #define DRAW_TEXT(x, y, from, to) \
279 mdraw_text_with_control \
280 (frame, (MDrawWindow) win, \
281 control.orientation_reversed ? x + win_width : x, y, \
282 mt, from, to, &control)
284 /* Store the extents of a text in the range $FROM to $TO in the
285 structure $RECT (type MDrawMetric). */
286 #define TEXT_EXTENTS(from, to, rect) \
287 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
289 /* Store the glyph information of a character at the position $POS in
290 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
291 $FROM is written at the coordinate (0, 0). */
292 #define GLYPH_INFO(from, pos, info) \
293 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
295 /* Set $X and $Y to the coordinate of character at position $POS
296 assuming that the text from $FROM is written at the coordinate (0,
298 #define COORDINATES_POSITION(from, pos, x, y) \
299 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
301 /* Interface macros for X library. */
302 #define COPY_AREA(y0, y1, to) \
303 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
305 #define CLEAR_AREA(x, y, w, h) \
306 XClearArea (display, win, (x), (y), (w), (h), False)
308 #define SELECTEDP() \
309 mtext_property_mtext (selection)
311 /* Format MSG by FMT and print the result to the stderr, and exit. */
312 #define FATAL_ERROR(fmt, arg) \
314 fprintf (stderr, fmt, arg); \
319 /* If POS is greater than zero, move POS back to the beginning of line
320 (BOL) position. If FORWARD is nonzero, move POS forward instead.
321 Return the new position. */
323 bol (int pos, int forward)
325 int limit = forward ? nchars : 0;
327 pos = mtext_character (mt, pos, limit, '\n');
328 return (pos < 0 ? limit : pos + 1);
331 /* Update the structure #TOP (struct LineInfo) to make $POS the first
332 character position of the screen. */
336 int from = bol (pos, 0);
339 GLYPH_INFO (from, pos, info);
340 top.from = info.line_from;
341 top.to = info.line_to;
343 top.y1 = info.metrics.height;
344 top.ascent = - info.metrics.y;
348 /* Update the scroll bar so that the text of the range $FROM to $TO
349 are shown on the window. */
351 update_scroll_bar (int from, int to)
353 float top = (float) from / nchars;
354 float shown = (float) (to - from) / nchars;
355 XtArgVal *l_top = (XtArgVal *) ⊤
356 XtArgVal *l_shown = (XtArgVal *) &shown;
358 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
359 XtSetArg (arg[1], XtNshown, *l_shown);
360 XtSetValues (SbarWidget, arg, 2);
364 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
365 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
366 is nonzero, update the scoll bar. */
368 redraw (int y0, int y1, int clear, int scroll_bar)
373 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
374 struct LineInfo *line;
376 if (clear || control.anti_alias)
377 CLEAR_AREA (0, y0, win_width, y1 - y0);
379 /* Find a line closest to y0. It is a cursor line if the cursor is
380 Y0, otherwise the top line. */
385 /* If there exists a selected region, check it too. */
386 if (sel_y0 > line->y0 && y0 >= sel_y0)
391 info.metrics.height = line->y1 - y;
392 info.metrics.y = - line->ascent;
393 info.line_to = line->to;
394 while (from < nchars && y + info.metrics.height <= y0)
396 y += info.metrics.height;
398 GLYPH_INFO (from, from, info);
400 y0 = y - info.metrics.y;
402 while (to < nchars && y < y1)
404 GLYPH_INFO (to, to, info);
405 y += info.metrics.height;
411 DRAW_TEXT (0, y0, from, to);
416 GLYPH_INFO (to, to, info);
417 if (y + info.metrics.height >= win_height)
420 y += info.metrics.height;
422 update_scroll_bar (top.from, to);
427 /* Set the current input method spot to the correct position. */
429 set_input_method_spot ()
431 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
432 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
435 int size = 0, ratio = 0, i;
438 n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
440 for (i = n - 1; i >= 0; i--)
443 size = (int) mface_get_prop (faces[i], Msize);
445 ratio = (int) mface_get_prop (faces[i], Mratio);
448 size = default_font_size;
450 size = size * ratio / 100;
451 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
452 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
457 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
460 redraw_cursor (int clear)
462 if (control.cursor_bidi)
464 /* We must update the whole line of the cursor. */
465 int beg = bol (cur.from, 0);
466 int end = bol (cur.to - 1, 1);
468 int y0 = cur.y0, y1 = cur.y1;
472 TEXT_EXTENTS (beg, cur.from, rect);
477 TEXT_EXTENTS (cur.to, end, rect);
480 redraw (y0, y1, clear, 0);
488 if (control.orientation_reversed)
489 x += win_width - cursor.logical_width;
490 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
492 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
497 /* Update the information about the location of cursor to the position
498 $POS. If $FULL is nonzero, update the information fully only from
499 the information about the top line. Otherwise, trust the current
500 information in the structure $CUR. */
502 update_cursor (int pos, int full)
508 /* CUR is inaccurate. We can trust only TOP. */
509 GLYPH_INFO (top.from, pos, cursor);
510 cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
512 else if (pos < cur.from)
514 int from = bol (pos, 0);
516 TEXT_EXTENTS (from, cur.from, rect);
517 GLYPH_INFO (from, pos, cursor);
518 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
520 else if (pos < cur.to)
522 GLYPH_INFO (cur.from, pos, cursor);
526 GLYPH_INFO (cur.from, pos, cursor);
527 cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
530 cur.from = cursor.line_from;
531 cur.to = cursor.line_to;
532 cur.y1 = cur.y0 + cursor.metrics.height;
533 cur.ascent = - cursor.metrics.y;
537 /* Update the information about the selected region. */
547 from = mtext_property_start (selection);
548 to = mtext_property_end (selection);
552 int pos = bol (from, 0);
554 TEXT_EXTENTS (pos, top.from, rect);
555 sel_start.y0 = top.y0 - rect.height;
556 sel_start.ascent = - rect.y;
557 GLYPH_INFO (pos, from, info);
558 if (pos < info.line_from)
559 sel_start.y0 += - rect.y + info.y + info.metrics.y;
563 GLYPH_INFO (top.from, from, info);
564 sel_start.y0 = top.ascent + info.y + info.metrics.y;
566 sel_start.ascent = -info.metrics.y;
567 sel_start.y1 = sel_start.y0 + info.metrics.height;
568 sel_start.from = info.line_from;
569 sel_start.to = info.line_to;
571 if (to <= sel_start.to)
577 GLYPH_INFO (sel_start.from, to, info);
578 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
579 sel_end.y1 = sel_end.y0 + info.metrics.height;
580 sel_end.ascent = - info.metrics.y;
581 sel_end.from = info.line_from;
582 sel_end.to = info.line_to;
587 /* Select the text in the region from $FROM to $TO. */
589 select_region (int from, int to)
594 pos = from, from = to, to = pos;
595 mtext_push_property (mt, from, to, selection);
600 /* Setup the window to display the character of $POS at the top left
606 /* Top and bottom Y positions to redraw. */
609 if (pos + 1000 < top.from)
610 y0 = 0, y1 = win_height;
611 else if (pos < top.from)
614 TEXT_EXTENTS (pos, top.from, rect);
615 if (rect.height >= win_height * 0.9)
620 COPY_AREA (0, win_height - y1, y1);
623 else if (pos < top.to)
625 /* No need of redrawing. */
628 else if (pos < top.from + 1000)
630 TEXT_EXTENTS (top.from, pos, rect);
631 if (rect.height >= win_height * 0.9)
635 y0 = win_height - rect.height;
636 COPY_AREA (rect.height, win_height, 0);
641 y0 = 0, y1 = win_height;
647 update_cursor (pos, 1);
649 update_cursor (cursor.from, 1);
651 redraw (y0, y1, 1, 1);
655 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
658 /* Select an input method accoding to $IDX. If $IDX is negative, turn
659 off the current input method, otherwide turn on the input method
660 input_method_table[$IDX]. */
662 select_input_method (idx)
664 if (idx == current_input_method)
666 if (current_input_context)
668 minput_destroy_ic (current_input_context);
669 current_input_context = NULL;
670 current_input_method = -1;
674 InputMethodInfo *im = input_method_table + idx;
676 if (im->language == Mnil)
678 MInputXIMArgIC arg_xic;
679 Window win = XtWindow (TextWidget);
681 arg_xic.input_style = 0;
682 arg_xic.client_win = arg_xic.focus_win = win;
683 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
684 current_input_context = minput_create_ic (im->im, &arg_xic);
688 MInputGUIArgIC arg_ic;
690 arg_ic.frame = frame;
691 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
692 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
693 current_input_context = minput_create_ic (im->im, &arg_ic);
696 if (current_input_context)
698 set_input_method_spot ();
699 current_input_method = idx;
702 if (current_input_method >= 0)
705 XtSetArg (arg[0], XtNlabel, &label);
706 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
707 XtSetArg (arg[0], XtNlabel, label);
710 XtSetArg (arg[0], XtNlabel, "");
711 XtSetValues (CurIMLang, arg, 1);
714 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
717 /* Display cursor according to the current information of #CUR.
718 $CLIENT_DATA is ignore. Most callback functions add this function
719 as a background processing procedure the current application (by
720 XtAppAddWorkProc) via the function hide_cursor. */
722 show_cursor (XtPointer client_data)
724 MFaceHLineProp *hline;
730 update_cursor (cursor.from, 1);
732 while (cur.y1 > win_height)
735 update_cursor (cursor.from, 1);
738 control.cursor_pos = cursor.from;
741 control.with_cursor = 1;
744 if (current_input_context)
745 set_input_method_spot ();
749 int pos = (SELECTEDP () ? mtext_property_start (selection)
750 : cursor.from > 0 ? cursor.from - 1
752 MFace *face = mface ();
753 MTextProperty *props[256];
754 int n = mtext_get_properties (mt, pos, Mface, props, 256);
756 char buf[256], *p = buf;
762 int size = (int) mfont_get_prop (cursor.font, Msize);
763 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
764 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
765 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
766 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
768 sprintf (p, "%dpt", size / 10), p += strlen (p);
770 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
772 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
774 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
776 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
780 mface_merge (face, face_default);
781 for (i = 0; i < n; i++)
782 if (props[i] != selection)
783 mface_merge (face, (MFace *) mtext_property_value (props[i]));
784 sym = (MSymbol) mface_get_prop (face, Mforeground);
786 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
787 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
788 strcat (p, ",rev"), p += strlen (p);
789 hline = mface_get_prop (face, Mhline);
790 if (hline && hline->width > 0)
791 strcat (p, ",ul"), p += strlen (p);
792 box = mface_get_prop (face, Mbox);
793 if (box && box->width > 0)
794 strcat (p, ",box"), p += strlen (p);
795 m17n_object_unref (face);
797 XtSetArg (arg[0], XtNborderWidth, 1);
798 XtSetArg (arg[1], XtNlabel, buf);
799 XtSetValues (CurFaceWidget, arg, 2);
802 if (control.cursor_pos < nchars)
804 MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
808 XtSetArg (arg[0], XtNborderWidth, 0);
809 XtSetArg (arg[1], XtNlabel, "");
813 XtSetArg (arg[0], XtNborderWidth, 1);
814 XtSetArg (arg[1], XtNlabel,
815 msymbol_name (msymbol_get (sym, Mlanguage)));
816 XtSetValues (CurLangWidget, arg, 2);
818 XtSetValues (CurLangWidget, arg, 2);
820 if (auto_input_method)
823 select_input_method (-1);
828 for (i = 0; i < num_input_methods; i++)
829 if (input_method_table[i].language == sym)
831 if (i < num_input_methods
832 && input_method_table[i].available >= 0)
834 if (! input_method_table[i].im)
836 input_method_table[i].im =
837 minput_open_im (input_method_table[i].language,
838 input_method_table[i].name, NULL);
839 if (! input_method_table[i].im)
840 input_method_table[i].available = -1;
842 if (input_method_table[i].im)
843 select_input_method (i);
845 select_input_method (-1);
848 select_input_method (-1);
853 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
859 /* Hide the cursor. */
863 control.with_cursor = 0;
865 XtAppAddWorkProc (context, show_cursor, NULL);
869 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
870 $Y1 and $NEW_Y1 assuming that the text in the other area is not
873 update_region (int y0, int old_y1, int new_y1)
879 if (old_y1 < win_height)
881 COPY_AREA (old_y1, win_height, new_y1);
882 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
885 redraw (new_y1, win_height, 1, 0);
887 else if (new_y1 > old_y1)
889 if (new_y1 < win_height)
890 COPY_AREA (old_y1, win_height, new_y1);
892 if (new_y1 > win_height)
894 redraw (y0, new_y1, 1, 1);
898 /* Delete the next $N characters. If $N is negative delete the
899 precious (- $N) characters. */
905 int y0, old_y1, new_y1;
907 int line_from = cursor.line_from;
910 from = cursor.from, to = from + n;
913 if (cursor.from == cur.from)
915 /* We are at the beginning of line. */
916 int pos = cursor.prev_from;
918 if (cursor.from == top.from)
920 /* We are at the beginning of screen. We must scroll
922 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
923 reseat (info.line_from);
925 update_cursor (pos, 1);
931 from = cursor.from - 1;
936 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
937 old_y1 = cur.y0 + rect.height;
939 /* Now delete a character. */
940 mtext_del (mt, from, to);
942 if (from >= top.from && from < top.to)
943 update_top (top.from);
944 update_cursor (from, 1);
947 if (line_from != cursor.line_from)
950 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
951 new_y1 = cur.y0 + rect.height;
953 update_region (cur.y0, old_y1, new_y1);
957 /* Insert M-text $NEWTEXT at the current cursor position. */
959 insert_chars (MText *newtext)
961 int n = mtext_len (newtext);
963 int y0, old_y1, new_y1;
968 int n = (mtext_property_end (selection)
969 - mtext_property_start (selection));
970 mtext_detach_property (selection);
975 if (cursor.line_from > 0
976 && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
977 y0 -= control.min_line_descent;
979 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
980 old_y1 = y0 + rect.height;
982 line_from = cursor.line_from;
984 /* Now insert chars. */
985 mtext_ins (mt, cursor.from, newtext);
987 if (cur.from == top.from)
988 update_top (top.from);
989 update_cursor (cursor.from + n, 1);
991 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
992 new_y1 = cur.y0 + rect.height;
994 update_region (y0, old_y1, new_y1);
1000 word_constituent_p (int c)
1002 MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
1003 char *name = category != Mnil ? msymbol_name (category) : NULL;
1005 return (name && (name[0] == 'L' || name[0] == 'M'));
1012 int pos = cursor.from;
1014 while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
1018 MTextProperty *prop = mtext_get_property (mt, pos, Mword);
1021 pos = mtext_property_end (prop);
1023 while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
1026 update_cursor (pos, 0);
1032 int pos = cursor.from;
1034 while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
1038 MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
1041 pos = mtext_property_start (prop);
1043 while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
1046 update_cursor (pos, 0);
1050 /* Convert the currently selected text to UTF8-STRING or
1051 COMPOUND-TEXT. It is called when someone requests the current
1052 value of the selection. */
1054 covert_selection (Widget w, Atom *selection_atom,
1055 Atom *target, Atom *return_type,
1056 XtPointer *value, unsigned long *length, int *format)
1058 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1059 MText *this_mt = mtext ();
1060 int from = mtext_property_start (selection);
1061 int to = mtext_property_end (selection);
1065 mtext_copy (this_mt, 0, mt, from, to);
1066 if (*target == XA_TEXT)
1068 #ifdef X_HAVE_UTF8_STRING
1069 coding = Mcoding_utf_8;
1070 *return_type = XA_UTF8_STRING;
1072 coding = Mcoding_compound_text;
1073 *return_type = XA_COMPOUND_TEXT;
1076 else if (*target == XA_UTF8_STRING)
1078 coding = Mcoding_utf_8;
1079 *return_type = XA_UTF8_STRING;
1081 else if (*target == XA_STRING)
1086 for (i = 0; i < len; i++)
1087 if (mtext_ref_char (this_mt, i) >= 0x100)
1088 /* Can't encode in XA_STRING */
1090 coding = Mcoding_iso_8859_1;
1091 *return_type = XA_STRING;
1093 else if (*target == XA_COMPOUND_TEXT)
1095 coding = Mcoding_compound_text;
1096 *return_type = XA_COMPOUND_TEXT;
1101 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1102 m17n_object_unref (this_mt);
1106 *value = (XtPointer) buf;
1112 /* Unselect the text. It is called when we loose the selection. */
1114 lose_selection (Widget w, Atom *selection_atom)
1118 mtext_detach_property (selection);
1119 redraw (sel_start.y0, sel_end.y1, 1, 0);
1124 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1125 XtPointer value, unsigned long *length, int *format)
1130 if (*type == XT_CONVERT_FAIL || ! value)
1132 if (*type == XA_STRING)
1134 else if (*type == XA_COMPOUND_TEXT)
1135 coding = msymbol ("compound-text");
1136 #ifdef X_HAVE_UTF8_STRING
1137 else if (*type == XA_UTF8_STRING)
1138 coding = msymbol ("utf-8");
1143 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1144 if (! this_mt && *type != XA_UTF8_STRING)
1146 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1153 insert_chars (this_mt);
1154 m17n_object_unref (this_mt);
1163 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1165 XExposeEvent *expose = (XExposeEvent *) event;
1169 Dimension width_max, width;
1171 XtSetArg (arg[0], XtNwidth, &width);
1172 XtGetValues (XtParent (w), arg, 1);
1174 XtGetValues (HeadWidget, arg, 1);
1175 if (width_max < width)
1177 XtGetValues (FaceWidget, arg, 1);
1178 if (width_max < width)
1180 XtGetValues (LangWidget, arg, 1);
1181 if (width_max < width)
1183 XtSetArg (arg[0], XtNwidth, width_max);
1184 XtSetValues (HeadWidget, arg, 1);
1185 XtSetValues (FaceWidget, arg, 1);
1186 XtSetValues (LangWidget, arg, 1);
1187 XtSetValues (XtParent (w), arg, 1);
1188 XtSetValues (TailWidget, arg, 1);
1191 update_cursor (0, 1);
1192 redraw (0, win_height, 0, 1);
1193 if (current_input_method >= 0)
1195 int idx = current_input_method;
1197 current_input_method = -1;
1198 input_method_table[idx].im =
1199 minput_open_im (input_method_table[idx].language,
1200 input_method_table[idx].name, NULL);
1201 if (input_method_table[idx].im)
1202 select_input_method (idx);
1204 input_method_table[idx].available = -1;
1210 redraw (expose->y, expose->y + expose->height, 0, 0);
1211 if (current_input_context
1212 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1213 set_input_method_spot ();
1218 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1220 XConfigureEvent *configure = (XConfigureEvent *) event;
1223 control.max_line_width = win_width = configure->width;
1224 win_height = configure->height;
1225 mdraw_clear_cache (mt);
1227 update_cursor (0, 1);
1228 redraw (0, win_height, 1, 1);
1229 if (current_input_context)
1230 set_input_method_spot ();
1234 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1237 int x = event->xbutton.x;
1238 int y = event->xbutton.y - top.ascent;
1240 if (control.orientation_reversed)
1242 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1245 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1246 mtext_detach_property (selection);
1247 redraw (sel_start.y0, sel_end.y1, 1, 0);
1250 if (current_input_context)
1252 MText *produced = mtext ();
1254 minput_reset_ic (current_input_context);
1255 minput_lookup (current_input_context, Mnil, NULL, produced);
1256 if (mtext_len (produced) > 0)
1258 insert_chars (produced);
1259 if (pos >= cursor.from)
1260 pos += mtext_len (produced);
1262 m17n_object_unref (produced);
1264 update_cursor (pos, 0);
1269 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1274 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1275 covert_selection, lose_selection, NULL);
1276 update_cursor (mtext_property_start (selection), 0);
1281 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1285 /* We don't have a local selection. */
1286 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1291 int from = mtext_property_start (selection);
1292 int to = mtext_property_end (selection);
1295 int x = event->xbutton.x;
1296 int y = event->xbutton.y - top.ascent;
1298 if (control.orientation_reversed)
1300 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1302 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1303 mtext_detach_property (selection);
1305 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1306 update_cursor (pos, 0);
1307 insert_chars (this_mt);
1308 m17n_object_unref (this_mt);
1313 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1316 int x = event->xbutton.x;
1317 int y = event->xbutton.y;
1319 if (control.orientation_reversed)
1322 pos = top.from, y -= top.ascent;
1324 pos = cur.from, y -= cur.y0 + cur.ascent;
1325 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1327 if (pos == cursor.from)
1333 /* Selection range changed. */
1334 int from = mtext_property_start (selection);
1335 int to = mtext_property_end (selection);
1336 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1337 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1339 if (cursor.from == from)
1341 /* Starting position changed. */
1344 /* Enlarged. We can simply overdraw. */
1345 select_region (pos, to);
1346 redraw (sel_start.y0, start_y1, 0, 0);
1350 /* Shrunken. Previous selection face must be cleared. */
1351 select_region (pos, to);
1352 redraw (start_y0, sel_start.y1, 1, 0);
1356 /* Shrunken to zero. */
1357 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1358 mtext_detach_property (selection);
1359 redraw (start_y0, end_y1, 1, 0);
1363 /* Full update is necessary. */
1364 select_region (to, pos);
1365 redraw (start_y0, sel_end.y1, 1, 0);
1370 /* Ending position changed. */
1373 /* Full update is necessary. */
1374 select_region (pos, from);
1375 redraw (sel_start.y0, end_y1, 1, 0);
1377 else if (pos == from)
1379 /* Shrunken to zero. */
1380 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1381 mtext_detach_property (selection);
1382 redraw (start_y0, end_y1, 1, 0);
1386 /* Shrunken. Previous selection face must be cleared. */
1387 select_region (from, pos);
1388 redraw (sel_end.y0, end_y1, 1, 0);
1392 /* Enlarged. We can simply overdraw. */
1393 select_region (from, pos);
1394 redraw (end_y0, sel_end.y1, 0, 0);
1400 /* Newly selected. */
1401 select_region (pos, cursor.from);
1402 redraw (sel_start.y0, sel_end.y1, 0, 0);
1404 update_cursor (pos, 1);
1408 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1411 MDrawGlyphInfo info;
1413 int cursor_pos = cursor.from;
1415 if (((int) position) < 0)
1421 height = top.y1 - top.y0;
1424 pos = bol (from - 1, 0);
1425 GLYPH_INFO (pos, from - 1, info);
1426 if (height + info.metrics.height > win_height)
1428 height += info.metrics.height;
1429 from = info.line_from;
1431 if (cursor_pos >= top.to)
1433 cursor_pos = top.from;
1435 while (cursor_pos < nchars)
1437 GLYPH_INFO (pos, pos, info);
1438 if (height + info.metrics.height > win_height)
1440 height += info.metrics.height;
1446 else if (cur.to < nchars)
1448 /* Scroll up, but leave at least one line. */
1451 while (from < nchars)
1453 GLYPH_INFO (from, from, info);
1454 if (height + info.metrics.height > win_height
1455 || info.line_to >= nchars)
1457 height += info.metrics.height;
1458 from = info.line_to;
1461 from = info.line_from;
1462 if (cursor_pos < from)
1466 /* Scroll up to make the cursor line top. */
1470 update_cursor (cursor_pos, 1);
1474 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1476 float persent = *(float *) persent_ptr;
1477 int pos1, pos2 = nchars * persent;
1478 MDrawGlyphInfo info;
1481 pos1 = bol (pos2, 0);
1482 GLYPH_INFO (pos1, pos2, info);
1483 pos1 = info.line_from;
1485 update_cursor (pos1, 1);
1490 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1492 XKeyEvent *key_event = (XKeyEvent *) event;
1494 KeySym keysym = NoSymbol;
1496 /* If set to 1, do not update target_x_position. */
1497 int keep_target_x_position = 0;
1500 if (current_input_context
1501 && minput_filter (current_input_context, Mnil, event))
1503 if (event->type == KeyRelease)
1508 produced = mtext ();
1509 ret = minput_lookup (current_input_context, Mnil, event, produced);
1510 if (mtext_len (produced) > 0)
1511 insert_chars (produced);
1513 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1514 m17n_object_unref (produced);
1524 n = (mtext_property_end (selection)
1525 - mtext_property_start (selection));
1526 mtext_detach_property (selection);
1528 else if (cursor.from < nchars)
1530 /* Delete the following grapheme cluster. */
1531 n = cursor.to - cursor.from;
1544 /* Delete selected region. */
1545 n = (mtext_property_end (selection)
1546 - mtext_property_start (selection));
1547 mtext_detach_property (selection);
1549 else if (cursor.from > 0)
1551 /* Delete the preceding character. */
1562 mtext_detach_property (selection);
1563 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1567 if (cursor.prev_from >= 0)
1568 update_cursor (cursor.prev_from, 0);
1572 if (cursor.left_from >= 0)
1573 update_cursor (cursor.left_from, 0);
1580 mtext_detach_property (selection);
1581 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1585 if (cursor.next_to >= 0)
1586 update_cursor (cursor.to, 0);
1590 if (cursor.right_from >= 0)
1591 update_cursor (cursor.right_from, 0);
1598 mtext_detach_property (selection);
1599 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1601 if (cur.to <= nchars)
1603 MDrawGlyphInfo info;
1606 GLYPH_INFO (cur.from, cur.to, info);
1607 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1608 target_x_position, info.y);
1609 keep_target_x_position = 1;
1610 update_cursor (pos, 0);
1617 mtext_detach_property (selection);
1618 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1624 int pos = bol (cur.from - 1, 0);
1626 TEXT_EXTENTS (pos, cur.from - 1, rect);
1627 y = rect.height + rect.y - 1;
1628 pos = COORDINATES_POSITION (pos, nchars,
1629 target_x_position, y);
1630 keep_target_x_position = 1;
1631 update_cursor (pos, 0);
1638 mtext_detach_property (selection);
1639 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1641 if (top.from < nchars)
1642 ScrollProc (w, NULL, (XtPointer) 1);
1648 mtext_detach_property (selection);
1649 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1652 ScrollProc (w, NULL, (XtPointer) -1);
1656 if (key_event->state >= Mod1Mask)
1658 lose_selection (NULL, NULL);
1664 if (key_event->state >= Mod1Mask)
1666 lose_selection (NULL, NULL);
1674 if (buf[0] == 17) /* C-q */
1676 XtAppSetExitFlag (context);
1679 else if (buf[0] == 12) /* C-l */
1681 redraw (0, win_height, 1, 1);
1686 MText *temp = mtext ();
1688 mtext_cat_char (temp, buf[0] == '\r' ? '\n'
1689 : ((unsigned char *) buf)[0]);
1690 if (current_input_context)
1691 mtext_put_prop (temp, 0, 1, Mlanguage,
1692 current_input_context->im->language);
1693 insert_chars (temp);
1694 m17n_object_unref (temp);
1699 if (! keep_target_x_position)
1700 target_x_position = cursor.x;
1704 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1706 char *name = (char *) client_data;
1708 int from = -1, to = 0;
1713 filename = strdup (name);
1716 fp = fopen (filename, "w");
1719 fprintf (stderr, "Open for write fail: %s", filename);
1725 from = mtext_property_start (selection);
1726 to = mtext_property_end (selection);
1727 mtext_detach_property (selection);
1730 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1733 select_region (from, to);
1737 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1743 mtext_detach_property (selection);
1744 serialized = (int) client_data;
1746 new = mtext_deserialize (mt);
1749 MPlist *plist = mplist ();
1751 mplist_push (plist, Mt, Mface);
1752 mplist_push (plist, Mt, Mlanguage);
1753 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1754 m17n_object_unref (plist);
1758 m17n_object_unref (mt);
1760 serialized = ! serialized;
1761 nchars = mtext_len (mt);
1764 update_cursor (0, 1);
1765 redraw (0, win_height, 1, 1);
1769 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1771 XtAppSetExitFlag (context);
1777 FILE *fp = fopen (filename, "r");
1780 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1781 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1784 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1789 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1791 int data = (int) client_data;
1796 control.enable_bidi = 0;
1797 control.orientation_reversed = 0;
1801 control.enable_bidi = 1;
1802 control.orientation_reversed = data == 2;
1804 for (i = 0; i < 3; i++)
1807 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1809 XtSetArg (arg[0], XtNleftBitmap, None);
1810 XtSetValues (BidiMenus[i], arg, 1);
1813 update_cursor (cursor.from, 1);
1814 redraw (0, win_height, 1, 0);
1818 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1820 int data = (int) client_data;
1824 control.max_line_width = 0;
1827 control.max_line_width = win_width;
1828 control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
1830 for (i = 0; i < 3; i++)
1833 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1835 XtSetArg (arg[0], XtNleftBitmap, None);
1836 XtSetValues (LineBreakMenus[i], arg, 1);
1839 update_cursor (cursor.from, 1);
1840 redraw (0, win_height, 1, 0);
1844 FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
1846 char *filter_module = (char *) client_data;
1848 void (*func) (MText *, int, int);
1852 handle = dlopen (filter_module, RTLD_NOW);
1855 *(void **) (&func) = dlsym (handle, "filter");
1857 (*func) (mt, mtext_property_start (selection),
1858 mtext_property_end (selection));
1863 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1865 int data = (int) client_data;
1879 control.cursor_bidi = 0, control.cursor_width = -1;
1883 control.cursor_bidi = 0, control.cursor_width = 2;
1887 control.cursor_bidi = 1;
1892 for (i = from; i < to; i++)
1895 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1897 XtSetArg (arg[0], XtNleftBitmap, None);
1898 XtSetValues (CursorMenus[i], arg, 1);
1901 update_cursor (cursor.from, 0);
1902 redraw (0, win_height, 1, 0);
1906 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1908 int idx = (int) client_data;
1910 if (idx == -2 ? current_input_method < 0
1911 : idx == -1 ? auto_input_method
1912 : idx == current_input_method)
1915 XtSetArg (arg[0], XtNleftBitmap, None);
1916 if (auto_input_method)
1918 XtSetValues (InputMethodMenus[1], arg, 1);
1919 auto_input_method = 0;
1921 else if (current_input_method < 0)
1922 XtSetValues (InputMethodMenus[0], arg, 1);
1924 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1928 auto_input_method = 1;
1931 else if (input_method_table[idx].available >= 0)
1933 if (! input_method_table[idx].im)
1935 input_method_table[idx].im =
1936 minput_open_im (input_method_table[idx].language,
1937 input_method_table[idx].name, NULL);
1938 if (! input_method_table[idx].im)
1939 input_method_table[idx].available = -1;
1941 if (input_method_table[idx].im)
1942 select_input_method (idx);
1944 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1945 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1948 MPlist *default_face_list;
1951 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1953 int idx = (int) client_data;
1964 MFace *face = mframe_get_prop (frame, Mface);
1966 for (plist = default_face_list; mplist_key (plist) != Mnil;
1967 plist = mplist_next (plist))
1968 mface_merge (face, mplist_value (plist));
1969 mplist_add (plist, Mt, *face_table[idx].face);
1970 mface_merge (face, *face_table[idx].face);
1972 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1974 MFace *face = mframe_get_prop (frame, Mface);
1976 for (plist = default_face_list;
1977 mplist_key (mplist_next (plist)) != Mnil;
1978 plist = mplist_next (plist))
1979 mface_merge (face, mplist_value (plist));
1983 update_cursor (0, 1);
1984 redraw (0, win_height, 1, 1);
1989 XtAppAddWorkProc (context, show_cursor, NULL);
1990 from = mtext_property_start (selection);
1991 to = mtext_property_end (selection);
1992 old_y1 = sel_end.y1;
1994 mtext_detach_property (selection);
1997 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1998 MTEXTPROP_REAR_STICKY);
1999 mtext_push_property (mt, from, to, prop);
2000 m17n_object_unref (prop);
2003 mtext_pop_prop (mt, from, to, Mface);
2005 update_top (top.from);
2006 update_cursor (cursor.from, 1);
2007 select_region (from, to);
2008 update_region (sel_start.y0, old_y1, sel_end.y1);
2009 if (cur.y1 > win_height)
2011 while (cur.y1 > win_height)
2014 update_cursor (cursor.from, 1);
2020 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
2022 MSymbol sym = (MSymbol) client_data;
2029 XtAppAddWorkProc (context, show_cursor, NULL);
2030 from = mtext_property_start (selection);
2031 to = mtext_property_end (selection);
2032 old_y1 = sel_end.y1;
2034 mtext_detach_property (selection);
2036 mtext_put_prop (mt, from, to, Mlanguage, sym);
2038 mtext_pop_prop (mt, from, to, Mlanguage);
2041 update_top (top.from);
2042 update_cursor (cursor.from, 1);
2043 select_region (from, to);
2044 update_region (sel_start.y0, old_y1, sel_end.y1);
2045 if (cur.y1 > win_height)
2047 while (cur.y1 > win_height)
2050 update_cursor (cursor.from, 1);
2056 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
2058 int narrowed = (int) client_data;
2061 MConverter *converter;
2067 from = mtext_property_start (selection);
2068 to = mtext_property_end (selection);
2077 mdump = popen ("mdump -q -p a4", "w");
2079 mdump = popen ("mdump -q", "w");
2082 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
2083 mconv_encode_range (converter, mt, from, to);
2084 mconv_free_converter (converter);
2089 input_status (MInputContext *ic, MSymbol command)
2091 XFillRectangle (display, input_status_pixmap, gc_inv,
2092 0, 0, input_status_width, input_status_height);
2093 if (command == Minput_status_draw)
2097 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2098 Mface, face_input_status);
2099 if (ic->im->language != Mnil)
2100 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
2101 Mlanguage, ic->im->language);
2102 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
2103 &input_status_control, NULL, NULL, &rect);
2104 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
2105 input_status_width - rect.width - 2, - rect.y,
2106 ic->status, 0, mtext_len (ic->status),
2107 &input_status_control);
2109 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2110 XtSetValues (CurIMStatus, arg, 1);
2114 compare_input_method (const void *elt1, const void *elt2)
2116 const InputMethodInfo *im1 = elt1;
2117 const InputMethodInfo *im2 = elt2;
2118 MSymbol lang1, lang2;
2120 if (im1->language == Mnil)
2122 if (im1->language == im2->language)
2123 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2124 if (im1->language == Mt)
2126 if (im2->language == Mt)
2128 lang1 = msymbol_get (im1->language, Mlanguage);
2129 lang2 = msymbol_get (im2->language, Mlanguage);
2130 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2134 setup_input_methods (int with_xim, char *initial_input_method)
2136 MInputMethod *im = NULL;
2137 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2140 char *lang_name = NULL, *method_name = NULL;
2142 if (initial_input_method)
2144 char *p = strchr (initial_input_method, '-');
2146 lang_name = initial_input_method, method_name = p + 1, *p = '\0';
2148 method_name = initial_input_method;
2151 num_input_methods = plist ? mplist_length (plist) : 0;
2155 MInputXIMArgIM arg_xim;
2157 arg_xim.display = display;
2159 arg_xim.res_name = arg_xim.res_class = NULL;
2160 arg_xim.locale = NULL;
2161 arg_xim.modifier_list = NULL;
2162 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2164 num_input_methods++;
2166 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2169 input_method_table[i].available = 1;
2170 input_method_table[i].language = Mnil;
2171 input_method_table[i].name = im->name;
2172 input_method_table[i].im = im;
2178 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2180 MDatabase *mdb = mplist_value (pl);
2181 MSymbol *tag = mdatabase_tag (mdb);
2185 input_method_table[i].language = tag[1];
2186 input_method_table[i].name = tag[2];
2191 m17n_object_unref (plist);
2193 num_input_methods = i;
2194 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2195 compare_input_method);
2196 current_input_context = NULL;
2198 mplist_put (minput_driver->callback_list, Minput_status_start,
2199 (void *) input_status);
2200 mplist_put (minput_driver->callback_list, Minput_status_draw,
2201 (void *) input_status);
2202 mplist_put (minput_driver->callback_list, Minput_status_done,
2203 (void *) input_status);
2206 for (i = 0; i < num_input_methods; i++)
2207 if (strcmp (method_name, msymbol_name (input_method_table[i].name)) == 0
2209 ? strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0
2210 : input_method_table[i].language == Mt))
2212 current_input_method = i;
2219 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2223 if (num && *num > 0)
2227 for (i = 0; i < *num; i++)
2228 bytes += strlen (str[i]) + 1;
2229 msg = alloca (bytes);
2230 strcpy (msg, str[0]);
2231 for (i = 1; i < *num; i++)
2232 strcat (msg, " "), strcat (msg, str[i]);
2234 else if (cursor.from < nchars)
2236 int c = mtext_ref_char (mt, cursor.from);
2237 char *name = mchar_get_prop (c, Mname);
2241 msg = alloca (10 + strlen (name));
2242 sprintf (msg, "U+%04X %s", c, name);
2248 XtSetArg (arg[0], XtNlabel, msg);
2249 XtSetValues (MessageWidget, arg, 1);
2255 char *name1, *name2;
2256 XtCallbackProc proc;
2257 XtPointer client_data;
2262 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2264 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2266 MenuRec FileMenu[] =
2267 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2268 { 0, "Save", NULL, SaveProc, NULL, -1 },
2269 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2271 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2272 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2274 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2275 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2277 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2280 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2282 MenuRec *rec = (MenuRec *) client_data;
2285 XtSetArg (arg[0], XtNvalue, "");
2286 XtSetArg (arg[1], XtNlabel, rec->name1);
2287 XtSetValues (FileDialogWidget, arg, 2);
2288 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2289 XtSetArg (arg[0], XtNx, x + 20);
2290 XtSetArg (arg[1], XtNy, y + 10);
2291 XtSetValues (FileShellWidget, arg, 2);
2292 XtPopup (FileShellWidget, XtGrabExclusive);
2296 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2301 XtPopdown (FileShellWidget);
2302 if ((int) client_data == 1)
2304 XtSetArg (arg[0], XtNlabel, &label);
2305 XtGetValues (FileDialogWidget, arg, 1);
2306 if (strcmp (label, FileMenu[0].name1) == 0)
2310 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2311 fp = fopen (filename, "r");
2313 m17n_object_unref (mt);
2316 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2324 nchars = mtext_len (mt);
2326 update_cursor (0, 1);
2327 redraw (0, win_height, 1, 1);
2329 else if (strcmp (label, FileMenu[2].name1) == 0)
2330 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2332 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2335 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2336 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2337 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2338 (MENU).status = (STATUS))
2342 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2343 char *menu_name, MenuRec *menus, int num_menus, char *help)
2345 Widget button, menu;
2346 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2347 <LeaveWindow>: reset() MenuHelp()\n\
2348 <BtnDown>: reset() PopupMenu()\n\
2349 <BtnUp>: highlight()";
2355 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2356 for (i = 0; i < num_menus; i++)
2367 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2369 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2371 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2373 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2377 XtSetArg (arg[0], XtNsensitive, False);
2378 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2384 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2389 trans = alloca (strlen (fmt) + strlen (help));
2390 sprintf (trans, fmt, help);
2391 XtSetArg (arg[0], XtNmenuName, menu_name);
2392 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2393 XtSetArg (arg[2], XtNinternalWidth, 2);
2394 XtSetArg (arg[3], XtNhighlightThickness, 1);
2395 XtSetArg (arg[4], XtNleft, XawChainLeft);
2396 XtSetArg (arg[5], XtNright, XawChainLeft);
2399 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2400 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2405 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2406 int *len = alloca (sizeof (int) * num_menus);
2409 XFontSetExtents *fontset_extents;
2411 XtSetArg (arg[0], XtNfontSet, &font_set);
2412 XtGetValues (button, arg, 1);
2414 fontset_extents = XExtentsOfFontSet (font_set);
2415 height = fontset_extents->max_logical_extent.height;
2416 ascent = - fontset_extents->max_logical_extent.y;
2418 for (i = 0; i < num_menus; i++)
2421 len[i] = strlen (menus[i].name2);
2422 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2423 if (max_width < width[i])
2424 max_width = width[i];
2426 for (i = 0; i < num_menus; i++)
2429 Pixmap pixmap = XCreatePixmap (display,
2430 RootWindow (display, screen),
2431 max_width, height, 1);
2432 XFillRectangle (display, pixmap, mono_gc_inv,
2433 0, 0, max_width, height);
2434 XmbDrawString (display, pixmap, font_set, mono_gc,
2435 max_width - width[i], ascent,
2436 menus[i].name2, len[i]);
2437 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2438 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2439 XtSetValues (menus[i].w, arg, 2);
2447 XtActionsRec actions[] = {
2448 {"Expose", ExposeProc},
2449 {"Configure", ConfigureProc},
2451 {"ButtonPress", ButtonProc},
2452 {"ButtonRelease", ButtonReleaseProc},
2453 {"ButtonMotion", ButtonMoveProc},
2454 {"Button2Press", Button2Proc},
2455 {"MenuHelp", MenuHelpProc}
2459 /* Print the usage of this program (the name is PROG), and exit with
2463 help_exit (char *prog, int exit_code)
2471 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2472 printf ("Display FILE on a window and allow users to edit it.\n");
2473 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2474 printf ("The following OPTIONs are available.\n");
2475 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2476 "Use the specified fontset\n");
2477 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2478 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2479 "Input method activated initially.\n");
2480 printf (" %-13s %s", "--version", "print version number\n");
2481 printf (" %-13s %s", "-h, --help", "print this message\n");
2487 main (int argc, char **argv)
2489 Widget form, BodyWidget, w;
2490 char *fontset_name = NULL;
2492 char *initial_input_method = NULL;
2493 int col = 80, row = 32;
2494 /* Translation table for TextWidget. */
2495 String trans = "<Expose>: Expose()\n\
2496 <Configure>: Configure()\n\
2499 <Btn1Down>: ButtonPress()\n\
2500 <Btn1Up>: ButtonRelease()\n\
2501 <Btn1Motion>: ButtonMotion()\n\
2502 <Btn2Down>: Button2Press()";
2503 /* Translation table for the top form widget. */
2504 String trans2 = "<Key>: Key()\n\
2506 String pop_face_trans
2507 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2508 <LeaveWindow>: MenuHelp() reset()\n\
2509 <Btn1Down>: set()\n\
2510 <Btn1Up>: notify() unset()";
2511 String pop_lang_trans
2512 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2513 <LeaveWindow>: MenuHelp() reset()\n\
2514 <Btn1Down>: set()\n\
2515 <Btn1Up>: notify() unset()";
2516 int font_width, font_ascent, font_descent;
2519 char *filter = NULL;
2521 setlocale (LC_ALL, "");
2522 /* Create the top shell. */
2523 XtSetLanguageProc (NULL, NULL, NULL);
2524 ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
2525 NULL, sessionShellWidgetClass, NULL, 0);
2526 display = XtDisplay (ShellWidget);
2527 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2529 /* Parse the remaining command line arguments. */
2530 for (i = 1; i < argc; i++)
2532 if (! strcmp (argv[i], "--help")
2533 || ! strcmp (argv[i], "-h"))
2534 help_exit (argv[0], 0);
2535 else if (! strcmp (argv[i], "--version"))
2537 printf ("m17n-edit (m17n library) %s\n", VERSION);
2538 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2541 else if (! strcmp (argv[i], "--geometry"))
2544 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2545 help_exit (argv[0], 1);
2547 else if (! strcmp (argv[i], "-s"))
2550 fontsize = atoi (argv[i]);
2554 else if (! strcmp (argv[i], "--fontset"))
2557 fontset_name = strdup (argv[i]);
2559 else if (! strcmp (argv[i], "--im"))
2562 initial_input_method = strdup (argv[i]);
2564 else if (! strcmp (argv[i], "--with-xim"))
2568 else if (! strcmp (argv[i], "--filter"))
2573 else if (argv[i][0] != '-')
2575 filename = strdup (argv[i]);
2579 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2580 help_exit (argv[0], 1);
2584 filename = strdup ("/dev/null");
2586 mdatabase_dir = ".";
2587 /* Initialize the m17n library. */
2589 if (merror_code != MERROR_NONE)
2590 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2591 minput_driver = &minput_gui_driver;
2593 mt = read_file (filename);
2596 nchars = mtext_len (mt);
2598 Mword = msymbol ("word");
2601 MFace *face = mface ();
2603 mface_put_prop (face, Mforeground, msymbol ("blue"));
2604 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2605 mface_put_prop (face, Mvideomode, Mreverse);
2606 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2607 m17n_object_unref (face);
2610 /* This tells ExposeProc to initialize everything. */
2613 XA_TEXT = XInternAtom (display, "TEXT", False);
2614 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2615 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2616 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2617 if (Mcoding_compound_text == Mnil)
2618 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2621 MPlist *plist = mplist ();
2625 mplist_put (plist, msymbol ("widget"), ShellWidget);
2626 if (fontset_name || fontsize > 0)
2628 MFontset *fontset = mfontset (fontset_name);
2631 mface_put_prop (face, Mfontset, fontset);
2632 mface_put_prop (face, Msize, (void *) fontsize);
2633 m17n_object_unref (fontset);
2634 mplist_add (plist, Mface, face);
2635 m17n_object_unref (face);
2637 frame = mframe (plist);
2639 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2640 m17n_object_unref (plist);
2641 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2642 default_face_list = mplist ();
2643 mplist_add (default_face_list, Mt, face_default);
2644 face_default_fontset = mface ();
2645 mface_put_prop (face_default_fontset, Mfontset,
2646 mface_get_prop (face_default, Mfontset));
2648 font = (MFont *) mframe_get_prop (frame, Mfont);
2649 default_font_size = (int) mfont_get_prop (font, Msize);
2652 font_width = (int) mframe_get_prop (frame, Mfont_width);
2653 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2654 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2655 win_width = font_width * col;
2656 win_height = (font_ascent + font_descent) * row;
2662 prop.color_top = prop.color_left = msymbol ("magenta");
2663 prop.color_bottom = prop.color_right = msymbol ("red");
2664 prop.inner_hmargin = prop.inner_vmargin = 1;
2665 prop.outer_hmargin = prop.outer_vmargin = 2;
2667 face_box = mface ();
2668 mface_put_prop (face_box, Mbox, &prop);
2671 face_courier = mface ();
2672 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2673 face_helvetica = mface ();
2674 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2675 face_times = mface ();
2676 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2677 face_dv_ttyogesh = mface ();
2678 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2679 face_freesans = mface ();
2680 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2681 face_freeserif = mface ();
2682 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2683 face_freemono = mface ();
2684 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2686 face_xxx_large = mface ();
2687 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2689 MFont *latin_font = mframe_get_prop (frame, Mfont);
2690 MFont *dev_font = mfont ();
2691 MFont *thai_font = mfont ();
2692 MFont *tib_font = mfont ();
2694 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2695 MSymbol no_ctl = msymbol ("no-ctl");
2697 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2698 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2699 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2700 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2701 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2702 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2704 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2705 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2706 latin_font, Mnil, 0);
2707 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2708 dev_font, no_ctl, 0);
2709 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2710 thai_font, no_ctl, 0);
2711 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2712 tib_font, no_ctl, 0);
2713 face_no_ctl_fontset = mface ();
2714 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2715 m17n_object_unref (fontset);
2722 setup_input_methods (with_xim, initial_input_method);
2724 gc = DefaultGC (display, screen);
2726 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2727 XtSetArg (arg[1], XtNdefaultDistance, 2);
2728 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2730 XtSetArg (arg[0], XtNborderWidth, 0);
2731 XtSetArg (arg[1], XtNdefaultDistance, 2);
2732 XtSetArg (arg[2], XtNtop, XawChainTop);
2733 XtSetArg (arg[3], XtNbottom, XawChainTop);
2734 XtSetArg (arg[4], XtNleft, XawChainLeft);
2735 XtSetArg (arg[5], XtNright, XawChainRight);
2736 XtSetArg (arg[6], XtNresizable, True);
2737 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2738 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2739 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2740 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2741 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2742 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2743 XtSetArg (arg[7], XtNfromVert, LangWidget);
2744 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2745 XtSetArg (arg[2], XtNtop, XawChainBottom);
2746 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2747 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2749 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2750 HeadWidget, NULL, 0);
2751 XtSetArg (arg[0], XtNvalue, "");
2752 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2753 FileShellWidget, arg, 1);
2754 XawDialogAddButton (FileDialogWidget, "OK",
2755 FileDialogProc, (XtPointer) 0);
2756 XawDialogAddButton (FileDialogWidget, "CANCEL",
2757 FileDialogProc, (XtPointer) 1);
2759 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2760 (char *) check_bits,
2761 check_width, check_height);
2763 unsigned long valuemask = GCForeground;
2766 values.foreground = 1;
2767 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2768 values.foreground = 0;
2769 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2776 if (num_menus < num_input_methods + 2)
2777 num_menus = num_input_methods + 2;
2778 if (num_menus < num_faces + 1)
2779 num_menus = num_faces + 1;
2780 menus = alloca (sizeof (MenuRec) * num_menus);
2782 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2783 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2784 "File I/O, Serialization, Image, Quit");
2786 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2787 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2788 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2789 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2790 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2791 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2792 w = create_menu_button (ShellWidget, HeadWidget, w,
2793 "Cursor", "Cursor Menu",
2794 menus, 6, "Cursor Movement Mode, Cursor Shape");
2795 CursorMenus[0] = menus[0].w;
2796 CursorMenus[1] = menus[1].w;
2797 CursorMenus[2] = menus[3].w;
2798 CursorMenus[3] = menus[4].w;
2799 CursorMenus[4] = menus[5].w;
2801 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2802 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2803 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2804 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2805 menus, 3, "BIDI Processing Mode");
2806 for (i = 0; i < 3; i++)
2807 BidiMenus[i] = menus[i].w;
2809 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2810 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2811 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2812 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2814 menus, 3, "How to break lines");
2815 for (i = 0; i < 3; i++)
2816 LineBreakMenus[i] = menus[i].w;
2818 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2819 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2820 for (i = 0; i < num_input_methods; i++)
2822 InputMethodInfo *im = input_method_table + i;
2823 char *name1, *name2;
2825 if (im->language != Mnil && im->language != Mt)
2827 MSymbol sym = msymbol_get (im->language, Mlanguage);
2829 name1 = msymbol_name (im->language);
2831 name1 = msymbol_name (sym);
2832 name2 = msymbol_name (im->name);
2835 name1 = msymbol_name (im->name), name2 = NULL;
2837 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2839 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2840 "Input Method Menu", menus, i + 2,
2841 "Select input method");
2844 unsigned long valuemask = GCForeground;
2847 XtSetArg (arg[0], XtNbackground, &values.foreground);
2848 XtGetValues (w, arg, 1);
2849 gc_inv = XCreateGC (display, RootWindow (display, screen),
2850 valuemask, &values);
2853 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2854 for (i = 0; i < num_input_methods + 2; i++)
2855 InputMethodMenus[i] = menus[i].w;
2859 SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
2860 w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
2861 "Filter Menu", menus, 1,
2862 "Select filter to run");
2865 input_status_width = font_width * 8;
2866 input_status_height = (font_ascent + font_descent) * 2.4;
2867 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2869 input_status_height,
2870 DefaultDepth (display, screen));
2875 prop.color_top = prop.color_bottom
2876 = prop.color_left = prop.color_right = Mnil;
2877 prop.inner_hmargin = prop.inner_vmargin = 1;
2878 prop.outer_hmargin = prop.outer_vmargin = 0;
2879 face_input_status = mface_copy (face_default);
2880 mface_put_prop (face_input_status, Mbox, &prop);
2883 XFillRectangle (display, input_status_pixmap, gc_inv,
2884 0, 0, input_status_width, input_status_height);
2885 XtSetArg (arg[0], XtNfromHoriz, w);
2886 XtSetArg (arg[1], XtNleft, XawRubber);
2887 XtSetArg (arg[2], XtNright, XawChainRight);
2888 XtSetArg (arg[3], XtNborderWidth, 0);
2889 XtSetArg (arg[4], XtNlabel, " ");
2890 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2891 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2892 HeadWidget, arg, 6);
2893 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2894 XtSetArg (arg[1], XtNleft, XawChainRight);
2895 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2896 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2897 HeadWidget, arg, 5);
2899 XtSetArg (arg[0], XtNborderWidth, 0);
2900 XtSetArg (arg[1], XtNleft, XawChainLeft);
2901 XtSetArg (arg[2], XtNright, XawChainLeft);
2902 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2903 for (i = 0; i < num_faces;)
2905 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2906 char *label = label_menu + 5; /* "Xxxx" */
2908 for (j = i; j < num_faces && face_table[j].face; j++)
2909 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2911 w = create_menu_button (ShellWidget, FaceWidget, w,
2913 menus, j - i, "Push face property");
2917 XtSetArg (arg[0], XtNfromHoriz, w);
2918 XtSetArg (arg[1], XtNleft, XawChainLeft);
2919 XtSetArg (arg[2], XtNright, XawChainLeft);
2920 XtSetArg (arg[3], XtNhorizDistance, 10);
2921 XtSetArg (arg[4], XtNlabel, "Pop");
2922 XtSetArg (arg[5], XtNtranslations,
2923 XtParseTranslationTable (pop_face_trans));
2924 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2925 FaceWidget, arg, 6);
2926 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2928 XtSetArg (arg[0], XtNfromHoriz, w);
2929 XtSetArg (arg[1], XtNleft, XawChainLeft);
2930 XtSetArg (arg[2], XtNright, XawChainRight);
2931 XtSetArg (arg[3], XtNlabel, "");
2932 XtSetArg (arg[4], XtNborderWidth, 0);
2933 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2934 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2935 FaceWidget, arg, 6);
2937 XtSetArg (arg[0], XtNborderWidth, 0);
2938 XtSetArg (arg[1], XtNleft, XawChainLeft);
2939 XtSetArg (arg[2], XtNright, XawChainLeft);
2940 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2942 MPlist *plist[11], *pl;
2945 for (i = 0; i < 11; i++) plist[i] = NULL;
2947 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2948 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2950 MSymbol sym = msymbol_exist (langname);
2954 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2956 char *name = msymbol_name (fullname);
2959 if (c >= 'a' && c <= 'z')
2961 int idx = (c < 'u') ? (c - 'a') / 2 : 10;
2965 pl = plist[idx] = mplist ();
2966 for (; mplist_next (pl); pl = mplist_next (pl))
2967 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2969 mplist_push (pl, sym, fullname);
2974 for (i = 0; i < 11; i++)
2977 char *name = alloca (9);
2979 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2982 for (j = 0, pl = plist[i]; mplist_next (pl);
2983 j++, pl = mplist_next (pl))
2984 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2985 msymbol_name (mplist_key (pl)),
2986 LangProc, mplist_key (pl), -1);
2987 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2988 menus, j, "Push language property");
2990 for (i = 0; i < 11; i++)
2992 m17n_object_unref (plist[i]);
2994 XtSetArg (arg[0], XtNfromHoriz, w);
2995 XtSetArg (arg[1], XtNleft, XawChainLeft);
2996 XtSetArg (arg[2], XtNright, XawChainLeft);
2997 XtSetArg (arg[3], XtNhorizDistance, 10);
2998 XtSetArg (arg[4], XtNlabel, "Pop");
2999 XtSetArg (arg[5], XtNtranslations,
3000 XtParseTranslationTable (pop_lang_trans));
3001 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
3002 LangWidget, arg, 6);
3003 XtAddCallback (w, XtNcallback, LangProc, Mnil);
3005 XtSetArg (arg[0], XtNfromHoriz, w);
3006 XtSetArg (arg[1], XtNleft, XawChainLeft);
3007 XtSetArg (arg[2], XtNright, XawChainRight);
3008 XtSetArg (arg[3], XtNlabel, "");
3009 XtSetArg (arg[4], XtNborderWidth, 0);
3010 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
3011 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
3012 LangWidget, arg, 6);
3015 XtSetArg (arg[0], XtNheight, win_height);
3016 XtSetArg (arg[1], XtNwidth, 10);
3017 XtSetArg (arg[2], XtNleft, XawChainLeft);
3018 XtSetArg (arg[3], XtNright, XawChainLeft);
3019 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
3021 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
3022 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
3024 XtSetArg (arg[0], XtNheight, win_height);
3025 XtSetArg (arg[1], XtNwidth, win_width);
3026 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
3027 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
3028 XtSetArg (arg[4], XtNleft, XawChainLeft);
3029 XtSetArg (arg[5], XtNright, XawChainRight);
3030 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
3033 XtSetArg (arg[0], XtNborderWidth, 0);
3034 XtSetArg (arg[1], XtNleft, XawChainLeft);
3035 XtSetArg (arg[2], XtNright, XawChainRight);
3036 XtSetArg (arg[3], XtNresizable, True);
3037 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
3038 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
3039 TailWidget, arg, 5);
3041 memset (&control, 0, sizeof control);
3042 control.two_dimensional = 1;
3043 control.enable_bidi = 1;
3044 control.anti_alias = 1;
3045 control.min_line_ascent = font_ascent;
3046 control.min_line_descent = font_descent;
3047 control.max_line_width = win_width;
3048 control.with_cursor = 1;
3049 control.cursor_width = 2;
3050 control.partial_update = 1;
3051 control.ignore_formatting_char = 1;
3053 memset (&input_status_control, 0, sizeof input_status_control);
3054 input_status_control.enable_bidi = 1;
3056 XtAppAddActions (context, actions, XtNumber (actions));
3057 XtRealizeWidget (ShellWidget);
3059 win = XtWindow (TextWidget);
3061 XtAppMainLoop (context);
3063 if (current_input_context)
3064 minput_destroy_ic (current_input_context);
3065 for (i = 0; i < num_input_methods; i++)
3066 if (input_method_table[i].im)
3067 minput_close_im (input_method_table[i].im);
3068 m17n_object_unref (frame);
3069 m17n_object_unref (mt);
3070 m17n_object_unref (face_xxx_large);
3071 m17n_object_unref (face_box);
3072 m17n_object_unref (face_courier);
3073 m17n_object_unref (face_helvetica);
3074 m17n_object_unref (face_times);
3075 m17n_object_unref (face_dv_ttyogesh);
3076 m17n_object_unref (face_freesans);
3077 m17n_object_unref (face_freeserif);
3078 m17n_object_unref (face_freemono);
3079 m17n_object_unref (face_default_fontset);
3080 m17n_object_unref (face_no_ctl_fontset);
3081 m17n_object_unref (face_input_status);
3082 m17n_object_unref (face_default);
3083 m17n_object_unref (default_face_list);
3084 m17n_object_unref (selection);
3086 XFreeGC (display, mono_gc);
3087 XFreeGC (display, mono_gc_inv);
3088 XFreeGC (display, gc_inv);
3089 XtUninstallTranslations (form);
3090 XtUninstallTranslations (TextWidget);
3091 XtDestroyWidget (ShellWidget);
3092 XtDestroyApplicationContext (context);
3096 free (fontset_name);
3098 free (input_method_table);
3099 free (InputMethodMenus);
3104 #else /* not HAVE_X11_XAW_COMMAND_H */
3107 main (int argc, char **argv)
3110 "Building of this program failed (lack of some header files)\n");
3114 #endif /* not HAVE_X11_XAW_COMMAND_H */
3116 #endif /* not FOR_DOXYGEN */