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