Edits the provided text based on the specified edit commands.
Processes a single line of text by applying a sequence of editing commands. Supports operations like inserting, deleting characters or words, moving the cursor, searching for substrings, and manipulating the kill buffer.
75 {
76 short count, new_kill;
77 char *ptr, *text_start, delimiter, *ptr1, *ptr2, *ptr3;
78 char *delimLoc, *editNext, *charList;
79 static char kill[4096], buffer[4096];
80 char *orig, *repl;
81 int global, conditional, conditionalReturn, here, i;
82 char *edit, cSave;
84 int stackLevel, stackDepth, doPush, parenCount, invert;
85 size_t j;
86
87#if DEBUG
88 printf("text = %s\nedit = %s\n", text, edit0);
89#endif
90 text_start = text;
91 kill[0] = 0;
92 if (!(editSeq = malloc(sizeof(*editSeq) * (stackDepth = 10))))
93 return 0;
94 cp_str(&editSeq[0].editText, edit0);
95 editSeq[0].count = 1;
96 for (i = 0; i < stackDepth; i++)
97 editSeq[i].pending = 0;
98 editSeq[0].editPtr = NULL;
99 stackLevel = 0;
100
101 new_kill = 1;
102 while (stackLevel >= 0) {
103#if DEBUG
104 printf("stackLevel = %ld\n", stackLevel);
105#endif
106 while (editSeq[stackLevel].pending || editSeq[stackLevel].count--) {
107 if (!editSeq[stackLevel].pending)
108 editSeq[stackLevel].editPtr = editSeq[stackLevel].editText;
109 editSeq[stackLevel].pending = 0;
110 if (!editSeq[stackLevel].editPtr)
111 continue;
112#if DEBUG
113 printf("Count = %ld\n", editSeq[stackLevel].count + 1);
114 printf("EditPtr = %s\n", editSeq[stackLevel].editPtr);
115#endif
116 edit = editSeq[stackLevel].editPtr;
117 while (*(editSeq[stackLevel].editPtr = edit)) {
118 count = 0;
119 while (isdigit(*edit))
120 count = count * 10 + (*edit++ - '0');
121 if (!count)
122 count = 1;
123 if (!*edit)
124 break;
125#if DEBUG
126 printf("count = %ld command = %c\n", count, *edit);
127#endif
128 doPush = 0;
129
130
131
132 switch (*edit) {
133 case '(':
134
135 parenCount = 1;
136 ptr = edit + 1;
137 while (parenCount && *++edit) {
138 if (*edit == '(')
139 parenCount++;
140 else if (*edit == ')')
141 parenCount--;
142 }
143 if (*edit) {
144 editSeq[stackLevel].pending = 1;
145 editSeq[stackLevel].editPtr = edit + 1;
146 } else {
147 editSeq[stackLevel].pending = 1;
148 editSeq[stackLevel].editPtr = NULL;
149 }
150 if (stackLevel >= stackDepth &&
151 !(editSeq = realloc(editSeq, sizeof(*editSeq) * (stackDepth += 10)))) {
152 fprintf(stderr, "memory allocation failure (edit_string)");
153 return 0;
154 }
155 stackLevel++;
156 editSeq[stackLevel].count = count;
157 cSave = *edit;
158 *edit = 0;
159 cp_str(&editSeq[stackLevel].editText, ptr);
160 *edit = cSave;
161 editSeq[stackLevel].editPtr = NULL;
162 doPush = 1;
163#if DEBUG
164 printf("stack pushing: %ld*>%s<\n", count,
165 editSeq[stackLevel].editText);
166#endif
167 break;
168 case 'c':
169
170 kill[0] = 0;
171 break;
172 case 'd':
173
174 if (count > (long)strlen(text))
175 count = strlen(text);
177 new_kill = 1;
178 break;
179 case 'f':
180
181 if (count > (long)strlen(text))
182 count = strlen(text);
183 text += count;
184 new_kill = 1;
185 break;
186 case 'b':
187
188 if ((text -= count) < text_start)
189 text = text_start;
190 new_kill = 1;
191 break;
192 case 'D':
193
194 while (count-- && (ptr = strpbrk(text, " \t_-"))) {
195 while (IS_WORD_END(*ptr))
196 ptr++;
198 }
199 if (count >= 0)
200 *text = 0;
201 new_kill = 1;
202 break;
203 case 'F':
204
205 while (count-- && (ptr = strpbrk(text, " \t_-"))) {
206 while (IS_WORD_END(*ptr))
207 ptr++;
208 text = ptr;
209 }
210 if (count >= 0)
211 text += strlen(text);
212 new_kill = 1;
213 break;
214 case 'B':
215
216 while (count--) {
217 while (IS_WORD_END(*text) && text > text_start)
218 text--;
219 while (!IS_WORD_END(*text) && text > text_start)
220 text--;
221 }
222 if (IS_WORD_END(*text))
223 text++;
224 new_kill = 1;
225 break;
226 case 'a':
227
228 text = text_start;
229 break;
230 case 'e':
231
232 text += strlen(text);
233 break;
234 case 'i':
235
236 delimiter = *++edit;
237 ptr1 = NULL;
238 if ((ptr = strchr(++edit, delimiter))) {
239 ptr1 = ptr;
240 *ptr = 0;
241 } else {
242 ptr = edit + strlen(edit) - 1;
243 }
244#if DEBUG
245 printf("insert string = >%s<\n", edit);
246#endif
247 while (count--) {
249 text += strlen(edit);
250 }
251 if (ptr1)
252 *ptr1 = delimiter;
253 edit = ptr;
254 new_kill = 1;
255 break;
256 case 'x':
257
258 delimiter = *++edit;
259 if (!*edit)
260 break;
261 invert = 0;
262 if (delimiter == '-') {
263 invert = 1;
264 delimiter = *++edit;
265 if (!*edit)
266 break;
267 }
268 delimLoc = NULL;
269 if ((editNext = strchr(++edit, delimiter))) {
270 delimLoc = editNext;
271 *editNext = 0;
272 } else {
273 editNext = edit + strlen(edit) - 1;
274 }
276 if (*charList == '[' && *(charList + strlen(charList) - 1) == ']') {
277
278
279
280
281 }
282#if DEBUG
283 printf("x-kill string = >%s< (was >%s<)\n", charList, edit);
284 printf("text position: >%s<\n", text);
285#endif
286 if (new_kill)
287 kill[0] = 0;
288 new_kill = 0;
289 if (invert) {
290
291 if ((ptr = strpbrk(text, charList))) {
292 strncat(kill, text, ptr - text);
294 } else
295
296 *text = 0;
297 } else {
298
299 int i, length, found;
300 found = 1;
301 length = strlen(charList);
302 ptr = text;
303 while (found && *ptr) {
304 found = 0;
305 for (i = 0; i < length; i++) {
306 if (*ptr == *(charList + i)) {
307 found = 1;
308 ptr++;
309 break;
310 }
311 }
312 }
313 if (ptr != text) {
314 strncat(kill, text, ptr - text);
316 }
317 }
318 free(charList);
319 if (delimLoc)
320 *delimLoc = delimiter;
321 edit = editNext;
322 break;
323 case 'r':
324
325 if (!(delimiter = *++edit))
326 return (0);
327 conditional = 0;
328 if (delimiter == '?') {
329 conditional = 1;
330 if (!(delimiter = *++edit))
331 return (0);
332 }
333 ptr1 = NULL;
334 if ((ptr = strchr(++edit, delimiter))) {
335 ptr1 = ptr;
336 *ptr = 0;
337 } else {
338 ptr = edit + strlen(edit) - 1;
339 }
340#if DEBUG
341 printf("search string = >%s<\n", edit);
342#endif
343 conditionalReturn = 0;
344 while (count--) {
345 j = strlen(text);
346 ptr3 = text;
347 text = text_start;
348 ptr2 = strstr(text, edit);
349 if (ptr2 == NULL) {
350 text = ptr3;
351 conditionalReturn = conditional;
352 break;
353 }
354 if (strlen(ptr2) <= j) {
355 text = ptr3;
356 conditionalReturn = conditional;
357 break;
358 }
359 text = ptr2 + strlen(edit);
360 while (1) {
361 ptr2 = strstr(text, edit);
362 if ((ptr2 == NULL) || (strlen(ptr2) <= j)) {
363 break;
364 }
365 text = ptr2 + strlen(edit);
366 }
367 if (count != 0)
368 text -= strlen(edit);
369 }
370 if (ptr1)
371 *ptr1 = delimiter;
372 edit = ptr;
373 new_kill = 1;
374 if (conditionalReturn)
375 return 1;
376 break;
377 case 'R':
378
379 if (!(delimiter = *++edit))
380 return (0);
381 conditional = 0;
382 if (delimiter == '?') {
383 conditional = 1;
384 if (!(delimiter = *++edit))
385 return (0);
386 }
387 ptr1 = NULL;
388 if ((ptr = strchr(++edit, delimiter))) {
389 ptr1 = ptr;
390 *ptr = 0;
391 } else {
392 ptr = edit + strlen(edit) - 1;
393 }
394#if DEBUG
395 printf("search string = >%s<\n", edit);
396#endif
397 conditionalReturn = 0;
398 while (count--) {
399 j = strlen(text);
400 ptr3 = text;
401 text = text_start;
402 ptr2 = strstr(text, edit);
403 if (ptr2 == NULL) {
404 text = ptr3;
405 conditionalReturn = conditional;
406 break;
407 }
408 if (strlen(ptr2) <= j) {
409 text = ptr3;
410 conditionalReturn = conditional;
411 break;
412 }
413 text = ptr2 + strlen(edit);
414 while (1) {
415 ptr2 = strstr(text, edit);
416 if ((ptr2 == NULL) || (strlen(ptr2) <= j)) {
417 break;
418 }
419 text = ptr2 + strlen(edit);
420 }
421 text -= strlen(edit);
422 }
423 if (ptr1)
424 *ptr1 = delimiter;
425 edit = ptr;
426 new_kill = 1;
427 if (conditionalReturn)
428 return 1;
429 break;
430 case 's':
431
432 if (!(delimiter = *++edit))
433 return (0);
434 conditional = 0;
435 if (delimiter == '?') {
436 conditional = 1;
437 if (!(delimiter = *++edit))
438 return (0);
439 }
440 ptr1 = NULL;
441 if ((ptr = strchr(++edit, delimiter))) {
442 ptr1 = ptr;
443 *ptr = 0;
444 } else {
445 ptr = edit + strlen(edit) - 1;
446 }
447#if DEBUG
448 printf("search string = >%s<\n", edit);
449#endif
450 conditionalReturn = 0;
451 while (count--) {
452 if ((ptr2 = strstr(text, edit)))
453 text = ptr2 + strlen(edit);
454 else {
455 conditionalReturn = conditional;
456 break;
457 }
458 }
459 if (ptr1)
460 *ptr1 = delimiter;
461 edit = ptr;
462 new_kill = 1;
463 if (conditionalReturn)
464 return 1;
465 break;
466 case 'S':
467
468 if (!(delimiter = *++edit))
469 return (0);
470 conditional = 0;
471 if (delimiter == '?') {
472 conditional = 1;
473 if (!(delimiter = *++edit))
474 return (0);
475 }
476 ptr1 = NULL;
477 if ((ptr = strchr(++edit, delimiter))) {
478 ptr1 = ptr;
479 *ptr = 0;
480 } else {
481 ptr = edit + strlen(edit) - 1;
482 }
483#if DEBUG
484 printf("search string = >%s<\n", edit);
485#endif
486 conditionalReturn = 0;
487 while (count--) {
488 if ((ptr2 = strstr(text, edit))) {
489 if (count != 0)
490 text = ptr2 + strlen(edit);
491 else
492 text = ptr2;
493 } else {
494 conditionalReturn = conditional;
495 break;
496 }
497 }
498 if (ptr1)
499 *ptr1 = delimiter;
500 edit = ptr;
501 new_kill = 1;
502 if (conditionalReturn)
503 return 1;
504 break;
505 case 'k':
506
507 if (new_kill)
508 kill[0] = 0;
509 strncat(kill, text, count);
511 new_kill = 0;
512#if DEBUG
513 printf("kill buffer: >%s<\n", kill);
514#endif
515 break;
516 case 'K':
517
518 if (new_kill)
519 kill[0] = 0;
520 while (count-- && (ptr = strpbrk(text, " \t_-"))) {
521 while (IS_WORD_END(*ptr))
522 ptr++;
523 strncat(kill, text, ptr - text);
525 }
526 if (count >= 0)
527 *text = 0;
528 new_kill = 0;
529#if DEBUG
530 printf("kill buffer: >%s<\n", kill);
531#endif
532 break;
533 case 'z':
534 case 'Z':
535 if (!(delimiter = *++edit))
536 return (0);
537 while (count--) {
538
539 if (new_kill)
540 kill[0] = 0;
541 if ((ptr = strchr(text, delimiter))) {
542 if (*(edit - 1) == 'Z')
543 ptr++;
544 strncat(kill, text, ptr - text);
546 }
547 new_kill = 0;
548#if DEBUG
549 printf("kill buffer: >%s<\n", kill);
550#endif
551 if (*(edit - 1) == 'z')
552 break;
553 }
554 break;
555 case 'y':
556
557#if DEBUG
558 printf("yank string = >%s<\n", kill);
559#endif
560 while (count--) {
562 text += strlen(kill);
563 }
564 break;
565 case '%':
566
567 global = here = 0;
568 if (*(edit + 1) == 'g') {
569 global = 1;
570 edit++;
571 }
572 if (*(edit + 1) == 'h') {
573 here = 1;
574 edit++;
575 }
576 if (!(delimiter = *++edit))
577 return (0);
578#if DEBUG
579 printf("delimiter = %c\n", delimiter);
580#endif
581 orig = edit + 1;
582 if (!(repl = strchr(orig + 1, delimiter)))
583 return (0);
584 *repl++ = 0;
585 if (!(ptr = strchr(repl, delimiter)))
586 return (0);
587 *ptr = 0;
588#if DEBUG
589 printf("orig: >%s< repl: >%s<\n", orig, repl);
590#endif
591 if (here) {
592 if (!global)
594 else
596 } else {
597 if (!global)
599 else
601 }
603 edit = ptr;
604 *(repl - 1) = delimiter;
605 *ptr = delimiter;
606 break;
607 default:
608 break;
609 }
610 if (doPush)
611 break;
612 edit++;
613 }
614 }
615 free(editSeq[stackLevel].editText);
616 editSeq[stackLevel].editPtr = NULL;
617 stackLevel--;
618 }
619 free(editSeq);
620 return 1;
621}
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
char * insert(char *s, char *t)
Inserts a substring into a target string.
int replaceString(char *t, char *s, char *orig, char *repl, long count_limit, long here)
Replace occurrences of one string with another string with additional options.
int replace_stringn(char *t, char *s, char *orig, char *repl, long count_limit)
Replace a limited number of occurrences of one string with another string.
int replace_string(char *t, char *s, char *orig, char *repl)
Replace all occurrences of one string with another string.
char * strcpy_ss(char *dest, const char *src)
Safely copies a string, handling memory overlap.
char * expand_ranges(char *template)
Expand range specifiers in a wildcard template into explicit character lists.