LCOV - code coverage report
Current view: top level - src/utils/foxtools - MFXTextFieldIcon.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 12.8 % 1136 145
Test Date: 2025-11-13 15:38:19 Functions: 12.4 % 129 16

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

Generated by: LCOV version 2.0-1