Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/foxtools/MFXTextFieldIcon.cpp
193905 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2006-2026 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file MFXTextFieldIcon.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Aug 2023
17
///
18
//
19
/****************************************************************************/
20
21
#include <utils/common/StdDefs.h>
22
#include <utils/gui/div/GUIDesigns.h>
23
24
#include <fxkeys.h>
25
#ifdef _MSC_VER
26
#pragma warning(push)
27
#pragma warning(disable: 4266) // mask warning about hidden member function FX::FXTextCodec::utf2mblen
28
#endif
29
#include <FX88591Codec.h>
30
#include <FXUTF16Codec.h>
31
#ifdef _MSC_VER
32
#pragma warning(pop)
33
#endif
34
35
#include "MFXStaticToolTip.h"
36
#include "MFXTextFieldIcon.h"
37
38
// ===========================================================================
39
// Macros
40
// ===========================================================================
41
42
#define JUSTIFY_MASK (JUSTIFY_HZ_APART|JUSTIFY_VT_APART)
43
#define TEXTFIELD_MASK (TEXTFIELD_PASSWD|TEXTFIELD_INTEGER|TEXTFIELD_REAL|TEXTFIELD_READONLY|TEXTFIELD_ENTER_ONLY|TEXTFIELD_LIMITED|TEXTFIELD_OVERSTRIKE|TEXTFIELD_AUTOHIDE|TEXTFIELD_AUTOGRAY)
44
#define ICON_SPACING 4 // Spacing between myIcon and label (2 + 2)
45
#define ICON_SIZE 16
46
47
// ===========================================================================
48
// FOX callback mapping
49
// ===========================================================================
50
51
// Map
52
FXDEFMAP(MFXTextFieldIcon) MFXTextFieldIconMap[] = {
53
FXMAPFUNC(SEL_CLIPBOARD_GAINED, 0, MFXTextFieldIcon::onClipboardGained),
54
FXMAPFUNC(SEL_CLIPBOARD_LOST, 0, MFXTextFieldIcon::onClipboardLost),
55
FXMAPFUNC(SEL_CLIPBOARD_REQUEST, 0, MFXTextFieldIcon::onClipboardRequest),
56
FXMAPFUNC(SEL_ENTER, 0, MFXTextFieldIcon::onEnter),
57
FXMAPFUNC(SEL_FOCUS_SELF, 0, MFXTextFieldIcon::onFocusSelf),
58
FXMAPFUNC(SEL_FOCUSIN, 0, MFXTextFieldIcon::onFocusIn),
59
FXMAPFUNC(SEL_FOCUSOUT, 0, MFXTextFieldIcon::onFocusOut),
60
FXMAPFUNC(SEL_KEYPRESS, 0, MFXTextFieldIcon::onKeyPress),
61
FXMAPFUNC(SEL_KEYRELEASE, 0, MFXTextFieldIcon::onKeyRelease),
62
FXMAPFUNC(SEL_LEAVE, 0, MFXTextFieldIcon::onLeave),
63
FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, MFXTextFieldIcon::onLeftBtnPress),
64
FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, MFXTextFieldIcon::onLeftBtnRelease),
65
FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, 0, MFXTextFieldIcon::onMiddleBtnPress),
66
FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, 0, MFXTextFieldIcon::onMiddleBtnRelease),
67
FXMAPFUNC(SEL_MOTION, 0, MFXTextFieldIcon::onMotion),
68
FXMAPFUNC(SEL_PAINT, 0, MFXTextFieldIcon::onPaint),
69
FXMAPFUNC(SEL_QUERY_HELP, 0, MFXTextFieldIcon::onQueryHelp),
70
FXMAPFUNC(SEL_QUERY_TIP, 0, MFXTextFieldIcon::onQueryTip),
71
FXMAPFUNC(SEL_SELECTION_GAINED, 0, MFXTextFieldIcon::onSelectionGained),
72
FXMAPFUNC(SEL_SELECTION_LOST, 0, MFXTextFieldIcon::onSelectionLost),
73
FXMAPFUNC(SEL_SELECTION_REQUEST, 0, MFXTextFieldIcon::onSelectionRequest),
74
FXMAPFUNC(SEL_UPDATE, 0, MFXTextFieldIcon::onUpdate),
75
FXMAPFUNC(SEL_VERIFY, 0, MFXTextFieldIcon::onVerify),
76
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_BACKSPACE, MFXTextFieldIcon::onCmdBackspace),
77
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_COPY_SEL, MFXTextFieldIcon::onCmdCopySel),
78
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_END, MFXTextFieldIcon::onCmdCursorEnd),
79
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_HOME, MFXTextFieldIcon::onCmdCursorHome),
80
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_LEFT, MFXTextFieldIcon::onCmdCursorLeft),
81
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_RIGHT, MFXTextFieldIcon::onCmdCursorRight),
82
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_END, MFXTextFieldIcon::onCmdCursorWordEnd),
83
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_LEFT, MFXTextFieldIcon::onCmdCursorWordLeft),
84
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_RIGHT, MFXTextFieldIcon::onCmdCursorWordRight),
85
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CURSOR_WORD_START, MFXTextFieldIcon::onCmdCursorWordStart),
86
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_CUT_SEL, MFXTextFieldIcon::onCmdCutSel),
87
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DELETE, MFXTextFieldIcon::onCmdDelete),
88
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DELETE_ALL, MFXTextFieldIcon::onCmdDeleteAll),
89
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DELETE_SEL, MFXTextFieldIcon::onCmdDeleteSel),
90
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_DESELECT_ALL, MFXTextFieldIcon::onCmdDeselectAll),
91
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_EXTEND, MFXTextFieldIcon::onCmdExtend),
92
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETHELPSTRING, MFXTextFieldIcon::onCmdGetHelp),
93
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETINTVALUE, MFXTextFieldIcon::onCmdGetIntValue),
94
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETREALVALUE, MFXTextFieldIcon::onCmdGetRealValue),
95
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETSTRINGVALUE, MFXTextFieldIcon::onCmdGetStringValue),
96
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_GETTIPSTRING, MFXTextFieldIcon::onCmdGetTip),
97
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_INSERT_STRING, MFXTextFieldIcon::onCmdInsertString),
98
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_MARK, MFXTextFieldIcon::onCmdMark),
99
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_OVERST_STRING, MFXTextFieldIcon::onCmdOverstString),
100
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_PASTE_MIDDLE, MFXTextFieldIcon::onCmdPasteMiddle),
101
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_PASTE_SEL, MFXTextFieldIcon::onCmdPasteSel),
102
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SELECT_ALL, MFXTextFieldIcon::onCmdSelectAll),
103
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETHELPSTRING, MFXTextFieldIcon::onCmdSetHelp),
104
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETINTVALUE, MFXTextFieldIcon::onCmdSetIntValue),
105
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETREALVALUE, MFXTextFieldIcon::onCmdSetRealValue),
106
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETSTRINGVALUE, MFXTextFieldIcon::onCmdSetStringValue),
107
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETTIPSTRING, MFXTextFieldIcon::onCmdSetTip),
108
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_SETVALUE, MFXTextFieldIcon::onCmdSetValue),
109
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_TOGGLE_EDITABLE, MFXTextFieldIcon::onCmdToggleEditable),
110
FXMAPFUNC(SEL_COMMAND, FXTextField::ID_TOGGLE_OVERSTRIKE, MFXTextFieldIcon::onCmdToggleOverstrike),
111
FXMAPFUNC(SEL_TIMEOUT, FXTextField::ID_AUTOSCROLL, MFXTextFieldIcon::onAutoScroll),
112
FXMAPFUNC(SEL_TIMEOUT, FXTextField::ID_BLINK, MFXTextFieldIcon::onBlink),
113
FXMAPFUNC(SEL_UPDATE, FXTextField::ID_COPY_SEL, MFXTextFieldIcon::onUpdHaveSelection),
114
FXMAPFUNC(SEL_UPDATE, FXTextField::ID_CUT_SEL, MFXTextFieldIcon::onUpdHaveSelection),
115
FXMAPFUNC(SEL_UPDATE, FXTextField::ID_DELETE_SEL, MFXTextFieldIcon::onUpdHaveSelection),
116
FXMAPFUNC(SEL_UPDATE, FXTextField::ID_PASTE_SEL, MFXTextFieldIcon::onUpdYes),
117
FXMAPFUNC(SEL_UPDATE, FXTextField::ID_SELECT_ALL, MFXTextFieldIcon::onUpdSelectAll),
118
FXMAPFUNC(SEL_UPDATE, FXTextField::ID_TOGGLE_EDITABLE, MFXTextFieldIcon::onUpdToggleEditable),
119
FXMAPFUNC(SEL_UPDATE, FXTextField::ID_TOGGLE_OVERSTRIKE, MFXTextFieldIcon::onUpdToggleOverstrike),
120
};
121
122
// Object implementation
123
FXIMPLEMENT(MFXTextFieldIcon, FXFrame, MFXTextFieldIconMap, ARRAYNUMBER(MFXTextFieldIconMap))
124
125
// ===========================================================================
126
// member method definitions
127
// ===========================================================================
128
129
MFXTextFieldIcon::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
155
MFXTextFieldIcon::~MFXTextFieldIcon() {
156
getApp()->removeTimeout(this, FXTextField::ID_BLINK);
157
getApp()->removeTimeout(this, ID_AUTOSCROLL);
158
myFont = (FXFont*) - 1L;
159
}
160
161
162
void
163
MFXTextFieldIcon::create() {
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
178
void
179
MFXTextFieldIcon::setFont(FXFont* fnt) {
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
191
FXFont*
192
MFXTextFieldIcon::getFont() const {
193
return myFont;
194
}
195
196
197
void
198
MFXTextFieldIcon::enable() {
199
if (!(flags & FLAG_ENABLED)) {
200
FXFrame::enable();
201
update();
202
}
203
}
204
205
206
void
207
MFXTextFieldIcon::disable() {
208
if (flags & FLAG_ENABLED) {
209
FXFrame::disable();
210
update();
211
}
212
}
213
214
215
FXint
216
MFXTextFieldIcon::getDefaultWidth() {
217
return padleft + padright + (border << 1) + myVisibleColumns * myFont->getTextWidth("8", 1);
218
}
219
220
221
222
FXint
223
MFXTextFieldIcon::getDefaultHeight() {
224
return padtop + padbottom + (border << 1) + myFont->getFontHeight();
225
}
226
227
228
long
229
MFXTextFieldIcon::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
245
long
246
MFXTextFieldIcon::onSelectionGained(FXObject* sender, FXSelector sel, void* ptr) {
247
FXFrame::onSelectionGained(sender, sel, ptr);
248
update();
249
return 1;
250
}
251
252
253
long
254
MFXTextFieldIcon::onSelectionLost(FXObject* sender, FXSelector sel, void* ptr) {
255
FXFrame::onSelectionLost(sender, sel, ptr);
256
update();
257
return 1;
258
}
259
260
261
long
262
MFXTextFieldIcon::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
281
if (myAnchorPosition < myCursorPosition) {
282
start = myAnchorPosition;
283
len = myCursorPosition - myAnchorPosition;
284
} else {
285
start = myCursorPosition;
286
len = myAnchorPosition - 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
324
long
325
MFXTextFieldIcon::onClipboardGained(FXObject* sender, FXSelector sel, void* ptr) {
326
FXFrame::onClipboardGained(sender, sel, ptr);
327
return 1;
328
}
329
330
331
long
332
MFXTextFieldIcon::onClipboardLost(FXObject* sender, FXSelector sel, void* ptr) {
333
FXFrame::onClipboardLost(sender, sel, ptr);
334
myClippedText.clear();
335
return 1;
336
}
337
338
339
340
long
341
MFXTextFieldIcon::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
388
long
389
MFXTextFieldIcon::onBlink(FXObject*, FXSelector, void*) {
390
drawCursor(flags ^ FLAG_CARET);
391
getApp()->addTimeout(this, FXTextField::ID_BLINK, getApp()->getBlinkSpeed());
392
return 0;
393
}
394
395
396
long
397
MFXTextFieldIcon::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
410
long
411
MFXTextFieldIcon::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
422
long
423
MFXTextFieldIcon::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
435
bool
436
MFXTextFieldIcon::canFocus() const {
437
return true;
438
}
439
440
441
void
442
MFXTextFieldIcon::setFocus() {
443
FXFrame::setFocus();
444
setDefault(TRUE);
445
flags &= ~FLAG_UPDATE;
446
if (getApp()->hasInputMethod()) {
447
createComposeContext();
448
}
449
}
450
451
452
void
453
MFXTextFieldIcon::killFocus() {
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
471
long
472
MFXTextFieldIcon::onCmdSetHelp(FXObject*, FXSelector, void* ptr) {
473
setHelpText(*((FXString*)ptr));
474
return 1;
475
}
476
477
478
long
479
MFXTextFieldIcon::onCmdGetHelp(FXObject*, FXSelector, void* ptr) {
480
*((FXString*)ptr) = getHelpText();
481
return 1;
482
}
483
484
485
long
486
MFXTextFieldIcon::onCmdSetTip(FXObject*, FXSelector, void* ptr) {
487
setTipText(*((FXString*)ptr));
488
return 1;
489
}
490
491
492
long
493
MFXTextFieldIcon::onCmdGetTip(FXObject*, FXSelector, void* ptr) {
494
*((FXString*)ptr) = getTipText();
495
return 1;
496
}
497
498
499
long
500
MFXTextFieldIcon::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
512
long
513
MFXTextFieldIcon::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
525
long
526
MFXTextFieldIcon::onCmdSetValue(FXObject*, FXSelector, void* ptr) {
527
setText((const FXchar*)ptr);
528
return 1;
529
}
530
531
532
long
533
MFXTextFieldIcon::onCmdSetIntValue(FXObject*, FXSelector, void* ptr) {
534
setText(FXStringVal(*((FXint*)ptr)));
535
return 1;
536
}
537
538
539
long
540
MFXTextFieldIcon::onCmdSetRealValue(FXObject*, FXSelector, void* ptr) {
541
setText(FXStringVal(*((FXdouble*)ptr)));
542
return 1;
543
}
544
545
546
long
547
MFXTextFieldIcon::onCmdSetStringValue(FXObject*, FXSelector, void* ptr) {
548
setText(*((FXString*)ptr));
549
return 1;
550
}
551
552
553
long
554
MFXTextFieldIcon::onCmdGetIntValue(FXObject*, FXSelector, void* ptr) {
555
*((FXint*)ptr) = FXIntVal(contents);
556
return 1;
557
}
558
559
560
long
561
MFXTextFieldIcon::onCmdGetRealValue(FXObject*, FXSelector, void* ptr) {
562
*((FXdouble*)ptr) = FXDoubleVal(contents);
563
return 1;
564
}
565
566
567
long
568
MFXTextFieldIcon::onCmdGetStringValue(FXObject*, FXSelector, void* ptr) {
569
*((FXString*)ptr) = getText();
570
return 1;
571
}
572
573
574
long
575
MFXTextFieldIcon::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) {
588
extendSelection(myCursorPosition);
589
} else {
590
killSelection();
591
setAnchorPos(myCursorPosition);
592
}
593
makePositionVisible(myCursorPosition);
594
flags |= FLAG_PRESSED;
595
} else {
596
setAnchorPos(0);
597
setCursorPos(contents.length());
598
extendSelection(contents.length());
599
makePositionVisible(myCursorPosition);
600
}
601
return 1;
602
}
603
return 0;
604
}
605
606
607
long
608
MFXTextFieldIcon::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
621
long
622
MFXTextFieldIcon::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));
632
setAnchorPos(myCursorPosition);
633
makePositionVisible(myCursorPosition);
634
update(border, border, width - (border << 1), height - (border << 1));
635
flags &= ~FLAG_UPDATE;
636
return 1;
637
}
638
return 0;
639
}
640
641
642
long
643
MFXTextFieldIcon::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
655
long
656
MFXTextFieldIcon::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);
673
myCursorPosition = t;
674
extendSelection(myCursorPosition);
675
}
676
}
677
return 1;
678
}
679
return 0;
680
}
681
682
683
long
684
MFXTextFieldIcon::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;
787
extendSelection(myCursorPosition);
788
}
789
}
790
return 1;
791
}
792
793
794
long
795
MFXTextFieldIcon::onCmdToggleOverstrike(FXObject*, FXSelector, void*) {
796
setOverstrike(!isOverstrike());
797
return 1;
798
}
799
800
801
long
802
MFXTextFieldIcon::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
810
long
811
MFXTextFieldIcon::onCmdToggleEditable(FXObject*, FXSelector, void*) {
812
setEditable(!isEditable());
813
return 1;
814
}
815
816
817
long
818
MFXTextFieldIcon::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
826
long
827
MFXTextFieldIcon::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
833
long
834
MFXTextFieldIcon::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
840
void
841
MFXTextFieldIcon::setCursorPos(FXint pos) {
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
853
FXint
854
MFXTextFieldIcon::getCursorPos() const {
855
return myCursorPosition;
856
}
857
858
859
void
860
MFXTextFieldIcon::setAnchorPos(FXint pos) {
861
myAnchorPosition = contents.validate(FXCLAMP(0, pos, contents.length()));
862
}
863
864
865
FXint
866
MFXTextFieldIcon::getAnchorPos() const {
867
return myAnchorPosition;
868
}
869
870
871
void
872
MFXTextFieldIcon::drawCursor(FXuint state) {
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
922
void
923
MFXTextFieldIcon::layout() {
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
967
makePositionVisible(myCursorPosition);
968
969
// Always redraw
970
update();
971
972
flags &= ~(FXuint)FLAG_DIRTY;
973
}
974
975
976
void
977
MFXTextFieldIcon::makePositionVisible(FXint pos) {
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
1027
FXint
1028
MFXTextFieldIcon::index(FXint x) const {
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
1071
FXint
1072
MFXTextFieldIcon::coord(FXint i) const {
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
1101
FXbool
1102
MFXTextFieldIcon::isPosVisible(FXint pos) const {
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
1111
FXbool
1112
MFXTextFieldIcon::isPosSelected(FXint pos) const {
1113
return hasSelection() && FXMIN(myAnchorPosition, myCursorPosition) <= pos && pos <= FXMAX(myAnchorPosition, myCursorPosition);
1114
}
1115
1116
1117
void
1118
MFXTextFieldIcon::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
1125
void
1126
MFXTextFieldIcon::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
1138
void 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
}
1162
if (myAnchorPosition < myCursorPosition) {
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
1325
long
1326
MFXTextFieldIcon::onEnter(FXObject* sender, FXSelector sel, void* ptr) {
1327
// check if show toolTip text
1328
if (myStaticToolTip) {
1329
if (!myToolTipText.empty()) {
1330
// show toolTip text
1331
setTipText(myToolTipText);
1332
// show myTooltipText show
1333
myStaticToolTip->showStaticToolTip(getTipText());
1334
} else if (myFont->getTextWidth(contents.text(), contents.length()) > getWidth()) {
1335
// only show myTooltipText Text if contents is bigger than textField width
1336
setTipText(contents);
1337
// show myTooltipText show
1338
myStaticToolTip->showStaticToolTip(getTipText());
1339
}
1340
// always show myHelpText text
1341
setHelpText(contents);
1342
}
1343
// continue with FXTextField function
1344
return FXFrame::onEnter(sender, sel, ptr);
1345
}
1346
1347
1348
long
1349
MFXTextFieldIcon::onLeave(FXObject* sender, FXSelector sel, void* ptr) {
1350
// hide static toolTip
1351
if (myStaticToolTip) {
1352
myStaticToolTip->hideStaticToolTip();
1353
}
1354
// continue with FXTextField function
1355
return FXFrame::onLeave(sender, sel, ptr);
1356
}
1357
1358
1359
long
1360
MFXTextFieldIcon::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
1396
long
1397
MFXTextFieldIcon::onCmdCursorHome(FXObject*, FXSelector, void*) {
1398
setCursorPos(0);
1399
makePositionVisible(0);
1400
return 1;
1401
}
1402
1403
1404
long
1405
MFXTextFieldIcon::onCmdCursorEnd(FXObject*, FXSelector, void*) {
1406
setCursorPos(contents.length());
1407
makePositionVisible(myCursorPosition);
1408
return 1;
1409
}
1410
1411
1412
long
1413
MFXTextFieldIcon::onCmdCursorRight(FXObject*, FXSelector, void*) {
1414
setCursorPos(contents.inc(myCursorPosition));
1415
makePositionVisible(myCursorPosition);
1416
return 1;
1417
}
1418
1419
1420
1421
long
1422
MFXTextFieldIcon::onCmdCursorLeft(FXObject*, FXSelector, void*) {
1423
setCursorPos(contents.dec(myCursorPosition));
1424
makePositionVisible(myCursorPosition);
1425
return 1;
1426
}
1427
1428
1429
static FXbool
1430
isdelimiter(const FXchar* myTextDelimiter, FXwchar w) {
1431
return w < 128 && strchr(myTextDelimiter, w); // FIXME for w >= 128
1432
}
1433
1434
1435
FXint
1436
MFXTextFieldIcon::leftWord(FXint pos) const {
1437
FXint pp = pos, p;
1438
1439
// Ensure input is valid
1440
FXASSERT(0 <= pos && pos <= contents.length());
1441
1442
// Back up until space or delimiter
1443
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
1461
FXint
1462
MFXTextFieldIcon::rightWord(FXint pos) const {
1463
FXint pp = pos;
1464
1465
// Ensure input is valid
1466
FXASSERT(0 <= pos && pos <= contents.length());
1467
1468
// Advance until space or delimiter
1469
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
1487
FXint
1488
MFXTextFieldIcon::wordStart(FXint pos) const {
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
1508
FXint
1509
MFXTextFieldIcon::wordEnd(FXint pos) const {
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
1528
long
1529
MFXTextFieldIcon::onCmdCursorWordRight(FXObject*, FXSelector, void*) {
1530
setCursorPos(rightWord(myCursorPosition));
1531
makePositionVisible(myCursorPosition);
1532
return 1;
1533
}
1534
1535
1536
long
1537
MFXTextFieldIcon::onCmdCursorWordLeft(FXObject*, FXSelector, void*) {
1538
setCursorPos(leftWord(myCursorPosition));
1539
makePositionVisible(myCursorPosition);
1540
return 1;
1541
}
1542
1543
1544
long
1545
MFXTextFieldIcon::onCmdCursorWordStart(FXObject*, FXSelector, void*) {
1546
setCursorPos(wordStart(myCursorPosition));
1547
makePositionVisible(myCursorPosition);
1548
return 1;
1549
}
1550
1551
1552
long
1553
MFXTextFieldIcon::onCmdCursorWordEnd(FXObject*, FXSelector, void*) {
1554
setCursorPos(wordEnd(myCursorPosition));
1555
makePositionVisible(myCursorPosition);
1556
return 1;
1557
}
1558
1559
1560
long
1561
MFXTextFieldIcon::onCmdMark(FXObject*, FXSelector, void*) {
1562
setAnchorPos(myCursorPosition);
1563
return 1;
1564
}
1565
1566
1567
long
1568
MFXTextFieldIcon::onCmdExtend(FXObject*, FXSelector, void*) {
1569
extendSelection(myCursorPosition);
1570
return 1;
1571
}
1572
1573
1574
long
1575
MFXTextFieldIcon::onCmdSelectAll(FXObject*, FXSelector, void*) {
1576
selectAll();
1577
makePositionVisible(myCursorPosition);
1578
return 1;
1579
}
1580
1581
1582
long
1583
MFXTextFieldIcon::onCmdDeselectAll(FXObject*, FXSelector, void*) {
1584
killSelection();
1585
return 1;
1586
}
1587
1588
1589
long
1590
MFXTextFieldIcon::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)) {
1599
if (myAnchorPosition < myCursorPosition) {
1600
myClippedText = contents.mid(myAnchorPosition, myCursorPosition - myAnchorPosition);
1601
} else {
1602
myClippedText = contents.mid(myCursorPosition, myAnchorPosition - myCursorPosition);
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
1614
long
1615
MFXTextFieldIcon::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)) {
1623
if (myAnchorPosition < myCursorPosition) {
1624
myClippedText = contents.mid(myAnchorPosition, myCursorPosition - myAnchorPosition);
1625
} else {
1626
myClippedText = contents.mid(myCursorPosition, myAnchorPosition - myCursorPosition);
1627
}
1628
}
1629
}
1630
return 1;
1631
}
1632
1633
1634
long
1635
MFXTextFieldIcon::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
1673
long
1674
MFXTextFieldIcon::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
1707
long
1708
MFXTextFieldIcon::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();
1719
makePositionVisible(st);
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
1732
long
1733
MFXTextFieldIcon::onCmdDeleteAll(FXObject*, FXSelector, void*) {
1734
if (isEditable()) {
1735
setCursorPos(0);
1736
setAnchorPos(0);
1737
contents.clear();
1738
layout();
1739
makePositionVisible(0);
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
1752
long
1753
MFXTextFieldIcon::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
1788
long
1789
MFXTextFieldIcon::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
1825
long
1826
MFXTextFieldIcon::onCmdBackspace(FXObject*, FXSelector, void*) {
1827
if (isEditable() && 0 < myCursorPosition) {
1828
setCursorPos(contents.dec(myCursorPosition));
1829
setAnchorPos(myCursorPosition);
1830
contents.erase(myCursorPosition, contents.extent(myCursorPosition));
1831
layout();
1832
makePositionVisible(myCursorPosition);
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
1845
long
1846
MFXTextFieldIcon::onCmdDelete(FXObject*, FXSelector, void*) {
1847
if (isEditable() && myCursorPosition < contents.length()) {
1848
contents.erase(myCursorPosition, contents.extent(myCursorPosition));
1849
layout();
1850
setCursorPos(myCursorPosition);
1851
setAnchorPos(myCursorPosition);
1852
makePositionVisible(myCursorPosition);
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
1865
long
1866
MFXTextFieldIcon::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
1939
long
1940
MFXTextFieldIcon::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
}
2057
FALLTHROUGH;
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
}
2065
FALLTHROUGH;
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
}
2073
FALLTHROUGH;
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
2094
long
2095
MFXTextFieldIcon::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
}
2128
FALLTHROUGH;
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
2140
FXbool
2141
MFXTextFieldIcon::killSelection() {
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
2151
FXbool
2152
MFXTextFieldIcon::selectAll() {
2153
setAnchorPos(0);
2154
setCursorPos(contents.length());
2155
extendSelection(myCursorPosition);
2156
return TRUE;
2157
}
2158
2159
2160
FXbool
2161
MFXTextFieldIcon::setSelection(FXint pos, FXint len) {
2162
setAnchorPos(pos);
2163
setCursorPos(pos + len);
2164
extendSelection(myCursorPosition);
2165
return TRUE;
2166
}
2167
2168
2169
FXbool
2170
MFXTextFieldIcon::extendSelection(FXint pos) {
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
2196
void
2197
MFXTextFieldIcon::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
2213
void
2214
MFXTextFieldIcon::setIcon(FXIcon* ic) {
2215
killSelection();
2216
myIcon = ic;
2217
myAnchorPosition = contents.length();
2218
myCursorPosition = contents.length();
2219
if (xid) {
2220
layout();
2221
}
2222
}
2223
2224
2225
FXString
2226
MFXTextFieldIcon::getText() const {
2227
return contents;
2228
}
2229
2230
2231
void
2232
MFXTextFieldIcon::setTextColor(FXColor clr) {
2233
if (myTextColor != clr) {
2234
myTextColor = clr;
2235
update();
2236
}
2237
}
2238
2239
2240
FXColor
2241
MFXTextFieldIcon::getTextColor() const {
2242
return myTextColor;
2243
}
2244
2245
2246
void
2247
MFXTextFieldIcon::setSelBackColor(FXColor clr) {
2248
if (mySelectedBackgroundColor != clr) {
2249
mySelectedBackgroundColor = clr;
2250
update();
2251
}
2252
}
2253
2254
2255
void
2256
MFXTextFieldIcon::setSelTextColor(FXColor clr) {
2257
if (mySelectedTextColor != clr) {
2258
mySelectedTextColor = clr;
2259
update();
2260
}
2261
}
2262
2263
2264
FXColor
2265
MFXTextFieldIcon::getSelTextColor() const {
2266
return mySelectedTextColor;
2267
}
2268
2269
2270
void
2271
MFXTextFieldIcon::setCursorColor(FXColor clr) {
2272
if (clr != myCursorColor) {
2273
myCursorColor = clr;
2274
update();
2275
}
2276
}
2277
2278
2279
FXColor
2280
MFXTextFieldIcon::getCursorColor() const {
2281
return myCursorColor;
2282
}
2283
2284
2285
void
2286
MFXTextFieldIcon::setNumColumns(FXint ncols) {
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
2300
FXint
2301
MFXTextFieldIcon::getNumColumns() const {
2302
return myVisibleColumns;
2303
}
2304
2305
2306
FXbool
2307
MFXTextFieldIcon::isEditable() const {
2308
return (options & TEXTFIELD_READONLY) == 0;
2309
}
2310
2311
2312
2313
void
2314
MFXTextFieldIcon::setEditable(FXbool edit) {
2315
if (edit) {
2316
options &= ~TEXTFIELD_READONLY;
2317
} else {
2318
options |= TEXTFIELD_READONLY;
2319
}
2320
}
2321
2322
2323
2324
FXbool
2325
MFXTextFieldIcon::isOverstrike() const {
2326
return (options & TEXTFIELD_OVERSTRIKE) != 0;
2327
}
2328
2329
2330
2331
void
2332
MFXTextFieldIcon::setOverstrike(FXbool over) {
2333
if (over) {
2334
options |= TEXTFIELD_OVERSTRIKE;
2335
} else {
2336
options &= ~TEXTFIELD_OVERSTRIKE;
2337
}
2338
}
2339
2340
2341
void
2342
MFXTextFieldIcon::setTextStyle(FXuint style) {
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
2354
FXuint
2355
MFXTextFieldIcon::getTextStyle() const {
2356
return (options & TEXTFIELD_MASK);
2357
}
2358
2359
2360
2361
void
2362
MFXTextFieldIcon::setJustify(FXuint style) {
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
2374
FXuint
2375
MFXTextFieldIcon::getJustify() const {
2376
return (options & JUSTIFY_MASK);
2377
}
2378
2379
2380
void
2381
MFXTextFieldIcon::setDelimiters(const FXchar* delims) {
2382
myTextDelimiter = delims;
2383
}
2384
2385
2386
const FXchar*
2387
MFXTextFieldIcon::getDelimiters() const {
2388
return myTextDelimiter;
2389
}
2390
2391
2392
void
2393
MFXTextFieldIcon::setHelpText(const FXString& text) {
2394
myHelpText = text;
2395
}
2396
2397
2398
const FXString&
2399
MFXTextFieldIcon::getHelpText() const {
2400
return myHelpText;
2401
}
2402
2403
2404
void
2405
MFXTextFieldIcon::setTipText(const FXString& text) {
2406
myTooltipText = text;
2407
}
2408
2409
2410
const FXString&
2411
MFXTextFieldIcon::getTipText() const {
2412
return myTooltipText;
2413
}
2414
2415
2416
void
2417
MFXTextFieldIcon::setToolTipText(const FXString& toolTip) {
2418
myToolTipText = toolTip;
2419
}
2420
2421
2422
MFXTextFieldIcon::MFXTextFieldIcon() {
2423
flags |= FLAG_ENABLED;
2424
myFont = (FXFont*) - 1L;
2425
}
2426
2427