]> git.lizzy.rs Git - dragonfireclient.git/blob - src/intlGUIEditBox.cpp
Revert "Fix serverlist not beeing escaped correctly"
[dragonfireclient.git] / src / intlGUIEditBox.cpp
1 // 11.11.2011 11:11 ValkaTR
2 //
3 // This is a copy of intlGUIEditBox from the irrlicht, but with a
4 // fix in the OnEvent function, which doesn't allowed input of
5 // other keyboard layouts than latin-1
6 //
7 // Characters like: ä ö ü õ ы й ю я ъ № € ° ...
8 //
9 // This fix is only needed for linux, because of a bug
10 // in the CIrrDeviceLinux.cpp:1014-1015 of the irrlicht
11 //
12 // Also locale in the programm should not be changed to
13 // a "C", "POSIX" or whatever, it should be set to "",
14 // or XLookupString will return nothing for the international
15 // characters.
16 //
17 // From the "man setlocale":
18 //
19 // On startup of the main program, the portable "C" locale
20 // is selected as default.  A  program  may  be  made
21 // portable to all locales by calling:
22 //
23 //           setlocale(LC_ALL, "");
24 //
25 //       after  program initialization....
26 //
27
28 // Copyright (C) 2002-2013 Nikolaus Gebhardt
29 // This file is part of the "Irrlicht Engine".
30 // For conditions of distribution and use, see copyright notice in irrlicht.h
31
32 #include "intlGUIEditBox.h"
33
34 #ifdef _IRR_COMPILE_WITH_GUI_
35
36 #include "IGUISkin.h"
37 #include "IGUIEnvironment.h"
38 #include "IGUIFont.h"
39 #include "IVideoDriver.h"
40 //#include "rect.h"
41 //#include "irrlicht/os.cpp"
42 #include "porting.h"
43 //#include "Keycodes.h"
44
45 /*
46         todo:
47         optional scrollbars
48         ctrl+left/right to select word
49         double click/ctrl click: word select + drag to select whole words, triple click to select line
50         optional? dragging selected text
51         numerical
52 */
53
54 namespace irr
55 {
56 namespace gui
57 {
58
59 //! constructor
60 intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border,
61                 IGUIEnvironment* environment, IGUIElement* parent, s32 id,
62                 const core::rect<s32>& rectangle)
63         : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false),
64         Border(border), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
65         OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0),
66         Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0),
67         WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false),
68         PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER),
69         CurrentTextRect(0,0,1,1), FrameRect(rectangle)
70 {
71         #ifdef _DEBUG
72         setDebugName("intlintlGUIEditBox");
73         #endif
74
75         Text = text;
76
77         if (Environment)
78                 Operator = Environment->getOSOperator();
79
80         if (Operator)
81                 Operator->grab();
82
83         // this element can be tabbed to
84         setTabStop(true);
85         setTabOrder(-1);
86
87         IGUISkin *skin = 0;
88         if (Environment)
89                 skin = Environment->getSkin();
90         if (Border && skin)
91         {
92                 FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
93                 FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
94                 FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
95                 FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
96         }
97
98         breakText();
99
100         calculateScrollPos();
101 }
102
103
104 //! destructor
105 intlGUIEditBox::~intlGUIEditBox()
106 {
107         if (OverrideFont)
108                 OverrideFont->drop();
109
110         if (Operator)
111                 Operator->drop();
112 }
113
114
115 //! Sets another skin independent font.
116 void intlGUIEditBox::setOverrideFont(IGUIFont* font)
117 {
118         if (OverrideFont == font)
119                 return;
120
121         if (OverrideFont)
122                 OverrideFont->drop();
123
124         OverrideFont = font;
125
126         if (OverrideFont)
127                 OverrideFont->grab();
128
129         breakText();
130 }
131
132 IGUIFont * intlGUIEditBox::getOverrideFont() const
133 {
134         return OverrideFont;
135 }
136
137 //! Get the font which is used right now for drawing
138 IGUIFont* intlGUIEditBox::getActiveFont() const
139 {
140         if ( OverrideFont )
141                 return OverrideFont;
142         IGUISkin* skin = Environment->getSkin();
143         if (skin)
144                 return skin->getFont();
145         return 0;
146 }
147
148 //! Sets another color for the text.
149 void intlGUIEditBox::setOverrideColor(video::SColor color)
150 {
151         OverrideColor = color;
152         OverrideColorEnabled = true;
153 }
154
155 video::SColor intlGUIEditBox::getOverrideColor() const
156 {
157         return OverrideColor;
158 }
159
160 //! Turns the border on or off
161 void intlGUIEditBox::setDrawBorder(bool border)
162 {
163         Border = border;
164 }
165
166 //! Sets whether to draw the background
167 void intlGUIEditBox::setDrawBackground(bool draw)
168 {
169 }
170
171 //! Sets if the text should use the overide color or the color in the gui skin.
172 void intlGUIEditBox::enableOverrideColor(bool enable)
173 {
174         OverrideColorEnabled = enable;
175 }
176
177 bool intlGUIEditBox::isOverrideColorEnabled() const
178 {
179         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
180         return OverrideColorEnabled;
181 }
182
183 //! Enables or disables word wrap
184 void intlGUIEditBox::setWordWrap(bool enable)
185 {
186         WordWrap = enable;
187         breakText();
188 }
189
190
191 void intlGUIEditBox::updateAbsolutePosition()
192 {
193     core::rect<s32> oldAbsoluteRect(AbsoluteRect);
194         IGUIElement::updateAbsolutePosition();
195         if ( oldAbsoluteRect != AbsoluteRect )
196         {
197         breakText();
198         }
199 }
200
201
202 //! Checks if word wrap is enabled
203 bool intlGUIEditBox::isWordWrapEnabled() const
204 {
205         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
206         return WordWrap;
207 }
208
209
210 //! Enables or disables newlines.
211 void intlGUIEditBox::setMultiLine(bool enable)
212 {
213         MultiLine = enable;
214 }
215
216
217 //! Checks if multi line editing is enabled
218 bool intlGUIEditBox::isMultiLineEnabled() const
219 {
220         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
221         return MultiLine;
222 }
223
224
225 void intlGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar)
226 {
227         PasswordBox = passwordBox;
228         if (PasswordBox)
229         {
230                 PasswordChar = passwordChar;
231                 setMultiLine(false);
232                 setWordWrap(false);
233                 BrokenText.clear();
234         }
235 }
236
237
238 bool intlGUIEditBox::isPasswordBox() const
239 {
240         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
241         return PasswordBox;
242 }
243
244
245 //! Sets text justification
246 void intlGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
247 {
248         HAlign = horizontal;
249         VAlign = vertical;
250 }
251
252
253 //! called if an event happened.
254 bool intlGUIEditBox::OnEvent(const SEvent& event)
255 {
256         if (IsEnabled)
257         {
258
259                 switch(event.EventType)
260                 {
261                 case EET_GUI_EVENT:
262                         if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
263                         {
264                                 if (event.GUIEvent.Caller == this)
265                                 {
266                                         MouseMarking = false;
267                                         setTextMarkers(0,0);
268                                 }
269                         }
270                         break;
271                 case EET_KEY_INPUT_EVENT:
272         {
273 #if defined(linux)
274             // ################################################################
275                         // ValkaTR:
276             // This part is the difference from the original intlGUIEditBox
277             // It converts UTF-8 character into a UCS-2 (wchar_t)
278             wchar_t wc = L'_';
279             mbtowc( &wc, (char *) &event.KeyInput.Char, sizeof(event.KeyInput.Char) );
280
281             //printf( "char: %lc (%u)  \r\n", wc, wc );
282
283             SEvent irrevent(event);
284             irrevent.KeyInput.Char = wc;
285             // ################################################################
286
287                         if (processKey(irrevent))
288                                 return true;
289 #else
290                         if (processKey(event))
291                                 return true;
292 #endif // defined(linux)
293
294                         break;
295         }
296                 case EET_MOUSE_INPUT_EVENT:
297                         if (processMouse(event))
298                                 return true;
299                         break;
300                 default:
301                         break;
302                 }
303         }
304
305         return IGUIElement::OnEvent(event);
306 }
307
308
309 bool intlGUIEditBox::processKey(const SEvent& event)
310 {
311         if (!event.KeyInput.PressedDown)
312                 return false;
313
314         bool textChanged = false;
315         s32 newMarkBegin = MarkBegin;
316         s32 newMarkEnd = MarkEnd;
317
318         // control shortcut handling
319
320         if (event.KeyInput.Control)
321         {
322                 // german backlash '\' entered with control + '?'
323                 if ( event.KeyInput.Char == '\\' )
324                 {
325                         inputChar(event.KeyInput.Char);
326                         return true;
327                 }
328
329                 switch(event.KeyInput.Key)
330                 {
331                 case KEY_KEY_A:
332                         // select all
333                         newMarkBegin = 0;
334                         newMarkEnd = Text.size();
335                         break;
336                 case KEY_KEY_C:
337                         // copy to clipboard
338                         if (!PasswordBox && Operator && MarkBegin != MarkEnd)
339                         {
340                                 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
341                                 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
342
343                                 core::stringc s;
344                                 s = Text.subString(realmbgn, realmend - realmbgn).c_str();
345                                 Operator->copyToClipboard(s.c_str());
346                         }
347                         break;
348                 case KEY_KEY_X:
349                         // cut to the clipboard
350                         if (!PasswordBox && Operator && MarkBegin != MarkEnd)
351                         {
352                                 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
353                                 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
354
355                                 // copy
356                                 core::stringc sc;
357                                 sc = Text.subString(realmbgn, realmend - realmbgn).c_str();
358                                 Operator->copyToClipboard(sc.c_str());
359
360                                 if (IsEnabled)
361                                 {
362                                         // delete
363                                         core::stringw s;
364                                         s = Text.subString(0, realmbgn);
365                                         s.append( Text.subString(realmend, Text.size()-realmend) );
366                                         Text = s;
367
368                                         CursorPos = realmbgn;
369                                         newMarkBegin = 0;
370                                         newMarkEnd = 0;
371                                         textChanged = true;
372                                 }
373                         }
374                         break;
375                 case KEY_KEY_V:
376                         if ( !IsEnabled )
377                                 break;
378
379                         // paste from the clipboard
380                         if (Operator)
381                         {
382                                 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
383                                 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
384
385                                 // add new character
386                                 const c8* p = Operator->getTextFromClipboard();
387                                 if (p)
388                                 {
389                                         if (MarkBegin == MarkEnd)
390                                         {
391                                                 // insert text
392                                                 core::stringw s = Text.subString(0, CursorPos);
393                                                 s.append(p);
394                                                 s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
395
396                                                 if (!Max || s.size()<=Max) // thx to Fish FH for fix
397                                                 {
398                                                         Text = s;
399                                                         s = p;
400                                                         CursorPos += s.size();
401                                                 }
402                                         }
403                                         else
404                                         {
405                                                 // replace text
406
407                                                 core::stringw s = Text.subString(0, realmbgn);
408                                                 s.append(p);
409                                                 s.append( Text.subString(realmend, Text.size()-realmend) );
410
411                                                 if (!Max || s.size()<=Max)  // thx to Fish FH for fix
412                                                 {
413                                                         Text = s;
414                                                         s = p;
415                                                         CursorPos = realmbgn + s.size();
416                                                 }
417                                         }
418                                 }
419
420                                 newMarkBegin = 0;
421                                 newMarkEnd = 0;
422                                 textChanged = true;
423                         }
424                         break;
425                 case KEY_HOME:
426                         // move/highlight to start of text
427                         if (event.KeyInput.Shift)
428                         {
429                                 newMarkEnd = CursorPos;
430                                 newMarkBegin = 0;
431                                 CursorPos = 0;
432                         }
433                         else
434                         {
435                                 CursorPos = 0;
436                                 newMarkBegin = 0;
437                                 newMarkEnd = 0;
438                         }
439                         break;
440                 case KEY_END:
441                         // move/highlight to end of text
442                         if (event.KeyInput.Shift)
443                         {
444                                 newMarkBegin = CursorPos;
445                                 newMarkEnd = Text.size();
446                                 CursorPos = 0;
447                         }
448                         else
449                         {
450                                 CursorPos = Text.size();
451                                 newMarkBegin = 0;
452                                 newMarkEnd = 0;
453                         }
454                         break;
455                 default:
456                         return false;
457                 }
458         }
459         // default keyboard handling
460         else
461         switch(event.KeyInput.Key)
462         {
463         case KEY_END:
464                 {
465                         s32 p = Text.size();
466                         if (WordWrap || MultiLine)
467                         {
468                                 p = getLineFromPos(CursorPos);
469                                 p = BrokenTextPositions[p] + (s32)BrokenText[p].size();
470                                 if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' ))
471                                         p-=1;
472                         }
473
474                         if (event.KeyInput.Shift)
475                         {
476                                 if (MarkBegin == MarkEnd)
477                                         newMarkBegin = CursorPos;
478
479                                 newMarkEnd = p;
480                         }
481                         else
482                         {
483                                 newMarkBegin = 0;
484                                 newMarkEnd = 0;
485                         }
486                         CursorPos = p;
487                         BlinkStartTime = porting::getTimeMs();
488                 }
489                 break;
490         case KEY_HOME:
491                 {
492
493                         s32 p = 0;
494                         if (WordWrap || MultiLine)
495                         {
496                                 p = getLineFromPos(CursorPos);
497                                 p = BrokenTextPositions[p];
498                         }
499
500                         if (event.KeyInput.Shift)
501                         {
502                                 if (MarkBegin == MarkEnd)
503                                         newMarkBegin = CursorPos;
504                                 newMarkEnd = p;
505                         }
506                         else
507                         {
508                                 newMarkBegin = 0;
509                                 newMarkEnd = 0;
510                         }
511                         CursorPos = p;
512                         BlinkStartTime = porting::getTimeMs();
513                 }
514                 break;
515         case KEY_RETURN:
516                 if (MultiLine)
517                 {
518                         inputChar(L'\n');
519                         return true;
520                 }
521                 else
522                 {
523                     sendGuiEvent( EGET_EDITBOX_ENTER );
524                 }
525                 break;
526         case KEY_LEFT:
527
528                 if (event.KeyInput.Shift)
529                 {
530                         if (CursorPos > 0)
531                         {
532                                 if (MarkBegin == MarkEnd)
533                                         newMarkBegin = CursorPos;
534
535                                 newMarkEnd = CursorPos-1;
536                         }
537                 }
538                 else
539                 {
540                         newMarkBegin = 0;
541                         newMarkEnd = 0;
542                 }
543
544                 if (CursorPos > 0) CursorPos--;
545                 BlinkStartTime = porting::getTimeMs();
546                 break;
547
548         case KEY_RIGHT:
549                 if (event.KeyInput.Shift)
550                 {
551                         if (Text.size() > (u32)CursorPos)
552                         {
553                                 if (MarkBegin == MarkEnd)
554                                         newMarkBegin = CursorPos;
555
556                                 newMarkEnd = CursorPos+1;
557                         }
558                 }
559                 else
560                 {
561                         newMarkBegin = 0;
562                         newMarkEnd = 0;
563                 }
564
565                 if (Text.size() > (u32)CursorPos) CursorPos++;
566                 BlinkStartTime = porting::getTimeMs();
567                 break;
568         case KEY_UP:
569                 if (MultiLine || (WordWrap && BrokenText.size() > 1) )
570                 {
571                         s32 lineNo = getLineFromPos(CursorPos);
572                         s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd);
573                         if (lineNo > 0)
574                         {
575                                 s32 cp = CursorPos - BrokenTextPositions[lineNo];
576                                 if ((s32)BrokenText[lineNo-1].size() < cp)
577                                         CursorPos = BrokenTextPositions[lineNo-1] + (s32)BrokenText[lineNo-1].size()-1;
578                                 else
579                                         CursorPos = BrokenTextPositions[lineNo-1] + cp;
580                         }
581
582                         if (event.KeyInput.Shift)
583                         {
584                                 newMarkBegin = mb;
585                                 newMarkEnd = CursorPos;
586                         }
587                         else
588                         {
589                                 newMarkBegin = 0;
590                                 newMarkEnd = 0;
591                         }
592
593                 }
594                 else
595                 {
596                         return false;
597                 }
598                 break;
599         case KEY_DOWN:
600                 if (MultiLine || (WordWrap && BrokenText.size() > 1) )
601                 {
602                         s32 lineNo = getLineFromPos(CursorPos);
603                         s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd);
604                         if (lineNo < (s32)BrokenText.size()-1)
605                         {
606                                 s32 cp = CursorPos - BrokenTextPositions[lineNo];
607                                 if ((s32)BrokenText[lineNo+1].size() < cp)
608                                         CursorPos = BrokenTextPositions[lineNo+1] + BrokenText[lineNo+1].size()-1;
609                                 else
610                                         CursorPos = BrokenTextPositions[lineNo+1] + cp;
611                         }
612
613                         if (event.KeyInput.Shift)
614                         {
615                                 newMarkBegin = mb;
616                                 newMarkEnd = CursorPos;
617                         }
618                         else
619                         {
620                                 newMarkBegin = 0;
621                                 newMarkEnd = 0;
622                         }
623
624                 }
625                 else
626                 {
627                         return false;
628                 }
629                 break;
630
631         case KEY_BACK:
632                 if ( !this->IsEnabled )
633                         break;
634
635                 if (Text.size())
636                 {
637                         core::stringw s;
638
639                         if (MarkBegin != MarkEnd)
640                         {
641                                 // delete marked text
642                                 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
643                                 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
644
645                                 s = Text.subString(0, realmbgn);
646                                 s.append( Text.subString(realmend, Text.size()-realmend) );
647                                 Text = s;
648
649                                 CursorPos = realmbgn;
650                         }
651                         else
652                         {
653                                 // delete text behind cursor
654                                 if (CursorPos>0)
655                                         s = Text.subString(0, CursorPos-1);
656                                 else
657                                         s = L"";
658                                 s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
659                                 Text = s;
660                                 --CursorPos;
661                         }
662
663                         if (CursorPos < 0)
664                                 CursorPos = 0;
665                         BlinkStartTime = porting::getTimeMs();
666                         newMarkBegin = 0;
667                         newMarkEnd = 0;
668                         textChanged = true;
669                 }
670                 break;
671         case KEY_DELETE:
672                 if ( !this->IsEnabled )
673                         break;
674
675                 if (Text.size() != 0)
676                 {
677                         core::stringw s;
678
679                         if (MarkBegin != MarkEnd)
680                         {
681                                 // delete marked text
682                                 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
683                                 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
684
685                                 s = Text.subString(0, realmbgn);
686                                 s.append( Text.subString(realmend, Text.size()-realmend) );
687                                 Text = s;
688
689                                 CursorPos = realmbgn;
690                         }
691                         else
692                         {
693                                 // delete text before cursor
694                                 s = Text.subString(0, CursorPos);
695                                 s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) );
696                                 Text = s;
697                         }
698
699                         if (CursorPos > (s32)Text.size())
700                                 CursorPos = (s32)Text.size();
701
702                         BlinkStartTime = porting::getTimeMs();
703                         newMarkBegin = 0;
704                         newMarkEnd = 0;
705                         textChanged = true;
706                 }
707                 break;
708
709         case KEY_ESCAPE:
710         case KEY_TAB:
711         case KEY_SHIFT:
712         case KEY_F1:
713         case KEY_F2:
714         case KEY_F3:
715         case KEY_F4:
716         case KEY_F5:
717         case KEY_F6:
718         case KEY_F7:
719         case KEY_F8:
720         case KEY_F9:
721         case KEY_F10:
722         case KEY_F11:
723         case KEY_F12:
724         case KEY_F13:
725         case KEY_F14:
726         case KEY_F15:
727         case KEY_F16:
728         case KEY_F17:
729         case KEY_F18:
730         case KEY_F19:
731         case KEY_F20:
732         case KEY_F21:
733         case KEY_F22:
734         case KEY_F23:
735         case KEY_F24:
736                 // ignore these keys
737                 return false;
738
739         default:
740                 inputChar(event.KeyInput.Char);
741                 return true;
742         }
743
744     // Set new text markers
745     setTextMarkers( newMarkBegin, newMarkEnd );
746
747         // break the text if it has changed
748         if (textChanged)
749         {
750                 breakText();
751                 sendGuiEvent(EGET_EDITBOX_CHANGED);
752         }
753
754         calculateScrollPos();
755
756         return true;
757 }
758
759
760 //! draws the element and its children
761 void intlGUIEditBox::draw()
762 {
763         if (!IsVisible)
764                 return;
765
766         const bool focus = Environment->hasFocus(this);
767
768         IGUISkin* skin = Environment->getSkin();
769         if (!skin)
770                 return;
771
772         FrameRect = AbsoluteRect;
773
774         // draw the border
775
776         if (Border)
777         {
778                 skin->draw3DSunkenPane(this, skin->getColor(EGDC_WINDOW),
779                         false, true, FrameRect, &AbsoluteClippingRect);
780
781                 FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
782                 FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
783                 FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
784                 FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
785         }
786         core::rect<s32> localClipRect = FrameRect;
787         localClipRect.clipAgainst(AbsoluteClippingRect);
788
789         // draw the text
790
791         IGUIFont* font = OverrideFont;
792         if (!OverrideFont)
793                 font = skin->getFont();
794
795         s32 cursorLine = 0;
796         s32 charcursorpos = 0;
797
798         if (font)
799         {
800                 if (LastBreakFont != font)
801                 {
802                         breakText();
803                 }
804
805                 // calculate cursor pos
806
807                 core::stringw *txtLine = &Text;
808                 s32 startPos = 0;
809
810                 core::stringw s, s2;
811
812                 // get mark position
813                 const bool ml = (!PasswordBox && (WordWrap || MultiLine));
814                 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
815                 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
816                 const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0;
817                 const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1;
818                 const s32 lineCount = ml ? BrokenText.size() : 1;
819
820                 // Save the override color information.
821                 // Then, alter it if the edit box is disabled.
822                 const bool prevOver = OverrideColorEnabled;
823                 const video::SColor prevColor = OverrideColor;
824
825                 if (Text.size())
826                 {
827                         if (!IsEnabled && !OverrideColorEnabled)
828                         {
829                                 OverrideColorEnabled = true;
830                                 OverrideColor = skin->getColor(EGDC_GRAY_TEXT);
831                         }
832
833                         for (s32 i=0; i < lineCount; ++i)
834                         {
835                                 setTextRect(i);
836
837                                 // clipping test - don't draw anything outside the visible area
838                                 core::rect<s32> c = localClipRect;
839                                 c.clipAgainst(CurrentTextRect);
840                                 if (!c.isValid())
841                                         continue;
842
843                                 // get current line
844                                 if (PasswordBox)
845                                 {
846                                         if (BrokenText.size() != 1)
847                                         {
848                                                 BrokenText.clear();
849                                                 BrokenText.push_back(core::stringw());
850                                         }
851                                         if (BrokenText[0].size() != Text.size())
852                                         {
853                                                 BrokenText[0] = Text;
854                                                 for (u32 q = 0; q < Text.size(); ++q)
855                                                 {
856                                                         BrokenText[0] [q] = PasswordChar;
857                                                 }
858                                         }
859                                         txtLine = &BrokenText[0];
860                                         startPos = 0;
861                                 }
862                                 else
863                                 {
864                                         txtLine = ml ? &BrokenText[i] : &Text;
865                                         startPos = ml ? BrokenTextPositions[i] : 0;
866                                 }
867
868
869                                 // draw normal text
870                                 font->draw(txtLine->c_str(), CurrentTextRect,
871                                         OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
872                                         false, true, &localClipRect);
873
874                                 // draw mark and marked text
875                                 if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount)
876                                 {
877
878                                         s32 mbegin = 0, mend = 0;
879                                         s32 lineStartPos = 0, lineEndPos = txtLine->size();
880
881                                         if (i == hlineStart)
882                                         {
883                                                 // highlight start is on this line
884                                                 s = txtLine->subString(0, realmbgn - startPos);
885                                                 mbegin = font->getDimension(s.c_str()).Width;
886
887                                                 // deal with kerning
888                                                 mbegin += font->getKerningWidth(
889                                                         &((*txtLine)[realmbgn - startPos]),
890                                                         realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0);
891
892                                                 lineStartPos = realmbgn - startPos;
893                                         }
894                                         if (i == hlineStart + hlineCount - 1)
895                                         {
896                                                 // highlight end is on this line
897                                                 s2 = txtLine->subString(0, realmend - startPos);
898                                                 mend = font->getDimension(s2.c_str()).Width;
899                                                 lineEndPos = (s32)s2.size();
900                                         }
901                                         else
902                                                 mend = font->getDimension(txtLine->c_str()).Width;
903
904                                         CurrentTextRect.UpperLeftCorner.X += mbegin;
905                                         CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin;
906
907                                         // draw mark
908                                         skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect);
909
910                                         // draw marked text
911                                         s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos);
912
913                                         if (s.size())
914                                                 font->draw(s.c_str(), CurrentTextRect,
915                                                         OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT),
916                                                         false, true, &localClipRect);
917
918                                 }
919                         }
920
921                         // Return the override color information to its previous settings.
922                         OverrideColorEnabled = prevOver;
923                         OverrideColor = prevColor;
924                 }
925
926                 // draw cursor
927
928                 if (WordWrap || MultiLine)
929                 {
930                         cursorLine = getLineFromPos(CursorPos);
931                         txtLine = &BrokenText[cursorLine];
932                         startPos = BrokenTextPositions[cursorLine];
933                 }
934                 s = txtLine->subString(0,CursorPos-startPos);
935                 charcursorpos = font->getDimension(s.c_str()).Width +
936                         font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0);
937
938                 if (focus && (porting::getTimeMs() - BlinkStartTime) % 700 < 350)
939                 {
940                         setTextRect(cursorLine);
941                         CurrentTextRect.UpperLeftCorner.X += charcursorpos;
942
943                         font->draw(L"_", CurrentTextRect,
944                                 OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
945                                 false, true, &localClipRect);
946                 }
947         }
948
949         // draw children
950         IGUIElement::draw();
951 }
952
953
954 //! Sets the new caption of this element.
955 void intlGUIEditBox::setText(const wchar_t* text)
956 {
957         Text = text;
958         if (u32(CursorPos) > Text.size())
959                 CursorPos = Text.size();
960         HScrollPos = 0;
961         breakText();
962 }
963
964
965 //! Enables or disables automatic scrolling with cursor position
966 //! \param enable: If set to true, the text will move around with the cursor position
967 void intlGUIEditBox::setAutoScroll(bool enable)
968 {
969         AutoScroll = enable;
970 }
971
972
973 //! Checks to see if automatic scrolling is enabled
974 //! \return true if automatic scrolling is enabled, false if not
975 bool intlGUIEditBox::isAutoScrollEnabled() const
976 {
977         _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
978         return AutoScroll;
979 }
980
981
982 //! Gets the area of the text in the edit box
983 //! \return Returns the size in pixels of the text
984 core::dimension2du intlGUIEditBox::getTextDimension()
985 {
986         core::rect<s32> ret;
987
988         setTextRect(0);
989         ret = CurrentTextRect;
990
991         for (u32 i=1; i < BrokenText.size(); ++i)
992         {
993                 setTextRect(i);
994                 ret.addInternalPoint(CurrentTextRect.UpperLeftCorner);
995                 ret.addInternalPoint(CurrentTextRect.LowerRightCorner);
996         }
997
998         return core::dimension2du(ret.getSize());
999 }
1000
1001
1002 //! Sets the maximum amount of characters which may be entered in the box.
1003 //! \param max: Maximum amount of characters. If 0, the character amount is
1004 //! infinity.
1005 void intlGUIEditBox::setMax(u32 max)
1006 {
1007         Max = max;
1008
1009         if (Text.size() > Max && Max != 0)
1010                 Text = Text.subString(0, Max);
1011 }
1012
1013
1014 //! Returns maximum amount of characters, previously set by setMax();
1015 u32 intlGUIEditBox::getMax() const
1016 {
1017         return Max;
1018 }
1019
1020
1021 bool intlGUIEditBox::processMouse(const SEvent& event)
1022 {
1023         switch(event.MouseInput.Event)
1024         {
1025         case irr::EMIE_LMOUSE_LEFT_UP:
1026                 if (Environment->hasFocus(this))
1027                 {
1028                         CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
1029                         if (MouseMarking)
1030                         {
1031                             setTextMarkers( MarkBegin, CursorPos );
1032                         }
1033                         MouseMarking = false;
1034                         calculateScrollPos();
1035                         return true;
1036                 }
1037                 break;
1038         case irr::EMIE_MOUSE_MOVED:
1039                 {
1040                         if (MouseMarking)
1041                         {
1042                                 CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
1043                                 setTextMarkers( MarkBegin, CursorPos );
1044                                 calculateScrollPos();
1045                                 return true;
1046                         }
1047                 }
1048                 break;
1049         case EMIE_LMOUSE_PRESSED_DOWN:
1050                 if (!Environment->hasFocus(this))
1051                 {
1052                         BlinkStartTime = porting::getTimeMs();
1053                         MouseMarking = true;
1054                         CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
1055                         setTextMarkers(CursorPos, CursorPos );
1056                         calculateScrollPos();
1057                         return true;
1058                 }
1059                 else
1060                 {
1061                         if (!AbsoluteClippingRect.isPointInside(
1062                                 core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
1063                         {
1064                                 return false;
1065                         }
1066                         else
1067                         {
1068                                 // move cursor
1069                                 CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
1070
1071                 s32 newMarkBegin = MarkBegin;
1072                                 if (!MouseMarking)
1073                                         newMarkBegin = CursorPos;
1074
1075                                 MouseMarking = true;
1076                                 setTextMarkers( newMarkBegin, CursorPos);
1077                                 calculateScrollPos();
1078                                 return true;
1079                         }
1080                 }
1081         default:
1082                 break;
1083         }
1084
1085         return false;
1086 }
1087
1088
1089 s32 intlGUIEditBox::getCursorPos(s32 x, s32 y)
1090 {
1091         IGUIFont* font = OverrideFont;
1092         IGUISkin* skin = Environment->getSkin();
1093         if (!OverrideFont)
1094                 font = skin->getFont();
1095
1096         const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
1097
1098         core::stringw *txtLine=0;
1099         s32 startPos=0;
1100         x+=3;
1101
1102         for (u32 i=0; i < lineCount; ++i)
1103         {
1104                 setTextRect(i);
1105                 if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y)
1106                         y = CurrentTextRect.UpperLeftCorner.Y;
1107                 if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y )
1108                         y = CurrentTextRect.LowerRightCorner.Y;
1109
1110                 // is it inside this region?
1111                 if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y)
1112                 {
1113                         // we've found the clicked line
1114                         txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text;
1115                         startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0;
1116                         break;
1117                 }
1118         }
1119
1120         if (x < CurrentTextRect.UpperLeftCorner.X)
1121                 x = CurrentTextRect.UpperLeftCorner.X;
1122
1123         s32 idx = font->getCharacterFromPos(Text.c_str(), x - CurrentTextRect.UpperLeftCorner.X);
1124
1125         // click was on or left of the line
1126         if (idx != -1)
1127                 return idx + startPos;
1128
1129         // click was off the right edge of the line, go to end.
1130         return txtLine->size() + startPos;
1131 }
1132
1133
1134 //! Breaks the single text line.
1135 void intlGUIEditBox::breakText()
1136 {
1137         IGUISkin* skin = Environment->getSkin();
1138
1139         if ((!WordWrap && !MultiLine) || !skin)
1140                 return;
1141
1142         BrokenText.clear(); // need to reallocate :/
1143         BrokenTextPositions.set_used(0);
1144
1145         IGUIFont* font = OverrideFont;
1146         if (!OverrideFont)
1147                 font = skin->getFont();
1148
1149         if (!font)
1150                 return;
1151
1152         LastBreakFont = font;
1153
1154         core::stringw line;
1155         core::stringw word;
1156         core::stringw whitespace;
1157         s32 lastLineStart = 0;
1158         s32 size = Text.size();
1159         s32 length = 0;
1160         s32 elWidth = RelativeRect.getWidth() - 6;
1161         wchar_t c;
1162
1163         for (s32 i=0; i<size; ++i)
1164         {
1165                 c = Text[i];
1166                 bool lineBreak = false;
1167
1168                 if (c == L'\r') // Mac or Windows breaks
1169                 {
1170                         lineBreak = true;
1171                         c = ' ';
1172                         if (Text[i+1] == L'\n') // Windows breaks
1173                         {
1174                                 Text.erase(i+1);
1175                                 --size;
1176                         }
1177                 }
1178                 else if (c == L'\n') // Unix breaks
1179                 {
1180                         lineBreak = true;
1181                         c = ' ';
1182                 }
1183
1184                 // don't break if we're not a multi-line edit box
1185                 if (!MultiLine)
1186                         lineBreak = false;
1187
1188                 if (c == L' ' || c == 0 || i == (size-1))
1189                 {
1190                         if (word.size())
1191                         {
1192                                 // here comes the next whitespace, look if
1193                                 // we can break the last word to the next line.
1194                                 s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
1195                                 s32 worldlgth = font->getDimension(word.c_str()).Width;
1196
1197                                 if (WordWrap && length + worldlgth + whitelgth > elWidth)
1198                                 {
1199                                         // break to next line
1200                                         length = worldlgth;
1201                                         BrokenText.push_back(line);
1202                                         BrokenTextPositions.push_back(lastLineStart);
1203                                         lastLineStart = i - (s32)word.size();
1204                                         line = word;
1205                                 }
1206                                 else
1207                                 {
1208                                         // add word to line
1209                                         line += whitespace;
1210                                         line += word;
1211                                         length += whitelgth + worldlgth;
1212                                 }
1213
1214                                 word = L"";
1215                                 whitespace = L"";
1216                         }
1217
1218                         whitespace += c;
1219
1220                         // compute line break
1221                         if (lineBreak)
1222                         {
1223                                 line += whitespace;
1224                                 line += word;
1225                                 BrokenText.push_back(line);
1226                                 BrokenTextPositions.push_back(lastLineStart);
1227                                 lastLineStart = i+1;
1228                                 line = L"";
1229                                 word = L"";
1230                                 whitespace = L"";
1231                                 length = 0;
1232                         }
1233                 }
1234                 else
1235                 {
1236                         // yippee this is a word..
1237                         word += c;
1238                 }
1239         }
1240
1241         line += whitespace;
1242         line += word;
1243         BrokenText.push_back(line);
1244         BrokenTextPositions.push_back(lastLineStart);
1245 }
1246
1247
1248 void intlGUIEditBox::setTextRect(s32 line)
1249 {
1250         core::dimension2du d;
1251
1252         IGUISkin* skin = Environment->getSkin();
1253         if (!skin)
1254                 return;
1255
1256         IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
1257
1258         if (!font)
1259                 return;
1260
1261         // get text dimension
1262         const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
1263         if (WordWrap || MultiLine)
1264         {
1265                 d = font->getDimension(BrokenText[line].c_str());
1266         }
1267         else
1268         {
1269                 d = font->getDimension(Text.c_str());
1270                 d.Height = AbsoluteRect.getHeight();
1271         }
1272         d.Height += font->getKerningHeight();
1273
1274         // justification
1275         switch (HAlign)
1276         {
1277         case EGUIA_CENTER:
1278                 // align to h centre
1279                 CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2);
1280                 CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2);
1281                 break;
1282         case EGUIA_LOWERRIGHT:
1283                 // align to right edge
1284                 CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width;
1285                 CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth();
1286                 break;
1287         default:
1288                 // align to left edge
1289                 CurrentTextRect.UpperLeftCorner.X = 0;
1290                 CurrentTextRect.LowerRightCorner.X = d.Width;
1291
1292         }
1293
1294         switch (VAlign)
1295         {
1296         case EGUIA_CENTER:
1297                 // align to v centre
1298                 CurrentTextRect.UpperLeftCorner.Y =
1299                         (FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line;
1300                 break;
1301         case EGUIA_LOWERRIGHT:
1302                 // align to bottom edge
1303                 CurrentTextRect.UpperLeftCorner.Y =
1304                         FrameRect.getHeight() - lineCount*d.Height + d.Height*line;
1305                 break;
1306         default:
1307                 // align to top edge
1308                 CurrentTextRect.UpperLeftCorner.Y = d.Height*line;
1309                 break;
1310         }
1311
1312         CurrentTextRect.UpperLeftCorner.X  -= HScrollPos;
1313         CurrentTextRect.LowerRightCorner.X -= HScrollPos;
1314         CurrentTextRect.UpperLeftCorner.Y  -= VScrollPos;
1315         CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height;
1316
1317         CurrentTextRect += FrameRect.UpperLeftCorner;
1318
1319 }
1320
1321
1322 s32 intlGUIEditBox::getLineFromPos(s32 pos)
1323 {
1324         if (!WordWrap && !MultiLine)
1325                 return 0;
1326
1327         s32 i=0;
1328         while (i < (s32)BrokenTextPositions.size())
1329         {
1330                 if (BrokenTextPositions[i] > pos)
1331                         return i-1;
1332                 ++i;
1333         }
1334         return (s32)BrokenTextPositions.size() - 1;
1335 }
1336
1337
1338 void intlGUIEditBox::inputChar(wchar_t c)
1339 {
1340         if (!IsEnabled)
1341                 return;
1342
1343         if (c != 0)
1344         {
1345                 if (Text.size() < Max || Max == 0)
1346                 {
1347                         core::stringw s;
1348
1349                         if (MarkBegin != MarkEnd)
1350                         {
1351                                 // replace marked text
1352                                 const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
1353                                 const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
1354
1355                                 s = Text.subString(0, realmbgn);
1356                                 s.append(c);
1357                                 s.append( Text.subString(realmend, Text.size()-realmend) );
1358                                 Text = s;
1359                                 CursorPos = realmbgn+1;
1360                         }
1361                         else
1362                         {
1363                                 // add new character
1364                                 s = Text.subString(0, CursorPos);
1365                                 s.append(c);
1366                                 s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
1367                                 Text = s;
1368                                 ++CursorPos;
1369                         }
1370
1371                         BlinkStartTime = porting::getTimeMs();
1372                         setTextMarkers(0, 0);
1373                 }
1374         }
1375         breakText();
1376         sendGuiEvent(EGET_EDITBOX_CHANGED);
1377         calculateScrollPos();
1378 }
1379
1380
1381 void intlGUIEditBox::calculateScrollPos()
1382 {
1383         if (!AutoScroll)
1384                 return;
1385
1386         // calculate horizontal scroll position
1387         s32 cursLine = getLineFromPos(CursorPos);
1388         setTextRect(cursLine);
1389
1390         // don't do horizontal scrolling when wordwrap is enabled.
1391         if (!WordWrap)
1392         {
1393                 // get cursor position
1394                 IGUISkin* skin = Environment->getSkin();
1395                 if (!skin)
1396                         return;
1397                 IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
1398                 if (!font)
1399                         return;
1400
1401                 core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text;
1402                 s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos;
1403
1404                 s32 cStart = CurrentTextRect.UpperLeftCorner.X + HScrollPos +
1405                         font->getDimension(txtLine->subString(0, cPos).c_str()).Width;
1406
1407                 s32 cEnd = cStart + font->getDimension(L"_ ").Width;
1408
1409                 if (FrameRect.LowerRightCorner.X < cEnd)
1410                         HScrollPos = cEnd - FrameRect.LowerRightCorner.X;
1411                 else if (FrameRect.UpperLeftCorner.X > cStart)
1412                         HScrollPos = cStart - FrameRect.UpperLeftCorner.X;
1413                 else
1414                         HScrollPos = 0;
1415
1416                 // todo: adjust scrollbar
1417         }
1418
1419         // vertical scroll position
1420         if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y + VScrollPos)
1421                 VScrollPos = CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y + VScrollPos;
1422
1423         else if (FrameRect.UpperLeftCorner.Y > CurrentTextRect.UpperLeftCorner.Y + VScrollPos)
1424                 VScrollPos = CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y + VScrollPos;
1425         else
1426                 VScrollPos = 0;
1427
1428         // todo: adjust scrollbar
1429 }
1430
1431 //! set text markers
1432 void intlGUIEditBox::setTextMarkers(s32 begin, s32 end)
1433 {
1434     if ( begin != MarkBegin || end != MarkEnd )
1435     {
1436         MarkBegin = begin;
1437         MarkEnd = end;
1438         sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
1439     }
1440 }
1441
1442 //! send some gui event to parent
1443 void intlGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
1444 {
1445         if ( Parent )
1446         {
1447         SEvent e;
1448         e.EventType = EET_GUI_EVENT;
1449         e.GUIEvent.Caller = this;
1450         e.GUIEvent.Element = 0;
1451         e.GUIEvent.EventType = type;
1452
1453         Parent->OnEvent(e);
1454         }
1455 }
1456
1457 //! Writes attributes of the element.
1458 void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
1459 {
1460         // IGUIEditBox::serializeAttributes(out,options);
1461
1462         out->addBool  ("OverrideColorEnabled",OverrideColorEnabled );
1463         out->addColor ("OverrideColor",       OverrideColor);
1464         // out->addFont("OverrideFont",OverrideFont);
1465         out->addInt   ("MaxChars",            Max);
1466         out->addBool  ("WordWrap",            WordWrap);
1467         out->addBool  ("MultiLine",           MultiLine);
1468         out->addBool  ("AutoScroll",          AutoScroll);
1469         out->addBool  ("PasswordBox",         PasswordBox);
1470         core::stringw ch = L" ";
1471         ch[0] = PasswordChar;
1472         out->addString("PasswordChar",        ch.c_str());
1473         out->addEnum  ("HTextAlign",          HAlign, GUIAlignmentNames);
1474         out->addEnum  ("VTextAlign",          VAlign, GUIAlignmentNames);
1475
1476         IGUIEditBox::serializeAttributes(out,options);
1477 }
1478
1479
1480 //! Reads attributes of the element
1481 void intlGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
1482 {
1483         IGUIEditBox::deserializeAttributes(in,options);
1484
1485         setOverrideColor(in->getAttributeAsColor("OverrideColor"));
1486         enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
1487         setMax(in->getAttributeAsInt("MaxChars"));
1488         setWordWrap(in->getAttributeAsBool("WordWrap"));
1489         setMultiLine(in->getAttributeAsBool("MultiLine"));
1490         setAutoScroll(in->getAttributeAsBool("AutoScroll"));
1491         core::stringw ch = in->getAttributeAsStringW("PasswordChar");
1492
1493         if (!ch.size())
1494                 setPasswordBox(in->getAttributeAsBool("PasswordBox"));
1495         else
1496                 setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]);
1497
1498         setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
1499                         (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
1500
1501         // setOverrideFont(in->getAttributeAsFont("OverrideFont"));
1502 }
1503
1504
1505 } // end namespace gui
1506 } // end namespace irr
1507
1508 #endif // _IRR_COMPILE_WITH_GUI_