Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2006-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MFXTextFieldIcon.cpp
15 : /// @author Pablo Alvarez Lopez
16 : /// @date Aug 2023
17 : ///
18 : //
19 : /****************************************************************************/
20 :
21 : #include <utils/common/StdDefs.h>
22 : #include <utils/gui/div/GUIDesigns.h>
23 :
24 : #include <fxkeys.h>
25 : #ifdef _MSC_VER
26 : #pragma warning(push)
27 : #pragma warning(disable: 4266) // mask warning about hidden member function FX::FXTextCodec::utf2mblen
28 : #endif
29 : #include <FX88591Codec.h>
30 : #include <FXUTF16Codec.h>
31 : #ifdef _MSC_VER
32 : #pragma warning(pop)
33 : #endif
34 :
35 : #include "MFXStaticToolTip.h"
36 : #include "MFXTextFieldIcon.h"
37 :
38 : // ===========================================================================
39 : // Macros
40 : // ===========================================================================
41 :
42 : #define JUSTIFY_MASK (JUSTIFY_HZ_APART|JUSTIFY_VT_APART)
43 : #define TEXTFIELD_MASK (TEXTFIELD_PASSWD|TEXTFIELD_INTEGER|TEXTFIELD_REAL|TEXTFIELD_READONLY|TEXTFIELD_ENTER_ONLY|TEXTFIELD_LIMITED|TEXTFIELD_OVERSTRIKE|TEXTFIELD_AUTOHIDE|TEXTFIELD_AUTOGRAY)
44 : #define ICON_SPACING 4 // Spacing between myIcon and label (2 + 2)
45 : #define ICON_SIZE 16
46 :
47 : // ===========================================================================
48 : // FOX callback mapping
49 : // ===========================================================================
50 :
51 : // Map
52 : FXDEFMAP(MFXTextFieldIcon) MFXTextFieldIconMap[] = {
53 : FXMAPFUNC(SEL_CLIPBOARD_GAINED, 0, MFXTextFieldIcon::onClipboardGained),
54 : FXMAPFUNC(SEL_CLIPBOARD_LOST, 0, MFXTextFieldIcon::onClipboardLost),
55 : FXMAPFUNC(SEL_CLIPBOARD_REQUEST, 0, MFXTextFieldIcon::onClipboardRequest),
56 : FXMAPFUNC(SEL_ENTER, 0, MFXTextFieldIcon::onEnter),
57 : FXMAPFUNC(SEL_FOCUS_SELF, 0, MFXTextFieldIcon::onFocusSelf),
58 : FXMAPFUNC(SEL_FOCUSIN, 0, MFXTextFieldIcon::onFocusIn),
59 : FXMAPFUNC(SEL_FOCUSOUT, 0, MFXTextFieldIcon::onFocusOut),
60 : FXMAPFUNC(SEL_KEYPRESS, 0, MFXTextFieldIcon::onKeyPress),
61 : FXMAPFUNC(SEL_KEYRELEASE, 0, MFXTextFieldIcon::onKeyRelease),
62 : FXMAPFUNC(SEL_LEAVE, 0, MFXTextFieldIcon::onLeave),
63 : FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, MFXTextFieldIcon::onLeftBtnPress),
64 : FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, MFXTextFieldIcon::onLeftBtnRelease),
65 : FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, 0, MFXTextFieldIcon::onMiddleBtnPress),
66 : FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, 0, MFXTextFieldIcon::onMiddleBtnRelease),
67 : FXMAPFUNC(SEL_MOTION, 0, MFXTextFieldIcon::onMotion),
68 : FXMAPFUNC(SEL_PAINT, 0, MFXTextFieldIcon::onPaint),
69 : FXMAPFUNC(SEL_QUERY_HELP, 0, MFXTextFieldIcon::onQueryHelp),
70 : FXMAPFUNC(SEL_QUERY_TIP, 0, MFXTextFieldIcon::onQueryTip),
71 : FXMAPFUNC(SEL_SELECTION_GAINED, 0, MFXTextFieldIcon::onSelectionGained),
72 : FXMAPFUNC(SEL_SELECTION_LOST, 0, MFXTextFieldIcon::onSelectionLost),
73 : FXMAPFUNC(SEL_SELECTION_REQUEST, 0, MFXTextFieldIcon::onSelectionRequest),
74 : FXMAPFUNC(SEL_UPDATE, 0, MFXTextFieldIcon::onUpdate),
75 : FXMAPFUNC(SEL_VERIFY, 0, MFXTextFieldIcon::onVerify),
76 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_BACKSPACE, MFXTextFieldIcon::onCmdBackspace),
77 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_COPY_SEL, MFXTextFieldIcon::onCmdCopySel),
78 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_END, MFXTextFieldIcon::onCmdCursorEnd),
79 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_HOME, MFXTextFieldIcon::onCmdCursorHome),
80 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_LEFT, MFXTextFieldIcon::onCmdCursorLeft),
81 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_RIGHT, MFXTextFieldIcon::onCmdCursorRight),
82 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_END, MFXTextFieldIcon::onCmdCursorWordEnd),
83 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_LEFT, MFXTextFieldIcon::onCmdCursorWordLeft),
84 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_RIGHT, MFXTextFieldIcon::onCmdCursorWordRight),
85 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_START, MFXTextFieldIcon::onCmdCursorWordStart),
86 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CUT_SEL, MFXTextFieldIcon::onCmdCutSel),
87 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DELETE, MFXTextFieldIcon::onCmdDelete),
88 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DELETE_ALL, MFXTextFieldIcon::onCmdDeleteAll),
89 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DELETE_SEL, MFXTextFieldIcon::onCmdDeleteSel),
90 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DESELECT_ALL, MFXTextFieldIcon::onCmdDeselectAll),
91 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_EXTEND, MFXTextFieldIcon::onCmdExtend),
92 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETHELPSTRING, MFXTextFieldIcon::onCmdGetHelp),
93 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETINTVALUE, MFXTextFieldIcon::onCmdGetIntValue),
94 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETREALVALUE, MFXTextFieldIcon::onCmdGetRealValue),
95 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETSTRINGVALUE, MFXTextFieldIcon::onCmdGetStringValue),
96 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETTIPSTRING, MFXTextFieldIcon::onCmdGetTip),
97 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_INSERT_STRING, MFXTextFieldIcon::onCmdInsertString),
98 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_MARK, MFXTextFieldIcon::onCmdMark),
99 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_OVERST_STRING, MFXTextFieldIcon::onCmdOverstString),
100 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_PASTE_MIDDLE, MFXTextFieldIcon::onCmdPasteMiddle),
101 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_PASTE_SEL, MFXTextFieldIcon::onCmdPasteSel),
102 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SELECT_ALL, MFXTextFieldIcon::onCmdSelectAll),
103 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETHELPSTRING, MFXTextFieldIcon::onCmdSetHelp),
104 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETINTVALUE, MFXTextFieldIcon::onCmdSetIntValue),
105 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETREALVALUE, MFXTextFieldIcon::onCmdSetRealValue),
106 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETSTRINGVALUE, MFXTextFieldIcon::onCmdSetStringValue),
107 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETTIPSTRING, MFXTextFieldIcon::onCmdSetTip),
108 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETVALUE, MFXTextFieldIcon::onCmdSetValue),
109 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_TOGGLE_EDITABLE, MFXTextFieldIcon::onCmdToggleEditable),
110 : FXMAPFUNC(SEL_COMMAND, FXTextField::ID_TOGGLE_OVERSTRIKE, MFXTextFieldIcon::onCmdToggleOverstrike),
111 : FXMAPFUNC(SEL_TIMEOUT, FXTextField::ID_AUTOSCROLL, MFXTextFieldIcon::onAutoScroll),
112 : FXMAPFUNC(SEL_TIMEOUT, FXTextField::ID_BLINK, MFXTextFieldIcon::onBlink),
113 : FXMAPFUNC(SEL_UPDATE, FXTextField::ID_COPY_SEL, MFXTextFieldIcon::onUpdHaveSelection),
114 : FXMAPFUNC(SEL_UPDATE, FXTextField::ID_CUT_SEL, MFXTextFieldIcon::onUpdHaveSelection),
115 : FXMAPFUNC(SEL_UPDATE, FXTextField::ID_DELETE_SEL, MFXTextFieldIcon::onUpdHaveSelection),
116 : FXMAPFUNC(SEL_UPDATE, FXTextField::ID_PASTE_SEL, MFXTextFieldIcon::onUpdYes),
117 : FXMAPFUNC(SEL_UPDATE, FXTextField::ID_SELECT_ALL, MFXTextFieldIcon::onUpdSelectAll),
118 : FXMAPFUNC(SEL_UPDATE, FXTextField::ID_TOGGLE_EDITABLE, MFXTextFieldIcon::onUpdToggleEditable),
119 : FXMAPFUNC(SEL_UPDATE, FXTextField::ID_TOGGLE_OVERSTRIKE, MFXTextFieldIcon::onUpdToggleOverstrike),
120 : };
121 :
122 : // Object implementation
123 329866 : FXIMPLEMENT(MFXTextFieldIcon, FXFrame, MFXTextFieldIconMap, ARRAYNUMBER(MFXTextFieldIconMap))
124 :
125 : // ===========================================================================
126 : // member method definitions
127 : // ===========================================================================
128 :
129 7548 : MFXTextFieldIcon::MFXTextFieldIcon(FXComposite* p, MFXStaticToolTip* staticToolTip, GUIIcon icon, FXObject* tgt, FXSelector sel,
130 7548 : FXuint opts, FXint x, FXint y, FXint w, FXint h, FXint pl, FXint pr, FXint pt, FXint pb) :
131 : FXFrame(p, opts, x, y, w, h, pl, pr, pt, pb),
132 7548 : myStaticToolTip(staticToolTip) {
133 : // set icon
134 7548 : if (icon != GUIIcon::EMPTY) {
135 0 : myIcon = GUIIconSubSys::getIcon(icon);
136 : }
137 7548 : flags |= FLAG_ENABLED;
138 7548 : target = tgt;
139 7548 : message = sel;
140 7548 : if (!(options & JUSTIFY_RIGHT)) {
141 7548 : options |= JUSTIFY_LEFT;
142 : }
143 7548 : defaultCursor = getApp()->getDefaultCursor(DEF_TEXT_CURSOR);
144 7548 : dragCursor = getApp()->getDefaultCursor(DEF_TEXT_CURSOR);
145 7548 : myFont = getApp()->getNormalFont();
146 7548 : backColor = getApp()->getBackColor();
147 7548 : myTextColor = getApp()->getForeColor();
148 7548 : mySelectedBackgroundColor = getApp()->getSelbackColor();
149 7548 : mySelectedTextColor = getApp()->getSelforeColor();
150 7548 : myCursorColor = getApp()->getForeColor();
151 7548 : myVisibleColumns = GUIDesignTextFieldNCol;
152 7548 : }
153 :
154 :
155 15062 : MFXTextFieldIcon::~MFXTextFieldIcon() {
156 7531 : getApp()->removeTimeout(this, FXTextField::ID_BLINK);
157 7531 : getApp()->removeTimeout(this, ID_AUTOSCROLL);
158 7531 : myFont = (FXFont*) - 1L;
159 15062 : }
160 :
161 :
162 : void
163 15095 : MFXTextFieldIcon::create() {
164 15095 : FXFrame::create();
165 15095 : if (!textType) {
166 0 : textType = getApp()->registerDragType(textTypeName);
167 : }
168 15095 : if (!utf8Type) {
169 0 : utf8Type = getApp()->registerDragType(utf8TypeName);
170 : }
171 15095 : if (!utf16Type) {
172 0 : utf16Type = getApp()->registerDragType(utf16TypeName);
173 : }
174 15095 : myFont->create();
175 15095 : }
176 :
177 :
178 : void
179 0 : MFXTextFieldIcon::setFont(FXFont* fnt) {
180 0 : if (!fnt) {
181 0 : fxerror("%s::setFont: NULL font specified.\n", getClassName());
182 : }
183 0 : if (myFont != fnt) {
184 0 : myFont = fnt;
185 0 : recalc();
186 0 : update();
187 : }
188 0 : }
189 :
190 :
191 : FXFont*
192 0 : MFXTextFieldIcon::getFont() const {
193 0 : return myFont;
194 : }
195 :
196 :
197 : void
198 0 : MFXTextFieldIcon::enable() {
199 0 : if (!(flags & FLAG_ENABLED)) {
200 0 : FXFrame::enable();
201 0 : update();
202 : }
203 0 : }
204 :
205 :
206 : void
207 0 : MFXTextFieldIcon::disable() {
208 0 : if (flags & FLAG_ENABLED) {
209 0 : FXFrame::disable();
210 0 : update();
211 : }
212 0 : }
213 :
214 :
215 : FXint
216 14836 : MFXTextFieldIcon::getDefaultWidth() {
217 14836 : return padleft + padright + (border << 1) + myVisibleColumns * myFont->getTextWidth("8", 1);
218 : }
219 :
220 :
221 :
222 : FXint
223 0 : MFXTextFieldIcon::getDefaultHeight() {
224 0 : return padtop + padbottom + (border << 1) + myFont->getFontHeight();
225 : }
226 :
227 :
228 : long
229 294710 : MFXTextFieldIcon::onUpdate(FXObject* sender, FXSelector sel, void* ptr) {
230 294710 : if (!FXFrame::onUpdate(sender, sel, ptr)) {
231 294710 : if (options & TEXTFIELD_AUTOHIDE) {
232 0 : if (shown()) {
233 0 : hide();
234 0 : recalc();
235 : }
236 : }
237 294710 : if (options & TEXTFIELD_AUTOGRAY) {
238 0 : disable();
239 : }
240 : }
241 294710 : return 1;
242 : }
243 :
244 :
245 : long
246 0 : MFXTextFieldIcon::onSelectionGained(FXObject* sender, FXSelector sel, void* ptr) {
247 0 : FXFrame::onSelectionGained(sender, sel, ptr);
248 0 : update();
249 0 : return 1;
250 : }
251 :
252 :
253 : long
254 0 : MFXTextFieldIcon::onSelectionLost(FXObject* sender, FXSelector sel, void* ptr) {
255 0 : FXFrame::onSelectionLost(sender, sel, ptr);
256 0 : update();
257 0 : return 1;
258 : }
259 :
260 :
261 : long
262 0 : MFXTextFieldIcon::onSelectionRequest(FXObject* sender, FXSelector sel, void* ptr) {
263 : FXEvent* event = (FXEvent*)ptr;
264 0 : FXString string;
265 : FXuint start;
266 : FXuint len;
267 :
268 : // Make sure
269 : FXASSERT(0 <= myAnchorPosition && myAnchorPosition <= contents.length());
270 : FXASSERT(0 <= myCursorPosition && myCursorPosition <= contents.length());
271 :
272 : // Perhaps the target wants to supply its own data for the selection
273 0 : if (FXFrame::onSelectionRequest(sender, sel, ptr)) {
274 : return 1;
275 : }
276 :
277 : // Recognize the request?
278 0 : if (event->target == stringType || event->target == textType || event->target == utf8Type || event->target == utf16Type) {
279 :
280 : // Figure selected bytes
281 0 : if (myAnchorPosition < myCursorPosition) {
282 0 : start = myAnchorPosition;
283 0 : len = myCursorPosition - myAnchorPosition;
284 : } else {
285 0 : start = myCursorPosition;
286 0 : len = myAnchorPosition - myCursorPosition;
287 : }
288 :
289 : // Get selected fragment
290 0 : string = contents.mid(start, len);
291 :
292 : // If password mode, replace by stars
293 0 : if (options & TEXTFIELD_PASSWD) {
294 0 : string.assign('*', string.count());
295 : }
296 :
297 : // Return text of the selection as UTF-8
298 0 : if (event->target == utf8Type) {
299 : FXTRACE((100, "Request UTF8\n"));
300 0 : setDNDData(FROM_SELECTION, event->target, string);
301 : return 1;
302 : }
303 :
304 : // Return text of the selection translated to 8859-1
305 0 : if (event->target == stringType || event->target == textType) {
306 : FX88591Codec ascii;
307 : FXTRACE((100, "Request ASCII\n"));
308 0 : setDNDData(FROM_SELECTION, event->target, ascii.utf2mb(string));
309 : return 1;
310 : }
311 :
312 : // Return text of the selection translated to UTF-16
313 0 : if (event->target == utf16Type) {
314 : FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
315 : FXTRACE((100, "Request UTF16\n"));
316 0 : setDNDData(FROM_SELECTION, event->target, unicode.utf2mb(string));
317 : return 1;
318 : }
319 : }
320 : return 0;
321 0 : }
322 :
323 :
324 : long
325 0 : MFXTextFieldIcon::onClipboardGained(FXObject* sender, FXSelector sel, void* ptr) {
326 0 : FXFrame::onClipboardGained(sender, sel, ptr);
327 0 : return 1;
328 : }
329 :
330 :
331 : long
332 0 : MFXTextFieldIcon::onClipboardLost(FXObject* sender, FXSelector sel, void* ptr) {
333 0 : FXFrame::onClipboardLost(sender, sel, ptr);
334 0 : myClippedText.clear();
335 0 : return 1;
336 : }
337 :
338 :
339 :
340 : long
341 0 : MFXTextFieldIcon::onClipboardRequest(FXObject* sender, FXSelector sel, void* ptr) {
342 : FXEvent* event = (FXEvent*)ptr;
343 0 : FXString string;
344 :
345 : // Perhaps the target wants to supply its own data for the clipboard
346 0 : if (FXFrame::onClipboardRequest(sender, sel, ptr)) {
347 : return 1;
348 : }
349 :
350 : // Recognize the request?
351 0 : if (event->target == stringType || event->target == textType || event->target == utf8Type || event->target == utf16Type) {
352 :
353 : // Get myClippedText string
354 0 : string = myClippedText;
355 :
356 : // If password mode, replace by stars
357 0 : if (options & TEXTFIELD_PASSWD) {
358 0 : string.assign('*', string.count());
359 : }
360 :
361 : // Return myClippedText text as as UTF-8
362 0 : if (event->target == utf8Type) {
363 : FXTRACE((100, "Request UTF8\n"));
364 0 : setDNDData(FROM_CLIPBOARD, event->target, string);
365 : return 1;
366 : }
367 :
368 : // Return myClippedText text translated to 8859-1
369 0 : if (event->target == stringType || event->target == textType) {
370 : FX88591Codec ascii;
371 : FXTRACE((100, "Request ASCII\n"));
372 0 : setDNDData(FROM_CLIPBOARD, event->target, ascii.utf2mb(string));
373 : return 1;
374 : }
375 :
376 : // Return text of the selection translated to UTF-16
377 0 : if (event->target == utf16Type) {
378 : FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
379 : FXTRACE((100, "Request UTF16\n"));
380 0 : setDNDData(FROM_CLIPBOARD, event->target, unicode.utf2mb(string));
381 : return 1;
382 : }
383 : }
384 : return 0;
385 0 : }
386 :
387 :
388 : long
389 0 : MFXTextFieldIcon::onBlink(FXObject*, FXSelector, void*) {
390 0 : drawCursor(flags ^ FLAG_CARET);
391 0 : getApp()->addTimeout(this, FXTextField::ID_BLINK, getApp()->getBlinkSpeed());
392 0 : return 0;
393 : }
394 :
395 :
396 : long
397 0 : MFXTextFieldIcon::onFocusIn(FXObject* sender, FXSelector sel, void* ptr) {
398 0 : FXFrame::onFocusIn(sender, sel, ptr);
399 0 : if (isEditable()) {
400 0 : getApp()->addTimeout(this, FXTextField::ID_BLINK, getApp()->getBlinkSpeed());
401 0 : drawCursor(FLAG_CARET);
402 : }
403 0 : if (hasSelection()) {
404 0 : update(border, border, width - (border << 1), height - (border << 1));
405 : }
406 0 : return 1;
407 : }
408 :
409 :
410 : long
411 0 : MFXTextFieldIcon::onFocusOut(FXObject* sender, FXSelector sel, void* ptr) {
412 0 : FXFrame::onFocusOut(sender, sel, ptr);
413 0 : getApp()->removeTimeout(this, FXTextField::ID_BLINK);
414 0 : drawCursor(0);
415 0 : if (hasSelection()) {
416 0 : update(border, border, width - (border << 1), height - (border << 1));
417 : }
418 0 : return 1;
419 : }
420 :
421 :
422 : long
423 0 : MFXTextFieldIcon::onFocusSelf(FXObject* sender, FXSelector sel, void* ptr) {
424 0 : if (FXFrame::onFocusSelf(sender, sel, ptr)) {
425 : FXEvent* event = (FXEvent*)ptr;
426 0 : if (event->type == SEL_KEYPRESS || event->type == SEL_KEYRELEASE) {
427 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_SELECT_ALL), NULL);
428 : }
429 0 : return 1;
430 : }
431 : return 0;
432 : }
433 :
434 :
435 : bool
436 0 : MFXTextFieldIcon::canFocus() const {
437 0 : return true;
438 : }
439 :
440 :
441 : void
442 0 : MFXTextFieldIcon::setFocus() {
443 0 : FXFrame::setFocus();
444 0 : setDefault(TRUE);
445 0 : flags &= ~FLAG_UPDATE;
446 0 : if (getApp()->hasInputMethod()) {
447 0 : createComposeContext();
448 : }
449 0 : }
450 :
451 :
452 : void
453 0 : MFXTextFieldIcon::killFocus() {
454 0 : FXFrame::killFocus();
455 0 : setDefault(MAYBE);
456 0 : flags |= FLAG_UPDATE;
457 0 : if (flags & FLAG_CHANGED) {
458 0 : flags &= ~FLAG_CHANGED;
459 0 : if (!(options & TEXTFIELD_ENTER_ONLY)) {
460 0 : if (target) {
461 0 : target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)contents.text());
462 : }
463 : }
464 : }
465 0 : if (getApp()->hasInputMethod()) {
466 0 : destroyComposeContext();
467 : }
468 0 : }
469 :
470 :
471 : long
472 0 : MFXTextFieldIcon::onCmdSetHelp(FXObject*, FXSelector, void* ptr) {
473 0 : setHelpText(*((FXString*)ptr));
474 0 : return 1;
475 : }
476 :
477 :
478 : long
479 0 : MFXTextFieldIcon::onCmdGetHelp(FXObject*, FXSelector, void* ptr) {
480 0 : *((FXString*)ptr) = getHelpText();
481 0 : return 1;
482 : }
483 :
484 :
485 : long
486 0 : MFXTextFieldIcon::onCmdSetTip(FXObject*, FXSelector, void* ptr) {
487 0 : setTipText(*((FXString*)ptr));
488 0 : return 1;
489 : }
490 :
491 :
492 : long
493 0 : MFXTextFieldIcon::onCmdGetTip(FXObject*, FXSelector, void* ptr) {
494 0 : *((FXString*)ptr) = getTipText();
495 0 : return 1;
496 : }
497 :
498 :
499 : long
500 0 : MFXTextFieldIcon::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
501 0 : if (FXWindow::onQueryTip(sender, sel, ptr)) {
502 : return 1;
503 : }
504 0 : if ((flags & FLAG_TIP) && !myTooltipText.empty()) {
505 0 : sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&myTooltipText);
506 0 : return 1;
507 : }
508 : return 0;
509 : }
510 :
511 :
512 : long
513 0 : MFXTextFieldIcon::onQueryHelp(FXObject* sender, FXSelector sel, void* ptr) {
514 0 : if (FXWindow::onQueryHelp(sender, sel, ptr)) {
515 : return 1;
516 : }
517 0 : if ((flags & FLAG_HELP) && !myHelpText.empty()) {
518 0 : sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&myHelpText);
519 0 : return 1;
520 : }
521 : return 0;
522 : }
523 :
524 :
525 : long
526 0 : MFXTextFieldIcon::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
527 0 : setText((const FXchar*)ptr);
528 0 : return 1;
529 : }
530 :
531 :
532 : long
533 0 : MFXTextFieldIcon::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
534 0 : setText(FXStringVal(*((FXint*)ptr)));
535 0 : return 1;
536 : }
537 :
538 :
539 : long
540 0 : MFXTextFieldIcon::onCmdSetRealValue(FXObject*, FXSelector, void* ptr) {
541 0 : setText(FXStringVal(*((FXdouble*)ptr)));
542 0 : return 1;
543 : }
544 :
545 :
546 : long
547 0 : MFXTextFieldIcon::onCmdSetStringValue(FXObject*, FXSelector, void* ptr) {
548 0 : setText(*((FXString*)ptr));
549 0 : return 1;
550 : }
551 :
552 :
553 : long
554 0 : MFXTextFieldIcon::onCmdGetIntValue(FXObject*, FXSelector, void* ptr) {
555 0 : *((FXint*)ptr) = FXIntVal(contents);
556 0 : return 1;
557 : }
558 :
559 :
560 : long
561 0 : MFXTextFieldIcon::onCmdGetRealValue(FXObject*, FXSelector, void* ptr) {
562 0 : *((FXdouble*)ptr) = FXDoubleVal(contents);
563 0 : return 1;
564 : }
565 :
566 :
567 : long
568 0 : MFXTextFieldIcon::onCmdGetStringValue(FXObject*, FXSelector, void* ptr) {
569 0 : *((FXString*)ptr) = getText();
570 0 : return 1;
571 : }
572 :
573 :
574 : long
575 0 : MFXTextFieldIcon::onLeftBtnPress(FXObject*, FXSelector, void* ptr) {
576 : FXEvent* ev = (FXEvent*)ptr;
577 0 : flags &= ~FLAG_TIP;
578 0 : handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
579 0 : if (isEnabled()) {
580 0 : grab();
581 0 : if (target && target->tryHandle(this, FXSEL(SEL_LEFTBUTTONPRESS, message), ptr)) {
582 : return 1;
583 : }
584 0 : flags &= ~FLAG_UPDATE;
585 0 : if (ev->click_count == 1) {
586 0 : setCursorPos(index(ev->win_x));
587 0 : if (ev->state & SHIFTMASK) {
588 0 : extendSelection(myCursorPosition);
589 : } else {
590 0 : killSelection();
591 0 : setAnchorPos(myCursorPosition);
592 : }
593 0 : makePositionVisible(myCursorPosition);
594 0 : flags |= FLAG_PRESSED;
595 : } else {
596 0 : setAnchorPos(0);
597 0 : setCursorPos(contents.length());
598 0 : extendSelection(contents.length());
599 0 : makePositionVisible(myCursorPosition);
600 : }
601 0 : return 1;
602 : }
603 : return 0;
604 : }
605 :
606 :
607 : long
608 0 : MFXTextFieldIcon::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) {
609 0 : if (isEnabled()) {
610 0 : ungrab();
611 0 : flags &= ~FLAG_PRESSED;
612 0 : if (target) {
613 0 : target->tryHandle(this, FXSEL(SEL_LEFTBUTTONRELEASE, message), ptr);
614 : }
615 0 : return 1;
616 : }
617 : return 0;
618 : }
619 :
620 :
621 : long
622 0 : MFXTextFieldIcon::onMiddleBtnPress(FXObject*, FXSelector, void* ptr) {
623 : FXEvent* ev = (FXEvent*)ptr;
624 0 : flags &= ~FLAG_TIP;
625 0 : handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
626 0 : if (isEnabled()) {
627 0 : grab();
628 0 : if (target && target->tryHandle(this, FXSEL(SEL_MIDDLEBUTTONPRESS, message), ptr)) {
629 : return 1;
630 : }
631 0 : setCursorPos(index(ev->win_x));
632 0 : setAnchorPos(myCursorPosition);
633 0 : makePositionVisible(myCursorPosition);
634 0 : update(border, border, width - (border << 1), height - (border << 1));
635 0 : flags &= ~FLAG_UPDATE;
636 0 : return 1;
637 : }
638 : return 0;
639 : }
640 :
641 :
642 : long
643 0 : MFXTextFieldIcon::onMiddleBtnRelease(FXObject*, FXSelector, void* ptr) {
644 0 : if (isEnabled()) {
645 0 : ungrab();
646 0 : if (target && target->tryHandle(this, FXSEL(SEL_MIDDLEBUTTONRELEASE, message), ptr)) {
647 : return 1;
648 : }
649 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_PASTE_MIDDLE), NULL);
650 : }
651 : return 0;
652 : }
653 :
654 :
655 : long
656 0 : MFXTextFieldIcon::onMotion(FXObject* sender, FXSelector sel, void* ptr) {
657 : // update static tooltip
658 0 : if (myStaticToolTip) {
659 0 : myStaticToolTip->onUpdate(sender, sel, ptr);
660 : }
661 : FXEvent* event = (FXEvent*)ptr;
662 : FXint t;
663 0 : if (flags & FLAG_PRESSED) {
664 0 : if (event->win_x < (border + padleft) || (width - border - padright) < event->win_x) {
665 0 : if (!getApp()->hasTimeout(this, ID_AUTOSCROLL)) {
666 0 : getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
667 : }
668 : } else {
669 0 : getApp()->removeTimeout(this, ID_AUTOSCROLL);
670 0 : t = index(event->win_x);
671 0 : if (t != myCursorPosition) {
672 0 : drawCursor(0);
673 0 : myCursorPosition = t;
674 0 : extendSelection(myCursorPosition);
675 : }
676 : }
677 0 : return 1;
678 : }
679 : return 0;
680 : }
681 :
682 :
683 : long
684 0 : MFXTextFieldIcon::onAutoScroll(FXObject*, FXSelector, void* ptr) {
685 : FXEvent* event = (FXEvent*)ptr;
686 0 : if (flags & FLAG_PRESSED) {
687 0 : FXint newcursor = myCursorPosition;
688 0 : FXint ll = border + padleft;
689 0 : FXint rr = width - border - padright;
690 0 : FXint ww = rr - ll;
691 : FXint tw;
692 :
693 0 : if (options & TEXTFIELD_PASSWD) {
694 0 : tw = myFont->getTextWidth("*", 1) * contents.count();
695 : } else {
696 0 : tw = myFont->getTextWidth(contents.text(), contents.length());
697 : }
698 :
699 : // Text right-aligned
700 0 : if (options & JUSTIFY_RIGHT) {
701 :
702 : // Scroll left
703 0 : if (event->win_x < ll) {
704 0 : if (tw > ww) {
705 0 : myShiftAmount += ll - event->win_x;
706 0 : if (ww > tw - myShiftAmount) {
707 0 : myShiftAmount = tw - ww;
708 : } else {
709 0 : getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
710 : }
711 : }
712 0 : newcursor = index(ll);
713 : }
714 :
715 : // Scroll right
716 0 : if (rr < event->win_x) {
717 0 : if (tw > ww) {
718 0 : myShiftAmount += rr - event->win_x;
719 0 : if (myShiftAmount <= 0) {
720 0 : myShiftAmount = 0;
721 : } else {
722 0 : getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
723 : }
724 : }
725 0 : newcursor = index(rr);
726 : }
727 : }
728 :
729 : // Text left-aligned
730 0 : else if (options & JUSTIFY_LEFT) {
731 :
732 : // Scroll left
733 0 : if (event->win_x < ll) {
734 0 : if (tw > ww) {
735 0 : myShiftAmount += ll - event->win_x;
736 0 : if (myShiftAmount >= 0) {
737 0 : myShiftAmount = 0;
738 : } else {
739 0 : getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
740 : }
741 : }
742 0 : newcursor = index(ll);
743 : }
744 :
745 : // Scroll right
746 0 : if (rr < event->win_x) {
747 0 : if (tw > ww) {
748 0 : myShiftAmount += rr - event->win_x;
749 0 : if (myShiftAmount + tw < ww) {
750 0 : myShiftAmount = ww - tw;
751 : } else {
752 0 : getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
753 : }
754 : }
755 0 : newcursor = index(rr);
756 : }
757 : } else {
758 : // Text centered, Scroll left
759 0 : if (event->win_x < ll) {
760 0 : if (tw > ww) {
761 0 : myShiftAmount += ll - event->win_x;
762 0 : if (myShiftAmount > tw / 2 - ww / 2) {
763 0 : myShiftAmount = tw / 2 - ww / 2;
764 : } else {
765 0 : getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
766 : }
767 : }
768 0 : newcursor = index(ll);
769 : }
770 : // Scroll right
771 0 : if (rr < event->win_x) {
772 0 : if (tw > ww) {
773 0 : myShiftAmount += rr - event->win_x;
774 0 : if (myShiftAmount < (ww - ww / 2) - tw / 2) {
775 0 : myShiftAmount = (ww - ww / 2) - tw / 2;
776 : } else {
777 0 : getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
778 : }
779 : }
780 0 : newcursor = index(rr);
781 : }
782 : }
783 : // Extend the selection
784 0 : if (newcursor != myCursorPosition) {
785 0 : drawCursor(0);
786 0 : myCursorPosition = newcursor;
787 0 : extendSelection(myCursorPosition);
788 : }
789 : }
790 0 : return 1;
791 : }
792 :
793 :
794 : long
795 0 : MFXTextFieldIcon::onCmdToggleOverstrike(FXObject*, FXSelector, void*) {
796 0 : setOverstrike(!isOverstrike());
797 0 : return 1;
798 : }
799 :
800 :
801 : long
802 0 : MFXTextFieldIcon::onUpdToggleOverstrike(FXObject* sender, FXSelector, void*) {
803 0 : sender->handle(this, isOverstrike() ? FXSEL(SEL_COMMAND, ID_CHECK) : FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
804 0 : sender->handle(this, FXSEL(SEL_COMMAND, ID_SHOW), NULL);
805 0 : sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), NULL);
806 0 : return 1;
807 : }
808 :
809 :
810 : long
811 0 : MFXTextFieldIcon::onCmdToggleEditable(FXObject*, FXSelector, void*) {
812 0 : setEditable(!isEditable());
813 0 : return 1;
814 : }
815 :
816 :
817 : long
818 0 : MFXTextFieldIcon::onUpdToggleEditable(FXObject* sender, FXSelector, void*) {
819 0 : sender->handle(this, isEditable() ? FXSEL(SEL_COMMAND, ID_CHECK) : FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
820 0 : sender->handle(this, FXSEL(SEL_COMMAND, ID_SHOW), NULL);
821 0 : sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), NULL);
822 0 : return 1;
823 : }
824 :
825 :
826 : long
827 0 : MFXTextFieldIcon::onUpdHaveSelection(FXObject* sender, FXSelector, void* ptr) {
828 0 : sender->handle(this, hasSelection() ? FXSEL(SEL_COMMAND, ID_ENABLE) : FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
829 0 : return 1;
830 : }
831 :
832 :
833 : long
834 0 : MFXTextFieldIcon::onUpdSelectAll(FXObject* sender, FXSelector, void* ptr) {
835 0 : sender->handle(this, contents.empty() ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
836 0 : return 1;
837 : }
838 :
839 :
840 : void
841 0 : MFXTextFieldIcon::setCursorPos(FXint pos) {
842 0 : pos = contents.validate(FXCLAMP(0, pos, contents.length()));
843 0 : if (myCursorPosition != pos) {
844 0 : drawCursor(0);
845 0 : myCursorPosition = pos;
846 0 : if (isEditable() && hasFocus()) {
847 0 : drawCursor(FLAG_CARET);
848 : }
849 : }
850 0 : }
851 :
852 :
853 : FXint
854 0 : MFXTextFieldIcon::getCursorPos() const {
855 0 : return myCursorPosition;
856 : }
857 :
858 :
859 : void
860 0 : MFXTextFieldIcon::setAnchorPos(FXint pos) {
861 0 : myAnchorPosition = contents.validate(FXCLAMP(0, pos, contents.length()));
862 0 : }
863 :
864 :
865 : FXint
866 0 : MFXTextFieldIcon::getAnchorPos() const {
867 0 : return myAnchorPosition;
868 : }
869 :
870 :
871 : void
872 0 : MFXTextFieldIcon::drawCursor(FXuint state) {
873 : FXint cl, ch, xx, xlo, xhi;
874 0 : if ((state ^ flags) & FLAG_CARET) {
875 0 : if (xid) {
876 0 : FXDCWindow dc(this);
877 : FXASSERT(0 <= myCursorPosition && myCursorPosition <= contents.length());
878 : FXASSERT(0 <= myAnchorPosition && myAnchorPosition <= contents.length());
879 0 : xx = coord(myCursorPosition) - 1;
880 : // add myIcon spacing
881 0 : if (myIcon) {
882 0 : xx += ICON_SPACING + ICON_SIZE;
883 : }
884 : // Clip rectangle around myCursorPosition
885 0 : xlo = FXMAX(xx - 2, border);
886 0 : xhi = FXMIN(xx + 3, width - border);
887 : // Cursor can overhang padding but not borders
888 0 : dc.setClipRectangle(xlo, border, xhi - xlo, height - (border << 1));
889 : // Draw I beam
890 0 : if (state & FLAG_CARET) {
891 : // Draw I-beam
892 0 : dc.setForeground(myCursorColor);
893 0 : dc.fillRectangle(xx, padtop + border, 1, height - padbottom - padtop - (border << 1));
894 0 : dc.fillRectangle(xx - 2, padtop + border, 5, 1);
895 0 : dc.fillRectangle(xx - 2, height - border - padbottom - 1, 5, 1);
896 : } else {
897 : // Erase I-beam, plus the text immediately surrounding it
898 0 : dc.setForeground(backColor);
899 0 : dc.fillRectangle(xx - 2, border, 5, height - (border << 1));
900 : // Draw two characters before and after myCursorPosition
901 0 : cl = ch = myCursorPosition;
902 0 : if (0 < cl) {
903 0 : cl = contents.dec(cl);
904 0 : if (0 < cl) {
905 0 : cl = contents.dec(cl);
906 : }
907 : }
908 0 : if (ch < contents.length()) {
909 0 : ch = contents.inc(ch);
910 0 : if (ch < contents.length()) {
911 0 : ch = contents.inc(ch);
912 : }
913 : }
914 0 : drawTextRange(dc, cl, ch);
915 : }
916 0 : }
917 0 : flags ^= FLAG_CARET;
918 : }
919 0 : }
920 :
921 :
922 : void
923 7487 : MFXTextFieldIcon::layout() {
924 7487 : FXint rr = width - border - padright;
925 7487 : FXint ll = border + padleft;
926 7487 : FXint ww = rr - ll;
927 : FXint tw;
928 7487 : if (!xid) {
929 : return;
930 : }
931 :
932 : // Figure text width
933 7487 : if (options & TEXTFIELD_PASSWD) {
934 0 : tw = myFont->getTextWidth("*", 1) * contents.count();
935 : } else {
936 7487 : tw = myFont->getTextWidth(contents.text(), contents.length());
937 : }
938 :
939 : // Constrain myShiftAmount
940 7487 : if (options & JUSTIFY_RIGHT) {
941 0 : if (ww >= tw) {
942 0 : myShiftAmount = 0;
943 0 : } else if (myShiftAmount < 0) {
944 0 : myShiftAmount = 0;
945 0 : } else if (myShiftAmount > tw - ww) {
946 0 : myShiftAmount = tw - ww;
947 : }
948 7487 : } else if (options & JUSTIFY_LEFT) {
949 7487 : if (ww >= tw) {
950 7421 : myShiftAmount = 0;
951 66 : } else if (myShiftAmount > 0) {
952 0 : myShiftAmount = 0;
953 66 : } else if (myShiftAmount < ww - tw) {
954 0 : myShiftAmount = ww - tw;
955 : }
956 : } else {
957 0 : if (ww >= tw) {
958 0 : myShiftAmount = 0;
959 0 : } else if (myShiftAmount > tw / 2 - ww / 2) {
960 0 : myShiftAmount = tw / 2 - ww / 2;
961 0 : } else if (myShiftAmount < (ww - ww / 2) - tw / 2) {
962 0 : myShiftAmount = (ww - ww / 2) - tw / 2;
963 : }
964 : }
965 :
966 : // Keep myCursorPosition in the picture if resizing field
967 7487 : makePositionVisible(myCursorPosition);
968 :
969 : // Always redraw
970 7487 : update();
971 :
972 7487 : flags &= ~(FXuint)FLAG_DIRTY;
973 : }
974 :
975 :
976 : void
977 7487 : MFXTextFieldIcon::makePositionVisible(FXint pos) {
978 7487 : FXint rr = width - border - padright;
979 7487 : FXint ll = border + padleft;
980 7487 : FXint ww = rr - ll;
981 7487 : FXint oldshift = myShiftAmount;
982 : FXint xx;
983 7487 : if (!xid) {
984 : return;
985 : }
986 7487 : pos = contents.validate(FXCLAMP(0, pos, contents.length()));
987 7487 : if (options & JUSTIFY_RIGHT) {
988 0 : if (options & TEXTFIELD_PASSWD) {
989 0 : xx = myFont->getTextWidth("*", 1) * contents.count(pos, contents.length());
990 : } else {
991 0 : xx = myFont->getTextWidth(&contents[pos], contents.length() - pos);
992 : }
993 0 : if (myShiftAmount - xx > 0) {
994 0 : myShiftAmount = xx;
995 0 : } else if (myShiftAmount - xx < -ww) {
996 0 : myShiftAmount = xx - ww;
997 : }
998 7487 : } else if (options & JUSTIFY_LEFT) {
999 7487 : if (options & TEXTFIELD_PASSWD) {
1000 0 : xx = myFont->getTextWidth("*", 1) * contents.index(pos);
1001 : } else {
1002 7487 : xx = myFont->getTextWidth(contents.text(), pos);
1003 : }
1004 7487 : if (myShiftAmount + xx < 0) {
1005 33 : myShiftAmount = -xx;
1006 7454 : } else if (myShiftAmount + xx >= ww) {
1007 33 : myShiftAmount = ww - xx;
1008 : }
1009 : } else {
1010 0 : if (options & TEXTFIELD_PASSWD) {
1011 0 : xx = myFont->getTextWidth("*", 1) * contents.index(pos) - (myFont->getTextWidth("*", 1) * contents.count()) / 2;
1012 : } else {
1013 0 : xx = myFont->getTextWidth(contents.text(), pos) - myFont->getTextWidth(contents.text(), contents.length()) / 2;
1014 : }
1015 0 : if (myShiftAmount + ww / 2 + xx < 0) {
1016 0 : myShiftAmount = -ww / 2 - xx;
1017 0 : } else if (myShiftAmount + ww / 2 + xx >= ww) {
1018 0 : myShiftAmount = ww - ww / 2 - xx;
1019 : }
1020 : }
1021 7487 : if (myShiftAmount != oldshift) {
1022 66 : update(border, border, width - (border << 1), height - (border << 1));
1023 : }
1024 : }
1025 :
1026 :
1027 : FXint
1028 0 : MFXTextFieldIcon::index(FXint x) const {
1029 0 : FXint rr = width - border - padright;
1030 0 : FXint ll = border + padleft;
1031 0 : FXint mm = (ll + rr) / 2;
1032 : FXint pos, xx, cw;
1033 0 : if (options & TEXTFIELD_PASSWD) {
1034 0 : cw = myFont->getTextWidth("*", 1);
1035 0 : if (options & JUSTIFY_RIGHT) {
1036 0 : xx = rr - cw * contents.count();
1037 0 : } else if (options & JUSTIFY_LEFT) {
1038 : xx = ll;
1039 : } else {
1040 0 : xx = mm - (cw * contents.count()) / 2;
1041 : }
1042 0 : xx += myShiftAmount;
1043 0 : pos = contents.offset((x - xx + (cw >> 1)) / cw);
1044 : } else {
1045 0 : if (options & JUSTIFY_RIGHT) {
1046 0 : xx = rr - myFont->getTextWidth(contents.text(), contents.length());
1047 0 : } else if (options & JUSTIFY_LEFT) {
1048 : xx = ll;
1049 : } else {
1050 0 : xx = mm - myFont->getTextWidth(contents.text(), contents.length()) / 2;
1051 : }
1052 0 : xx += myShiftAmount;
1053 0 : for (pos = 0; pos < contents.length(); pos = contents.inc(pos)) {
1054 0 : cw = myFont->getTextWidth(&contents[pos], contents.extent(pos));
1055 0 : if (x < (xx + (cw >> 1))) {
1056 : break;
1057 : }
1058 0 : xx += cw;
1059 : }
1060 : }
1061 0 : if (pos < 0) {
1062 : pos = 0;
1063 : }
1064 0 : if (pos > contents.length()) {
1065 : pos = contents.length();
1066 : }
1067 0 : return pos;
1068 : }
1069 :
1070 :
1071 : FXint
1072 0 : MFXTextFieldIcon::coord(FXint i) const {
1073 0 : FXint rr = width - border - padright;
1074 0 : FXint ll = border + padleft;
1075 0 : FXint mm = (ll + rr) / 2;
1076 : FXint pos;
1077 : FXASSERT(0 <= i && i <= contents.length());
1078 0 : if (options & JUSTIFY_RIGHT) {
1079 0 : if (options & TEXTFIELD_PASSWD) {
1080 0 : pos = rr - myFont->getTextWidth("*", 1) * (contents.count() - contents.index(i));
1081 : } else {
1082 0 : pos = rr - myFont->getTextWidth(&contents[i], contents.length() - i);
1083 : }
1084 0 : } else if (options & JUSTIFY_LEFT) {
1085 0 : if (options & TEXTFIELD_PASSWD) {
1086 0 : pos = ll + myFont->getTextWidth("*", 1) * contents.index(i);
1087 : } else {
1088 0 : pos = ll + myFont->getTextWidth(contents.text(), i);
1089 : }
1090 : } else {
1091 0 : if (options & TEXTFIELD_PASSWD) {
1092 0 : pos = mm + myFont->getTextWidth("*", 1) * contents.index(i) - (myFont->getTextWidth("*", 1) * contents.count()) / 2;
1093 : } else {
1094 0 : pos = mm + myFont->getTextWidth(contents.text(), i) - myFont->getTextWidth(contents.text(), contents.length()) / 2;
1095 : }
1096 : }
1097 0 : return pos + myShiftAmount;
1098 : }
1099 :
1100 :
1101 : FXbool
1102 0 : MFXTextFieldIcon::isPosVisible(FXint pos) const {
1103 0 : if (0 <= pos && pos <= contents.length()) {
1104 0 : FXint x = coord(contents.validate(pos));
1105 0 : return border + padleft <= x && x <= width - border - padright;
1106 : }
1107 : return FALSE;
1108 : }
1109 :
1110 :
1111 : FXbool
1112 0 : MFXTextFieldIcon::isPosSelected(FXint pos) const {
1113 0 : return hasSelection() && FXMIN(myAnchorPosition, myCursorPosition) <= pos && pos <= FXMAX(myAnchorPosition, myCursorPosition);
1114 : }
1115 :
1116 :
1117 : void
1118 20240 : MFXTextFieldIcon::drawTextFragment(FXDCWindow& dc, FXint x, FXint y, FXint fm, FXint to) {
1119 20240 : x += myFont->getTextWidth(contents.text(), fm);
1120 20240 : y += myFont->getFontAscent();
1121 20240 : dc.drawText(x, y, &contents[fm], to - fm);
1122 20240 : }
1123 :
1124 :
1125 : void
1126 0 : MFXTextFieldIcon::drawPWDTextFragment(FXDCWindow& dc, FXint x, FXint y, FXint fm, FXint to) {
1127 0 : FXint cw = myFont->getTextWidth("*", 1);
1128 : FXint i;
1129 0 : y += myFont->getFontAscent();
1130 0 : x += cw * contents.index(fm);
1131 0 : for (i = fm; i < to; i = contents.inc(i), x += cw) {
1132 0 : dc.drawText(x, y, "*", 1);
1133 : }
1134 0 : }
1135 :
1136 :
1137 : // Draw range of text
1138 20240 : void MFXTextFieldIcon::drawTextRange(FXDCWindow& dc, FXint fm, FXint to) {
1139 : FXint sx, ex, xx, yy, cw, hh, ww, si, ei, lx, rx, t;
1140 20240 : FXint rr = width - border - padright;
1141 20240 : FXint ll = border + padleft;
1142 20240 : FXint mm = (ll + rr) / 2;
1143 20240 : if (to <= fm) {
1144 : return;
1145 : }
1146 : // set font
1147 20240 : dc.setFont(myFont);
1148 : // Text color
1149 20240 : dc.setForeground(myTextColor);
1150 : // Height
1151 20240 : hh = myFont->getFontHeight();
1152 : // Text sticks to top of field
1153 20240 : if (options & JUSTIFY_TOP) {
1154 0 : yy = padtop + border;
1155 20240 : } else if (options & JUSTIFY_BOTTOM) {
1156 : // Text sticks to bottom of field
1157 0 : yy = height - padbottom - border - hh;
1158 : } else {
1159 : // Text centered in y
1160 20240 : yy = border + padtop + (height - padbottom - padtop - (border << 1) - hh) / 2;
1161 : }
1162 20240 : if (myAnchorPosition < myCursorPosition) {
1163 : si = myAnchorPosition;
1164 : ei = myCursorPosition;
1165 : } else {
1166 : si = myCursorPosition;
1167 : ei = myAnchorPosition;
1168 : }
1169 : // Password mode
1170 20240 : if (options & TEXTFIELD_PASSWD) {
1171 0 : cw = myFont->getTextWidth("*", 1);
1172 0 : ww = cw * contents.count();
1173 : // Text sticks to right of field
1174 0 : if (options & JUSTIFY_RIGHT) {
1175 0 : xx = myShiftAmount + rr - ww;
1176 0 : } else if (options & JUSTIFY_LEFT) {
1177 : // Text sticks on left of field
1178 0 : xx = myShiftAmount + ll;
1179 : } else {
1180 : // Text centered in field
1181 0 : xx = myShiftAmount + mm - ww / 2;
1182 : }
1183 : // check if add myIcon spacing
1184 0 : if (myIcon) {
1185 0 : xx += ICON_SPACING + ICON_SIZE;
1186 : }
1187 : // Reduce to avoid drawing excessive amounts of text
1188 0 : lx = xx + cw * contents.index(fm);
1189 0 : rx = xx + cw * contents.index(to);
1190 0 : while (fm < to) {
1191 0 : if (lx + cw >= 0) {
1192 : break;
1193 : }
1194 : lx += cw;
1195 0 : fm = contents.inc(fm);
1196 : }
1197 0 : while (fm < to) {
1198 0 : if (rx - cw < width) {
1199 : break;
1200 : }
1201 : rx -= cw;
1202 0 : to = contents.dec(to);
1203 : }
1204 : // Adjust selected range
1205 0 : if (si < fm) {
1206 : si = fm;
1207 : }
1208 0 : if (ei > to) {
1209 : ei = to;
1210 : }
1211 :
1212 : // Nothing selected
1213 0 : if (!hasSelection() || to <= si || ei <= fm) {
1214 0 : drawPWDTextFragment(dc, xx, yy, fm, to);
1215 : } else {
1216 : // Stuff selected
1217 0 : if (fm < si) {
1218 0 : drawPWDTextFragment(dc, xx, yy, fm, si);
1219 : } else {
1220 : si = fm;
1221 : }
1222 0 : if (ei < to) {
1223 0 : drawPWDTextFragment(dc, xx, yy, ei, to);
1224 : } else {
1225 : ei = to;
1226 : }
1227 0 : if (si < ei) {
1228 0 : sx = xx + cw * contents.index(si);
1229 0 : ex = xx + cw * contents.index(ei);
1230 0 : if (hasFocus()) {
1231 0 : dc.setForeground(mySelectedBackgroundColor);
1232 0 : dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1233 0 : dc.setForeground(mySelectedTextColor);
1234 0 : drawPWDTextFragment(dc, xx, yy, si, ei);
1235 : } else {
1236 0 : dc.setForeground(baseColor);
1237 0 : dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1238 0 : dc.setForeground(myTextColor);
1239 0 : drawPWDTextFragment(dc, xx, yy, si, ei);
1240 : }
1241 : }
1242 : }
1243 : } else {
1244 : // Normal mode
1245 20240 : ww = myFont->getTextWidth(contents.text(), contents.length());
1246 : // Text sticks to right of field
1247 20240 : if (options & JUSTIFY_RIGHT) {
1248 0 : xx = myShiftAmount + rr - ww;
1249 20240 : } else if (options & JUSTIFY_LEFT) {
1250 : // Text sticks on left of field
1251 20240 : xx = myShiftAmount + ll;
1252 : } else {
1253 : // Text centered in field
1254 0 : xx = myShiftAmount + mm - ww / 2;
1255 : }
1256 : // check if add myIcon spacing
1257 20240 : if (myIcon) {
1258 0 : xx += ICON_SPACING + ICON_SIZE;
1259 : }
1260 : // Reduce to avoid drawing excessive amounts of text
1261 20240 : lx = xx + myFont->getTextWidth(&contents[0], fm);
1262 20240 : rx = lx + myFont->getTextWidth(&contents[fm], to - fm);
1263 20474 : while (fm < to) {
1264 20474 : t = contents.inc(fm);
1265 20474 : cw = myFont->getTextWidth(&contents[fm], t - fm);
1266 20474 : if (lx + cw >= 0) {
1267 : break;
1268 : }
1269 : lx += cw;
1270 : fm = t;
1271 : }
1272 79928 : while (fm < to) {
1273 72467 : t = contents.dec(to);
1274 72467 : cw = myFont->getTextWidth(&contents[t], to - t);
1275 72467 : if (rx - cw < width) {
1276 : break;
1277 : }
1278 : rx -= cw;
1279 : to = t;
1280 : }
1281 :
1282 : // Adjust selected range
1283 20240 : if (si < fm) {
1284 : si = fm;
1285 : }
1286 20240 : if (ei > to) {
1287 : ei = to;
1288 : }
1289 :
1290 : // Nothing selected
1291 20240 : if (!hasSelection() || to <= si || ei <= fm) {
1292 20240 : drawTextFragment(dc, xx, yy, fm, to);
1293 : } else {
1294 : // Stuff selected
1295 0 : if (fm < si) {
1296 0 : drawTextFragment(dc, xx, yy, fm, si);
1297 : } else {
1298 : si = fm;
1299 : }
1300 0 : if (ei < to) {
1301 0 : drawTextFragment(dc, xx, yy, ei, to);
1302 : } else {
1303 : ei = to;
1304 : }
1305 0 : if (si < ei) {
1306 0 : sx = xx + myFont->getTextWidth(contents.text(), si);
1307 0 : ex = xx + myFont->getTextWidth(contents.text(), ei);
1308 0 : if (hasFocus()) {
1309 0 : dc.setForeground(mySelectedBackgroundColor);
1310 0 : dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1311 0 : dc.setForeground(mySelectedTextColor);
1312 0 : drawTextFragment(dc, xx, yy, si, ei);
1313 : } else {
1314 0 : dc.setForeground(baseColor);
1315 0 : dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1316 0 : dc.setForeground(myTextColor);
1317 0 : drawTextFragment(dc, xx, yy, si, ei);
1318 : }
1319 : }
1320 : }
1321 : }
1322 : }
1323 :
1324 :
1325 : long
1326 0 : MFXTextFieldIcon::onEnter(FXObject* sender, FXSelector sel, void* ptr) {
1327 : // check if show toolTip text
1328 0 : if (myStaticToolTip) {
1329 0 : if (!myToolTipText.empty()) {
1330 : // show toolTip text
1331 0 : setTipText(myToolTipText);
1332 : // show myTooltipText show
1333 0 : myStaticToolTip->showStaticToolTip(getTipText());
1334 0 : } else if (myFont->getTextWidth(contents.text(), contents.length()) > getWidth()) {
1335 : // only show myTooltipText Text if contents is bigger than textField width
1336 0 : setTipText(contents);
1337 : // show myTooltipText show
1338 0 : myStaticToolTip->showStaticToolTip(getTipText());
1339 : }
1340 : // always show myHelpText text
1341 0 : setHelpText(contents);
1342 : }
1343 : // continue with FXTextField function
1344 0 : return FXFrame::onEnter(sender, sel, ptr);
1345 : }
1346 :
1347 :
1348 : long
1349 0 : MFXTextFieldIcon::onLeave(FXObject* sender, FXSelector sel, void* ptr) {
1350 : // hide static toolTip
1351 0 : if (myStaticToolTip) {
1352 0 : myStaticToolTip->hideStaticToolTip();
1353 : }
1354 : // continue with FXTextField function
1355 0 : return FXFrame::onLeave(sender, sel, ptr);
1356 : }
1357 :
1358 :
1359 : long
1360 20240 : MFXTextFieldIcon::onPaint(FXObject*, FXSelector, void* ptr) {
1361 : FXEvent* ev = (FXEvent*)ptr;
1362 20240 : FXDCWindow dc(this, ev);
1363 : // Draw frame
1364 20240 : drawFrame(dc, 0, 0, width, height);
1365 : // Gray background if disabled
1366 20240 : if (isEnabled()) {
1367 20240 : dc.setForeground(backColor);
1368 : } else {
1369 0 : dc.setForeground(baseColor);
1370 : }
1371 : // Draw background
1372 20240 : dc.fillRectangle(border, border, width - (border << 1), height - (border << 1));
1373 : // Draw text, myClippedText against frame interior
1374 20240 : dc.setClipRectangle(border, border, width - (border << 1), height - (border << 1));
1375 20240 : drawTextRange(dc, 0, contents.length());
1376 : // Draw caret
1377 20240 : if (flags & FLAG_CARET) {
1378 0 : int xx = coord(myCursorPosition) - 1;
1379 : // check if add myIcon spacing
1380 0 : if (myIcon) {
1381 0 : xx += ICON_SPACING + ICON_SIZE;
1382 : }
1383 0 : dc.setForeground(myCursorColor);
1384 0 : dc.fillRectangle(xx, padtop + border, 1, height - padbottom - padtop - (border << 1));
1385 0 : dc.fillRectangle(xx - 2, padtop + border, 5, 1);
1386 0 : dc.fillRectangle(xx - 2, height - border - padbottom - 1, 5, 1);
1387 : }
1388 : // draw myIcon
1389 20240 : if (myIcon) {
1390 0 : dc.drawIcon(myIcon, ICON_SPACING / 2, border + padtop + (height - padbottom - padtop - (border << 1) - ICON_SIZE) / 2);
1391 : }
1392 20240 : return 1;
1393 20240 : }
1394 :
1395 :
1396 : long
1397 0 : MFXTextFieldIcon::onCmdCursorHome(FXObject*, FXSelector, void*) {
1398 0 : setCursorPos(0);
1399 0 : makePositionVisible(0);
1400 0 : return 1;
1401 : }
1402 :
1403 :
1404 : long
1405 0 : MFXTextFieldIcon::onCmdCursorEnd(FXObject*, FXSelector, void*) {
1406 0 : setCursorPos(contents.length());
1407 0 : makePositionVisible(myCursorPosition);
1408 0 : return 1;
1409 : }
1410 :
1411 :
1412 : long
1413 0 : MFXTextFieldIcon::onCmdCursorRight(FXObject*, FXSelector, void*) {
1414 0 : setCursorPos(contents.inc(myCursorPosition));
1415 0 : makePositionVisible(myCursorPosition);
1416 0 : return 1;
1417 : }
1418 :
1419 :
1420 :
1421 : long
1422 0 : MFXTextFieldIcon::onCmdCursorLeft(FXObject*, FXSelector, void*) {
1423 0 : setCursorPos(contents.dec(myCursorPosition));
1424 0 : makePositionVisible(myCursorPosition);
1425 0 : return 1;
1426 : }
1427 :
1428 :
1429 : static FXbool
1430 : isdelimiter(const FXchar* myTextDelimiter, FXwchar w) {
1431 0 : return w < 128 && strchr(myTextDelimiter, w); // FIXME for w >= 128
1432 : }
1433 :
1434 :
1435 : FXint
1436 0 : MFXTextFieldIcon::leftWord(FXint pos) const {
1437 : FXint pp = pos, p;
1438 :
1439 : // Ensure input is valid
1440 : FXASSERT(0 <= pos && pos <= contents.length());
1441 :
1442 : // Back up until space or delimiter
1443 0 : while (0 <= (p = contents.dec(pp)) && !Unicode::isSpace(contents.wc(p)) && !isdelimiter(myTextDelimiter, contents.wc(p))) {
1444 : pp = p;
1445 : }
1446 :
1447 : // Back up over run of spaces
1448 0 : while (0 <= (p = contents.dec(pp)) && Unicode::isSpace(contents.wc(p))) {
1449 : pp = p;
1450 : }
1451 :
1452 : // One more in case we didn't move
1453 0 : if ((pos == pp) && 0 <= (p = contents.dec(pp))) {
1454 : pp = p;
1455 : }
1456 :
1457 0 : return pp;
1458 : }
1459 :
1460 :
1461 : FXint
1462 0 : MFXTextFieldIcon::rightWord(FXint pos) const {
1463 : FXint pp = pos;
1464 :
1465 : // Ensure input is valid
1466 : FXASSERT(0 <= pos && pos <= contents.length());
1467 :
1468 : // Advance until space or delimiter
1469 0 : while (pp < contents.length() && !Unicode::isSpace(contents.wc(pp)) && !isdelimiter(myTextDelimiter, contents.wc(pp))) {
1470 0 : pp = contents.inc(pp);
1471 : }
1472 :
1473 : // Advance over run of spaces
1474 0 : while (pp < contents.length() && Unicode::isSpace(contents.wc(pp))) {
1475 0 : pp = contents.inc(pp);
1476 : }
1477 :
1478 : // One more in case we didn't move
1479 0 : if ((pos == pp) && pp < contents.length()) {
1480 0 : pp = contents.inc(pp);
1481 : }
1482 :
1483 0 : return pp;
1484 : }
1485 :
1486 :
1487 : FXint
1488 0 : MFXTextFieldIcon::wordStart(FXint pos) const {
1489 : FXint p;
1490 : FXASSERT(0 <= pos && pos <= contents.length());
1491 0 : if (pos == contents.length() || Unicode::isSpace(contents.wc(pos))) {
1492 0 : while (0 <= (p = contents.dec(pos)) && Unicode::isSpace(contents.wc(p))) {
1493 : pos = p;
1494 : }
1495 0 : } else if (isdelimiter(myTextDelimiter, contents.wc(pos))) {
1496 0 : while (0 <= (p = contents.dec(pos)) && isdelimiter(myTextDelimiter, contents.wc(p))) {
1497 : pos = p;
1498 : }
1499 : } else {
1500 0 : while (0 <= (p = contents.dec(pos)) && !isdelimiter(myTextDelimiter, contents.wc(p)) && !Unicode::isSpace(contents.wc(p))) {
1501 : pos = p;
1502 : }
1503 : }
1504 0 : return pos;
1505 : }
1506 :
1507 :
1508 : FXint
1509 0 : MFXTextFieldIcon::wordEnd(FXint pos) const {
1510 : FXASSERT(0 <= pos && pos <= contents.length());
1511 0 : if (pos == contents.length() || Unicode::isSpace(contents.wc(pos))) {
1512 0 : while (pos < contents.length() && Unicode::isSpace(contents.wc(pos))) {
1513 0 : pos = contents.inc(pos);
1514 : }
1515 0 : } else if (isdelimiter(myTextDelimiter, contents.wc(pos))) {
1516 0 : while (pos < contents.length() && isdelimiter(myTextDelimiter, contents.wc(pos))) {
1517 0 : pos = contents.inc(pos);
1518 : }
1519 : } else {
1520 0 : while (pos < contents.length() && !isdelimiter(myTextDelimiter, contents.wc(pos)) && !Unicode::isSpace(contents.wc(pos))) {
1521 0 : pos = contents.inc(pos);
1522 : }
1523 : }
1524 0 : return pos;
1525 : }
1526 :
1527 :
1528 : long
1529 0 : MFXTextFieldIcon::onCmdCursorWordRight(FXObject*, FXSelector, void*) {
1530 0 : setCursorPos(rightWord(myCursorPosition));
1531 0 : makePositionVisible(myCursorPosition);
1532 0 : return 1;
1533 : }
1534 :
1535 :
1536 : long
1537 0 : MFXTextFieldIcon::onCmdCursorWordLeft(FXObject*, FXSelector, void*) {
1538 0 : setCursorPos(leftWord(myCursorPosition));
1539 0 : makePositionVisible(myCursorPosition);
1540 0 : return 1;
1541 : }
1542 :
1543 :
1544 : long
1545 0 : MFXTextFieldIcon::onCmdCursorWordStart(FXObject*, FXSelector, void*) {
1546 0 : setCursorPos(wordStart(myCursorPosition));
1547 0 : makePositionVisible(myCursorPosition);
1548 0 : return 1;
1549 : }
1550 :
1551 :
1552 : long
1553 0 : MFXTextFieldIcon::onCmdCursorWordEnd(FXObject*, FXSelector, void*) {
1554 0 : setCursorPos(wordEnd(myCursorPosition));
1555 0 : makePositionVisible(myCursorPosition);
1556 0 : return 1;
1557 : }
1558 :
1559 :
1560 : long
1561 0 : MFXTextFieldIcon::onCmdMark(FXObject*, FXSelector, void*) {
1562 0 : setAnchorPos(myCursorPosition);
1563 0 : return 1;
1564 : }
1565 :
1566 :
1567 : long
1568 0 : MFXTextFieldIcon::onCmdExtend(FXObject*, FXSelector, void*) {
1569 0 : extendSelection(myCursorPosition);
1570 0 : return 1;
1571 : }
1572 :
1573 :
1574 : long
1575 0 : MFXTextFieldIcon::onCmdSelectAll(FXObject*, FXSelector, void*) {
1576 0 : selectAll();
1577 0 : makePositionVisible(myCursorPosition);
1578 0 : return 1;
1579 : }
1580 :
1581 :
1582 : long
1583 0 : MFXTextFieldIcon::onCmdDeselectAll(FXObject*, FXSelector, void*) {
1584 0 : killSelection();
1585 0 : return 1;
1586 : }
1587 :
1588 :
1589 : long
1590 0 : MFXTextFieldIcon::onCmdCutSel(FXObject*, FXSelector, void*) {
1591 0 : if (isEditable()) {
1592 0 : if (hasSelection()) {
1593 : FXDragType types[4];
1594 0 : types[0] = stringType;
1595 0 : types[1] = textType;
1596 0 : types[2] = utf8Type;
1597 0 : types[3] = utf16Type;
1598 0 : if (acquireClipboard(types, 4)) {
1599 0 : if (myAnchorPosition < myCursorPosition) {
1600 0 : myClippedText = contents.mid(myAnchorPosition, myCursorPosition - myAnchorPosition);
1601 : } else {
1602 0 : myClippedText = contents.mid(myCursorPosition, myAnchorPosition - myCursorPosition);
1603 : }
1604 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
1605 : }
1606 : }
1607 : } else {
1608 0 : getApp()->beep();
1609 : }
1610 0 : return 1;
1611 : }
1612 :
1613 :
1614 : long
1615 0 : MFXTextFieldIcon::onCmdCopySel(FXObject*, FXSelector, void*) {
1616 0 : if (hasSelection()) {
1617 : FXDragType types[4];
1618 0 : types[0] = stringType;
1619 0 : types[1] = textType;
1620 0 : types[2] = utf8Type;
1621 0 : types[3] = utf16Type;
1622 0 : if (acquireClipboard(types, 4)) {
1623 0 : if (myAnchorPosition < myCursorPosition) {
1624 0 : myClippedText = contents.mid(myAnchorPosition, myCursorPosition - myAnchorPosition);
1625 : } else {
1626 0 : myClippedText = contents.mid(myCursorPosition, myAnchorPosition - myCursorPosition);
1627 : }
1628 : }
1629 : }
1630 0 : return 1;
1631 : }
1632 :
1633 :
1634 : long
1635 0 : MFXTextFieldIcon::onCmdPasteSel(FXObject*, FXSelector, void*) {
1636 0 : if (isEditable()) {
1637 0 : FXString string;
1638 :
1639 : // Delete existing selection
1640 0 : if (hasSelection()) {
1641 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
1642 : }
1643 :
1644 : // First, try UTF-8
1645 0 : if (getDNDData(FROM_CLIPBOARD, utf8Type, string)) {
1646 : FXTRACE((100, "Paste UTF8\n"));
1647 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)string.text());
1648 : return 1;
1649 : }
1650 :
1651 : // Next, try UTF-16
1652 0 : if (getDNDData(FROM_CLIPBOARD, utf16Type, string)) {
1653 : FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
1654 : FXTRACE((100, "Paste UTF16\n"));
1655 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)unicode.mb2utf(string).text());
1656 : return 1;
1657 : }
1658 :
1659 : // Next, try good old Latin-1
1660 0 : if (getDNDData(FROM_CLIPBOARD, stringType, string)) {
1661 : FX88591Codec ascii;
1662 : FXTRACE((100, "Paste ASCII\n"));
1663 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)ascii.mb2utf(string).text());
1664 : return 1;
1665 : }
1666 0 : } else {
1667 0 : getApp()->beep();
1668 : }
1669 : return 1;
1670 : }
1671 :
1672 :
1673 : long
1674 0 : MFXTextFieldIcon::onCmdPasteMiddle(FXObject*, FXSelector, void*) {
1675 0 : if (isEditable()) {
1676 0 : FXString string;
1677 :
1678 : // First, try UTF-8
1679 0 : if (getDNDData(FROM_SELECTION, utf8Type, string)) {
1680 : FXTRACE((100, "Paste UTF8\n"));
1681 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)string.text());
1682 : return 1;
1683 : }
1684 :
1685 : // Next, try UTF-16
1686 0 : if (getDNDData(FROM_SELECTION, utf16Type, string)) {
1687 : FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
1688 : FXTRACE((100, "Paste UTF16\n"));
1689 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)unicode.mb2utf(string).text());
1690 : return 1;
1691 : }
1692 :
1693 : // Finally, try good old 8859-1
1694 0 : if (getDNDData(FROM_SELECTION, stringType, string)) {
1695 : FX88591Codec ascii;
1696 : FXTRACE((100, "Paste ASCII\n"));
1697 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)ascii.mb2utf(string).text());
1698 : return 1;
1699 : }
1700 0 : } else {
1701 0 : getApp()->beep();
1702 : }
1703 : return 1;
1704 : }
1705 :
1706 :
1707 : long
1708 0 : MFXTextFieldIcon::onCmdDeleteSel(FXObject*, FXSelector, void*) {
1709 0 : if (isEditable()) {
1710 0 : if (!hasSelection()) {
1711 : return 1;
1712 : }
1713 0 : FXint st = FXMIN(myAnchorPosition, myCursorPosition);
1714 0 : FXint en = FXMAX(myAnchorPosition, myCursorPosition);
1715 0 : setCursorPos(st);
1716 0 : setAnchorPos(st);
1717 0 : contents.erase(st, en - st);
1718 0 : layout();
1719 0 : makePositionVisible(st);
1720 0 : killSelection();
1721 0 : flags |= FLAG_CHANGED;
1722 0 : if (target) {
1723 0 : target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1724 : }
1725 : } else {
1726 0 : getApp()->beep();
1727 : }
1728 : return 1;
1729 : }
1730 :
1731 :
1732 : long
1733 0 : MFXTextFieldIcon::onCmdDeleteAll(FXObject*, FXSelector, void*) {
1734 0 : if (isEditable()) {
1735 0 : setCursorPos(0);
1736 0 : setAnchorPos(0);
1737 0 : contents.clear();
1738 0 : layout();
1739 0 : makePositionVisible(0);
1740 0 : killSelection();
1741 0 : flags |= FLAG_CHANGED;
1742 0 : if (target) {
1743 0 : target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1744 : }
1745 : } else {
1746 0 : getApp()->beep();
1747 : }
1748 0 : return 1;
1749 : }
1750 :
1751 :
1752 : long
1753 0 : MFXTextFieldIcon::onCmdOverstString(FXObject*, FXSelector, void* ptr) {
1754 0 : if (isEditable()) {
1755 0 : FXString tentative = contents;
1756 0 : FXint len = (int)strlen((FXchar*)ptr);
1757 0 : FXint reppos = myCursorPosition;
1758 : FXint replen = len;
1759 0 : if (hasSelection()) {
1760 0 : reppos = FXMIN(myAnchorPosition, myCursorPosition);
1761 0 : replen = FXMAX(myAnchorPosition, myCursorPosition) - reppos;
1762 : }
1763 0 : tentative.replace(reppos, replen, (FXchar*)ptr, len);
1764 0 : if (handle(this, FXSEL(SEL_VERIFY, 0), (void*)tentative.text())) {
1765 0 : getApp()->beep();
1766 : return 1;
1767 : }
1768 0 : setCursorPos(reppos);
1769 0 : setAnchorPos(reppos);
1770 0 : contents = tentative;
1771 0 : layout();
1772 0 : setCursorPos(reppos + len);
1773 0 : setAnchorPos(reppos + len);
1774 0 : makePositionVisible(reppos + len);
1775 0 : killSelection();
1776 0 : update(border, border, width - (border << 1), height - (border << 1));
1777 0 : flags |= FLAG_CHANGED;
1778 0 : if (target) {
1779 0 : target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1780 : }
1781 0 : } else {
1782 0 : getApp()->beep();
1783 : }
1784 : return 1;
1785 : }
1786 :
1787 :
1788 : long
1789 0 : MFXTextFieldIcon::onCmdInsertString(FXObject*, FXSelector, void* ptr) {
1790 0 : if (isEditable()) {
1791 0 : FXString tentative = contents;
1792 0 : FXint len = (int)strlen((FXchar*)ptr);
1793 0 : FXint reppos = myCursorPosition;
1794 : FXint replen = 0;
1795 0 : if (hasSelection()) {
1796 0 : reppos = FXMIN(myAnchorPosition, myCursorPosition);
1797 0 : replen = FXMAX(myAnchorPosition, myCursorPosition) - reppos;
1798 : }
1799 0 : tentative.replace(reppos, replen, (FXchar*)ptr, len);
1800 0 : if (handle(this, FXSEL(SEL_VERIFY, 0), (void*)tentative.text())) {
1801 0 : getApp()->beep();
1802 : return 1;
1803 : }
1804 0 : setCursorPos(reppos);
1805 0 : setAnchorPos(reppos);
1806 0 : contents = tentative;
1807 0 : layout();
1808 0 : setCursorPos(reppos + len);
1809 0 : setAnchorPos(reppos + len);
1810 0 : makePositionVisible(reppos + len);
1811 0 : killSelection();
1812 0 : update(border, border, width - (border << 1), height - (border << 1));
1813 0 : flags |= FLAG_CHANGED;
1814 0 : if (target) {
1815 0 : target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1816 : }
1817 0 : } else {
1818 0 : getApp()->beep();
1819 : }
1820 : return 1;
1821 : }
1822 :
1823 :
1824 :
1825 : long
1826 0 : MFXTextFieldIcon::onCmdBackspace(FXObject*, FXSelector, void*) {
1827 0 : if (isEditable() && 0 < myCursorPosition) {
1828 0 : setCursorPos(contents.dec(myCursorPosition));
1829 0 : setAnchorPos(myCursorPosition);
1830 0 : contents.erase(myCursorPosition, contents.extent(myCursorPosition));
1831 0 : layout();
1832 0 : makePositionVisible(myCursorPosition);
1833 0 : update(border, border, width - (border << 1), height - (border << 1));
1834 0 : flags |= FLAG_CHANGED;
1835 0 : if (target) {
1836 0 : target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1837 : }
1838 : } else {
1839 0 : getApp()->beep();
1840 : }
1841 0 : return 1;
1842 : }
1843 :
1844 :
1845 : long
1846 0 : MFXTextFieldIcon::onCmdDelete(FXObject*, FXSelector, void*) {
1847 0 : if (isEditable() && myCursorPosition < contents.length()) {
1848 0 : contents.erase(myCursorPosition, contents.extent(myCursorPosition));
1849 0 : layout();
1850 0 : setCursorPos(myCursorPosition);
1851 0 : setAnchorPos(myCursorPosition);
1852 0 : makePositionVisible(myCursorPosition);
1853 0 : update(border, border, width - (border << 1), height - (border << 1));
1854 0 : flags |= FLAG_CHANGED;
1855 0 : if (target) {
1856 0 : target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1857 : }
1858 : } else {
1859 0 : getApp()->beep();
1860 : }
1861 0 : return 1;
1862 : }
1863 :
1864 :
1865 : long
1866 0 : MFXTextFieldIcon::onVerify(FXObject*, FXSelector, void* ptr) {
1867 : FXchar* p = (FXchar*)ptr;
1868 :
1869 : // Limit number of myVisibleColumns
1870 0 : if (options & TEXTFIELD_LIMITED) {
1871 0 : if ((FXint)wcslen(p) > myVisibleColumns) {
1872 : return 1;
1873 : }
1874 : }
1875 :
1876 : // Integer input
1877 0 : if (options & TEXTFIELD_INTEGER) {
1878 0 : while (Ascii::isSpace(*p)) {
1879 0 : p++;
1880 : }
1881 0 : if (*p == '-' || *p == '+') {
1882 0 : p++;
1883 : }
1884 0 : while (Ascii::isDigit(*p)) {
1885 0 : p++;
1886 : }
1887 0 : while (Ascii::isSpace(*p)) {
1888 0 : p++;
1889 : }
1890 0 : if (*p != '\0') {
1891 : return 1; // Objection!
1892 : }
1893 : }
1894 :
1895 : // Real input
1896 0 : if (options & TEXTFIELD_REAL) {
1897 0 : while (Ascii::isSpace(*p)) {
1898 0 : p++;
1899 : }
1900 0 : if (*p == '-' || *p == '+') {
1901 0 : p++;
1902 : }
1903 0 : while (Ascii::isDigit(*p)) {
1904 0 : p++;
1905 : }
1906 0 : if (*p == '.') {
1907 0 : p++;
1908 : }
1909 0 : while (Ascii::isDigit(*p)) {
1910 0 : p++;
1911 : }
1912 0 : if (*p == 'E' || *p == 'e') {
1913 0 : p++;
1914 0 : if (*p == '-' || *p == '+') {
1915 0 : p++;
1916 : }
1917 0 : while (Ascii::isDigit(*p)) {
1918 0 : p++;
1919 : }
1920 : }
1921 0 : while (Ascii::isSpace(*p)) {
1922 0 : p++;
1923 : }
1924 0 : if (*p != '\0') {
1925 : return 1; // Objection!
1926 : }
1927 : }
1928 :
1929 : // Target has chance to object to the proposed change
1930 0 : if (target && target->tryHandle(this, FXSEL(SEL_VERIFY, message), ptr)) {
1931 : return 1;
1932 : }
1933 :
1934 : // No objections have been raised!
1935 : return 0;
1936 : }
1937 :
1938 :
1939 : long
1940 0 : MFXTextFieldIcon::onKeyPress(FXObject*, FXSelector, void* ptr) {
1941 : FXEvent* event = (FXEvent*)ptr;
1942 0 : flags &= ~FLAG_TIP;
1943 0 : if (isEnabled()) {
1944 : FXTRACE((200, "%s::onKeyPress keysym = 0x%04x state = %04x\n", getClassName(), event->code, event->state));
1945 0 : if (target && target->tryHandle(this, FXSEL(SEL_KEYPRESS, message), ptr)) {
1946 : return 1;
1947 : }
1948 0 : flags &= ~FLAG_UPDATE;
1949 0 : switch (event->code) {
1950 0 : case KEY_Right:
1951 : case KEY_KP_Right:
1952 0 : if (!(event->state & SHIFTMASK)) {
1953 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1954 : }
1955 0 : if (event->state & CONTROLMASK) {
1956 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_RIGHT), NULL);
1957 : } else {
1958 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_RIGHT), NULL);
1959 : }
1960 0 : if (event->state & SHIFTMASK) {
1961 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
1962 : } else {
1963 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
1964 : }
1965 0 : return 1;
1966 0 : case KEY_Left:
1967 : case KEY_KP_Left:
1968 0 : if (!(event->state & SHIFTMASK)) {
1969 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1970 : }
1971 0 : if (event->state & CONTROLMASK) {
1972 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_LEFT), NULL);
1973 : } else {
1974 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_LEFT), NULL);
1975 : }
1976 0 : if (event->state & SHIFTMASK) {
1977 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
1978 : } else {
1979 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
1980 : }
1981 0 : return 1;
1982 0 : case KEY_Home:
1983 : case KEY_KP_Home:
1984 0 : if (!(event->state & SHIFTMASK)) {
1985 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1986 : }
1987 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_HOME), NULL);
1988 0 : if (event->state & SHIFTMASK) {
1989 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
1990 : } else {
1991 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
1992 : }
1993 0 : return 1;
1994 0 : case KEY_End:
1995 : case KEY_KP_End:
1996 0 : if (!(event->state & SHIFTMASK)) {
1997 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1998 : }
1999 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_END), NULL);
2000 0 : if (event->state & SHIFTMASK) {
2001 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
2002 : } else {
2003 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
2004 : }
2005 0 : return 1;
2006 0 : case KEY_Insert:
2007 : case KEY_KP_Insert:
2008 0 : if (event->state & CONTROLMASK) {
2009 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_COPY_SEL), NULL);
2010 0 : } else if (event->state & SHIFTMASK) {
2011 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_PASTE_SEL), NULL);
2012 : } else {
2013 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_TOGGLE_OVERSTRIKE), NULL);
2014 : }
2015 0 : return 1;
2016 0 : case KEY_Delete:
2017 : case KEY_KP_Delete:
2018 0 : if (hasSelection()) {
2019 0 : if (event->state & SHIFTMASK) {
2020 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CUT_SEL), NULL);
2021 : } else {
2022 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
2023 : }
2024 : } else {
2025 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE), NULL);
2026 : }
2027 0 : return 1;
2028 0 : case KEY_BackSpace:
2029 0 : if (hasSelection()) {
2030 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
2031 : } else {
2032 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_BACKSPACE), NULL);
2033 : }
2034 0 : return 1;
2035 0 : case KEY_Return:
2036 : case KEY_KP_Enter:
2037 0 : if (isEditable()) {
2038 0 : flags |= FLAG_UPDATE;
2039 0 : flags &= ~FLAG_CHANGED;
2040 0 : if (target) {
2041 0 : target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)contents.text());
2042 : }
2043 : } else {
2044 0 : getApp()->beep();
2045 : }
2046 0 : return 1;
2047 0 : case KEY_a:
2048 0 : if (!(event->state & CONTROLMASK)) {
2049 : break;
2050 : }
2051 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_SELECT_ALL), NULL);
2052 0 : return 1;
2053 0 : case KEY_x:
2054 0 : if (!(event->state & CONTROLMASK)) {
2055 : break;
2056 : }
2057 : FALLTHROUGH;
2058 : case KEY_F20: // Sun Cut key
2059 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CUT_SEL), NULL);
2060 0 : return 1;
2061 0 : case KEY_c:
2062 0 : if (!(event->state & CONTROLMASK)) {
2063 : break;
2064 : }
2065 : FALLTHROUGH;
2066 : case KEY_F16: // Sun Copy key
2067 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_COPY_SEL), NULL);
2068 0 : return 1;
2069 0 : case KEY_v:
2070 0 : if (!(event->state & CONTROLMASK)) {
2071 : break;
2072 : }
2073 : FALLTHROUGH;
2074 : case KEY_F18: // Sun Paste key
2075 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_PASTE_SEL), NULL);
2076 0 : return 1;
2077 : default:
2078 : break;
2079 : }
2080 0 : if ((event->state & (CONTROLMASK | ALTMASK)) || ((FXuchar)event->text[0] < 32)) {
2081 : return 0;
2082 : }
2083 0 : if (isOverstrike()) {
2084 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_OVERST_STRING), (void*)event->text.text());
2085 : } else {
2086 0 : handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)event->text.text());
2087 : }
2088 0 : return 1;
2089 : }
2090 : return 0;
2091 : }
2092 :
2093 :
2094 : long
2095 0 : MFXTextFieldIcon::onKeyRelease(FXObject*, FXSelector, void* ptr) {
2096 : FXEvent* event = (FXEvent*)ptr;
2097 0 : if (isEnabled()) {
2098 : FXTRACE((200, "%s::onKeyRelease keysym = 0x%04x state = %04x\n", getClassName(), ((FXEvent*)ptr)->code, ((FXEvent*)ptr)->state));
2099 0 : if (target && target->tryHandle(this, FXSEL(SEL_KEYRELEASE, message), ptr)) {
2100 : return 1;
2101 : }
2102 0 : switch (event->code) {
2103 : case KEY_Right:
2104 : case KEY_KP_Right:
2105 : case KEY_Left:
2106 : case KEY_KP_Left:
2107 : case KEY_Home:
2108 : case KEY_KP_Home:
2109 : case KEY_End:
2110 : case KEY_KP_End:
2111 : case KEY_Insert:
2112 : case KEY_KP_Insert:
2113 : case KEY_Delete:
2114 : case KEY_KP_Delete:
2115 : case KEY_BackSpace:
2116 : case KEY_Return:
2117 : case KEY_F20: // Sun Cut key
2118 : case KEY_F16: // Sun Copy key
2119 : case KEY_F18: // Sun Paste key
2120 : return 1;
2121 0 : case KEY_a:
2122 : case KEY_x:
2123 : case KEY_c:
2124 : case KEY_v:
2125 0 : if (event->state & CONTROLMASK) {
2126 : return 1;
2127 : }
2128 : FALLTHROUGH;
2129 : default:
2130 0 : if ((event->state & (CONTROLMASK | ALTMASK)) || ((FXuchar)event->text[0] < 32)) {
2131 : return 0;
2132 : }
2133 : return 1;
2134 : }
2135 : }
2136 : return 0;
2137 : }
2138 :
2139 :
2140 : FXbool
2141 30262 : MFXTextFieldIcon::killSelection() {
2142 30262 : if (hasSelection()) {
2143 0 : releaseSelection();
2144 0 : update(border, border, width - (border << 1), height - (border << 1));
2145 0 : return TRUE;
2146 : }
2147 : return FALSE;
2148 : }
2149 :
2150 :
2151 : FXbool
2152 0 : MFXTextFieldIcon::selectAll() {
2153 0 : setAnchorPos(0);
2154 0 : setCursorPos(contents.length());
2155 0 : extendSelection(myCursorPosition);
2156 0 : return TRUE;
2157 : }
2158 :
2159 :
2160 : FXbool
2161 0 : MFXTextFieldIcon::setSelection(FXint pos, FXint len) {
2162 0 : setAnchorPos(pos);
2163 0 : setCursorPos(pos + len);
2164 0 : extendSelection(myCursorPosition);
2165 0 : return TRUE;
2166 : }
2167 :
2168 :
2169 : FXbool
2170 0 : MFXTextFieldIcon::extendSelection(FXint pos) {
2171 : FXDragType types[4];
2172 :
2173 : // Validate position to start of character
2174 0 : pos = contents.validate(FXCLAMP(0, pos, contents.length()));
2175 :
2176 : // Got a selection at all?
2177 0 : if (myAnchorPosition != pos) {
2178 0 : types[0] = stringType;
2179 0 : types[1] = textType;
2180 0 : types[2] = utf8Type;
2181 0 : types[3] = utf16Type;
2182 0 : if (!hasSelection()) {
2183 0 : acquireSelection(types, 4);
2184 : }
2185 : } else {
2186 0 : if (hasSelection()) {
2187 0 : releaseSelection();
2188 : }
2189 : }
2190 :
2191 0 : update(border, border, width - (border << 1), height - (border << 1));
2192 0 : return TRUE;
2193 : }
2194 :
2195 :
2196 : void
2197 15131 : MFXTextFieldIcon::setText(const FXString& text, FXbool notify) {
2198 15131 : killSelection();
2199 15131 : if (contents != text) {
2200 7583 : contents = text;
2201 7583 : myAnchorPosition = contents.length();
2202 7583 : myCursorPosition = contents.length();
2203 7583 : if (xid) {
2204 35 : layout();
2205 : }
2206 7583 : if (notify && target) {
2207 0 : target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)contents.text());
2208 : }
2209 : }
2210 15131 : }
2211 :
2212 :
2213 : void
2214 15131 : MFXTextFieldIcon::setIcon(FXIcon* ic) {
2215 15131 : killSelection();
2216 15131 : myIcon = ic;
2217 15131 : myAnchorPosition = contents.length();
2218 15131 : myCursorPosition = contents.length();
2219 15131 : if (xid) {
2220 35 : layout();
2221 : }
2222 15131 : }
2223 :
2224 :
2225 : FXString
2226 0 : MFXTextFieldIcon::getText() const {
2227 0 : return contents;
2228 : }
2229 :
2230 :
2231 : void
2232 0 : MFXTextFieldIcon::setTextColor(FXColor clr) {
2233 0 : if (myTextColor != clr) {
2234 0 : myTextColor = clr;
2235 0 : update();
2236 : }
2237 0 : }
2238 :
2239 :
2240 : FXColor
2241 0 : MFXTextFieldIcon::getTextColor() const {
2242 0 : return myTextColor;
2243 : }
2244 :
2245 :
2246 : void
2247 0 : MFXTextFieldIcon::setSelBackColor(FXColor clr) {
2248 0 : if (mySelectedBackgroundColor != clr) {
2249 0 : mySelectedBackgroundColor = clr;
2250 0 : update();
2251 : }
2252 0 : }
2253 :
2254 :
2255 : void
2256 0 : MFXTextFieldIcon::setSelTextColor(FXColor clr) {
2257 0 : if (mySelectedTextColor != clr) {
2258 0 : mySelectedTextColor = clr;
2259 0 : update();
2260 : }
2261 0 : }
2262 :
2263 :
2264 : FXColor
2265 0 : MFXTextFieldIcon::getSelTextColor() const {
2266 0 : return mySelectedTextColor;
2267 : }
2268 :
2269 :
2270 : void
2271 0 : MFXTextFieldIcon::setCursorColor(FXColor clr) {
2272 0 : if (clr != myCursorColor) {
2273 0 : myCursorColor = clr;
2274 0 : update();
2275 : }
2276 0 : }
2277 :
2278 :
2279 : FXColor
2280 0 : MFXTextFieldIcon::getCursorColor() const {
2281 0 : return myCursorColor;
2282 : }
2283 :
2284 :
2285 : void
2286 0 : MFXTextFieldIcon::setNumColumns(FXint ncols) {
2287 0 : if (ncols < 0) {
2288 : ncols = 0;
2289 : }
2290 0 : if (myVisibleColumns != ncols) {
2291 0 : myShiftAmount = 0;
2292 0 : myVisibleColumns = ncols;
2293 0 : layout(); // This may not be necessary!
2294 0 : recalc();
2295 0 : update();
2296 : }
2297 0 : }
2298 :
2299 :
2300 : FXint
2301 0 : MFXTextFieldIcon::getNumColumns() const {
2302 0 : return myVisibleColumns;
2303 : }
2304 :
2305 :
2306 : FXbool
2307 0 : MFXTextFieldIcon::isEditable() const {
2308 0 : return (options & TEXTFIELD_READONLY) == 0;
2309 : }
2310 :
2311 :
2312 :
2313 : void
2314 7548 : MFXTextFieldIcon::setEditable(FXbool edit) {
2315 7548 : if (edit) {
2316 0 : options &= ~TEXTFIELD_READONLY;
2317 : } else {
2318 7548 : options |= TEXTFIELD_READONLY;
2319 : }
2320 7548 : }
2321 :
2322 :
2323 :
2324 : FXbool
2325 0 : MFXTextFieldIcon::isOverstrike() const {
2326 0 : return (options & TEXTFIELD_OVERSTRIKE) != 0;
2327 : }
2328 :
2329 :
2330 :
2331 : void
2332 0 : MFXTextFieldIcon::setOverstrike(FXbool over) {
2333 0 : if (over) {
2334 0 : options |= TEXTFIELD_OVERSTRIKE;
2335 : } else {
2336 0 : options &= ~TEXTFIELD_OVERSTRIKE;
2337 : }
2338 0 : }
2339 :
2340 :
2341 : void
2342 0 : MFXTextFieldIcon::setTextStyle(FXuint style) {
2343 0 : FXuint opts = (options & ~TEXTFIELD_MASK) | (style & TEXTFIELD_MASK);
2344 0 : if (options != opts) {
2345 0 : myShiftAmount = 0;
2346 0 : options = opts;
2347 0 : recalc();
2348 0 : update();
2349 : }
2350 0 : }
2351 :
2352 :
2353 :
2354 : FXuint
2355 0 : MFXTextFieldIcon::getTextStyle() const {
2356 0 : return (options & TEXTFIELD_MASK);
2357 : }
2358 :
2359 :
2360 :
2361 : void
2362 0 : MFXTextFieldIcon::setJustify(FXuint style) {
2363 0 : FXuint opts = (options & ~JUSTIFY_MASK) | (style & JUSTIFY_MASK);
2364 0 : if (options != opts) {
2365 0 : myShiftAmount = 0;
2366 0 : options = opts;
2367 0 : recalc();
2368 0 : update();
2369 : }
2370 0 : }
2371 :
2372 :
2373 :
2374 : FXuint
2375 0 : MFXTextFieldIcon::getJustify() const {
2376 0 : return (options & JUSTIFY_MASK);
2377 : }
2378 :
2379 :
2380 : void
2381 0 : MFXTextFieldIcon::setDelimiters(const FXchar* delims) {
2382 0 : myTextDelimiter = delims;
2383 0 : }
2384 :
2385 :
2386 : const FXchar*
2387 0 : MFXTextFieldIcon::getDelimiters() const {
2388 0 : return myTextDelimiter;
2389 : }
2390 :
2391 :
2392 : void
2393 0 : MFXTextFieldIcon::setHelpText(const FXString& text) {
2394 0 : myHelpText = text;
2395 0 : }
2396 :
2397 :
2398 : const FXString&
2399 0 : MFXTextFieldIcon::getHelpText() const {
2400 0 : return myHelpText;
2401 : }
2402 :
2403 :
2404 : void
2405 0 : MFXTextFieldIcon::setTipText(const FXString& text) {
2406 0 : myTooltipText = text;
2407 0 : }
2408 :
2409 :
2410 : const FXString&
2411 0 : MFXTextFieldIcon::getTipText() const {
2412 0 : return myTooltipText;
2413 : }
2414 :
2415 :
2416 : void
2417 0 : MFXTextFieldIcon::setToolTipText(const FXString& toolTip) {
2418 0 : myToolTipText = toolTip;
2419 0 : }
2420 :
2421 :
2422 0 : MFXTextFieldIcon::MFXTextFieldIcon() {
2423 0 : flags |= FLAG_ENABLED;
2424 0 : myFont = (FXFont*) - 1L;
2425 0 : }
|