田中@東大情報工学です。 その後、いろいろ fix したりして割とまともにうごくようになりました。 やはりオリジナル版より重くなってますが、なんとか耐えられると思います。 ------------------------------------------------------------ 田中伸哉(たなか・しんや) tanaka@garlic.q.t.u-tokyo.ac.jp diff -c org/gtktext.c new/gtktext.c *** org/gtktext.c Sun May 10 13:17:27 1998 --- new/gtktext.c Fri Jun 12 17:02:13 1998 *************** *** 29,34 **** --- 29,38 ---- #include "line-wrap.xbm" #include "line-arrow.xbm" + #ifdef JP_HACK + #include "gdk/gdki18n.h" + #include + #endif #define INITIAL_BUFFER_SIZE 1024 #define INITIAL_LINE_CACHE_SIZE 256 *************** *** 102,107 **** --- 106,114 ---- GdkFont *gdk_font; gint16 char_widths[256]; + #ifdef JP_HACK + gint16 mbchar_width; /* supports only Fixed-width multibyte characters */ + #endif }; struct _TextProperty *************** *** 412,417 **** --- 419,433 ---- NULL, /* z */ }; + #ifdef JP_HACK + static gboolean jptext_is_boundary( GtkText* text, gint index ); + #define GTK_TEXT_INDEX_P(t, index) \ + ((index) < (t)->gap_position ? &((t)->text[index]) : \ + &((t)->text[(index) + (t)->gap_size]) ) + #define GTK_TEXT_INDEX_I(t, index) \ + ((index) < (t)->gap_position ? (index) : \ + ((index) + (t)->gap_size) ) + #endif /**********************************************************************/ /* Widget Crap */ *************** *** 768,773 **** --- 784,794 ---- if (nchars > text->point.index || nchars <= 0) return FALSE; + #ifdef JP_HACK + while ( !jptext_is_boundary( text, text->point.index-nchars ) ) + nchars++; + #endif + gtk_text_set_point (text, text->point.index - nchars); return gtk_text_forward_delete (text, nchars); *************** *** 787,792 **** --- 808,818 ---- if (text->point.index + nchars > TEXT_LENGTH (text) || nchars <= 0) return FALSE; + #ifdef JP_HACK + while ( !jptext_is_boundary( text, text->point.index+nchars ) ) + nchars++; + #endif + if (!text->freeze && (nchars > FREEZE_LENGTH)) { gtk_text_freeze (text); *************** *** 1609,1614 **** --- 1635,1652 ---- gtk_text_forward_delete (text, end_pos - start_pos); } + #ifdef JP_HACK + static void + check_event_state(GdkEventKey* event) + { + /* kinput2経由で漢字を入力すると、どういう理由かわからないが + event->state == 0 でなくなる場合がある */ + if ( mblen(event->string, MB_CUR_MAX) >= 2 ) { /* if multibyte */ + event->state = 0; + } + } + #endif + static gint gtk_text_key_press (GtkWidget *widget, GdkEventKey *event) *************** *** 1622,1627 **** --- 1660,1667 ---- g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); + check_event_state(event); + return_val = FALSE; text = GTK_TEXT (widget); *************** *** 1762,1767 **** --- 1802,1810 ---- case GDK_Escape: /* Don't insert literally */ return_val = FALSE; + #if 1 + g_print( "%d, %d\n", text->cursor_mark.index, text->cursor_pos_x ); + #endif break; default: *************** *** 1803,1809 **** gtk_text_insert_1_at_point (text, event->string[0]); gtk_editable_changed (editable); } ! return_val = TRUE; } else --- 1846,1861 ---- gtk_text_insert_1_at_point (text, event->string[0]); gtk_editable_changed (editable); } ! #ifdef JP_HACK ! else /* multibyte input */ ! { ! gint tmp_pos = editable->current_pos; ! gtk_editable_delete_selection (editable); ! gtk_text_insert_text (editable, event->string, event->length, ! &tmp_pos); ! editable->current_pos = tmp_pos; ! } ! #endif return_val = TRUE; } else *************** *** 2462,2467 **** --- 2514,2522 ---- for(i = 0; i < 256; i += 1) tf->char_widths[i] = gdk_char_width (gfont, (char)i); + #ifdef JP_HACK + tf->mbchar_width = gdk_text_width( gfont, "あ", 2 ); + #endif g_hash_table_insert (font_cache_table, gfont, tf); *************** *** 2587,2593 **** SET_PROPERTY_MARK (&text->point, MARK_PREV_LIST_PTR (mark), backward_prop->length); ! backward_prop->length += len; } else if ((MARK_NEXT_LIST_PTR(mark) == NULL) && --- 2642,2651 ---- SET_PROPERTY_MARK (&text->point, MARK_PREV_LIST_PTR (mark), backward_prop->length); ! #ifdef JP_HACK ! text->point.owner = text; ! #endif ! backward_prop->length += len; } else if ((MARK_NEXT_LIST_PTR(mark) == NULL) && *************** *** 2615,2620 **** --- 2673,2681 ---- new_prop->data = new_text_property (font, fore, back, len); SET_PROPERTY_MARK (mark, new_prop, 0); + #ifdef JP_HACK + mark->owner = text; + #endif } } else *************** *** 2641,2646 **** --- 2702,2710 ---- MARK_NEXT_LIST_PTR(mark) = new_prop; SET_PROPERTY_MARK (mark, new_prop, 0); + #ifdef JP_HACK + mark->owner = text; + #endif } else { *************** *** 2673,2678 **** --- 2737,2745 ---- next->prev = new_prop_forward; SET_PROPERTY_MARK (mark, new_prop, 0); + #ifdef JP_HACK + mark->owner = text; + #endif } } *************** *** 2761,2767 **** text->text_properties_end = text->text_properties; SET_PROPERTY_MARK (&text->point, text->text_properties, 0); ! text->point.index = 0; } } --- 2828,2836 ---- text->text_properties_end = text->text_properties; SET_PROPERTY_MARK (&text->point, text->text_properties, 0); ! #ifdef JP_HACK ! text->point.owner = text; ! #endif text->point.index = 0; } } *************** *** 2794,2799 **** --- 2863,2869 ---- static void advance_mark (GtkPropertyMark* mark) { + TextProperty* prop = MARK_CURRENT_PROPERTY (mark); mark->index += 1; *************** *** 2852,2857 **** --- 2922,2930 ---- gint diffb; GtkPropertyMark mark; + #ifdef JP_HACK + mark.owner = text; + #endif if (!near) diffa = mark_position + 1; *************** *** 2984,2989 **** --- 3057,3063 ---- { gchar ch; gint16* char_widths; + static gint mb_width = 0; if (LAST_INDEX (text, *mark)) return 0; *************** *** 2995,3004 **** --- 3069,3097 ---- { return tab_mark->to_next_tab * char_widths[' ']; } + #ifdef JP_HACK + else + { + gint nchar = mblen( GTK_TEXT_INDEX_P(text, mark->index), MB_CUR_MAX ); + gboolean boundary = jptext_is_boundary( text, mark->index ); + if ( nchar >= 2 ) + { + if ( boundary ) /* multibyte head */ + return MARK_CURRENT_TEXT_FONT (mark)->mbchar_width; + else /* multibyte trail */ + return 0; + } + else if ( nchar < 0 ) /* illegal */ + return 0; + else + return char_widths[ch & 0xff]; + } + #else else { return char_widths[ch & 0xff]; } + #endif } static void *************** *** 3042,3048 **** while (mark.index < text->cursor_mark.index) { ! pixel_width += find_char_width (text, &mark, &tab_mark); advance_tab_mark (text, &tab_mark, GTK_TEXT_INDEX(text, mark.index)); advance_mark (&mark); --- 3135,3142 ---- while (mark.index < text->cursor_mark.index) { ! gint w = find_char_width (text, &mark, &tab_mark); ! pixel_width += w; advance_tab_mark (text, &tab_mark, GTK_TEXT_INDEX(text, mark.index)); advance_mark (&mark); *************** *** 3122,3127 **** --- 3216,3225 ---- if (button_x < pixel_width || mark.index == lp->end.index) { + #ifdef JP_HACK + while ( !jptext_is_boundary(text, mark.index) ) + advance_mark (&mark); + #endif text->cursor_pos_x = pixel_width - (char_width+1)/2; text->cursor_mark = mark; text->cursor_char_offset = lp->font_descent; *************** *** 3303,3308 **** --- 3401,3411 ---- if (LAST_INDEX(text, mark) || GTK_TEXT_INDEX(text, mark.index) == LINE_DELIM) break; + #ifdef JP_HACK + if ( !jptext_is_boundary( text, mark.index ) ) + advance_mark (&mark); + #endif + undraw_cursor (text, FALSE); text->cursor_mark = mark; *************** *** 3328,3333 **** --- 3431,3444 ---- undraw_cursor (text, FALSE); + #ifdef JP_HACK + if (count == 1) + while ( !jptext_is_boundary( text, text->point.index+count ) ) + count++; + else if (count == -1) + while ( !jptext_is_boundary( text, text->point.index+count ) ) + count--; + #endif move_mark_n (&text->cursor_mark, count); find_cursor (text, TRUE); *************** *** 3922,3927 **** --- 4033,4043 ---- lp.font_ascent = 0; lp.font_descent = 0; + #ifdef JP_HACK + while ( !jptext_is_boundary( text, lp.start.index ) ) + advance_mark (&lp.start); + #endif + init_tab_cont (text, next_cont); while (!LAST_INDEX(text, lp.end)) *************** *** 4807,4810 **** --- 4923,4964 ---- if (proplen - 1 != TEXT_LENGTH(text)) g_warning ("incorrect property list length in %s:%d -- bad!", msg, line); } + #endif + + #ifdef JP_HACK + + /* + * これぐらい前から調べれば,正しい文字境界がわかるんじゃないかという甘い予想値 + */ + #define MAGIC_NUMBER 4 + + static + gboolean jptext_is_boundary( GtkText* text, gint index ) + { + static gint cache = 0; + gint i; + gint charlen; + if ( cache < index ) + i = cache; + else if ( index > MAGIC_NUMBER ) + i = index-MAGIC_NUMBER; + else + i = 0; + + while ( i < index ) + { + gchar* p = GTK_TEXT_INDEX_P( text, i ); + charlen = mblen( p, MB_CUR_MAX ); + charlen = charlen <= 0 ? 1 : charlen; + i += charlen; + } + if ( i == index ) + { + cache = index; + return TRUE; + } + else + return FALSE; + } + #endif diff -c org/gtktext.h new/gtktext.h *** org/gtktext.h Mon Apr 13 11:02:00 1998 --- new/gtktext.h Fri Jun 12 16:26:45 1998 *************** *** 19,24 **** --- 19,25 ---- #ifndef __GTK_TEXT_H__ #define __GTK_TEXT_H__ + #define JP_HACK #include #include *************** *** 49,54 **** --- 50,60 ---- /* Current index. */ guint index; + + #ifdef JP_HACK + /* owner */ + GtkText* owner; + #endif }; struct _GtkText