]> pd.if.org Git - pd_readline/blob - mg/word.c
Added mg from an OpenBSD mirror site. Many thanks to the OpenBSD team and the mg...
[pd_readline] / mg / word.c
1 /*      $OpenBSD: word.c,v 1.15 2008/09/15 16:11:35 kjell Exp $ */
2
3 /* This file is in the public domain. */
4
5 /*
6  *              Word mode commands.
7  * The routines in this file implement commands that work word at a time.
8  * There are all sorts of word mode commands.
9  */
10
11 #include "def.h"
12
13 RSIZE   countfword(void);
14
15 /*
16  * Move the cursor backward by "n" words. All of the details of motion are
17  * performed by the "backchar" and "forwchar" routines.
18  */
19 /* ARGSUSED */
20 int
21 backword(int f, int n)
22 {
23         if (n < 0)
24                 return (forwword(f | FFRAND, -n));
25         if (backchar(FFRAND, 1) == FALSE)
26                 return (FALSE);
27         while (n--) {
28                 while (inword() == FALSE) {
29                         if (backchar(FFRAND, 1) == FALSE)
30                                 return (TRUE);
31                 }
32                 while (inword() != FALSE) {
33                         if (backchar(FFRAND, 1) == FALSE)
34                                 return (TRUE);
35                 }
36         }
37         return (forwchar(FFRAND, 1));
38 }
39
40 /*
41  * Move the cursor forward by the specified number of words.  All of the
42  * motion is done by "forwchar".
43  */
44 /* ARGSUSED */
45 int
46 forwword(int f, int n)
47 {
48         if (n < 0)
49                 return (backword(f | FFRAND, -n));
50         while (n--) {
51                 while (inword() == FALSE) {
52                         if (forwchar(FFRAND, 1) == FALSE)
53                                 return (TRUE);
54                 }
55                 while (inword() != FALSE) {
56                         if (forwchar(FFRAND, 1) == FALSE)
57                                 return (TRUE);
58                 }
59         }
60         return (TRUE);
61 }
62
63 /*
64  * Move the cursor forward by the specified number of words.  As you move,
65  * convert any characters to upper case.
66  */
67 /* ARGSUSED */
68 int
69 upperword(int f, int n)
70 {
71         int     c, s;
72         RSIZE   size;
73
74         if ((s = checkdirty(curbp)) != TRUE)
75                 return (s);
76         if (curbp->b_flag & BFREADONLY) {
77                 ewprintf("Buffer is read-only");
78                 return (FALSE);
79         }
80
81         if (n < 0)
82                 return (FALSE);
83         while (n--) {
84                 while (inword() == FALSE) {
85                         if (forwchar(FFRAND, 1) == FALSE)
86                                 return (TRUE);
87                 }
88                 size = countfword();
89                 undo_add_change(curwp->w_dotp, curwp->w_doto, size);
90
91                 while (inword() != FALSE) {
92                         c = lgetc(curwp->w_dotp, curwp->w_doto);
93                         if (ISLOWER(c) != FALSE) {
94                                 c = TOUPPER(c);
95                                 lputc(curwp->w_dotp, curwp->w_doto, c);
96                                 lchange(WFFULL);
97                         }
98                         if (forwchar(FFRAND, 1) == FALSE)
99                                 return (TRUE);
100                 }
101         }
102         return (TRUE);
103 }
104
105 /*
106  * Move the cursor forward by the specified number of words.  As you move
107  * convert characters to lower case.
108  */
109 /* ARGSUSED */
110 int
111 lowerword(int f, int n)
112 {
113         int     c, s;
114         RSIZE   size;
115
116         if ((s = checkdirty(curbp)) != TRUE)
117                 return (s);
118         if (curbp->b_flag & BFREADONLY) {
119                 ewprintf("Buffer is read-only");
120                 return (FALSE);
121         }
122         if (n < 0)
123                 return (FALSE);
124         while (n--) {
125                 while (inword() == FALSE) {
126                         if (forwchar(FFRAND, 1) == FALSE)
127                                 return (TRUE);
128                 }
129                 size = countfword();
130                 undo_add_change(curwp->w_dotp, curwp->w_doto, size);
131
132                 while (inword() != FALSE) {
133                         c = lgetc(curwp->w_dotp, curwp->w_doto);
134                         if (ISUPPER(c) != FALSE) {
135                                 c = TOLOWER(c);
136                                 lputc(curwp->w_dotp, curwp->w_doto, c);
137                                 lchange(WFFULL);
138                         }
139                         if (forwchar(FFRAND, 1) == FALSE)
140                                 return (TRUE);
141                 }
142         }
143         return (TRUE);
144 }
145
146 /*
147  * Move the cursor forward by the specified number of words.  As you move
148  * convert the first character of the word to upper case, and subsequent
149  * characters to lower case.  Error if you try to move past the end of the
150  * buffer.
151  */
152 /* ARGSUSED */
153 int
154 capword(int f, int n)
155 {
156         int     c, s;
157         RSIZE   size;
158
159         if ((s = checkdirty(curbp)) != TRUE)
160                 return (s);
161         if (curbp->b_flag & BFREADONLY) {
162                 ewprintf("Buffer is read-only");
163                 return (FALSE);
164         }
165
166         if (n < 0)
167                 return (FALSE);
168         while (n--) {
169                 while (inword() == FALSE) {
170                         if (forwchar(FFRAND, 1) == FALSE)
171                                 return (TRUE);
172                 }
173                 size = countfword();
174                 undo_add_change(curwp->w_dotp, curwp->w_doto, size);
175
176                 if (inword() != FALSE) {
177                         c = lgetc(curwp->w_dotp, curwp->w_doto);
178                         if (ISLOWER(c) != FALSE) {
179                                 c = TOUPPER(c);
180                                 lputc(curwp->w_dotp, curwp->w_doto, c);
181                                 lchange(WFFULL);
182                         }
183                         if (forwchar(FFRAND, 1) == FALSE)
184                                 return (TRUE);
185                         while (inword() != FALSE) {
186                                 c = lgetc(curwp->w_dotp, curwp->w_doto);
187                                 if (ISUPPER(c) != FALSE) {
188                                         c = TOLOWER(c);
189                                         lputc(curwp->w_dotp, curwp->w_doto, c);
190                                         lchange(WFFULL);
191                                 }
192                                 if (forwchar(FFRAND, 1) == FALSE)
193                                         return (TRUE);
194                         }
195                 }
196         }
197         return (TRUE);
198 }
199
200 /*
201  * Count characters in word, from current position
202  */
203 RSIZE
204 countfword()
205 {
206         RSIZE            size;
207         struct line     *dotp;
208         int              doto;
209
210         dotp = curwp->w_dotp;
211         doto = curwp->w_doto;
212         size = 0;
213
214         while (inword() != FALSE) {
215                 if (forwchar(FFRAND, 1) == FALSE)
216                         /* hit the end of the buffer */
217                         goto out;
218                 ++size;
219         }
220 out:
221         curwp->w_dotp = dotp;
222         curwp->w_doto = doto;
223         return (size);
224 }
225
226
227 /*
228  * Kill forward by "n" words.
229  */
230 /* ARGSUSED */
231 int
232 delfword(int f, int n)
233 {
234         RSIZE            size;
235         struct line     *dotp;
236         int              doto;
237         int s;
238
239         if ((s = checkdirty(curbp)) != TRUE)
240                 return (s);
241         if (curbp->b_flag & BFREADONLY) {
242                 ewprintf("Buffer is read-only");
243                 return (FALSE);
244         }
245         if (n < 0)
246                 return (FALSE);
247
248         /* purge kill buffer */
249         if ((lastflag & CFKILL) == 0)
250                 kdelete();
251
252         thisflag |= CFKILL;
253         dotp = curwp->w_dotp;
254         doto = curwp->w_doto;
255         size = 0;
256
257         while (n--) {
258                 while (inword() == FALSE) {
259                         if (forwchar(FFRAND, 1) == FALSE)
260                                 /* hit the end of the buffer */
261                                 goto out;
262                         ++size;
263                 }
264                 while (inword() != FALSE) {
265                         if (forwchar(FFRAND, 1) == FALSE)
266                                 /* hit the end of the buffer */
267                                 goto out;
268                         ++size;
269                 }
270         }
271 out:
272         curwp->w_dotp = dotp;
273         curwp->w_doto = doto;
274         return (ldelete(size, KFORW));
275 }
276
277 /*
278  * Kill backwards by "n" words.  The rules for success and failure are now
279  * different, to prevent strange behavior at the start of the buffer.  The
280  * command only fails if something goes wrong with the actual delete of the
281  * characters.  It is successful even if no characters are deleted, or if you
282  * say delete 5 words, and there are only 4 words left.  I considered making
283  * the first call to "backchar" special, but decided that that would just be
284  * weird. Normally this is bound to "M-Rubout" and to "M-Backspace".
285  */
286 /* ARGSUSED */
287 int
288 delbword(int f, int n)
289 {
290         RSIZE   size;
291         int s;
292
293         if ((s = checkdirty(curbp)) != TRUE)
294                 return (s);
295         if (curbp->b_flag & BFREADONLY) {
296                 ewprintf("Buffer is read-only");
297                 return (FALSE);
298         }
299
300         if (n < 0)
301                 return (FALSE);
302
303         /* purge kill buffer */
304         if ((lastflag & CFKILL) == 0)
305                 kdelete();
306         thisflag |= CFKILL;
307         if (backchar(FFRAND, 1) == FALSE)
308                 /* hit buffer start */
309                 return (TRUE);
310
311         /* one deleted */
312         size = 1;
313         while (n--) {
314                 while (inword() == FALSE) {
315                         if (backchar(FFRAND, 1) == FALSE)
316                                 /* hit buffer start */
317                                 goto out;
318                         ++size;
319                 }
320                 while (inword() != FALSE) {
321                         if (backchar(FFRAND, 1) == FALSE)
322                                 /* hit buffer start */
323                                 goto out;
324                         ++size;
325                 }
326         }
327         if (forwchar(FFRAND, 1) == FALSE)
328                 return (FALSE);
329
330         /* undo assumed delete */
331         --size;
332 out:
333         return (ldelete(size, KBACK));
334 }
335
336 /*
337  * Return TRUE if the character at dot is a character that is considered to be
338  * part of a word. The word character list is hard coded. Should be settable.
339  */
340 int
341 inword(void)
342 {
343         /* can't use lgetc in ISWORD due to bug in OSK cpp */
344         return (curwp->w_doto != llength(curwp->w_dotp) &&
345             ISWORD(curwp->w_dotp->l_text[curwp->w_doto]));
346 }