1 2 3 /* This version of microEmacs is based on the public domain C
4 * version written by Dave G. Conroy.
5 * The D programming language version is written by Walter Bright.
6 * http://www.digitalmars.com/d/
7 * This program is in the public domain.
8 */9 10 /*
11 * The routines in this file implement commands that work word at a time.
12 * There are all sorts of word mode commands. If I do any sentence and/or
13 * paragraph mode commands, they are likely to be put in this file.
14 */15 16 moduleword;
17 18 importstd.ascii;
19 20 imported;
21 importmain;
22 importwindow;
23 importrandom;
24 importline;
25 importterminal;
26 importregion;
27 importbasic;
28 importdisplay;
29 30 /* Word wrap. Back-over whatever precedes the point on the current
31 * line and stop on the first word-break or the beginning of the line. If we
32 * reach the beginning of the line, jump back to the end of the word and start
33 * a new line. Otherwise, break the line at the word-break, eat it, and jump
34 * back to the end of the word.
35 * NOTE: This function may leaving trailing blanks.
36 * Returns true on success, false on errors.
37 */38 intword_wrap(boolf, intn)
39 {
40 intcnt;
41 LINE* oldp;
42 43 oldp = curwp.w_dotp;
44 cnt = -1;
45 do {
46 cnt++;
47 if (! backchar(false, 1))
48 gotoerr;
49 } while (! inword());
50 if (! word_back(false, 1))
51 gotoerr;
52 /* If still on same line (but not at the beginning) */53 if (oldp == curwp.w_dotp && curwp.w_doto)
54 { inti;
55 56 if (!random_backdel(false, 1))
57 gotoerr;
58 if (!random_newline(false, 1))
59 gotoerr;
60 oldp = lback(curwp.w_dotp);
61 i = 0;
62 while (1)
63 {
64 autoc = lgetc(oldp,i);
65 if (c != ' ' && c != '\t')
66 break;
67 line_insert(1,c);
68 i++;
69 }
70 }
71 while (inword() == true)
72 if (forwchar(false, 1) == false)
73 gotoerr;
74 returnforwchar(false, cnt);
75 76 err:
77 returnfalse;
78 }
79 80 /****************************
81 * Word wrap the current line.
82 */83 84 intword_wrap_line(boolf, intn)
85 {
86 inti;
87 intj;
88 intcol;
89 charc;
90 intinword;
91 intlasti;
92 LINE* oldp;
93 LINE* dotpsave;
94 intdotosave;
95 96 if (n < 0)
97 gotoerr;
98 99 if (window_marking(curwp))
100 { REGIONregion;
101 ints;
102 103 if ((s = getregion(®ion)) != true)
104 returns;
105 dotpsave = curwp.w_dotp;
106 dotosave = curwp.w_doto;
107 curwp.w_dotp = region.r_linep;
108 curwp.w_doto = region.r_offset;
109 n = region.r_nlines;
110 }
111 112 while (n-- > 0)
113 {
114 L1:
115 col = 0;
116 lasti = 0;
117 inword = 0;
118 for (i = 0; i < llength(curwp.w_dotp); i++)
119 {
120 c = lgetc(curwp.w_dotp, i);
121 if (c == ' ' || c == '\t')
122 {
123 if (inword)
124 lasti = i;
125 inword = 0;
126 }
127 else128 {
129 inword = 1;
130 }
131 col = getcol(curwp.w_dotp, i);
132 if (col >= term.t_ncol && lasti)
133 {
134 if (!forwchar(0, lasti - curwp.w_doto))
135 gotoerr;
136 if (!random_newline(0,1))
137 gotoerr;
138 139 /* Remove leading whitespace from new line */140 while (1)
141 {
142 if (!llength(curwp.w_dotp))
143 break;
144 c = lgetc(curwp.w_dotp, 0);
145 if (c == ' ' || c == '\t')
146 {
147 if (!random_forwdel(0, 1))
148 gotoerr;
149 }
150 else151 break;
152 }
153 154 /* Match indenting of original line (oldp) */155 oldp = lback(curwp.w_dotp);
156 for (j = 0; j < llength(oldp); j++)
157 {
158 c = lgetc(oldp, j);
159 if (c == ' ' || c == '\t')
160 {
161 if (!line_insert(1, c))
162 gotoerr;
163 }
164 else165 break;
166 }
167 168 gotoL1;
169 }
170 }
171 if (!forwline(0, 1))
172 gotoerr;
173 }
174 if (window_marking(curwp))
175 {
176 if (dotosave > llength(dotpsave))
177 dotosave = llength(dotpsave);
178 curwp.w_dotp = dotpsave;
179 curwp.w_doto = dotosave;
180 }
181 returntrue;
182 183 err:
184 returnfalse;
185 }
186 187 /*************************
188 * Select word that the cursor is on.
189 */190 191 intword_select(boolf, intn)
192 {
193 intinw;
194 ints;
195 196 inw = inword();
197 do198 s = backchar(false, 1);
199 while (s && inword() == inw);
200 201 returns &&
202 forwchar(false,1) &&
203 basic_setmark(false,1) &&
204 word_forw(f,n);
205 }
206 207 /******************************
208 * Select line that the cursor is on.
209 */210 211 intword_lineselect(boolf, intn)
212 {
213 return (curwp.w_doto == 0 || gotobol(false,1)) &&
214 basic_setmark(false,1) &&
215 forwline(f,n);
216 }
217 218 /*
219 * Move the cursor backward by "n" words. All of the details of motion are
220 * performed by the "backchar" and "forwchar" routines. Error if you try to
221 * move beyond the buffers.
222 */223 intword_back(boolf, intn)
224 {
225 if (n < 0)
226 return (word_forw(f, -n));
227 if (backchar(false, 1) == false)
228 return (false);
229 while (n--) {
230 autoinw = inword();
231 do232 if (backchar(false, 1) == false)
233 return (false);
234 while (inword() == inw);
235 }
236 return (forwchar(false, 1));
237 }
238 239 /*
240 * Move the cursor forward by the specified number of words. All of the motion
241 * is done by "forwchar". Error if you try and move beyond the buffer's end.
242 */243 intword_forw(boolf, intn)
244 {
245 if (n < 0)
246 return (word_back(f, -n));
247 while (n--) {
248 autoinw = inword();
249 do250 if (forwchar(false, 1) == false)
251 return (false);
252 while (inword() == inw);
253 }
254 return (true);
255 }
256 257 /*
258 * Move the cursor forward by the specified number of words. As you move,
259 * convert any characters to upper case. Error if you try and move beyond the
260 * end of the buffer. Bound to "M-U".
261 */262 intword_upper(boolf, intn)
263 {
264 returnword_setcase(f,n,0);
265 }
266 267 /*
268 * Move the cursor forward by the specified number of words. As you move
269 * convert characters to lower case. Error if you try and move over the end of
270 * the buffer. Bound to "M-L".
271 */272 intword_lower(boolf, intn)
273 {
274 returnword_setcase(f,n,1);
275 }
276 277 /*************************
278 * Move the cursor forward by the specified number of words. As you move
279 * convert the first character of the word to upper case, and subsequent
280 * characters to lower case. Error if you try and move past the end of the
281 * buffer. Bound to "M-C".
282 */283 284 intcapword(boolf, intn)
285 {
286 returnword_setcase(f,n,2);
287 }
288 289 privateintword_setcase(boolf, intn, intflag)
290 {
291 charc;
292 293 if (n < 0)
294 return (false);
295 while (n--) {
296 while (inword() == false) {
297 if (forwchar(false, 1) == false)
298 return (false);
299 }
300 if (flag == 2 && inword() != false) {
301 c = lgetc(curwp.w_dotp, curwp.w_doto);
302 if (isLower(c))
303 { c -= 'a'-'A';
304 lputc(curwp.w_dotp, curwp.w_doto, c);
305 line_change(WFHARD);
306 }
307 if (forwchar(false, 1) == false)
308 return (false);
309 }
310 while (inword() != false) {
311 c = lgetc(curwp.w_dotp, curwp.w_doto);
312 finalswitch (flag)
313 { case0:
314 if (isLower(c)) {
315 c -= 'a'-'A';
316 gotoL1;
317 }
318 break;
319 case1:
320 case2:
321 if (isUpper(c)) {
322 c += 'a'-'A';
323 L1: lputc(curwp.w_dotp, curwp.w_doto, c);
324 line_change(WFHARD);
325 }
326 break;
327 }
328 if (forwchar(false, 1) == false)
329 return (false);
330 }
331 }
332 return (true);
333 }
334 335 /*
336 * Kill forward by "n" words. Remember the location of dot. Move forward by
337 * the right number of words. Put dot back where it was and issue the kill
338 * command for the right number of characters. Bound to "M-D".
339 */340 intdelfword(boolf, intn)
341 {
342 intsize;
343 LINE* dotp;
344 intdoto;
345 346 if (n < 0)
347 return (false);
348 dotp = curwp.w_dotp;
349 doto = curwp.w_doto;
350 size = 0;
351 while (n--) {
352 while (inword() == false) {
353 if (forwchar(false, 1) == false)
354 return (false);
355 ++size;
356 }
357 while (inword() != false) {
358 if (forwchar(false, 1) == false)
359 return (false);
360 ++size;
361 }
362 }
363 curwp.w_dotp = dotp;
364 curwp.w_doto = doto;
365 return (line_delete(size, true));
366 }
367 368 /*
369 * Kill backwards by "n" words. Move backwards by the desired number of words,
370 * counting the characters. When dot is finally moved to its resting place,
371 * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
372 */373 intdelbword(boolf, intn)
374 {
375 intsize;
376 377 if (n < 0)
378 return (false);
379 if (backchar(false, 1) == false)
380 return (false);
381 size = 0;
382 while (n--) {
383 while (inword() == false) {
384 if (backchar(false, 1) == false)
385 return (false);
386 ++size;
387 }
388 while (inword() != false) {
389 if (backchar(false, 1) == false)
390 return (false);
391 ++size;
392 }
393 }
394 if (forwchar(false, 1) == false)
395 returnfalse;
396 returnline_delete(size, true);
397 }
398 399 /*
400 * Return true if the character at dot is a character that is considered to be
401 * part of a word. The word character list is hard coded. Should be setable.
402 * This routine MUST return only a 1 or a 0.
403 */404 boolinword()
405 {
406 if (curwp.w_doto == llength(curwp.w_dotp))
407 returnfalse;
408 autoc = lgetc(curwp.w_dotp, curwp.w_doto);
409 return (isAlphaNum(c) ||
410 c=='$' || c=='_'); /* For identifiers */411 }