00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "label.h"
00016
00017 u_int16 label::cursor_blink_cycle = 75;
00018
00019
00020
00021
00022 label::label () : image ()
00023 {
00024
00025 my_font_ = NULL;
00026 new_text_ = "";
00027
00028
00029 init_vec_cursor ();
00030
00031
00032 set_form (NOTHING);
00033
00034 set_cursor_visible (false);
00035
00036 set_cursor_moveable (false);
00037
00038 cursor_cur_blink_ = 0;
00039
00040 set_mask (true);
00041 }
00042
00043
00044
00045
00046
00047 label::~label ()
00048 {
00049 }
00050
00051
00052
00053
00054
00055 void label::set_font (win_font & font)
00056 {
00057 my_font_ = &font;
00058
00059 }
00060
00061
00062
00063
00064
00065 void label::set_text (const string & text)
00066 {
00067
00068 init_vec_cursor ();
00069
00070 my_old_cursor_ = my_cursor_;
00071
00072
00073 my_text_ = text;
00074 my_cursor_.idx = my_text_.length ();
00075
00076
00077 build (true);
00078 }
00079
00080
00081
00082
00083
00084
00085 void label::add_text (const string & text)
00086 {
00087 new_text_ += text;
00088
00089
00090 int size = new_text_.length ();
00091 if (size == 2 && (u_int8) new_text_[0] >= 0xE0) return;
00092 if (size == 1 && (u_int8) new_text_[0] >= 0x80) return;
00093
00094 my_old_cursor_ = my_cursor_;
00095
00096 if (my_old_cursor_.idx == my_text_.length ())
00097 {
00098 my_text_ += new_text_;
00099 my_cursor_.idx = my_text_.length ();
00100 }
00101 else my_text_.insert (my_cursor_.idx, new_text_);
00102 new_text_ = "";
00103
00104 build (false);
00105 }
00106
00107
00108
00109
00110
00111 void label::resize (u_int16 l, u_int16 h)
00112 {
00113 image::resize (l, h);
00114 set_text (my_text_);
00115 }
00116
00117
00118
00119
00120
00121 void label::set_form (const u_int8 form)
00122 {
00123 my_form_ = form;
00124 build (true);
00125 }
00126
00127
00128
00129
00130
00131 void label::init_vec_cursor ()
00132 {
00133
00134 my_cursor_.pos_x = my_cursor_.pos_y = my_cursor_.line = my_cursor_.idx = 0;
00135
00136
00137 my_vect_.clear ();
00138
00139
00140 Sline_text tmp;
00141 tmp.pos_x = tmp.idx_beg = tmp.idx_end = 0;
00142
00143
00144 my_vect_.push_back (tmp);
00145
00146
00147 start_line_ = 0;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157 void label::build (const bool erase_all)
00158 {
00159 if (my_font_ == NULL) return;
00160 set_mask (false);
00161 switch (my_form_)
00162 {
00163 case NOTHING :
00164 build_form_nothing ();
00165 update_cursor ();
00166 draw_string (!erase_all);
00167 break;
00168
00169 case AUTO_HEIGHT :
00170 build_form_auto_height ();
00171 update_cursor ();
00172 draw_string (!erase_all);
00173 break;
00174
00175 case AUTO_SIZE :
00176 build_form_auto_size ();
00177 update_cursor ();
00178 draw_string (false);
00179 break;
00180 }
00181 set_mask (true);
00182 }
00183
00184
00185
00186
00187
00188
00189 void label::set_cursor_visible (const bool b)
00190 {
00191 visible_cursor_ = b;
00192 }
00193
00194
00195
00196
00197
00198 void label::set_cursor_moveable (const bool b)
00199 {
00200 moveable_cursor_ = b;
00201 }
00202
00203
00204
00205
00206
00207 void label::build_form_nothing ()
00208 {
00209
00210 u_int16 j, word_length, word_length_pix, start_idx;
00211
00212
00213 Sline_text line_tmp;
00214
00215
00216 line_tmp.idx_beg = my_vect_[my_old_cursor_.line].idx_beg;
00217 line_tmp.pos_x = 0;
00218
00219
00220 start_idx = line_tmp.idx_beg;
00221
00222
00223 vector <Sline_text>::iterator ii = my_vect_.begin ();
00224 u_int16 i = 0;
00225 while (i != my_old_cursor_.line) { i++; ii++; }
00226 my_vect_.erase (ii, my_vect_.end ());
00227
00228
00229 while (start_idx < my_text_.length () )
00230 {
00231
00232 if (my_text_[start_idx] == '\n')
00233 {
00234
00235 line_tmp.idx_end = start_idx;
00236
00237
00238 my_vect_.push_back (line_tmp);
00239
00240
00241 line_tmp.pos_x = 0;
00242 line_tmp.idx_beg = ++start_idx;
00243 }
00244 else if (my_text_[start_idx] == ' ')
00245 {
00246 if ((*my_font_) [' '].length () + line_tmp.pos_x > length ())
00247 {
00248 line_tmp.idx_end = start_idx;
00249
00250
00251 my_vect_.push_back (line_tmp);
00252
00253
00254 line_tmp.pos_x = 0;
00255 line_tmp.idx_beg = ++start_idx;
00256
00257 } else
00258 {
00259 line_tmp.pos_x += (*my_font_) [' '].length ();
00260 start_idx++;
00261 }
00262 }
00263 else
00264 {
00265
00266
00267 switch (find_word (start_idx, word_length, word_length_pix, line_tmp.pos_x))
00268 {
00269 case 0 :
00270 line_tmp.pos_x += word_length_pix;
00271 break;
00272
00273 case 1 :
00274
00275
00276 if (length () && height ())
00277 {
00278
00279 lock ();
00280 fillrect (line_tmp.pos_x,
00281 (my_vect_.size () - start_line_) * my_font_->height (),
00282 length () - line_tmp.pos_x,
00283 my_font_->height (), screen::trans_col () );
00284 unlock ();
00285 }
00286 line_tmp.idx_end = (start_idx - word_length) - 1;
00287 my_vect_.push_back (line_tmp);
00288
00289 line_tmp.pos_x = word_length_pix;
00290 line_tmp.idx_beg = start_idx - word_length;
00291
00292 break;
00293
00294 case 2 :
00295
00296 j = start_idx - word_length;
00297 while (j < start_idx)
00298 {
00299 u_int16 c = ucd (j);
00300 if (line_tmp.pos_x + (*my_font_) [c].length () > length ())
00301 {
00302 line_tmp.idx_end = j - 1;
00303 my_vect_.push_back (line_tmp);
00304
00305 line_tmp.pos_x = 0;
00306 line_tmp.idx_beg = j;
00307 }
00308 line_tmp.pos_x += (*my_font_) [c].length ();
00309 j++;
00310 }
00311 break;
00312 }
00313 }
00314 }
00315
00316
00317 line_tmp.idx_end = start_idx - 1;
00318 my_vect_.push_back (line_tmp);
00319 }
00320
00321
00322 void label::build_form_auto_height ()
00323 {
00324
00325 build_form_nothing ();
00326
00327
00328
00329 u_int16 new_size = my_vect_.size () * my_font_->height ();
00330
00331 if (new_size != height ())
00332 {
00333 image tmp (length (), new_size);
00334 tmp.lock ();
00335 tmp.fillrect (0, 0, length (), new_size, screen::trans_col ());
00336 tmp.unlock ();
00337 draw (0, 0, 0, 0, length (), my_old_cursor_.pos_y + my_font_->height (), NULL, &tmp);
00338 image::resize (length (), new_size);
00339 tmp.draw (0, 0, NULL, this);
00340 }
00341 }
00342
00343
00344 void label::build_form_auto_size ()
00345 {
00346
00347
00348
00349 my_vect_.clear ();
00350
00351
00352 Sline_text line_tmp;
00353
00354 line_tmp.pos_x = 0;
00355 line_tmp.idx_beg = 0;
00356 u_int16 i = 0, max_length = 0;
00357
00358 while ( i < my_text_.size ())
00359 {
00360 if (my_text_[i] == '\n')
00361 {
00362 if (line_tmp.pos_x > max_length) max_length = line_tmp.pos_x;
00363 line_tmp.idx_end = i;
00364 my_vect_.push_back (line_tmp);
00365
00366 line_tmp.idx_beg = i+1;
00367 line_tmp.pos_x = 0;
00368 }
00369 else
00370 {
00371 line_tmp.pos_x += (*my_font_) [ucd (i)].length ();
00372 }
00373 i++;
00374 }
00375
00376 if (line_tmp.pos_x > max_length) max_length = line_tmp.pos_x;
00377
00378 line_tmp.idx_end = i-1;
00379 my_vect_.push_back (line_tmp);
00380
00381
00382 image::resize (max_length, my_vect_.size () * my_font_->height ());
00383 }
00384
00385 void label::clean_surface (const bool erase_all)
00386 {
00387 if (length () && height ())
00388 {
00389 if ( my_cursor_.idx != my_text_.length ())
00390 {
00391 lock ();
00392 fillrect ( my_old_cursor_.pos_x, my_old_cursor_.pos_y, length () - my_old_cursor_.pos_x,
00393 my_font_->height (), screen::trans_col ());
00394 fillrect (0, my_old_cursor_.pos_y + my_font_->height (), length (),
00395 height () -my_old_cursor_.pos_y + my_font_->height (), screen::trans_col ());
00396 unlock ();
00397 } else if (erase_all)
00398 {
00399 lock ();
00400 fillrect (0, 0, length (), height (), screen::trans_col ());
00401 unlock ();
00402 }
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 u_int8 label::find_word (u_int16 & index, u_int16 & wlength, u_int16 & wlengthpix, const u_int16 rlength)
00418 {
00419 wlength = index;
00420 wlengthpix = 0;
00421 while (index < my_text_.length () && my_text_[index] != ' ' && my_text_[index] != '\n')
00422 {
00423 wlengthpix += (*my_font_) [ucd (index)].length ();
00424 index++;
00425 }
00426
00427
00428 wlength = index - wlength;
00429
00430
00431 if (wlengthpix < length () - rlength) return 0;
00432 else if (wlengthpix < length ()) return 1;
00433 return 2;
00434 }
00435
00436
00437
00438 void label::update_cursor ()
00439 {
00440
00441 bool b = false;
00442
00443
00444 cursor_cur_blink_ = cursor_blink_cycle;
00445
00446
00447 while (!b && my_cursor_.line < my_vect_.size () )
00448 {
00449 if (my_cursor_.idx >= my_vect_[my_cursor_.line].idx_beg &&
00450 my_cursor_.idx <= my_vect_[my_cursor_.line].idx_end ) b = true;
00451 else if (my_cursor_.idx > my_vect_[my_cursor_.line].idx_end)
00452 {
00453 if (my_cursor_.line == my_vect_.size () - 1) b = true;
00454 else my_cursor_.line++;
00455 }
00456 else if (my_cursor_.idx < my_vect_[my_cursor_.line].idx_beg)
00457 {
00458 my_cursor_.line--;
00459 }
00460 }
00461
00462
00463 my_cursor_.pos_x = 0;
00464
00465 u_int16 j = my_vect_[my_cursor_.line].idx_beg;
00466 while (j < my_cursor_.idx) {
00467 my_cursor_.pos_x+= (*my_font_) [ucd (j)].length ();
00468 j++;
00469 }
00470
00471 my_cursor_.pos_y = (my_cursor_.line - start_line_) * my_font_->height ();
00472
00473 if (my_cursor_.pos_y > height ())
00474 {
00475
00476
00477 }
00478 }
00479
00480
00481
00482
00483 void label::draw_string (const bool at_cursor)
00484 {
00485 u_int16 tmp_start_line;
00486 u_int16 tx = 0, ty = 0;
00487 u_int16 idx_cur_line, j;
00488 u_int16 c;
00489
00490
00491 clean_surface (!at_cursor);
00492
00493 if (at_cursor)
00494 {
00495 tmp_start_line = my_old_cursor_.line;
00496 tx = my_old_cursor_.pos_x;
00497 idx_cur_line = my_old_cursor_.idx;
00498 ty = (tmp_start_line - start_line_) * my_font_->height ();
00499 }
00500 else
00501 {
00502 tmp_start_line = start_line_;
00503 idx_cur_line = my_vect_[tmp_start_line].idx_beg;
00504 }
00505
00506
00507 for (j = idx_cur_line;
00508 j < my_vect_[tmp_start_line].idx_end + 1 ;
00509 j++)
00510 {
00511 c = ucd (j);
00512 if (c != '\n' && my_font_->in_table (c))
00513 {
00514 (*my_font_) [c].draw (tx, ty, NULL, this);
00515 tx += (*my_font_) [c].length ();
00516 }
00517 }
00518 ty += my_font_->height ();
00519 tmp_start_line++;
00520
00521
00522
00523 while (tmp_start_line < my_vect_.size ())
00524 {
00525 tx = 0;
00526 for (j = my_vect_[tmp_start_line].idx_beg;
00527 j < my_vect_[tmp_start_line].idx_end + 1 ;
00528 j++)
00529 {
00530 c = ucd (j);
00531 if (my_font_->in_table (c))
00532 {
00533 (*my_font_) [c].draw (tx, ty, NULL, this);
00534 tx += (*my_font_) [c].length ();
00535 }
00536 }
00537 ty += my_font_->height ();
00538 tmp_start_line++;
00539 }
00540 }
00541
00542
00543 bool label::update ()
00544 {
00545 if (visible_cursor_)
00546 {
00547 if (! (height () && length ())) return true;
00548 if (cursor_cur_blink_ == cursor_blink_cycle)
00549 {
00550 cursor_draw ();
00551 cursor_cur_blink_ = 0;
00552 }else if (cursor_cur_blink_ == (cursor_blink_cycle >> 1))
00553 cursor_undraw ();
00554 cursor_cur_blink_++;
00555 }
00556 return true;
00557 }
00558
00559
00560
00561 void label::cursor_draw ()
00562 {
00563
00564 u_int16 idx = my_cursor_.idx;
00565 if (last_letter (idx) || my_text_[idx] == '\n')
00566 my_font_->cursor->draw (my_cursor_.pos_x, my_cursor_.pos_y,NULL, this);
00567 else
00568 my_font_->cursor->draw (my_cursor_.pos_x, my_cursor_.pos_y,0, 0,
00569 (*my_font_) [ucd (idx)].length (),
00570 my_font_->height (), NULL, this);
00571 }
00572
00573 void label::cursor_undraw ()
00574 {
00575
00576 u_int16 idx = my_cursor_.idx;
00577 if (last_letter (idx) || my_text_[idx] == '\n')
00578 {
00579 lock ();
00580 fillrect(my_cursor_.pos_x, my_cursor_.pos_y,
00581 my_font_->cursor->length () ,
00582 my_font_->cursor->height(),
00583 screen::trans_col());
00584 unlock ();
00585 }
00586 else (*my_font_) [ucd (idx)].draw (my_cursor_.pos_x, my_cursor_.pos_y, NULL, this);
00587 }
00588
00589 bool label::last_letter (u_int16 idx)
00590 {
00591 if ((u_int8) my_text_[idx] == 0xEF) return my_text_.length () - idx == 2;
00592 if ((u_int8) my_text_[idx] == 0xC3) return my_text_.length () - idx == 1;
00593 return my_cursor_.idx == my_text_.length ();
00594 }
00595
00596 bool label::input_update ()
00597 {
00598
00599 if(input::has_been_pushed(KEY_CURSOR_NEXT))
00600 {
00601 if (! (height () && length ())) return false;
00602
00603
00604 }
00605 else if (input::has_been_pushed(KEY_CURSOR_PREVIOUS))
00606 {
00607 if (! (height () && length ())) return false;
00608
00609
00610 }
00611
00612 return true;
00613 }
00614
00615
00616 void label::cursor_next ()
00617 {
00618 if (!moveable_cursor_) return;
00619 if (my_cursor_.idx < my_text_.length ())
00620 {
00621 u_int8 count;
00622 if (my_cursor_.idx < my_text_.length () - 2 && (u_int8) my_text_[my_cursor_.idx+1] == 0xEF) count = 3;
00623 else if (my_cursor_.idx < my_text_.length () - 1 && (u_int8) my_text_[my_cursor_.idx+1] == 0xC3) count = 2;
00624 else count = 1;
00625
00626 my_cursor_.idx += count;
00627 update_cursor ();
00628 }
00629 }
00630
00631
00632 void label::cursor_previous ()
00633 {
00634 if (!moveable_cursor_) return;
00635 if (my_cursor_.idx > 0)
00636 {
00637 u_int8 count;
00638 if (my_cursor_.idx > 2 && (u_int8) my_text_[my_cursor_.idx-3] == 0xEF) count = 3;
00639 else if (my_cursor_.idx > 1 && (u_int8) my_text_[my_cursor_.idx-2] == 0xC3) count = 2;
00640 else count = 1;
00641
00642 my_cursor_.idx -= count;
00643 update_cursor ();
00644 }
00645 }
00646
00647
00648 const string label::text_string () const
00649 {
00650 return my_text_;
00651 }
00652
00653 const char * label::text_char () const
00654 {
00655 return my_text_.c_str ();
00656 }
00657
00658
00659 u_int16 label::ucd (u_int16 & idx)
00660 {
00661 u_int8 c = my_text_[idx];
00662 if (c < 0x80) return c;
00663
00664 if (c < 0xe0)
00665 {
00666 u_int8 c1 = my_text_[++idx];
00667 return ((u_int16) (c & 0x1f) << 6)
00668 | (u_int16) (c1 ^ 0x80);
00669 }
00670
00671 u_int8 c1 = my_text_[++idx];
00672 u_int8 c2 = my_text_[++idx];
00673 return ((u_int16) (c & 0x0f) << 12)
00674 | ((u_int16) (c1 ^ 0x80) << 6)
00675 | (u_int16) (c2 ^ 0x80);
00676 }
00677