ushort TEditor::prevWord( ushort p ) { while( p > 0 && isWordChar(bufChar(prevChar(p))) == 0 ) p = prevChar(p); while( p > 0 && isWordChar(bufChar(prevChar(p))) != 0 ) p = prevChar(p); return p; }
size_t TextEdit::moveWordFromCursor(Direction dir, bool word_end) const { size_t new_pos = current_pos; const char *cur = point; if (cur == gapstart) cur = gapend; if (dir == DIR_FORWARD) { if (word_end) { // search for the first white character after nonwhite characters bool nonwhite = false; while (new_pos < text_length) { if (!g_unichar_isspace(g_utf8_get_char(cur)) && *cur != '\n') nonwhite = true; else if (nonwhite) break; cur = nextChar(cur); new_pos++; } return new_pos; } else { // search for the first nonwhite character after white characters bool white = false; while (new_pos < text_length) { if (g_unichar_isspace(g_utf8_get_char(cur)) || *cur == '\n') white = true; else if (white) break; cur = nextChar(cur); new_pos++; } return new_pos; } } else { // DIR_BACK if (new_pos == 0) return 0; // always move at least one character back cur = prevChar(cur); new_pos--; // search for the first white character before nonwhite characters bool nonwhite = false; while (new_pos != static_cast<size_t>(-1)) { if (!g_unichar_isspace(g_utf8_get_char(cur)) && *cur != '\n') nonwhite = true; else if (nonwhite) break; if (new_pos > 0) cur = prevChar(cur); new_pos--; } return ++new_pos; } }
int TwordWrap::pwidthsLeft(int x) { if (x == 0) { return 0; } return pwidths[prevChar(x)]; }
void ScriptEdit::TextEdit::keyPressEvent(QKeyEvent *e) { updateCursor(); switch(e->key()) { // case Qt::Key_Space: // if(!(e->modifiers() & Qt::ControlModifier)) QTextEdit::keyPressEvent(e); // else Kernel::run(document()->toPlainText()); break; case Qt::Key_Tab: insert(" "); break; case Qt::Key_ParenLeft: if(!curChar().isLetterOrNumber()) { insert("()"); moveCursor(-1); } else QTextEdit::keyPressEvent(e); break; case Qt::Key_ParenRight: if(curChar() == ')') moveCursor(1); else QTextEdit::keyPressEvent(e); break; case Qt::Key_BraceLeft: insert("{}"); moveCursor(-1); break; case Qt::Key_BraceRight: if(curChar() == '}') moveCursor(1); else QTextEdit::keyPressEvent(e); break; case Qt::Key_Return: { QString text = document()->toPlainText(), space = ""; int n = 0; for(int i = 0; i < pos(); i++) if(text.at(i) == '{') n++; else if(text.at(i) == '}') n--; space.fill(' ', 4*n); if(prevChar() == '{') { insert("\n" + space); if(curChar() == '}') { insert("\n" + space.left(space.length()-4)); moveCursor(3-4*n); } break; } else if(curChar() == '}') { insert("\n" + space.left(space.length()-4)); break; } else { insert("\n" + space); break; } QTextEdit::keyPressEvent(e); break; } default: QTextEdit::keyPressEvent(e); } }
void TextEdit::deleteFromCursor(DeleteType type, Direction dir) { if (!editable) return; assertUpdatedScreenLines(); int count = 0; switch (type) { case DELETE_CHARS: count = moveLogicallyFromCursor(dir) - current_pos; break; case DELETE_WORD_ENDS: count = moveWordFromCursor(dir, true) - current_pos; break; default: g_assert_not_reached(); } if (count) { const char *min = gapstart; const char *max = gapend; moveGapToCursor(); while (count > 0) { gapend = nextChar(gapend); text_length--; count--; } while (count < 0) { gapstart = prevChar(gapstart); current_pos--; text_length--; count++; } point = gapstart; updateScreenLines(MIN(min, gapstart), MAX(max, gapend)); updateScreenCursor(); redraw(); signal_text_change(*this); } }
QChar QComplexText::shapedCharacter( const QString &str, int pos, const QFontMetrics *fm ) { const QChar *ch = str.unicode() + pos; if ( ch->row() != 0x06 ) return *ch; else { int shape = glyphVariantLogical( str, pos ); //qDebug("mapping U+%x to shape %d glyph=0x%x", ch->unicode(), shape, arabicUnicodeMapping[ch->cell()][shape]); // lam aleph ligatures switch ( ch->cell() ) { case 0x44: { // lam const QChar *nch = nextChar( str, pos ); if ( nch->row() == 0x06 ) { switch ( nch->cell() ) { case 0x22: case 0x23: case 0x25: case 0x27: return QChar(arabicUnicodeLamAlefMapping[nch->cell() - 0x22][shape]); default: break; } } break; } case 0x22: // alef with madda case 0x23: // alef with hamza above case 0x25: // alef with hamza below case 0x27: // alef if ( prevChar( str, pos )->unicode() == 0x0644 ) // have a lam alef ligature return QChar(0); default: break; } return QChar( getShape( ch, ch->cell(), shape, fm ) ); } }
static inline bool nextLogicalCharJoins( const QString &str, int pos) { QChar::Joining join = prevChar( str, pos )->joining(); return ( join == QChar::Dual || join == QChar::Center ); }
static inline bool prevVisualCharJoins( const QString &str, int pos) { return ( prevChar( str, pos )->joining() != QChar::OtherJoining ); }
void TEditor::handleEvent( TEvent& event ) { TView::handleEvent( event ); convertEvent( event ); Boolean centerCursor = Boolean(!cursorVisible()); uchar selectMode = 0; if( selecting == True || (getShiftState() & 0x03) != 0 ) selectMode = smExtend; switch( event.what ) { case evMouseDown: if( event.mouse.doubleClick == True ) selectMode |= smDouble; do { lock(); if( event.what == evMouseAuto ) { TPoint mouse = makeLocal( event.mouse.where ); TPoint d = delta; if( mouse.x < 0 ) d.x--; if( mouse.x >= size.x ) d.x++; if( mouse.y < 0 ) d.y--; if( mouse.y >= size.y ) d.y++; scrollTo(d.x, d.y); } setCurPtr(getMousePtr(event.mouse.where), selectMode); selectMode |= smExtend; unlock(); } while( mouseEvent(event, evMouseMove + evMouseAuto) ); break; case evKeyDown: if( event.keyDown.charScan.charCode == 9 || ( event.keyDown.charScan.charCode >= 32 && event.keyDown.charScan.charCode < 255 ) ) { lock(); if( overwrite == True && hasSelection() == False ) if( curPtr != lineEnd(curPtr) ) selEnd = nextChar(curPtr); insertText( &event.keyDown.charScan.charCode, 1, False); trackCursor(centerCursor); unlock(); } else return; break; case evCommand: switch( event.message.command ) { case cmFind: find(); break; case cmReplace: replace(); break; case cmSearchAgain: doSearchReplace(); break; default: lock(); switch( event.message.command ) { case cmCut: clipCut(); break; case cmCopy: clipCopy(); // hideSelect(); // JS 12.4.94 break; case cmPaste: clipPaste(); break; case cmUndo: undo(); break; case cmClear: deleteSelect(); break; case cmCharLeft: setCurPtr(prevChar(curPtr), selectMode); break; case cmCharRight: setCurPtr(nextChar(curPtr), selectMode); break; case cmWordLeft: setCurPtr(prevWord(curPtr), selectMode); break; case cmWordRight: setCurPtr(nextWord(curPtr), selectMode); break; case cmLineStart: setCurPtr(lineStart(curPtr), selectMode); break; case cmLineEnd: setCurPtr(lineEnd(curPtr), selectMode); break; case cmLineUp: setCurPtr(lineMove(curPtr, -1), selectMode); break; case cmLineDown: setCurPtr(lineMove(curPtr, 1), selectMode); break; case cmPageUp: setCurPtr(lineMove(curPtr, -(size.y-1)), selectMode); break; case cmPageDown: setCurPtr(lineMove(curPtr, size.y-1), selectMode); break; case cmTextStart: setCurPtr(0, selectMode); break; case cmTextEnd: setCurPtr(bufLen, selectMode); break; case cmNewLine: newLine(); break; case cmBackSpace: deleteRange(prevChar(curPtr), curPtr, True); break; case cmDelChar: deleteRange(curPtr, nextChar(curPtr), True); break; case cmDelWord: deleteRange(curPtr, nextWord(curPtr), False); break; case cmDelStart: deleteRange(lineStart(curPtr), curPtr, False); break; case cmDelEnd: deleteRange(curPtr, lineEnd(curPtr), False); break; case cmDelLine: deleteRange(lineStart(curPtr), nextLine(curPtr), False); break; case cmInsMode: toggleInsMode(); break; case cmStartSelect: startSelect(); break; case cmHideSelect: hideSelect(); break; case cmIndentMode: autoIndent = Boolean(!autoIndent); break; default: unlock(); return; } trackCursor(centerCursor); unlock(); break; } case evBroadcast: switch( event.message.command ) { case cmScrollBarChanged: checkScrollBar( event, hScrollBar, delta.x ); checkScrollBar( event, vScrollBar, delta.y ); break; default: return; } } clearEvent(event); }
int TwordWrap::smart() { int left = 0; int strlenp = (int)str.size(); bool skippingSpace = false; int xx = 0; rightOfTheLines.clear(); for (int x = 0; x < strlenp; x++) { if (skippingSpace || (pwidths[x] - left > splitdxMin && pwidths[x] - left <= splitdxMax)) { // ideal for line break. if (skippingSpace) { if (!iswspace(str.at(x))) { skippingSpace = false; left = x > 0 ? pwidths[x - 1] : 0; xx = x; } } else { if (iswspace(str.at(x))) { rightOfTheLines.push_back(x > 0 ? x - 1 : 0); skippingSpace = true; } } } if (pwidths[x] - left > splitdxMax && !skippingSpace) { // Not ideal, but we have to break before current word. bool found = false; skippingSpace = false; for (; x > xx; x--) { if (pwidths[x] - left <= splitdxMax) { if (iswspace(str.at(x))) { rightOfTheLines.push_back(x > 0 ? x - 1 : 0); left = pwidths[x]; xx = nextChar(x); found = true; break; } } } // fail over : no space to cut. Japanese subtitles often come here. if (!found) { if (assCompatibleMode) { for (; x < strlenp; x++) { if (iswspace(str.at(x))) { rightOfTheLines.push_back(x > 0 ? x - 1 : 0); skippingSpace = true; break; } } } else { for (; x < strlenp; x++) { if (pwidths[x] - left > splitdxMin) { if (x > xx && pwidths[x] - left > splitdxMax) { x = prevChar(x); } left = pwidths[x]; xx = nextChar(x); rightOfTheLines.push_back(x); break; } } } } } } rightOfTheLines.push_back(strlenp); return (int)rightOfTheLines.size(); }
int TwordWrap::smartReverse() { int strlenp = (int)str.size(); int right = pwidths[strlenp - 1]; bool skippingSpace = false; int xx = strlenp - 1; rightOfTheLines.clear(); rightOfTheLines.push_front(xx); for (int x = strlenp - 1; x >= 0; x--) { if (skippingSpace || (right - pwidthsLeft(x) > splitdxMin && right - pwidthsLeft(x) <= splitdxMax)) { // ideal for line break. if (skippingSpace) { if (!iswspace(str.at(x))) { skippingSpace = false; right = pwidths[x]; xx = x; rightOfTheLines.push_front(xx); } } else { if (iswspace(str.at(x))) { skippingSpace = true; } } } if (right - pwidthsLeft(x) > splitdxMax && !skippingSpace) { // Not ideal, but we have to break after current word. bool found = false; skippingSpace = false; for (; x < xx; x++) { if (right - pwidths[x] <= splitdxMax) { if (iswspace(str.at(x))) { xx = x > 0 ? x - 1 : 0; rightOfTheLines.push_front(xx); right = pwidths[xx]; found = true; break; } } } // fail over : no space to cut. Japanese subtitles often come here. if (!found) { if (assCompatibleMode) { for (; x >= 0; x--) { if (iswspace(str.at(x))) { skippingSpace = true; break; } } } else { for (; x >= 0; x--) { if (right - pwidths[x] > splitdxMin) { if (x < xx && right - pwidthsLeft(x) > splitdxMax) { x = nextChar(x); } xx = prevChar(x); rightOfTheLines.push_front(xx); right = pwidths[xx]; break; } } } } } } return (int)rightOfTheLines.size(); }
ushort TEditor::prevLine( ushort p ) { return lineStart(prevChar(p)); }
void TextEdit::moveCursor(CursorMovement step, Direction dir) { assertUpdatedScreenLines(); size_t old_pos = current_pos; switch (step) { case MOVE_LOGICAL_POSITIONS: current_pos = moveLogicallyFromCursor(dir); break; case MOVE_WORDS: current_pos = moveWordFromCursor(dir, false); break; case MOVE_DISPLAY_LINES: if (dir == DIR_FORWARD) { if (current_sc_line + 1 < screen_lines.size()) { int oldw = width(screen_lines[current_sc_line].start, current_sc_linepos); // first move to end of current line current_pos += screen_lines[current_sc_line].length - current_sc_linepos; // find a character close to the original position const char *ch = screen_lines[current_sc_line + 1].start; size_t i = 0; int w = 0; while (w < oldw && i < screen_lines[current_sc_line + 1].length - 1) { gunichar uc = g_utf8_get_char(ch); w += onScreenWidth(uc, w); ch = nextChar(ch); i++; } current_pos += i; } } else { // DIR_BACK if (current_sc_line > 0) { int oldw = width(screen_lines[current_sc_line].start, current_sc_linepos); // first move to start of current line current_pos -= current_sc_linepos; // move to the start of the previous line current_pos -= screen_lines[current_sc_line - 1].length; // find a character close to the original position const char *ch = screen_lines[current_sc_line - 1].start; size_t i = 0; int w = 0; while (w < oldw && i < screen_lines[current_sc_line - 1].length - 1) { gunichar uc = g_utf8_get_char(ch); w += onScreenWidth(uc, w); ch = nextChar(ch); i++; } current_pos += i; } } break; case MOVE_DISPLAY_LINE_ENDS: if (dir == DIR_FORWARD) current_pos += screen_lines[current_sc_line].length - current_sc_linepos - 1; else // DIR_BACK current_pos -= current_sc_linepos; break; default: g_assert_not_reached(); } // update point while (old_pos > current_pos) { point = prevChar(point); old_pos--; } while (old_pos < current_pos) { point = nextChar(point); old_pos++; } updateScreenCursor(); redraw(); }
int lex_nextToken(lex_Context* c) { if (c->sourceCodeCursor == c->sourceCodeEnd) return token(c, tokEOF); nextChar(c); if (c->c == '_' || isalpha(c->c)) { const char* idBegin = c->sourceCodeCursor - 1; while(c->sourceCodeCursor - idBegin < lex_MAX_ID_LENGTH) { nextChar(c); if (!(c->c == '_' || isalnum(c->c))) { prevChar(c); return tokenId(c, idBegin); } } return token(c, tokERROR_IDENTIFIER_TOO_LONG); } if (isdigit(c->c)) { const char* constBegin = c->sourceCodeCursor - 1; while(c->sourceCodeCursor - constBegin < lex_MAX_NUMCONST_LENGTH) { nextChar(c); if (!isdigit(c->c)) { prevChar(c); return tokenNumConst(c, constBegin); } } return token(c, tokERROR_NUMCONST_OVERFLOW); } for (;;) { switch(c->c) { case -1 : return token(c, tokEOF); case '\r': /* Fall through */ case '\n': for(;;) { nextChar(c); if (c->c != '\r' && c->c != '\n') { prevChar(c); break; } } return token(c, tokNEWLINE); case '+' : return token(c, tokPLUS); case '-' : return token(c, tokMINUS); case '*' : return token(c, tokMULT); case '/' : return token(c, tokDIV); case '%' : return token(c, tokMOD); case '=' : return token(c, tokEQ); case '<' : nextChar(c); if (c->c == '>') return token(c, tokNE); else if (c->c == '=') return token(c, tokLE); else prevChar(c); return token(c, tokLT); case '>' : nextChar(c); if (c->c == '=') return token(c, tokGE); else prevChar(c); return token(c, tokGT); case ' ' : return token(c, tokWHITE); case '\t': return token(c, tokWHITE); case '(' : return token(c, tokLPAR); case ')' : return token(c, tokRPAR); case ':' : return token(c, tokCOLON); case ',' : return token(c, tokCOMMA); case '#' : /* comment */ for(;;) { nextChar(c); if (c->c == '\n' || c->c == -1) { prevChar(c); break; } } break; default : return token(c, tokERROR_ILLEGAL_CHARACTER); } } }