1
//============================================================================
5
// SS tttttt eeee ll ll aaaa
6
// SSSS tt ee ee ll ll aa
7
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8
// SS SS tt ee ll ll aa aa
9
// SSSS ttt eeeee llll llll aaaaa
11
// Copyright (c) 1995-2005 by Bradford W. Mott and the Stella team
13
// See the file "license" for information on usage and redistribution of
14
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
// $Id: EditableWidget.cxx,v 1.17 2006/03/25 00:34:17 stephena Exp $
18
// Based on code from ScummVM - Scumm Interpreter
19
// Copyright (C) 2002-2004 The ScummVM project
20
//============================================================================
22
#include "EditableWidget.hxx"
25
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
26
EditableWidget::EditableWidget(GuiObject* boss, const GUI::Font& font,
27
int x, int y, int w, int h)
28
: Widget(boss, font, x, y, w, h),
32
_caretVisible = false;
34
_caretPos = 0; // FIXME
36
_caretInverse = false;
38
_editScrollOffset = 0;
41
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
42
EditableWidget::~EditableWidget()
46
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47
void EditableWidget::setEditString(const string& str)
49
// TODO: We probably should filter the input string here,
50
// e.g. using tryInsertChar.
52
_caretPos = _editString.size();
54
_editScrollOffset = (_font->getStringWidth(_editString) - (getEditRect().width()));
55
if (_editScrollOffset < 0)
56
_editScrollOffset = 0;
58
// Make sure the new string is seen onscreen
62
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
63
bool EditableWidget::tryInsertChar(char c, int pos)
67
_editString.insert(pos, 1, c);
73
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
74
bool EditableWidget::handleKeyDown(int ascii, int keycode, int modifiers)
79
// Ignore all alt-mod keys
80
if(instance()->eventHandler().kbdAlt(modifiers))
88
case '\n': // enter/return
90
// confirm edit and exit editmode
92
sendCommand(kEditAcceptCmd, 0, _id);
98
sendCommand(kEditCancelCmd, 0, _id);
103
dirty = killChar(-1);
107
dirty = killChar(+1);
110
case 256 + 20: // left arrow
112
dirty = setCaretPos(_caretPos - 1);
115
case 256 + 19: // right arrow
116
if (_caretPos < (int)_editString.size())
117
dirty = setCaretPos(_caretPos + 1);
120
case 256 + 22: // home
121
dirty = setCaretPos(0);
124
case 256 + 23: // end
125
dirty = setCaretPos(_editString.size());
129
if (instance()->eventHandler().kbdControl(modifiers))
131
dirty = specialKeys(keycode);
133
else if (tryInsertChar((char)ascii, _caretPos))
136
sendCommand(kEditChangedCmd, ascii, _id);
151
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
152
int EditableWidget::getCaretOffset() const
155
for (int i = 0; i < _caretPos; i++)
156
caretpos += _font->getCharWidth(_editString[i]);
158
caretpos -= _editScrollOffset;
163
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
164
void EditableWidget::drawCaret()
166
//cerr << "EditableWidget::drawCaret()\n";
167
// Only draw if item is visible
168
if (!_editable || !isVisible() || !_boss->isVisible() || !_hasFocus)
171
GUI::Rect editRect = getEditRect();
173
int color = kTextColorHi;
174
int x = editRect.left;
175
int y = editRect.top;
177
x += getCaretOffset();
182
FrameBuffer& fb = _boss->instance()->frameBuffer();
183
fb.vLine(x, y+2, y + editRect.height() - 2, color);
186
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187
bool EditableWidget::setCaretPos(int newPos)
189
assert(newPos >= 0 && newPos <= (int)_editString.size());
192
return adjustOffset();
195
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
196
bool EditableWidget::adjustOffset()
198
// check if the caret is still within the textbox; if it isn't,
199
// adjust _editScrollOffset
201
// For some reason (differences in ScummVM event handling??),
202
// this method should always return true.
204
int caretpos = getCaretOffset();
205
const int editWidth = getEditRect().width();
210
_editScrollOffset += caretpos;
212
else if (caretpos >= editWidth)
215
_editScrollOffset -= (editWidth - caretpos);
217
else if (_editScrollOffset > 0)
219
const int strWidth = _font->getStringWidth(_editString);
220
if (strWidth - _editScrollOffset < editWidth)
223
_editScrollOffset = (strWidth - editWidth);
224
if (_editScrollOffset < 0)
225
_editScrollOffset = 0;
232
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
233
bool EditableWidget::specialKeys(int keycode)
244
setCaretPos(_editString.size());
248
handled = killChar(+1);
252
handled = killLine(+1);
256
handled = killLine(-1);
260
handled = killLastWord();
270
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
271
bool EditableWidget::killChar(int direction)
273
bool handled = false;
275
if(direction == -1) // Delete previous character (backspace)
280
_editString.erase(_caretPos, 1);
284
else if(direction == 1) // Delete next character (delete)
286
_editString.erase(_caretPos, 1);
293
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
294
bool EditableWidget::killLine(int direction)
296
bool handled = false;
298
if(direction == -1) // erase from current position to beginning of line
300
int count = _caretPos;
303
for (int i = 0; i < count; i++)
309
else if(direction == 1) // erase from current position to end of line
311
int count = _editString.size() - _caretPos;
314
for (int i = 0; i < count; i++)
324
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
325
bool EditableWidget::killLastWord()
327
bool handled = false;
328
int count = 0, currentPos = _caretPos;
330
while (currentPos > 0)
332
if (_editString[currentPos - 1] == ' ')
346
for (int i = 0; i < count; i++)