Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "textbuf_type.h"
00014 #include "string_func.h"
00015 #include "gfx_type.h"
00016 #include "gfx_func.h"
00017 #include "window_func.h"
00018
00025 bool GetClipboardContents(char *buffer, size_t buff_len);
00026
00027 int _caret_timer;
00028
00029
00036 bool Textbuf::CanDelChar(bool backspace)
00037 {
00038 return backspace ? this->caretpos != 0 : this->caretpos < this->bytes - 1;
00039 }
00040
00048 WChar Textbuf::GetNextDelChar(bool backspace)
00049 {
00050 assert(this->CanDelChar(backspace));
00051
00052 const char *s;
00053 if (backspace) {
00054 s = Utf8PrevChar(this->buf + this->caretpos);
00055 } else {
00056 s = this->buf + this->caretpos;
00057 }
00058
00059 WChar c;
00060 Utf8Decode(&c, s);
00061 return c;
00062 }
00063
00070 void Textbuf::DelChar(bool backspace)
00071 {
00072 assert(this->CanDelChar(backspace));
00073
00074 WChar c;
00075 char *s = this->buf + this->caretpos;
00076
00077 if (backspace) s = Utf8PrevChar(s);
00078
00079 uint16 len = (uint16)Utf8Decode(&c, s);
00080 uint width = GetCharacterWidth(FS_NORMAL, c);
00081
00082 this->pixels -= width;
00083 if (backspace) {
00084 this->caretpos -= len;
00085 this->caretxoffs -= width;
00086 }
00087
00088
00089 memmove(s, s + len, this->bytes - (s - this->buf) - len);
00090 this->bytes -= len;
00091 this->chars--;
00092 }
00093
00100 bool Textbuf::DeleteChar(int delmode)
00101 {
00102 if (delmode == WKC_BACKSPACE || delmode == WKC_DELETE) {
00103 bool backspace = delmode == WKC_BACKSPACE;
00104 if (CanDelChar(backspace)) {
00105 this->DelChar(backspace);
00106 return true;
00107 }
00108 return false;
00109 }
00110
00111 if (delmode == (WKC_CTRL | WKC_BACKSPACE) || delmode == (WKC_CTRL | WKC_DELETE)) {
00112 bool backspace = delmode == (WKC_CTRL | WKC_BACKSPACE);
00113
00114 if (!CanDelChar(backspace)) return false;
00115 WChar c = this->GetNextDelChar(backspace);
00116
00117
00118
00119
00120 while (backspace ? IsWhitespace(c) : !IsWhitespace(c)) {
00121 this->DelChar(backspace);
00122 if (!this->CanDelChar(backspace)) return true;
00123 c = this->GetNextDelChar(backspace);
00124 }
00125
00126
00127
00128 while (backspace ? !IsWhitespace(c) : IsWhitespace(c)) {
00129 this->DelChar(backspace);
00130 if (!this->CanDelChar(backspace)) return true;
00131 c = this->GetNextDelChar(backspace);
00132 }
00133 return true;
00134 }
00135
00136 return false;
00137 }
00138
00142 void Textbuf::DeleteAll()
00143 {
00144 memset(this->buf, 0, this->max_bytes);
00145 this->bytes = this->chars = 1;
00146 this->pixels = this->caretpos = this->caretxoffs = 0;
00147 }
00148
00156 bool Textbuf::InsertChar(WChar key)
00157 {
00158 const byte charwidth = GetCharacterWidth(FS_NORMAL, key);
00159 uint16 len = (uint16)Utf8CharLen(key);
00160 if (this->bytes + len <= this->max_bytes && this->chars + 1 <= this->max_chars) {
00161 memmove(this->buf + this->caretpos + len, this->buf + this->caretpos, this->bytes - this->caretpos);
00162 Utf8Encode(this->buf + this->caretpos, key);
00163 this->chars++;
00164 this->bytes += len;
00165 this->pixels += charwidth;
00166
00167 this->caretpos += len;
00168 this->caretxoffs += charwidth;
00169 return true;
00170 }
00171 return false;
00172 }
00173
00180 bool Textbuf::InsertClipboard()
00181 {
00182 char utf8_buf[512];
00183
00184 if (!GetClipboardContents(utf8_buf, lengthof(utf8_buf))) return false;
00185
00186 uint16 pixels = 0, bytes = 0, chars = 0;
00187 WChar c;
00188 for (const char *ptr = utf8_buf; (c = Utf8Consume(&ptr)) != '\0';) {
00189 if (!IsPrintable(c)) break;
00190
00191 byte len = Utf8CharLen(c);
00192 if (this->bytes + bytes + len > this->max_bytes) break;
00193 if (this->chars + chars + 1 > this->max_chars) break;
00194
00195 byte char_pixels = GetCharacterWidth(FS_NORMAL, c);
00196
00197 pixels += char_pixels;
00198 bytes += len;
00199 chars++;
00200 }
00201
00202 if (bytes == 0) return false;
00203
00204 memmove(this->buf + this->caretpos + bytes, this->buf + this->caretpos, this->bytes - this->caretpos);
00205 memcpy(this->buf + this->caretpos, utf8_buf, bytes);
00206 this->pixels += pixels;
00207 this->caretxoffs += pixels;
00208
00209 this->bytes += bytes;
00210 this->chars += chars;
00211 this->caretpos += bytes;
00212 assert(this->bytes <= this->max_bytes);
00213 assert(this->chars <= this->max_chars);
00214 this->buf[this->bytes - 1] = '\0';
00215
00216 return true;
00217 }
00218
00223 bool Textbuf::CanMoveCaretLeft()
00224 {
00225 return this->caretpos != 0;
00226 }
00227
00233 WChar Textbuf::MoveCaretLeft()
00234 {
00235 assert(this->CanMoveCaretLeft());
00236
00237 WChar c;
00238 const char *s = Utf8PrevChar(this->buf + this->caretpos);
00239 Utf8Decode(&c, s);
00240 this->caretpos = s - this->buf;
00241 this->caretxoffs -= GetCharacterWidth(FS_NORMAL, c);
00242
00243 return c;
00244 }
00245
00250 bool Textbuf::CanMoveCaretRight()
00251 {
00252 return this->caretpos < this->bytes - 1;
00253 }
00254
00260 WChar Textbuf::MoveCaretRight()
00261 {
00262 assert(this->CanMoveCaretRight());
00263
00264 WChar c;
00265 this->caretpos += (uint16)Utf8Decode(&c, this->buf + this->caretpos);
00266 this->caretxoffs += GetCharacterWidth(FS_NORMAL, c);
00267
00268 Utf8Decode(&c, this->buf + this->caretpos);
00269 return c;
00270 }
00271
00278 bool Textbuf::MovePos(int navmode)
00279 {
00280 switch (navmode) {
00281 case WKC_LEFT:
00282 if (this->CanMoveCaretLeft()) {
00283 this->MoveCaretLeft();
00284 return true;
00285 }
00286 break;
00287
00288 case WKC_CTRL | WKC_LEFT: {
00289 if (!this->CanMoveCaretLeft()) break;
00290
00291
00292 WChar c = this->MoveCaretLeft();
00293
00294 while (IsWhitespace(c)) {
00295 if (!this->CanMoveCaretLeft()) return true;
00296 c = this->MoveCaretLeft();
00297 }
00298
00299 while (!IsWhitespace(c)) {
00300 if (!this->CanMoveCaretLeft()) return true;
00301 c = this->MoveCaretLeft();
00302 }
00303
00304 this->MoveCaretRight();
00305 return true;
00306 }
00307
00308 case WKC_RIGHT:
00309 if (this->CanMoveCaretRight()) {
00310 this->MoveCaretRight();
00311 return true;
00312 }
00313 break;
00314
00315 case WKC_CTRL | WKC_RIGHT: {
00316 if (!this->CanMoveCaretRight()) break;
00317
00318
00319 WChar c = this->MoveCaretRight();
00320
00321 while (!IsWhitespace(c)) {
00322 if (!this->CanMoveCaretRight()) return true;
00323 c = this->MoveCaretRight();
00324 }
00325
00326 while (IsWhitespace(c)) {
00327 if (!this->CanMoveCaretRight()) return true;
00328 c = this->MoveCaretRight();
00329 }
00330 return true;
00331 }
00332
00333 case WKC_HOME:
00334 this->caretpos = 0;
00335 this->caretxoffs = 0;
00336 return true;
00337
00338 case WKC_END:
00339 this->caretpos = this->bytes - 1;
00340 this->caretxoffs = this->pixels;
00341 return true;
00342
00343 default:
00344 break;
00345 }
00346
00347 return false;
00348 }
00349
00356 void Textbuf::Initialize(char *buf, uint16 max_bytes)
00357 {
00358 this->Initialize(buf, max_bytes, max_bytes);
00359 }
00360
00368 void Textbuf::Initialize(char *buf, uint16 max_bytes, uint16 max_chars)
00369 {
00370 assert(max_bytes != 0);
00371 assert(max_chars != 0);
00372
00373 this->buf = buf;
00374 this->max_bytes = max_bytes;
00375 this->max_chars = max_chars;
00376 this->caret = true;
00377 this->UpdateSize();
00378 }
00379
00385 void Textbuf::UpdateSize()
00386 {
00387 const char *buf = this->buf;
00388
00389 this->pixels = 0;
00390 this->chars = this->bytes = 1;
00391
00392 WChar c;
00393 while ((c = Utf8Consume(&buf)) != '\0') {
00394 this->pixels += GetCharacterWidth(FS_NORMAL, c);
00395 this->bytes += Utf8CharLen(c);
00396 this->chars++;
00397 }
00398
00399 assert(this->bytes <= this->max_bytes);
00400 assert(this->chars <= this->max_chars);
00401
00402 this->caretpos = this->bytes - 1;
00403 this->caretxoffs = this->pixels;
00404 }
00405
00410 bool Textbuf::HandleCaret()
00411 {
00412
00413 bool b = !!(_caret_timer & 0x20);
00414
00415 if (b != this->caret) {
00416 this->caret = b;
00417 return true;
00418 }
00419 return false;
00420 }