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.0.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.this.height;
338 top.ascent = - info.this.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.this.height = line->y1 - y;
386 info.this.y = - line->ascent;
387 info.line_to = line->to;
388 while (from < nchars && y + info.this.height <= y0)
390 y += info.this.height;
392 GLYPH_INFO (from, from, info);
394 y0 = y - info.this.y;
396 while (to < nchars && y < y1)
398 GLYPH_INFO (to, to, info);
399 y += info.this.height;
405 DRAW_TEXT (0, y0, from, to);
410 GLYPH_INFO (to, to, info);
411 if (y + info.this.height >= win_height)
414 y += info.this.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.this.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.this.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.this.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.this.y;
524 cur.from = cursor.line_from;
525 cur.to = cursor.line_to;
526 cur.y1 = cur.y0 + cursor.this.height;
527 cur.ascent = - cursor.this.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.this.y;
557 GLYPH_INFO (top.from, from, info);
558 sel_start.y0 = top.ascent + info.y + info.this.y;
560 sel_start.ascent = -info.this.y;
561 sel_start.y1 = sel_start.y0 + info.this.height;
562 sel_start.from = info.line_from;
563 sel_start.to = info.line_to;
565 if (to <= sel_start.to)
568 if (to >= sel_end.to)
570 GLYPH_INFO (sel_start.from, to, info);
571 sel_end.y1 = sel_end.y0 + info.y + info.this.height;
572 sel_end.to = info.line_to;
577 GLYPH_INFO (sel_start.from, to, info);
578 sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
579 sel_end.y1 = sel_end.y0 + info.this.height;
580 sel_end.ascent = - info.this.y;
581 sel_end.from = info.line_from;
582 sel_end.to = info.line_to;
587 /* Select the text in the region from $FROM to $TO. */
589 select_region (int from, int to)
594 pos = from, from = to, to = pos;
595 mtext_push_property (mt, from, to, selection);
600 /* Setup the window to display the character of $POS at the top left
606 /* Top and bottom Y positions to redraw. */
609 if (pos + 1000 < top.from)
610 y0 = 0, y1 = win_height;
611 else if (pos < top.from)
614 TEXT_EXTENTS (pos, top.from, rect);
615 if (rect.height >= win_height * 0.9)
620 COPY_AREA (0, win_height - y1, y1);
623 else if (pos < top.to)
625 /* No need of redrawing. */
628 else if (pos < top.from + 1000)
630 TEXT_EXTENTS (top.from, pos, rect);
631 if (rect.height >= win_height * 0.9)
635 y0 = win_height - rect.height;
636 COPY_AREA (rect.height, win_height, 0);
641 y0 = 0, y1 = win_height;
647 update_cursor (pos, 1);
649 update_cursor (cursor.from, 1);
651 redraw (y0, y1, 1, 1);
655 static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
658 /* Select an input method accoding to $IDX. If $IDX is negative, turn
659 off the current input method, otherwide turn on the input method
660 input_method_table[$IDX]. */
662 select_input_method (idx)
664 if (idx == current_input_method)
666 if (current_input_context)
668 minput_destroy_ic (current_input_context);
669 current_input_context = NULL;
670 current_input_method = -1;
674 InputMethodInfo *im = input_method_table + idx;
676 if (im->language == Mnil)
678 MInputXIMArgIC arg_xic;
679 Window win = XtWindow (TextWidget);
681 arg_xic.input_style = 0;
682 arg_xic.client_win = arg_xic.focus_win = win;
683 arg_xic.preedit_attrs = arg_xic.status_attrs = NULL;
684 current_input_context = minput_create_ic (im->im, &arg_xic);
688 MInputGUIArgIC arg_ic;
690 arg_ic.frame = frame;
691 arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
692 arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
693 current_input_context = minput_create_ic (im->im, &arg_ic);
696 if (current_input_context)
698 set_input_method_spot ();
699 current_input_method = idx;
702 if (current_input_method >= 0)
705 XtSetArg (arg[0], XtNlabel, &label);
706 XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
707 XtSetArg (arg[0], XtNlabel, label);
710 XtSetArg (arg[0], XtNlabel, "");
711 XtSetValues (CurIMLang, arg, 1);
714 static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
717 /* Display cursor according to the current information of #CUR.
718 $CLIENT_DATA is ignore. Most callback functions add this function
719 as a background processing procedure the current application (by
720 XtAppAddWorkProc) via the function hide_cursor. */
722 show_cursor (XtPointer client_data)
724 MFaceHLineProp *hline;
730 update_cursor (cursor.from, 1);
732 while (cur.y1 > win_height)
735 update_cursor (cursor.from, 1);
738 control.cursor_pos = cursor.from;
741 control.with_cursor = 1;
744 if (current_input_context)
745 set_input_method_spot ();
749 int pos = (SELECTEDP () ? mtext_property_start (selection)
750 : cursor.from > 0 ? cursor.from - 1
752 MFace *face = mface ();
753 MTextProperty *props[256];
754 int n = mtext_get_properties (mt, pos, Mface, props, 256);
756 char buf[256], *p = buf;
762 int size = (int) mfont_get_prop (cursor.font, Msize);
763 MSymbol family = mfont_get_prop (cursor.font, Mfamily);
764 MSymbol weight = mfont_get_prop (cursor.font, Mweight);
765 MSymbol style = mfont_get_prop (cursor.font, Mstyle);
766 MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
768 sprintf (p, "%dpt", size / 10), p += strlen (p);
770 strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
772 strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
774 strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
776 strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
780 mface_merge (face, face_default);
781 for (i = 0; i < n; i++)
782 if (props[i] != selection)
783 mface_merge (face, (MFace *) mtext_property_value (props[i]));
784 sym = (MSymbol) mface_get_prop (face, Mforeground);
786 strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
787 if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
788 strcat (p, ",rev"), p += strlen (p);
789 hline = mface_get_prop (face, Mhline);
790 if (hline && hline->width > 0)
791 strcat (p, ",ul"), p += strlen (p);
792 box = mface_get_prop (face, Mbox);
793 if (box && box->width > 0)
794 strcat (p, ",box"), p += strlen (p);
795 m17n_object_unref (face);
797 XtSetArg (arg[0], XtNborderWidth, 1);
798 XtSetArg (arg[1], XtNlabel, buf);
799 XtSetValues (CurFaceWidget, arg, 2);
802 if (control.cursor_pos < nchars)
806 if (control.cursor_pos > 0
807 && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
808 sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
810 sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
814 XtSetArg (arg[0], XtNborderWidth, 0);
815 XtSetArg (arg[1], XtNlabel, "");
819 XtSetArg (arg[0], XtNborderWidth, 1);
820 XtSetArg (arg[1], XtNlabel,
821 msymbol_name (msymbol_get (sym, Mlanguage)));
822 XtSetValues (CurLangWidget, arg, 2);
824 XtSetValues (CurLangWidget, arg, 2);
826 if (auto_input_method)
829 select_input_method (-1);
834 for (i = 0; i < num_input_methods; i++)
835 if (input_method_table[i].language == sym)
837 if (i < num_input_methods
838 && input_method_table[i].available >= 0)
840 if (! input_method_table[i].im)
842 input_method_table[i].im =
843 minput_open_im (input_method_table[i].language,
844 input_method_table[i].name, NULL);
845 if (! input_method_table[i].im)
846 input_method_table[i].available = -1;
848 if (input_method_table[i].im)
849 select_input_method (i);
851 select_input_method (-1);
854 select_input_method (-1);
859 MenuHelpProc (MessageWidget, NULL, NULL, NULL);
865 /* Hide the cursor. */
869 control.with_cursor = 0;
871 XtAppAddWorkProc (context, show_cursor, NULL);
875 /* Update the window area between the Y-positions $Y0 and $OLD_Y1 to
876 $Y1 and $NEW_Y1 assuming that the text in the other area is not
879 update_region (int y0, int old_y1, int new_y1)
885 if (old_y1 < win_height)
887 COPY_AREA (old_y1, win_height, new_y1);
888 redraw (win_height - (old_y1 - new_y1), win_height, 1, 0);
891 redraw (new_y1, win_height, 1, 0);
893 else if (new_y1 > old_y1)
895 if (new_y1 < win_height)
896 COPY_AREA (old_y1, win_height, new_y1);
898 if (new_y1 > win_height)
900 redraw (y0, new_y1, 1, 1);
904 /* Delete the next $N characters. If $N is negative delete the
905 precious (- $N) characters. */
915 from = cursor.from, to = from + n;
918 if (cursor.from == cur.from)
920 /* We are at the beginning of line. */
921 int pos = cursor.prev_from;
923 if (cursor.from == top.from)
925 /* We are at the beginning of screen. We must scroll
927 GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info);
928 reseat (info.line_from);
930 update_cursor (pos, 1);
936 from = cursor.from - 1;
941 TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect);
942 old_y1 = cur.y0 + rect.height;
944 /* Now delete a character. */
945 mtext_del (mt, from, to);
947 if (from >= top.from && from < top.to)
948 update_top (top.from);
949 update_cursor (from, 1);
951 TEXT_EXTENTS (cur.from, bol (to, 1), rect);
952 new_y1 = cur.y0 + rect.height;
954 update_region (cur.y0, old_y1, new_y1);
958 /* Insert M-text $NEWTEXT at the current cursor position. */
960 insert_chars (MText *newtext)
962 int n = mtext_len (newtext);
964 int y0, old_y1, new_y1;
968 int n = (mtext_property_end (selection)
969 - mtext_property_start (selection));
970 mtext_detach_property (selection);
975 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
976 old_y1 = y0 + rect.height;
978 /* Now insert chars. */
979 mtext_ins (mt, cursor.from, newtext);
981 if (cur.from == top.from)
982 update_top (top.from);
983 update_cursor (cursor.from + n, 1);
985 TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
986 new_y1 = cur.y0 + rect.height;
988 update_region (y0, old_y1, new_y1);
993 /* Convert the currently selected text to UTF8-STRING or
994 COMPOUND-TEXT. It is called when someone requests the current
995 value of the selection. */
997 covert_selection (Widget w, Atom *selection_atom,
998 Atom *target, Atom *return_type,
999 XtPointer *value, unsigned long *length, int *format)
1001 unsigned char *buf = (unsigned char *) XtMalloc (4096);
1002 MText *this_mt = mtext ();
1003 int from = mtext_property_start (selection);
1004 int to = mtext_property_end (selection);
1007 mtext_copy (this_mt, 0, mt, from, to);
1008 if (*target == XA_TEXT)
1010 #ifdef X_HAVE_UTF8_STRING
1011 coding = Mcoding_utf_8;
1012 *return_type = XA_UTF8_STRING;
1014 coding = Mcoding_compound_text;
1015 *return_type = XA_COMPOUND_TEXT;
1018 else if (*target == XA_STRING)
1020 int len = to - from;
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;
1035 *length = mconv_encode_buffer (coding, this_mt, buf, 4096);
1036 m17n_object_unref (this_mt);
1039 *value = (XtPointer) buf;
1045 /* Unselect the text. It is called when we loose the selection. */
1047 lose_selection (Widget w, Atom *selection_atom)
1051 mtext_detach_property (selection);
1052 redraw (sel_start.y0, sel_end.y1, 1, 0);
1057 get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type,
1058 XtPointer value, unsigned long *length, int *format)
1063 if (*type == XT_CONVERT_FAIL || ! value)
1065 if (*type == XA_STRING)
1067 else if (*type == XA_COMPOUND_TEXT)
1068 coding = msymbol ("compound-text");
1069 #ifdef X_HAVE_UTF8_STRING
1070 else if (*type == XA_UTF8_STRING)
1071 coding = msymbol ("utf-8");
1076 this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
1077 if (! this_mt && *type != XA_UTF8_STRING)
1079 XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
1086 insert_chars (this_mt);
1087 m17n_object_unref (this_mt);
1096 ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
1098 XExposeEvent *expose = (XExposeEvent *) event;
1102 Dimension width_max, width;
1104 XtSetArg (arg[0], XtNwidth, &width);
1105 XtGetValues (XtParent (w), arg, 1);
1107 XtGetValues (HeadWidget, arg, 1);
1108 if (width_max < width)
1110 XtGetValues (FaceWidget, arg, 1);
1111 if (width_max < width)
1113 XtGetValues (LangWidget, arg, 1);
1114 if (width_max < width)
1116 XtSetArg (arg[0], XtNwidth, width_max);
1117 XtSetValues (HeadWidget, arg, 1);
1118 XtSetValues (FaceWidget, arg, 1);
1119 XtSetValues (LangWidget, arg, 1);
1120 XtSetValues (XtParent (w), arg, 1);
1121 XtSetValues (TailWidget, arg, 1);
1124 update_cursor (0, 1);
1125 redraw (0, win_height, 0, 1);
1130 redraw (expose->y, expose->y + expose->height, 0, 0);
1131 if (current_input_context
1132 && expose->y < cur.y0 && expose->y + expose->height < cur.y1)
1133 set_input_method_spot ();
1138 ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num)
1140 XConfigureEvent *configure = (XConfigureEvent *) event;
1143 control.max_line_width = win_width = configure->width;
1144 win_height = configure->height;
1145 mdraw_clear_cache (mt);
1147 update_cursor (0, 1);
1148 redraw (0, win_height, 1, 1);
1149 if (current_input_context)
1150 set_input_method_spot ();
1154 ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
1157 int x = event->xbutton.x;
1158 int y = event->xbutton.y - top.ascent;
1160 if (control.orientation_reversed)
1162 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1165 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1166 mtext_detach_property (selection);
1167 redraw (sel_start.y0, sel_end.y1, 1, 0);
1170 update_cursor (pos, 0);
1175 ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num)
1180 XtOwnSelection (w, XA_PRIMARY, CurrentTime,
1181 covert_selection, lose_selection, NULL);
1182 update_cursor (mtext_property_start (selection), 0);
1187 Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num)
1191 /* We don't have a local selection. */
1192 XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL,
1197 int from = mtext_property_start (selection);
1198 int to = mtext_property_end (selection);
1201 int x = event->xbutton.x;
1202 int y = event->xbutton.y - top.ascent;
1204 if (control.orientation_reversed)
1206 pos = COORDINATES_POSITION (top.from, nchars + 1, x, y);
1208 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1209 mtext_detach_property (selection);
1211 this_mt = mtext_copy (mtext (), 0, mt, from, to);
1212 update_cursor (pos, 0);
1213 insert_chars (this_mt);
1214 m17n_object_unref (this_mt);
1219 ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
1222 int x = event->xbutton.x;
1223 int y = event->xbutton.y;
1225 if (control.orientation_reversed)
1228 pos = top.from, y -= top.ascent;
1230 pos = cur.from, y -= cur.y0 + cur.ascent;
1231 pos = COORDINATES_POSITION (pos, nchars + 1, x, y);
1233 if (pos == cursor.from)
1239 /* Selection range changed. */
1240 int from = mtext_property_start (selection);
1241 int to = mtext_property_end (selection);
1242 int start_y0 = sel_start.y0, start_y1 = sel_start.y1;
1243 int end_y0 = sel_end.y0, end_y1 = sel_end.y1;
1245 if (cursor.from == from)
1247 /* Starting position changed. */
1250 /* Enlarged. We can simply overdraw. */
1251 select_region (pos, to);
1252 redraw (sel_start.y0, start_y1, 0, 0);
1256 /* Shrunken. Previous selection face must be cleared. */
1257 select_region (pos, to);
1258 redraw (start_y0, sel_start.y1, 1, 0);
1262 /* Shrunken to zero. */
1263 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1264 mtext_detach_property (selection);
1265 redraw (start_y0, end_y1, 1, 0);
1269 /* Full update is necessary. */
1270 select_region (to, pos);
1271 redraw (start_y0, sel_end.y1, 1, 0);
1276 /* Ending position changed. */
1279 /* Full update is necessary. */
1280 select_region (pos, from);
1281 redraw (sel_start.y0, end_y1, 1, 0);
1283 else if (pos == from)
1285 /* Shrunken to zero. */
1286 XtDisownSelection (w, XA_PRIMARY, CurrentTime);
1287 mtext_detach_property (selection);
1288 redraw (start_y0, end_y1, 1, 0);
1292 /* Shrunken. Previous selection face must be cleared. */
1293 select_region (from, pos);
1294 redraw (sel_end.y0, end_y1, 1, 0);
1298 /* Enlarged. We can simply overdraw. */
1299 select_region (from, pos);
1300 redraw (end_y0, sel_end.y1, 0, 0);
1306 /* Newly selected. */
1307 select_region (pos, cursor.from);
1308 redraw (sel_start.y0, sel_end.y1, 0, 0);
1310 update_cursor (pos, 1);
1314 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
1317 MDrawGlyphInfo info;
1319 int cursor_pos = cursor.from;
1321 if (((int) position) < 0)
1327 height = top.y1 - top.y0;
1330 pos = bol (from - 1, 0);
1331 GLYPH_INFO (pos, from - 1, info);
1332 if (height + info.this.height > win_height)
1334 height += info.this.height;
1335 from = info.line_from;
1337 if (cursor_pos >= top.to)
1339 cursor_pos = top.from;
1341 while (cursor_pos < nchars)
1343 GLYPH_INFO (pos, pos, info);
1344 if (height + info.this.height > win_height)
1346 height += info.this.height;
1352 else if (cur.to < nchars)
1354 /* Scroll up, but leave at least one line. */
1357 while (from < nchars)
1359 GLYPH_INFO (from, from, info);
1360 if (height + info.this.height > win_height
1361 || info.line_to >= nchars)
1363 height += info.this.height;
1364 from = info.line_to;
1367 from = info.line_from;
1368 if (cursor_pos < from)
1372 /* Scroll up to make the cursor line top. */
1376 update_cursor (cursor_pos, 1);
1380 JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
1382 float persent = *(float *) persent_ptr;
1383 int pos1, pos2 = nchars * persent;
1384 MDrawGlyphInfo info;
1387 pos1 = bol (pos2, 0);
1388 GLYPH_INFO (pos1, pos2, info);
1389 pos1 = info.line_from;
1391 update_cursor (pos1, 1);
1396 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
1398 XKeyEvent *key_event = (XKeyEvent *) event;
1400 KeySym keysym = NoSymbol;
1402 /* If set to 1, do not update target_x_position. */
1403 int keep_target_x_position = 0;
1406 if (current_input_context
1407 && minput_filter (current_input_context, Mnil, event))
1409 if (event->type == KeyRelease)
1414 produced = mtext ();
1415 ret = minput_lookup (current_input_context, Mnil, event, produced);
1416 if (mtext_len (produced) > 0)
1417 insert_chars (produced);
1419 ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
1420 m17n_object_unref (produced);
1430 n = (mtext_property_end (selection)
1431 - mtext_property_start (selection));
1432 mtext_detach_property (selection);
1434 else if (cursor.from < nchars)
1436 /* Delete the following grapheme cluster. */
1437 n = cursor.to - cursor.from;
1450 /* Delete selected region. */
1451 n = (mtext_property_end (selection)
1452 - mtext_property_start (selection));
1453 mtext_detach_property (selection);
1455 else if (cursor.from > 0)
1457 /* Delete the preceding character. */
1468 mtext_detach_property (selection);
1469 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1473 if (cursor.prev_from >= 0)
1474 update_cursor (cursor.prev_from, 0);
1478 if (cursor.left_from >= 0)
1479 update_cursor (cursor.left_from, 0);
1486 mtext_detach_property (selection);
1487 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1491 if (cursor.next_to >= 0)
1492 update_cursor (cursor.to, 0);
1496 if (cursor.right_from >= 0)
1497 update_cursor (cursor.right_from, 0);
1504 mtext_detach_property (selection);
1505 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1507 if (cur.to <= nchars)
1509 MDrawGlyphInfo info;
1512 GLYPH_INFO (cur.from, cur.to, info);
1513 pos = COORDINATES_POSITION (cur.from, nchars + 1,
1514 target_x_position, info.y);
1515 keep_target_x_position = 1;
1516 update_cursor (pos, 0);
1523 mtext_detach_property (selection);
1524 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1530 int pos = bol (cur.from - 1, 0);
1532 TEXT_EXTENTS (pos, cur.from - 1, rect);
1533 y = rect.height + rect.y - 1;
1534 pos = COORDINATES_POSITION (pos, nchars,
1535 target_x_position, y);
1536 keep_target_x_position = 1;
1537 update_cursor (pos, 0);
1544 mtext_detach_property (selection);
1545 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1547 if (top.from < nchars)
1548 ScrollProc (w, NULL, (XtPointer) 1);
1554 mtext_detach_property (selection);
1555 redraw (sel_start.y0, sel_end.y1, 1, 0);;
1558 ScrollProc (w, NULL, (XtPointer) -1);
1564 if (buf[0] == 17) /* C-q */
1566 XtAppSetExitFlag (context);
1569 else if (buf[0] == 12) /* C-l */
1571 redraw (0, win_height, 1, 1);
1576 MText *temp = mtext ();
1578 mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
1579 if (current_input_context)
1580 mtext_put_prop (temp, 0, 1, Mlanguage,
1581 current_input_context->im->language);
1582 insert_chars (temp);
1583 m17n_object_unref (temp);
1588 if (! keep_target_x_position)
1589 target_x_position = cursor.x;
1593 SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
1595 char *name = (char *) client_data;
1597 int from = -1, to = 0;
1602 filename = strdup (name);
1605 fp = fopen (filename, "w");
1608 fprintf (stderr, "Open for write fail: %s", filename);
1614 from = mtext_property_start (selection);
1615 to = mtext_property_end (selection);
1616 mtext_detach_property (selection);
1619 mconv_encode_stream (Mcoding_utf_8, mt, fp);
1622 select_region (from, to);
1626 SerializeProc (Widget w, XtPointer client_data, XtPointer call_data)
1632 mtext_detach_property (selection);
1633 serialized = (int) client_data;
1635 new = mtext_deserialize (mt);
1638 MPlist *plist = mplist ();
1640 mplist_push (plist, Mt, Mface);
1641 mplist_push (plist, Mt, Mlanguage);
1642 new = mtext_serialize (mt, 0, mtext_len (mt), plist);
1643 m17n_object_unref (plist);
1647 m17n_object_unref (mt);
1649 serialized = ! serialized;
1650 nchars = mtext_len (mt);
1653 update_cursor (0, 1);
1654 redraw (0, win_height, 1, 1);
1658 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
1660 XtAppSetExitFlag (context);
1666 FILE *fp = fopen (filename, "r");
1669 FATAL_ERROR ("Can't read \"%s\"!\n", filename);
1670 mt = mconv_decode_stream (Mcoding_utf_8, fp);
1673 FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
1678 BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
1680 int data = (int) client_data;
1685 control.enable_bidi = 0;
1686 control.orientation_reversed = 0;
1690 control.enable_bidi = 1;
1691 control.orientation_reversed = data == 2;
1693 for (i = 0; i < 3; i++)
1696 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1698 XtSetArg (arg[0], XtNleftBitmap, None);
1699 XtSetValues (BidiMenus[i], arg, 1);
1702 update_cursor (cursor.from, 1);
1703 redraw (0, win_height, 1, 0);
1706 extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
1709 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
1711 int data = (int) client_data;
1715 control.max_line_width = 0;
1718 control.max_line_width = win_width;
1719 control.line_break = (data == 1 ? NULL : line_break);
1721 for (i = 0; i < 3; i++)
1724 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1726 XtSetArg (arg[0], XtNleftBitmap, None);
1727 XtSetValues (LineBreakMenus[i], arg, 1);
1730 update_cursor (cursor.from, 1);
1731 redraw (0, win_height, 1, 0);
1735 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
1737 int data = (int) client_data;
1751 control.cursor_bidi = 0, control.cursor_width = -1;
1755 control.cursor_bidi = 0, control.cursor_width = 2;
1759 control.cursor_bidi = 1;
1764 for (i = from; i < to; i++)
1767 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1769 XtSetArg (arg[0], XtNleftBitmap, None);
1770 XtSetValues (CursorMenus[i], arg, 1);
1773 update_cursor (cursor.from, 0);
1774 redraw (0, win_height, 1, 0);
1778 InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
1780 int idx = (int) client_data;
1782 if (idx == -2 ? current_input_method < 0
1783 : idx == -1 ? auto_input_method
1784 : idx == current_input_method)
1787 XtSetArg (arg[0], XtNleftBitmap, None);
1788 if (auto_input_method)
1790 XtSetValues (InputMethodMenus[1], arg, 1);
1791 auto_input_method = 0;
1793 else if (current_input_method < 0)
1794 XtSetValues (InputMethodMenus[0], arg, 1);
1796 XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
1800 auto_input_method = 1;
1803 else if (input_method_table[idx].available >= 0)
1805 if (! input_method_table[idx].im)
1807 input_method_table[idx].im =
1808 minput_open_im (input_method_table[idx].language,
1809 input_method_table[idx].name, NULL);
1810 if (! input_method_table[idx].im)
1811 input_method_table[idx].available = -1;
1813 if (input_method_table[idx].im)
1814 select_input_method (idx);
1816 XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
1817 XtSetValues (InputMethodMenus[idx + 2], arg, 1);
1820 MPlist *default_face_list;
1823 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
1825 int idx = (int) client_data;
1835 MFace *face = mframe_get_prop (frame, Mface);
1837 for (plist = default_face_list; mplist_key (plist) != Mnil;
1838 plist = mplist_next (plist))
1839 mface_merge (face, mplist_value (plist));
1840 mplist_add (plist, Mt, *face_table[idx].face);
1841 mface_merge (face, *face_table[idx].face);
1843 else if (mplist_key (mplist_next (default_face_list)) != Mnil)
1845 MFace *face = mframe_get_prop (frame, Mface);
1847 for (plist = default_face_list;
1848 mplist_key (mplist_next (plist)) != Mnil;
1849 plist = mplist_next (plist))
1850 mface_merge (face, mplist_value (plist));
1854 update_cursor (0, 1);
1855 redraw (0, win_height, 1, 1);
1860 XtAppAddWorkProc (context, show_cursor, NULL);
1861 from = mtext_property_start (selection);
1862 to = mtext_property_end (selection);
1863 old_y1 = sel_end.y1;
1865 mtext_detach_property (selection);
1868 MTextProperty *prop = mtext_property (Mface, *face_table[idx].face,
1869 MTEXTPROP_REAR_STICKY);
1870 mtext_push_property (mt, from, to, prop);
1871 m17n_object_unref (prop);
1874 mtext_pop_prop (mt, from, to, Mface);
1876 update_top (top.from);
1877 update_cursor (cursor.from, 1);
1878 select_region (from, to);
1879 update_region (sel_start.y0, old_y1, sel_end.y1);
1880 if (cur.y1 > win_height)
1882 while (cur.y1 > win_height)
1885 update_cursor (cursor.from, 1);
1891 LangProc (Widget w, XtPointer client_data, XtPointer call_data)
1893 MSymbol sym = (MSymbol) client_data;
1900 XtAppAddWorkProc (context, show_cursor, NULL);
1901 from = mtext_property_start (selection);
1902 to = mtext_property_end (selection);
1903 old_y1 = sel_end.y1;
1905 mtext_detach_property (selection);
1907 mtext_put_prop (mt, from, to, Mlanguage, sym);
1909 mtext_pop_prop (mt, from, to, Mlanguage);
1912 update_top (top.from);
1913 update_cursor (cursor.from, 1);
1914 select_region (from, to);
1915 update_region (sel_start.y0, old_y1, sel_end.y1);
1916 if (cur.y1 > win_height)
1918 while (cur.y1 > win_height)
1921 update_cursor (cursor.from, 1);
1927 DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
1929 int narrowed = (int) client_data;
1932 MConverter *converter;
1938 from = mtext_property_start (selection);
1939 to = mtext_property_end (selection);
1948 mdump = popen ("mdump -q -p a4", "w");
1950 mdump = popen ("mdump -q", "w");
1953 converter = mconv_stream_converter (Mcoding_utf_8, mdump);
1954 mconv_encode_range (converter, mt, from, to);
1955 mconv_free_converter (converter);
1960 input_status (MInputContext *ic, MSymbol command)
1962 XFillRectangle (display, input_status_pixmap, gc_inv,
1963 0, 0, input_status_width, input_status_height);
1964 if (command == Minput_status_draw)
1968 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1969 Mface, face_input_status);
1970 if (ic->im->language != Mnil)
1971 mtext_put_prop (ic->status, 0, mtext_len (ic->status),
1972 Mlanguage, ic->im->language);
1973 mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status),
1974 &input_status_control, NULL, NULL, &rect);
1975 mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap,
1976 input_status_width - rect.width - 2, - rect.y,
1977 ic->status, 0, mtext_len (ic->status),
1978 &input_status_control);
1980 XtSetArg (arg[0], XtNbitmap, input_status_pixmap);
1981 XtSetValues (CurIMStatus, arg, 1);
1985 compare_input_method (const void *elt1, const void *elt2)
1987 const InputMethodInfo *im1 = elt1;
1988 const InputMethodInfo *im2 = elt2;
1989 MSymbol lang1, lang2;
1991 if (im1->language == Mnil)
1993 if (im1->language == im2->language)
1994 return strcmp (msymbol_name (im1->name), msymbol_name (im2->name));
1995 if (im1->language == Mt)
1997 if (im2->language == Mt)
1999 lang1 = msymbol_get (im1->language, Mlanguage);
2000 lang2 = msymbol_get (im2->language, Mlanguage);
2001 return strcmp (msymbol_name (lang1), msymbol_name (lang2));
2005 setup_input_methods (int with_xim)
2007 MInputMethod *im = NULL;
2008 MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
2012 num_input_methods = mplist_length (plist);
2016 MInputXIMArgIM arg_xim;
2018 arg_xim.display = display;
2020 arg_xim.res_name = arg_xim.res_class = NULL;
2021 arg_xim.locale = NULL;
2022 arg_xim.modifier_list = NULL;
2023 im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
2025 num_input_methods++;
2027 input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
2030 input_method_table[i].available = 1;
2031 input_method_table[i].language = Mnil;
2032 input_method_table[i].name = im->name;
2033 input_method_table[i].im = im;
2037 for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
2039 MDatabase *mdb = mplist_value (pl);
2040 MSymbol *tag = mdatabase_tag (mdb);
2044 input_method_table[i].language = tag[1];
2045 input_method_table[i].name = tag[2];
2050 m17n_object_unref (plist);
2051 num_input_methods = i;
2052 qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
2053 compare_input_method);
2054 current_input_context = NULL;
2056 mplist_put (minput_driver->callback_list, Minput_status_start,
2057 (void *) input_status);
2058 mplist_put (minput_driver->callback_list, Minput_status_draw,
2059 (void *) input_status);
2060 mplist_put (minput_driver->callback_list, Minput_status_done,
2061 (void *) input_status);
2066 MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num)
2070 if (num && *num > 0)
2074 for (i = 0; i < *num; i++)
2075 bytes += strlen (str[i]) + 1;
2076 msg = alloca (bytes);
2077 strcpy (msg, str[0]);
2078 for (i = 1; i < *num; i++)
2079 strcat (msg, " "), strcat (msg, str[i]);
2081 else if (cursor.from < nchars)
2083 int c = mtext_ref_char (mt, cursor.from);
2084 char *name = mchar_get_prop (c, Mname);
2088 msg = alloca (10 + strlen (name));
2089 sprintf (msg, "U+%04X %s", c, name);
2095 XtSetArg (arg[0], XtNlabel, msg);
2096 XtSetValues (MessageWidget, arg, 1);
2102 char *name1, *name2;
2103 XtCallbackProc proc;
2104 XtPointer client_data;
2109 void PopupProc (Widget w, XtPointer client_data, XtPointer call_data);
2111 void SaveProc (Widget w, XtPointer client_data, XtPointer call_data);
2113 MenuRec FileMenu[] =
2114 { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 },
2115 { 0, "Save", NULL, SaveProc, NULL, -1 },
2116 { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 },
2118 { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 },
2119 { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 },
2121 { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 },
2122 { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 },
2124 { 0, "Quit", NULL, QuitProc, NULL, -1 } };
2127 PopupProc (Widget w, XtPointer client_data, XtPointer call_data)
2129 MenuRec *rec = (MenuRec *) client_data;
2132 XtSetArg (arg[0], XtNvalue, "");
2133 XtSetArg (arg[1], XtNlabel, rec->name1);
2134 XtSetValues (FileDialogWidget, arg, 2);
2135 XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y);
2136 XtSetArg (arg[0], XtNx, x + 20);
2137 XtSetArg (arg[1], XtNy, y + 10);
2138 XtSetValues (FileShellWidget, arg, 2);
2139 XtPopup (FileShellWidget, XtGrabExclusive);
2143 FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
2148 XtPopdown (FileShellWidget);
2149 if ((int) client_data == 1)
2151 XtSetArg (arg[0], XtNlabel, &label);
2152 XtGetValues (FileDialogWidget, arg, 1);
2153 if (strcmp (label, FileMenu[0].name1) == 0)
2157 filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget));
2158 fp = fopen (filename, "r");
2160 m17n_object_unref (mt);
2163 mt = mconv_decode_stream (Mcoding_utf_8, fp);
2171 nchars = mtext_len (mt);
2173 update_cursor (0, 1);
2174 redraw (0, win_height, 1, 1);
2176 else if (strcmp (label, FileMenu[2].name1) == 0)
2177 SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL);
2179 fprintf (stderr, "Invalid calling sequence: FileDialogProc\n");
2182 #define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \
2183 ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \
2184 (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \
2185 (MENU).status = (STATUS))
2189 create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
2190 char *menu_name, MenuRec *menus, int num_menus, char *help)
2192 Widget button, menu;
2193 char *fmt = "<EnterWindow>: highlight() MenuHelp(%s)\n\
2194 <LeaveWindow>: reset() MenuHelp()\n\
2195 <BtnDown>: reset() PopupMenu()\n\
2196 <BtnUp>: highlight()";
2202 menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0);
2203 for (i = 0; i < num_menus; i++)
2214 XtSetArg (arg[n], XtNleftMargin, 20), n++;
2216 XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++;
2218 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2220 XtAddCallback (m->w, XtNcallback, m->proc, m->client_data);
2224 XtSetArg (arg[0], XtNsensitive, False);
2225 m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass,
2231 XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0);
2236 trans = alloca (strlen (fmt) + strlen (help));
2237 sprintf (trans, fmt, help);
2238 XtSetArg (arg[0], XtNmenuName, menu_name);
2239 XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans));
2240 XtSetArg (arg[2], XtNinternalWidth, 2);
2241 XtSetArg (arg[3], XtNhighlightThickness, 1);
2242 XtSetArg (arg[4], XtNleft, XawChainLeft);
2243 XtSetArg (arg[5], XtNright, XawChainLeft);
2246 XtSetArg (arg[i], XtNfromHoriz, left), i++;
2247 button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
2252 int height, ascent, *width = alloca (sizeof (int) * num_menus);
2253 int *len = alloca (sizeof (int) * num_menus);
2256 XFontSetExtents *fontset_extents;
2258 XtSetArg (arg[0], XtNfontSet, &font_set);
2259 XtGetValues (button, arg, 1);
2261 fontset_extents = XExtentsOfFontSet (font_set);
2262 height = fontset_extents->max_logical_extent.height;
2263 ascent = - fontset_extents->max_logical_extent.y;
2265 for (i = 0; i < num_menus; i++)
2268 len[i] = strlen (menus[i].name2);
2269 width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]);
2270 if (max_width < width[i])
2271 max_width = width[i];
2273 for (i = 0; i < num_menus; i++)
2276 Pixmap pixmap = XCreatePixmap (display,
2277 RootWindow (display, screen),
2278 max_width, height, 1);
2279 XFillRectangle (display, pixmap, mono_gc_inv,
2280 0, 0, max_width, height);
2281 XmbDrawString (display, pixmap, font_set, mono_gc,
2282 max_width - width[i], ascent,
2283 menus[i].name2, len[i]);
2284 XtSetArg (arg[0], XtNrightBitmap, pixmap);
2285 XtSetArg (arg[1], XtNrightMargin, max_width + 20);
2286 XtSetValues (menus[i].w, arg, 2);
2294 XtActionsRec actions[] = {
2295 {"Expose", ExposeProc},
2296 {"Configure", ConfigureProc},
2298 {"ButtonPress", ButtonProc},
2299 {"ButtonRelease", ButtonReleaseProc},
2300 {"ButtonMotion", ButtonMoveProc},
2301 {"Button2Press", Button2Proc},
2302 {"MenuHelp", MenuHelpProc}
2306 /* Print the usage of this program (the name is PROG), and exit with
2310 help_exit (char *prog, int exit_code)
2318 printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog);
2319 printf ("Display FILE on a window and allow users to edit it.\n");
2320 printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
2321 printf ("The following OPTIONs are available.\n");
2322 printf (" %-13s %s", "--version", "print version number\n");
2323 printf (" %-13s %s", "-h, --help", "print this message\n");
2328 main (int argc, char **argv)
2330 Widget form, BodyWidget, w;
2331 char *fontset_name = NULL;
2332 int col = 80, row = 32;
2333 /* Translation table for TextWidget. */
2334 String trans = "<Expose>: Expose()\n\
2335 <Configure>: Configure()\n\
2338 <Btn1Down>: ButtonPress()\n\
2339 <Btn1Up>: ButtonRelease()\n\
2340 <Btn1Motion>: ButtonMotion()\n\
2341 <Btn2Down>: Button2Press()";
2342 /* Translation table for the top form widget. */
2343 String trans2 = "<Key>: Key()\n\
2345 String pop_face_trans
2346 = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
2347 <LeaveWindow>: MenuHelp() reset()\n\
2348 <Btn1Down>: set()\n\
2349 <Btn1Up>: notify() unset()";
2350 String pop_lang_trans
2351 = "<EnterWindow>: MenuHelp(Pop language property) highlight()\n\
2352 <LeaveWindow>: MenuHelp() reset()\n\
2353 <Btn1Down>: set()\n\
2354 <Btn1Up>: notify() unset()";
2355 int font_width, font_ascent, font_descent;
2359 setlocale (LC_ALL, "");
2360 /* Create the top shell. */
2361 XtSetLanguageProc (NULL, NULL, NULL);
2362 ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
2363 NULL, sessionShellWidgetClass, NULL, 0);
2364 display = XtDisplay (ShellWidget);
2365 screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
2367 /* Parse the remaining command line arguments. */
2368 for (i = 1; i < argc; i++)
2370 if (! strcmp (argv[i], "--help")
2371 || ! strcmp (argv[i], "-h"))
2372 help_exit (argv[0], 0);
2373 else if (! strcmp (argv[i], "--version"))
2375 printf ("medit (m17n library) %s\n", VERSION);
2376 printf ("Copyright (C) 2003 AIST, JAPAN\n");
2379 else if (! strcmp (argv[i], "--geometry"))
2382 if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
2383 help_exit (argv[0], 1);
2385 else if (! strcmp (argv[i], "--fontset"))
2388 fontset_name = strdup (argv[i]);
2390 else if (! strcmp (argv[i], "--with-xim"))
2394 else if (argv[i][0] != '-')
2396 filename = strdup (argv[i]);
2400 fprintf (stderr, "Unknown option: %s", argv[i]);
2401 help_exit (argv[0], 1);
2405 help_exit (argv[0], 1);
2407 mdatabase_dir = ".";
2408 /* Initialize the m17n library. */
2410 if (merror_code != MERROR_NONE)
2411 FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
2413 mt = read_file (filename);
2416 nchars = mtext_len (mt);
2419 MFace *face = mface ();
2421 mface_put_prop (face, Mforeground, msymbol ("blue"));
2422 mface_put_prop (face, Mbackground, msymbol ("yellow"));
2423 mface_put_prop (face, Mvideomode, Mreverse);
2424 selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
2425 m17n_object_unref (face);
2428 /* This tells ExposeProc to initialize everything. */
2431 XA_TEXT = XInternAtom (display, "TEXT", False);
2432 XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
2433 XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
2434 Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
2435 if (Mcoding_compound_text == Mnil)
2436 FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
2439 MPlist *plist = mplist ();
2443 mplist_put (plist, msymbol ("widget"), ShellWidget);
2446 MFontset *fontset = mfontset (fontset_name);
2449 mface_put_prop (face, Mfontset, fontset);
2450 m17n_object_unref (fontset);
2451 mplist_add (plist, Mface, face);
2452 m17n_object_unref (face);
2454 frame = mframe (plist);
2456 FATAL_ERROR ("%s\n", "Fail to create a frame!");
2457 m17n_object_unref (plist);
2458 face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
2459 default_face_list = mplist ();
2460 mplist_add (default_face_list, Mt, face_default);
2461 face_default_fontset = mface ();
2462 mface_put_prop (face_default_fontset, Mfontset,
2463 mface_get_prop (face_default, Mfontset));
2465 font = (MFont *) mframe_get_prop (frame, Mfont);
2466 default_font_size = (int) mfont_get_prop (font, Msize);
2469 font_width = (int) mframe_get_prop (frame, Mfont_width);
2470 font_ascent = (int) mframe_get_prop (frame, Mfont_ascent);
2471 font_descent = (int) mframe_get_prop (frame, Mfont_descent);
2472 win_width = font_width * col;
2473 win_height = (font_ascent + font_descent) * row;
2479 prop.color_top = prop.color_left = msymbol ("magenta");
2480 prop.color_bottom = prop.color_right = msymbol ("red");
2481 prop.inner_hmargin = prop.inner_vmargin = 1;
2482 prop.outer_hmargin = prop.outer_vmargin = 2;
2484 face_box = mface ();
2485 mface_put_prop (face_box, Mbox, &prop);
2488 face_courier = mface ();
2489 mface_put_prop (face_courier, Mfamily, msymbol ("courier"));
2490 face_helvetica = mface ();
2491 mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica"));
2492 face_times = mface ();
2493 mface_put_prop (face_times, Mfamily, msymbol ("times"));
2494 face_dv_ttyogesh = mface ();
2495 mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
2496 face_freesans = mface ();
2497 mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
2498 face_freeserif = mface ();
2499 mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
2500 face_freemono = mface ();
2501 mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
2503 face_xxx_large = mface ();
2504 mface_put_prop (face_xxx_large, Mratio, (void *) 300);
2506 MFont *latin_font = mframe_get_prop (frame, Mfont);
2507 MFont *dev_font = mfont ();
2508 MFont *thai_font = mfont ();
2509 MFont *tib_font = mfont ();
2511 MSymbol unicode_bmp = msymbol ("unicode-bmp");
2512 MSymbol no_ctl = msymbol ("no-ctl");
2514 mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi"));
2515 mfont_put_prop (dev_font, Mregistry, unicode_bmp);
2516 mfont_put_prop (thai_font, Mfamily, msymbol ("norasi"));
2517 mfont_put_prop (thai_font, Mregistry, unicode_bmp);
2518 mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
2519 mfont_put_prop (tib_font, Mregistry, unicode_bmp);
2521 fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
2522 mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
2523 latin_font, Mnil, 0);
2524 mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
2525 dev_font, no_ctl, 0);
2526 mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
2527 thai_font, no_ctl, 0);
2528 mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
2529 tib_font, no_ctl, 0);
2530 face_no_ctl_fontset = mface ();
2531 mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
2532 m17n_object_unref (fontset);
2539 setup_input_methods (with_xim);
2541 gc = DefaultGC (display, screen);
2543 XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2));
2544 XtSetArg (arg[1], XtNdefaultDistance, 2);
2545 form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2);
2547 XtSetArg (arg[0], XtNborderWidth, 0);
2548 XtSetArg (arg[1], XtNdefaultDistance, 2);
2549 XtSetArg (arg[2], XtNtop, XawChainTop);
2550 XtSetArg (arg[3], XtNbottom, XawChainTop);
2551 XtSetArg (arg[4], XtNleft, XawChainLeft);
2552 XtSetArg (arg[5], XtNright, XawChainRight);
2553 XtSetArg (arg[6], XtNresizable, True);
2554 HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7);
2555 XtSetArg (arg[7], XtNfromVert, HeadWidget);
2556 FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8);
2557 XtSetArg (arg[7], XtNfromVert, FaceWidget);
2558 LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8);
2559 XtSetArg (arg[3], XtNbottom, XawChainBottom);
2560 XtSetArg (arg[7], XtNfromVert, LangWidget);
2561 BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8);
2562 XtSetArg (arg[2], XtNtop, XawChainBottom);
2563 XtSetArg (arg[7], XtNfromVert, BodyWidget);
2564 TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8);
2566 FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass,
2567 HeadWidget, NULL, 0);
2568 XtSetArg (arg[0], XtNvalue, "");
2569 FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass,
2570 FileShellWidget, arg, 1);
2571 XawDialogAddButton (FileDialogWidget, "OK",
2572 FileDialogProc, (XtPointer) 0);
2573 XawDialogAddButton (FileDialogWidget, "CANCEL",
2574 FileDialogProc, (XtPointer) 1);
2576 CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen),
2577 (char *) check_bits,
2578 check_width, check_height);
2580 unsigned long valuemask = GCForeground;
2583 values.foreground = 1;
2584 mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values);
2585 values.foreground = 0;
2586 mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values);
2593 if (num_menus < num_input_methods + 2)
2594 num_menus = num_input_methods + 2;
2595 if (num_menus < num_faces + 1)
2596 num_menus = num_faces + 1;
2597 menus = alloca (sizeof (MenuRec) * num_menus);
2599 w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu",
2600 FileMenu, sizeof FileMenu / sizeof (MenuRec),
2601 "File I/O, Serialization, Image, Quit");
2603 SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1);
2604 SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0);
2605 SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0);
2606 SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0);
2607 SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1);
2608 SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0);
2609 w = create_menu_button (ShellWidget, HeadWidget, w,
2610 "Cursor", "Cursor Menu",
2611 menus, 6, "Cursor Movement Mode, Cursor Shape");
2612 CursorMenus[0] = menus[0].w;
2613 CursorMenus[1] = menus[1].w;
2614 CursorMenus[2] = menus[3].w;
2615 CursorMenus[3] = menus[4].w;
2616 CursorMenus[4] = menus[5].w;
2618 SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0);
2619 SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1);
2620 SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0);
2621 w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu",
2622 menus, 3, "BIDI Processing Mode");
2623 for (i = 0; i < 3; i++)
2624 BidiMenus[i] = menus[i].w;
2626 SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0);
2627 SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1);
2628 SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0);
2629 w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak",
2631 menus, 3, "How to break lines");
2632 for (i = 0; i < 3; i++)
2633 LineBreakMenus[i] = menus[i].w;
2635 SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1);
2636 SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
2637 for (i = 0; i < num_input_methods; i++)
2639 InputMethodInfo *im = input_method_table + i;
2640 char *name1, *name2;
2642 if (im->language != Mnil && im->language != Mt)
2644 MSymbol sym = msymbol_get (im->language, Mlanguage);
2646 name1 = msymbol_name (im->language);
2648 name1 = msymbol_name (sym);
2649 name2 = msymbol_name (im->name);
2652 name1 = msymbol_name (im->name), name2 = NULL;
2654 SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0);
2656 w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod",
2657 "Input Method Menu", menus, i + 2,
2658 "Select input method");
2661 unsigned long valuemask = GCForeground;
2664 XtSetArg (arg[0], XtNbackground, &values.foreground);
2665 XtGetValues (w, arg, 1);
2666 gc_inv = XCreateGC (display, RootWindow (display, screen),
2667 valuemask, &values);
2670 InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2));
2671 for (i = 0; i < num_input_methods + 2; i++)
2672 InputMethodMenus[i] = menus[i].w;
2674 input_status_width = font_width * 8;
2675 input_status_height = (font_ascent + font_descent) * 2.4;
2676 input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
2678 input_status_height,
2679 DefaultDepth (display, screen));
2684 prop.color_top = prop.color_bottom
2685 = prop.color_left = prop.color_right = Mnil;
2686 prop.inner_hmargin = prop.inner_vmargin = 1;
2687 prop.outer_hmargin = prop.outer_vmargin = 0;
2688 face_input_status = mface_copy (face_default);
2689 mface_put_prop (face_input_status, Mbox, &prop);
2692 XFillRectangle (display, input_status_pixmap, gc_inv,
2693 0, 0, input_status_width, input_status_height);
2694 XtSetArg (arg[0], XtNfromHoriz, w);
2695 XtSetArg (arg[1], XtNleft, XawRubber);
2696 XtSetArg (arg[2], XtNright, XawChainRight);
2697 XtSetArg (arg[3], XtNborderWidth, 0);
2698 XtSetArg (arg[4], XtNlabel, " ");
2699 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2700 CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass,
2701 HeadWidget, arg, 6);
2702 XtSetArg (arg[0], XtNfromHoriz, CurIMLang);
2703 XtSetArg (arg[1], XtNleft, XawChainRight);
2704 XtSetArg (arg[4], XtNbitmap, input_status_pixmap);
2705 CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass,
2706 HeadWidget, arg, 5);
2708 XtSetArg (arg[0], XtNborderWidth, 0);
2709 XtSetArg (arg[1], XtNleft, XawChainLeft);
2710 XtSetArg (arg[2], XtNright, XawChainLeft);
2711 w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3);
2712 for (i = 0; i < num_faces;)
2714 char *label_menu = face_table[i++].name; /* "Menu Xxxx" */
2715 char *label = label_menu + 5; /* "Xxxx" */
2717 for (j = i; j < num_faces && face_table[j].face; j++)
2718 SetMenu (menus[j - i], 0, face_table[j].name, NULL,
2720 w = create_menu_button (ShellWidget, FaceWidget, w,
2722 menus, j - i, "Push face property");
2726 XtSetArg (arg[0], XtNfromHoriz, w);
2727 XtSetArg (arg[1], XtNleft, XawChainLeft);
2728 XtSetArg (arg[2], XtNright, XawChainLeft);
2729 XtSetArg (arg[3], XtNhorizDistance, 10);
2730 XtSetArg (arg[4], XtNlabel, "Pop");
2731 XtSetArg (arg[5], XtNtranslations,
2732 XtParseTranslationTable (pop_face_trans));
2733 w = XtCreateManagedWidget ("Pop Face", commandWidgetClass,
2734 FaceWidget, arg, 6);
2735 XtAddCallback (w, XtNcallback, FaceProc, (void *) -1);
2737 XtSetArg (arg[0], XtNfromHoriz, w);
2738 XtSetArg (arg[1], XtNleft, XawChainLeft);
2739 XtSetArg (arg[2], XtNright, XawChainRight);
2740 XtSetArg (arg[3], XtNlabel, "");
2741 XtSetArg (arg[4], XtNborderWidth, 0);
2742 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2743 CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass,
2744 FaceWidget, arg, 6);
2746 XtSetArg (arg[0], XtNborderWidth, 0);
2747 XtSetArg (arg[1], XtNleft, XawChainLeft);
2748 XtSetArg (arg[2], XtNright, XawChainLeft);
2749 w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3);
2751 MPlist *plist[11], *pl;
2754 for (i = 0; i < 11; i++) plist[i] = NULL;
2756 for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++)
2757 for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++)
2759 MSymbol sym = msymbol_exist (langname);
2763 && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
2765 char *name = msymbol_name (fullname);
2768 if (c >= 'A' && c <= 'Z')
2770 int idx = (c < 'U') ? (c - 'A') / 2 : 10;
2774 pl = plist[idx] = mplist ();
2775 for (; mplist_next (pl); pl = mplist_next (pl))
2776 if (strcmp (name, (char *) mplist_value (pl)) < 0)
2778 mplist_push (pl, sym, fullname);
2783 for (i = 0; i < 11; i++)
2786 char *name = alloca (9);
2788 sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
2791 for (j = 0, pl = plist[i]; mplist_next (pl);
2792 j++, pl = mplist_next (pl))
2793 SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)),
2794 msymbol_name (mplist_key (pl)),
2795 LangProc, mplist_key (pl), -1);
2796 w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name,
2797 menus, j, "Push language property");
2799 for (i = 0; i < 11; i++)
2801 m17n_object_unref (plist[i]);
2803 XtSetArg (arg[0], XtNfromHoriz, w);
2804 XtSetArg (arg[1], XtNleft, XawChainLeft);
2805 XtSetArg (arg[2], XtNright, XawChainLeft);
2806 XtSetArg (arg[3], XtNhorizDistance, 10);
2807 XtSetArg (arg[4], XtNlabel, "Pop");
2808 XtSetArg (arg[5], XtNtranslations,
2809 XtParseTranslationTable (pop_lang_trans));
2810 w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass,
2811 LangWidget, arg, 6);
2812 XtAddCallback (w, XtNcallback, LangProc, Mnil);
2814 XtSetArg (arg[0], XtNfromHoriz, w);
2815 XtSetArg (arg[1], XtNleft, XawChainLeft);
2816 XtSetArg (arg[2], XtNright, XawChainRight);
2817 XtSetArg (arg[3], XtNlabel, "");
2818 XtSetArg (arg[4], XtNborderWidth, 0);
2819 XtSetArg (arg[5], XtNjustify, XtJustifyRight);
2820 CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass,
2821 LangWidget, arg, 6);
2824 XtSetArg (arg[0], XtNheight, win_height);
2825 XtSetArg (arg[1], XtNwidth, 10);
2826 XtSetArg (arg[2], XtNleft, XawChainLeft);
2827 XtSetArg (arg[3], XtNright, XawChainLeft);
2828 SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget,
2830 XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL);
2831 XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL);
2833 XtSetArg (arg[0], XtNheight, win_height);
2834 XtSetArg (arg[1], XtNwidth, win_width);
2835 XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans));
2836 XtSetArg (arg[3], XtNfromHoriz, SbarWidget);
2837 XtSetArg (arg[4], XtNleft, XawChainLeft);
2838 XtSetArg (arg[5], XtNright, XawChainRight);
2839 TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget,
2842 XtSetArg (arg[0], XtNborderWidth, 0);
2843 XtSetArg (arg[1], XtNleft, XawChainLeft);
2844 XtSetArg (arg[2], XtNright, XawChainRight);
2845 XtSetArg (arg[3], XtNresizable, True);
2846 XtSetArg (arg[4], XtNjustify, XtJustifyLeft);
2847 MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass,
2848 TailWidget, arg, 5);
2850 memset (&control, 0, sizeof control);
2851 control.two_dimensional = 1;
2852 control.enable_bidi = 1;
2853 control.anti_alias = 1;
2854 control.min_line_ascent = font_ascent;
2855 control.min_line_descent = font_descent;
2856 control.max_line_width = win_width;
2857 control.with_cursor = 1;
2858 control.cursor_width = 2;
2859 control.partial_update = 1;
2860 control.ignore_formatting_char = 1;
2862 memset (&input_status_control, 0, sizeof input_status_control);
2863 input_status_control.enable_bidi = 1;
2865 XtAppAddActions (context, actions, XtNumber (actions));
2866 XtRealizeWidget (ShellWidget);
2868 win = XtWindow (TextWidget);
2870 XtAppMainLoop (context);
2872 if (current_input_context)
2873 minput_destroy_ic (current_input_context);
2874 for (i = 0; i < num_input_methods; i++)
2875 if (input_method_table[i].im)
2876 minput_close_im (input_method_table[i].im);
2877 m17n_object_unref (frame);
2878 m17n_object_unref (mt);
2879 m17n_object_unref (face_xxx_large);
2880 m17n_object_unref (face_box);
2881 m17n_object_unref (face_courier);
2882 m17n_object_unref (face_helvetica);
2883 m17n_object_unref (face_times);
2884 m17n_object_unref (face_dv_ttyogesh);
2885 m17n_object_unref (face_freesans);
2886 m17n_object_unref (face_freeserif);
2887 m17n_object_unref (face_freemono);
2888 m17n_object_unref (face_default_fontset);
2889 m17n_object_unref (face_no_ctl_fontset);
2890 m17n_object_unref (face_input_status);
2891 m17n_object_unref (face_default);
2892 m17n_object_unref (default_face_list);
2893 m17n_object_unref (selection);
2895 XFreeGC (display, mono_gc);
2896 XFreeGC (display, mono_gc_inv);
2897 XFreeGC (display, gc_inv);
2898 XtUninstallTranslations (form);
2899 XtUninstallTranslations (TextWidget);
2900 XtDestroyWidget (ShellWidget);
2901 XtDestroyApplicationContext (context);
2905 free (fontset_name);
2907 free (input_method_table);
2908 free (InputMethodMenus);
2912 #endif /* not FOR_DOXYGEN */