Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MFXTextFieldIcon.cpp
Go to the documentation of this file.
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/****************************************************************************/
18//
19/****************************************************************************/
20
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
52FXDEFMAP(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
123FXIMPLEMENT(MFXTextFieldIcon, FXFrame, MFXTextFieldIconMap, ARRAYNUMBER(MFXTextFieldIconMap))
124
125// ===========================================================================
126// member method definitions
127// ===========================================================================
128
129MFXTextFieldIcon::MFXTextFieldIcon(FXComposite* p, MFXStaticToolTip* staticToolTip, GUIIcon icon, FXObject* tgt, FXSelector sel,
130 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 myStaticToolTip(staticToolTip) {
133 // set icon
134 if (icon != GUIIcon::EMPTY) {
135 myIcon = GUIIconSubSys::getIcon(icon);
136 }
137 flags |= FLAG_ENABLED;
138 target = tgt;
139 message = sel;
140 if (!(options & JUSTIFY_RIGHT)) {
141 options |= JUSTIFY_LEFT;
142 }
143 defaultCursor = getApp()->getDefaultCursor(DEF_TEXT_CURSOR);
144 dragCursor = getApp()->getDefaultCursor(DEF_TEXT_CURSOR);
145 myFont = getApp()->getNormalFont();
146 backColor = getApp()->getBackColor();
147 myTextColor = getApp()->getForeColor();
148 mySelectedBackgroundColor = getApp()->getSelbackColor();
149 mySelectedTextColor = getApp()->getSelforeColor();
150 myCursorColor = getApp()->getForeColor();
151 myVisibleColumns = GUIDesignTextFieldNCol;
152}
153
154
156 getApp()->removeTimeout(this, FXTextField::ID_BLINK);
157 getApp()->removeTimeout(this, ID_AUTOSCROLL);
158 myFont = (FXFont*) - 1L;
159}
160
161
162void
164 FXFrame::create();
165 if (!textType) {
166 textType = getApp()->registerDragType(textTypeName);
167 }
168 if (!utf8Type) {
169 utf8Type = getApp()->registerDragType(utf8TypeName);
170 }
171 if (!utf16Type) {
172 utf16Type = getApp()->registerDragType(utf16TypeName);
173 }
174 myFont->create();
175}
176
177
178void
180 if (!fnt) {
181 fxerror("%s::setFont: NULL font specified.\n", getClassName());
182 }
183 if (myFont != fnt) {
184 myFont = fnt;
185 recalc();
186 update();
187 }
188}
189
190
191FXFont*
193 return myFont;
194}
195
196
197void
199 if (!(flags & FLAG_ENABLED)) {
200 FXFrame::enable();
201 update();
202 }
203}
204
205
206void
208 if (flags & FLAG_ENABLED) {
209 FXFrame::disable();
210 update();
211 }
212}
213
214
215FXint
217 return padleft + padright + (border << 1) + myVisibleColumns * myFont->getTextWidth("8", 1);
218}
219
220
221
222FXint
224 return padtop + padbottom + (border << 1) + myFont->getFontHeight();
225}
226
227
228long
229MFXTextFieldIcon::onUpdate(FXObject* sender, FXSelector sel, void* ptr) {
230 if (!FXFrame::onUpdate(sender, sel, ptr)) {
231 if (options & TEXTFIELD_AUTOHIDE) {
232 if (shown()) {
233 hide();
234 recalc();
235 }
236 }
237 if (options & TEXTFIELD_AUTOGRAY) {
238 disable();
239 }
240 }
241 return 1;
242}
243
244
245long
246MFXTextFieldIcon::onSelectionGained(FXObject* sender, FXSelector sel, void* ptr) {
247 FXFrame::onSelectionGained(sender, sel, ptr);
248 update();
249 return 1;
250}
251
252
253long
254MFXTextFieldIcon::onSelectionLost(FXObject* sender, FXSelector sel, void* ptr) {
255 FXFrame::onSelectionLost(sender, sel, ptr);
256 update();
257 return 1;
258}
259
260
261long
262MFXTextFieldIcon::onSelectionRequest(FXObject* sender, FXSelector sel, void* ptr) {
263 FXEvent* event = (FXEvent*)ptr;
264 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 if (FXFrame::onSelectionRequest(sender, sel, ptr)) {
274 return 1;
275 }
276
277 // Recognize the request?
278 if (event->target == stringType || event->target == textType || event->target == utf8Type || event->target == utf16Type) {
279
280 // Figure selected bytes
282 start = myAnchorPosition;
284 } else {
285 start = myCursorPosition;
287 }
288
289 // Get selected fragment
290 string = contents.mid(start, len);
291
292 // If password mode, replace by stars
293 if (options & TEXTFIELD_PASSWD) {
294 string.assign('*', string.count());
295 }
296
297 // Return text of the selection as UTF-8
298 if (event->target == utf8Type) {
299 FXTRACE((100, "Request UTF8\n"));
300 setDNDData(FROM_SELECTION, event->target, string);
301 return 1;
302 }
303
304 // Return text of the selection translated to 8859-1
305 if (event->target == stringType || event->target == textType) {
306 FX88591Codec ascii;
307 FXTRACE((100, "Request ASCII\n"));
308 setDNDData(FROM_SELECTION, event->target, ascii.utf2mb(string));
309 return 1;
310 }
311
312 // Return text of the selection translated to UTF-16
313 if (event->target == utf16Type) {
314 FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
315 FXTRACE((100, "Request UTF16\n"));
316 setDNDData(FROM_SELECTION, event->target, unicode.utf2mb(string));
317 return 1;
318 }
319 }
320 return 0;
321}
322
323
324long
325MFXTextFieldIcon::onClipboardGained(FXObject* sender, FXSelector sel, void* ptr) {
326 FXFrame::onClipboardGained(sender, sel, ptr);
327 return 1;
328}
329
330
331long
332MFXTextFieldIcon::onClipboardLost(FXObject* sender, FXSelector sel, void* ptr) {
333 FXFrame::onClipboardLost(sender, sel, ptr);
334 myClippedText.clear();
335 return 1;
336}
337
338
339
340long
341MFXTextFieldIcon::onClipboardRequest(FXObject* sender, FXSelector sel, void* ptr) {
342 FXEvent* event = (FXEvent*)ptr;
343 FXString string;
344
345 // Perhaps the target wants to supply its own data for the clipboard
346 if (FXFrame::onClipboardRequest(sender, sel, ptr)) {
347 return 1;
348 }
349
350 // Recognize the request?
351 if (event->target == stringType || event->target == textType || event->target == utf8Type || event->target == utf16Type) {
352
353 // Get myClippedText string
354 string = myClippedText;
355
356 // If password mode, replace by stars
357 if (options & TEXTFIELD_PASSWD) {
358 string.assign('*', string.count());
359 }
360
361 // Return myClippedText text as as UTF-8
362 if (event->target == utf8Type) {
363 FXTRACE((100, "Request UTF8\n"));
364 setDNDData(FROM_CLIPBOARD, event->target, string);
365 return 1;
366 }
367
368 // Return myClippedText text translated to 8859-1
369 if (event->target == stringType || event->target == textType) {
370 FX88591Codec ascii;
371 FXTRACE((100, "Request ASCII\n"));
372 setDNDData(FROM_CLIPBOARD, event->target, ascii.utf2mb(string));
373 return 1;
374 }
375
376 // Return text of the selection translated to UTF-16
377 if (event->target == utf16Type) {
378 FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
379 FXTRACE((100, "Request UTF16\n"));
380 setDNDData(FROM_CLIPBOARD, event->target, unicode.utf2mb(string));
381 return 1;
382 }
383 }
384 return 0;
385}
386
387
388long
389MFXTextFieldIcon::onBlink(FXObject*, FXSelector, void*) {
390 drawCursor(flags ^ FLAG_CARET);
391 getApp()->addTimeout(this, FXTextField::ID_BLINK, getApp()->getBlinkSpeed());
392 return 0;
393}
394
395
396long
397MFXTextFieldIcon::onFocusIn(FXObject* sender, FXSelector sel, void* ptr) {
398 FXFrame::onFocusIn(sender, sel, ptr);
399 if (isEditable()) {
400 getApp()->addTimeout(this, FXTextField::ID_BLINK, getApp()->getBlinkSpeed());
401 drawCursor(FLAG_CARET);
402 }
403 if (hasSelection()) {
404 update(border, border, width - (border << 1), height - (border << 1));
405 }
406 return 1;
407}
408
409
410long
411MFXTextFieldIcon::onFocusOut(FXObject* sender, FXSelector sel, void* ptr) {
412 FXFrame::onFocusOut(sender, sel, ptr);
413 getApp()->removeTimeout(this, FXTextField::ID_BLINK);
414 drawCursor(0);
415 if (hasSelection()) {
416 update(border, border, width - (border << 1), height - (border << 1));
417 }
418 return 1;
419}
420
421
422long
423MFXTextFieldIcon::onFocusSelf(FXObject* sender, FXSelector sel, void* ptr) {
424 if (FXFrame::onFocusSelf(sender, sel, ptr)) {
425 FXEvent* event = (FXEvent*)ptr;
426 if (event->type == SEL_KEYPRESS || event->type == SEL_KEYRELEASE) {
427 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_SELECT_ALL), NULL);
428 }
429 return 1;
430 }
431 return 0;
432}
433
434
435bool
437 return true;
438}
439
440
441void
443 FXFrame::setFocus();
444 setDefault(TRUE);
445 flags &= ~FLAG_UPDATE;
446 if (getApp()->hasInputMethod()) {
447 createComposeContext();
448 }
449}
450
451
452void
454 FXFrame::killFocus();
455 setDefault(MAYBE);
456 flags |= FLAG_UPDATE;
457 if (flags & FLAG_CHANGED) {
458 flags &= ~FLAG_CHANGED;
459 if (!(options & TEXTFIELD_ENTER_ONLY)) {
460 if (target) {
461 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)contents.text());
462 }
463 }
464 }
465 if (getApp()->hasInputMethod()) {
466 destroyComposeContext();
467 }
468}
469
470
471long
472MFXTextFieldIcon::onCmdSetHelp(FXObject*, FXSelector, void* ptr) {
473 setHelpText(*((FXString*)ptr));
474 return 1;
475}
476
477
478long
479MFXTextFieldIcon::onCmdGetHelp(FXObject*, FXSelector, void* ptr) {
480 *((FXString*)ptr) = getHelpText();
481 return 1;
482}
483
484
485long
486MFXTextFieldIcon::onCmdSetTip(FXObject*, FXSelector, void* ptr) {
487 setTipText(*((FXString*)ptr));
488 return 1;
489}
490
491
492long
493MFXTextFieldIcon::onCmdGetTip(FXObject*, FXSelector, void* ptr) {
494 *((FXString*)ptr) = getTipText();
495 return 1;
496}
497
498
499long
500MFXTextFieldIcon::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
501 if (FXWindow::onQueryTip(sender, sel, ptr)) {
502 return 1;
503 }
504 if ((flags & FLAG_TIP) && !myTooltipText.empty()) {
505 sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&myTooltipText);
506 return 1;
507 }
508 return 0;
509}
510
511
512long
513MFXTextFieldIcon::onQueryHelp(FXObject* sender, FXSelector sel, void* ptr) {
514 if (FXWindow::onQueryHelp(sender, sel, ptr)) {
515 return 1;
516 }
517 if ((flags & FLAG_HELP) && !myHelpText.empty()) {
518 sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&myHelpText);
519 return 1;
520 }
521 return 0;
522}
523
524
525long
526MFXTextFieldIcon::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
527 setText((const FXchar*)ptr);
528 return 1;
529}
530
531
532long
533MFXTextFieldIcon::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
534 setText(FXStringVal(*((FXint*)ptr)));
535 return 1;
536}
537
538
539long
540MFXTextFieldIcon::onCmdSetRealValue(FXObject*, FXSelector, void* ptr) {
541 setText(FXStringVal(*((FXdouble*)ptr)));
542 return 1;
543}
544
545
546long
547MFXTextFieldIcon::onCmdSetStringValue(FXObject*, FXSelector, void* ptr) {
548 setText(*((FXString*)ptr));
549 return 1;
550}
551
552
553long
554MFXTextFieldIcon::onCmdGetIntValue(FXObject*, FXSelector, void* ptr) {
555 *((FXint*)ptr) = FXIntVal(contents);
556 return 1;
557}
558
559
560long
561MFXTextFieldIcon::onCmdGetRealValue(FXObject*, FXSelector, void* ptr) {
562 *((FXdouble*)ptr) = FXDoubleVal(contents);
563 return 1;
564}
565
566
567long
568MFXTextFieldIcon::onCmdGetStringValue(FXObject*, FXSelector, void* ptr) {
569 *((FXString*)ptr) = getText();
570 return 1;
571}
572
573
574long
575MFXTextFieldIcon::onLeftBtnPress(FXObject*, FXSelector, void* ptr) {
576 FXEvent* ev = (FXEvent*)ptr;
577 flags &= ~FLAG_TIP;
578 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
579 if (isEnabled()) {
580 grab();
581 if (target && target->tryHandle(this, FXSEL(SEL_LEFTBUTTONPRESS, message), ptr)) {
582 return 1;
583 }
584 flags &= ~FLAG_UPDATE;
585 if (ev->click_count == 1) {
586 setCursorPos(index(ev->win_x));
587 if (ev->state & SHIFTMASK) {
589 } else {
592 }
594 flags |= FLAG_PRESSED;
595 } else {
596 setAnchorPos(0);
597 setCursorPos(contents.length());
598 extendSelection(contents.length());
600 }
601 return 1;
602 }
603 return 0;
604}
605
606
607long
608MFXTextFieldIcon::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) {
609 if (isEnabled()) {
610 ungrab();
611 flags &= ~FLAG_PRESSED;
612 if (target) {
613 target->tryHandle(this, FXSEL(SEL_LEFTBUTTONRELEASE, message), ptr);
614 }
615 return 1;
616 }
617 return 0;
618}
619
620
621long
622MFXTextFieldIcon::onMiddleBtnPress(FXObject*, FXSelector, void* ptr) {
623 FXEvent* ev = (FXEvent*)ptr;
624 flags &= ~FLAG_TIP;
625 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
626 if (isEnabled()) {
627 grab();
628 if (target && target->tryHandle(this, FXSEL(SEL_MIDDLEBUTTONPRESS, message), ptr)) {
629 return 1;
630 }
631 setCursorPos(index(ev->win_x));
634 update(border, border, width - (border << 1), height - (border << 1));
635 flags &= ~FLAG_UPDATE;
636 return 1;
637 }
638 return 0;
639}
640
641
642long
643MFXTextFieldIcon::onMiddleBtnRelease(FXObject*, FXSelector, void* ptr) {
644 if (isEnabled()) {
645 ungrab();
646 if (target && target->tryHandle(this, FXSEL(SEL_MIDDLEBUTTONRELEASE, message), ptr)) {
647 return 1;
648 }
649 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_PASTE_MIDDLE), NULL);
650 }
651 return 0;
652}
653
654
655long
656MFXTextFieldIcon::onMotion(FXObject* sender, FXSelector sel, void* ptr) {
657 // update static tooltip
658 if (myStaticToolTip) {
659 myStaticToolTip->onUpdate(sender, sel, ptr);
660 }
661 FXEvent* event = (FXEvent*)ptr;
662 FXint t;
663 if (flags & FLAG_PRESSED) {
664 if (event->win_x < (border + padleft) || (width - border - padright) < event->win_x) {
665 if (!getApp()->hasTimeout(this, ID_AUTOSCROLL)) {
666 getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
667 }
668 } else {
669 getApp()->removeTimeout(this, ID_AUTOSCROLL);
670 t = index(event->win_x);
671 if (t != myCursorPosition) {
672 drawCursor(0);
675 }
676 }
677 return 1;
678 }
679 return 0;
680}
681
682
683long
684MFXTextFieldIcon::onAutoScroll(FXObject*, FXSelector, void* ptr) {
685 FXEvent* event = (FXEvent*)ptr;
686 if (flags & FLAG_PRESSED) {
687 FXint newcursor = myCursorPosition;
688 FXint ll = border + padleft;
689 FXint rr = width - border - padright;
690 FXint ww = rr - ll;
691 FXint tw;
692
693 if (options & TEXTFIELD_PASSWD) {
694 tw = myFont->getTextWidth("*", 1) * contents.count();
695 } else {
696 tw = myFont->getTextWidth(contents.text(), contents.length());
697 }
698
699 // Text right-aligned
700 if (options & JUSTIFY_RIGHT) {
701
702 // Scroll left
703 if (event->win_x < ll) {
704 if (tw > ww) {
705 myShiftAmount += ll - event->win_x;
706 if (ww > tw - myShiftAmount) {
707 myShiftAmount = tw - ww;
708 } else {
709 getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
710 }
711 }
712 newcursor = index(ll);
713 }
714
715 // Scroll right
716 if (rr < event->win_x) {
717 if (tw > ww) {
718 myShiftAmount += rr - event->win_x;
719 if (myShiftAmount <= 0) {
720 myShiftAmount = 0;
721 } else {
722 getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
723 }
724 }
725 newcursor = index(rr);
726 }
727 }
728
729 // Text left-aligned
730 else if (options & JUSTIFY_LEFT) {
731
732 // Scroll left
733 if (event->win_x < ll) {
734 if (tw > ww) {
735 myShiftAmount += ll - event->win_x;
736 if (myShiftAmount >= 0) {
737 myShiftAmount = 0;
738 } else {
739 getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
740 }
741 }
742 newcursor = index(ll);
743 }
744
745 // Scroll right
746 if (rr < event->win_x) {
747 if (tw > ww) {
748 myShiftAmount += rr - event->win_x;
749 if (myShiftAmount + tw < ww) {
750 myShiftAmount = ww - tw;
751 } else {
752 getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
753 }
754 }
755 newcursor = index(rr);
756 }
757 } else {
758 // Text centered, Scroll left
759 if (event->win_x < ll) {
760 if (tw > ww) {
761 myShiftAmount += ll - event->win_x;
762 if (myShiftAmount > tw / 2 - ww / 2) {
763 myShiftAmount = tw / 2 - ww / 2;
764 } else {
765 getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
766 }
767 }
768 newcursor = index(ll);
769 }
770 // Scroll right
771 if (rr < event->win_x) {
772 if (tw > ww) {
773 myShiftAmount += rr - event->win_x;
774 if (myShiftAmount < (ww - ww / 2) - tw / 2) {
775 myShiftAmount = (ww - ww / 2) - tw / 2;
776 } else {
777 getApp()->addTimeout(this, ID_AUTOSCROLL, getApp()->getScrollSpeed(), event);
778 }
779 }
780 newcursor = index(rr);
781 }
782 }
783 // Extend the selection
784 if (newcursor != myCursorPosition) {
785 drawCursor(0);
786 myCursorPosition = newcursor;
788 }
789 }
790 return 1;
791}
792
793
794long
795MFXTextFieldIcon::onCmdToggleOverstrike(FXObject*, FXSelector, void*) {
797 return 1;
798}
799
800
801long
802MFXTextFieldIcon::onUpdToggleOverstrike(FXObject* sender, FXSelector, void*) {
803 sender->handle(this, isOverstrike() ? FXSEL(SEL_COMMAND, ID_CHECK) : FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
804 sender->handle(this, FXSEL(SEL_COMMAND, ID_SHOW), NULL);
805 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), NULL);
806 return 1;
807}
808
809
810long
811MFXTextFieldIcon::onCmdToggleEditable(FXObject*, FXSelector, void*) {
813 return 1;
814}
815
816
817long
818MFXTextFieldIcon::onUpdToggleEditable(FXObject* sender, FXSelector, void*) {
819 sender->handle(this, isEditable() ? FXSEL(SEL_COMMAND, ID_CHECK) : FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
820 sender->handle(this, FXSEL(SEL_COMMAND, ID_SHOW), NULL);
821 sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), NULL);
822 return 1;
823}
824
825
826long
827MFXTextFieldIcon::onUpdHaveSelection(FXObject* sender, FXSelector, void* ptr) {
828 sender->handle(this, hasSelection() ? FXSEL(SEL_COMMAND, ID_ENABLE) : FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
829 return 1;
830}
831
832
833long
834MFXTextFieldIcon::onUpdSelectAll(FXObject* sender, FXSelector, void* ptr) {
835 sender->handle(this, contents.empty() ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
836 return 1;
837}
838
839
840void
842 pos = contents.validate(FXCLAMP(0, pos, contents.length()));
843 if (myCursorPosition != pos) {
844 drawCursor(0);
845 myCursorPosition = pos;
846 if (isEditable() && hasFocus()) {
847 drawCursor(FLAG_CARET);
848 }
849 }
850}
851
852
853FXint
857
858
859void
861 myAnchorPosition = contents.validate(FXCLAMP(0, pos, contents.length()));
862}
863
864
865FXint
869
870
871void
873 FXint cl, ch, xx, xlo, xhi;
874 if ((state ^ flags) & FLAG_CARET) {
875 if (xid) {
876 FXDCWindow dc(this);
877 FXASSERT(0 <= myCursorPosition && myCursorPosition <= contents.length());
878 FXASSERT(0 <= myAnchorPosition && myAnchorPosition <= contents.length());
879 xx = coord(myCursorPosition) - 1;
880 // add myIcon spacing
881 if (myIcon) {
882 xx += ICON_SPACING + ICON_SIZE;
883 }
884 // Clip rectangle around myCursorPosition
885 xlo = FXMAX(xx - 2, border);
886 xhi = FXMIN(xx + 3, width - border);
887 // Cursor can overhang padding but not borders
888 dc.setClipRectangle(xlo, border, xhi - xlo, height - (border << 1));
889 // Draw I beam
890 if (state & FLAG_CARET) {
891 // Draw I-beam
892 dc.setForeground(myCursorColor);
893 dc.fillRectangle(xx, padtop + border, 1, height - padbottom - padtop - (border << 1));
894 dc.fillRectangle(xx - 2, padtop + border, 5, 1);
895 dc.fillRectangle(xx - 2, height - border - padbottom - 1, 5, 1);
896 } else {
897 // Erase I-beam, plus the text immediately surrounding it
898 dc.setForeground(backColor);
899 dc.fillRectangle(xx - 2, border, 5, height - (border << 1));
900 // Draw two characters before and after myCursorPosition
901 cl = ch = myCursorPosition;
902 if (0 < cl) {
903 cl = contents.dec(cl);
904 if (0 < cl) {
905 cl = contents.dec(cl);
906 }
907 }
908 if (ch < contents.length()) {
909 ch = contents.inc(ch);
910 if (ch < contents.length()) {
911 ch = contents.inc(ch);
912 }
913 }
914 drawTextRange(dc, cl, ch);
915 }
916 }
917 flags ^= FLAG_CARET;
918 }
919}
920
921
922void
924 FXint rr = width - border - padright;
925 FXint ll = border + padleft;
926 FXint ww = rr - ll;
927 FXint tw;
928 if (!xid) {
929 return;
930 }
931
932 // Figure text width
933 if (options & TEXTFIELD_PASSWD) {
934 tw = myFont->getTextWidth("*", 1) * contents.count();
935 } else {
936 tw = myFont->getTextWidth(contents.text(), contents.length());
937 }
938
939 // Constrain myShiftAmount
940 if (options & JUSTIFY_RIGHT) {
941 if (ww >= tw) {
942 myShiftAmount = 0;
943 } else if (myShiftAmount < 0) {
944 myShiftAmount = 0;
945 } else if (myShiftAmount > tw - ww) {
946 myShiftAmount = tw - ww;
947 }
948 } else if (options & JUSTIFY_LEFT) {
949 if (ww >= tw) {
950 myShiftAmount = 0;
951 } else if (myShiftAmount > 0) {
952 myShiftAmount = 0;
953 } else if (myShiftAmount < ww - tw) {
954 myShiftAmount = ww - tw;
955 }
956 } else {
957 if (ww >= tw) {
958 myShiftAmount = 0;
959 } else if (myShiftAmount > tw / 2 - ww / 2) {
960 myShiftAmount = tw / 2 - ww / 2;
961 } else if (myShiftAmount < (ww - ww / 2) - tw / 2) {
962 myShiftAmount = (ww - ww / 2) - tw / 2;
963 }
964 }
965
966 // Keep myCursorPosition in the picture if resizing field
968
969 // Always redraw
970 update();
971
972 flags &= ~(FXuint)FLAG_DIRTY;
973}
974
975
976void
978 FXint rr = width - border - padright;
979 FXint ll = border + padleft;
980 FXint ww = rr - ll;
981 FXint oldshift = myShiftAmount;
982 FXint xx;
983 if (!xid) {
984 return;
985 }
986 pos = contents.validate(FXCLAMP(0, pos, contents.length()));
987 if (options & JUSTIFY_RIGHT) {
988 if (options & TEXTFIELD_PASSWD) {
989 xx = myFont->getTextWidth("*", 1) * contents.count(pos, contents.length());
990 } else {
991 xx = myFont->getTextWidth(&contents[pos], contents.length() - pos);
992 }
993 if (myShiftAmount - xx > 0) {
994 myShiftAmount = xx;
995 } else if (myShiftAmount - xx < -ww) {
996 myShiftAmount = xx - ww;
997 }
998 } else if (options & JUSTIFY_LEFT) {
999 if (options & TEXTFIELD_PASSWD) {
1000 xx = myFont->getTextWidth("*", 1) * contents.index(pos);
1001 } else {
1002 xx = myFont->getTextWidth(contents.text(), pos);
1003 }
1004 if (myShiftAmount + xx < 0) {
1005 myShiftAmount = -xx;
1006 } else if (myShiftAmount + xx >= ww) {
1007 myShiftAmount = ww - xx;
1008 }
1009 } else {
1010 if (options & TEXTFIELD_PASSWD) {
1011 xx = myFont->getTextWidth("*", 1) * contents.index(pos) - (myFont->getTextWidth("*", 1) * contents.count()) / 2;
1012 } else {
1013 xx = myFont->getTextWidth(contents.text(), pos) - myFont->getTextWidth(contents.text(), contents.length()) / 2;
1014 }
1015 if (myShiftAmount + ww / 2 + xx < 0) {
1016 myShiftAmount = -ww / 2 - xx;
1017 } else if (myShiftAmount + ww / 2 + xx >= ww) {
1018 myShiftAmount = ww - ww / 2 - xx;
1019 }
1020 }
1021 if (myShiftAmount != oldshift) {
1022 update(border, border, width - (border << 1), height - (border << 1));
1023 }
1024}
1025
1026
1027FXint
1029 FXint rr = width - border - padright;
1030 FXint ll = border + padleft;
1031 FXint mm = (ll + rr) / 2;
1032 FXint pos, xx, cw;
1033 if (options & TEXTFIELD_PASSWD) {
1034 cw = myFont->getTextWidth("*", 1);
1035 if (options & JUSTIFY_RIGHT) {
1036 xx = rr - cw * contents.count();
1037 } else if (options & JUSTIFY_LEFT) {
1038 xx = ll;
1039 } else {
1040 xx = mm - (cw * contents.count()) / 2;
1041 }
1042 xx += myShiftAmount;
1043 pos = contents.offset((x - xx + (cw >> 1)) / cw);
1044 } else {
1045 if (options & JUSTIFY_RIGHT) {
1046 xx = rr - myFont->getTextWidth(contents.text(), contents.length());
1047 } else if (options & JUSTIFY_LEFT) {
1048 xx = ll;
1049 } else {
1050 xx = mm - myFont->getTextWidth(contents.text(), contents.length()) / 2;
1051 }
1052 xx += myShiftAmount;
1053 for (pos = 0; pos < contents.length(); pos = contents.inc(pos)) {
1054 cw = myFont->getTextWidth(&contents[pos], contents.extent(pos));
1055 if (x < (xx + (cw >> 1))) {
1056 break;
1057 }
1058 xx += cw;
1059 }
1060 }
1061 if (pos < 0) {
1062 pos = 0;
1063 }
1064 if (pos > contents.length()) {
1065 pos = contents.length();
1066 }
1067 return pos;
1068}
1069
1070
1071FXint
1073 FXint rr = width - border - padright;
1074 FXint ll = border + padleft;
1075 FXint mm = (ll + rr) / 2;
1076 FXint pos;
1077 FXASSERT(0 <= i && i <= contents.length());
1078 if (options & JUSTIFY_RIGHT) {
1079 if (options & TEXTFIELD_PASSWD) {
1080 pos = rr - myFont->getTextWidth("*", 1) * (contents.count() - contents.index(i));
1081 } else {
1082 pos = rr - myFont->getTextWidth(&contents[i], contents.length() - i);
1083 }
1084 } else if (options & JUSTIFY_LEFT) {
1085 if (options & TEXTFIELD_PASSWD) {
1086 pos = ll + myFont->getTextWidth("*", 1) * contents.index(i);
1087 } else {
1088 pos = ll + myFont->getTextWidth(contents.text(), i);
1089 }
1090 } else {
1091 if (options & TEXTFIELD_PASSWD) {
1092 pos = mm + myFont->getTextWidth("*", 1) * contents.index(i) - (myFont->getTextWidth("*", 1) * contents.count()) / 2;
1093 } else {
1094 pos = mm + myFont->getTextWidth(contents.text(), i) - myFont->getTextWidth(contents.text(), contents.length()) / 2;
1095 }
1096 }
1097 return pos + myShiftAmount;
1098}
1099
1100
1101FXbool
1103 if (0 <= pos && pos <= contents.length()) {
1104 FXint x = coord(contents.validate(pos));
1105 return border + padleft <= x && x <= width - border - padright;
1106 }
1107 return FALSE;
1108}
1109
1110
1111FXbool
1113 return hasSelection() && FXMIN(myAnchorPosition, myCursorPosition) <= pos && pos <= FXMAX(myAnchorPosition, myCursorPosition);
1114}
1115
1116
1117void
1118MFXTextFieldIcon::drawTextFragment(FXDCWindow& dc, FXint x, FXint y, FXint fm, FXint to) {
1119 x += myFont->getTextWidth(contents.text(), fm);
1120 y += myFont->getFontAscent();
1121 dc.drawText(x, y, &contents[fm], to - fm);
1122}
1123
1124
1125void
1126MFXTextFieldIcon::drawPWDTextFragment(FXDCWindow& dc, FXint x, FXint y, FXint fm, FXint to) {
1127 FXint cw = myFont->getTextWidth("*", 1);
1128 FXint i;
1129 y += myFont->getFontAscent();
1130 x += cw * contents.index(fm);
1131 for (i = fm; i < to; i = contents.inc(i), x += cw) {
1132 dc.drawText(x, y, "*", 1);
1133 }
1134}
1135
1136
1137// Draw range of text
1138void MFXTextFieldIcon::drawTextRange(FXDCWindow& dc, FXint fm, FXint to) {
1139 FXint sx, ex, xx, yy, cw, hh, ww, si, ei, lx, rx, t;
1140 FXint rr = width - border - padright;
1141 FXint ll = border + padleft;
1142 FXint mm = (ll + rr) / 2;
1143 if (to <= fm) {
1144 return;
1145 }
1146 // set font
1147 dc.setFont(myFont);
1148 // Text color
1149 dc.setForeground(myTextColor);
1150 // Height
1151 hh = myFont->getFontHeight();
1152 // Text sticks to top of field
1153 if (options & JUSTIFY_TOP) {
1154 yy = padtop + border;
1155 } else if (options & JUSTIFY_BOTTOM) {
1156 // Text sticks to bottom of field
1157 yy = height - padbottom - border - hh;
1158 } else {
1159 // Text centered in y
1160 yy = border + padtop + (height - padbottom - padtop - (border << 1) - hh) / 2;
1161 }
1163 si = myAnchorPosition;
1164 ei = myCursorPosition;
1165 } else {
1166 si = myCursorPosition;
1167 ei = myAnchorPosition;
1168 }
1169 // Password mode
1170 if (options & TEXTFIELD_PASSWD) {
1171 cw = myFont->getTextWidth("*", 1);
1172 ww = cw * contents.count();
1173 // Text sticks to right of field
1174 if (options & JUSTIFY_RIGHT) {
1175 xx = myShiftAmount + rr - ww;
1176 } else if (options & JUSTIFY_LEFT) {
1177 // Text sticks on left of field
1178 xx = myShiftAmount + ll;
1179 } else {
1180 // Text centered in field
1181 xx = myShiftAmount + mm - ww / 2;
1182 }
1183 // check if add myIcon spacing
1184 if (myIcon) {
1185 xx += ICON_SPACING + ICON_SIZE;
1186 }
1187 // Reduce to avoid drawing excessive amounts of text
1188 lx = xx + cw * contents.index(fm);
1189 rx = xx + cw * contents.index(to);
1190 while (fm < to) {
1191 if (lx + cw >= 0) {
1192 break;
1193 }
1194 lx += cw;
1195 fm = contents.inc(fm);
1196 }
1197 while (fm < to) {
1198 if (rx - cw < width) {
1199 break;
1200 }
1201 rx -= cw;
1202 to = contents.dec(to);
1203 }
1204 // Adjust selected range
1205 if (si < fm) {
1206 si = fm;
1207 }
1208 if (ei > to) {
1209 ei = to;
1210 }
1211
1212 // Nothing selected
1213 if (!hasSelection() || to <= si || ei <= fm) {
1214 drawPWDTextFragment(dc, xx, yy, fm, to);
1215 } else {
1216 // Stuff selected
1217 if (fm < si) {
1218 drawPWDTextFragment(dc, xx, yy, fm, si);
1219 } else {
1220 si = fm;
1221 }
1222 if (ei < to) {
1223 drawPWDTextFragment(dc, xx, yy, ei, to);
1224 } else {
1225 ei = to;
1226 }
1227 if (si < ei) {
1228 sx = xx + cw * contents.index(si);
1229 ex = xx + cw * contents.index(ei);
1230 if (hasFocus()) {
1231 dc.setForeground(mySelectedBackgroundColor);
1232 dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1233 dc.setForeground(mySelectedTextColor);
1234 drawPWDTextFragment(dc, xx, yy, si, ei);
1235 } else {
1236 dc.setForeground(baseColor);
1237 dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1238 dc.setForeground(myTextColor);
1239 drawPWDTextFragment(dc, xx, yy, si, ei);
1240 }
1241 }
1242 }
1243 } else {
1244 // Normal mode
1245 ww = myFont->getTextWidth(contents.text(), contents.length());
1246 // Text sticks to right of field
1247 if (options & JUSTIFY_RIGHT) {
1248 xx = myShiftAmount + rr - ww;
1249 } else if (options & JUSTIFY_LEFT) {
1250 // Text sticks on left of field
1251 xx = myShiftAmount + ll;
1252 } else {
1253 // Text centered in field
1254 xx = myShiftAmount + mm - ww / 2;
1255 }
1256 // check if add myIcon spacing
1257 if (myIcon) {
1258 xx += ICON_SPACING + ICON_SIZE;
1259 }
1260 // Reduce to avoid drawing excessive amounts of text
1261 lx = xx + myFont->getTextWidth(&contents[0], fm);
1262 rx = lx + myFont->getTextWidth(&contents[fm], to - fm);
1263 while (fm < to) {
1264 t = contents.inc(fm);
1265 cw = myFont->getTextWidth(&contents[fm], t - fm);
1266 if (lx + cw >= 0) {
1267 break;
1268 }
1269 lx += cw;
1270 fm = t;
1271 }
1272 while (fm < to) {
1273 t = contents.dec(to);
1274 cw = myFont->getTextWidth(&contents[t], to - t);
1275 if (rx - cw < width) {
1276 break;
1277 }
1278 rx -= cw;
1279 to = t;
1280 }
1281
1282 // Adjust selected range
1283 if (si < fm) {
1284 si = fm;
1285 }
1286 if (ei > to) {
1287 ei = to;
1288 }
1289
1290 // Nothing selected
1291 if (!hasSelection() || to <= si || ei <= fm) {
1292 drawTextFragment(dc, xx, yy, fm, to);
1293 } else {
1294 // Stuff selected
1295 if (fm < si) {
1296 drawTextFragment(dc, xx, yy, fm, si);
1297 } else {
1298 si = fm;
1299 }
1300 if (ei < to) {
1301 drawTextFragment(dc, xx, yy, ei, to);
1302 } else {
1303 ei = to;
1304 }
1305 if (si < ei) {
1306 sx = xx + myFont->getTextWidth(contents.text(), si);
1307 ex = xx + myFont->getTextWidth(contents.text(), ei);
1308 if (hasFocus()) {
1309 dc.setForeground(mySelectedBackgroundColor);
1310 dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1311 dc.setForeground(mySelectedTextColor);
1312 drawTextFragment(dc, xx, yy, si, ei);
1313 } else {
1314 dc.setForeground(baseColor);
1315 dc.fillRectangle(sx, padtop + border, ex - sx, height - padtop - padbottom - (border << 1));
1316 dc.setForeground(myTextColor);
1317 drawTextFragment(dc, xx, yy, si, ei);
1318 }
1319 }
1320 }
1321 }
1322}
1323
1324
1325long
1326MFXTextFieldIcon::onEnter(FXObject* sender, FXSelector sel, void* ptr) {
1327 // check if show toolTip text
1328 if (myStaticToolTip) {
1329 if (!myToolTipText.empty()) {
1330 // show toolTip text
1332 // show myTooltipText show
1334 } else if (myFont->getTextWidth(contents.text(), contents.length()) > getWidth()) {
1335 // only show myTooltipText Text if contents is bigger than textField width
1337 // show myTooltipText show
1339 }
1340 // always show myHelpText text
1342 }
1343 // continue with FXTextField function
1344 return FXFrame::onEnter(sender, sel, ptr);
1345}
1346
1347
1348long
1349MFXTextFieldIcon::onLeave(FXObject* sender, FXSelector sel, void* ptr) {
1350 // hide static toolTip
1351 if (myStaticToolTip) {
1353 }
1354 // continue with FXTextField function
1355 return FXFrame::onLeave(sender, sel, ptr);
1356}
1357
1358
1359long
1360MFXTextFieldIcon::onPaint(FXObject*, FXSelector, void* ptr) {
1361 FXEvent* ev = (FXEvent*)ptr;
1362 FXDCWindow dc(this, ev);
1363 // Draw frame
1364 drawFrame(dc, 0, 0, width, height);
1365 // Gray background if disabled