JL_DLLEXPORT void jl_uv_putc(uv_stream_t *stream, uint32_t wchar) { char s[4]; jl_uv_puts(stream, s, u8_wc_toutf8(s, wchar)); }
std::shared_ptr<Object> read_string(std::istream &in) { std::stringstream buf; // lambda to get the next char, or throw EOF exception std::function<int ()> getc = [&in] () -> int { int c = in.get(); if (in.eof()) { throw "EOF while reading string"; } return c; }; while (1) { int c = getc(); if (c == '"') { return std::make_shared<String>(buf.str()); } if (c == '\\') { c = getc(); if (octal_digit(c)) { int j = 0; char eseq[4] = { 0, 0, 0, 0 } ; do { eseq[j++] = c; c = getc(); } while (octal_digit(c) && j < 3); in.unget(); if (!octal_digit(c) && j < 3) { if (c == '\\') { } else { buf.str("Invalid digit: "); buf.put(c); throw buf.str(); } } u8_wc_toutf8(buf, std::strtol(eseq, 0, 8)); } else if (c == 'u') { int j = 0; char eseq[5] = { 0, 0, 0, 0, 0 }; c = getc(); while (hex_digit(c) && j < 4) { eseq[j++] = c; c = getc(); } if (j != 4) { buf.str("Invalid character length: "); buf << j << ", should be: 4"; throw buf.str(); } in.unget(); long uni = std::strtol(eseq, 0, 16); u8_wc_toutf8(buf, uni); } else { if (c == 'b') { buf.put('\b'); } else if (c == 'n') { buf.put('\n'); } else if (c == 't') { buf.put('\t'); } else if (c == 'f') { buf.put('\f'); } else if (c == 'r') { buf.put('\r'); } else if (c == '"') { buf.put('\''); } else if (c == '\\') { buf.put('\\'); } else { buf.str("Unsupported escape character: \\"); buf.put(c); throw buf.str(); } } } else { buf.put(c); } } return Object::nil; }
static value_t read_string(void) { char *buf, *temp; char eseq[10]; size_t i=0, j, sz = 64, ndig; int c; value_t s; u_int32_t wc=0; buf = malloc(sz); while (1) { if (i >= sz-4) { // -4: leaves room for longest utf8 sequence sz *= 2; temp = realloc(buf, sz); if (temp == NULL) { free(buf); lerror(ParseError, "read: out of memory reading string"); } buf = temp; } c = ios_getc(F); if (c == IOS_EOF) { free(buf); lerror(ParseError, "read: unexpected end of input in string"); } if (c == '"') break; else if (c == '\\') { c = ios_getc(F); if (c == IOS_EOF) { free(buf); lerror(ParseError, "read: end of input in escape sequence"); } j=0; if (octal_digit(c)) { do { eseq[j++] = c; c = ios_getc(F); } while (octal_digit(c) && j<3 && (c!=IOS_EOF)); if (c!=IOS_EOF) ios_ungetc(c, F); eseq[j] = '\0'; wc = strtol(eseq, NULL, 8); // \DDD and \xXX read bytes, not characters buf[i++] = ((char)wc); } else if ((c=='x' && (ndig=2)) || (c=='u' && (ndig=4)) || (c=='U' && (ndig=8))) { c = ios_getc(F); while (hex_digit(c) && j<ndig && (c!=IOS_EOF)) { eseq[j++] = c; c = ios_getc(F); } if (c!=IOS_EOF) ios_ungetc(c, F); eseq[j] = '\0'; if (j) wc = strtol(eseq, NULL, 16); if (!j || wc > 0x10ffff) { free(buf); lerror(ParseError, "read: invalid escape sequence"); } if (ndig == 2) buf[i++] = ((char)wc); else i += u8_wc_toutf8(&buf[i], wc); } else { buf[i++] = read_escape_control_char((char)c); } } else { buf[i++] = c; } } s = cvalue_string(i); memcpy(cvalue_data(s), buf, i); free(buf); return s; }
void TextEdit::Key(const KeyInput &input) { if (!HasFocus()) return; // Process navigation keys. These aren't chars. if (input.flags & KEY_DOWN) { switch (input.keyCode) { case NKCODE_CTRL_LEFT: case NKCODE_CTRL_RIGHT: ctrlDown_ = true; break; case NKCODE_DPAD_LEFT: // ASCII left arrow u8_dec(text_.c_str(), &caret_); break; case NKCODE_DPAD_RIGHT: // ASCII right arrow u8_inc(text_.c_str(), &caret_); break; case NKCODE_MOVE_HOME: case NKCODE_PAGE_UP: caret_ = 0; break; case NKCODE_MOVE_END: case NKCODE_PAGE_DOWN: caret_ = (int)text_.size(); break; case NKCODE_FORWARD_DEL: if (caret_ < (int)text_.size()) { int endCaret = caret_; u8_inc(text_.c_str(), &endCaret); undo_ = text_; text_.erase(text_.begin() + caret_, text_.begin() + endCaret); } break; case NKCODE_DEL: if (caret_ > 0) { int begCaret = caret_; u8_dec(text_.c_str(), &begCaret); undo_ = text_; text_.erase(text_.begin() + begCaret, text_.begin() + caret_); caret_--; } break; } if (ctrlDown_) { switch (input.keyCode) { case NKCODE_C: // Just copy the entire text contents, until we get selection support. System_SendMessage("setclipboardtext", text_.c_str()); break; case NKCODE_V: { std::string clipText = System_GetProperty(SYSPROP_CLIPBOARD_TEXT); clipText = FirstLine(clipText); if (clipText.size()) { // Until we get selection, replace the whole text undo_ = text_; text_.clear(); caret_ = 0; size_t maxPaste = maxLen_ - text_.size(); if (clipText.size() > maxPaste) { int end = 0; while ((size_t)end < maxPaste) { u8_inc(clipText.c_str(), &end); } if (end > 0) { u8_dec(clipText.c_str(), &end); } clipText = clipText.substr(0, end); } InsertAtCaret(clipText.c_str()); } } break; case NKCODE_Z: text_ = undo_; break; } } if (caret_ < 0) { caret_ = 0; } if (caret_ > (int)text_.size()) { caret_ = (int)text_.size(); } } if (input.flags & KEY_UP) { switch (input.keyCode) { case NKCODE_CTRL_LEFT: case NKCODE_CTRL_RIGHT: ctrlDown_ = false; break; } } // Process chars. if (input.flags & KEY_CHAR) { int unichar = input.keyCode; if (unichar >= 0x20 && !ctrlDown_) { // Ignore control characters. // Insert it! (todo: do it with a string insert) char buf[8]; buf[u8_wc_toutf8(buf, unichar)] = '\0'; if (strlen(buf) + text_.size() < maxLen_) { undo_ = text_; InsertAtCaret(buf); } } } }