/** * Yudit Unicode Editor Source File * * GNU Copyright (C) 1997-2006 Gaspar Sinai * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * dated June 1991. See file COPYYING for details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "swidget/SYuditInput.h" /** * SYuditInput is receiving events from STextEdit * It insert glyphs underlined into editorID and * when composition finished it sends it to the editor, after that * it may put half finished compsitions in the buffer. * @param name is the input name. * @param _eif is the editor interface to modify text. * @param ed is the editor. */ SYuditInput::SYuditInput (const SString& name, SEditorIF* _eif, SEditor* ed): encoder (name) { eif = _eif; editor = ed; startDirection = SS_DR_L; } /** * Delete SYuditInput. * for normal operaztion use clear before deleting. */ SYuditInput::~SYuditInput () { } /** * If SYuditInput is present and working, STextEdit sends the * events here first for processing. */ void SYuditInput::keyPressed (SWindowListener::SKey key, const SString& _s, bool ctrl, bool shift, bool meta) { SString s = _s; if (!eif->isEditable()) { clear(); editor->keyPressed (key, s, ctrl, shift, meta); } switch (key) { case SWindowListener::Key_BackSpace: case SWindowListener::Key_Delete: if (startIndex.getTextIndex()!=endIndex.getTextIndex()) { SString pre = encoder.preEditBuffer(); SV_UCS4 pb = encoder.postEditBuffer(); almostClear(); (void) encoder.decode ("", false); /* clear */ SString post = encoder.encode (pb); SString a = encoder.encode (SV_UCS4()); if (a.size()) post.append (a); if (pre.size()) post.append (pre); if (post.size() > 0) post.truncate(post.size()-1); s = post; } else { editor->keyPressed (key, s, ctrl, shift, meta); return; } break; /* Do not clear - we might need to press shift! */ case SWindowListener::Key_Shift_R: case SWindowListener::Key_Shift_L: if (startIndex.getTextIndex()==endIndex.getTextIndex()) { editor->keyPressed (key, s, ctrl, shift, meta); } break; case SWindowListener::Key_Control_R: case SWindowListener::Key_Control_L: case SWindowListener::Key_Meta_R: case SWindowListener::Key_Meta_L: case SWindowListener::Key_Alt_R: case SWindowListener::Key_Alt_L: case SWindowListener::Key_Escape: case SWindowListener::Key_Home: case SWindowListener::Key_End: case SWindowListener::Key_Prior: case SWindowListener::Key_Next: case SWindowListener::Key_Up: case SWindowListener::Key_Down: case SWindowListener::Key_Left: case SWindowListener::Key_Right: case SWindowListener::Key_Enter: case SWindowListener::Key_Return: case SWindowListener::Key_F1: case SWindowListener::Key_F2: case SWindowListener::Key_F3: case SWindowListener::Key_F4: case SWindowListener::Key_F5: case SWindowListener::Key_F6: case SWindowListener::Key_F7: case SWindowListener::Key_F8: case SWindowListener::Key_F9: case SWindowListener::Key_F10: case SWindowListener::Key_F11: case SWindowListener::Key_F12: if (startIndex.getTextIndex()!=endIndex.getTextIndex()) { clear(); } editor->keyPressed (key, s, ctrl, shift, meta); return; default: if (s.size()==0 && !(ctrl || meta)) return; if (ctrl || meta) { if (startIndex.getTextIndex()!=endIndex.getTextIndex()) clear(); editor->keyPressed (key, s, ctrl, shift, meta); return; } } if (s.size()==0) return; SString remaining = s; SV_UCS4 pbefore = encoder.postEditBuffer(); SV_UCS4 u = encoder.decode (s); SV_UCS4 pafter = encoder.postEditBuffer(); SV_UCS4 pedit; /* we just append ? */ if (u.size() > 0 || pafter.size() != pbefore.size()) { remaining = encoder.preEditBuffer(); pedit = pafter; almostClear (); SEncoder utf8; editor->keyPressed (SWindowListener::Key_Send, utf8.encode(u), false, false, false); } /* process glyphs here */ if (startIndex.getTextIndex()==endIndex.getTextIndex()) { startIndex = eif->getCursorIndex(); startDirection = eif->getDirection(); endIndex = startIndex; } if (pedit.size()) { SEncoder utf8; eif->insertPreEditText (utf8.encode (pedit)); endIndex = eif->getCursorIndex(); } if (remaining.size()) { eif->insertPreEditText (remaining); endIndex = eif->getCursorIndex(); } preEditSize = remaining.size() + pedit.size(); } /** * clear the input text. * @param tosend is true if the remaining characters should * be sent out. * @return true if it had a text. */ bool SYuditInput::clear(bool tosend) { SString toSend; if (preEditSize) { /* flush */ SV_UCS4 u = encoder.decode ("", false); if (u.size() > 0) { SEncoder utf8; toSend = utf8.encode(u); } } /* make it pre-emptive */ encoder = SEncoder(encoder.getName()); almostClear(); if (toSend.size()) { if (tosend) { editor->keyPressed (SWindowListener::Key_Send, toSend, false, false, false); } return true; } return false; } /** * clear it. */ void SYuditInput::almostClear() { if (startIndex.getTextIndex() == endIndex.getTextIndex()) { startIndex = SCursorIndex (0, 0); endIndex = startIndex; preEditSize = 0; return; } /* Make it pre-emptive */ SCursorIndex s = startIndex; SCursorIndex e = endIndex; startIndex = SCursorIndex (0, 0); endIndex = startIndex; preEditSize = 0; eif->endSelect (); eif->setCursorIndex (s); eif->eraseText (e.getTextIndex()); //fprintf (stderr, "setCursor\n"); eif->setCursorIndex (s); //fprintf (stderr, "setDirection\n"); eif->setDirection (startDirection); return; } /** * return true if input method works fine. */ bool SYuditInput::isOK() { return encoder.isOK(); } /** * Try to reverse encode the input with the current keymap */ SString SYuditInput::encode (const SV_UCS4& v) const { SString ret; if (v.size()==0) return SString(ret); SEncoder e = encoder; ret = e.encode (v); /* flush */ SV_UCS4 empty; ret.append (e.encode (empty)); /* check it against input */ SV_UCS4 check = e.decode (ret, true); SString es; check.append (e.decode (es, false)); bool tryagain = false; if (v.size() != check.size()) { tryagain = true; } else for (unsigned int i=0; i v.size() && check.size() > 1 && check[check.size()-1] == (SS_UCS4)' ') { check.truncate (check.size()-1); } if (v.size() != check.size()) { ret.clear(); } else for (unsigned int i=0; i