LCOV - code coverage report
Current view: top level - src/utils/foxtools - MFXTextFieldIcon.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 13.1 % 1107 145
Test Date: 2024-11-22 15:46:21 Functions: 14.0 % 114 16

            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       595197 : FXIMPLEMENT(MFXTextFieldIcon, FXFrame, MFXTextFieldIconMap, ARRAYNUMBER(MFXTextFieldIconMap))
     120              : 
     121              : // ===========================================================================
     122              : // member method definitions
     123              : // ===========================================================================
     124              : 
     125         7106 : MFXTextFieldIcon::MFXTextFieldIcon(FXComposite* p, FXint ncols, FXIcon* ic, FXObject* tgt, FXSelector sel,
     126         7106 :                                    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         7106 :     icon(ic) {
     129         7106 :     if (ncols < 0) {
     130              :         ncols = 0;
     131              :     }
     132         7106 :     flags |= FLAG_ENABLED;
     133         7106 :     target = tgt;
     134         7106 :     message = sel;
     135         7106 :     if (!(options & JUSTIFY_RIGHT)) {
     136         7106 :         options |= JUSTIFY_LEFT;
     137              :     }
     138         7106 :     defaultCursor = getApp()->getDefaultCursor(DEF_TEXT_CURSOR);
     139         7106 :     dragCursor = getApp()->getDefaultCursor(DEF_TEXT_CURSOR);
     140         7106 :     font = getApp()->getNormalFont();
     141         7106 :     backColor = getApp()->getBackColor();
     142         7106 :     textColor = getApp()->getForeColor();
     143         7106 :     selbackColor = getApp()->getSelbackColor();
     144         7106 :     seltextColor = getApp()->getSelforeColor();
     145         7106 :     cursorColor = getApp()->getForeColor();
     146         7106 :     columns = ncols;
     147         7106 : }
     148              : 
     149              : 
     150        14186 : MFXTextFieldIcon::~MFXTextFieldIcon() {
     151         7093 :     getApp()->removeTimeout(this, FXTextField::ID_BLINK);
     152         7093 :     getApp()->removeTimeout(this, ID_AUTOSCROLL);
     153         7093 :     font = (FXFont*) - 1L;
     154        14186 : }
     155              : 
     156              : 
     157              : void
     158        14212 : MFXTextFieldIcon::create() {
     159        14212 :     FXFrame::create();
     160        14212 :     if (!textType) {
     161            0 :         textType = getApp()->registerDragType(textTypeName);
     162              :     }
     163        14212 :     if (!utf8Type) {
     164            0 :         utf8Type = getApp()->registerDragType(utf8TypeName);
     165              :     }
     166        14212 :     if (!utf16Type) {
     167            0 :         utf16Type = getApp()->registerDragType(utf16TypeName);
     168              :     }
     169        14212 :     font->create();
     170        14212 : }
     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        13684 : MFXTextFieldIcon::getDefaultWidth() {
     206        13684 :     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       562755 : MFXTextFieldIcon::onUpdate(FXObject* sender, FXSelector sel, void* ptr) {
     219       562755 :     if (!FXFrame::onUpdate(sender, sel, ptr)) {
     220       562755 :         if (options & TEXTFIELD_AUTOHIDE) {
     221            0 :             if (shown()) {
     222            0 :                 hide();
     223            0 :                 recalc();
     224              :             }
     225              :         }
     226       562755 :         if (options & TEXTFIELD_AUTOGRAY) {
     227            0 :             disable();
     228              :         }
     229              :     }
     230       562755 :     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         6906 : MFXTextFieldIcon::layout() {
     897         6906 :     FXint rr = width - border - padright;
     898         6906 :     FXint ll = border + padleft;
     899         6906 :     FXint ww = rr - ll;
     900              :     FXint tw;
     901         6906 :     if (!xid) {
     902              :         return;
     903              :     }
     904              : 
     905              :     // Figure text width
     906         6906 :     if (options & TEXTFIELD_PASSWD) {
     907            0 :         tw = font->getTextWidth("*", 1) * contents.count();
     908              :     } else {
     909         6906 :         tw = font->getTextWidth(contents.text(), contents.length());
     910              :     }
     911              : 
     912              :     // Constrain shift
     913         6906 :     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         6906 :     } else if (options & JUSTIFY_LEFT) {
     922         6906 :         if (ww >= tw) {
     923         6844 :             shift = 0;
     924           62 :         } else if (shift > 0) {
     925            0 :             shift = 0;
     926           62 :         } 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         6906 :     makePositionVisible(cursor);
     941              : 
     942              :     // Always redraw
     943         6906 :     update();
     944              : 
     945         6906 :     flags &= ~(FXuint)FLAG_DIRTY;
     946              : }
     947              : 
     948              : 
     949              : void
     950         6906 : MFXTextFieldIcon::makePositionVisible(FXint pos) {
     951         6906 :     FXint rr = width - border - padright;
     952         6906 :     FXint ll = border + padleft;
     953         6906 :     FXint ww = rr - ll;
     954         6906 :     FXint oldshift = shift;
     955              :     FXint xx;
     956         6906 :     if (!xid) {
     957              :         return;
     958              :     }
     959         6906 :     pos = contents.validate(FXCLAMP(0, pos, contents.length()));
     960         6906 :     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         6906 :     } else if (options & JUSTIFY_LEFT) {
     972         6906 :         if (options & TEXTFIELD_PASSWD) {
     973            0 :             xx = font->getTextWidth("*", 1) * contents.index(pos);
     974              :         } else {
     975         6906 :             xx = font->getTextWidth(contents.text(), pos);
     976              :         }
     977         6906 :         if (shift + xx < 0) {
     978           31 :             shift = -xx;
     979         6875 :         } else if (shift + xx >= ww) {
     980           31 :             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         6906 :     if (shift != oldshift) {
     995           62 :         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            0 :     if (pos < 0) {
    1035              :         pos = 0;
    1036              :     }
    1037            0 :     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        18548 : MFXTextFieldIcon::drawTextFragment(FXDCWindow& dc, FXint x, FXint y, FXint fm, FXint to) {
    1092        18548 :     x += font->getTextWidth(contents.text(), fm);
    1093        18548 :     y += font->getFontAscent();
    1094        18548 :     dc.drawText(x, y, &contents[fm], to - fm);
    1095        18548 : }
    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        18548 : void MFXTextFieldIcon::drawTextRange(FXDCWindow& dc, FXint fm, FXint to) {
    1112              :     FXint sx, ex, xx, yy, cw, hh, ww, si, ei, lx, rx, t;
    1113        18548 :     FXint rr = width - border - padright;
    1114        18548 :     FXint ll = border + padleft;
    1115        18548 :     FXint mm = (ll + rr) / 2;
    1116        18548 :     if (to <= fm) {
    1117              :         return;
    1118              :     }
    1119              :     // set font
    1120        18548 :     dc.setFont(font);
    1121              :     // Text color
    1122        18548 :     dc.setForeground(textColor);
    1123              :     // Height
    1124        18548 :     hh = font->getFontHeight();
    1125              :     // Text sticks to top of field
    1126        18548 :     if (options & JUSTIFY_TOP) {
    1127            0 :         yy = padtop + border;
    1128        18548 :     } 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        18548 :         yy = border + padtop + (height - padbottom - padtop - (border << 1) - hh) / 2;
    1134              :     }
    1135        18548 :     if (anchor < cursor) {
    1136              :         si = anchor;
    1137              :         ei = cursor;
    1138              :     } else {
    1139              :         si = cursor;
    1140              :         ei = anchor;
    1141              :     }
    1142              :     // Password mode
    1143        18548 :     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            0 :         if (si < fm) {
    1179              :             si = fm;
    1180              :         }
    1181            0 :         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        18548 :         ww = font->getTextWidth(contents.text(), contents.length());
    1219              :         // Text sticks to right of field
    1220        18548 :         if (options & JUSTIFY_RIGHT) {
    1221            0 :             xx = shift + rr - ww;
    1222        18548 :         } else if (options & JUSTIFY_LEFT) {
    1223              :             // Text sticks on left of field
    1224        18548 :             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        18548 :         if (icon) {
    1231            0 :             xx += ICON_SPACING + ICON_SIZE;
    1232              :         }
    1233              :         // Reduce to avoid drawing excessive amounts of text
    1234        18548 :         lx = xx + font->getTextWidth(&contents[0], fm);
    1235        18548 :         rx = lx + font->getTextWidth(&contents[fm], to - fm);
    1236        18756 :         while (fm < to) {
    1237        18756 :             t = contents.inc(fm);
    1238        18756 :             cw = font->getTextWidth(&contents[fm], t - fm);
    1239        18756 :             if (lx + cw >= 0) {
    1240              :                 break;
    1241              :             }
    1242              :             lx += cw;
    1243              :             fm = t;
    1244              :         }
    1245        74548 :         while (fm < to) {
    1246        67548 :             t = contents.dec(to);
    1247        67548 :             cw = font->getTextWidth(&contents[t], to - t);
    1248        67548 :             if (rx - cw < width) {
    1249              :                 break;
    1250              :             }
    1251              :             rx -= cw;
    1252              :             to = t;
    1253              :         }
    1254              : 
    1255              :         // Adjust selected range
    1256        18548 :         if (si < fm) {
    1257              :             si = fm;
    1258              :         }
    1259        18548 :         if (ei > to) {
    1260              :             ei = to;
    1261              :         }
    1262              : 
    1263              :         // Nothing selected
    1264        18548 :         if (!hasSelection() || to <= si || ei <= fm) {
    1265        18548 :             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        18548 : MFXTextFieldIcon::onPaint(FXObject*, FXSelector, void* ptr) {
    1300              :     FXEvent* ev = (FXEvent*)ptr;
    1301        18548 :     FXDCWindow dc(this, ev);
    1302              :     // Draw frame
    1303        18548 :     drawFrame(dc, 0, 0, width, height);
    1304              :     // Gray background if disabled
    1305        18548 :     if (isEnabled()) {
    1306        18548 :         dc.setForeground(backColor);
    1307              :     } else {
    1308            0 :         dc.setForeground(baseColor);
    1309              :     }
    1310              :     // Draw background
    1311        18548 :     dc.fillRectangle(border, border, width - (border << 1), height - (border << 1));
    1312              :     // Draw text, clipped against frame interior
    1313        18548 :     dc.setClipRectangle(border, border, width - (border << 1), height - (border << 1));
    1314        18548 :     drawTextRange(dc, 0, contents.length());
    1315              :     // Draw caret
    1316        18548 :     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        18548 :     if (icon) {
    1329            0 :         dc.drawIcon(icon, ICON_SPACING / 2, border + padtop + (height - padbottom - padtop - (border << 1) - ICON_SIZE) / 2);
    1330              :     }
    1331        18548 :     return 1;
    1332        18548 : }
    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            0 :         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              :         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              :                     return 0;
    2071              :                 }
    2072              :                 return 1;
    2073              :         }
    2074              :     }
    2075              :     return 0;
    2076              : }
    2077              : 
    2078              : 
    2079              : FXbool
    2080        28488 : MFXTextFieldIcon::killSelection() {
    2081        28488 :     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        14244 : MFXTextFieldIcon::setText(const FXString& text, FXbool notify) {
    2138        14244 :     killSelection();
    2139        14244 :     if (contents != text) {
    2140         7138 :         contents = text;
    2141         7138 :         anchor = contents.length();
    2142         7138 :         cursor = contents.length();
    2143         7138 :         if (xid) {
    2144           32 :             layout();
    2145              :         }
    2146         7138 :         if (notify && target) {
    2147            0 :             target->tryHandle(this, FXSEL(SEL_COMMAND, message), (void*)contents.text());
    2148              :         }
    2149              :     }
    2150        14244 : }
    2151              : 
    2152              : 
    2153              : void
    2154        14244 : MFXTextFieldIcon::setIcon(FXIcon* ic) {
    2155        14244 :     killSelection();
    2156        14244 :     icon = ic;
    2157        14244 :     anchor = contents.length();
    2158        14244 :     cursor = contents.length();
    2159        14244 :     if (xid) {
    2160           32 :         layout();
    2161              :     }
    2162        14244 : }
    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            0 :     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         7106 : MFXTextFieldIcon::setEditable(FXbool edit) {
    2229         7106 :     if (edit) {
    2230            0 :         options &= ~TEXTFIELD_READONLY;
    2231              :     } else {
    2232         7106 :         options |= TEXTFIELD_READONLY;
    2233              :     }
    2234         7106 : }
    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 2.0-1