X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=example%2Fmedit.c;h=fe6fad2a3faa7fccf6779bff578f10ff717d6184;hb=87ffd3c24820a4c2876d9b213584280d6160618e;hp=fc5197b2ede7c5041d58ac25bd340ef8ef6e67fb;hpb=f25c45fa73cc66a93a447257c12b09e75ce887d9;p=m17n%2Fm17n-lib.git diff --git a/example/medit.c b/example/medit.c index fc5197b..fe6fad2 100644 --- a/example/medit.c +++ b/example/medit.c @@ -1,5 +1,5 @@ -/* medit.c -- simple multilingual editor. - Copyright (C) 2003, 2004 +/* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H15PRO112 @@ -17,17 +17,17 @@ You should have received a copy of the GNU Lesser General Public License along with the m17n library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 02111-1307, USA. */ /***en - @enpage medit edit multilingual text + @enpage m17n-edit edit multilingual text - @section medit-synopsis SYNOPSIS + @section m17n-edit-synopsis SYNOPSIS - medit [ XT-OPTION ...] [ OPTION ... ] FILE + m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE - @section medit-description DESCRIPTION + @section m17n-edit-description DESCRIPTION Display FILE on a window and allow users to edit it. @@ -48,18 +48,18 @@ This program is to demonstrate how to use the m17n GUI API. - Although medit directly uses the GUI API, the API is mainly for - toolkit libraries or to implement XOM (X Outout Method), not for - direct use from application programs. + Although m17n-edit directly uses the GUI API, the API is mainly + for toolkit libraries or to implement XOM (X Output Method), not + for direct use from application programs. */ /***ja - @japage medit ¿¸À¸ì¥Æ¥­¥¹¥È¤ÎÊÔ½¸ + @japage m17n-edit ¿¸À¸ì¥Æ¥­¥¹¥È¤ÎÊÔ½¸ - @section medit-synopsis SYNOPSIS + @section m17n-edit-synopsis SYNOPSIS - medit [ XT-OPTION ...] [ OPTION ... ] FILE + m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE - @section medit-description DESCRIPTION + @section m17n-edit-description DESCRIPTION FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë¡£ @@ -79,10 +79,10 @@ - ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£medit ¤Ïľ - ÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥­¥Ã¥È¥é¥¤¥Ö¥é¥ê¤ä - XOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é ¥à - ¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£ + ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit + ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥­¥Ã¥È¥é¥¤¥Ö¥é + ¥ê¤äXOM (X Output Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é + ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£ */ #ifndef FOR_DOXYGEN @@ -95,12 +95,20 @@ #include #include #include +#include + +#ifdef HAVE_X11_XAW_COMMAND_H #include #include #include #include #include + +#include +#include +#include + #include #include #include @@ -112,12 +120,6 @@ #include #include -#include -#include -#include - -#define VERSION "1.0.1" - /* Global variables. */ char *filename; @@ -169,23 +171,37 @@ Pixmap CheckPixmap; MFrame *frame; MText *mt; int nchars; /* == mtext_len (mt) */ +int mt_modified; MDrawControl control, input_status_control; MTextProperty *selection; +MSymbol Mword; + MFace *face_default; MFace *face_xxx_large; MFace *face_box; MFace *face_courier, *face_helvetica, *face_times; -MFace *face_dv_ttyogesh, *face_freesans, *face_freemono; +MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono; MFace *face_default_fontset, *face_no_ctl_fontset; MFace *face_input_status; +MSymbol Mcoding_compound_text; + int logical_move = 1; /* If 0, move cursor visually. */ -MInputMethod **input_method_table; +typedef struct { + int available; + MSymbol language, name; + MInputMethod *im; +} InputMethodInfo; + +InputMethodInfo *input_method_table; + int num_input_methods; int current_input_method = -1; /* i.e. none */ +int unicode_input_method = -1; int auto_input_method = 0; +int saved_input_method = -3; MInputContext *current_input_context; struct FaceRec @@ -209,6 +225,7 @@ struct FaceRec {"times", &face_times}, {"dv-ttyogesh", &face_dv_ttyogesh}, {"freesans", &face_freesans}, + {"freeserif", &face_freeserif}, {"freemono", &face_freemono}, {"Menu Style", NULL}, @@ -241,7 +258,7 @@ struct LineInfo { int from; /* BOL position of the line. */ int to; /* BOL position of the next line. */ - int y0, y1; /* Top and bottom Y position of the line. */ + int y0, y1; /* Top and bottom Y position of the line. */ int ascent; /* Height of the top Y position. */ }; @@ -324,8 +341,8 @@ update_top (int pos) top.from = info.line_from; top.to = info.line_to; top.y0 = 0; - top.y1 = info.this.height; - top.ascent = - info.this.y; + top.y1 = info.metrics.height; + top.ascent = - info.metrics.y; } @@ -336,12 +353,8 @@ update_scroll_bar (int from, int to) { float top = (float) from / nchars; float shown = (float) (to - from) / nchars; - XtArgVal *l_top = (XtArgVal *) ⊤ - XtArgVal *l_shown = (XtArgVal *) &shown; - XtSetArg (arg[0], XtNtopOfThumb, *l_top); - XtSetArg (arg[1], XtNshown, *l_shown); - XtSetValues (SbarWidget, arg, 2); + XawScrollbarSetThumb (SbarWidget, top, shown); } @@ -357,7 +370,7 @@ redraw (int y0, int y1, int clear, int scroll_bar) int sel_y0 = SELECTEDP () ? sel_start.y0 : 0; struct LineInfo *line; - if (clear) + if (clear || control.anti_alias) CLEAR_AREA (0, y0, win_width, y1 - y0); /* Find a line closest to y0. It is a cursor line if the cursor is @@ -372,21 +385,26 @@ redraw (int y0, int y1, int clear, int scroll_bar) from = line->from; y = line->y0; - info.this.height = line->y1 - y; - info.this.y = - line->ascent; + info.metrics.height = line->y1 - y; + info.metrics.y = - line->ascent; info.line_to = line->to; - while (from < nchars && y + info.this.height <= y0) + while (y + info.metrics.height <= y0) { - y += info.this.height; + y += info.metrics.height; from = info.line_to; + if (from >= nchars) + break; GLYPH_INFO (from, from, info); } - y0 = y - info.this.y; + if (y + info.metrics.height <= y0) + return; + + y0 = y - info.metrics.y; to = from; while (to < nchars && y < y1) { GLYPH_INFO (to, to, info); - y += info.this.height; + y += info.metrics.height; to = info.line_to; } if (to == nchars) @@ -398,10 +416,10 @@ redraw (int y0, int y1, int clear, int scroll_bar) while (to < nchars) { GLYPH_INFO (to, to, info); - if (y + info.this.height >= win_height) + if (y + info.metrics.height >= win_height) break; to = info.line_to; - y += info.this.height; + y += info.metrics.height; } update_scroll_bar (top.from, to); } @@ -415,16 +433,19 @@ set_input_method_spot () int x = cursor.x + (control.orientation_reversed ? win_width : 0); int pos = cursor.from > 0 ? cursor.from - 1 : 0; MFace *faces[256]; - int n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256); + int n = 0; int size = 0, ratio = 0, i; - for (i = n - 1; i >= 0; i--) - { - if (! size) - size = (int) mface_get_prop (faces[i], Msize); - if (! ratio) - ratio = (int) mface_get_prop (faces[i], Mratio); - } + if (nchars > 0) + n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256); + if (n > 0) + for (i = n - 1; i >= 0; i--) + { + if (! size) + size = (int) mface_get_prop (faces[i], Msize); + if (! ratio) + ratio = (int) mface_get_prop (faces[i], Mratio); + } if (! size) size = default_font_size; if (ratio) @@ -448,12 +469,12 @@ redraw_cursor (int clear) MDrawMetric rect; int y0 = cur.y0, y1 = cur.y1; - if (beg != cur.from) + if (beg < cur.from) { TEXT_EXTENTS (beg, cur.from, rect); y0 -= rect.height; } - if (end != cur.to) + if (end > cur.to) { TEXT_EXTENTS (cur.to, end, rect); y1 += rect.height; @@ -467,8 +488,8 @@ redraw_cursor (int clear) int x = cursor.x; if (control.orientation_reversed) - x += win_width - cursor.this.width; - CLEAR_AREA (x, cur.y0, cursor.this.width, cursor.this.height); + x += win_width - cursor.logical_width; + CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height); } DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to); } @@ -477,18 +498,19 @@ redraw_cursor (int clear) /* Update the information about the location of cursor to the position $POS. If $FULL is nonzero, update the information fully only from - the information about the top line. Otherwise, truct the current + the information about the top line. Otherwise, trust the current information in the structure $CUR. */ void update_cursor (int pos, int full) { MDrawMetric rect; + control.cursor_pos = pos; if (full) { /* CUR is inaccurate. We can trust only TOP. */ GLYPH_INFO (top.from, pos, cursor); - cur.y0 = top.ascent + cursor.y + cursor.this.y; + cur.y0 = top.ascent + cursor.y + cursor.metrics.y; } else if (pos < cur.from) { @@ -496,7 +518,7 @@ update_cursor (int pos, int full) TEXT_EXTENTS (from, cur.from, rect); GLYPH_INFO (from, pos, cursor); - cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y); + cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y); } else if (pos < cur.to) { @@ -505,13 +527,13 @@ update_cursor (int pos, int full) else { GLYPH_INFO (cur.from, pos, cursor); - cur.y0 += cur.ascent + cursor.y + cursor.this.y; + cur.y0 += cur.ascent + cursor.y + cursor.metrics.y; } cur.from = cursor.line_from; cur.to = cursor.line_to; - cur.y1 = cur.y0 + cursor.this.height; - cur.ascent = - cursor.this.y; + cur.y1 = cur.y0 + cursor.metrics.height; + cur.ascent = - cursor.metrics.y; } @@ -537,34 +559,28 @@ update_selection () sel_start.ascent = - rect.y; GLYPH_INFO (pos, from, info); if (pos < info.line_from) - sel_start.y0 += - rect.y + info.y + info.this.y; + sel_start.y0 += - rect.y + info.y + info.metrics.y; } else { GLYPH_INFO (top.from, from, info); - sel_start.y0 = top.ascent + info.y + info.this.y; + sel_start.y0 = top.ascent + info.y + info.metrics.y; } - sel_start.ascent = -info.this.y; - sel_start.y1 = sel_start.y0 + info.this.height; + sel_start.ascent = -info.metrics.y; + sel_start.y1 = sel_start.y0 + info.metrics.height; sel_start.from = info.line_from; sel_start.to = info.line_to; if (to <= sel_start.to) { sel_end = sel_start; - if (to >= sel_end.to) - { - GLYPH_INFO (sel_start.from, to, info); - sel_end.y1 = sel_end.y0 + info.y + info.this.height; - sel_end.to = info.line_to; - } } else { GLYPH_INFO (sel_start.from, to, info); - sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y; - sel_end.y1 = sel_end.y0 + info.this.height; - sel_end.ascent = - info.this.y; + sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y; + sel_end.y1 = sel_end.y0 + info.metrics.height; + sel_end.ascent = - info.metrics.y; sel_end.from = info.line_from; sel_end.to = info.line_to; } @@ -648,53 +664,101 @@ static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *); void select_input_method (idx) { + int previous_input_method = current_input_method; + if (idx == current_input_method) return; - if (current_input_context) + if (current_input_method >= 0) { minput_destroy_ic (current_input_context); current_input_context = NULL; current_input_method = -1; } - if (idx >= 0) + + if (idx >= 0 + && input_method_table[idx].available >= 0) { - MInputMethod *im = input_method_table[idx]; + InputMethodInfo *im = input_method_table + idx; - if (im->language == Mnil) + if (im->available == 0) { - MInputXIMArgIC arg_xic; - Window win = XtWindow (TextWidget); - - arg_xic.input_style = 0; - arg_xic.client_win = arg_xic.focus_win = win; - arg_xic.preedit_attrs = arg_xic.status_attrs = NULL; - current_input_context = minput_create_ic (im, &arg_xic); + if (im->language) + im->im = minput_open_im (im->language, im->name, NULL); + else + { + MInputXIMArgIM arg_xim; + + arg_xim.display = display; + arg_xim.db = NULL; + arg_xim.res_name = arg_xim.res_class = NULL; + arg_xim.locale = NULL; + arg_xim.modifier_list = NULL; + im->im = minput_open_im (Mnil, im->name, &arg_xim); + } + im->available = im->im ? 1 : -1; } - else + if (im->im) { - MInputGUIArgIC arg_ic; + if (im->language == Mnil) + { + MInputXIMArgIC arg_xic; + Window win = XtWindow (TextWidget); - arg_ic.frame = frame; - arg_ic.client = (MDrawWindow) XtWindow (ShellWidget); - arg_ic.focus = (MDrawWindow) XtWindow (TextWidget); - current_input_context = minput_create_ic (im, &arg_ic); - } + arg_xic.input_style = 0; + arg_xic.client_win = arg_xic.focus_win = win; + arg_xic.preedit_attrs = arg_xic.status_attrs = NULL; + current_input_context = minput_create_ic (im->im, &arg_xic); + } + else + { + MInputGUIArgIC arg_ic; - if (current_input_context) - { - set_input_method_spot (); - current_input_method = idx; + arg_ic.frame = frame; + arg_ic.client = (MDrawWindow) XtWindow (ShellWidget); + arg_ic.focus = (MDrawWindow) XtWindow (TextWidget); + current_input_context = minput_create_ic (im->im, &arg_ic); + } + + if (current_input_context) + { + current_input_method = idx; + set_input_method_spot (); + } + else + { + minput_close_im (im->im); + im->im = NULL; + im->available = -1; + current_input_method = -1; + } } } + if (! auto_input_method) + { + XtSetArg (arg[0], XtNleftBitmap, None); + if (previous_input_method >= 0) + XtSetValues (InputMethodMenus[previous_input_method + 2], arg, 1); + else + XtSetValues (InputMethodMenus[0], arg, 1); + XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); + if (current_input_method >= 0) + XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1); + else + XtSetValues (InputMethodMenus[0], arg, 1); + } + if (current_input_method >= 0) { char *label; + XtSetArg (arg[0], XtNlabel, &label); XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1); XtSetArg (arg[0], XtNlabel, label); } else - XtSetArg (arg[0], XtNlabel, ""); + { + XtSetArg (arg[0], XtNlabel, ""); + } XtSetValues (CurIMLang, arg, 1); } @@ -708,6 +772,9 @@ static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num); Boolean show_cursor (XtPointer client_data) { + MFaceHLineProp *hline; + MFaceBoxProp *box; + if (cur.y0 < 0) { reseat (cur.from); @@ -728,68 +795,65 @@ show_cursor (XtPointer client_data) if (current_input_context) set_input_method_spot (); - { - int pos = (SELECTEDP () ? mtext_property_start (selection) - : cursor.from > 0 ? cursor.from - 1 - : cursor.from); - MFace *face = mface (); - MTextProperty *props[256]; - int n = mtext_get_properties (mt, pos, Mface, props, 256); - int i; - char buf[256], *p = buf; - MSymbol sym; - - buf[0] = '\0'; - if (cursor.font) - { - int size = (int) mfont_get_prop (cursor.font, Msize); - MSymbol family = mfont_get_prop (cursor.font, Mfamily); - MSymbol weight = mfont_get_prop (cursor.font, Mweight); - MSymbol style = mfont_get_prop (cursor.font, Mstyle); - MSymbol registry = mfont_get_prop (cursor.font, Mregistry); - - sprintf (p, "%dpt", size / 10), p += strlen (p); - if (family) - strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p); - if (weight) - strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p); - if (style) - strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p); - if (registry) - strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p); - p += strlen (p); - } + if (nchars > 0) + { + int pos = (SELECTEDP () ? mtext_property_start (selection) + : cursor.from > 0 ? cursor.from - 1 + : cursor.from); + MFace *face = mface (); + MTextProperty *props[256]; + int n = mtext_get_properties (mt, pos, Mface, props, 256); + int i; + char buf[256], *p = buf; + MSymbol sym; - mface_merge (face, face_default); - for (i = 0; i < n; i++) - if (props[i] != selection) - mface_merge (face, (MFace *) mtext_property_value (props[i])); - sym = (MSymbol) mface_get_prop (face, Mforeground); - if (sym != Mnil) - strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p); - if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse) - strcat (p, ",rev"), p += strlen (p); - if (mface_get_prop (face, Mhline)) - strcat (p, ",ul"), p += strlen (p); - if (mface_get_prop (face, Mbox)) - strcat (p, ",box"), p += strlen (p); - m17n_object_unref (face); + buf[0] = '\0'; + if (cursor.font) + { + int size = (int) mfont_get_prop (cursor.font, Msize); + MSymbol family = mfont_get_prop (cursor.font, Mfamily); + MSymbol weight = mfont_get_prop (cursor.font, Mweight); + MSymbol style = mfont_get_prop (cursor.font, Mstyle); + MSymbol registry = mfont_get_prop (cursor.font, Mregistry); + + sprintf (p, "%dpt", size / 10), p += strlen (p); + if (family) + strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p); + if (weight) + strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p); + if (style) + strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p); + if (registry) + strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p); + p += strlen (p); + } - XtSetArg (arg[0], XtNborderWidth, 1); - XtSetArg (arg[1], XtNlabel, buf); - XtSetValues (CurFaceWidget, arg, 2); - } + mface_merge (face, face_default); + for (i = 0; i < n; i++) + if (props[i] != selection) + mface_merge (face, (MFace *) mtext_property_value (props[i])); + sym = (MSymbol) mface_get_prop (face, Mforeground); + if (sym != Mnil) + strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p); + if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse) + strcat (p, ",rev"), p += strlen (p); + hline = mface_get_prop (face, Mhline); + if (hline && hline->width > 0) + strcat (p, ",ul"), p += strlen (p); + box = mface_get_prop (face, Mbox); + if (box && box->width > 0) + strcat (p, ",box"), p += strlen (p); + m17n_object_unref (face); + + XtSetArg (arg[0], XtNborderWidth, 1); + XtSetArg (arg[1], XtNlabel, buf); + XtSetValues (CurFaceWidget, arg, 2); + } if (control.cursor_pos < nchars) { - MSymbol sym = Mnil; + MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage); - if (control.cursor_pos > 0 - && mtext_ref_char (mt, control.cursor_pos - 1) != '\n') - sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage); - if (sym == Mnil) - sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage); - if (sym == Mnil) { XtSetArg (arg[0], XtNborderWidth, 0); @@ -798,8 +862,8 @@ show_cursor (XtPointer client_data) else { XtSetArg (arg[0], XtNborderWidth, 1); - XtSetArg (arg[1], XtNlabel, - msymbol_name (msymbol_get (sym, Mlanguage))); + sym = mlanguage_name (sym); + XtSetArg (arg[1], XtNlabel, msymbol_name (sym)); XtSetValues (CurLangWidget, arg, 2); } XtSetValues (CurLangWidget, arg, 2); @@ -813,7 +877,8 @@ show_cursor (XtPointer client_data) int i; for (i = 0; i < num_input_methods; i++) - if (input_method_table[i]->language == sym) + if (input_method_table[i].language == sym + && input_method_table[i].available >= 0) break; if (i < num_input_methods) select_input_method (i); @@ -875,13 +940,16 @@ delete_char (int n) { MDrawMetric rect; MDrawGlyphInfo info; - int old_y1, new_y1; + int y0, old_y1, new_y1; int from, to; + int line_from = cursor.line_from; if (n > 0) from = cursor.from, to = from + n; else { + from = cursor.from + n; + to = cursor.from; if (cursor.from == cur.from) { /* We are at the beginning of line. */ @@ -895,13 +963,6 @@ delete_char (int n) reseat (info.line_from); } update_cursor (pos, 1); - from = cursor.from; - to = cursor.to; - } - else - { - from = cursor.from - 1; - to = cursor.from; } } @@ -910,11 +971,15 @@ delete_char (int n) /* Now delete a character. */ mtext_del (mt, from, to); - nchars--; + nchars -= to - from; if (from >= top.from && from < top.to) update_top (top.from); update_cursor (from, 1); + y0 = cur.y0; + if (line_from != cursor.line_from) + y0 -= 1; + TEXT_EXTENTS (cur.from, bol (to, 1), rect); new_y1 = cur.y0 + rect.height; @@ -929,6 +994,7 @@ insert_chars (MText *newtext) int n = mtext_len (newtext); MDrawMetric rect; int y0, old_y1, new_y1; + int line_from; if (SELECTEDP ()) { @@ -939,9 +1005,15 @@ insert_chars (MText *newtext) } y0 = cur.y0; + if (cursor.line_from > 0 + && mtext_ref_char (mt, cursor.line_from - 1) != '\n') + y0 -= control.min_line_descent; + TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect); old_y1 = y0 + rect.height; + line_from = cursor.line_from; + /* Now insert chars. */ mtext_ins (mt, cursor.from, newtext); nchars += n; @@ -957,8 +1029,60 @@ insert_chars (MText *newtext) } -/* Convert the currently selected text to COMPOUND-TEXT. It is called - when someone requests the current value of the selection. */ +int +word_constituent_p (int c) +{ + MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory); + char *name = category != Mnil ? msymbol_name (category) : NULL; + + return (name && (name[0] == 'L' || name[0] == 'M')); +} + + +void +forward_word () +{ + int pos = cursor.from; + + while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos))) + pos++; + if (pos < nchars) + { + MTextProperty *prop = mtext_get_property (mt, pos, Mword); + + if (prop) + pos = mtext_property_end (prop); + else + while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos))) + pos++; + } + update_cursor (pos, 0); +} + +void +backward_word () +{ + int pos = cursor.from; + + while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1))) + pos--; + if (pos > 0) + { + MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword); + + if (prop) + pos = mtext_property_start (prop); + else + while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1))) + pos--; + } + update_cursor (pos, 0); +} + + +/* Convert the currently selected text to UTF8-STRING or + COMPOUND-TEXT. It is called when someone requests the current + value of the selection. */ Boolean covert_selection (Widget w, Atom *selection_atom, Atom *target, Atom *return_type, @@ -968,14 +1092,52 @@ covert_selection (Widget w, Atom *selection_atom, MText *this_mt = mtext (); int from = mtext_property_start (selection); int to = mtext_property_end (selection); + MSymbol coding; + int len; mtext_copy (this_mt, 0, mt, from, to); - *length = mconv_encode_buffer (msymbol ("compound-text"), - this_mt, buf, 4096); - *return_type = XA_COMPOUND_TEXT; + if (*target == XA_TEXT) + { +#ifdef X_HAVE_UTF8_STRING + coding = Mcoding_utf_8; + *return_type = XA_UTF8_STRING; +#else + coding = Mcoding_compound_text; + *return_type = XA_COMPOUND_TEXT; +#endif + } + else if (*target == XA_UTF8_STRING) + { + coding = Mcoding_utf_8; + *return_type = XA_UTF8_STRING; + } + else if (*target == XA_STRING) + { + int i; + + len = to - from; + for (i = 0; i < len; i++) + if (mtext_ref_char (this_mt, i) >= 0x100) + /* Can't encode in XA_STRING */ + return False; + coding = Mcoding_iso_8859_1; + *return_type = XA_STRING; + } + else if (*target == XA_COMPOUND_TEXT) + { + coding = Mcoding_compound_text; + *return_type = XA_COMPOUND_TEXT; + } + else + return False; + + len = mconv_encode_buffer (coding, this_mt, buf, 4096); + m17n_object_unref (this_mt); + if (len < 0) + return False; + *length = len; *value = (XtPointer) buf; *format = 8; - m17n_object_unref (this_mt); return True; } @@ -1004,12 +1166,20 @@ get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type, coding = Mnil; else if (*type == XA_COMPOUND_TEXT) coding = msymbol ("compound-text"); +#ifdef X_HAVE_UTF8_STRING else if (*type == XA_UTF8_STRING) coding = msymbol ("utf-8"); +#endif else goto err; this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length); + if (! this_mt && *type != XA_UTF8_STRING) + { + XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL, + CurrentTime); + goto err; + } if (this_mt) { hide_cursor (); @@ -1053,6 +1223,13 @@ ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num) update_top (0); update_cursor (0, 1); redraw (0, win_height, 0, 1); + if (current_input_method >= 0) + { + int idx = current_input_method; + + current_input_method = -1; + select_input_method (idx); + } show_cursor (NULL); } else @@ -1097,6 +1274,20 @@ ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num) redraw (sel_start.y0, sel_end.y1, 1, 0); } hide_cursor (); + if (current_input_context + && minput_filter (current_input_context, Minput_focus_move, NULL) == 0) + { + MText *produced = mtext (); + + minput_lookup (current_input_context, Mnil, NULL, produced); + if (mtext_len (produced) > 0) + { + insert_chars (produced); + if (pos >= cursor.from) + pos += mtext_len (produced); + } + m17n_object_unref (produced); + } update_cursor (pos, 0); } @@ -1241,6 +1432,42 @@ ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num) } void +FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + if (current_input_context + && minput_filter (current_input_context, Minput_focus_in, NULL) == 0) + { + MText *produced = mtext (); + + minput_lookup (current_input_context, Mnil, NULL, produced); + if (mtext_len (produced) > 0) + { + hide_cursor (); + insert_chars (produced); + } + m17n_object_unref (produced); + } +} + +void +FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + if (current_input_context + && minput_filter (current_input_context, Minput_focus_out, NULL) == 0) + { + MText *produced = mtext (); + + minput_lookup (current_input_context, Mnil, NULL, produced); + if (mtext_len (produced) > 0) + { + hide_cursor (); + insert_chars (produced); + } + m17n_object_unref (produced); + } +} + +void ScrollProc (Widget w, XtPointer client_data, XtPointer position) { int from; @@ -1259,9 +1486,9 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position) { pos = bol (from - 1, 0); GLYPH_INFO (pos, from - 1, info); - if (height + info.this.height > win_height) + if (height + info.metrics.height > win_height) break; - height += info.this.height; + height += info.metrics.height; from = info.line_from; } if (cursor_pos >= top.to) @@ -1271,9 +1498,9 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position) while (cursor_pos < nchars) { GLYPH_INFO (pos, pos, info); - if (height + info.this.height > win_height) + if (height + info.metrics.height > win_height) break; - height += info.this.height; + height += info.metrics.height; cursor_pos = pos; pos = info.line_to; } @@ -1287,10 +1514,10 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position) while (from < nchars) { GLYPH_INFO (from, from, info); - if (height + info.this.height > win_height + if (height + info.metrics.height > win_height || info.line_to >= nchars) break; - height += info.this.height; + height += info.metrics.height; from = info.line_to; } if (from == nchars) @@ -1321,6 +1548,7 @@ JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr) update_cursor (pos1, 1); } +static void InputMethodProc (Widget, XtPointer, XtPointer); static void KeyProc (Widget w, XEvent *event, String *str, Cardinal *num) @@ -1332,15 +1560,26 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num) /* If set to 1, do not update target_x_position. */ int keep_target_x_position = 0; MText *produced; + int y0, old_y1, new_y1; + hide_cursor (); + + mt_modified = 0; + y0 = cur.y0; + old_y1 = cur.y1; if (current_input_context && minput_filter (current_input_context, Mnil, event)) - return; + { + if (mt_modified) + { + new_y1 = cur.y1; + update_region (y0, old_y1, new_y1); + } + return; + } if (event->type == KeyRelease) return; - hide_cursor (); - produced = mtext (); ret = minput_lookup (current_input_context, Mnil, event, produced); if (mtext_len (produced) > 0) @@ -1349,6 +1588,12 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num) ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL); m17n_object_unref (produced); + if (saved_input_method > -3) + { + InputMethodProc (w, (XtPointer) saved_input_method, NULL); + saved_input_method = -3; + } + switch (keysym) { case XK_Delete: @@ -1488,6 +1733,22 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num) ScrollProc (w, NULL, (XtPointer) -1); break; + case XK_b: + if (key_event->state >= Mod1Mask) + { + lose_selection (NULL, NULL); + backward_word (); + break; + } + + case XK_f: + if (key_event->state >= Mod1Mask) + { + lose_selection (NULL, NULL); + forward_word (); + break; + } + default: if (ret > 0) { @@ -1501,11 +1762,20 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num) redraw (0, win_height, 1, 1); return; } + else if (buf[0] == '=' + && (event->xkey.state & ControlMask) + && unicode_input_method >= 0) + { + saved_input_method = current_input_method; + InputMethodProc (w, (XtPointer) unicode_input_method, NULL); + minput_filter (current_input_context, msymbol ("C-u"), NULL); + } else { MText *temp = mtext (); - mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]); + mtext_cat_char (temp, buf[0] == '\r' ? '\n' + : ((unsigned char *) buf)[0]); if (current_input_context) mtext_put_prop (temp, 0, 1, Mlanguage, current_input_context->im->language); @@ -1546,7 +1816,7 @@ SaveProc (Widget w, XtPointer client_data, XtPointer call_data) mtext_detach_property (selection); } - mconv_encode_stream (Mcoding_utf_8, mt, fp); + mconv_encode_stream (Mcoding_utf_8_full, mt, fp); fclose (fp); if (from >= 0) select_region (from, to); @@ -1597,7 +1867,7 @@ read_file () if (! fp) FATAL_ERROR ("Can't read \"%s\"!\n", filename); - mt = mconv_decode_stream (Mcoding_utf_8, fp); + mt = mconv_decode_stream (Mcoding_utf_8_full, fp); fclose (fp); if (! mt) FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename); @@ -1633,8 +1903,6 @@ BidiProc (Widget w, XtPointer client_data, XtPointer call_data) redraw (0, win_height, 1, 0); } -extern int line_break (MText *mt, int pos, int from, int to, int line, int y); - void LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data) { @@ -1646,7 +1914,7 @@ LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data) else { control.max_line_width = win_width; - control.line_break = (data == 1 ? NULL : line_break); + control.line_break = (data == 1 ? NULL : mdraw_default_line_break); } for (i = 0; i < 3; i++) { @@ -1662,6 +1930,25 @@ LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data) } void +FilterProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + char *filter_module = (char *) client_data; + void *handle; + void (*func) (MText *, int, int); + + if (! SELECTEDP ()) + return; + handle = dlopen (filter_module, RTLD_NOW); + if (! handle) + return; + func = (void (*) (MText *, int, int)) dlsym (handle, "filter"); + if (func) + (*func) (mt, mtext_property_start (selection), + mtext_property_end (selection)); + dlclose (handle); +} + +void CursorProc (Widget w, XtPointer client_data, XtPointer call_data) { int data = (int) client_data; @@ -1700,6 +1987,7 @@ CursorProc (Widget w, XtPointer client_data, XtPointer call_data) XtSetValues (CursorMenus[i], arg, 1); } + update_cursor (cursor.from, 0); redraw (0, win_height, 1, 0); } @@ -1708,33 +1996,37 @@ InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data) { int idx = (int) client_data; - if (idx == -2 ? current_input_method < 0 + if (idx == -2 ? (! auto_input_method && current_input_method < 0) : idx == -1 ? auto_input_method : idx == current_input_method) return; - XtSetArg (arg[0], XtNleftBitmap, None); if (auto_input_method) { + select_input_method (-1); + XtSetArg (arg[0], XtNleftBitmap, None); XtSetValues (InputMethodMenus[1], arg, 1); auto_input_method = 0; } - else if (current_input_method < 0) - XtSetValues (InputMethodMenus[0], arg, 1); - else - XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1); if (idx == -1) { + select_input_method (-1); + XtSetArg (arg[0], XtNleftBitmap, None); + XtSetValues (InputMethodMenus[0], arg, 1); + XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); + XtSetValues (InputMethodMenus[1], arg, 1); auto_input_method = 1; hide_cursor (); } else - select_input_method (idx); - XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); - XtSetValues (InputMethodMenus[idx + 2], arg, 1); + { + select_input_method (idx); + } } +MPlist *default_face_list; + void FaceProc (Widget w, XtPointer client_data, XtPointer call_data) { @@ -1742,8 +2034,37 @@ FaceProc (Widget w, XtPointer client_data, XtPointer call_data) int from, to; int old_y1; + hide_cursor (); if (! SELECTEDP ()) - return; + { + MPlist *plist; + + if (idx >= 0) + { + MFace *face = mframe_get_prop (frame, Mface); + + for (plist = default_face_list; mplist_key (plist) != Mnil; + plist = mplist_next (plist)) + mface_merge (face, mplist_value (plist)); + mplist_add (plist, Mt, *face_table[idx].face); + mface_merge (face, *face_table[idx].face); + } + else if (mplist_key (mplist_next (default_face_list)) != Mnil) + { + MFace *face = mframe_get_prop (frame, Mface); + + for (plist = default_face_list; + mplist_key (mplist_next (plist)) != Mnil; + plist = mplist_next (plist)) + mface_merge (face, mplist_value (plist)); + mplist_pop (plist); + } + update_top (0); + update_cursor (0, 1); + redraw (0, win_height, 1, 1); + show_cursor (NULL); + return; + } XtAppAddWorkProc (context, show_cursor, NULL); from = mtext_property_start (selection); @@ -1838,7 +2159,7 @@ DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data) mdump = popen ("mdump -q", "w"); if (! mdump) return; - converter = mconv_stream_converter (Mcoding_utf_8, mdump); + converter = mconv_stream_converter (Mcoding_utf_8_full, mdump); mconv_encode_range (converter, mt, from, to); mconv_free_converter (converter); fclose (mdump); @@ -1869,11 +2190,64 @@ input_status (MInputContext *ic, MSymbol command) XtSetValues (CurIMStatus, arg, 1); } +void +surrounding_text_handler (MInputContext *ic, MSymbol command) +{ + if (command == Minput_get_surrounding_text) + { + int len = (int) mplist_value (ic->plist); + int pos; + MText *surround; + + if (len < 0) + { + pos = cursor.from + len; + if (pos < 0) + pos = 0; + surround = mtext_duplicate (mt, pos, cursor.from); + } + else if (len > 0) + { + pos = cursor.from + len; + if (pos > nchars) + pos = nchars; + surround = mtext_duplicate (mt, cursor.from, pos); + } + else + surround = mtext (); + mplist_set (ic->plist, Mtext, surround); + m17n_object_unref (surround); + } + else if (command == Minput_delete_surrounding_text) + { + int len = (int) mplist_value (ic->plist); + + if (len < 0) + { + if (cursor.from + len < 0) + len = - cursor.from; + mtext_del (mt, cursor.from + len, cursor.from); + nchars += len; + update_cursor (cursor.from + len, 1); + } + else if (len > 0) + { + if (cursor.from + len > nchars) + len = nchars - cursor.from; + mtext_del (mt, cursor.from, cursor.from + len); + nchars -= len; + update_cursor (cursor.from, 1); + } + if (len) + mt_modified = 1; + } +} + int compare_input_method (const void *elt1, const void *elt2) { - const MInputMethod *im1 = *(MInputMethod **) elt1; - const MInputMethod *im2 = *(MInputMethod **) elt2; + const InputMethodInfo *im1 = elt1; + const InputMethodInfo *im2 = elt2; MSymbol lang1, lang2; if (im1->language == Mnil) @@ -1884,61 +2258,91 @@ compare_input_method (const void *elt1, const void *elt2) return 1; if (im2->language == Mt) return -1; - lang1 = msymbol_get (im1->language, Mlanguage); - lang2 = msymbol_get (im2->language, Mlanguage); + lang1 = mlanguage_name (im1->language); + lang2 = mlanguage_name (im2->language); return strcmp (msymbol_name (lang1), msymbol_name (lang2)); } void -setup_input_methods (int with_xim) +setup_input_methods (int with_xim, char *initial_input_method) { - MInputMethod *im = NULL; - MInputXIMArgIM arg_xim; MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil); MPlist *pl; - int i = 0; - - num_input_methods = mplist_length (plist); + int i; + MSymbol Municode = msymbol ("unicode"); + num_input_methods = plist ? mplist_length (plist) : 0; if (with_xim) - { - arg_xim.display = display; - arg_xim.db = NULL; - arg_xim.res_name = arg_xim.res_class = NULL; - arg_xim.locale = NULL; - arg_xim.modifier_list = NULL; - im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim); - if (im) - num_input_methods++; - } - input_method_table = calloc (num_input_methods, sizeof (MInputMethod *)); - if (im) - input_method_table[i++] = im; - for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl)) - { - MDatabase *mdb = mplist_value (pl); - MSymbol *tag = mdatabase_tag (mdb); + num_input_methods++; + input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo)); - if (tag[1] != Mnil) + i = 0; + if (plist) + { + for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++) { - im = minput_open_im (tag[1], tag[2], NULL); - if (im) - input_method_table[i++] = im; + MDatabase *mdb = mplist_value (pl); + MSymbol *tag = mdatabase_tag (mdb); + + if (tag[2] == Mnil) + i--, num_input_methods--; + else + { + input_method_table[i].language = tag[1]; + input_method_table[i].name = tag[2]; + } } + m17n_object_unref (plist); + } + if (with_xim) + { + input_method_table[i].language = Mnil; + input_method_table[i].name = msymbol ("xim"); + i++; } - m17n_object_unref (plist); - num_input_methods = i; qsort (input_method_table, num_input_methods, sizeof input_method_table[0], compare_input_method); + for (i = 0; i < num_input_methods; i++) + if (input_method_table[i].language == Mt + && input_method_table[i].name == Municode) + { + unicode_input_method = i; + break; + } + mplist_put_func (minput_driver->callback_list, Minput_status_start, + M17N_FUNC (input_status)); + mplist_put_func (minput_driver->callback_list, Minput_status_draw, + M17N_FUNC (input_status)); + mplist_put_func (minput_driver->callback_list, Minput_status_done, + M17N_FUNC (input_status)); + mplist_put_func (minput_driver->callback_list, Minput_get_surrounding_text, + M17N_FUNC (surrounding_text_handler)); + mplist_put_func (minput_driver->callback_list, Minput_delete_surrounding_text, + M17N_FUNC (surrounding_text_handler)); + current_input_context = NULL; + current_input_method = -1; + + if (initial_input_method) + { + char *lang_name, *method_name; + char *p = strchr (initial_input_method, '-'); + + if (p && p[1]) + lang_name = initial_input_method, *p = '\0', method_name = p + 1; + else + lang_name = "t", method_name = initial_input_method; - mplist_put (minput_driver->callback_list, Minput_status_start, - (void *) input_status); - mplist_put (minput_driver->callback_list, Minput_status_draw, - (void *) input_status); - mplist_put (minput_driver->callback_list, Minput_status_done, - (void *) input_status); + for (i = 0; i < num_input_methods; i++) + if ((strcmp (method_name, msymbol_name (input_method_table[i].name)) + == 0) + && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0)) + { + current_input_method = i; + break; + } + } } @@ -2040,7 +2444,7 @@ FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data) m17n_object_unref (mt); if (fp) { - mt = mconv_decode_stream (Mcoding_utf_8, fp); + mt = mconv_decode_stream (Mcoding_utf_8_full, fp); fclose (fp); if (! mt) mt = mtext (); @@ -2121,7 +2525,8 @@ create_menu_button (Widget top, Widget parent, Widget left, char *button_name, XtSetArg (arg[3], XtNhighlightThickness, 1); XtSetArg (arg[4], XtNleft, XawChainLeft); XtSetArg (arg[5], XtNright, XawChainLeft); - i = 6; + XtSetArg (arg[6], XtNinternational, True); + i = 7; if (left) XtSetArg (arg[i], XtNfromHoriz, left), i++; button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent, @@ -2179,7 +2584,9 @@ XtActionsRec actions[] = { {"ButtonRelease", ButtonReleaseProc}, {"ButtonMotion", ButtonMoveProc}, {"Button2Press", Button2Proc}, - {"MenuHelp", MenuHelpProc} + {"MenuHelp", MenuHelpProc}, + {"FocusIn", FocusInProc}, + {"FocusOut", FocusOutProc} }; @@ -2199,8 +2606,14 @@ help_exit (char *prog, int exit_code) printf ("Display FILE on a window and allow users to edit it.\n"); printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n"); printf ("The following OPTIONs are available.\n"); + printf (" %-13s\n\t\t%s", "--fontset FONTSET", + "Use the specified fontset\n"); + printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n"); + printf (" %-13s\n\t\t%s", "--im INPUT-METHOD", + "Input method activated initially.\n"); printf (" %-13s %s", "--version", "print version number\n"); printf (" %-13s %s", "-h, --help", "print this message\n"); + exit (exit_code); } @@ -2209,6 +2622,9 @@ main (int argc, char **argv) { Widget form, BodyWidget, w; char *fontset_name = NULL; + char *font_name = NULL; + int fontsize = 0; + char *initial_input_method = NULL; int col = 80, row = 32; /* Translation table for TextWidget. */ String trans = ": Expose()\n\ @@ -2221,7 +2637,9 @@ main (int argc, char **argv) : Button2Press()"; /* Translation table for the top form widget. */ String trans2 = ": Key()\n\ - : Key()"; + : Key()\n\ + : FocusIn()\n\ + : FocusOut()"; String pop_face_trans = ": MenuHelp(Pop face property) highlight()\n\ : MenuHelp() reset()\n\ @@ -2235,11 +2653,13 @@ main (int argc, char **argv) int font_width, font_ascent, font_descent; int with_xim = 0; int i, j; + char *filter = NULL; + MFont *font = NULL; setlocale (LC_ALL, ""); /* Create the top shell. */ XtSetLanguageProc (NULL, NULL, NULL); - ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv, + ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv, NULL, sessionShellWidgetClass, NULL, 0); display = XtDisplay (ShellWidget); screen = XScreenNumberOfScreen (XtScreen (ShellWidget)); @@ -2252,8 +2672,8 @@ main (int argc, char **argv) help_exit (argv[0], 0); else if (! strcmp (argv[i], "--version")) { - printf ("medit (m17n library) %s\n", VERSION); - printf ("Copyright (C) 2003 AIST, JAPAN\n"); + printf ("m17n-edit (m17n library) %s\n", M17NLIB_VERSION_NAME); + printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 AIST, JAPAN\n"); exit (0); } else if (! strcmp (argv[i], "--geometry")) @@ -2262,44 +2682,70 @@ main (int argc, char **argv) if (sscanf (argv[i], "%dx%d", &col, &row) != 2) help_exit (argv[0], 1); } + else if (! strcmp (argv[i], "-s")) + { + i++; + fontsize = atoi (argv[i]); + if (fontsize < 0) + fontsize = 120; + } else if (! strcmp (argv[i], "--fontset")) { i++; fontset_name = strdup (argv[i]); } + else if (! strcmp (argv[i], "--font")) + { + i++; + font_name = strdup (argv[i]); + } + else if (! strcmp (argv[i], "--im")) + { + i++; + initial_input_method = strdup (argv[i]); + } else if (! strcmp (argv[i], "--with-xim")) { with_xim = 1; } + else if (! strcmp (argv[i], "--filter")) + { + i++; + filter = argv[i]; + } else if (argv[i][0] != '-') { filename = strdup (argv[i]); } else { - fprintf (stderr, "Unknown option: %s", argv[i]); + fprintf (stderr, "Unknown option: %s\n", argv[i]); help_exit (argv[0], 1); } } if (! filename) - help_exit (argv[0], 1); + filename = strdup ("/dev/null"); mdatabase_dir = "."; /* Initialize the m17n library. */ M17N_INIT (); if (merror_code != MERROR_NONE) FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!"); + minput_driver = &minput_gui_driver; mt = read_file (filename); serialized = 0; nchars = mtext_len (mt); + Mword = msymbol ("word"); + { MFace *face = mface (); - mface_put_prop (face, Mbackground, msymbol ("blue")); - mface_put_prop (face, Mforeground, msymbol ("yellow")); + mface_put_prop (face, Mforeground, msymbol ("blue")); + mface_put_prop (face, Mbackground, msymbol ("yellow")); + mface_put_prop (face, Mvideomode, Mreverse); selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE); m17n_object_unref (face); } @@ -2310,25 +2756,48 @@ main (int argc, char **argv) XA_TEXT = XInternAtom (display, "TEXT", False); XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False); XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); + Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text")); + if (Mcoding_compound_text == Mnil) + FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!"); + { MPlist *plist = mplist (); - MFace *face; MFont *font; mplist_put (plist, msymbol ("widget"), ShellWidget); - if (fontset_name) + if (fontset_name || font_name || fontsize > 0) { - MFontset *fontset = mfontset (fontset_name); - - face = mface (); - mface_put_prop (face, Mfontset, fontset); - m17n_object_unref (fontset); + MFace *face; + + if (font_name) + { + font = mfont_parse_name (font_name, Mnil); + if (font) + face = mface_from_font (font); + else + face = mface (); + } + else + face = mface (); + if (fontset_name) + { + MFontset *fontset = mfontset (fontset_name); + + mface_put_prop (face, Mfontset, fontset); + m17n_object_unref (fontset); + } + if (fontsize > 0) + mface_put_prop (face, Msize, (void *) fontsize); mplist_add (plist, Mface, face); m17n_object_unref (face); } frame = mframe (plist); + if (! frame) + FATAL_ERROR ("%s\n", "Fail to create a frame!"); m17n_object_unref (plist); - face_default = (MFace *) mframe_get_prop (frame, Mface); + face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface)); + default_face_list = mplist (); + mplist_add (default_face_list, Mt, face_default); face_default_fontset = mface (); mface_put_prop (face_default_fontset, Mfontset, mface_get_prop (face_default, Mfontset)); @@ -2366,6 +2835,8 @@ main (int argc, char **argv) mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh")); face_freesans = mface (); mface_put_prop (face_freesans, Mfamily, msymbol ("freesans")); + face_freeserif = mface (); + mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif")); face_freemono = mface (); mface_put_prop (face_freemono, Mfamily, msymbol ("freemono")); @@ -2376,7 +2847,7 @@ main (int argc, char **argv) MFont *dev_font = mfont (); MFont *thai_font = mfont (); MFont *tib_font = mfont (); - MFontset *fontset; + MFontset *fontset, *fontset_no_ctl; MSymbol unicode_bmp = msymbol ("unicode-bmp"); MSymbol no_ctl = msymbol ("no-ctl"); @@ -2387,25 +2858,27 @@ main (int argc, char **argv) mfont_put_prop (tib_font, Mfamily, msymbol ("mtib")); mfont_put_prop (tib_font, Mregistry, unicode_bmp); - fontset = mfontset_copy (mfontset (fontset_name), "no-ctl"); - mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil, + fontset = mfontset (fontset_name); + fontset_no_ctl = mfontset_copy (fontset, "no-ctl"); + m17n_object_unref (fontset); + mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil, latin_font, Mnil, 0); - mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil, + mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil, dev_font, no_ctl, 0); - mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil, + mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil, thai_font, no_ctl, 0); - mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil, + mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil, tib_font, no_ctl, 0); face_no_ctl_fontset = mface (); - mface_put_prop (face_no_ctl_fontset, Mfontset, fontset); - m17n_object_unref (fontset); + mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl); + m17n_object_unref (fontset_no_ctl); free (dev_font); free (thai_font); free (tib_font); } - setup_input_methods (with_xim); + setup_input_methods (with_xim, initial_input_method); gc = DefaultGC (display, screen); @@ -2505,12 +2978,12 @@ main (int argc, char **argv) SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0); for (i = 0; i < num_input_methods; i++) { - MInputMethod *im = input_method_table[i]; + InputMethodInfo *im = input_method_table + i; char *name1, *name2; if (im->language != Mnil && im->language != Mt) { - MSymbol sym = msymbol_get (im->language, Mlanguage); + MSymbol sym = mlanguage_name (im->language); if (sym == Mnil) name1 = msymbol_name (im->language); else @@ -2540,6 +3013,14 @@ main (int argc, char **argv) for (i = 0; i < num_input_methods + 2; i++) InputMethodMenus[i] = menus[i].w; + if (filter) + { + SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0); + w = create_menu_button (ShellWidget, HeadWidget, w, "Filter", + "Filter Menu", menus, 1, + "Select filter to run"); + } + input_status_width = font_width * 8; input_status_height = (font_ascent + font_descent) * 2.4; input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen), @@ -2554,7 +3035,7 @@ main (int argc, char **argv) = prop.color_left = prop.color_right = Mnil; prop.inner_hmargin = prop.inner_vmargin = 1; prop.outer_hmargin = prop.outer_vmargin = 0; - face_input_status = mface (); + face_input_status = mface_copy (face_default); mface_put_prop (face_input_status, Mbox, &prop); } @@ -2629,14 +3110,14 @@ main (int argc, char **argv) MSymbol fullname; if (sym != Mnil - && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil)) + && ((fullname = mlanguage_name (sym)) != Mnil)) { char *name = msymbol_name (fullname); char c = name[0]; - if (c >= 'A' && c <= 'Z') + if (c >= 'a' && c <= 'z') { - int idx = (c < 'U') ? (c - 'A') / 2 : 10; + int idx = (c < 'u') ? (c - 'a') / 2 : 10; pl = plist[idx]; if (! pl) @@ -2719,9 +3200,7 @@ main (int argc, char **argv) memset (&control, 0, sizeof control); control.two_dimensional = 1; control.enable_bidi = 1; -#if 0 control.anti_alias = 1; -#endif control.min_line_ascent = font_ascent; control.min_line_descent = font_descent; control.max_line_width = win_width; @@ -2743,7 +3222,8 @@ main (int argc, char **argv) if (current_input_context) minput_destroy_ic (current_input_context); for (i = 0; i < num_input_methods; i++) - minput_close_im (input_method_table[i]); + if (input_method_table[i].im) + minput_close_im (input_method_table[i].im); m17n_object_unref (frame); m17n_object_unref (mt); m17n_object_unref (face_xxx_large); @@ -2753,18 +3233,16 @@ main (int argc, char **argv) m17n_object_unref (face_times); m17n_object_unref (face_dv_ttyogesh); m17n_object_unref (face_freesans); + m17n_object_unref (face_freeserif); m17n_object_unref (face_freemono); m17n_object_unref (face_default_fontset); m17n_object_unref (face_no_ctl_fontset); m17n_object_unref (face_input_status); + m17n_object_unref (face_default); + m17n_object_unref (default_face_list); m17n_object_unref (selection); - - M17N_FINI (); - - free (fontset_name); - free (filename); - free (input_method_table); - free (InputMethodMenus); + if (font) + free (font); XFreeGC (display, mono_gc); XFreeGC (display, mono_gc_inv); @@ -2774,6 +3252,27 @@ main (int argc, char **argv) XtDestroyWidget (ShellWidget); XtDestroyApplicationContext (context); + M17N_FINI (); + + free (font_name); + free (fontset_name); + free (filename); + free (input_method_table); + free (InputMethodMenus); + exit (0); } + +#else /* not HAVE_X11_XAW_COMMAND_H */ + +int +main (int argc, char **argv) +{ + fprintf (stderr, + "Building of this program failed (lack of some header files)\n"); + exit (1); +} + +#endif /* not HAVE_X11_XAW_COMMAND_H */ + #endif /* not FOR_DOXYGEN */