File indexing completed on 2024-06-16 04:10:05

0001 
0002 /*
0003    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0004    All rights reserved.
0005 
0006    Redistribution and use in source and binary forms, with or without
0007    modification, are permitted provided that the following conditions
0008    are met:
0009 
0010    1. Redistributions of source code must retain the above copyright
0011       notice, this list of conditions and the following disclaimer.
0012    2. Redistributions in binary form must reproduce the above copyright
0013       notice, this list of conditions and the following disclaimer in the
0014       documentation and/or other materials provided with the distribution.
0015 
0016    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0017    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0018    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0019    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0020    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0022    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0023    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 #define DEBUG_KP_TOOL_TEXT 0
0029 
0030 
0031 #include "tools/selection/text/kpToolText.h"
0032 #include "kpLogCategories.h"
0033 #include "document/kpDocument.h"
0034 #include "layers/selections/text/kpTextSelection.h"
0035 #include "commands/tools/selection/text/kpToolTextBackspaceCommand.h"
0036 #include "commands/tools/selection/text/kpToolTextChangeStyleCommand.h"
0037 #include "commands/tools/selection/kpToolSelectionCreateCommand.h"
0038 #include "environments/tools/selection/kpToolSelectionEnvironment.h"
0039 #include "commands/tools/selection/text/kpToolTextDeleteCommand.h"
0040 #include "commands/tools/selection/text/kpToolTextEnterCommand.h"
0041 #include "commands/tools/selection/text/kpToolTextInsertCommand.h"
0042 #include "widgets/toolbars/options/kpToolWidgetOpaqueOrTransparent.h"
0043 #include "views/kpView.h"
0044 #include "views/manager/kpViewManager.h"
0045 
0046 #include <QList>
0047 
0048 #include <KLocalizedString>
0049 
0050 // protected static
0051 bool kpToolText::CursorIsOnWordChar (const QList <QString> &textLines,
0052     int cursorRow, int cursorCol)
0053 {
0054     return (cursorRow >= 0 && cursorRow < textLines.size () &&
0055             cursorCol >= 0 && cursorCol < textLines [cursorRow].length () &&
0056             !textLines [cursorRow][cursorCol].isSpace ());
0057 }
0058 
0059 
0060 // protected static
0061 bool kpToolText::CursorIsAtStart (const QList <QString> &,
0062     int cursorRow, int cursorCol)
0063 {
0064     return (cursorRow == 0 && cursorCol == 0);
0065 }
0066 
0067 // protected static
0068 bool kpToolText::CursorIsAtEnd (const QList <QString> &textLines,
0069     int cursorRow, int cursorCol)
0070 {
0071     if (textLines.isEmpty ()) {
0072         return (cursorRow == 0 && cursorCol == 0);
0073     }
0074         
0075     return (cursorRow == textLines.size () - 1 &&
0076             cursorCol == textLines [cursorRow].length ());
0077 }
0078 
0079 
0080 // protected static
0081 void kpToolText::MoveCursorLeft (const QList <QString> &textLines,
0082     int *cursorRow, int *cursorCol)
0083 {
0084     if (textLines.isEmpty ()) {
0085         return;
0086     }
0087         
0088     (*cursorCol)--;
0089 
0090     if (*cursorCol < 0)
0091     {
0092         (*cursorRow)--;
0093         if (*cursorRow < 0)
0094         {
0095             *cursorRow = 0;
0096             *cursorCol = 0;
0097         }
0098         else {
0099             *cursorCol = textLines [*cursorRow].length ();
0100         }
0101     }
0102 }
0103 
0104 // protected static
0105 void kpToolText::MoveCursorRight (const QList <QString> &textLines,
0106     int *cursorRow, int *cursorCol)
0107 {
0108     if (textLines.isEmpty ()) {
0109         return;
0110     }
0111         
0112     (*cursorCol)++;
0113 
0114     if (*cursorCol > textLines [*cursorRow].length ())
0115     {
0116         (*cursorRow)++;
0117         if (*cursorRow > textLines.size () - 1)
0118         {
0119             *cursorRow = textLines.size () - 1;
0120             *cursorCol = textLines [*cursorRow].length ();
0121         }
0122         else {
0123             *cursorCol = 0;
0124         }
0125     }
0126 }
0127 
0128 
0129 #define IS_ON_SPACE_OR_EOL() !CursorIsOnWordChar (textLines, *cursorRow, *cursorCol)
0130 
0131 // protected static
0132 int kpToolText::MoveCursorToWordStart (const QList <QString> &textLines,
0133     int *cursorRow, int *cursorCol)
0134 {
0135     if (textLines.isEmpty ()) {
0136         return 0;
0137     }
0138 
0139     int numMoves = 0;
0140 
0141 #define IS_ON_ANCHOR()                                            \
0142     (CursorIsOnWordChar (textLines, *cursorRow, *cursorCol) &&    \
0143          (cursorCol == nullptr ||                                 \
0144              !CursorIsOnWordChar (textLines, *cursorRow, *cursorCol - 1)))
0145 #define MOVE_CURSOR_LEFT()    \
0146     (MoveCursorLeft (textLines, cursorRow, cursorCol), ++numMoves)
0147 
0148 
0149     // (these comments will exclude the row=0,col=0 boundary case)
0150 
0151     if (IS_ON_ANCHOR ()) {
0152         MOVE_CURSOR_LEFT ();
0153     }
0154 
0155     // --- now we're not on an anchor point (start of word) ---
0156 
0157     // End up on a letter...
0158     while (!(*cursorRow == 0 && *cursorCol == 0) &&
0159             (IS_ON_SPACE_OR_EOL ()))
0160     {
0161         MOVE_CURSOR_LEFT ();
0162     }
0163 
0164     // --- now we're on a letter ---
0165 
0166     // Find anchor point
0167     while (!(*cursorRow == 0 && *cursorCol == 0) && !IS_ON_ANCHOR ())
0168     {
0169         MOVE_CURSOR_LEFT ();
0170     }
0171 
0172 
0173 #undef IS_ON_ANCHOR
0174 #undef MOVE_CURSOR_LEFT
0175 
0176     return numMoves;
0177 }
0178 
0179 // protected static
0180 int kpToolText::MoveCursorToNextWordStart (const QList <QString> &textLines,
0181     int *cursorRow, int *cursorCol)
0182 {
0183     if (textLines.isEmpty ()) {
0184         return 0;
0185     }
0186         
0187     int numMoves = 0;
0188 
0189 #define IS_AT_END() CursorIsAtEnd (textLines, *cursorRow, *cursorCol)
0190 #define MOVE_CURSOR_RIGHT()    \
0191     (MoveCursorRight (textLines, cursorRow, cursorCol), ++numMoves)
0192 
0193 
0194     // (these comments will exclude the last row,end col boundary case)
0195 
0196     // Find space
0197     while (!IS_AT_END () && !IS_ON_SPACE_OR_EOL ())
0198     {
0199         MOVE_CURSOR_RIGHT ();
0200     }
0201 
0202     // --- now we're on a space ---
0203 
0204     // Find letter
0205     while (!IS_AT_END () && IS_ON_SPACE_OR_EOL ())
0206     {
0207         MOVE_CURSOR_RIGHT ();
0208     }
0209 
0210     // --- now we're on a letter ---
0211 
0212 
0213 #undef IS_AT_END
0214 #undef MOVE_CURSOR_RIGHT
0215 
0216     return numMoves;
0217 }
0218 
0219 #undef IS_ON_SPACE_OR_EOL
0220