// classes for preedit draw #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "xim.h" #include "kkconv.h" #include "convdisp.h" #include "xdispatch.h" #include "gtkdispatch.h" #define INVALID_POS -1 // // PeWinプリエディット用の基本ウィンドウ // PeLineWin root window style // PeOvWin over the spot // CandidateWin 候補表示用のウィンドウ //IMEはインタラクティブである必要があるので、気安くXFlushを使う。 static XFontSet gFontset; void init_convdisp() { char **missing, *def; int nr_missing; gFontset = XCreateFontSet(gDpy, "-misc-fixed-medium-r-normal--14-110-100-100-c-70-iso8859-1," "-misc-fixed-medium-r-normal--14-130-75-75-c-140-jisx0208.1983-0," "-misc-fixed-medium-r-normal--14-130-75-75-c-70-jisx0201.1976-0", &missing, &nr_missing, &def); // ktermの使うフォントセットを取ってきた。 if (missing) { XFreeStringList(missing); } } struct char_ent { cchar c; int stat; int width; int height; int x, y; }; // プリエディットWindow class PeWin : public WindowIf { public: PeWin(Window pw); virtual ~PeWin(); virtual void release(); virtual void destroy(Window); void expose(Window w); void draw_char(int x,int y,cchar ch,int stat); void set_back(unsigned long p); void set_fore(unsigned long p); void set_fontset(XFontSet f); virtual void set_size(int w,int h); void set_pos(int x,int y); void do_map(); void clear(); void draw(); void unmap(); protected: Window mParentWin; Window mWin; Pixmap mPixmap; GC mGC,mClearGC; GC mHilitGC; unsigned int mFore,mBack; XFontSet mFontset; int mWidth,mHeight; bool mIsMapped; }; // RootWindowStyle用の1行ウィンドウ class PeLineWin : public PeWin { public: PeLineWin(Window w); virtual ~PeLineWin(); void draw_pe(pe_stat *p); void draw_segment(pe_jstring *s); private: void calc_extent(pe_stat *p); int m_x; }; // over the spot用のウィンドウ class PeOvWin : public PeWin { public: PeOvWin(Window w); void draw_ce(char_ent *ce,int len); virtual void set_size(int w,int h); virtual ~PeOvWin(); private: void draw_a_ce(char_ent *ce); Pixmap m_mask_pix; GC m_mask_pix_gc; }; // //候補表示用のウィンドウ // ConvdispOvの作成時と破棄時にそれぞれ作成、破棄される // class CandidateWin : WidgetIf{ public: CandidateWin(Convdisp *); virtual ~CandidateWin(); void update(pe_stat *); virtual void select_row(GtkWidget *,int,int ); virtual void key_press(GtkWidget *w,GdkEventKey *e); void set_pos(int x, int y); void show(); void hide(); private: void build_candidate_list(); bool trim_base_row(); GtkWidget *top_win; GtkWidget *clist; Convdisp *mConvdisp; pe_stat *m_pe; bool bInit; int m_select_count; int m_base_row; }; class ConvdispOv : public Convdisp{ public: ConvdispOv(KKContext *,icxatr *); virtual ~ConvdispOv(); void update_preedit(); virtual void update_icxatr(); virtual void set_focus(); virtual void unset_focus(); private: bool check_win(); bool check_atr(); void layoutCharEnt(); void make_ce_array(); void drawPreedit(); void do_draw_preedit(); int calc_ce_width(int b,int e); void validate_area(); char_ent *m_ce; int m_ce_len; PeOvWin *m_ov_win; }; // RootWindowスタイル class ConvdispRw : public Convdisp{ public: ConvdispRw(KKContext *,icxatr *); virtual ~ConvdispRw(); void update_preedit(); virtual void update_icxatr(); private: PeLineWin *mPeWin; }; class Connection; class ConvdispOs : public Convdisp{ public: ConvdispOs(KKContext *,icxatr *,Connection *); virtual ~ConvdispOs(); virtual void update_preedit(); virtual void update_icxatr(); virtual void set_focus(); virtual void unset_focus(); private: void compose_preedit_array(TxPacket *); void compose_feedback_array(TxPacket *); void update_CandidateWin(); Connection *mConn; int mImid,mIcid; int mPrevLen; }; CandidateWin *g_cur_cand_win; Convdisp *create_convdisp(int style, KKContext *k, icxatr *a, Connection *c) { switch (style) { case IS_ROOT_WINDOW: return new ConvdispRw(k, a); case IS_OVER_THE_SPOT: return new ConvdispOv(k, a); case IS_ON_THE_SPOT: return new ConvdispOs(k, a, c); default: break; } return 0; } // // PeWin(PreeEdit Window) // PeWin::PeWin(Window pw) { mParentWin = pw; int scr_num = DefaultScreen(gDpy); // とりあえずテキトー mWidth = 1; mHeight = 1; mWin = XCreateSimpleWindow(gDpy, mParentWin, 0, 0, mWidth, mHeight, 0, BlackPixel(gDpy, scr_num), WhitePixel(gDpy, scr_num)); XSetWindowAttributes attr; attr.override_redirect = True; XChangeWindowAttributes(gDpy, mWin, CWOverrideRedirect, &attr); mPixmap = XCreatePixmap(gDpy, DefaultRootWindow(gDpy), mWidth, mHeight, DefaultDepth(gDpy, scr_num)); mGC = XCreateGC(gDpy, mPixmap, 0, 0); mClearGC = XCreateGC(gDpy, mPixmap, 0, 0); mHilitGC = XCreateGC(gDpy, mPixmap, 0, 0); XSetBackground(gDpy, mGC, WhitePixel(gDpy, scr_num)); XSetForeground(gDpy, mGC, BlackPixel(gDpy, scr_num)); XSetForeground(gDpy, mClearGC, WhitePixel(gDpy, scr_num)); XSetBackground(gDpy, mClearGC, BlackPixel(gDpy, scr_num)); add_window_watch(mWin, this, EXPOSE_MASK|STRUCTURE_NOTIFY_MASK); mIsMapped = false;//マップされてない mFontset = gFontset; XFlush(gDpy); } PeWin::~PeWin() { if (mWin) { release(); } XFreePixmap(gDpy, mPixmap); XFreeGC(gDpy, mGC); XFreeGC(gDpy, mClearGC); XFreeGC(gDpy, mHilitGC); XFlush(gDpy); } void PeWin::release() { remove_window_watch(mWin); XDestroyWindow(gDpy, mWin); mWin = 0; } void PeWin::destroy(Window w) { if (mWin && mWin == w) { mWin = 0; } } void PeWin::expose(Window w) { XCopyArea(gDpy, mPixmap, mWin, mGC, 0, 0, mWidth, mHeight, 0, 0); XFlush(gDpy); } void PeWin::draw_char(int x,int y,cchar ch,int stat) { GC gc = mGC; if (stat & PE_REVERSE) { gc = mClearGC; } if (stat & PE_HILIGHT) { //gc = mHilitGC; } if (ch < 256) { char c = ch; XmbDrawImageString(gDpy, mPixmap, mFontset, gc, x, y, &c, 1); } else { unsigned char c[2]; c[0] = ((ch >>8)&255)|0x80; c[1] = (ch & 255)|0x80; XmbDrawImageString(gDpy, mPixmap, mFontset, gc, x, y, (char *)c, 2); } } void PeWin::set_back(unsigned long p) { mBack = p; XSetBackground(gDpy, mGC, p); XSetForeground(gDpy, mClearGC, p); } void PeWin::set_fore(unsigned long p) { mFore = p; XSetForeground(gDpy, mGC, p); XSetBackground(gDpy, mClearGC, p); } void PeWin::set_fontset(XFontSet f) { mFontset = f; } void PeWin::set_size(int w, int h) { if (w == mWidth && h == mHeight) { return ; } XResizeWindow(gDpy, mWin, w, h); XFreePixmap(gDpy, mPixmap); mPixmap =XCreatePixmap(gDpy, DefaultRootWindow(gDpy), w, h, DefaultDepth(gDpy, DefaultScreen(gDpy))); mWidth = w; mHeight = h; clear(); } void PeWin::set_pos(int x, int y) { XWindowChanges ch; ch.x = x; ch.y = y; XConfigureWindow(gDpy, mWin, CWX|CWY, &ch); } void PeWin::do_map() { if (!mIsMapped) { XFlush(gDpy); XMapRaised(gDpy, mWin); mIsMapped = true; } } void PeWin::clear() { XFillRectangle(gDpy, mPixmap, mClearGC, 0, 0, mWidth, mHeight); } void PeWin::draw() { if (!mIsMapped) { do_map(); } else { expose(mWin); } } void PeWin::unmap() { if (mIsMapped) { XUnmapWindow(gDpy, mWin); XFlush(gDpy); mIsMapped = false; } } // // PeLineWin // PeLineWin::PeLineWin(Window w) : PeWin(w) { set_size(400, 40); clear(); } PeLineWin::~PeLineWin() { } void PeLineWin::draw_pe(pe_stat *p) { clear(); calc_extent(p); m_x = 0; std::list::iterator i; for (i = p->jstrings.begin(); i != p->jstrings.end(); i++) { draw_segment(&(*i)); } } void PeLineWin::draw_segment(pe_jstring *s) { jstring_t::iterator i; for (i = s->s.begin(); i != s->s.end(); i++) { cchar ch= *i; draw_char(m_x, 20, ch, s->stat); m_x += 20; } } void PeLineWin::calc_extent(pe_stat *p) { int c; c = p->get_char_count(); set_size(400, 40); } // // PeOvWin // PeOvWin::PeOvWin(Window w) : PeWin(w) { m_mask_pix = 0; m_mask_pix_gc = 0; } PeOvWin::~PeOvWin() { if (m_mask_pix) { XFreePixmap(gDpy, m_mask_pix); XFreeGC(gDpy, m_mask_pix_gc); } } void PeOvWin::set_size(int w, int h) { if (w == mWidth && h == mHeight) { return ; } PeWin::set_size(w, h); if (m_mask_pix) { XFreePixmap(gDpy, m_mask_pix); m_mask_pix = XCreatePixmap(gDpy, mWin, mWidth, mHeight, 1); } } void PeOvWin::draw_ce(char_ent *ce, int len) { if (m_mask_pix == 0) { m_mask_pix = XCreatePixmap(gDpy, mWin, mWidth, mHeight, 1); m_mask_pix_gc = XCreateGC(gDpy, m_mask_pix, 0, 0); } clear(); XSetForeground(gDpy, m_mask_pix_gc, BlackPixel(gDpy, DefaultScreen(gDpy))); XFillRectangle(gDpy, m_mask_pix, m_mask_pix_gc, 0, 0, mWidth, mHeight); XSetForeground(gDpy, m_mask_pix_gc, WhitePixel(gDpy, DefaultScreen(gDpy))); int i; for (i = 0; i < len; i++) { draw_a_ce(&ce[i]); } XShapeCombineMask(gDpy, mWin, ShapeBounding, 0, 0, m_mask_pix, ShapeSet); do_map(); } void PeOvWin::draw_a_ce(char_ent *ce) { draw_char(ce->x, ce->y, ce->c, ce->stat); XFillRectangle(gDpy, m_mask_pix, m_mask_pix_gc, ce->x, ce->y - ce->height + 2, ce->width, ce->height+1); if (ce->stat & PE_UNDERLINE) { XDrawLine(gDpy, mPixmap, mGC, ce->x, ce->y+2, ce->x+ce->width, ce->y + 2); } } // // // CandidateWin::CandidateWin(Convdisp *c) { mConvdisp = c; gchar *titles[2]={"index","候補"}; bInit = false; m_pe = 0; top_win = gtk_window_new(GTK_WINDOW_POPUP); gtk_widget_set_usize(top_win, CAND_WIN_WIDTH, CAND_WIN_HEIGHT); clist = gtk_clist_new_with_titles(2, titles); gtk_container_add(GTK_CONTAINER(top_win), clist); gtk_clist_set_column_width(GTK_CLIST(clist), 0, 50); gtk_clist_set_column_width(GTK_CLIST(clist), 1, 150); gtk_widget_show(clist); add_widget_watch(clist, WIDGET_ROW_SELECTED, this); add_widget_watch(top_win, WIDGET_KEY_PRESS, this); m_select_count = 0; } CandidateWin::~CandidateWin() { if (g_cur_cand_win == this) { g_cur_cand_win = 0; } gtk_widget_destroy(top_win); } void CandidateWin::select_row(GtkWidget *w, int row, int col) { if (m_select_count == 0) { m_pe->cands->nth = row; mConvdisp->candidate_selected(row); }else{ m_select_count --; } } void CandidateWin::key_press(GtkWidget *w, GdkEventKey *e) { keyState k(e); if (k.is_modifier()) { return ; } m_pe->cont->pushKey(&k); } void CandidateWin::set_pos(int x, int y) { if (x == INVALID_POS) { x = (gdk_screen_width() - CAND_WIN_WIDTH) / 2; } if (y == INVALID_POS) { y = gdk_screen_height() - CAND_WIN_HEIGHT; } gtk_widget_set_uposition(top_win, x, y); } void CandidateWin::update(pe_stat *pe) { m_pe = pe; if (pe->cands) { int nth = m_pe->cands->nth; if (!bInit) { m_base_row = 0; bInit = true; build_candidate_list(); m_select_count = 1; } if (trim_base_row()) { build_candidate_list(); m_select_count = 1; } show(); gtk_clist_select_row((GtkCList*)clist, nth-m_base_row, 0); m_select_count ++; } else { bInit = false; gtk_widget_hide(top_win); gtk_clist_clear((GtkCList*)clist); } } bool CandidateWin::trim_base_row() { int nth = m_pe->cands->nth; if (m_base_row +CAND_COUNT > nth && m_base_row <= nth) { return false; } while (m_base_row +CAND_COUNT <= nth) { m_base_row += CAND_COUNT; } while (m_base_row > nth) { m_base_row -=CAND_COUNT; } return true; } void CandidateWin::build_candidate_list() { int i; int size = m_pe->cands->cands.size(); char idx[12]; char *buf[2]; gtk_clist_clear((GtkCList*)clist); for (i = m_base_row; i < (int)size && i < m_base_row + CAND_COUNT; i++) { char *c; if (i == m_base_row && i > 0) { sprintf(idx,"%d(<<)",i+1); } else if (i == m_base_row + CAND_COUNT - 1 && i < size) { sprintf(idx,"%d(>>)", i+1); } else { sprintf(idx,"%d", i+1); } c = jstring_to_str(&m_pe->cands->cands[i]); buf[0]= idx; buf[1] = c; gtk_clist_append((GtkCList*)clist, buf); free(c); } sprintf(idx, "(%d/%d)", m_base_row, size); buf[0] = "候補数"; buf[1] = idx; gtk_clist_append((GtkCList*)clist, buf); } void CandidateWin::show() { if (m_pe && m_pe->cands && bInit) { if (g_cur_cand_win && g_cur_cand_win !=this) { g_cur_cand_win->hide(); } g_cur_cand_win = this; gtk_widget_show(top_win); } } void CandidateWin::hide() { gtk_widget_hide(top_win); } // // // Convdisp::Convdisp(KKContext *k, icxatr *a) { mKkContext = k; m_atr = a; m_cands_win = new CandidateWin(this); } Convdisp::~Convdisp() { delete m_cands_win; } void Convdisp::set_pe(pe_stat *p) { m_pe = p; } void Convdisp::candidate_selected(int n) { if (n == 12) { return ; } mKkContext->candidate_selected(n); } //ルートウィンドウスタイル ConvdispRw::ConvdispRw(KKContext *k, icxatr *a) : Convdisp(k, a) { mPeWin = new PeLineWin(DefaultRootWindow(gDpy)); } ConvdispRw::~ConvdispRw() { delete mPeWin; } void ConvdispRw::update_preedit() { if (m_pe && m_pe->get_char_count()) { // preeditの中身が存在すれば mPeWin->do_map(); mPeWin->draw_pe(m_pe); mPeWin->draw(); } else { mPeWin->clear(); mPeWin->expose(0); XFlush(gDpy); } m_cands_win->set_pos(0, 0); m_cands_win->update(m_pe); } void ConvdispRw::update_icxatr() { } //Over the spot style ConvdispOv::ConvdispOv(KKContext *k, icxatr *a) : Convdisp(k, a) { m_ov_win = 0; } ConvdispOv::~ConvdispOv() { if (m_ov_win) { delete m_ov_win; } } void ConvdispOv::update_preedit() { if (!m_pe) { return ; } if (!m_pe->get_char_count()) { delete m_ov_win; m_ov_win = NULL; m_cands_win->update(m_pe); return ; } // preeditを書く drawPreedit(); // update candidate window if (m_atr->has_atr(ICA_FocusWindow) && m_atr->has_atr(ICA_SpotLocation)){ int x, y; Window win; XTranslateCoordinates(gDpy,m_atr->focus_window, DefaultRootWindow(gDpy), m_atr->spot_location.x, m_atr->spot_location.y, &x, &y, &win); if (x + CAND_WIN_WIDTH > scr_width) { x = scr_width - CAND_WIN_WIDTH; } if (x < 0) { x = 0; } if (y + CAND_WIN_HEIGHT > scr_height) { //上側に候補ウィンドウを出す。 y -= (CAND_WIN_HEIGHT+m_atr->line_space+2); }else{ // 下側に候補ウィンドウを出す。 y += 2; } m_cands_win->set_pos(x, y); }else{ m_cands_win->set_pos(INVALID_POS, INVALID_POS); } m_cands_win->update(m_pe); } void ConvdispOv::validate_area() { Window r, win; int x; unsigned int w, h, tmp; if (m_atr->has_atr(ICA_ClientWindow)) { win = m_atr->client_window; } else { win = m_atr->focus_window; } XGetGeometry(gDpy, win, &r, &x, &x, &w, &h, &tmp, &tmp); /* そんな無茶な,, (RedHat7.3のQt対策、たぶん他のQtもこの動作)*/ m_atr->area.width = w; m_atr->area.height = h; } void ConvdispOv::update_icxatr() { if (!m_ov_win) { return ; } if (m_atr->is_changed(ICA_FocusWindow)) { //なんか忘れたけど、FocusWindowを後から指定してくるものがある if (!check_win()) { return ; } } if (m_atr->is_changed(ICA_Area)) { if (m_atr->area.width == 0) { validate_area(); } m_ov_win->set_size(m_atr->area.width, m_atr->area.height); m_atr->unset_change_mask(ICA_Area); } if (m_atr->is_changed(ICA_Foreground)) { m_ov_win->set_fore(m_atr->foreground_pixel); m_atr->unset_change_mask(ICA_Foreground); } if (m_atr->is_changed(ICA_Background)) { m_ov_win->set_back(m_atr->background_pixel); m_atr->unset_change_mask(ICA_Background); } if (m_atr->is_changed(ICA_FontSet)) { m_ov_win->set_fontset(m_atr->font_set); m_atr->unset_change_mask(ICA_FontSet); } update_preedit(); } void ConvdispOv::set_focus() { m_cands_win->show(); } void ConvdispOv::unset_focus() { } void ConvdispOv::drawPreedit() { m_ce_len = m_pe->get_char_count(); if (!check_win()) { return ; } m_ce = (char_ent *)malloc(sizeof(char_ent)*m_ce_len); make_ce_array();//配列を準備して、 layoutCharEnt();//レイアウトして、 do_draw_preedit();//描画 free(m_ce); m_cands_win->update(m_pe); m_ov_win->draw(); XFlush(gDpy); } void ConvdispOv::do_draw_preedit() { m_ov_win->set_pos(0, 0); m_ov_win->draw_ce(m_ce, m_ce_len); } bool ConvdispOv::check_win() { if (!check_atr()) { //プリエディットウィンドウを出すのに十分な情報が無い。 return false; } if (m_ov_win && !m_atr->is_changed(ICA_FocusWindow)) { // ウィンドウをupdateする必要は無い。 return true; } if (m_ov_win) { delete m_ov_win; } m_atr->unset_change_mask(ICA_FocusWindow); m_atr->unset_change_mask(ICA_Foreground); m_atr->unset_change_mask(ICA_Background); m_atr->unset_change_mask(ICA_FontSet); Window w; if (m_atr->has_atr(ICA_ClientWindow)) { w = m_atr->client_window; } else { w = m_atr->focus_window; } m_ov_win = new PeOvWin(w); m_ov_win->set_size(m_atr->area.width, m_atr->area.height); m_ov_win->set_fore(m_atr->foreground_pixel); m_ov_win->set_back(m_atr->background_pixel); m_ov_win->set_fontset(m_atr->font_set); return true; } bool ConvdispOv::check_atr() { if (!m_atr->has_atr(ICA_FocusWindow) && !m_atr->has_atr(ICA_ClientWindow)) { return false; } if (!m_atr->has_atr(ICA_SpotLocation)) { //入力場所が未定なら左上 m_atr->spot_location.x = 0; m_atr->spot_location.y = 0; } if (!m_atr->has_atr(ICA_Area) || m_atr->area.width == 0) { validate_area(); m_atr->area.x = 0; m_atr->area.y = 0; } if (!m_atr->has_atr(ICA_FontSet)) { m_atr->font_set = gFontset; } if (!m_atr->has_atr(ICA_LineSpace)) { m_atr->line_space = 14; } if (!m_atr->has_atr(ICA_Foreground)) { m_atr->foreground_pixel = BlackPixel(gDpy, DefaultScreen(gDpy)); } if (!m_atr->has_atr(ICA_Background)) { m_atr->background_pixel = WhitePixel(gDpy, DefaultScreen(gDpy)); } return true; } void ConvdispOv::make_ce_array() { std::list::iterator i; jstring_t::iterator j; int s; int c = 0; for (i = m_pe->jstrings.begin(); i != m_pe->jstrings.end(); i++) { s = (*i).stat; for (j = (*i).s.begin(); j != (*i).s.end(); j++) { m_ce[c].c = *j; m_ce[c].stat = s; c++; } } } void ConvdispOv::layoutCharEnt() { int i; int x,y; x = m_atr->spot_location.x; y = m_atr->spot_location.y; for (i = 0; i < m_ce_len; i++) { cchar ch = m_ce[i].c; char buf[2]; int l; XRectangle ink,logical; if (ch < 256) { buf[0] = ch; l = 1; } else { buf[1] = (ch & 255)|0x80; buf[0] = ((ch>>8)&255)|0x80; l = 2; } XmbTextExtents(m_atr->font_set, buf, l, &ink, &logical); m_ce[i].width = logical.width; m_ce[i].height = logical.height; if (m_ce[i].width + x > m_atr->area.width /*+ m_atr->area.x*/) { x = 0;/*m_atr->area.x;*/ y += m_atr->line_space; } m_ce[i].x = x; m_ce[i].y = y; x += m_ce[i].width; } } int ConvdispOv::calc_ce_width(int b, int e) { int i,w=0; for (i = b; i < e; i++) { w += m_ce[i].width; } return w; } ConvdispOs::ConvdispOs(KKContext *k, icxatr *a, Connection *c) : Convdisp(k, a) { XimIC *ic=k->get_ic(); mConn = c; mImid = ic->get_imid(); mIcid = ic->get_icid(); mPrevLen = 0; } ConvdispOs::~ConvdispOs() { } void ConvdispOs::update_preedit() { if (!m_pe) { return ; } update_CandidateWin(); TxPacket *t; int len; len = m_pe->get_char_count(); if (mPrevLen == 0 && len == 0) { return ; } if (mPrevLen == 0 && len) { t = createTxPacket(XIM_PREEDIT_START, 0); t->pushC16(mImid); t->pushC16(mIcid); mConn->push_passive_packet(t); } t = createTxPacket(XIM_PREEDIT_DRAW, 0); t->pushC16(mImid); t->pushC16(mIcid); t->pushC32(0);// caret t->pushC32(0); // chg_first t->pushC32(mPrevLen); // chg_length //feedback array をセットしないとmozillaが落ちるが、それはIMEが悪いと考えるのが普通だろう。 if (m_pe->jstrings.size()) { t->pushC32(0); } else { t->pushC32(3); } compose_preedit_array(t); compose_feedback_array(t); mConn->push_passive_packet(t); if (mPrevLen && len == 0) { t = createTxPacket(XIM_PREEDIT_DONE, 0); t->pushC16(mImid); t->pushC16(mIcid); mConn->push_passive_packet(t); } mPrevLen = len; /* t = createTxPacket(XIM_PREEDIT_CARET,0); t->pushC16(mImid); t->pushC16(mIcid); t->pushC32(pos); t->pushC32(dir); t->pushC32(style); mConn->push_passive_packet(t); */ } void ConvdispOs::update_icxatr() { } void ConvdispOs::compose_preedit_array(TxPacket *t) { jstring_t s; std::list::iterator it; for (it = m_pe->jstrings.begin(); it != m_pe->jstrings.end(); it++) { append_jstring(&s, &(*it).s); } char *c = jstring_to_ctext(&s); int i,len; len = strlen(c); t->pushC16(len);// LENGTH for (i = 0 ; i < len ; i++) { t->pushC8(c[i]); // CTEXT } len = pad4(len+2); for (i = 0; i < len; i++) { t->pushC8(0); // PADDING } free(c); } void ConvdispOs::compose_feedback_array(TxPacket *t) { int i,len,stat,xstat; len = m_pe->get_char_count(); t->pushC16(len*4); t->pushC16(0); std::list::iterator it; for (it = m_pe->jstrings.begin(); it != m_pe->jstrings.end(); it++) { len = (*it).s.size(); stat = (*it).stat; xstat = FB_None; if (stat & PE_REVERSE) { xstat |= FB_Reverse; } if (stat & PE_UNDERLINE) { xstat |= FB_Underline; } if (stat & PE_HILIGHT) { xstat |= FB_Highlight; } for (i = 0; i < len; i++) { t->pushC32(xstat); } } } void ConvdispOs::set_focus() { m_cands_win->show(); } void ConvdispOs::unset_focus() { } void ConvdispOs::update_CandidateWin() { m_cands_win->set_pos(INVALID_POS, INVALID_POS); m_cands_win->update(m_pe); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * End: */