void LineEdit::UpdateText() { unsigned utf8Length = line_.LengthUTF8(); if (!echoCharacter_) text_->SetText(line_); else { String echoText; for (unsigned i = 0; i < utf8Length; ++i) echoText.AppendUTF8(echoCharacter_); text_->SetText(echoText); } if (cursorPosition_ > utf8Length) { cursorPosition_ = utf8Length; UpdateCursor(); } using namespace TextChanged; VariantMap& eventData = GetEventDataMap(); eventData[P_ELEMENT] = this; eventData[P_TEXT] = line_; SendEvent(E_TEXTCHANGED, eventData); }
String String::SubstringUTF8(unsigned pos) const { unsigned utf8Length = LengthUTF8(); unsigned byteOffset = ByteOffsetUTF8(pos); String ret; while (pos < utf8Length) { ret.AppendUTF8(NextUTF8Char(byteOffset)); ++pos; } return ret; }
String String::SubstringUTF8(size_t pos) const { size_t utf8Length = LengthUTF8(); size_t byteOffset = ByteOffsetUTF8(pos); String ret; while (pos < utf8Length) { ret.AppendUTF8(NextUTF8Char(byteOffset)); ++pos; } return ret; }
void LineEdit::OnChar(unsigned c, int buttons, int qualifiers) { if (!editable_) return; bool changed = false; // If only CTRL is held down, do not edit if ((qualifiers & (QUAL_CTRL | QUAL_ALT)) == QUAL_CTRL) return; if (c >= 0x20 && (!maxLength_ || line_.LengthUTF8() < maxLength_)) { String charStr; charStr.AppendUTF8(c); if (!text_->GetSelectionLength()) { if (cursorPosition_ == line_.LengthUTF8()) line_ += charStr; else line_ = line_.SubstringUTF8(0, cursorPosition_) + charStr + line_.SubstringUTF8(cursorPosition_); ++cursorPosition_; } else { // If a selection exists, erase it first unsigned start = text_->GetSelectionStart(); unsigned length = text_->GetSelectionLength(); if (start + length < line_.LengthUTF8()) line_ = line_.SubstringUTF8(0, start) + charStr + line_.SubstringUTF8(start + length); else line_ = line_.SubstringUTF8(0, start) + charStr; cursorPosition_ = start + 1; } changed = true; } if (changed) { text_->ClearSelection(); UpdateText(); UpdateCursor(); } }
String ReadLine() { String ret; #ifdef _WIN32 HANDLE input = GetStdHandle(STD_INPUT_HANDLE); HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE); if (input == INVALID_HANDLE_VALUE || output == INVALID_HANDLE_VALUE) return ret; // Use char-based input SetConsoleMode(input, ENABLE_PROCESSED_INPUT); INPUT_RECORD record; DWORD events = 0; DWORD readEvents = 0; if (!GetNumberOfConsoleInputEvents(input, &events)) return ret; while (events--) { ReadConsoleInputW(input, &record, 1, &readEvents); if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown) { unsigned c = record.Event.KeyEvent.uChar.UnicodeChar; if (c) { if (c == '\b') { PrintUnicode("\b \b"); size_t length = currentLine.LengthUTF8(); if (length) currentLine = currentLine.SubstringUTF8(0, length - 1); } else if (c == '\r') { PrintUnicode("\n"); ret = currentLine; currentLine.Clear(); return ret; } else { // We have disabled echo, so echo manually wchar_t out = (wchar_t)c; DWORD charsWritten; WriteConsoleW(output, &out, 1, &charsWritten, 0); currentLine.AppendUTF8(c); } } } } #else int flags = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); for (;;) { int ch = fgetc(stdin); if (ch >= 0 && ch != '\n') ret += (char)ch; else break; } #endif return ret; }
bool JSONValue::ReadJSONString(String& dest, const char*& pos, const char*& end, bool inQuote) { char c; if (!inQuote) { if (!NextChar(c, pos, end, true) || c != '\"') return false; } dest.Clear(); for (;;) { if (!NextChar(c, pos, end, false)) return false; if (c == '\"') break; else if (c != '\\') dest += c; else { if (!NextChar(c, pos, end, false)) return false; switch (c) { case '\\': dest += '\\'; break; case '\"': dest += '\"'; break; case 'b': dest += '\b'; break; case 'f': dest += '\f'; break; case 'n': dest += '\n'; break; case 'r': dest += '\r'; break; case 't': dest += '\t'; break; case 'u': { /// \todo Doesn't handle unicode surrogate pairs unsigned code; /// @todo check return value code = strtol(pos, 0, 16); pos += 4; dest.AppendUTF8(code); } break; } } } return true; }
void FileWatcher::ThreadFunction() { #if defined(ENABLE_FILEWATCHER) #if defined(WIN32) unsigned char buffer[BUFFERSIZE]; DWORD bytesFilled = 0; while (shouldRun_) { if (ReadDirectoryChangesW((HANDLE)dirHandle_, buffer, BUFFERSIZE, watchSubDirs_, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE, &bytesFilled, 0, 0)) { unsigned offset = 0; while (offset < bytesFilled) { FILE_NOTIFY_INFORMATION* record = (FILE_NOTIFY_INFORMATION*)&buffer[offset]; if (record->Action == FILE_ACTION_MODIFIED || record->Action == FILE_ACTION_RENAMED_NEW_NAME) { String fileName; const wchar_t* src = record->FileName; const wchar_t* end = src + record->FileNameLength / 2; while (src < end) fileName.AppendUTF8(String::DecodeUTF16(src)); fileName = GetInternalPath(fileName); AddChange(fileName); } if (!record->NextEntryOffset) break; else offset += record->NextEntryOffset; } } } #elif defined(__linux__) unsigned char buffer[BUFFERSIZE]; while (shouldRun_) { int i = 0; int length = read(watchHandle_, buffer, sizeof(buffer)); if (length < 0) return; while (i < length) { inotify_event* event = (inotify_event*)&buffer[i]; if (event->len > 0) { if (event->mask & IN_MODIFY || event->mask & IN_MOVE) { String fileName; fileName = dirHandle_[event->wd] + event->name; AddChange(fileName); } } i += sizeof(inotify_event) + event->len; } } #elif defined(__APPLE__) && !defined(IOS) while (shouldRun_) { Time::Sleep(100); String changes = ReadFileWatcher(watcher_); if (!changes.Empty()) { Vector<String> fileNames = changes.Split(1); for (unsigned i = 0; i < fileNames.Size(); ++i) AddChange(fileNames[i]); } } #endif #endif }