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
1366 if (isEnabled()) {
1367 dc.setForeground(backColor);
1368 } else {
1369 dc.setForeground(baseColor);
1370 }
1371 // Draw background
1372 dc.fillRectangle(border, border, width - (border << 1), height - (border << 1));
1373 // Draw text, myClippedText against frame interior
1374 dc.setClipRectangle(border, border, width - (border << 1), height - (border << 1));
1375 drawTextRange(dc, 0, contents.length());
1376 // Draw caret
1377 if (flags & FLAG_CARET) {
1378 int xx = coord(myCursorPosition) - 1;
1379 // check if add myIcon spacing
1380 if (myIcon) {
1381 xx += ICON_SPACING + ICON_SIZE;
1382 }
1383 dc.setForeground(myCursorColor);
1384 dc.fillRectangle(xx, padtop + border, 1, height - padbottom - padtop - (border << 1));
1385 dc.fillRectangle(xx - 2, padtop + border, 5, 1);
1386 dc.fillRectangle(xx - 2, height - border - padbottom - 1, 5, 1);
1387 }
1388 // draw myIcon
1389 if (myIcon) {
1390 dc.drawIcon(myIcon, ICON_SPACING / 2, border + padtop + (height - padbottom - padtop - (border << 1) - ICON_SIZE) / 2);
1391 }
1392 return 1;
1393}
1394
1395
1396long
1397MFXTextFieldIcon::onCmdCursorHome(FXObject*, FXSelector, void*) {
1398 setCursorPos(0);
1400 return 1;
1401}
1402
1403
1404long
1405MFXTextFieldIcon::onCmdCursorEnd(FXObject*, FXSelector, void*) {
1406 setCursorPos(contents.length());
1408 return 1;
1409}
1410
1411
1412long
1413MFXTextFieldIcon::onCmdCursorRight(FXObject*, FXSelector, void*) {
1416 return 1;
1417}
1418
1419
1420
1421long
1422MFXTextFieldIcon::onCmdCursorLeft(FXObject*, FXSelector, void*) {
1425 return 1;
1426}
1427
1428
1429static FXbool
1430isdelimiter(const FXchar* myTextDelimiter, FXwchar w) {
1431 return w < 128 && strchr(myTextDelimiter, w); // FIXME for w >= 128
1432}
1433
1434
1435FXint
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 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 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 if ((pos == pp) && 0 <= (p = contents.dec(pp))) {
1454 pp = p;
1455 }
1456
1457 return pp;
1458}
1459
1460
1461FXint
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 while (pp < contents.length() && !Unicode::isSpace(contents.wc(pp)) && !isdelimiter(myTextDelimiter, contents.wc(pp))) {
1470 pp = contents.inc(pp);
1471 }
1472
1473 // Advance over run of spaces
1474 while (pp < contents.length() && Unicode::isSpace(contents.wc(pp))) {
1475 pp = contents.inc(pp);
1476 }
1477
1478 // One more in case we didn't move
1479 if ((pos == pp) && pp < contents.length()) {
1480 pp = contents.inc(pp);
1481 }
1482
1483 return pp;
1484}
1485
1486
1487FXint
1489 FXint p;
1490 FXASSERT(0 <= pos && pos <= contents.length());
1491 if (pos == contents.length() || Unicode::isSpace(contents.wc(pos))) {
1492 while (0 <= (p = contents.dec(pos)) && Unicode::isSpace(contents.wc(p))) {
1493 pos = p;
1494 }
1495 } else if (isdelimiter(myTextDelimiter, contents.wc(pos))) {
1496 while (0 <= (p = contents.dec(pos)) && isdelimiter(myTextDelimiter, contents.wc(p))) {
1497 pos = p;
1498 }
1499 } else {
1500 while (0 <= (p = contents.dec(pos)) && !isdelimiter(myTextDelimiter, contents.wc(p)) && !Unicode::isSpace(contents.wc(p))) {
1501 pos = p;
1502 }
1503 }
1504 return pos;
1505}
1506
1507
1508FXint
1510 FXASSERT(0 <= pos && pos <= contents.length());
1511 if (pos == contents.length() || Unicode::isSpace(contents.wc(pos))) {
1512 while (pos < contents.length() && Unicode::isSpace(contents.wc(pos))) {
1513 pos = contents.inc(pos);
1514 }
1515 } else if (isdelimiter(myTextDelimiter, contents.wc(pos))) {
1516 while (pos < contents.length() && isdelimiter(myTextDelimiter, contents.wc(pos))) {
1517 pos = contents.inc(pos);
1518 }
1519 } else {
1520 while (pos < contents.length() && !isdelimiter(myTextDelimiter, contents.wc(pos)) && !Unicode::isSpace(contents.wc(pos))) {
1521 pos = contents.inc(pos);
1522 }
1523 }
1524 return pos;
1525}
1526
1527
1528long
1534
1535
1536long
1542
1543
1544long
1550
1551
1552long
1553MFXTextFieldIcon::onCmdCursorWordEnd(FXObject*, FXSelector, void*) {
1556 return 1;
1557}
1558
1559
1560long
1561MFXTextFieldIcon::onCmdMark(FXObject*, FXSelector, void*) {
1563 return 1;
1564}
1565
1566
1567long
1568MFXTextFieldIcon::onCmdExtend(FXObject*, FXSelector, void*) {
1570 return 1;
1571}
1572
1573
1574long
1575MFXTextFieldIcon::onCmdSelectAll(FXObject*, FXSelector, void*) {
1576 selectAll();
1578 return 1;
1579}
1580
1581
1582long
1583MFXTextFieldIcon::onCmdDeselectAll(FXObject*, FXSelector, void*) {
1584 killSelection();
1585 return 1;
1586}
1587
1588
1589long
1590MFXTextFieldIcon::onCmdCutSel(FXObject*, FXSelector, void*) {
1591 if (isEditable()) {
1592 if (hasSelection()) {
1593 FXDragType types[4];
1594 types[0] = stringType;
1595 types[1] = textType;
1596 types[2] = utf8Type;
1597 types[3] = utf16Type;
1598 if (acquireClipboard(types, 4)) {
1601 } else {
1603 }
1604 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
1605 }
1606 }
1607 } else {
1608 getApp()->beep();
1609 }
1610 return 1;
1611}
1612
1613
1614long
1615MFXTextFieldIcon::onCmdCopySel(FXObject*, FXSelector, void*) {
1616 if (hasSelection()) {
1617 FXDragType types[4];
1618 types[0] = stringType;
1619 types[1] = textType;
1620 types[2] = utf8Type;
1621 types[3] = utf16Type;
1622 if (acquireClipboard(types, 4)) {
1625 } else {
1627 }
1628 }
1629 }
1630 return 1;
1631}
1632
1633
1634long
1635MFXTextFieldIcon::onCmdPasteSel(FXObject*, FXSelector, void*) {
1636 if (isEditable()) {
1637 FXString string;
1638
1639 // Delete existing selection
1640 if (hasSelection()) {
1641 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
1642 }
1643
1644 // First, try UTF-8
1645 if (getDNDData(FROM_CLIPBOARD, utf8Type, string)) {
1646 FXTRACE((100, "Paste UTF8\n"));
1647 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)string.text());
1648 return 1;
1649 }
1650
1651 // Next, try UTF-16
1652 if (getDNDData(FROM_CLIPBOARD, utf16Type, string)) {
1653 FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
1654 FXTRACE((100, "Paste UTF16\n"));
1655 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 if (getDNDData(FROM_CLIPBOARD, stringType, string)) {
1661 FX88591Codec ascii;
1662 FXTRACE((100, "Paste ASCII\n"));
1663 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)ascii.mb2utf(string).text());
1664 return 1;
1665 }
1666 } else {
1667 getApp()->beep();
1668 }
1669 return 1;
1670}
1671
1672
1673long
1674MFXTextFieldIcon::onCmdPasteMiddle(FXObject*, FXSelector, void*) {
1675 if (isEditable()) {
1676 FXString string;
1677
1678 // First, try UTF-8
1679 if (getDNDData(FROM_SELECTION, utf8Type, string)) {
1680 FXTRACE((100, "Paste UTF8\n"));
1681 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)string.text());
1682 return 1;
1683 }
1684
1685 // Next, try UTF-16
1686 if (getDNDData(FROM_SELECTION, utf16Type, string)) {
1687 FXUTF16LECodec unicode; // FIXME maybe other endianness for unix
1688 FXTRACE((100, "Paste UTF16\n"));
1689 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 if (getDNDData(FROM_SELECTION, stringType, string)) {
1695 FX88591Codec ascii;
1696 FXTRACE((100, "Paste ASCII\n"));
1697 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)ascii.mb2utf(string).text());
1698 return 1;
1699 }
1700 } else {
1701 getApp()->beep();
1702 }
1703 return 1;
1704}
1705
1706
1707long
1708MFXTextFieldIcon::onCmdDeleteSel(FXObject*, FXSelector, void*) {
1709 if (isEditable()) {
1710 if (!hasSelection()) {
1711 return 1;
1712 }
1713 FXint st = FXMIN(myAnchorPosition, myCursorPosition);
1714 FXint en = FXMAX(myAnchorPosition, myCursorPosition);
1715 setCursorPos(st);
1716 setAnchorPos(st);
1717 contents.erase(st, en - st);
1718 layout();
1720 killSelection();
1721 flags |= FLAG_CHANGED;
1722 if (target) {
1723 target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1724 }
1725 } else {
1726 getApp()->beep();
1727 }
1728 return 1;
1729}
1730
1731
1732long
1733MFXTextFieldIcon::onCmdDeleteAll(FXObject*, FXSelector, void*) {
1734 if (isEditable()) {
1735 setCursorPos(0);
1736 setAnchorPos(0);
1737 contents.clear();
1738 layout();
1740 killSelection();
1741 flags |= FLAG_CHANGED;
1742 if (target) {
1743 target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1744 }
1745 } else {
1746 getApp()->beep();
1747 }
1748 return 1;
1749}
1750
1751
1752long
1753MFXTextFieldIcon::onCmdOverstString(FXObject*, FXSelector, void* ptr) {
1754 if (isEditable()) {
1755 FXString tentative = contents;
1756 FXint len = (int)strlen((FXchar*)ptr);
1757 FXint reppos = myCursorPosition;
1758 FXint replen = len;
1759 if (hasSelection()) {
1760 reppos = FXMIN(myAnchorPosition, myCursorPosition);
1761 replen = FXMAX(myAnchorPosition, myCursorPosition) - reppos;
1762 }
1763 tentative.replace(reppos, replen, (FXchar*)ptr, len);
1764 if (handle(this, FXSEL(SEL_VERIFY, 0), (void*)tentative.text())) {
1765 getApp()->beep();
1766 return 1;
1767 }
1768 setCursorPos(reppos);
1769 setAnchorPos(reppos);
1770 contents = tentative;
1771 layout();
1772 setCursorPos(reppos + len);
1773 setAnchorPos(reppos + len);
1774 makePositionVisible(reppos + len);
1775 killSelection();
1776 update(border, border, width - (border << 1), height - (border << 1));
1777 flags |= FLAG_CHANGED;
1778 if (target) {
1779 target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1780 }
1781 } else {
1782 getApp()->beep();
1783 }
1784 return 1;
1785}
1786
1787
1788long
1789MFXTextFieldIcon::onCmdInsertString(FXObject*, FXSelector, void* ptr) {
1790 if (isEditable()) {
1791 FXString tentative = contents;
1792 FXint len = (int)strlen((FXchar*)ptr);
1793 FXint reppos = myCursorPosition;
1794 FXint replen = 0;
1795 if (hasSelection()) {
1796 reppos = FXMIN(myAnchorPosition, myCursorPosition);
1797 replen = FXMAX(myAnchorPosition, myCursorPosition) - reppos;
1798 }
1799 tentative.replace(reppos, replen, (FXchar*)ptr, len);
1800 if (handle(this, FXSEL(SEL_VERIFY, 0), (void*)tentative.text())) {
1801 getApp()->beep();
1802 return 1;
1803 }
1804 setCursorPos(reppos);
1805 setAnchorPos(reppos);
1806 contents = tentative;
1807 layout();
1808 setCursorPos(reppos + len);
1809 setAnchorPos(reppos + len);
1810 makePositionVisible(reppos + len);
1811 killSelection();
1812 update(border, border, width - (border << 1), height - (border << 1));
1813 flags |= FLAG_CHANGED;
1814 if (target) {
1815 target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1816 }
1817 } else {
1818 getApp()->beep();
1819 }
1820 return 1;
1821}
1822
1823
1824
1825long
1826MFXTextFieldIcon::onCmdBackspace(FXObject*, FXSelector, void*) {
1827 if (isEditable() && 0 < myCursorPosition) {
1831 layout();
1833 update(border, border, width - (border << 1), height - (border << 1));
1834 flags |= FLAG_CHANGED;
1835 if (target) {
1836 target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1837 }
1838 } else {
1839 getApp()->beep();
1840 }
1841 return 1;
1842}
1843
1844
1845long
1846MFXTextFieldIcon::onCmdDelete(FXObject*, FXSelector, void*) {
1847 if (isEditable() && myCursorPosition < contents.length()) {
1849 layout();
1853 update(border, border, width - (border << 1), height - (border << 1));
1854 flags |= FLAG_CHANGED;
1855 if (target) {
1856 target->tryHandle(this, FXSEL(SEL_CHANGED, message), (void*)contents.text());
1857 }
1858 } else {
1859 getApp()->beep();
1860 }
1861 return 1;
1862}
1863
1864
1865long
1866MFXTextFieldIcon::onVerify(FXObject*, FXSelector, void* ptr) {
1867 FXchar* p = (FXchar*)ptr;
1868
1869 // Limit number of myVisibleColumns
1870 if (options & TEXTFIELD_LIMITED) {
1871 if ((FXint)wcslen(p) > myVisibleColumns) {
1872 return 1;
1873 }
1874 }
1875
1876 // Integer input
1877 if (options & TEXTFIELD_INTEGER) {
1878 while (Ascii::isSpace(*p)) {
1879 p++;
1880 }
1881 if (*p == '-' || *p == '+') {
1882 p++;
1883 }
1884 while (Ascii::isDigit(*p)) {
1885 p++;
1886 }
1887 while (Ascii::isSpace(*p)) {
1888 p++;
1889 }
1890 if (*p != '\0') {
1891 return 1; // Objection!
1892 }
1893 }
1894
1895 // Real input
1896 if (options & TEXTFIELD_REAL) {
1897 while (Ascii::isSpace(*p)) {
1898 p++;
1899 }
1900 if (*p == '-' || *p == '+') {
1901 p++;
1902 }
1903 while (Ascii::isDigit(*p)) {
1904 p++;
1905 }
1906 if (*p == '.') {
1907 p++;
1908 }
1909 while (Ascii::isDigit(*p)) {
1910 p++;
1911 }
1912 if (*p == 'E' || *p == 'e') {
1913 p++;
1914 if (*p == '-' || *p == '+') {
1915 p++;
1916 }
1917 while (Ascii::isDigit(*p)) {
1918 p++;
1919 }
1920 }
1921 while (Ascii::isSpace(*p)) {
1922 p++;
1923 }
1924 if (*p != '\0') {
1925 return 1; // Objection!
1926 }
1927 }
1928
1929 // Target has chance to object to the proposed change
1930 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
1939long
1940MFXTextFieldIcon::onKeyPress(FXObject*, FXSelector, void* ptr) {
1941 FXEvent* event = (FXEvent*)ptr;
1942 flags &= ~FLAG_TIP;
1943 if (isEnabled()) {
1944 FXTRACE((200, "%s::onKeyPress keysym = 0x%04x state = %04x\n", getClassName(), event->code, event->state));
1945 if (target && target->tryHandle(this, FXSEL(SEL_KEYPRESS, message), ptr)) {
1946 return 1;
1947 }
1948 flags &= ~FLAG_UPDATE;
1949 switch (event->code) {
1950 case KEY_Right:
1951 case KEY_KP_Right:
1952 if (!(event->state & SHIFTMASK)) {
1953 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1954 }
1955 if (event->state & CONTROLMASK) {
1956 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_RIGHT), NULL);
1957 } else {
1958 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_RIGHT), NULL);
1959 }
1960 if (event->state & SHIFTMASK) {
1961 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
1962 } else {
1963 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
1964 }
1965 return 1;
1966 case KEY_Left:
1967 case KEY_KP_Left:
1968 if (!(event->state & SHIFTMASK)) {
1969 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1970 }
1971 if (event->state & CONTROLMASK) {
1972 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_LEFT), NULL);
1973 } else {
1974 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_LEFT), NULL);
1975 }
1976 if (event->state & SHIFTMASK) {
1977 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
1978 } else {
1979 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
1980 }
1981 return 1;
1982 case KEY_Home:
1983 case KEY_KP_Home:
1984 if (!(event->state & SHIFTMASK)) {
1985 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1986 }
1987 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_HOME), NULL);
1988 if (event->state & SHIFTMASK) {
1989 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
1990 } else {
1991 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
1992 }
1993 return 1;
1994 case KEY_End:
1995 case KEY_KP_End:
1996 if (!(event->state & SHIFTMASK)) {
1997 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DESELECT_ALL), NULL);
1998 }
1999 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CURSOR_END), NULL);
2000 if (event->state & SHIFTMASK) {
2001 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_EXTEND), NULL);
2002 } else {
2003 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_MARK), NULL);
2004 }
2005 return 1;
2006 case KEY_Insert:
2007 case KEY_KP_Insert:
2008 if (event->state & CONTROLMASK) {
2009 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_COPY_SEL), NULL);
2010 } else if (event->state & SHIFTMASK) {
2011 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_PASTE_SEL), NULL);
2012 } else {
2013 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_TOGGLE_OVERSTRIKE), NULL);
2014 }
2015 return 1;
2016 case KEY_Delete:
2017 case KEY_KP_Delete:
2018 if (hasSelection()) {
2019 if (event->state & SHIFTMASK) {
2020 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CUT_SEL), NULL);
2021 } else {
2022 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
2023 }
2024 } else {
2025 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE), NULL);
2026 }
2027 return 1;
2028 case KEY_BackSpace:
2029 if (hasSelection()) {
2030 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_DELETE_SEL), NULL);
2031 } else {
2032 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_BACKSPACE), NULL);
2033 }
2034 return 1;
2035 case KEY_Return:
2036 case KEY_KP_Enter:
2037 if (isEditable()) {
2038 flags |= FLAG_UPDATE;
2039 flags &= ~FLAG_CHANGED;
2040 if (target) {
2041 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)contents.text());
2042 }
2043 } else {
2044 getApp()->beep();
2045 }
2046 return 1;
2047 case KEY_a:
2048 if (!(event->state & CONTROLMASK)) {
2049 break;
2050 }
2051 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_SELECT_ALL), NULL);
2052 return 1;
2053 case KEY_x:
2054 if (!(event->state & CONTROLMASK)) {
2055 break;
2056 }
2058 case KEY_F20: // Sun Cut key
2059 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_CUT_SEL), NULL);
2060 return 1;
2061 case KEY_c:
2062 if (!(event->state & CONTROLMASK)) {
2063 break;
2064 }
2066 case KEY_F16: // Sun Copy key
2067 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_COPY_SEL), NULL);
2068 return 1;
2069 case KEY_v:
2070 if (!(event->state & CONTROLMASK)) {
2071 break;
2072 }
2074 case KEY_F18: // Sun Paste key
2075 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_PASTE_SEL), NULL);
2076 return 1;
2077 default:
2078 break;
2079 }
2080 if ((event->state & (CONTROLMASK | ALTMASK)) || ((FXuchar)event->text[0] < 32)) {
2081 return 0;
2082 }
2083 if (isOverstrike()) {
2084 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_OVERST_STRING), (void*)event->text.text());
2085 } else {
2086 handle(this, FXSEL(SEL_COMMAND, FXTextField::ID_INSERT_STRING), (void*)event->text.text());
2087 }
2088 return 1;
2089 }
2090 return 0;
2091}
2092
2093
2094long
2095MFXTextFieldIcon::onKeyRelease(FXObject*, FXSelector, void* ptr) {
2096 FXEvent* event = (FXEvent*)ptr;
2097 if (isEnabled()) {
2098 FXTRACE((200, "%s::onKeyRelease keysym = 0x%04x state = %04x\n", getClassName(), ((FXEvent*)ptr)->code, ((FXEvent*)ptr)->state));
2099 if (target && target->tryHandle(this, FXSEL(SEL_KEYRELEASE, message), ptr)) {
2100 return 1;
2101 }
2102 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 case KEY_a:
2122 case KEY_x:
2123 case KEY_c:
2124 case KEY_v:
2125 if (event->state & CONTROLMASK) {
2126 return 1;
2127 }
2129 default:
2130 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
2140FXbool
2142 if (hasSelection()) {
2143 releaseSelection();
2144 update(border, border, width - (border << 1), height - (border << 1));
2145 return TRUE;
2146 }
2147 return FALSE;
2148}
2149
2150
2151FXbool
2153 setAnchorPos(0);
2154 setCursorPos(contents.length());
2156 return TRUE;
2157}
2158
2159
2160FXbool
2161MFXTextFieldIcon::setSelection(FXint pos, FXint len) {
2162 setAnchorPos(pos);
2163 setCursorPos(pos + len);
2165 return TRUE;
2166}
2167
2168
2169FXbool
2171 FXDragType types[4];
2172
2173 // Validate position to start of character
2174 pos = contents.validate(FXCLAMP(0, pos, contents.length()));
2175
2176 // Got a selection at all?
2177 if (myAnchorPosition != pos) {
2178 types[0] = stringType;
2179 types[1] = textType;
2180 types[2] = utf8Type;
2181 types[3] = utf16Type;
2182 if (!hasSelection()) {
2183 acquireSelection(types, 4);
2184 }
2185 } else {
2186 if (hasSelection()) {
2187 releaseSelection();
2188 }
2189 }
2190
2191 update(border, border, width - (border << 1), height - (border << 1));
2192 return TRUE;
2193}
2194
2195
2196void
2197MFXTextFieldIcon::setText(const FXString& text, FXbool notify) {
2198 killSelection();
2199 if (contents != text) {
2200 contents = text;
2201 myAnchorPosition = contents.length();
2202 myCursorPosition = contents.length();
2203 if (xid) {
2204 layout();
2205 }
2206 if (notify && target) {
2207 target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)contents.text());
2208 }
2209 }
2210}
2211
2212
2213void
2215 killSelection();
2216 myIcon = ic;
2217 myAnchorPosition = contents.length();
2218 myCursorPosition = contents.length();
2219 if (xid) {
2220 layout();
2221 }
2222}
2223
2224
2225FXString
2227 return contents;
2228}
2229
2230
2231void
2233 if (myTextColor != clr) {
2234 myTextColor = clr;
2235 update();
2236 }
2237}
2238
2239
2240FXColor
2242 return myTextColor;
2243}
2244
2245
2246void
2248 if (mySelectedBackgroundColor != clr) {
2250 update();
2251 }
2252}
2253
2254
2255void
2257 if (mySelectedTextColor != clr) {
2258 mySelectedTextColor = clr;
2259 update();
2260 }
2261}
2262
2263
2264FXColor
2268
2269
2270void
2272 if (clr != myCursorColor) {
2273 myCursorColor = clr;
2274 update();
2275 }
2276}
2277
2278
2279FXColor
2283
2284
2285void
2287 if (ncols < 0) {
2288 ncols = 0;
2289 }
2290 if (myVisibleColumns != ncols) {
2291 myShiftAmount = 0;
2292 myVisibleColumns = ncols;
2293 layout(); // This may not be necessary!
2294 recalc();
2295 update();
2296 }
2297}
2298
2299
2300FXint
2304
2305
2306FXbool
2308 return (options & TEXTFIELD_READONLY) == 0;
2309}
2310
2311
2312
2313void
2315 if (edit) {
2316 options &= ~TEXTFIELD_READONLY;
2317 } else {
2318 options |= TEXTFIELD_READONLY;
2319 }
2320}
2321
2322
2323
2324FXbool
2326 return (options & TEXTFIELD_OVERSTRIKE) != 0;
2327}
2328
2329
2330
2331void
2333 if (over) {
2334 options |= TEXTFIELD_OVERSTRIKE;
2335 } else {
2336 options &= ~TEXTFIELD_OVERSTRIKE;
2337 }
2338}
2339
2340
2341void
2343 FXuint opts = (options & ~TEXTFIELD_MASK) | (style & TEXTFIELD_MASK);
2344 if (options != opts) {
2345 myShiftAmount = 0;
2346 options = opts;
2347 recalc();
2348 update();
2349 }
2350}
2351
2352
2353
2354FXuint
2356 return (options & TEXTFIELD_MASK);
2357}
2358
2359
2360
2361void
2363 FXuint opts = (options & ~JUSTIFY_MASK) | (style & JUSTIFY_MASK);
2364 if (options != opts) {
2365 myShiftAmount = 0;
2366 options = opts;
2367 recalc();
2368 update();
2369 }
2370}
2371
2372
2373
2374FXuint
2376 return (options & JUSTIFY_MASK);
2377}
2378
2379
2380void
2381MFXTextFieldIcon::setDelimiters(const FXchar* delims) {
2382 myTextDelimiter = delims;
2383}
2384
2385
2386const FXchar*
2390
2391
2392void
2393MFXTextFieldIcon::setHelpText(const FXString& text) {
2394 myHelpText = text;
2395}
2396
2397
2398const FXString&
2400 return myHelpText;
2401}
2402
2403
2404void
2405MFXTextFieldIcon::setTipText(const FXString& text) {
2406 myTooltipText = text;
2407}
2408
2409
2410const FXString&
2412 return myTooltipText;
2413}
2414
2415
2416void
2417MFXTextFieldIcon::setToolTipText(const FXString& toolTip) {
2418 myToolTipText = toolTip;
2419}
2420
2421
2423 flags |= FLAG_ENABLED;
2424 myFont = (FXFont*) - 1L;
2425}
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition GUIDesigns.h:92
GUIIcon
An enumeration of icons used by the gui applications.
Definition GUIIcons.h:33
@ KEY_a
@ KEY_c
@ KEY_x
@ KEY_v
#define ICON_SPACING
#define ICON_SIZE
static FXbool isdelimiter(const FXchar *myTextDelimiter, FXwchar w)
FXDEFMAP(MFXTextFieldIcon) MFXTextFieldIconMap[]
#define JUSTIFY_MASK
#define TEXTFIELD_MASK
#define FALLTHROUGH
Definition StdDefs.h:39
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
MFXStaticToolTip (based on FXToolTip)
long onUpdate(FXObject *sender, FXSelector sel, void *ptr)
called when tooltip is updated
void showStaticToolTip(const FXString &toolTipText)
show static toolTip
void hideStaticToolTip()
hide static toolTip
FXint myShiftAmount
Shift amount.
void setToolTipText(const FXString &toolTip)
set toolTip
FXString contents
Edited text.
FXIcon * myIcon
myIcon
long onCmdOverstString(FXObject *, FXSelector, void *)
virtual void disable()
Disable text field.
FXint coord(FXint i) const
coordinates
long onCmdSelectAll(FXObject *, FXSelector, void *)
long onCmdGetStringValue(FXObject *, FXSelector, void *)
FXint myAnchorPosition
Anchor position.
void setCursorColor(FXColor clr)
Changes the cursor color.
void setSelTextColor(FXColor clr)
Change selected text color.
virtual void setFocus()
Move the focus to this window.
void setOverstrike(FXbool over=TRUE)
Set overstrike mode.
long onLeftBtnRelease(FXObject *, FXSelector, void *)
long onCmdGetRealValue(FXObject *, FXSelector, void *)
FXString myTooltipText
Tooltip.
long onCmdGetHelp(FXObject *, FXSelector, void *)
long onBlink(FXObject *, FXSelector, void *)
long onCmdCursorHome(FXObject *, FXSelector, void *)
long onCmdCursorWordStart(FXObject *, FXSelector, void *)
FXString myClippedText
Clipped text.
long onLeave(FXObject *, FXSelector, void *)
const FXString & getTipText() const
Get the tool tip message for this text field.
long onKeyPress(FXObject *, FXSelector, void *)
FXint getCursorPos() const
Return cursor position.
FXFont * myFont
Text font.
FXint myVisibleColumns
Number of myVisibleColumns visible.
FXString myHelpText
Help string.
long onFocusIn(FXObject *, FXSelector, void *)
virtual void killFocus()
Remove the focus from this window.
long onCmdSetTip(FXObject *, FXSelector, void *)
FXint wordStart(FXint pos) const
word start
long onCmdToggleOverstrike(FXObject *, FXSelector, void *)
void drawPWDTextFragment(FXDCWindow &dc, FXint x, FXint y, FXint fm, FXint to)
draw password text fragment
virtual void enable()
Enable text field.
long onClipboardGained(FXObject *, FXSelector, void *)
long onLeftBtnPress(FXObject *, FXSelector, void *)
long onFocusOut(FXObject *, FXSelector, void *)
virtual FXint getDefaultWidth()
Return default width.
long onAutoScroll(FXObject *, FXSelector, void *)
MFXTextFieldIcon()
FOX need this.
void drawTextFragment(FXDCWindow &dc, FXint x, FXint y, FXint fm, FXint to)
draw text fragment
FXbool killSelection()
Unselect the text.
long onCmdPasteSel(FXObject *, FXSelector, void *)
long onQueryTip(FXObject *, FXSelector, void *)
long onCmdCopySel(FXObject *, FXSelector, void *)
void makePositionVisible(FXint pos)
Scroll text to make the given position visible.
void setSelBackColor(FXColor clr)
Change selected background color.
long onUpdToggleOverstrike(FXObject *, FXSelector, void *)
long onVerify(FXObject *, FXSelector, void *)
FXint leftWord(FXint pos) const
left word
long onCmdCursorLeft(FXObject *, FXSelector, void *)
FXint myCursorPosition
Cursor position.
MFXStaticToolTip * myStaticToolTip
static tooltip
long onCmdExtend(FXObject *, FXSelector, void *)
void drawTextRange(FXDCWindow &dc, FXint fm, FXint to)
draw text range
FXbool setSelection(FXint pos, FXint len)
Select len characters starting at given position pos.
long onMiddleBtnRelease(FXObject *, FXSelector, void *)
const FXchar * myTextDelimiter
Set of text delimiter.
long onCmdCursorWordEnd(FXObject *, FXSelector, void *)
void drawCursor(FXuint state)
draw myCursorPosition
void setAnchorPos(FXint pos)
Change anchor position.
FXColor getTextColor() const
Return text color.
long onKeyRelease(FXObject *, FXSelector, void *)
long onSelectionRequest(FXObject *, FXSelector, void *ptr)
long onCmdDelete(FXObject *, FXSelector, void *)
FXColor myCursorColor
Color of the Cursor.
long onCmdDeleteSel(FXObject *, FXSelector, void *)
long onClipboardLost(FXObject *, FXSelector, void *)
long onCmdSetRealValue(FXObject *, FXSelector, void *)
long onCmdCursorEnd(FXObject *, FXSelector, void *)
virtual bool canFocus() const
Yes, text field may receive focus.
long onCmdSetValue(FXObject *, FXSelector, void *)
void setCursorPos(FXint pos)
Set cursor position.
void setFont(FXFont *fnt)
Set the text font.
long onUpdate(FXObject *, FXSelector, void *)
FXbool extendSelection(FXint pos)
Extend the selection from the anchor to the given position.
FXString getText() const
Get the text for this label.
FXColor mySelectedBackgroundColor
Selected background color.
long onUpdSelectAll(FXObject *, FXSelector, void *)
FXint index(FXint x) const
index
long onCmdPasteMiddle(FXObject *, FXSelector, void *)
long onCmdCursorWordLeft(FXObject *, FXSelector, void *)
void setEditable(FXbool edit=TRUE)
Set editable mode.
long onCmdSetStringValue(FXObject *, FXSelector, void *)
long onMotion(FXObject *, FXSelector, void *)
virtual FXint getDefaultHeight()
Return default height.
long onCmdCutSel(FXObject *, FXSelector, void *)
FXColor myTextColor
Text color.
long onFocusSelf(FXObject *, FXSelector, void *)
void setJustify(FXuint mode)
Change text justification mode.
FXuint getTextStyle() const
Return text style.
virtual ~MFXTextFieldIcon()
Destructor.
long onSelectionGained(FXObject *, FXSelector, void *)
long onCmdDeselectAll(FXObject *, FXSelector, void *)
FXbool isPosVisible(FXint pos) const
Return TRUE if position is fully visible.
FXint getAnchorPos() const
Return anchor position.
long onUpdToggleEditable(FXObject *, FXSelector, void *)
long onEnter(FXObject *, FXSelector, void *)
fox callbacks
FXbool selectAll()
Select all text.
void setNumColumns(FXint cols)
Change the default width of the text field.
FXint rightWord(FXint pos) const
right word
long onCmdGetTip(FXObject *, FXSelector, void *)
long onClipboardRequest(FXObject *, FXSelector, void *)
void setTextColor(FXColor clr)
Change text color.
long onSelectionLost(FXObject *, FXSelector, void *)
FXint getNumColumns() const
Return number of columns.
long onCmdToggleEditable(FXObject *, FXSelector, void *)
long onCmdSetHelp(FXObject *, FXSelector, void *)
long onCmdInsertString(FXObject *, FXSelector, void *)
FXFont * getFont() const
Get the text font.
long onPaint(FXObject *, FXSelector, void *)
long onCmdDeleteAll(FXObject *, FXSelector, void *)
const FXString & getHelpText() const
Get the status line help text for this label.
const FXchar * getDelimiters() const
Return word delimiters.
long onUpdHaveSelection(FXObject *, FXSelector, void *)
void setHelpText(const FXString &text)
Set the status line help text for this label.
FXbool isEditable() const
Return TRUE if text field may be edited.
long onQueryHelp(FXObject *, FXSelector, void *)
void setIcon(FXIcon *ic)
Change the icon.
void setDelimiters(const FXchar *delims=FXTextField::textDelimiters)
Change word delimiters.
FXString myToolTipText
toolTip text (if set, tooltip will be always show)
long onCmdSetIntValue(FXObject *, FXSelector, void *)
void setTextStyle(FXuint style)
Change text style.
FXColor getSelTextColor() const
Return selected text color.
FXColor mySelectedTextColor
Selected text color.
long onCmdCursorRight(FXObject *, FXSelector, void *)
FXColor getCursorColor() const
Return the cursor color.
void setTipText(const FXString &text)
Set the tool tip message for this text field.
FXint wordEnd(FXint pos) const
word end
long onMiddleBtnPress(FXObject *, FXSelector, void *)
virtual void create()
Create server-side resources.
virtual void layout()
Perform layout.
FXbool isPosSelected(FXint pos) const
Return TRUE if position pos is selected.
void setText(const FXString &text, FXbool notify=FALSE)
Change the text and move cursor to end.
long onCmdGetIntValue(FXObject *, FXSelector, void *)
long onCmdBackspace(FXObject *, FXSelector, void *)
FXbool isOverstrike() const
Return TRUE if overstrike mode in effect.
long onCmdCursorWordRight(FXObject *, FXSelector, void *)
FXuint getJustify() const
Return text justification mode.
long onCmdMark(FXObject *, FXSelector, void *)