X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=example%2Fmedit.c;h=b32052cbdbe6e89dd86231d9af7c11fbed676f5c;hb=74a65ebd93be6eb40eb5a9b44e1ef06e784c6a20;hp=1dc78af15997b61fed23656df32f4515118f60c4;hpb=336b5e6995bf5ea4d128c905c5f8a39af9ac40c3;p=m17n%2Fm17n-lib.git diff --git a/example/medit.c b/example/medit.c index 1dc78af..b32052c 100644 --- a/example/medit.c +++ b/example/medit.c @@ -1,5 +1,5 @@ /* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*- - Copyright (C) 2003, 2004 + Copyright (C) 2003, 2004, 2005 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H15PRO112 @@ -49,7 +49,7 @@ This program is to demonstrate how to use the m17n GUI API. Although m17n-edit directly uses the GUI API, the API is mainly - for toolkit libraries or to implement XOM (X Outout Method), not + for toolkit libraries or to implement XOM (X Output Method), not for direct use from application programs. */ /***ja @@ -81,7 +81,7 @@ ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥­¥Ã¥È¥é¥¤¥Ö¥é - ¥ê¤äXOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é + ¥ê¤äXOM (X Output Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£ */ @@ -97,6 +97,8 @@ #include #include +#ifdef HAVE_X11_XAW_COMMAND_H + #include #include #include @@ -107,8 +109,6 @@ #include #include -#ifdef HAVE_X11_XAW_COMMAND_H - #include #include #include @@ -173,6 +173,7 @@ Pixmap CheckPixmap; MFrame *frame; MText *mt; int nchars; /* == mtext_len (mt) */ +int mt_modified; MDrawControl control, input_status_control; MTextProperty *selection; @@ -257,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. */ }; @@ -391,12 +392,17 @@ redraw (int y0, int y1, int clear, int scroll_bar) info.metrics.height = line->y1 - y; info.metrics.y = - line->ascent; info.line_to = line->to; - while (from < nchars && y + info.metrics.height <= y0) + while (y + info.metrics.height <= y0) { y += info.metrics.height; from = info.line_to; + if (from >= nchars) + break; GLYPH_INFO (from, from, info); } + if (y + info.metrics.height <= y0) + return; + y0 = y - info.metrics.y; to = from; while (to < nchars && y < y1) @@ -661,53 +667,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) { 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->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->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); } @@ -811,8 +865,7 @@ show_cursor (XtPointer client_data) else { XtSetArg (arg[0], XtNborderWidth, 1); - XtSetArg (arg[1], XtNlabel, - msymbol_name (msymbol_get (sym, Mlanguage))); + XtSetArg (arg[1], XtNlabel, mlanguage_name (sym)); XtSetValues (CurLangWidget, arg, 2); } XtSetValues (CurLangWidget, arg, 2); @@ -826,24 +879,11 @@ 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 - && input_method_table[i].available >= 0) - { - if (! input_method_table[i].im) - { - input_method_table[i].im = - minput_open_im (input_method_table[i].language, - input_method_table[i].name, NULL); - if (! input_method_table[i].im) - input_method_table[i].available = -1; - } - if (input_method_table[i].im) - select_input_method (i); - else - select_input_method (-1); - } + if (i < num_input_methods) + select_input_method (i); else select_input_method (-1); } @@ -910,6 +950,8 @@ delete_char (int n) 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. */ @@ -923,13 +965,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; } } @@ -1191,18 +1226,12 @@ ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num) update_cursor (0, 1); redraw (0, win_height, 0, 1); if (current_input_method >= 0) - { - int idx = current_input_method; + { + int idx = current_input_method; - current_input_method = -1; - input_method_table[idx].im = - minput_open_im (input_method_table[idx].language, - input_method_table[idx].name, NULL); - if (input_method_table[idx].im) + current_input_method = -1; select_input_method (idx); - else - input_method_table[idx].available = -1; - } + } show_cursor (NULL); } else @@ -1247,12 +1276,12 @@ ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num) redraw (sel_start.y0, sel_end.y1, 1, 0); } hide_cursor (); - if (current_input_context) + if (current_input_context + && minput_filter (current_input_context, Minput_focus_move, NULL) == 0) { MText *produced = mtext (); - minput_reset_ic (current_input_context); - minput_lookup (current_input_context, Mnil, NULL, produced); + minput_lookup (current_input_context, Mnil, NULL, produced); if (mtext_len (produced) > 0) { insert_chars (produced); @@ -1405,6 +1434,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; @@ -1496,15 +1561,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) @@ -1907,42 +1983,33 @@ 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 if (input_method_table[idx].available >= 0) + else { - if (! input_method_table[idx].im) - { - input_method_table[idx].im = - minput_open_im (input_method_table[idx].language, - input_method_table[idx].name, NULL); - if (! input_method_table[idx].im) - input_method_table[idx].available = -1; - } - if (input_method_table[idx].im) - select_input_method (idx); + select_input_method (idx); } - XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); - XtSetValues (InputMethodMenus[idx + 2], arg, 1); } MPlist *default_face_list; @@ -2110,6 +2177,60 @@ 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 = NULL; + + 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); + } + if (surround) + { + 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) { @@ -2125,93 +2246,83 @@ 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, char *initial_input_method) { - MInputMethod *im = NULL; MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil); MPlist *pl; - int i = 0; - char *lang_name = NULL, *method_name = NULL; - - if (initial_input_method) - { - char *p = strchr (initial_input_method, '-'); - if (p) - lang_name = initial_input_method, method_name = p + 1, *p = '\0'; - else - method_name = initial_input_method; - } + int i; num_input_methods = plist ? mplist_length (plist) : 0; - if (with_xim) - { - 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 = minput_open_im (Mnil, msymbol ("xim"), &arg_xim); - if (im) - num_input_methods++; - } + num_input_methods++; input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo)); - if (im) - { - input_method_table[i].available = 1; - input_method_table[i].language = Mnil; - input_method_table[i].name = im->name; - input_method_table[i].im = im; - i++; - } + i = 0; if (plist) { - for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl)) + for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++) { MDatabase *mdb = mplist_value (pl); MSymbol *tag = mdatabase_tag (mdb); - if (tag[1] != Mnil) + if (tag[2] == Mnil) + i--, num_input_methods--; + else { input_method_table[i].language = tag[1]; input_method_table[i].name = tag[2]; - i++; } } - m17n_object_unref (plist); } - num_input_methods = i; + if (with_xim) + { + input_method_table[i].language = Mnil; + input_method_table[i].name = msymbol ("xim"); + i++; + } + qsort (input_method_table, num_input_methods, sizeof input_method_table[0], compare_input_method); - current_input_context = NULL; - 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); + mplist_put (minput_driver->callback_list, Minput_get_surrounding_text, + (void *) surrounding_text_handler); + mplist_put (minput_driver->callback_list, Minput_delete_surrounding_text, + (void *) surrounding_text_handler); - if (method_name) - for (i = 0; i < num_input_methods; i++) - if (strcmp (method_name, msymbol_name (input_method_table[i].name)) == 0 - && (lang_name - ? strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0 - : input_method_table[i].language == Mt)) - { - current_input_method = i; - break; - } + 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; + + 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; + } + } } @@ -2452,7 +2563,9 @@ XtActionsRec actions[] = { {"ButtonRelease", ButtonReleaseProc}, {"ButtonMotion", ButtonMoveProc}, {"Button2Press", Button2Proc}, - {"MenuHelp", MenuHelpProc} + {"MenuHelp", MenuHelpProc}, + {"FocusIn", FocusInProc}, + {"FocusOut", FocusOutProc} }; @@ -2488,6 +2601,7 @@ 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; @@ -2502,7 +2616,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\ @@ -2517,6 +2633,7 @@ main (int argc, char **argv) int with_xim = 0; int i, j; char *filter = NULL; + MFont *font = NULL; setlocale (LC_ALL, ""); /* Create the top shell. */ @@ -2556,6 +2673,11 @@ main (int argc, char **argv) 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++; @@ -2619,18 +2741,32 @@ main (int argc, char **argv) { MPlist *plist = mplist (); - MFace *face; MFont *font; mplist_put (plist, msymbol ("widget"), ShellWidget); - if (fontset_name || fontsize > 0) + if (fontset_name || font_name || fontsize > 0) { - MFontset *fontset = mfontset (fontset_name); - - face = mface (); - mface_put_prop (face, Mfontset, fontset); - mface_put_prop (face, Msize, (void *) fontsize); - 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); } @@ -2690,7 +2826,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"); @@ -2701,18 +2837,20 @@ 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); @@ -2824,7 +2962,7 @@ main (int argc, char **argv) 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 @@ -2951,7 +3089,7 @@ 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]; @@ -3082,6 +3220,8 @@ main (int argc, char **argv) m17n_object_unref (face_default); m17n_object_unref (default_face_list); m17n_object_unref (selection); + if (font) + free (font); XFreeGC (display, mono_gc); XFreeGC (display, mono_gc_inv); @@ -3093,6 +3233,7 @@ main (int argc, char **argv) M17N_FINI (); + free (font_name); free (fontset_name); free (filename); free (input_method_table);