1 /* bzflag
2  * Copyright (c) 1993-2021 Tim Riker
3  *
4  * This package is free software;  you can redistribute it and/or
5  * modify it under the terms of the license found in the file
6  * named COPYING that should have accompanied this file.
7  *
8  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11  */
12 
13 // interface headers
14 #include "HUDuiTypeIn.h"
15 
16 // system implementation headers
17 #include <ctype.h>
18 
19 // common implementation headers
20 #include "FontManager.h"
21 
22 // local implementation headers
23 #include "HUDui.h"
24 
25 //
26 // HUDuiTypeIn
27 //
28 
HUDuiTypeIn()29 HUDuiTypeIn::HUDuiTypeIn()
30     : HUDuiControl()
31     , maxLength(0)
32     , cursorPos(0)
33     , allowEdit(true)
34     , obfuscate(false)
35     , colorFunc(NULL)
36 {
37 }
38 
~HUDuiTypeIn()39 HUDuiTypeIn::~HUDuiTypeIn()
40 {
41 }
42 
setObfuscation(bool on)43 void            HUDuiTypeIn::setObfuscation(bool on)
44 {
45     obfuscate = on;
46 }
47 
getMaxLength() const48 int         HUDuiTypeIn::getMaxLength() const
49 {
50     return maxLength;
51 }
52 
getString() const53 std::string     HUDuiTypeIn::getString() const
54 {
55     return string;
56 }
57 
setMaxLength(int _maxLength)58 void            HUDuiTypeIn::setMaxLength(int _maxLength)
59 {
60     maxLength = _maxLength;
61     string = string.substr(0, maxLength);
62     if (cursorPos > maxLength)
63         cursorPos = maxLength;
64     onSetFont();
65 }
66 
setString(const std::string & _string)67 void            HUDuiTypeIn::setString(const std::string& _string)
68 {
69     string = _string;
70     cursorPos = string.length();
71     onSetFont();
72 }
73 
74 // allows composing, otherwise not
setEditing(bool _allowEdit)75 void            HUDuiTypeIn::setEditing(bool _allowEdit)
76 {
77     allowEdit = _allowEdit;
78 }
79 
doKeyPress(const BzfKeyEvent & key)80 bool            HUDuiTypeIn::doKeyPress(const BzfKeyEvent& key)
81 {
82     static const char backspace = '\b';   // ^H
83     static const char whitespace = ' ';
84 
85     if (!allowEdit) return false; //or return true ??
86     char c = key.ascii;
87     if (c == 0)
88     {
89         switch (key.button)
90         {
91         case BzfKeyEvent::Up:
92             HUDui::setFocus(getPrev());
93             return true;
94 
95         case BzfKeyEvent::Down:
96             HUDui::setFocus(getNext());
97             return true;
98 
99         case BzfKeyEvent::Left:
100             if (cursorPos > 0)
101                 cursorPos--;
102             return true;
103 
104         case BzfKeyEvent::Right:
105             if (cursorPos < (int)string.length())
106                 cursorPos++;
107             return true;
108 
109         case BzfKeyEvent::Home:
110             cursorPos = 0;
111             return true;
112 
113         case BzfKeyEvent::End:
114             cursorPos = string.length();
115             return true;
116 
117         case BzfKeyEvent::Backspace:
118             c = backspace;
119             break;
120 
121         case BzfKeyEvent::Delete:
122             if (cursorPos < (int)string.length())
123             {
124                 cursorPos++;
125                 c = backspace;
126             }
127             else
128                 return true;
129             break;
130 
131         default:
132             return false;
133         }
134     }
135 
136     if (c == '\t')
137     {
138         HUDui::setFocus(getNext());
139         return true;
140     }
141     if (c >0 && (!isprint(c) && c != backspace))
142         return false;
143 
144     if (c == backspace)
145     {
146         if (cursorPos == 0)
147             return true;
148 
149         cursorPos--;
150         string = string.substr(0, cursorPos) + string.substr(cursorPos + 1, string.length() - cursorPos + 1);
151         onSetFont();
152     }
153     else if (c > 0)
154     {
155         if (isspace(c))
156             c = whitespace;
157         if ((int)string.length() == maxLength)
158             return true;
159 
160         string = string.substr(0, cursorPos) + c + string.substr( cursorPos, string.length() - cursorPos);
161         cursorPos++;
162         onSetFont();
163     }
164     return true;
165 }
166 
doKeyRelease(const BzfKeyEvent & key)167 bool            HUDuiTypeIn::doKeyRelease(const BzfKeyEvent& key)
168 {
169     if (key.ascii == '\t' || !isprint(key.ascii)) // ignore non-printing and tab
170         return false;
171 
172     // slurp up releases
173     return true;
174 }
175 
doRender()176 void            HUDuiTypeIn::doRender()
177 {
178     if (getFontFace() < 0) return;
179 
180     // render string
181     glColor3fv(hasFocus() ? textColor : dimTextColor);
182 
183     FontManager &fm = FontManager::instance();
184     std::string renderStr;
185     if (obfuscate)
186         renderStr.append(string.size(), '*');
187     else
188         renderStr = string;
189     if (colorFunc)
190         renderStr = colorFunc(renderStr);
191     fm.drawString(getX(), getY(), 0, getFontFace(), getFontSize(), renderStr);
192 
193     // find the position of where to draw the input cursor
194     const std::string noAnsi = stripAnsiCodes(renderStr);
195     float start = fm.getStrLength(getFontFace(), getFontSize(), noAnsi.substr(0, cursorPos));
196 
197     if (HUDui::getFocus() == this && allowEdit)
198         fm.drawString(getX() + start, getY(), 0, getFontFace(), getFontSize(), "_");
199 }
200 
201 // Local Variables: ***
202 // mode: C++ ***
203 // tab-width: 4 ***
204 // c-basic-offset: 4 ***
205 // indent-tabs-mode: nil ***
206 // End: ***
207 // ex: shiftwidth=4 tabstop=4
208