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.2.0"
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'
1596 : ((unsigned char *) buf)[0]);
1597 if (current_input_context)
1598 mtext_put_prop (temp, 0, 1, Mlanguage,
1599 current_input_context->im->language);
1600 insert_chars (temp);
1601 m17n_object_unref (temp);
1606 if (! keep_target_x_position)
1607 target_x_position = cursor.x;
1611 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1613 char *name = (char *) client_data;
1615 int from = -1, to = 0;
1620 filename = strdup (name);
1623 fp = fopen (filename, "w");
1626 fprintf (stderr, "Open for write fail: %s", filename);
1632 from = mtext_property_start (selection);
1633 to = mtext_property_end (selection);
1634 mtext_detach_property (selection);
1637 mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
1640 select_region (from, to);
1644 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1650 mtext_detach_property (selection);
1651 serialized = (int) client_data;
1653 new = mtext_deserialize (mt);
1656 MPlist *plist = mplist ();
1658 mplist_push (plist, Mt, Mface);
1659 mplist_push (plist, Mt, Mlanguage);
1660 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1661 m17n_object_unref (plist);
1665 m17n_object_unref (mt);
1667 serialized = ! serialized;
1668 nchars = mtext_len (mt);
1671 update_cursor (0, 1);
1672 redraw (0, win_height, 1, 1);
1676 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1678 XtAppSetExitFlag (context);
1684 FILE *fp = fopen (filename, "r");
1687 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1688 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
1691 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1696 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1698 int data = (int) client_data;
1703 control.enable_bidi = 0;
1704 control.orientation_reversed = 0;
1708 control.enable_bidi = 1;
1709 control.orientation_reversed = data == 2;
1711 for (i = 0; i < 3; i++)
1714 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1716 XtSetArg (arg[0], XtNleftBitmap, None);
1717 XtSetValues (BidiMenus[i], arg, 1);
1720 update_cursor (cursor.from, 1);
1721 redraw (0, win_height, 1, 0);
1724 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1727 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1729 int data = (int) client_data;
1733 control.max_line_width = 0;
1736 control.max_line_width = win_width;
1737 control.line_break = (data == 1 ? NULL : line_break);
1739 for (i = 0; i < 3; i++)
1742 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1744 XtSetArg (arg[0], XtNleftBitmap, None);
1745 XtSetValues (LineBreakMenus[i], arg, 1);
1748 update_cursor (cursor.from, 1);
1749 redraw (0, win_height, 1, 0);
1753 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1755 int data = (int) client_data;
1769 control.cursor_bidi = 0, control.cursor_width = -1;
1773 control.cursor_bidi = 0, control.cursor_width = 2;
1777 control.cursor_bidi = 1;
1782 for (i = from; i < to; i++)
1785 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1787 XtSetArg (arg[0], XtNleftBitmap, None);
1788 XtSetValues (CursorMenus[i], arg, 1);
1791 update_cursor (cursor.from, 0);
1792 redraw (0, win_height, 1, 0);
1796 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1798 int idx = (int) client_data;
1800 if (idx == -2 ? current_input_method < 0
1801 : idx == -1 ? auto_input_method
1802 : idx == current_input_method)
1805 XtSetArg (arg[0], XtNleftBitmap, None);
1806 if (auto_input_method)
1808 XtSetValues (InputMethodMenus[1], arg, 1);
1809 auto_input_method = 0;
1811 else if (current_input_method < 0)
1812 XtSetValues (InputMethodMenus[0], arg, 1);
1814 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1818 auto_input_method = 1;
1821 else if (input_method_table[idx].available >= 0)
1823 if (! input_method_table[idx].im)
1825 input_method_table[idx].im =
1826 minput_open_im (input_method_table[idx].language,
1827 input_method_table[idx].name, NULL);
1828 if (! input_method_table[idx].im)
1829 input_method_table[idx].available = -1;
1831 if (input_method_table[idx].im)
1832 select_input_method (idx);
1834 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1835 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1838 MPlist *default_face_list;
1841 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1843 int idx = (int) client_data;
1854 MFace *face = mframe_get_prop (frame, Mface);
1856 for (plist = default_face_list; mplist_key (plist) != Mnil;
1857 plist = mplist_next (plist))
1858 mface_merge (face, mplist_value (plist));
1859 mplist_add (plist, Mt, *face_table[idx].face);
1860 mface_merge (face, *face_table[idx].face);
1862 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1864 MFace *face = mframe_get_prop (frame, Mface);
1866 for (plist = default_face_list;
1867 mplist_key (mplist_next (plist)) != Mnil;
1868 plist = mplist_next (plist))
1869 mface_merge (face, mplist_value (plist));
1873 update_cursor (0, 1);
1874 redraw (0, win_height, 1, 1);
1879 XtAppAddWorkProc (context, show_cursor, NULL);
1880 from = mtext_property_start (selection);
1881 to = mtext_property_end (selection);
1882 old_y1 = sel_end.y1;
1884 mtext_detach_property (selection);
1887 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1888 MTEXTPROP_REAR_STICKY);
1889 mtext_push_property (mt, from, to, prop);
1890 m17n_object_unref (prop);
1893 mtext_pop_prop (mt, from, to, Mface);
1895 update_top (top.from);
1896 update_cursor (cursor.from, 1);
1897 select_region (from, to);
1898 update_region (sel_start.y0, old_y1, sel_end.y1);
1899 if (cur.y1 > win_height)
1901 while (cur.y1 > win_height)
1904 update_cursor (cursor.from, 1);
1910 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1912 MSymbol sym = (MSymbol) client_data;
1919 XtAppAddWorkProc (context, show_cursor, NULL);
1920 from = mtext_property_start (selection);
1921 to = mtext_property_end (selection);
1922 old_y1 = sel_end.y1;
1924 mtext_detach_property (selection);
1926 mtext_put_prop (mt, from, to, Mlanguage, sym);
1928 mtext_pop_prop (mt, from, to, Mlanguage);
1931 update_top (top.from);
1932 update_cursor (cursor.from, 1);
1933 select_region (from, to);
1934 update_region (sel_start.y0, old_y1, sel_end.y1);
1935 if (cur.y1 > win_height)
1937 while (cur.y1 > win_height)
1940 update_cursor (cursor.from, 1);
1946 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1948 int narrowed = (int) client_data;
1951 MConverter *converter;
1957 from = mtext_property_start (selection);
1958 to = mtext_property_end (selection);
1967 mdump = popen ("mdump -q -p a4", "w");
1969 mdump = popen ("mdump -q", "w");
1972 converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
1973 mconv_encode_range (converter, mt, from, to);
1974 mconv_free_converter (converter);
1979 input_status (MInputContext *ic, MSymbol command)
1981 XFillRectangle (display, input_status_pixmap, gc_inv,
1982 0, 0, input_status_width, input_status_height);
1983 if (command == Minput_status_draw)
1987 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1988 Mface, face_input_status);
1989 if (ic->im->language != Mnil)
1990 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1991 Mlanguage, ic->im->language);
1992 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1993 &input_status_control, NULL, NULL, &rect);
1994 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1995 input_status_width - rect.width - 2, - rect.y,
1996 ic->status, 0, mtext_len (ic->status),
1997 &input_status_control);
1999 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
2000 XtSetValues (CurIMStatus, arg, 1);
2004 compare_input_method (const void *elt1, const void *elt2)
2006 const InputMethodInfo *im1 = elt1;
2007 const InputMethodInfo *im2 = elt2;
2008 MSymbol lang1, lang2;
2010 if (im1->language == Mnil)
2012 if (im1->language == im2->language)
2013 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
2014 if (im1->language == Mt)
2016 if (im2->language == Mt)
2018 lang1 = msymbol_get (im1->language, Mlanguage);
2019 lang2 = msymbol_get (im2->language, Mlanguage);
2020 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2024 setup_input_methods (int with_xim, char *initial_input_method)
2026 MInputMethod *im = NULL;
2027 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2030 char *lang_name = NULL, *method_name = NULL;
2032 if (initial_input_method)
2034 char *p = strchr (initial_input_method, '-');
2036 lang_name = initial_input_method, method_name = p + 1, *p = '\0';
2038 method_name = initial_input_method;
2041 num_input_methods = mplist_length (plist);
2045 MInputXIMArgIM arg_xim;
2047 arg_xim.display = display;
2049 arg_xim.res_name = arg_xim.res_class = NULL;
2050 arg_xim.locale = NULL;
2051 arg_xim.modifier_list = NULL;
2052 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2054 num_input_methods++;
2056 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2059 input_method_table[i].available = 1;
2060 input_method_table[i].language = Mnil;
2061 input_method_table[i].name = im->name;
2062 input_method_table[i].im = im;
2066 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2068 MDatabase *mdb = mplist_value (pl);
2069 MSymbol *tag = mdatabase_tag (mdb);
2073 input_method_table[i].language = tag[1];
2074 input_method_table[i].name = tag[2];
2079 m17n_object_unref (plist);
2080 num_input_methods = i;
2081 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2082 compare_input_method);
2083 current_input_context = NULL;
2085 mplist_put (minput_driver->callback_list, Minput_status_start,
2086 (void *) input_status);
2087 mplist_put (minput_driver->callback_list, Minput_status_draw,
2088 (void *) input_status);
2089 mplist_put (minput_driver->callback_list, Minput_status_done,
2090 (void *) input_status);
2093 for (i = 0; i < num_input_methods; i++)
2094 if (strcmp (method_name, msymbol_name (input_method_table[i].name)) == 0
2096 ? strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0
2097 : input_method_table[i].language == Mt))
2099 current_input_method = i;
2106 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2110 if (num && *num > 0)
2114 for (i = 0; i < *num; i++)
2115 bytes += strlen (str[i]) + 1;
2116 msg = alloca (bytes);
2117 strcpy (msg, str[0]);
2118 for (i = 1; i < *num; i++)
2119 strcat (msg, " "), strcat (msg, str[i]);
2121 else if (cursor.from < nchars)
2123 int c = mtext_ref_char (mt, cursor.from);
2124 char *name = mchar_get_prop (c, Mname);
2128 msg = alloca (10 + strlen (name));
2129 sprintf (msg, "U+%04X %s", c, name);
2135 XtSetArg (arg[0], XtNlabel, msg);
2136 XtSetValues (MessageWidget, arg, 1);
2142 char *name1, *name2;
2143 XtCallbackProc proc;
2144 XtPointer client_data;
2149 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2151 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2153 MenuRec FileMenu[] =
2154 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2155 { 0, "Save", NULL, SaveProc, NULL, -1 },
2156 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2158 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2159 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2161 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2162 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2164 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2167 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2169 MenuRec *rec = (MenuRec *) client_data;
2172 XtSetArg (arg[0], XtNvalue, "");
2173 XtSetArg (arg[1], XtNlabel, rec->name1);
2174 XtSetValues (FileDialogWidget, arg, 2);
2175 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2176 XtSetArg (arg[0], XtNx, x + 20);
2177 XtSetArg (arg[1], XtNy, y + 10);
2178 XtSetValues (FileShellWidget, arg, 2);
2179 XtPopup (FileShellWidget, XtGrabExclusive);
2183 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2188 XtPopdown (FileShellWidget);
2189 if ((int) client_data == 1)
2191 XtSetArg (arg[0], XtNlabel, &label);
2192 XtGetValues (FileDialogWidget, arg, 1);
2193 if (strcmp (label, FileMenu[0].name1) == 0)
2197 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2198 fp = fopen (filename, "r");
2200 m17n_object_unref (mt);
2203 mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
2211 nchars = mtext_len (mt);
2213 update_cursor (0, 1);
2214 redraw (0, win_height, 1, 1);
2216 else if (strcmp (label, FileMenu[2].name1) == 0)
2217 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2219 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2222 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2223 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2224 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2225 (MENU).status = (STATUS))
2229 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2230 char *menu_name, MenuRec *menus, int num_menus, char *help)
2232 Widget button, menu;
2233 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2234 <LeaveWindow>: reset() MenuHelp()\n\
2235 <BtnDown>: reset() PopupMenu()\n\
2236 <BtnUp>: highlight()";
2242 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2243 for (i = 0; i < num_menus; i++)
2254 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2256 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2258 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2260 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2264 XtSetArg (arg[0], XtNsensitive, False);
2265 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2271 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2276 trans = alloca (strlen (fmt) + strlen (help));
2277 sprintf (trans, fmt, help);
2278 XtSetArg (arg[0], XtNmenuName, menu_name);
2279 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2280 XtSetArg (arg[2], XtNinternalWidth, 2);
2281 XtSetArg (arg[3], XtNhighlightThickness, 1);
2282 XtSetArg (arg[4], XtNleft, XawChainLeft);
2283 XtSetArg (arg[5], XtNright, XawChainLeft);
2286 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2287 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2292 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2293 int *len = alloca (sizeof (int) * num_menus);
2296 XFontSetExtents *fontset_extents;
2298 XtSetArg (arg[0], XtNfontSet, &font_set);
2299 XtGetValues (button, arg, 1);
2301 fontset_extents = XExtentsOfFontSet (font_set);
2302 height = fontset_extents->max_logical_extent.height;
2303 ascent = - fontset_extents->max_logical_extent.y;
2305 for (i = 0; i < num_menus; i++)
2308 len[i] = strlen (menus[i].name2);
2309 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2310 if (max_width < width[i])
2311 max_width = width[i];
2313 for (i = 0; i < num_menus; i++)
2316 Pixmap pixmap = XCreatePixmap (display,
2317 RootWindow (display, screen),
2318 max_width, height, 1);
2319 XFillRectangle (display, pixmap, mono_gc_inv,
2320 0, 0, max_width, height);
2321 XmbDrawString (display, pixmap, font_set, mono_gc,
2322 max_width - width[i], ascent,
2323 menus[i].name2, len[i]);
2324 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2325 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2326 XtSetValues (menus[i].w, arg, 2);
2334 XtActionsRec actions[] = {
2335 {"Expose", ExposeProc},
2336 {"Configure", ConfigureProc},
2338 {"ButtonPress", ButtonProc},
2339 {"ButtonRelease", ButtonReleaseProc},
2340 {"ButtonMotion", ButtonMoveProc},
2341 {"Button2Press", Button2Proc},
2342 {"MenuHelp", MenuHelpProc}
2346 /* Print the usage of this program (the name is PROG), and exit with
2350 help_exit (char *prog, int exit_code)
2358 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2359 printf ("Display FILE on a window and allow users to edit it.\n");
2360 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2361 printf ("The following OPTIONs are available.\n");
2362 printf (" %-13s\n\t\t%s", "--fontset FONTSET",
2363 "Use the specified fontset\n");
2364 printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
2365 printf (" %-13s\n\t\t%s", "--im INPUT-METHOD",
2366 "Input method activated initially.\n");
2367 printf (" %-13s %s", "--version", "print version number\n");
2368 printf (" %-13s %s", "-h, --help", "print this message\n");
2374 main (int argc, char **argv)
2376 Widget form, BodyWidget, w;
2377 char *fontset_name = NULL;
2379 char *initial_input_method = NULL;
2380 int col = 80, row = 32;
2381 /* Translation table for TextWidget. */
2382 String trans = "<Expose>: Expose()\n\
2383 <Configure>: Configure()\n\
2386 <Btn1Down>: ButtonPress()\n\
2387 <Btn1Up>: ButtonRelease()\n\
2388 <Btn1Motion>: ButtonMotion()\n\
2389 <Btn2Down>: Button2Press()";
2390 /* Translation table for the top form widget. */
2391 String trans2 = "<Key>: Key()\n\
2393 String pop_face_trans
2394 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2395 <LeaveWindow>: MenuHelp() reset()\n\
2396 <Btn1Down>: set()\n\
2397 <Btn1Up>: notify() unset()";
2398 String pop_lang_trans
2399 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2400 <LeaveWindow>: MenuHelp() reset()\n\
2401 <Btn1Down>: set()\n\
2402 <Btn1Up>: notify() unset()";
2403 int font_width, font_ascent, font_descent;
2407 setlocale (LC_ALL, "");
2408 /* Create the top shell. */
2409 XtSetLanguageProc (NULL, NULL, NULL);
2410 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2411 NULL, sessionShellWidgetClass, NULL, 0);
2412 display = XtDisplay (ShellWidget);
2413 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2415 /* Parse the remaining command line arguments. */
2416 for (i = 1; i < argc; i++)
2418 if (! strcmp (argv[i], "--help")
2419 || ! strcmp (argv[i], "-h"))
2420 help_exit (argv[0], 0);
2421 else if (! strcmp (argv[i], "--version"))
2423 printf ("medit (m17n library) %s\n", VERSION);
2424 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2427 else if (! strcmp (argv[i], "--geometry"))
2430 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2431 help_exit (argv[0], 1);
2433 else if (! strcmp (argv[i], "-s"))
2436 fontsize = atoi (argv[i]);
2440 else if (! strcmp (argv[i], "--fontset"))
2443 fontset_name = strdup (argv[i]);
2445 else if (! strcmp (argv[i], "--im"))
2448 initial_input_method = strdup (argv[i]);
2450 else if (! strcmp (argv[i], "--with-xim"))
2454 else if (argv[i][0] != '-')
2456 filename = strdup (argv[i]);
2460 fprintf (stderr, "Unknown option: %s\n", argv[i]);
2461 help_exit (argv[0], 1);
2465 filename = "/dev/null";
2467 mdatabase_dir = ".";
2468 /* Initialize the m17n library. */
2470 if (merror_code != MERROR_NONE)
2471 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2473 mt = read_file (filename);
2476 nchars = mtext_len (mt);
2479 MFace *face = mface ();
2481 mface_put_prop (face, Mforeground, msymbol ("blue"));
2482 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2483 mface_put_prop (face, Mvideomode, Mreverse);
2484 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2485 m17n_object_unref (face);
2488 /* This tells ExposeProc to initialize everything. */
2491 XA_TEXT = XInternAtom (display, "TEXT", False);
2492 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2493 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2494 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2495 if (Mcoding_compound_text == Mnil)
2496 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2499 MPlist *plist = mplist ();
2503 mplist_put (plist, msymbol ("widget"), ShellWidget);
2504 if (fontset_name || fontsize > 0)
2506 MFontset *fontset = mfontset (fontset_name);
2509 mface_put_prop (face, Mfontset, fontset);
2510 mface_put_prop (face, Msize, (void *) fontsize);
2511 m17n_object_unref (fontset);
2512 mplist_add (plist, Mface, face);
2513 m17n_object_unref (face);
2515 frame = mframe (plist);
2517 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2518 m17n_object_unref (plist);
2519 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2520 default_face_list = mplist ();
2521 mplist_add (default_face_list, Mt, face_default);
2522 face_default_fontset = mface ();
2523 mface_put_prop (face_default_fontset, Mfontset,
2524 mface_get_prop (face_default, Mfontset));
2526 font = (MFont *) mframe_get_prop (frame, Mfont);
2527 default_font_size = (int) mfont_get_prop (font, Msize);
2530 font_width = (int) mframe_get_prop (frame, Mfont_width);
2531 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2532 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2533 win_width = font_width * col;
2534 win_height = (font_ascent + font_descent) * row;
2540 prop.color_top = prop.color_left = msymbol ("magenta");
2541 prop.color_bottom = prop.color_right = msymbol ("red");
2542 prop.inner_hmargin = prop.inner_vmargin = 1;
2543 prop.outer_hmargin = prop.outer_vmargin = 2;
2545 face_box = mface ();
2546 mface_put_prop (face_box, Mbox, &prop);
2549 face_courier = mface ();
2550 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2551 face_helvetica = mface ();
2552 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2553 face_times = mface ();
2554 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2555 face_dv_ttyogesh = mface ();
2556 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2557 face_freesans = mface ();
2558 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2559 face_freeserif = mface ();
2560 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2561 face_freemono = mface ();
2562 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2564 face_xxx_large = mface ();
2565 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2567 MFont *latin_font = mframe_get_prop (frame, Mfont);
2568 MFont *dev_font = mfont ();
2569 MFont *thai_font = mfont ();
2570 MFont *tib_font = mfont ();
2572 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2573 MSymbol no_ctl = msymbol ("no-ctl");
2575 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2576 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2577 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2578 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2579 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2580 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2582 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2583 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2584 latin_font, Mnil, 0);
2585 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2586 dev_font, no_ctl, 0);
2587 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2588 thai_font, no_ctl, 0);
2589 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2590 tib_font, no_ctl, 0);
2591 face_no_ctl_fontset = mface ();
2592 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2593 m17n_object_unref (fontset);
2600 setup_input_methods (with_xim, initial_input_method);
2602 gc = DefaultGC (display, screen);
2604 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2605 XtSetArg (arg[1], XtNdefaultDistance, 2);
2606 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2608 XtSetArg (arg[0], XtNborderWidth, 0);
2609 XtSetArg (arg[1], XtNdefaultDistance, 2);
2610 XtSetArg (arg[2], XtNtop, XawChainTop);
2611 XtSetArg (arg[3], XtNbottom, XawChainTop);
2612 XtSetArg (arg[4], XtNleft, XawChainLeft);
2613 XtSetArg (arg[5], XtNright, XawChainRight);
2614 XtSetArg (arg[6], XtNresizable, True);
2615 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2616 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2617 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2618 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2619 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2620 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2621 XtSetArg (arg[7], XtNfromVert, LangWidget);
2622 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2623 XtSetArg (arg[2], XtNtop, XawChainBottom);
2624 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2625 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2627 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2628 HeadWidget, NULL, 0);
2629 XtSetArg (arg[0], XtNvalue, "");
2630 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2631 FileShellWidget, arg, 1);
2632 XawDialogAddButton (FileDialogWidget, "OK",
2633 FileDialogProc, (XtPointer) 0);
2634 XawDialogAddButton (FileDialogWidget, "CANCEL",
2635 FileDialogProc, (XtPointer) 1);
2637 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2638 (char *) check_bits,
2639 check_width, check_height);
2641 unsigned long valuemask = GCForeground;
2644 values.foreground = 1;
2645 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2646 values.foreground = 0;
2647 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2654 if (num_menus < num_input_methods + 2)
2655 num_menus = num_input_methods + 2;
2656 if (num_menus < num_faces + 1)
2657 num_menus = num_faces + 1;
2658 menus = alloca (sizeof (MenuRec) * num_menus);
2660 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2661 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2662 "File I/O, Serialization, Image, Quit");
2664 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2665 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2666 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2667 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2668 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2669 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2670 w = create_menu_button (ShellWidget, HeadWidget, w,
2671 "Cursor", "Cursor Menu",
2672 menus, 6, "Cursor Movement Mode, Cursor Shape");
2673 CursorMenus[0] = menus[0].w;
2674 CursorMenus[1] = menus[1].w;
2675 CursorMenus[2] = menus[3].w;
2676 CursorMenus[3] = menus[4].w;
2677 CursorMenus[4] = menus[5].w;
2679 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2680 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2681 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2682 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2683 menus, 3, "BIDI Processing Mode");
2684 for (i = 0; i < 3; i++)
2685 BidiMenus[i] = menus[i].w;
2687 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2688 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2689 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2690 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2692 menus, 3, "How to break lines");
2693 for (i = 0; i < 3; i++)
2694 LineBreakMenus[i] = menus[i].w;
2696 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2697 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2698 for (i = 0; i < num_input_methods; i++)
2700 InputMethodInfo *im = input_method_table + i;
2701 char *name1, *name2;
2703 if (im->language != Mnil && im->language != Mt)
2705 MSymbol sym = msymbol_get (im->language, Mlanguage);
2707 name1 = msymbol_name (im->language);
2709 name1 = msymbol_name (sym);
2710 name2 = msymbol_name (im->name);
2713 name1 = msymbol_name (im->name), name2 = NULL;
2715 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2717 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2718 "Input Method Menu", menus, i + 2,
2719 "Select input method");
2722 unsigned long valuemask = GCForeground;
2725 XtSetArg (arg[0], XtNbackground, &values.foreground);
2726 XtGetValues (w, arg, 1);
2727 gc_inv = XCreateGC (display, RootWindow (display, screen),
2728 valuemask, &values);
2731 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2732 for (i = 0; i < num_input_methods + 2; i++)
2733 InputMethodMenus[i] = menus[i].w;
2735 input_status_width = font_width * 8;
2736 input_status_height = (font_ascent + font_descent) * 2.4;
2737 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2739 input_status_height,
2740 DefaultDepth (display, screen));
2745 prop.color_top = prop.color_bottom
2746 = prop.color_left = prop.color_right = Mnil;
2747 prop.inner_hmargin = prop.inner_vmargin = 1;
2748 prop.outer_hmargin = prop.outer_vmargin = 0;
2749 face_input_status = mface_copy (face_default);
2750 mface_put_prop (face_input_status, Mbox, &prop);
2753 XFillRectangle (display, input_status_pixmap, gc_inv,
2754 0, 0, input_status_width, input_status_height);
2755 XtSetArg (arg[0], XtNfromHoriz, w);
2756 XtSetArg (arg[1], XtNleft, XawRubber);
2757 XtSetArg (arg[2], XtNright, XawChainRight);
2758 XtSetArg (arg[3], XtNborderWidth, 0);
2759 XtSetArg (arg[4], XtNlabel, " ");
2760 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2761 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2762 HeadWidget, arg, 6);
2763 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2764 XtSetArg (arg[1], XtNleft, XawChainRight);
2765 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2766 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2767 HeadWidget, arg, 5);
2769 XtSetArg (arg[0], XtNborderWidth, 0);
2770 XtSetArg (arg[1], XtNleft, XawChainLeft);
2771 XtSetArg (arg[2], XtNright, XawChainLeft);
2772 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2773 for (i = 0; i < num_faces;)
2775 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2776 char *label = label_menu + 5; /* "Xxxx" */
2778 for (j = i; j < num_faces && face_table[j].face; j++)
2779 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2781 w = create_menu_button (ShellWidget, FaceWidget, w,
2783 menus, j - i, "Push face property");
2787 XtSetArg (arg[0], XtNfromHoriz, w);
2788 XtSetArg (arg[1], XtNleft, XawChainLeft);
2789 XtSetArg (arg[2], XtNright, XawChainLeft);
2790 XtSetArg (arg[3], XtNhorizDistance, 10);
2791 XtSetArg (arg[4], XtNlabel, "Pop");
2792 XtSetArg (arg[5], XtNtranslations,
2793 XtParseTranslationTable (pop_face_trans));
2794 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2795 FaceWidget, arg, 6);
2796 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2798 XtSetArg (arg[0], XtNfromHoriz, w);
2799 XtSetArg (arg[1], XtNleft, XawChainLeft);
2800 XtSetArg (arg[2], XtNright, XawChainRight);
2801 XtSetArg (arg[3], XtNlabel, "");
2802 XtSetArg (arg[4], XtNborderWidth, 0);
2803 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2804 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2805 FaceWidget, arg, 6);
2807 XtSetArg (arg[0], XtNborderWidth, 0);
2808 XtSetArg (arg[1], XtNleft, XawChainLeft);
2809 XtSetArg (arg[2], XtNright, XawChainLeft);
2810 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2812 MPlist *plist[11], *pl;
2815 for (i = 0; i < 11; i++) plist[i] = NULL;
2817 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2818 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2820 MSymbol sym = msymbol_exist (langname);
2824 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2826 char *name = msymbol_name (fullname);
2829 if (c >= 'A' && c <= 'Z')
2831 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2835 pl = plist[idx] = mplist ();
2836 for (; mplist_next (pl); pl = mplist_next (pl))
2837 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2839 mplist_push (pl, sym, fullname);
2844 for (i = 0; i < 11; i++)
2847 char *name = alloca (9);
2849 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2852 for (j = 0, pl = plist[i]; mplist_next (pl);
2853 j++, pl = mplist_next (pl))
2854 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2855 msymbol_name (mplist_key (pl)),
2856 LangProc, mplist_key (pl), -1);
2857 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2858 menus, j, "Push language property");
2860 for (i = 0; i < 11; i++)
2862 m17n_object_unref (plist[i]);
2864 XtSetArg (arg[0], XtNfromHoriz, w);
2865 XtSetArg (arg[1], XtNleft, XawChainLeft);
2866 XtSetArg (arg[2], XtNright, XawChainLeft);
2867 XtSetArg (arg[3], XtNhorizDistance, 10);
2868 XtSetArg (arg[4], XtNlabel, "Pop");
2869 XtSetArg (arg[5], XtNtranslations,
2870 XtParseTranslationTable (pop_lang_trans));
2871 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2872 LangWidget, arg, 6);
2873 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2875 XtSetArg (arg[0], XtNfromHoriz, w);
2876 XtSetArg (arg[1], XtNleft, XawChainLeft);
2877 XtSetArg (arg[2], XtNright, XawChainRight);
2878 XtSetArg (arg[3], XtNlabel, "");
2879 XtSetArg (arg[4], XtNborderWidth, 0);
2880 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2881 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2882 LangWidget, arg, 6);
2885 XtSetArg (arg[0], XtNheight, win_height);
2886 XtSetArg (arg[1], XtNwidth, 10);
2887 XtSetArg (arg[2], XtNleft, XawChainLeft);
2888 XtSetArg (arg[3], XtNright, XawChainLeft);
2889 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2891 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2892 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2894 XtSetArg (arg[0], XtNheight, win_height);
2895 XtSetArg (arg[1], XtNwidth, win_width);
2896 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2897 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2898 XtSetArg (arg[4], XtNleft, XawChainLeft);
2899 XtSetArg (arg[5], XtNright, XawChainRight);
2900 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2903 XtSetArg (arg[0], XtNborderWidth, 0);
2904 XtSetArg (arg[1], XtNleft, XawChainLeft);
2905 XtSetArg (arg[2], XtNright, XawChainRight);
2906 XtSetArg (arg[3], XtNresizable, True);
2907 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2908 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2909 TailWidget, arg, 5);
2911 memset (&control, 0, sizeof control);
2912 control.two_dimensional = 1;
2913 control.enable_bidi = 1;
2914 control.anti_alias = 1;
2915 control.min_line_ascent = font_ascent;
2916 control.min_line_descent = font_descent;
2917 control.max_line_width = win_width;
2918 control.with_cursor = 1;
2919 control.cursor_width = 2;
2920 control.partial_update = 1;
2921 control.ignore_formatting_char = 1;
2923 memset (&input_status_control, 0, sizeof input_status_control);
2924 input_status_control.enable_bidi = 1;
2926 XtAppAddActions (context, actions, XtNumber (actions));
2927 XtRealizeWidget (ShellWidget);
2929 win = XtWindow (TextWidget);
2931 XtAppMainLoop (context);
2933 if (current_input_context)
2934 minput_destroy_ic (current_input_context);
2935 for (i = 0; i < num_input_methods; i++)
2936 if (input_method_table[i].im)
2937 minput_close_im (input_method_table[i].im);
2938 m17n_object_unref (frame);
2939 m17n_object_unref (mt);
2940 m17n_object_unref (face_xxx_large);
2941 m17n_object_unref (face_box);
2942 m17n_object_unref (face_courier);
2943 m17n_object_unref (face_helvetica);
2944 m17n_object_unref (face_times);
2945 m17n_object_unref (face_dv_ttyogesh);
2946 m17n_object_unref (face_freesans);
2947 m17n_object_unref (face_freeserif);
2948 m17n_object_unref (face_freemono);
2949 m17n_object_unref (face_default_fontset);
2950 m17n_object_unref (face_no_ctl_fontset);
2951 m17n_object_unref (face_input_status);
2952 m17n_object_unref (face_default);
2953 m17n_object_unref (default_face_list);
2954 m17n_object_unref (selection);
2956 XFreeGC (display, mono_gc);
2957 XFreeGC (display, mono_gc_inv);
2958 XFreeGC (display, gc_inv);
2959 XtUninstallTranslations (form);
2960 XtUninstallTranslations (TextWidget);
2961 XtDestroyWidget (ShellWidget);
2962 XtDestroyApplicationContext (context);
2966 free (fontset_name);
2968 free (input_method_table);
2969 free (InputMethodMenus);
2973 #endif /* not FOR_DOXYGEN */