LCOV - code coverage report
Current view: top level - src/utils/foxtools - MFXTextFieldIcon.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 142 1100 12.9 %
Date: 2024-04-27 15:34:54 Functions: 16 114 14.0 %

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

Generated by: LCOV version 1.14