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 medit edit multilingual text
26 @section medit-synopsis SYNOPSIS
28 medit [ XT-OPTION ...] [ OPTION ... ] FILE
30 @section medit-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 medit directly uses the GUI API, the API is mainly for
52 toolkit libraries or to implement XOM (X Outout Method), not for
53 direct use from application programs.
56 @japage medit ¿¸À¸ì¥Æ¥¥¹¥È¤ÎÊÔ½¸
58 @section medit-synopsis SYNOPSIS
60 medit [ XT-OPTION ...] [ OPTION ... ] FILE
62 @section medit-description DESCRIPTION
64 FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¡£
66 XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg).
68 °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ¤ë¡£
74 ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£
78 ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£
82 ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£medit ¤Ïľ
83 ÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥¥Ã¥È¥é¥¤¥Ö¥é¥ê¤ä
84 XOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é ¥à
85 ¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
92 #include <sys/types.h>
99 #include <X11/keysym.h>
100 #include <X11/Xatom.h>
101 #include <X11/Intrinsic.h>
102 #include <X11/StringDefs.h>
103 #include <X11/Shell.h>
104 #include <X11/Xaw/Command.h>
105 #include <X11/Xaw/Box.h>
106 #include <X11/Xaw/Form.h>
107 #include <X11/Xaw/Dialog.h>
108 #include <X11/Xaw/Scrollbar.h>
109 #include <X11/Xaw/Toggle.h>
110 #include <X11/Xaw/SimpleMenu.h>
111 #include <X11/Xaw/SmeBSB.h>
112 #include <X11/Xaw/SmeLine.h>
113 #include <X11/Xaw/MenuButton.h>
115 #include <m17n-gui.h>
116 #include <m17n-misc.h>
119 #define VERSION "1.1"
121 /* Global variables. */
126 /* For the X Window System. */
129 /* GCs for normal drawing, filling by background color, normal drawing
130 on bitmap (i.e. pixmap of depth 1), filling bitmap by background
132 GC gc, gc_inv, mono_gc, mono_gc_inv;
134 Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */
135 XtAppContext context;
136 int default_font_size;
140 Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM;
141 +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace
142 +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang
143 +- Body -- Sbar, Text
147 Widget ShellWidget, HeadWidget, TailWidget, MessageWidget;
148 Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus;
149 Widget SbarWidget, TextWidget;
150 Widget FileShellWidget, FileDialogWidget;
151 Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget;
152 Widget CurIMLang, CurIMStatus;
154 int win_width, win_height; /* Size of TextWidget. */
157 Pixmap input_status_pixmap;
158 int input_status_width, input_status_height;
160 /* Bitmap for "check" glyph. */
161 #define check_width 9
162 #define check_height 8
163 static unsigned char check_bits[] = {
164 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
165 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 };
168 /* For the m17n library. */
171 int nchars; /* == mtext_len (mt) */
172 MDrawControl control, input_status_control;
173 MTextProperty *selection;
176 MFace *face_xxx_large;
178 MFace *face_courier, *face_helvetica, *face_times;
179 MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
180 MFace *face_default_fontset, *face_no_ctl_fontset;
181 MFace *face_input_status;
183 MSymbol Mcoding_compound_text;
185 int logical_move = 1; /* If 0, move cursor visually. */
189 MSymbol language, name;
193 InputMethodInfo *input_method_table;
195 int num_input_methods;
196 int current_input_method = -1; /* i.e. none */
197 int auto_input_method = 0;
198 MInputContext *current_input_context;
205 { {"Menu Size", NULL},
206 {"xx-small", &mface_xx_small},
207 {"x-small", &mface_x_small},
208 {"small", &mface_small},
209 {"normalsize", &mface_normalsize},
210 {"large", &mface_large},
211 {"x-large", &mface_x_large},
212 {"xx-large", &mface_xx_large},
213 {"xxx-large", &face_xxx_large},
215 {"Menu Family", NULL},
216 {"courier", &face_courier},
217 {"helvetica", &face_helvetica},
218 {"times", &face_times},
219 {"dv-ttyogesh", &face_dv_ttyogesh},
220 {"freesans", &face_freesans},
221 {"freeserif", &face_freeserif},
222 {"freemono", &face_freemono},
224 {"Menu Style", NULL},
225 {"medium", &mface_medium},
226 {"bold", &mface_bold},
227 {"italic", &mface_italic},
229 {"Menu Color", NULL},
230 {"black", &mface_black},
231 {"white", &mface_white},
233 {"green", &mface_green},
234 {"blue", &mface_blue},
235 {"cyan", &mface_cyan},
236 {"yello", &mface_yellow},
237 {"magenta", &mface_magenta},
240 {"normal", &mface_normal_video},
241 {"reverse", &mface_reverse_video},
242 {"underline", &mface_underline},
244 {"No CTL", &face_no_ctl_fontset} };
247 int num_faces = sizeof (face_table) / sizeof (struct FaceRec);
249 /* Information about a physical line metric. */
252 int from; /* BOL position of the line. */
253 int to; /* BOL position of the next line. */
254 int y0, y1; /* Top and bottom Y position of the line. */
255 int ascent; /* Height of the top Y position. */
258 struct LineInfo top; /* Topmost line. */
259 struct LineInfo cur; /* Line containing cursor. */
260 struct LineInfo sel_start; /* Line containing selection start. */
261 struct LineInfo sel_end; /* Line containing selection end. */
263 MDrawGlyphInfo cursor; /* Information about the cursor glyph. */
265 /* X position to keep on vertical (up and down) cursor motion. */
266 int target_x_position;
268 /* Interface macros for m17n-lib drawing routines. */
270 /* Draw a text in the range $FROM to $TO of the M-text #MT at the
271 coordinate ($X, $Y) */
272 #define DRAW_TEXT(x, y, from, to) \
273 mdraw_text_with_control \
274 (frame, (MDrawWindow) win, \
275 control.orientation_reversed ? x + win_width : x, y, \
276 mt, from, to, &control)
278 /* Store the extents of a text in the range $FROM to $TO in the
279 structure $RECT (type MDrawMetric). */
280 #define TEXT_EXTENTS(from, to, rect) \
281 mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect))
283 /* Store the glyph information of a character at the position $POS in
284 the struct $INFO (type MDrawGlyphInfo) assuming that the text from
285 $FROM is written at the coordinate (0, 0). */
286 #define GLYPH_INFO(from, pos, info) \
287 mdraw_glyph_info (frame, mt, from, (pos), &control, &(info))
289 /* Set $X and $Y to the coordinate of character at position $POS
290 assuming that the text from $FROM is written at the coordinate (0,
292 #define COORDINATES_POSITION(from, pos, x, y) \
293 mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control)
295 /* Interface macros for X library. */
296 #define COPY_AREA(y0, y1, to) \
297 XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to))
299 #define CLEAR_AREA(x, y, w, h) \
300 XClearArea (display, win, (x), (y), (w), (h), False)
302 #define SELECTEDP() \
303 mtext_property_mtext (selection)
305 /* Format MSG by FMT and print the result to the stderr, and exit. */
306 #define FATAL_ERROR(fmt, arg) \
308 fprintf (stderr, fmt, arg); \
313 /* If POS is greater than zero, move POS back to the beginning of line
314 (BOL) position. If FORWARD is nonzero, move POS forward instead.
315 Return the new position. */
317 bol (int pos, int forward)
319 int limit = forward ? nchars : 0;
321 pos = mtext_character (mt, pos, limit, '\n');
322 return (pos < 0 ? limit : pos + 1);
325 /* Update the structure #TOP (struct LineInfo) to make $POS the first
326 character position of the screen. */
330 int from = bol (pos, 0);
333 GLYPH_INFO (from, pos, info);
334 top.from = info.line_from;
335 top.to = info.line_to;
337 top.y1 = info.metrics.height;
338 top.ascent = - info.metrics.y;
342 /* Update the scroll bar so that the text of the range $FROM to $TO
343 are shown on the window. */
345 update_scroll_bar (int from, int to)
347 float top = (float) from / nchars;
348 float shown = (float) (to - from) / nchars;
349 XtArgVal *l_top = (XtArgVal *) ⊤
350 XtArgVal *l_shown = (XtArgVal *) &shown;
352 XtSetArg (arg[0], XtNtopOfThumb, *l_top);
353 XtSetArg (arg[1], XtNshown, *l_shown);
354 XtSetValues (SbarWidget, arg, 2);
358 /* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If
359 $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR
360 is nonzero, update the scoll bar. */
362 redraw (int y0, int y1, int clear, int scroll_bar)
367 int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
368 struct LineInfo *line;
370 if (clear || control.anti_alias)
371 CLEAR_AREA (0, y0, win_width, y1 - y0);
373 /* Find a line closest to y0. It is a cursor line if the cursor is
374 Y0, otherwise the top line. */
379 /* If there exists a selected region, check it too. */
380 if (sel_y0 > line->y0 && y0 >= sel_y0)
385 info.metrics.height = line->y1 - y;
386 info.metrics.y = - line->ascent;
387 info.line_to = line->to;
388 while (from < nchars && y + info.metrics.height <= y0)
390 y += info.metrics.height;
392 GLYPH_INFO (from, from, info);
394 y0 = y - info.metrics.y;
396 while (to < nchars && y < y1)
398 GLYPH_INFO (to, to, info);
399 y += info.metrics.height;
405 DRAW_TEXT (0, y0, from, to);
410 GLYPH_INFO (to, to, info);
411 if (y + info.metrics.height >= win_height)
414 y += info.metrics.height;
416 update_scroll_bar (top.from, to);
421 /* Set the current input method spot to the correct position. */
423 set_input_method_spot ()
425 int x = cursor.x + (control.orientation_reversed ? win_width : 0);
426 int pos = cursor.from > 0 ? cursor.from - 1 : 0;
429 int size = 0, ratio = 0, i;
432 n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
434 for (i = n - 1; i >= 0; i--)
437 size = (int) mface_get_prop (faces[i], Msize);
439 ratio = (int) mface_get_prop (faces[i], Mratio);
442 size = default_font_size;
444 size = size * ratio / 100;
445 minput_set_spot (current_input_context, x, cur.y0 + cur.ascent,
446 cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size,
451 /* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area
454 redraw_cursor (int clear)
456 if (control.cursor_bidi)
458 /* We must update the whole line of the cursor. */
459 int beg = bol (cur.from, 0);
460 int end = bol (cur.to - 1, 1);
462 int y0 = cur.y0, y1 = cur.y1;
466 TEXT_EXTENTS (beg, cur.from, rect);
471 TEXT_EXTENTS (cur.to, end, rect);
474 redraw (y0, y1, clear, 0);
482 if (control.orientation_reversed)
483 x += win_width - cursor.logical_width;
484 CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
486 DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
491 /* Update the information about the location of cursor to the position
492 $POS. If $FULL is nonzero, update the information fully only from
493 the information about the top line. Otherwise, truct the current
494 information in the structure $CUR. */
496 update_cursor (int pos, int full)
502 /* CUR is inaccurate. We can trust only TOP. */
503 GLYPH_INFO (top.from, pos, cursor);
504 cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
506 else if (pos < cur.from)
508 int from = bol (pos, 0);
510 TEXT_EXTENTS (from, cur.from, rect);
511 GLYPH_INFO (from, pos, cursor);
512 cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
514 else if (pos < cur.to)
516 GLYPH_INFO (cur.from, pos, cursor);
520 GLYPH_INFO (cur.from, pos, cursor);
521 cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
524 cur.from = cursor.line_from;
525 cur.to = cursor.line_to;
526 cur.y1 = cur.y0 + cursor.metrics.height;
527 cur.ascent = - cursor.metrics.y;
531 /* Update the information about the selected region. */
541 from = mtext_property_start (selection);
542 to = mtext_property_end (selection);
546 int pos = bol (from, 0);
548 TEXT_EXTENTS (pos, top.from, rect);
549 sel_start.y0 = top.y0 - rect.height;
550 sel_start.ascent = - rect.y;
551 GLYPH_INFO (pos, from, info);
552 if (pos < info.line_from)
553 sel_start.y0 += - rect.y + info.y + info.metrics.y;
557 GLYPH_INFO (top.from, from, info);
558 sel_start.y0 = top.ascent + info.y + info.metrics.y;
560 sel_start.ascent = -info.metrics.y;
561 sel_start.y1 = sel_start.y0 + info.metrics.height;
562 sel_start.from = info.line_from;
563 sel_start.to = info.line_to;
565 if (to <= sel_start.to)
571 GLYPH_INFO (sel_start.from, to, info);
572 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
573 sel_end.y1 = sel_end.y0 + info.metrics.height;
574 sel_end.ascent = - info.metrics.y;
575 sel_end.from = info.line_from;
576 sel_end.to = info.line_to;
581 /* Select the text in the region from $FROM to $TO. */
583 select_region (int from, int to)
588 pos = from, from = to, to = pos;
589 mtext_push_property (mt, from, to, selection);
594 /* Setup the window to display the character of $POS at the top left
600 /* Top and bottom Y positions to redraw. */
603 if (pos + 1000 < top.from)
604 y0 = 0, y1 = win_height;
605 else if (pos < top.from)
608 TEXT_EXTENTS (pos, top.from, rect);
609 if (rect.height >= win_height * 0.9)
614 COPY_AREA (0, win_height - y1, y1);
617 else if (pos < top.to)
619 /* No need of redrawing. */
622 else if (pos < top.from + 1000)
624 TEXT_EXTENTS (top.from, pos, rect);
625 if (rect.height >= win_height * 0.9)
629 y0 = win_height - rect.height;
630 COPY_AREA (rect.height, win_height, 0);
635 y0 = 0, y1 = win_height;
641 update_cursor (pos, 1);
643 update_cursor (cursor.from, 1);
645 redraw (y0, y1, 1, 1);
649 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
652 /* Select an input method accoding to $IDX. If $IDX is negative, turn
653 off the current input method, otherwide turn on the input method
654 input_method_table[$IDX]. */
656 select_input_method (idx)
658 if (idx == current_input_method)
660 if (current_input_context)
662 minput_destroy_ic (current_input_context);
663 current_input_context = NULL;
664 current_input_method = -1;
668 InputMethodInfo *im = input_method_table + idx;
670 if (im->language == Mnil)
672 MInputXIMArgIC arg_xic;
673 Window win = XtWindow (TextWidget);
675 arg_xic.input_style = 0;
676 arg_xic.client_win = arg_xic.focus_win = win;
677 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
678 current_input_context = minput_create_ic (im->im, &arg_xic);
682 MInputGUIArgIC arg_ic;
684 arg_ic.frame = frame;
685 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
686 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
687 current_input_context = minput_create_ic (im->im, &arg_ic);
690 if (current_input_context)
692 set_input_method_spot ();
693 current_input_method = idx;
696 if (current_input_method >= 0)
699 XtSetArg (arg[0], XtNlabel, &label);
700 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
701 XtSetArg (arg[0], XtNlabel, label);
704 XtSetArg (arg[0], XtNlabel, "");
705 XtSetValues (CurIMLang, arg, 1);
708 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
711 /* Display cursor according to the current information of #CUR.
712 $CLIENT_DATA is ignore. Most callback functions add this function
713 as a background processing procedure the current application (by
714 XtAppAddWorkProc) via the function hide_cursor. */
716 show_cursor (XtPointer client_data)
718 MFaceHLineProp *hline;
724 update_cursor (cursor.from, 1);
726 while (cur.y1 > win_height)
729 update_cursor (cursor.from, 1);
732 control.cursor_pos = cursor.from;
735 control.with_cursor = 1;
738 if (current_input_context)
739 set_input_method_spot ();
743 int pos = (SELECTEDP () ? mtext_property_start (selection)
744 : cursor.from > 0 ? cursor.from - 1
746 MFace *face = mface ();
747 MTextProperty *props[256];
748 int n = mtext_get_properties (mt, pos, Mface, props, 256);
750 char buf[256], *p = buf;
756 int size = (int) mfont_get_prop (cursor.font, Msize);
757 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
758 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
759 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
760 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
762 sprintf (p, "%dpt", size / 10), p += strlen (p);
764 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
766 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
768 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
770 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
774 mface_merge (face, face_default);
775 for (i = 0; i < n; i++)
776 if (props[i] != selection)
777 mface_merge (face, (MFace *) mtext_property_value (props[i]));
778 sym = (MSymbol) mface_get_prop (face, Mforeground);
780 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
781 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
782 strcat (p, ",rev"), p += strlen (p);
783 hline = mface_get_prop (face, Mhline);
784 if (hline && hline->width > 0)
785 strcat (p, ",ul"), p += strlen (p);
786 box = mface_get_prop (face, Mbox);
787 if (box && box->width > 0)
788 strcat (p, ",box"), p += strlen (p);
789 m17n_object_unref (face);
791 XtSetArg (arg[0], XtNborderWidth, 1);
792 XtSetArg (arg[1], XtNlabel, buf);
793 XtSetValues (CurFaceWidget, arg, 2);
796 if (control.cursor_pos < nchars)
800 if (control.cursor_pos > 0
801 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
802 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
804 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. */
909 from = cursor.from, to = from + n;
912 if (cursor.from == cur.from)
914 /* We are at the beginning of line. */
915 int pos = cursor.prev_from;
917 if (cursor.from == top.from)
919 /* We are at the beginning of screen. We must scroll
921 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
922 reseat (info.line_from);
924 update_cursor (pos, 1);
930 from = cursor.from - 1;
935 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
936 old_y1 = cur.y0 + rect.height;
938 /* Now delete a character. */
939 mtext_del (mt, from, to);
941 if (from >= top.from && from < top.to)
942 update_top (top.from);
943 update_cursor (from, 1);
945 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
946 new_y1 = cur.y0 + rect.height;
948 update_region (cur.y0, old_y1, new_y1);
952 /* Insert M-text $NEWTEXT at the current cursor position. */
954 insert_chars (MText *newtext)
956 int n = mtext_len (newtext);
958 int y0, old_y1, new_y1;
962 int n = (mtext_property_end (selection)
963 - mtext_property_start (selection));
964 mtext_detach_property (selection);
969 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
970 old_y1 = y0 + rect.height;
972 /* Now insert chars. */
973 mtext_ins (mt, cursor.from, newtext);
975 if (cur.from == top.from)
976 update_top (top.from);
977 update_cursor (cursor.from + n, 1);
979 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
980 new_y1 = cur.y0 + rect.height;
982 update_region (y0, old_y1, new_y1);
987 /* Convert the currently selected text to UTF8-STRING or
988 COMPOUND-TEXT. It is called when someone requests the current
989 value of the selection. */
991 covert_selection (Widget w, Atom *selection_atom,
992 Atom *target, Atom *return_type,
993 XtPointer *value, unsigned long *length, int *format)
995 unsigned char *buf = (unsigned char *) XtMalloc (4096);
996 MText *this_mt = mtext ();
997 int from = mtext_property_start (selection);
998 int to = mtext_property_end (selection);
1002 mtext_copy (this_mt, 0, mt, from, to);
1003 if (*target == XA_TEXT)
1005 #ifdef X_HAVE_UTF8_STRING
1006 coding = Mcoding_utf_8;
1007 *return_type = XA_UTF8_STRING;
1009 coding = Mcoding_compound_text;
1010 *return_type = XA_COMPOUND_TEXT;
1013 else if (*target == XA_UTF8_STRING)
1015 coding = Mcoding_utf_8;
1016 *return_type = XA_UTF8_STRING;
1018 else if (*target == XA_STRING)
1023 for (i = 0; i < len; i++)
1024 if (mtext_ref_char (this_mt, i) >= 0x100)
1025 /* Can't encode in XA_STRING */
1027 coding = Mcoding_iso_8859_1;
1028 *return_type = XA_STRING;
1030 else if (*target == XA_COMPOUND_TEXT)
1032 coding = Mcoding_compound_text;
1033 *return_type = XA_COMPOUND_TEXT;
1038 len = mconv_encode_buffer (coding, this_mt, buf, 4096);
1039 m17n_object_unref (this_mt);
1043 *value = (XtPointer) buf;
1049 /* Unselect the text. It is called when we loose the selection. */
1051 lose_selection (Widget w, Atom *selection_atom)
1055 mtext_detach_property (selection);
1056 redraw (sel_start.y0, sel_end.y1, 1, 0);
1061 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1062 XtPointer value, unsigned long *length, int *format)
1067 if (*type == XT_CONVERT_FAIL || ! value)
1069 if (*type == XA_STRING)
1071 else if (*type == XA_COMPOUND_TEXT)
1072 coding = msymbol ("compound-text");
1073 #ifdef X_HAVE_UTF8_STRING
1074 else if (*type == XA_UTF8_STRING)
1075 coding = msymbol ("utf-8");
1080 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1081 if (! this_mt && *type != XA_UTF8_STRING)
1083 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1090 insert_chars (this_mt);
1091 m17n_object_unref (this_mt);
1100 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1102 XExposeEvent *expose = (XExposeEvent *) event;
1106 Dimension width_max, width;
1108 XtSetArg (arg[0], XtNwidth, &width);
1109 XtGetValues (XtParent (w), arg, 1);
1111 XtGetValues (HeadWidget, arg, 1);
1112 if (width_max < width)
1114 XtGetValues (FaceWidget, arg, 1);
1115 if (width_max < width)
1117 XtGetValues (LangWidget, arg, 1);
1118 if (width_max < width)
1120 XtSetArg (arg[0], XtNwidth, width_max);
1121 XtSetValues (HeadWidget, arg, 1);
1122 XtSetValues (FaceWidget, arg, 1);
1123 XtSetValues (LangWidget, arg, 1);
1124 XtSetValues (XtParent (w), arg, 1);
1125 XtSetValues (TailWidget, arg, 1);
1128 update_cursor (0, 1);
1129 redraw (0, win_height, 0, 1);
1130 if (current_input_method >= 0)
1132 int idx = current_input_method;
1134 current_input_method = -1;
1135 input_method_table[idx].im =
1136 minput_open_im (input_method_table[idx].language,
1137 input_method_table[idx].name, NULL);
1138 if (input_method_table[idx].im)
1139 select_input_method (idx);
1141 input_method_table[idx].available = -1;
1147 redraw (expose->y, expose->y + expose->height, 0, 0);
1148 if (current_input_context
1149 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1150 set_input_method_spot ();
1155 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1157 XConfigureEvent *configure = (XConfigureEvent *) event;
1160 control.max_line_width = win_width = configure->width;
1161 win_height = configure->height;
1162 mdraw_clear_cache (mt);
1164 update_cursor (0, 1);
1165 redraw (0, win_height, 1, 1);
1166 if (current_input_context)
1167 set_input_method_spot ();
1171 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1174 int x = event->xbutton.x;
1175 int y = event->xbutton.y - top.ascent;
1177 if (control.orientation_reversed)
1179 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1182 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1183 mtext_detach_property (selection);
1184 redraw (sel_start.y0, sel_end.y1, 1, 0);
1187 update_cursor (pos, 0);
1192 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1197 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1198 covert_selection, lose_selection, NULL);
1199 update_cursor (mtext_property_start (selection), 0);
1204 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1208 /* We don't have a local selection. */
1209 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1214 int from = mtext_property_start (selection);
1215 int to = mtext_property_end (selection);
1218 int x = event->xbutton.x;
1219 int y = event->xbutton.y - top.ascent;
1221 if (control.orientation_reversed)
1223 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1225 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1226 mtext_detach_property (selection);
1228 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1229 update_cursor (pos, 0);
1230 insert_chars (this_mt);
1231 m17n_object_unref (this_mt);
1236 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1239 int x = event->xbutton.x;
1240 int y = event->xbutton.y;
1242 if (control.orientation_reversed)
1245 pos = top.from, y -= top.ascent;
1247 pos = cur.from, y -= cur.y0 + cur.ascent;
1248 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1250 if (pos == cursor.from)
1256 /* Selection range changed. */
1257 int from = mtext_property_start (selection);
1258 int to = mtext_property_end (selection);
1259 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1260 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1262 if (cursor.from == from)
1264 /* Starting position changed. */
1267 /* Enlarged. We can simply overdraw. */
1268 select_region (pos, to);
1269 redraw (sel_start.y0, start_y1, 0, 0);
1273 /* Shrunken. Previous selection face must be cleared. */
1274 select_region (pos, to);
1275 redraw (start_y0, sel_start.y1, 1, 0);
1279 /* Shrunken to zero. */
1280 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1281 mtext_detach_property (selection);
1282 redraw (start_y0, end_y1, 1, 0);
1286 /* Full update is necessary. */
1287 select_region (to, pos);
1288 redraw (start_y0, sel_end.y1, 1, 0);
1293 /* Ending position changed. */
1296 /* Full update is necessary. */
1297 select_region (pos, from);
1298 redraw (sel_start.y0, end_y1, 1, 0);
1300 else if (pos == from)
1302 /* Shrunken to zero. */
1303 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1304 mtext_detach_property (selection);
1305 redraw (start_y0, end_y1, 1, 0);
1309 /* Shrunken. Previous selection face must be cleared. */
1310 select_region (from, pos);
1311 redraw (sel_end.y0, end_y1, 1, 0);
1315 /* Enlarged. We can simply overdraw. */
1316 select_region (from, pos);
1317 redraw (end_y0, sel_end.y1, 0, 0);
1323 /* Newly selected. */
1324 select_region (pos, cursor.from);
1325 redraw (sel_start.y0, sel_end.y1, 0, 0);
1327 update_cursor (pos, 1);
1331 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1334 MDrawGlyphInfo info;
1336 int cursor_pos = cursor.from;
1338 if (((int) position) < 0)
1344 height = top.y1 - top.y0;
1347 pos = bol (from - 1, 0);
1348 GLYPH_INFO (pos, from - 1, info);
1349 if (height + info.metrics.height > win_height)
1351 height += info.metrics.height;
1352 from = info.line_from;
1354 if (cursor_pos >= top.to)
1356 cursor_pos = top.from;
1358 while (cursor_pos < nchars)
1360 GLYPH_INFO (pos, pos, info);
1361 if (height + info.metrics.height > win_height)
1363 height += info.metrics.height;
1369 else if (cur.to < nchars)
1371 /* Scroll up, but leave at least one line. */
1374 while (from < nchars)
1376 GLYPH_INFO (from, from, info);
1377 if (height + info.metrics.height > win_height
1378 || info.line_to >= nchars)
1380 height += info.metrics.height;
1381 from = info.line_to;
1384 from = info.line_from;
1385 if (cursor_pos < from)
1389 /* Scroll up to make the cursor line top. */
1393 update_cursor (cursor_pos, 1);
1397 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1399 float persent = *(float *) persent_ptr;
1400 int pos1, pos2 = nchars * persent;
1401 MDrawGlyphInfo info;
1404 pos1 = bol (pos2, 0);
1405 GLYPH_INFO (pos1, pos2, info);
1406 pos1 = info.line_from;
1408 update_cursor (pos1, 1);
1413 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1415 XKeyEvent *key_event = (XKeyEvent *) event;
1417 KeySym keysym = NoSymbol;
1419 /* If set to 1, do not update target_x_position. */
1420 int keep_target_x_position = 0;
1423 if (current_input_context
1424 && minput_filter (current_input_context, Mnil, event))
1426 if (event->type == KeyRelease)
1431 produced = mtext ();
1432 ret = minput_lookup (current_input_context, Mnil, event, produced);
1433 if (mtext_len (produced) > 0)
1434 insert_chars (produced);
1436 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1437 m17n_object_unref (produced);
1447 n = (mtext_property_end (selection)
1448 - mtext_property_start (selection));
1449 mtext_detach_property (selection);
1451 else if (cursor.from < nchars)
1453 /* Delete the following grapheme cluster. */
1454 n = cursor.to - cursor.from;
1467 /* Delete selected region. */
1468 n = (mtext_property_end (selection)
1469 - mtext_property_start (selection));
1470 mtext_detach_property (selection);
1472 else if (cursor.from > 0)
1474 /* Delete the preceding character. */
1485 mtext_detach_property (selection);
1486 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1490 if (cursor.prev_from >= 0)
1491 update_cursor (cursor.prev_from, 0);
1495 if (cursor.left_from >= 0)
1496 update_cursor (cursor.left_from, 0);
1503 mtext_detach_property (selection);
1504 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1508 if (cursor.next_to >= 0)
1509 update_cursor (cursor.to, 0);
1513 if (cursor.right_from >= 0)
1514 update_cursor (cursor.right_from, 0);
1521 mtext_detach_property (selection);
1522 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1524 if (cur.to <= nchars)
1526 MDrawGlyphInfo info;
1529 GLYPH_INFO (cur.from, cur.to, info);
1530 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1531 target_x_position, info.y);
1532 keep_target_x_position = 1;
1533 update_cursor (pos, 0);
1540 mtext_detach_property (selection);
1541 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1547 int pos = bol (cur.from - 1, 0);
1549 TEXT_EXTENTS (pos, cur.from - 1, rect);
1550 y = rect.height + rect.y - 1;
1551 pos = COORDINATES_POSITION (pos, nchars,
1552 target_x_position, y);
1553 keep_target_x_position = 1;
1554 update_cursor (pos, 0);
1561 mtext_detach_property (selection);
1562 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1564 if (top.from < nchars)
1565 ScrollProc (w, NULL, (XtPointer) 1);
1571 mtext_detach_property (selection);
1572 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1575 ScrollProc (w, NULL, (XtPointer) -1);
1581 if (buf[0] == 17) /* C-q */
1583 XtAppSetExitFlag (context);
1586 else if (buf[0] == 12) /* C-l */
1588 redraw (0, win_height, 1, 1);
1593 MText *temp = mtext ();
1595 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1596 if (current_input_context)
1597 mtext_put_prop (temp, 0, 1, Mlanguage,
1598 current_input_context->im->language);
1599 insert_chars (temp);
1600 m17n_object_unref (temp);
1605 if (! keep_target_x_position)
1606 target_x_position = cursor.x;
1610 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1612 char *name = (char *) client_data;
1614 int from = -1, to = 0;
1619 filename = strdup (name);
1622 fp = fopen (filename, "w");
1625 fprintf (stderr, "Open for write fail: %s", filename);
1631 from = mtext_property_start (selection);
1632 to = mtext_property_end (selection);
1633 mtext_detach_property (selection);
1636 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1639 select_region (from, to);
1643 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1649 mtext_detach_property (selection);
1650 serialized = (int) client_data;
1652 new = mtext_deserialize (mt);
1655 MPlist *plist = mplist ();
1657 mplist_push (plist, Mt, Mface);
1658 mplist_push (plist, Mt, Mlanguage);
1659 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1660 m17n_object_unref (plist);
1664 m17n_object_unref (mt);
1666 serialized = ! serialized;
1667 nchars = mtext_len (mt);
1670 update_cursor (0, 1);
1671 redraw (0, win_height, 1, 1);
1675 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1677 XtAppSetExitFlag (context);
1683 FILE *fp = fopen (filename, "r");
1686 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1687 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1690 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1695 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1697 int data = (int) client_data;
1702 control.enable_bidi = 0;
1703 control.orientation_reversed = 0;
1707 control.enable_bidi = 1;
1708 control.orientation_reversed = data == 2;
1710 for (i = 0; i < 3; i++)
1713 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1715 XtSetArg (arg[0], XtNleftBitmap, None);
1716 XtSetValues (BidiMenus[i], arg, 1);
1719 update_cursor (cursor.from, 1);
1720 redraw (0, win_height, 1, 0);
1723 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1726 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1728 int data = (int) client_data;
1732 control.max_line_width = 0;
1735 control.max_line_width = win_width;
1736 control.line_break = (data == 1 ? NULL : line_break);
1738 for (i = 0; i < 3; i++)
1741 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1743 XtSetArg (arg[0], XtNleftBitmap, None);
1744 XtSetValues (LineBreakMenus[i], arg, 1);
1747 update_cursor (cursor.from, 1);
1748 redraw (0, win_height, 1, 0);
1752 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1754 int data = (int) client_data;
1768 control.cursor_bidi = 0, control.cursor_width = -1;
1772 control.cursor_bidi = 0, control.cursor_width = 2;
1776 control.cursor_bidi = 1;
1781 for (i = from; i < to; i++)
1784 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1786 XtSetArg (arg[0], XtNleftBitmap, None);
1787 XtSetValues (CursorMenus[i], arg, 1);
1790 update_cursor (cursor.from, 0);
1791 redraw (0, win_height, 1, 0);
1795 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1797 int idx = (int) client_data;
1799 if (idx == -2 ? current_input_method < 0
1800 : idx == -1 ? auto_input_method
1801 : idx == current_input_method)
1804 XtSetArg (arg[0], XtNleftBitmap, None);
1805 if (auto_input_method)
1807 XtSetValues (InputMethodMenus[1], arg, 1);
1808 auto_input_method = 0;
1810 else if (current_input_method < 0)
1811 XtSetValues (InputMethodMenus[0], arg, 1);
1813 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1817 auto_input_method = 1;
1820 else if (input_method_table[idx].available >= 0)
1822 if (! input_method_table[idx].im)
1824 input_method_table[idx].im =
1825 minput_open_im (input_method_table[idx].language,
1826 input_method_table[idx].name, NULL);
1827 if (! input_method_table[idx].im)
1828 input_method_table[idx].available = -1;
1830 if (input_method_table[idx].im)
1831 select_input_method (idx);
1833 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1834 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1837 MPlist *default_face_list;
1840 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1842 int idx = (int) client_data;
1852 MFace *face = mframe_get_prop (frame, Mface);
1854 for (plist = default_face_list; mplist_key (plist) != Mnil;
1855 plist = mplist_next (plist))
1856 mface_merge (face, mplist_value (plist));
1857 mplist_add (plist, Mt, *face_table[idx].face);
1858 mface_merge (face, *face_table[idx].face);
1860 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1862 MFace *face = mframe_get_prop (frame, Mface);
1864 for (plist = default_face_list;
1865 mplist_key (mplist_next (plist)) != Mnil;
1866 plist = mplist_next (plist))
1867 mface_merge (face, mplist_value (plist));
1871 update_cursor (0, 1);
1872 redraw (0, win_height, 1, 1);
1877 XtAppAddWorkProc (context, show_cursor, NULL);
1878 from = mtext_property_start (selection);
1879 to = mtext_property_end (selection);
1880 old_y1 = sel_end.y1;
1882 mtext_detach_property (selection);
1885 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1886 MTEXTPROP_REAR_STICKY);
1887 mtext_push_property (mt, from, to, prop);
1888 m17n_object_unref (prop);
1891 mtext_pop_prop (mt, from, to, Mface);
1893 update_top (top.from);
1894 update_cursor (cursor.from, 1);
1895 select_region (from, to);
1896 update_region (sel_start.y0, old_y1, sel_end.y1);
1897 if (cur.y1 > win_height)
1899 while (cur.y1 > win_height)
1902 update_cursor (cursor.from, 1);
1908 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1910 MSymbol sym = (MSymbol) client_data;
1917 XtAppAddWorkProc (context, show_cursor, NULL);
1918 from = mtext_property_start (selection);
1919 to = mtext_property_end (selection);
1920 old_y1 = sel_end.y1;
1922 mtext_detach_property (selection);
1924 mtext_put_prop (mt, from, to, Mlanguage, sym);
1926 mtext_pop_prop (mt, from, to, Mlanguage);
1929 update_top (top.from);
1930 update_cursor (cursor.from, 1);
1931 select_region (from, to);
1932 update_region (sel_start.y0, old_y1, sel_end.y1);
1933 if (cur.y1 > win_height)
1935 while (cur.y1 > win_height)
1938 update_cursor (cursor.from, 1);
1944 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1946 int narrowed = (int) client_data;
1949 MConverter *converter;
1955 from = mtext_property_start (selection);
1956 to = mtext_property_end (selection);
1965 mdump = popen ("mdump -q -p a4", "w");
1967 mdump = popen ("mdump -q", "w");
1970 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1971 mconv_encode_range (converter, mt, from, to);
1972 mconv_free_converter (converter);
1977 input_status (MInputContext *ic, MSymbol command)
1979 XFillRectangle (display, input_status_pixmap, gc_inv,
1980 0, 0, input_status_width, input_status_height);
1981 if (command == Minput_status_draw)
1985 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1986 Mface, face_input_status);
1987 if (ic->im->language != Mnil)
1988 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1989 Mlanguage, ic->im->language);
1990 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1991 &input_status_control, NULL, NULL, &rect);
1992 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1993 input_status_width - rect.width - 2, - rect.y,
1994 ic->status, 0, mtext_len (ic->status),
1995 &input_status_control);
1997 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1998 XtSetValues (CurIMStatus, arg, 1);
2002 compare_input_method (const void *elt1, const void *elt2)
2004 const InputMethodInfo *im1 = elt1;
2005 const InputMethodInfo *im2 = elt2;
2006 MSymbol lang1, lang2;
2008 if (im1->language == Mnil)
2010 if (im1->language == im2->language)
2011 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2012 if (im1->language == Mt)
2014 if (im2->language == Mt)
2016 lang1 = msymbol_get (im1->language, Mlanguage);
2017 lang2 = msymbol_get (im2->language, Mlanguage);
2018 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2022 setup_input_methods (int with_xim, char *initial_input_method)
2024 MInputMethod *im = NULL;
2025 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2028 char *lang_name = NULL, *method_name = NULL;
2030 if (initial_input_method)
2032 char *p = strchr (initial_input_method, '-');
2034 lang_name = initial_input_method, method_name = p + 1, *p = '\0';
2036 method_name = initial_input_method;
2039 num_input_methods = mplist_length (plist);
2043 MInputXIMArgIM arg_xim;
2045 arg_xim.display = display;
2047 arg_xim.res_name = arg_xim.res_class = NULL;
2048 arg_xim.locale = NULL;
2049 arg_xim.modifier_list = NULL;
2050 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2052 num_input_methods++;
2054 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2057 input_method_table[i].available = 1;
2058 input_method_table[i].language = Mnil;
2059 input_method_table[i].name = im->name;
2060 input_method_table[i].im = im;
2064 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2066 MDatabase *mdb = mplist_value (pl);
2067 MSymbol *tag = mdatabase_tag (mdb);
2071 input_method_table[i].language = tag[1];
2072 input_method_table[i].name = tag[2];
2077 m17n_object_unref (plist);
2078 num_input_methods = i;
2079 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2080 compare_input_method);
2081 current_input_context = NULL;
2083 mplist_put (minput_driver->callback_list, Minput_status_start,
2084 (void *) input_status);
2085 mplist_put (minput_driver->callback_list, Minput_status_draw,
2086 (void *) input_status);
2087 mplist_put (minput_driver->callback_list, Minput_status_done,
2088 (void *) input_status);
2091 for (i = 0; i < num_input_methods; i++)
2092 if (strcmp (method_name, msymbol_name (input_method_table[i].name)) == 0
2094 ? strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0
2095 : input_method_table[i].language == Mt))
2097 current_input_method = i;
2104 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2108 if (num && *num > 0)
2112 for (i = 0; i < *num; i++)
2113 bytes += strlen (str[i]) + 1;
2114 msg = alloca (bytes);
2115 strcpy (msg, str[0]);
2116 for (i = 1; i < *num; i++)
2117 strcat (msg, " "), strcat (msg, str[i]);
2119 else if (cursor.from < nchars)
2121 int c = mtext_ref_char (mt, cursor.from);
2122 char *name = mchar_get_prop (c, Mname);
2126 msg = alloca (10 + strlen (name));
2127 sprintf (msg, "U+%04X %s", c, name);
2133 XtSetArg (arg[0], XtNlabel, msg);
2134 XtSetValues (MessageWidget, arg, 1);
2140 char *name1, *name2;
2141 XtCallbackProc proc;
2142 XtPointer client_data;
2147 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2149 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2151 MenuRec FileMenu[] =
2152 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2153 { 0, "Save", NULL, SaveProc, NULL, -1 },
2154 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2156 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2157 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2159 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2160 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2162 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2165 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2167 MenuRec *rec = (MenuRec *) client_data;
2170 XtSetArg (arg[0], XtNvalue, "");
2171 XtSetArg (arg[1], XtNlabel, rec->name1);
2172 XtSetValues (FileDialogWidget, arg, 2);
2173 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2174 XtSetArg (arg[0], XtNx, x + 20);
2175 XtSetArg (arg[1], XtNy, y + 10);
2176 XtSetValues (FileShellWidget, arg, 2);
2177 XtPopup (FileShellWidget, XtGrabExclusive);
2181 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2186 XtPopdown (FileShellWidget);
2187 if ((int) client_data == 1)
2189 XtSetArg (arg[0], XtNlabel, &label);
2190 XtGetValues (FileDialogWidget, arg, 1);
2191 if (strcmp (label, FileMenu[0].name1) == 0)
2195 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2196 fp = fopen (filename, "r");
2198 m17n_object_unref (mt);
2201 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2209 nchars = mtext_len (mt);
2211 update_cursor (0, 1);
2212 redraw (0, win_height, 1, 1);
2214 else if (strcmp (label, FileMenu[2].name1) == 0)
2215 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2217 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2220 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2221 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2222 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2223 (MENU).status = (STATUS))
2227 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2228 char *menu_name, MenuRec *menus, int num_menus, char *help)
2230 Widget button, menu;
2231 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2232 <LeaveWindow>: reset() MenuHelp()\n\
2233 <BtnDown>: reset() PopupMenu()\n\
2234 <BtnUp>: highlight()";
2240 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2241 for (i = 0; i < num_menus; i++)
2252 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2254 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2256 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2258 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2262 XtSetArg (arg[0], XtNsensitive, False);
2263 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2269 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2274 trans = alloca (strlen (fmt) + strlen (help));
2275 sprintf (trans, fmt, help);
2276 XtSetArg (arg[0], XtNmenuName, menu_name);
2277 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2278 XtSetArg (arg[2], XtNinternalWidth, 2);
2279 XtSetArg (arg[3], XtNhighlightThickness, 1);
2280 XtSetArg (arg[4], XtNleft, XawChainLeft);
2281 XtSetArg (arg[5], XtNright, XawChainLeft);
2284 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2285 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2290 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2291 int *len = alloca (sizeof (int) * num_menus);
2294 XFontSetExtents *fontset_extents;
2296 XtSetArg (arg[0], XtNfontSet, &font_set);
2297 XtGetValues (button, arg, 1);
2299 fontset_extents = XExtentsOfFontSet (font_set);
2300 height = fontset_extents->max_logical_extent.height;
2301 ascent = - fontset_extents->max_logical_extent.y;
2303 for (i = 0; i < num_menus; i++)
2306 len[i] = strlen (menus[i].name2);
2307 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2308 if (max_width < width[i])
2309 max_width = width[i];
2311 for (i = 0; i < num_menus; i++)
2314 Pixmap pixmap = XCreatePixmap (display,
2315 RootWindow (display, screen),
2316 max_width, height, 1);
2317 XFillRectangle (display, pixmap, mono_gc_inv,
2318 0, 0, max_width, height);
2319 XmbDrawString (display, pixmap, font_set, mono_gc,
2320 max_width - width[i], ascent,
2321 menus[i].name2, len[i]);
2322 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2323 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2324 XtSetValues (menus[i].w, arg, 2);
2332 XtActionsRec actions[] = {
2333 {"Expose", ExposeProc},
2334 {"Configure", ConfigureProc},
2336 {"ButtonPress", ButtonProc},
2337 {"ButtonRelease", ButtonReleaseProc},
2338 {"ButtonMotion", ButtonMoveProc},
2339 {"Button2Press", Button2Proc},
2340 {"MenuHelp", MenuHelpProc}
2344 /* Print the usage of this program (the name is PROG), and exit with
2348 help_exit (char *prog, int exit_code)
2356 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2357 printf ("Display FILE on a window and allow users to edit it.\n");
2358 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2359 printf ("The following OPTIONs are available.\n");
2360 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2361 "Use the specified fontset\n");
2362 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2363 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2364 "Input method activated initially.\n");
2365 printf (" %-13s %s", "--version", "print version number\n");
2366 printf (" %-13s %s", "-h, --help", "print this message\n");
2372 main (int argc, char **argv)
2374 Widget form, BodyWidget, w;
2375 char *fontset_name = NULL;
2377 char *initial_input_method = NULL;
2378 int col = 80, row = 32;
2379 /* Translation table for TextWidget. */
2380 String trans = "<Expose>: Expose()\n\
2381 <Configure>: Configure()\n\
2384 <Btn1Down>: ButtonPress()\n\
2385 <Btn1Up>: ButtonRelease()\n\
2386 <Btn1Motion>: ButtonMotion()\n\
2387 <Btn2Down>: Button2Press()";
2388 /* Translation table for the top form widget. */
2389 String trans2 = "<Key>: Key()\n\
2391 String pop_face_trans
2392 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2393 <LeaveWindow>: MenuHelp() reset()\n\
2394 <Btn1Down>: set()\n\
2395 <Btn1Up>: notify() unset()";
2396 String pop_lang_trans
2397 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2398 <LeaveWindow>: MenuHelp() reset()\n\
2399 <Btn1Down>: set()\n\
2400 <Btn1Up>: notify() unset()";
2401 int font_width, font_ascent, font_descent;
2405 setlocale (LC_ALL, "");
2406 /* Create the top shell. */
2407 XtSetLanguageProc (NULL, NULL, NULL);
2408 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2409 NULL, sessionShellWidgetClass, NULL, 0);
2410 display = XtDisplay (ShellWidget);
2411 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2413 /* Parse the remaining command line arguments. */
2414 for (i = 1; i < argc; i++)
2416 if (! strcmp (argv[i], "--help")
2417 || ! strcmp (argv[i], "-h"))
2418 help_exit (argv[0], 0);
2419 else if (! strcmp (argv[i], "--version"))
2421 printf ("medit (m17n library) %s\n", VERSION);
2422 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2425 else if (! strcmp (argv[i], "--geometry"))
2428 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2429 help_exit (argv[0], 1);
2431 else if (! strcmp (argv[i], "-s"))
2434 fontsize = atoi (argv[i]);
2438 else if (! strcmp (argv[i], "--fontset"))
2441 fontset_name = strdup (argv[i]);
2443 else if (! strcmp (argv[i], "--im"))
2446 initial_input_method = strdup (argv[i]);
2448 else if (! strcmp (argv[i], "--with-xim"))
2452 else if (argv[i][0] != '-')
2454 filename = strdup (argv[i]);
2458 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2459 help_exit (argv[0], 1);
2463 help_exit (argv[0], 1);
2465 mdatabase_dir = ".";
2466 /* Initialize the m17n library. */
2468 if (merror_code != MERROR_NONE)
2469 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2471 mt = read_file (filename);
2474 nchars = mtext_len (mt);
2477 MFace *face = mface ();
2479 mface_put_prop (face, Mforeground, msymbol ("blue"));
2480 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2481 mface_put_prop (face, Mvideomode, Mreverse);
2482 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2483 m17n_object_unref (face);
2486 /* This tells ExposeProc to initialize everything. */
2489 XA_TEXT = XInternAtom (display, "TEXT", False);
2490 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2491 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2492 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2493 if (Mcoding_compound_text == Mnil)
2494 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2497 MPlist *plist = mplist ();
2501 mplist_put (plist, msymbol ("widget"), ShellWidget);
2502 if (fontset_name || fontsize != 120)
2504 MFontset *fontset = mfontset (fontset_name);
2507 mface_put_prop (face, Mfontset, fontset);
2508 mface_put_prop (face, Msize, (void *) fontsize);
2509 m17n_object_unref (fontset);
2510 mplist_add (plist, Mface, face);
2511 m17n_object_unref (face);
2513 frame = mframe (plist);
2515 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2516 m17n_object_unref (plist);
2517 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2518 default_face_list = mplist ();
2519 mplist_add (default_face_list, Mt, face_default);
2520 face_default_fontset = mface ();
2521 mface_put_prop (face_default_fontset, Mfontset,
2522 mface_get_prop (face_default, Mfontset));
2524 font = (MFont *) mframe_get_prop (frame, Mfont);
2525 default_font_size = (int) mfont_get_prop (font, Msize);
2528 font_width = (int) mframe_get_prop (frame, Mfont_width);
2529 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2530 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2531 win_width = font_width * col;
2532 win_height = (font_ascent + font_descent) * row;
2538 prop.color_top = prop.color_left = msymbol ("magenta");
2539 prop.color_bottom = prop.color_right = msymbol ("red");
2540 prop.inner_hmargin = prop.inner_vmargin = 1;
2541 prop.outer_hmargin = prop.outer_vmargin = 2;
2543 face_box = mface ();
2544 mface_put_prop (face_box, Mbox, &prop);
2547 face_courier = mface ();
2548 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2549 face_helvetica = mface ();
2550 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2551 face_times = mface ();
2552 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2553 face_dv_ttyogesh = mface ();
2554 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2555 face_freesans = mface ();
2556 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2557 face_freeserif = mface ();
2558 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2559 face_freemono = mface ();
2560 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2562 face_xxx_large = mface ();
2563 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2565 MFont *latin_font = mframe_get_prop (frame, Mfont);
2566 MFont *dev_font = mfont ();
2567 MFont *thai_font = mfont ();
2568 MFont *tib_font = mfont ();
2570 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2571 MSymbol no_ctl = msymbol ("no-ctl");
2573 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2574 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2575 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2576 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2577 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2578 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2580 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2581 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2582 latin_font, Mnil, 0);
2583 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2584 dev_font, no_ctl, 0);
2585 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2586 thai_font, no_ctl, 0);
2587 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2588 tib_font, no_ctl, 0);
2589 face_no_ctl_fontset = mface ();
2590 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2591 m17n_object_unref (fontset);
2598 setup_input_methods (with_xim, initial_input_method);
2600 gc = DefaultGC (display, screen);
2602 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2603 XtSetArg (arg[1], XtNdefaultDistance, 2);
2604 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2606 XtSetArg (arg[0], XtNborderWidth, 0);
2607 XtSetArg (arg[1], XtNdefaultDistance, 2);
2608 XtSetArg (arg[2], XtNtop, XawChainTop);
2609 XtSetArg (arg[3], XtNbottom, XawChainTop);
2610 XtSetArg (arg[4], XtNleft, XawChainLeft);
2611 XtSetArg (arg[5], XtNright, XawChainRight);
2612 XtSetArg (arg[6], XtNresizable, True);
2613 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2614 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2615 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2616 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2617 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2618 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2619 XtSetArg (arg[7], XtNfromVert, LangWidget);
2620 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2621 XtSetArg (arg[2], XtNtop, XawChainBottom);
2622 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2623 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2625 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2626 HeadWidget, NULL, 0);
2627 XtSetArg (arg[0], XtNvalue, "");
2628 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2629 FileShellWidget, arg, 1);
2630 XawDialogAddButton (FileDialogWidget, "OK",
2631 FileDialogProc, (XtPointer) 0);
2632 XawDialogAddButton (FileDialogWidget, "CANCEL",
2633 FileDialogProc, (XtPointer) 1);
2635 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2636 (char *) check_bits,
2637 check_width, check_height);
2639 unsigned long valuemask = GCForeground;
2642 values.foreground = 1;
2643 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2644 values.foreground = 0;
2645 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2652 if (num_menus < num_input_methods + 2)
2653 num_menus = num_input_methods + 2;
2654 if (num_menus < num_faces + 1)
2655 num_menus = num_faces + 1;
2656 menus = alloca (sizeof (MenuRec) * num_menus);
2658 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2659 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2660 "File I/O, Serialization, Image, Quit");
2662 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2663 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2664 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2665 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2666 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2667 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2668 w = create_menu_button (ShellWidget, HeadWidget, w,
2669 "Cursor", "Cursor Menu",
2670 menus, 6, "Cursor Movement Mode, Cursor Shape");
2671 CursorMenus[0] = menus[0].w;
2672 CursorMenus[1] = menus[1].w;
2673 CursorMenus[2] = menus[3].w;
2674 CursorMenus[3] = menus[4].w;
2675 CursorMenus[4] = menus[5].w;
2677 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2678 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2679 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2680 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2681 menus, 3, "BIDI Processing Mode");
2682 for (i = 0; i < 3; i++)
2683 BidiMenus[i] = menus[i].w;
2685 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2686 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2687 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2688 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2690 menus, 3, "How to break lines");
2691 for (i = 0; i < 3; i++)
2692 LineBreakMenus[i] = menus[i].w;
2694 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2695 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2696 for (i = 0; i < num_input_methods; i++)
2698 InputMethodInfo *im = input_method_table + i;
2699 char *name1, *name2;
2701 if (im->language != Mnil && im->language != Mt)
2703 MSymbol sym = msymbol_get (im->language, Mlanguage);
2705 name1 = msymbol_name (im->language);
2707 name1 = msymbol_name (sym);
2708 name2 = msymbol_name (im->name);
2711 name1 = msymbol_name (im->name), name2 = NULL;
2713 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2715 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2716 "Input Method Menu", menus, i + 2,
2717 "Select input method");
2720 unsigned long valuemask = GCForeground;
2723 XtSetArg (arg[0], XtNbackground, &values.foreground);
2724 XtGetValues (w, arg, 1);
2725 gc_inv = XCreateGC (display, RootWindow (display, screen),
2726 valuemask, &values);
2729 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2730 for (i = 0; i < num_input_methods + 2; i++)
2731 InputMethodMenus[i] = menus[i].w;
2733 input_status_width = font_width * 8;
2734 input_status_height = (font_ascent + font_descent) * 2.4;
2735 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2737 input_status_height,
2738 DefaultDepth (display, screen));
2743 prop.color_top = prop.color_bottom
2744 = prop.color_left = prop.color_right = Mnil;
2745 prop.inner_hmargin = prop.inner_vmargin = 1;
2746 prop.outer_hmargin = prop.outer_vmargin = 0;
2747 face_input_status = mface_copy (face_default);
2748 mface_put_prop (face_input_status, Mbox, &prop);
2751 XFillRectangle (display, input_status_pixmap, gc_inv,
2752 0, 0, input_status_width, input_status_height);
2753 XtSetArg (arg[0], XtNfromHoriz, w);
2754 XtSetArg (arg[1], XtNleft, XawRubber);
2755 XtSetArg (arg[2], XtNright, XawChainRight);
2756 XtSetArg (arg[3], XtNborderWidth, 0);
2757 XtSetArg (arg[4], XtNlabel, " ");
2758 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2759 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2760 HeadWidget, arg, 6);
2761 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2762 XtSetArg (arg[1], XtNleft, XawChainRight);
2763 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2764 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2765 HeadWidget, arg, 5);
2767 XtSetArg (arg[0], XtNborderWidth, 0);
2768 XtSetArg (arg[1], XtNleft, XawChainLeft);
2769 XtSetArg (arg[2], XtNright, XawChainLeft);
2770 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2771 for (i = 0; i < num_faces;)
2773 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2774 char *label = label_menu + 5; /* "Xxxx" */
2776 for (j = i; j < num_faces && face_table[j].face; j++)
2777 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2779 w = create_menu_button (ShellWidget, FaceWidget, w,
2781 menus, j - i, "Push face property");
2785 XtSetArg (arg[0], XtNfromHoriz, w);
2786 XtSetArg (arg[1], XtNleft, XawChainLeft);
2787 XtSetArg (arg[2], XtNright, XawChainLeft);
2788 XtSetArg (arg[3], XtNhorizDistance, 10);
2789 XtSetArg (arg[4], XtNlabel, "Pop");
2790 XtSetArg (arg[5], XtNtranslations,
2791 XtParseTranslationTable (pop_face_trans));
2792 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2793 FaceWidget, arg, 6);
2794 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2796 XtSetArg (arg[0], XtNfromHoriz, w);
2797 XtSetArg (arg[1], XtNleft, XawChainLeft);
2798 XtSetArg (arg[2], XtNright, XawChainRight);
2799 XtSetArg (arg[3], XtNlabel, "");
2800 XtSetArg (arg[4], XtNborderWidth, 0);
2801 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2802 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2803 FaceWidget, arg, 6);
2805 XtSetArg (arg[0], XtNborderWidth, 0);
2806 XtSetArg (arg[1], XtNleft, XawChainLeft);
2807 XtSetArg (arg[2], XtNright, XawChainLeft);
2808 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2810 MPlist *plist[11], *pl;
2813 for (i = 0; i < 11; i++) plist[i] = NULL;
2815 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2816 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2818 MSymbol sym = msymbol_exist (langname);
2822 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2824 char *name = msymbol_name (fullname);
2827 if (c >= 'A' && c <= 'Z')
2829 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2833 pl = plist[idx] = mplist ();
2834 for (; mplist_next (pl); pl = mplist_next (pl))
2835 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2837 mplist_push (pl, sym, fullname);
2842 for (i = 0; i < 11; i++)
2845 char *name = alloca (9);
2847 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2850 for (j = 0, pl = plist[i]; mplist_next (pl);
2851 j++, pl = mplist_next (pl))
2852 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2853 msymbol_name (mplist_key (pl)),
2854 LangProc, mplist_key (pl), -1);
2855 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2856 menus, j, "Push language property");
2858 for (i = 0; i < 11; i++)
2860 m17n_object_unref (plist[i]);
2862 XtSetArg (arg[0], XtNfromHoriz, w);
2863 XtSetArg (arg[1], XtNleft, XawChainLeft);
2864 XtSetArg (arg[2], XtNright, XawChainLeft);
2865 XtSetArg (arg[3], XtNhorizDistance, 10);
2866 XtSetArg (arg[4], XtNlabel, "Pop");
2867 XtSetArg (arg[5], XtNtranslations,
2868 XtParseTranslationTable (pop_lang_trans));
2869 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2870 LangWidget, arg, 6);
2871 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2873 XtSetArg (arg[0], XtNfromHoriz, w);
2874 XtSetArg (arg[1], XtNleft, XawChainLeft);
2875 XtSetArg (arg[2], XtNright, XawChainRight);
2876 XtSetArg (arg[3], XtNlabel, "");
2877 XtSetArg (arg[4], XtNborderWidth, 0);
2878 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2879 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2880 LangWidget, arg, 6);
2883 XtSetArg (arg[0], XtNheight, win_height);
2884 XtSetArg (arg[1], XtNwidth, 10);
2885 XtSetArg (arg[2], XtNleft, XawChainLeft);
2886 XtSetArg (arg[3], XtNright, XawChainLeft);
2887 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2889 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2890 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2892 XtSetArg (arg[0], XtNheight, win_height);
2893 XtSetArg (arg[1], XtNwidth, win_width);
2894 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2895 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2896 XtSetArg (arg[4], XtNleft, XawChainLeft);
2897 XtSetArg (arg[5], XtNright, XawChainRight);
2898 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2901 XtSetArg (arg[0], XtNborderWidth, 0);
2902 XtSetArg (arg[1], XtNleft, XawChainLeft);
2903 XtSetArg (arg[2], XtNright, XawChainRight);
2904 XtSetArg (arg[3], XtNresizable, True);
2905 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2906 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2907 TailWidget, arg, 5);
2909 memset (&control, 0, sizeof control);
2910 control.two_dimensional = 1;
2911 control.enable_bidi = 1;
2912 control.anti_alias = 1;
2913 control.min_line_ascent = font_ascent;
2914 control.min_line_descent = font_descent;
2915 control.max_line_width = win_width;
2916 control.with_cursor = 1;
2917 control.cursor_width = 2;
2918 control.partial_update = 1;
2919 control.ignore_formatting_char = 1;
2921 memset (&input_status_control, 0, sizeof input_status_control);
2922 input_status_control.enable_bidi = 1;
2924 XtAppAddActions (context, actions, XtNumber (actions));
2925 XtRealizeWidget (ShellWidget);
2927 win = XtWindow (TextWidget);
2929 XtAppMainLoop (context);
2931 if (current_input_context)
2932 minput_destroy_ic (current_input_context);
2933 for (i = 0; i < num_input_methods; i++)
2934 if (input_method_table[i].im)
2935 minput_close_im (input_method_table[i].im);
2936 m17n_object_unref (frame);
2937 m17n_object_unref (mt);
2938 m17n_object_unref (face_xxx_large);
2939 m17n_object_unref (face_box);
2940 m17n_object_unref (face_courier);
2941 m17n_object_unref (face_helvetica);
2942 m17n_object_unref (face_times);
2943 m17n_object_unref (face_dv_ttyogesh);
2944 m17n_object_unref (face_freesans);
2945 m17n_object_unref (face_freeserif);
2946 m17n_object_unref (face_freemono);
2947 m17n_object_unref (face_default_fontset);
2948 m17n_object_unref (face_no_ctl_fontset);
2949 m17n_object_unref (face_input_status);
2950 m17n_object_unref (face_default);
2951 m17n_object_unref (default_face_list);
2952 m17n_object_unref (selection);
2954 XFreeGC (display, mono_gc);
2955 XFreeGC (display, mono_gc_inv);
2956 XFreeGC (display, gc_inv);
2957 XtUninstallTranslations (form);
2958 XtUninstallTranslations (TextWidget);
2959 XtDestroyWidget (ShellWidget);
2960 XtDestroyApplicationContext (context);
2964 free (fontset_name);
2966 free (input_method_table);
2967 free (InputMethodMenus);
2971 #endif /* not FOR_DOXYGEN */