text.cpp

Go to the documentation of this file.
00001 /* $Id: text.cpp 26270 2008-05-01 06:44:21Z mordante $ */
00002 /*
00003    copyright (C) 2008 by mark de wever <koraq@xs4all.nl>
00004    part of the battle for wesnoth project http://www.wesnoth.org/
00005 
00006    this program is free software; you can redistribute it and/or modify
00007    it under the terms of the gnu general public license version 2
00008    or at your option any later version.
00009    this program is distributed in the hope that it will be useful,
00010    but without any warranty.
00011 
00012    see the copying file for more details.
00013 */
00014 
00015 #include "gui/widgets/text.hpp"
00016 
00017 #include "clipboard.hpp"
00018 #include "gui/widgets/event_handler.hpp"
00019 #include "log.hpp"
00020 #include "serialization/string_utils.hpp"
00021 
00022 #define DBG_G LOG_STREAM_INDENT(debug, gui)
00023 #define LOG_G LOG_STREAM_INDENT(info, gui)
00024 #define WRN_G LOG_STREAM_INDENT(warn, gui)
00025 #define ERR_G LOG_STREAM_INDENT(err, gui)
00026 
00027 #define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
00028 #define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
00029 #define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
00030 #define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
00031 
00032 #define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
00033 #define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
00034 #define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
00035 #define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
00036 
00037 #define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
00038 #define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
00039 #define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
00040 #define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
00041 
00042 namespace gui2 {
00043 
00044 void ttext_::set_cursor(const size_t offset, const bool select)
00045 {
00046     if(select) {
00047 
00048         if(sel_start_ == offset) {
00049             sel_len_ = 0;
00050         } else {
00051             sel_len_ = - (sel_start_ - offset);
00052         }
00053 
00054 #ifdef __unix__
00055         // selecting copies on UNIX systems.
00056         copy_selection(true);
00057 #endif
00058         set_canvas_text();
00059         set_dirty();
00060 
00061     } else {
00062         assert(offset <= text_.size());
00063         sel_start_ = offset;
00064         sel_len_ = 0;
00065 
00066         set_canvas_text();
00067         set_dirty();
00068     }
00069 }
00070 
00071 void ttext_::mouse_move(tevent_handler&)
00072 {
00073     DBG_G_E << "Text_box: mouse move.\n"; 
00074 
00075     // if in select mode select text and move cursor
00076 }
00077 
00078 void ttext_::mouse_left_button_down(tevent_handler& event) 
00079 { 
00080     DBG_G_E << "Text_box: left mouse button down.\n"; 
00081 
00082     event.keyboard_capture(this);
00083     event.mouse_capture();
00084 }
00085 
00086 void ttext_::mouse_left_button_up(tevent_handler&) 
00087 { 
00088     // reset select  mode
00089     DBG_G_E << "Text_box: left mouse button up.\n";
00090 }
00091 
00092 void ttext_::mouse_left_button_double_click(tevent_handler&) 
00093 { 
00094     DBG_G_E << "Text_box: left mouse button double click.\n";
00095 
00096     sel_start_ = 0;
00097     sel_len_ = text_.size();
00098 
00099 }
00100 
00101 void ttext_::mouse_middle_button_click(tevent_handler&)
00102 {
00103     DBG_G_E << "Text_box: middle mouse button click.\n";
00104 #ifdef __unix__
00105         // pastes on UNIX systems.
00106         paste_selection(true);
00107 #endif
00108 
00109 }
00110 
00111 void ttext_::key_press(tevent_handler& /*event*/, bool& handled, SDLKey key, SDLMod modifier, Uint16 unicode)
00112 {
00113     DBG_G_E << "Text_box: key press.\n";
00114 
00115 // For copy/paste we use a different key on the MAC. Other ctrl modifiers won't 
00116 // be modifed seems not to be required when I read the comment in 
00117 // widgets/textbox.cpp:516. Would be nice if somebody on a MAC would test it.
00118 #ifdef __APPLE__
00119     const unsigned copypaste_modifier = KMOD_LMETA | KMOD_RMETA;
00120 #else
00121     const unsigned copypaste_modifier = KMOD_CTRL;
00122 #endif
00123 
00124     switch(key) {
00125 
00126         case SDLK_LEFT :
00127             handle_key_left_arrow(modifier, handled);
00128             break;
00129 
00130         case SDLK_RIGHT :
00131             handle_key_right_arrow(modifier, handled);
00132             break;
00133 
00134         case SDLK_UP :
00135             handle_key_up_arrow(modifier, handled);
00136             break;
00137 
00138         case SDLK_DOWN :
00139             handle_key_down_arrow(modifier, handled);
00140             break;
00141 
00142         case SDLK_PAGEUP :
00143             handle_key_page_up(modifier, handled);
00144             break;
00145 
00146         case SDLK_PAGEDOWN :
00147             handle_key_page_down(modifier, handled);
00148             break;
00149 
00150         case SDLK_a :
00151             if(!(modifier & KMOD_CTRL)) {
00152                 handle_key_default(handled, key, modifier, unicode);
00153                 break;
00154             }
00155             
00156             // If ctrl-a is used for home drop the control modifier
00157             modifier = static_cast<SDLMod>(modifier &~ KMOD_CTRL);
00158             /* FALL DOWN */
00159 
00160         case SDLK_HOME :
00161             handle_key_home(modifier, handled);
00162             break;
00163             
00164         case SDLK_e :
00165             if(!(modifier & KMOD_CTRL)) {
00166                 handle_key_default(handled, key, modifier, unicode);
00167                 break;
00168             }
00169             
00170             // If ctrl-e is used for end drop the control modifier
00171             modifier = static_cast<SDLMod>(modifier &~ KMOD_CTRL);
00172             /* FALL DOWN */
00173 
00174         case SDLK_END :
00175             handle_key_end(modifier, handled);
00176             break;
00177 
00178         case SDLK_BACKSPACE :
00179             handle_key_backspace(modifier, handled);
00180             break;
00181 
00182         case SDLK_u :
00183             if(modifier & KMOD_CTRL) {
00184                 handle_key_clear_line(modifier, handled);
00185             } else {
00186                 handle_key_default(handled, key, modifier, unicode);
00187             }
00188             break;
00189 
00190         case SDLK_DELETE :
00191             handle_key_delete(modifier, handled);
00192             break;
00193 
00194         case SDLK_c :
00195             if(!(modifier & copypaste_modifier)) {
00196                 handle_key_default(handled, key, modifier, unicode);
00197                 break;
00198             }
00199             
00200             // atm we don't care whether there is something to copy or paste
00201             // if nothing is there we still don't want to be chained.
00202             copy_selection(false);
00203             handled = true;
00204             break;
00205 
00206         case SDLK_x :
00207             if(!(modifier & copypaste_modifier)) {
00208                 handle_key_default(handled, key, modifier, unicode);
00209                 break;
00210             }
00211             
00212             copy_selection(false);
00213             delete_selection();
00214             handled = true;
00215             break;
00216 
00217         case SDLK_v :
00218             if(!(modifier & copypaste_modifier)) {
00219                 handle_key_default(handled, key, modifier, unicode);
00220                 break;
00221             }
00222             
00223             paste_selection(false);
00224             handled = true;
00225             break;
00226 
00227         default :
00228             handle_key_default(handled, key, modifier, unicode);
00229 
00230     }
00231 
00232 }
00233 
00234 void ttext_::set_text(const std::string& text)
00235 { 
00236     if(text != text_) { 
00237         text_ = text; 
00238         calculate_char_offset(); 
00239 
00240         // default to put the cursor at the end of the buffer.
00241         sel_start_ = text_.size();
00242         sel_len_ = 0;
00243         set_canvas_text();
00244         set_dirty(); 
00245     } 
00246 }
00247 
00248 void ttext_::set_state(tstate state)
00249 {
00250     if(state != state_) {
00251         state_ = state;
00252         set_dirty(true);
00253     }
00254 }
00255 
00256 //! Copies the current selection.
00257 void ttext_::copy_selection(const bool mouse)
00258 {
00259     int len = sel_len();
00260     unsigned start = sel_start();
00261 
00262     if(len < 0) {
00263         len = - len;
00264         start -= len;
00265     }
00266 
00267     const wide_string& wtext = utils::string_to_wstring(text_);
00268     const std::string& text = utils::wstring_to_string(wide_string(wtext.begin() + start, wtext.begin() + start +len));
00269     copy_to_clipboard(text, mouse);
00270 }
00271 
00272 //! Pastes the current selection.
00273 void ttext_::paste_selection(const bool mouse)
00274 {
00275     const std::string& text = copy_from_clipboard(mouse);
00276     if(text.empty()) {
00277         return;
00278     }
00279 
00280     delete_selection();
00281 
00282     text_.insert(sel_start_, text);
00283 
00284     sel_start_ += utils::string_to_wstring(text).size();
00285 
00286     calculate_char_offset(); 
00287     set_canvas_text();
00288     set_dirty(); 
00289 }
00290 
00291 // Go a character left of not at start of buffer else beep.
00292 // ctrl moves a word instead of character.
00293 // shift selects while moving.
00294 void ttext_::handle_key_left_arrow(SDLMod modifier, bool& handled)
00295 {
00296     DBG_G_E << "Text_box: key press: left arrow.\n";
00297 
00298     handled = true;
00299     if(sel_start_) {
00300         set_cursor(sel_start_ - 1 + sel_len_, modifier & KMOD_SHIFT);
00301     }
00302 }
00303 
00304 // Go a character right of not at end of buffer else beep.
00305 // ctrl moves a word instead of character.
00306 // shift selects while moving.
00307 void ttext_::handle_key_right_arrow(SDLMod modifier, bool& handled)
00308 {
00309     DBG_G_E << "Text_box: key press: right arrow.\n";
00310 
00311     handled = true;
00312     if(sel_start_ < text_.size()) {
00313         set_cursor(sel_start_ + 1 + sel_len_, modifier & KMOD_SHIFT);
00314     }
00315 }
00316 
00317 // Go to the beginning of the line.
00318 // ctrl moves the start of data (except when ctrl-e but caller does that) 
00319 // shift selects while moving.
00320 void ttext_::handle_key_home(SDLMod modifier, bool& handled)
00321 {
00322     DBG_G_E << "Text_box: key press: home.\n";
00323 
00324     handled = true;
00325     if(modifier & KMOD_CTRL) {
00326         goto_start_of_data(modifier & KMOD_SHIFT);
00327     } else {
00328         goto_start_of_line(modifier & KMOD_SHIFT);
00329     }
00330 }
00331 
00332 // Go to the end of the line.
00333 // ctrl moves the end of data (except when ctrl-a but caller does that) 
00334 // shift selects while moving.
00335 void ttext_::handle_key_end(SDLMod modifier, bool& handled)
00336 {
00337     DBG_G_E << "Text_box: key press: end.\n";
00338 
00339     handled = true;
00340     if(modifier & KMOD_CTRL) {
00341         goto_end_of_data(modifier & KMOD_SHIFT);
00342     } else {
00343         goto_end_of_line(modifier & KMOD_SHIFT);
00344     }
00345 }
00346 
00347 // Deletes the character in front of the cursor (if not at the beginning).
00348 void ttext_::handle_key_backspace(SDLMod /*modifier*/, bool& handled)
00349 {
00350     DBG_G_E << "Text_box: key press: backspace.\n";
00351 
00352     handled = true;
00353     if(sel_start_){
00354         delete_char(true);
00355     }
00356 
00357 }
00358 
00359 // Deletes either the selection or the character beyond the cursor
00360 void ttext_::handle_key_delete(SDLMod /*modifier*/, bool& handled)
00361 {
00362     DBG_G_E << "Text_box: key press: delete.\n";
00363 
00364     handled = true;
00365     if(sel_len_ != 0) {
00366         delete_selection();
00367     } else if (sel_start_ < text_.size()) {
00368         delete_char(false);
00369     }
00370 }
00371 
00372 void ttext_::handle_key_default(bool& handled, SDLKey /*key*/, SDLMod /*modifier*/, Uint16 unicode)
00373 {
00374     DBG_G_E << "Text_box: key press: default.\n";
00375 
00376     if(unicode >= 32 && unicode != 127) {
00377         handled = true;
00378         insert_char(unicode);
00379     }
00380 }
00381 
00382 } // namespace gui2
00383 

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs