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