enable openmotif-2.3.1 and link on phoenix host
[nedit-bw.git] / ForbackwardSame.diff
blob38ad532ecad1d5af05f30f2f88d297ba3311ed8d
1 From: Tony Balinski <ajbj@free.fr>
2 Subject: New arrow key action routines improving the "word jump" action procedures
4 Available as a patch:
6 http://sourceforge.net/tracker/index.php?func=detail&aid=970496&group_id=11005&atid=311005
7 [ 970496 ] New arrow key action routines improving "word jump" actions
8 ForbackwardSame.diff 2004-06-10 08:41
10 Instead of always stopping at the fronts of words, you can set these action
11 routines to stop at line ends, the ends of runs of spaces, etc. by setting
12 appropriate translations. This patch also allows "jump to end of selection":
13 if you have an active selection, you can get your left/right keys to move to
14 the end of it before deselecting it, rather than just moving one character
15 position.
17 * Added forward_same/backward_same action routines, to bind to
18 ctrl-right/left for word skipping
19 * Added forward/backward_character skipselect argument, to move to
20 either end of an active selection before clearing it
21 * Added forward_same/backward_same skipselect, skipblanks arguments,
22 allowing fine control over where the cursor ends up
24 Example translations:
26 NEdit*text.translations: #override \
27 Shift Ctrl<KeyPress>osfLeft: backward_same("extend")\n\
28 Ctrl<KeyPress>osfLeft: backward_same("skipselect","skipblanks")\n\
29 Shift Ctrl<KeyPress>osfRight: forward_same("extend","skipblanks")\n\
30 Ctrl<KeyPress>osfRight: forward_same("skipselect","skipblanks")\n\
31 ~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfRight: forward_character(skipselect)\n\
32 ~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfLeft: backward_character(skipselect)\n\
33 ...
35 ---
37 source/text.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
38 1 file changed, 207 insertions(+), 2 deletions(-)
40 diff --quilt old/source/text.c new/source/text.c
41 --- old/source/text.c
42 +++ new/source/text.c
43 @@ -162,18 +162,24 @@ static void deleteNextWordAP(Widget w, X
44 Cardinal *nArgs);
45 static void deleteToStartOfLineAP(Widget w, XEvent *event, String *args,
46 Cardinal *nArgs);
47 static void deleteToEndOfLineAP(Widget w, XEvent *event, String *args,
48 Cardinal *nArgs);
49 +static Boolean forwardSkipSelect(Widget w, int insertPos);
50 +static Boolean backwardSkipSelect(Widget w, int insertPos);
51 static void forwardCharacterAP(Widget w, XEvent *event, String *args,
52 Cardinal *nArgs);
53 static void backwardCharacterAP(Widget w, XEvent *event, String *args,
54 Cardinal *nArgs);
55 static void forwardWordAP(Widget w, XEvent *event, String *args,
56 Cardinal *nArgs);
57 static void backwardWordAP(Widget w, XEvent *event, String *args,
58 Cardinal *nArgs);
59 +static void forwardSameAP(Widget w, XEvent *event, String *args,
60 + Cardinal *nArgs);
61 +static void backwardSameAP(Widget w, XEvent *event, String *args,
62 + Cardinal *nArgs);
63 static void forwardParagraphAP(Widget w, XEvent *event, String *args,
64 Cardinal *nArgs);
65 static void backwardParagraphAP(Widget w, XEvent *event, String *args,
66 Cardinal *nArgs);
67 static void keySelectAP(Widget w, XEvent *event, String *args, Cardinal *nArgs);
68 @@ -214,10 +220,12 @@ static void focusInAP(Widget w, XEvent *
69 Cardinal *nArgs);
70 static void focusOutAP(Widget w, XEvent *event, String *args,
71 Cardinal *nArgs);
72 static void checkMoveSelectionChange(Widget w, XEvent *event, int startPos,
73 String *args, Cardinal *nArgs);
74 +static int getWidgetSelectionPos(Widget w, int *start, int *end, int *isRect,
75 + int *rectStart, int *rectEnd);
76 static void keyMoveExtendSelection(Widget w, XEvent *event, int startPos,
77 int rectangular);
78 static void checkAutoShowInsertPos(Widget w);
79 static int checkReadOnly(Widget w);
80 static void simpleInsertAtCursor(Widget w, char *chars, XEvent *event,
81 @@ -537,10 +545,14 @@ static XtActionsRec actionsList[] = {
82 {"process_home", beginningOfLineAP},
83 {"forward-word", forwardWordAP},
84 {"forward_word", forwardWordAP},
85 {"backward-word", backwardWordAP},
86 {"backward_word", backwardWordAP},
87 + {"forward-same", forwardSameAP},
88 + {"forward_same", forwardSameAP},
89 + {"backward-same", backwardSameAP},
90 + {"backward_same", backwardSameAP},
91 {"forward-paragraph", forwardParagraphAP},
92 {"forward_paragraph", forwardParagraphAP},
93 {"backward-paragraph", backwardParagraphAP},
94 {"backward_paragraph", backwardParagraphAP},
95 {"beginning-of-line", beginningOfLineAP},
96 @@ -2639,18 +2651,44 @@ static void deleteToStartOfLineAP(Widget
97 BufRemove(textD->buffer, startOfLine, insertPos);
98 checkAutoShowInsertPos(w);
99 callCursorMovementCBs(w, event);
102 +/* move insertPos to end of selection if in selection - return true if done */
103 +static Boolean forwardSkipSelect(Widget w, int insertPos)
105 + int start, end;
106 + if (getWidgetSelectionPos(w, &start, &end, NULL, NULL, NULL) &&
107 + start <= insertPos && insertPos <= end) {
108 + TextDSetInsertPosition(((TextWidget)w)->text.textD, end);
109 + return True;
111 + return False;
114 +/* move insertPos to start of selection if in selection - return true if done */
115 +static Boolean backwardSkipSelect(Widget w, int insertPos)
117 + int start, end;
118 + if (getWidgetSelectionPos(w, &start, &end, NULL, NULL, NULL) &&
119 + start <= insertPos && insertPos <= end) {
120 + TextDSetInsertPosition(((TextWidget)w)->text.textD, start);
121 + return True;
123 + return False;
126 static void forwardCharacterAP(Widget w, XEvent *event, String *args,
127 Cardinal *nArgs)
129 int insertPos = TextDGetInsertPosition(((TextWidget)w)->text.textD);
130 int silent = hasKey("nobell", args, nArgs);
131 + int skipsel = hasKey("skipselect", args, nArgs);
133 cancelDrag(w);
134 - if (!TextDMoveRight(((TextWidget)w)->text.textD)) {
135 + if (!(skipsel && forwardSkipSelect(w, insertPos)) &&
136 + !TextDMoveRight(((TextWidget)w)->text.textD)) {
137 ringIfNecessary(silent, w);
139 checkMoveSelectionChange(w, event, insertPos, args, nArgs);
140 checkAutoShowInsertPos(w);
141 callCursorMovementCBs(w, event);
142 @@ -2659,13 +2697,15 @@ static void forwardCharacterAP(Widget w,
143 static void backwardCharacterAP(Widget w, XEvent *event, String *args,
144 Cardinal *nArgs)
146 int insertPos = TextDGetInsertPosition(((TextWidget)w)->text.textD);
147 int silent = hasKey("nobell", args, nArgs);
148 + int skipsel = hasKey("skipselect", args, nArgs);
150 cancelDrag(w);
151 - if (!TextDMoveLeft(((TextWidget)w)->text.textD)) {
152 + if (!(skipsel && backwardSkipSelect(w, insertPos)) &&
153 + !TextDMoveLeft(((TextWidget)w)->text.textD)) {
154 ringIfNecessary(silent, w);
156 checkMoveSelectionChange(w, event, insertPos, args, nArgs);
157 checkAutoShowInsertPos(w);
158 callCursorMovementCBs(w, event);
159 @@ -2749,10 +2789,158 @@ static void backwardWordAP(Widget w, XEv
160 checkMoveSelectionChange(w, event, insertPos, args, nArgs);
161 checkAutoShowInsertPos(w);
162 callCursorMovementCBs(w, event);
165 +static char *sameCharClassMap(char map[256], char *delimiters)
167 + static char spaces[] = " \t";
168 + static char classMap[256];
169 + static int done = 0;
170 + static int spaceClass = 0, nlClass = 0, delimClass = 0;
171 + int i;
172 + if (!done) {
173 + /* default value */
174 + for (i = 0; i < sizeof classMap; i++)
175 + classMap[i] = done; /* zero */
177 + /* letters, digits, _ */
178 + ++done;
179 + for (i = 0; i < sizeof classMap; i++)
180 + if (isalnum(i) || i == '_')
181 + classMap[i] = done;
183 + /* other graphic characters */
184 + ++done;
185 + for (i = 0; i < sizeof classMap; i++)
186 + if (isgraph(i) && !classMap[i])
187 + classMap[i] = done;
189 + /* control characters */
190 + ++done;
191 + for (i = 0; i < sizeof classMap; i++)
192 + if (iscntrl(i) && !classMap[i])
193 + classMap[i] = done;
195 + /* other ascii characters */
196 + ++done;
197 + for (i = 0; i < sizeof classMap; i++)
198 + if (isascii(i) && !classMap[i])
199 + classMap[i] = done;
201 + /* NEdit's spaces */
202 + spaceClass = ++done;
203 + for (i = 0; spaces[i]; i++)
204 + classMap[spaces[i]] = done;
205 + /* and newline */
206 + nlClass = ++done;
207 + classMap['\n'] = done;
208 + /* and a class for delimiters */
209 + delimClass = ++done;
212 + /* current delimiters */
213 + memcpy(map, classMap, 256);
214 + for (i = 0; delimiters[i]; i++) {
215 + unsigned char ch = delimiters[i];
216 + int cl = classMap[ch];
217 + /* do NOT overwrite the NEdit spaces/newline classes */
218 + if (cl != spaceClass && cl != nlClass)
219 + map[ch] = delimClass;
221 + return map;
224 +static void forwardSameAP(Widget w, XEvent *event, String *args,
225 + Cardinal *nArgs)
227 + textDisp *textD = ((TextWidget)w)->text.textD;
228 + textBuffer *buf = textD->buffer;
229 + int pos, insertPos = TextDGetInsertPosition(textD);
230 + char *delimiters = ((TextWidget)w)->text.delimiters;
231 + int silent = hasKey("nobell", args, nArgs);
232 + int incBlanks = hasKey("skipblanks", args, nArgs);
233 + int skipsel = hasKey("skipselect", args, nArgs);
235 + char classMap[256];
236 + int chClass, spClass;
238 + cancelDrag(w);
239 + if (insertPos == buf->length) {
240 + ringIfNecessary(silent, w);
241 + return;
244 + if (!(skipsel && forwardSkipSelect(w, insertPos))) {
245 + pos = insertPos;
246 + /* pick up the class map and the current char class, move forward */
247 + sameCharClassMap(classMap, delimiters);
248 + chClass = classMap[(unsigned char)BufGetCharacter(buf, pos++)];
249 + spClass = incBlanks ? classMap[' '] : chClass;
251 + /* now skip over all characters from here of that class */
252 + for (; pos < buf->length; pos++) {
253 + if (classMap[(unsigned char)BufGetCharacter(buf, pos)] != chClass)
254 + break;
256 + /* and skip over all characters from there for trailing blanks */
257 + for (; spClass != chClass && pos < buf->length; pos++) {
258 + if (classMap[(unsigned char)BufGetCharacter(buf, pos)] != spClass)
259 + break;
261 + /* pos is position of first character not of the same class */
262 + TextDSetInsertPosition(textD, pos);
264 + checkMoveSelectionChange(w, event, insertPos, args, nArgs);
265 + checkAutoShowInsertPos(w);
266 + callCursorMovementCBs(w, event);
269 +static void backwardSameAP(Widget w, XEvent *event, String *args,
270 + Cardinal *nArgs)
272 + textDisp *textD = ((TextWidget)w)->text.textD;
273 + textBuffer *buf = textD->buffer;
274 + int pos, insertPos = TextDGetInsertPosition(textD);
275 + char *delimiters = ((TextWidget)w)->text.delimiters;
276 + int silent = hasKey("nobell", args, nArgs);
277 + int incBlanks = hasKey("skipblanks", args, nArgs);
278 + int skipsel = hasKey("skipselect", args, nArgs);
280 + char classMap[256];
281 + int chClass, spClass;
282 + cancelDrag(w);
283 + if (insertPos == 0) {
284 + ringIfNecessary(silent, w);
285 + return;
288 + if (!(skipsel && backwardSkipSelect(w, insertPos))) {
289 + pos = insertPos - 1; /* we know insertPos != 0 */
290 + sameCharClassMap(classMap, delimiters); /* get class map */
291 + /* pick up the class of previous character */
292 + chClass = classMap[(unsigned char)BufGetCharacter(buf, pos)];
293 + spClass = incBlanks ? classMap[' '] : chClass;
295 + /* now skip back over all characters from here of that class */
296 + for (; pos > 0; --pos) {
297 + if (classMap[(unsigned char)BufGetCharacter(buf, pos-1)] != chClass)
298 + break;
300 + /* and skip back over all characters from there for leading blanks */
301 + for (; spClass != chClass && pos > 0; --pos) {
302 + if (classMap[(unsigned char)BufGetCharacter(buf, pos-1)] != spClass)
303 + break;
305 + /* pos is position of first character not of the same class */
306 + TextDSetInsertPosition(textD, pos);
308 + checkMoveSelectionChange(w, event, insertPos, args, nArgs);
309 + checkAutoShowInsertPos(w);
310 + callCursorMovementCBs(w, event);
313 static Boolean lineIsBlank(textBuffer *buf, int pos, int *start)
315 static const char whiteChars[] = " \t";
316 char c;
318 @@ -3587,10 +3775,27 @@ static void checkMoveSelectionChange(Wid
319 else
320 BufUnselect((((TextWidget)w)->text.textD)->buffer);
324 +** Fish out current selection information, returning true if there is one.
326 +static int getWidgetSelectionPos(Widget w, int *start, int *end, int *isRect,
327 + int *rectStart, int *rectEnd)
329 + int dummy;
330 + if (!isRect)
331 + isRect = &dummy;
332 + if (!rectStart)
333 + rectStart = &dummy;
334 + if (!rectEnd)
335 + rectEnd = &dummy;
336 + return BufGetSelectionPos((((TextWidget)w)->text.textD)->buffer,
337 + start, end, isRect, rectStart, rectEnd);
341 ** If a selection change was requested via a keyboard command for moving
342 ** the insertion cursor (usually with the "extend" keyword), adjust the
343 ** selection to include the new cursor position, or begin a new selection
344 ** between startPos and the new cursor position with anchor at startPos.