1 #include "platform/sdl/platform.hpp"
4 #define MAXHISTORY 1000
8 volatile uint32_t autorepeat_first
= 10;
9 volatile uint32_t autorepeat_subsequent
= 4;
11 bool is_whitespace(uint32_t cp
)
40 commandline_model::commandline_model() throw()
43 autorepeating_key
= SPECIAL_NOOP
;
46 overwrite_mode
= false;
49 std::string
commandline_model::key(uint32_t k
) throw(std::bad_alloc
)
56 history_itr
= history
.end();
57 history
.push_back(codepoints
);
58 if(history
.size() > MAXHISTORY
)
71 //Set up autorepeat if needed.
72 if(k
& PRESSED_MASK
) {
73 autorepeating_key
= k
;
74 autorepeat_counter
= 0;
77 //These all are active on positive edge.
78 autorepeating_key
= SPECIAL_NOOP
;
79 autorepeat_counter
= 0;
84 switch(k
& ~PRESSED_MASK
) {
86 overwrite_mode
= !overwrite_mode
;
91 cursor_pos
= codepoints
.size();
99 scroll_history_down();
106 if(cursor_pos
< codepoints
.size())
109 case SPECIAL_BACKSPACE
:
113 delete_codepoint(cursor_pos
- 1);
117 if(cursor_pos
== codepoints
.size())
120 delete_codepoint(cursor_pos
);
122 case SPECIAL_LEFT_WORD
:
123 while(cursor_pos
> 0 && (cursor_pos
== codepoints
.size() || isspace(codepoints
[cursor_pos
])))
125 while(cursor_pos
> 0 && (cursor_pos
== codepoints
.size() || !isspace(codepoints
[cursor_pos
])))
127 //If the previous position is whitespace, back off to it.
128 while(cursor_pos
> 0 && isspace(codepoints
[cursor_pos
- 1]))
131 case SPECIAL_RIGHT_WORD
:
132 while(cursor_pos
< codepoints
.size() && isspace(codepoints
[cursor_pos
]))
134 while(cursor_pos
< codepoints
.size() && !isspace(codepoints
[cursor_pos
]))
137 case SPECIAL_DELETE_WORD
:
138 while(cursor_pos
> 0 && !isspace(codepoints
[cursor_pos
- 1])) {
139 delete_codepoint(cursor_pos
- 1);
142 while(cursor_pos
> 0 && isspace(codepoints
[cursor_pos
- 1])) {
143 delete_codepoint(cursor_pos
- 1);
152 //This can't be NOOP, ACK nor NAK because those were checked above, nor is it special. Therefore
155 if(!overwrite_mode
|| cursor_pos
== codepoints
.size()) {
156 codepoints
.resize(codepoints
.size() + 1);
157 for(size_t i
= codepoints
.size() - 1; i
> cursor_pos
; i
--)
158 codepoints
[i
] = codepoints
[i
- 1];
160 codepoints
[cursor_pos
++] = k
& ~PRESSED_MASK
;
165 void commandline_model::tick() throw(std::bad_alloc
)
167 if(autorepeat_phase
== 0 || !enabled_flag
)
169 if(autorepeat_phase
== 1) {
170 autorepeat_counter
++;
171 if(autorepeat_counter
>= autorepeat_first
) {
172 key(autorepeating_key
);
173 autorepeat_phase
= 2;
174 autorepeat_counter
= 0;
177 if(autorepeat_phase
== 2) {
178 autorepeat_counter
++;
179 if(autorepeat_counter
>= autorepeat_subsequent
) {
180 key(autorepeating_key
);
181 autorepeat_counter
= 0;
186 size_t commandline_model::cursor() throw()
188 return enabled_flag
? cursor_pos
: 0;
191 bool commandline_model::enabled() throw()
196 bool commandline_model::overwriting() throw()
198 return overwrite_mode
;
201 void commandline_model::enable(const std::string
& cmd
) throw()
206 for(size_t itr
= 0; itr
< cmd
.length(); itr
++) {
207 unsigned char ch
= cmd
[itr
];
209 codepoints
.push_back(ch
);
212 tmp
= tmp
* 64 + (ch
& 0x3F);
214 codepoints
.push_back(tmp
);
215 } else if(ch
< 192) {
216 } else if(ch
< 224) {
219 } else if(ch
< 240) {
222 } else if(ch
< 248) {
227 cursor_pos
= codepoints
.size();
230 void commandline_model::enable() throw()
235 autorepeat_phase
= 0;
236 autorepeat_counter
= 0;
239 overwrite_mode
= false;
240 history_itr
= history
.end();
243 std::string
commandline_model::read_command() throw(std::bad_alloc
)
245 std::ostringstream o
;
246 for(auto i
: codepoints
) {
247 char buf
[5] = {0, 0, 0, 0, 0};
251 buf
[0] = 0xC0 | (i
>> 6);
252 buf
[1] = 0x80 | (i
& 63);
253 } else if(i
< 0x10000) {
254 buf
[0] = 0xE0 | (i
>> 12);
255 buf
[1] = 0x80 | ((i
>> 6) & 63);
256 buf
[2] = 0x80 | (i
& 63);
257 } else if(i
< 0x10FFFF) {
258 buf
[0] = 0xF0 | (i
>> 18);
259 buf
[1] = 0x80 | ((i
>> 12) & 63);
260 buf
[2] = 0x80 | ((i
>> 6) & 63);
261 buf
[3] = 0x80 | (i
& 63);
268 void commandline_model::handle_cow()
270 if(history_itr
== history
.end())
271 //Latched to end of history.
273 codepoints
= *history_itr
;
274 history_itr
= history
.end();
277 void commandline_model::scroll_history_up()
279 if(history_itr
== history
.end())
280 //Save the current commandline.
281 saved_codepoints
= codepoints
;
282 if(history_itr
== history
.begin())
286 codepoints
= *history_itr
;
287 if(cursor_pos
> codepoints
.size())
288 cursor_pos
= codepoints
.size();
291 void commandline_model::scroll_history_down()
293 if(history_itr
== history
.end())
297 if(history_itr
== history
.end())
298 codepoints
= saved_codepoints
;
300 codepoints
= *history_itr
;
301 if(cursor_pos
> codepoints
.size())
302 cursor_pos
= codepoints
.size();
305 void commandline_model::delete_codepoint(size_t idx
)
308 for(size_t i
= idx
; i
< codepoints
.size() - 1; i
++)
309 codepoints
[i
] = codepoints
[i
+ 1];
310 codepoints
.resize(codepoints
.size() - 1);
313 void commandline_model::paint(SDL_Surface
* surf
, uint32_t x
, uint32_t y
, uint32_t maxwidth
, uint32_t color
,
314 bool box
, uint32_t boxcolor
) throw()
320 draw_box(surf
, x
, y
, maxwidth
, 16, boxcolor
);
322 draw_string(surf
, read_command(), x
, y
, maxwidth
, color
, overwrite_mode
? 2 : 1, cursor_pos
);
324 draw_string(surf
, "", x
, y
, maxwidth
, color
, 0, 0);