1 /* -*- mode: C; mode: fold; -*- */
2 /* Copyright (c) 1992, 1998 John E. Davis
3 * This file is part of JED editor library source.
4 *
5 * You may distribute this file under the terms the GNU General Public
6 * License. See the file COPYING for more information.
7 */
8 #include "config.h"
9 #include "jed-feat.h"
10 /*{{{ Include Files */
11
12 #include <stdio.h>
13 #include <string.h>
14
15 #include <slang.h>
16
17 #include "jdmacros.h"
18
19 #include "buffer.h"
20 #include "replace.h"
21 #include "search.h"
22 #include "screen.h"
23 #include "ins.h"
24 #include "ledit.h"
25 #include "misc.h"
26 #include "paste.h"
27 #include "cmds.h"
28
29 /*}}}*/
30
31 int Replace_Preserve_Case = 0;
32 #define USE_PRESERVE_CASE 0
33
34 /* returns the length of the region inserted. */
replace_chars(int * np,char * neew)35 int replace_chars (int *np, char *neew) /*{{{*/
36 {
37 int len;
38 int n;
39 #if USE_PRESERVE_CASE
40 int preserve_case;
41 char *old = NULL;
42 int i;
43 #endif
44
45 CHECK_READ_ONLY
46 n = *np;
47 if (n < 0) return 0;
48 len = strlen (neew);
49 #if USE_PRESERVE_CASE
50 preserve_case = (Replace_Preserve_Case && (len == n));
51 #endif
52 push_mark ();
53 #if USE_PRESERVE_CASE
54 if (preserve_case) push_mark ();
55 #endif
56 n = forwchars (np);
57 #if USE_PRESERVE_CASE
58 if (preserve_case)
59 {
60 if (n == len)
61 {
62 if (NULL == (old = make_buffer_substring(&n))) return 0;
63 }
64 else
65 {
66 preserve_case = 0;
67 pop_mark (&Number_Zero);
68 }
69 }
70 #endif
71
72 delete_region ();
73 #if USE_PRESERVE_CASE
74 if (preserve_case)
75 {
76 unsigned char ch;
77
78 for (i = 0; i < len; i++)
79 {
80 ch = (unsigned char) old[i];
81 if (ch == UPPER_CASE(ch))
82 {
83 if (ch == LOWER_CASE(ch))
84 old[i] = neew[i];
85 else
86 old[i] = UPPER_CASE(neew[i]);
87 }
88 else old[i] = LOWER_CASE(neew[i]);
89 }
90 neew = old;
91 }
92 #endif
93 ins_chars((unsigned char *) neew, len);
94 #if USE_PRESERVE_CASE
95 if (preserve_case) SLfree (old);
96 #endif
97 return len;
98 }
99
100 /*}}}*/
101
replace_next(char * old,char * neew)102 int replace_next(char *old, char *neew) /*{{{*/
103 {
104 int n;
105
106 if (search(old, 1, 0) == 0) return(0);
107 n = strlen (old);
108 (void) replace_chars (&n, neew);
109 return(1);
110 }
111
112 /*}}}*/
113
114 /* This code implements a kill ring of sorts. It could be done in S-Lang but
115 * S-Lang cannot handle strings with embedded NULL characters. I do not
116 * want to lose compatability with C or I would allow S-Lang strings to handle
117 * the NULL chars.
118 */
119
120 #ifndef SIXTEEN_BIT_SYSTEM
121
122 # define MAX_KILL_ARRAY_SIZE 16
123 int Kill_Array_Size = MAX_KILL_ARRAY_SIZE;
124
125 typedef struct /*{{{*/
126 {
127 unsigned char *buf;
128 int len;
129 }
130
131 /*}}}*/
132 Char_Array_Type;
133
134 Char_Array_Type Kill_Array [MAX_KILL_ARRAY_SIZE];
135
copy_region_to_kill_array(int * np)136 void copy_region_to_kill_array (int *np) /*{{{*/
137 {
138 int n = *np;
139
140 if (n < 0) n = 0;
141 n = n % MAX_KILL_ARRAY_SIZE;
142
143 SLfree ((char *) Kill_Array[n].buf);
144 Kill_Array[n].buf = (unsigned char *) make_buffer_substring (&Kill_Array[n].len);
145 }
146
147 /*}}}*/
148
insert_from_kill_array(int * np)149 void insert_from_kill_array (int *np) /*{{{*/
150 {
151 int n = *np;
152 unsigned char *buf;
153
154 CHECK_READ_ONLY_VOID
155 if (n < 0) n = 0;
156 n = n % MAX_KILL_ARRAY_SIZE;
157
158 if ((buf = Kill_Array[n].buf) == NULL) return;
159 ins_chars (buf, Kill_Array[n].len);
160 }
161
162 /*}}}*/
163
append_region_to_kill_array(int * np)164 void append_region_to_kill_array (int *np) /*{{{*/
165 {
166 int n = *np, len, oldlen;
167 unsigned char *buf, *newbuf;
168
169 if (n < 0) n = 0;
170 n = n % MAX_KILL_ARRAY_SIZE;
171
172 buf = (unsigned char *) make_buffer_substring (&len);
173 if (buf == NULL) return;
174
175 oldlen = Kill_Array[n].len;
176 newbuf = (unsigned char *) SLrealloc ((char *)Kill_Array[n].buf, oldlen + len + 1);
177
178 if (newbuf != NULL)
179 {
180 SLMEMCPY ((char *) newbuf + oldlen, (char *) buf, len);
181 Kill_Array[n].buf = newbuf;
182 Kill_Array[n].len = oldlen + len;
183 }
184
185 SLfree ((char *)buf);
186 }
187
188 /*}}}*/
189
190 #endif /* NOT 16bit system */
191
bol_bsearch_char(int * ch)192 static int bol_bsearch_char (int *ch) /*{{{*/
193 {
194 char buf[2];
195 buf[0] = (unsigned char) (*ch); buf[1] = 0;
196 return bol_bsearch (buf);
197 }
198
199 /*}}}*/
200
bol_fsearch_char(int * ch)201 static int bol_fsearch_char (int *ch) /*{{{*/
202 {
203 char buf[2];
204 buf[0] = (unsigned char) (*ch); buf[1] = 0;
205 return bol_fsearch (buf);
206 }
207
208 /*}}}*/
209
fsearch_char(int * ch)210 static int fsearch_char (int *ch) /*{{{*/
211 {
212 char buf[2];
213 buf[0] = (unsigned char) (*ch); buf[1] = 0;
214 return search_forward (buf);
215 }
216
217 /*}}}*/
218
bsearch_char(int * ch)219 static int bsearch_char (int *ch) /*{{{*/
220 {
221 char buf[2];
222 buf[0] = (unsigned char) (*ch); buf[1] = 0;
223 return search_backward (buf);
224 }
225
226 /*}}}*/
227
ffind_char(int * ch)228 static int ffind_char (int *ch) /*{{{*/
229 {
230 char buf[2];
231 buf[0] = (unsigned char) (*ch); buf[1] = 0;
232 return forward_search_line (buf);
233 }
234
235 /*}}}*/
236
bfind_char(int * ch)237 static int bfind_char (int *ch) /*{{{*/
238 {
239 char buf[2];
240 buf[0] = (unsigned char) (*ch); buf[1] = 0;
241 return backward_search_line (buf);
242 }
243
244 /*}}}*/
245
widen_this_buffer(void)246 static void widen_this_buffer (void) /*{{{*/
247 {
248 jed_widen_whole_buffer (CBuf);
249 }
250
251 /*}}}*/
252
is_visible_mark(void)253 static int is_visible_mark (void) /*{{{*/
254 {
255 if ((CBuf->marks == NULL) || (0 == (CBuf->marks->flags & VISIBLE_MARK)))
256 return 0;
257 return 1;
258 }
259
260 /*}}}*/
261
get_jed_library_path(void)262 static char *get_jed_library_path (void)
263 {
264 return Jed_Library;
265 }
266
set_jed_library_path(void)267 static void set_jed_library_path (void)
268 {
269 char *s;
270
271 if (SLang_pop_slstring (&s))
272 return;
273
274 SLang_free_slstring (Jed_Library);
275 Jed_Library = s;
276 }
277
set_buffer_umask(int * cmask)278 static int set_buffer_umask (int *cmask)
279 {
280 int u = CBuf->umask;
281 if (*cmask != -1)
282 CBuf->umask = *cmask;
283 return u;
284 }
285
286 SLang_Intrin_Fun_Type Jed_Other_Intrinsics [] = /*{{{*/
287 {
288 MAKE_INTRINSIC_I("set_buffer_umask", set_buffer_umask, INT_TYPE),
289 /* Prototype: Integer set_buffer_umask (Integer cmask);
290 * The function may be used to set the process file creation mask
291 * for the appropriate operations associated with the current
292 * buffer. This makes it possible to have a buffer-dependent
293 * umask setting. The function takes the desired umask setting and
294 * returns the previous setting. If @cmask@ is zero, the default
295 * process umask setting will be used for operations while the buffer
296 * is current. If @cmask@ is -1, the umask associated with the buffer
297 * will not be changed.
298 */
299 MAKE_INTRINSIC_S("fsearch", search_forward, INT_TYPE),
300 /* Prototype: Integer fsearch (String str);
301 * This function may be used to search forward in buffer looking for the
302 * string @str@. If not found, this functions returns zero. However,
303 * if found, the length of the string is returned and the current point
304 * is moved to the to the start of the match. It respects the setting
305 * of the variable @CASE_SEARCH@. If the string that one is searching
306 * for is known to be at the beginning of a line, the function
307 * @bol_fsearch@ should be used instead.
308 *
309 * Note: This function cannot find a match that crosses lines.
310 * Related Functions: @ffind@, @fsearch_char@, @bsearch@, @bol_fsearch@, @re_fsearch@, @looking_at@
311 * Related Variables: @CASE_SEARCH@
312 */
313
314 MAKE_INTRINSIC_S("bsearch", search_backward, INT_TYPE),
315 /* Prototype: Integer bsearch (String str);
316 * The @bsearch@ function searches backward from the current position
317 * for the string @str@. If @str@ is found, this function will return
318 * the length of @str@ and move the current position to the beginning of
319 * the matched text. If a match is not found, zero will be returned and
320 * the position will not change. It respects the value of the variable
321 * @CASE_SEARCH@.
322 *
323 * Related Functions: @fsearch@, @bol_bsearch@, @re_bsearch@
324 */
325 MAKE_INTRINSIC_S("bfind", backward_search_line, INT_TYPE),
326 /* Prototype: Integer bfind (String str);
327 * @bfind@ searches backward from the current position to the beginning
328 * of the line for the string @str@. If a match is found, the length of
329 * @str@ is returned and the current point is moved to the start of the
330 * match. If no match is found, zero is returned.
331 * Note: This function respects the setting of the @CASE_SEARCH@ variable.
332 * Related Functions: @bsearch@, @ffind@, @bol_bsearch@, @re_bsearch@
333 * Related Variables: @CASE_SEARCH@
334 */
335 MAKE_INTRINSIC_S("ffind", forward_search_line, INT_TYPE),
336 /* Prototype: Integer ffind (String s);
337 * @ffind@ searches forward from the current position to the end of the
338 * line for the string @str@. If a match is found, the length of @str@
339 * is returned and the current point is moved to the start of the match.
340 * If no match is found, zero is returned.
341 * Note: This function respects the setting of the @CASE_SEARCH@ variable.
342 * To perform a search that includes multiple lines, use the @fsearch@
343 * function.
344 * Related Functions: @fsearch@, @bfind@, @re_fsearch@, @bol_fsearch@
345 */
346 MAKE_INTRINSIC_S("bol_fsearch", bol_fsearch, INT_TYPE),
347 /* Prototype: Integer bol_fsearch (str);
348 * @bol_fsearch@ searches forward from the current point until the end
349 * of the buffer for occurrences of the string @str@ at the beginning of
350 * a line. If a match is found, the length of @str@ is returned and the
351 * current point is moved to the start of the match. If no match is
352 * found, zero is returned.
353 * Note: @bol_fsearch@ is much faster than using @re_fsearch@ to perform
354 * a search that matches the beginning of a line.
355 *
356 * Related Functions: @bol_bsearch@, @fsearch@, @ffind@, @re_fsearch@
357 * Related Variables: @CASE_SEARCH@
358 */
359 MAKE_INTRINSIC_S("bol_bsearch", bol_bsearch, INT_TYPE),
360 /* Prototype: Integer bol_bsearch (str);
361 * @bol_bsearch@ searches backward from the current point until the
362 * beginning of the buffer for the occurrences of the string @str@ at
363 * the beginning of a line. If a match is found, the length of @str@ is
364 * returned and the current point is moved to the start of the match. If
365 * no match is found, zero is returned.
366 *
367 * Note: @bol_bsearch@ is much faster than using @re_bsearch@ to perform
368 * a search that matches the beginning of a line.
369 *
370 * Related Functions: @bol_fsearch@, @bsearch@, @bfind@, @re_bsearch@
371 * Related Variables: @CASE_SEARCH@
372 */
373
374 MAKE_INTRINSIC_I("bol_fsearch_char", bol_fsearch_char, INT_TYPE),
375 /* Prototype: Integer bol_fsearch_char (Integer ch);
376 * This function searches forward for a character @ch@ at the beginning
377 * of a line. If it is found, @1@ is returned; otherwise @0@ is returned.
378 * Related functions: @bol_fsearch@, @bol_bsearch_char@, @fsearch_char@
379 * Related variables: @CASE_SEARCH@
380 */
381 MAKE_INTRINSIC_I("bol_bsearch_char", bol_bsearch_char, INT_TYPE),
382 /* Prototype: Integer bol_fsearch_char (Integer ch);
383 * This function searches backward for a character @ch@ at the beginning
384 * of a line. If it is found, @1@ is returned; otherwise @0@ is returned.
385 * Related functions: @bol_bsearch@, @bol_fsearch_char@, @bsearch_char@
386 * Related variables: @CASE_SEARCH@
387 */
388 MAKE_INTRINSIC_I("fsearch_char", fsearch_char, INT_TYPE),
389 /* Prototype: Integer fsearch_char (Integer ch);
390 * This function searches forward for a character @ch@. If it is
391 * found, @1@ is returned; otherwise @0@ is returned.
392 * Related functions: @fsearch@, @ffind_char@, @bsearch_char@
393 * Related variables: @CASE_SEARCH@
394 */
395 MAKE_INTRINSIC_I("bsearch_char", bsearch_char, INT_TYPE),
396 /* Prototype: Integer fsearch_char (Integer ch);
397 * This function searches backward for a character @ch@. If it is
398 * found, @1@ is returned; otherwise @0@ is returned.
399 * Related functions: @fsearch_char@, @ffind_char@, @fsearch@
400 * Related variables: @CASE_SEARCH@
401 */
402 MAKE_INTRINSIC_I("bfind_char", bfind_char, INT_TYPE),
403 /* Prototype: Integer fsearch_char (Integer ch);
404 * This function searches backward on the current line for a character
405 * @ch@. If it is found, @1@ is returned; otherwise @0@ is returned.
406 * Related functions: @fsearch_char@, @ffind_char@, @fsearch@
407 * Related variables: @CASE_SEARCH@
408 */
409 MAKE_INTRINSIC_I("ffind_char", ffind_char, INT_TYPE),
410 /* Prototype: Integer fsearch_char (Integer ch);
411 * This function searches forwardward on the current line for a character
412 * @ch@. If it is found, @1@ is returned; otherwise @0@ is returned.
413 * Related functions: @fsearch_char@, @bfind_char@, @fsearch@
414 * Related variables: @CASE_SEARCH@
415 */
416 MAKE_INTRINSIC_SS("replace", replace_cmd, VOID_TYPE),
417 /* Prototype: Void replace(String old, String new);
418 * This function may be used to replace all occurances of the string
419 * @old@ with the string, @new@, from current editing point to the end
420 * of the buffer. The editing point is returned to the initial location.
421 * That is, this function does not move the editing point.
422 * Related Functions: @replace_chars@, @fsearch@, @re_fsearch@, @bsearch@, @ffind@, @del@
423 * Related Variables: @REPLACE_PRESERVE_CASE@
424 */
425 MAKE_INTRINSIC_IS("replace_chars", replace_chars, INT_TYPE),
426 /* Prototype: Void replace_chars (Integer n, String new);
427 * This function may be used to replace the next @n@ characters at the
428 * editing position by the string @new@. After the replacement, the editing
429 * point will be moved to the end of the inserted string. The length of
430 * the replacement string @new@ is returned.
431 * Related Functions: @fsearch@, @re_fsearch@, @bsearch@, @ffind@, @del@
432 * Related Variables: @REPLACE_PRESERVE_CASE@
433 */
434 MAKE_INTRINSIC_I("regexp_nth_match", regexp_nth_match, VOID_TYPE),
435 /* Prototype: String regexp_nth_match (Integer n);
436 * This function returns the nth sub-expression matched by the last regular
437 * expression search. If the parameter @n@ is zero, the entire match is
438 * returned.
439 * Note: The value returned by this function is meaningful only if the
440 * editing point has not been moved since the match.
441 * Related Functions: @re_fsearch@, @re_bsearch@
442 */
443 MAKE_INTRINSIC_SI("replace_match", replace_match, INT_TYPE),
444 /* Prototype: Integer replace_match(String s, Integer how);
445 * This function replaces text previously matched with @re_fsearch@ or
446 * @re_bsearch@ at the current editing point with string @s@. If @how@ is
447 * zero, @s@ is a specially formatted string of the form described below.
448 * If @how@ is non-zero, @s@ is regarded as a simple string and is used
449 * literally. If the replacement fails, this function returns zero
450 * otherwise, it returns non-zero.
451 */
452 MAKE_INTRINSIC_S("re_fsearch", re_search_forward, INT_TYPE),
453 /* Prototype: Integer re_fsearch(String pattern);
454 * Search forward for regular expression @pattern@. This function returns
455 * the 1 + length of the string matched. If no match is found, it returns
456 * 0.
457 *
458 * Related Functions: @fsearch@, @bol_fsearch@, @re_bsearch@ */
459 MAKE_INTRINSIC_S("re_bsearch", re_search_backward, INT_TYPE),
460 /* Prototype: Integer re_bsearch(String pattern);
461 * Search backward for regular expression @pattern@. This function returns
462 * the 1 + length of the string matched. If no match is found, it returns
463 * 0.
464 *
465 * Related Functions: @bsearch@, @bol_bsearch@, @re_fsearch@ */
466 MAKE_INTRINSIC("is_visible_mark", is_visible_mark, INT_TYPE, 0),
467 /* Prototype: is_visible_mark ();
468 * This function may be used to test whether or not the mark is a visible
469 * mark. A visible mar is one which causes the region defined by it to
470 * be highlighted.
471 * It returns @1@ is the mark is visible, or @0@ if the mark
472 * is not visible or does not exist.
473 *
474 * Related Functions: @markp@, @push_mark@
475 */
476 #if JED_HAS_SAVE_NARROW
477 MAKE_INTRINSIC("push_narrow", jed_push_narrow, VOID_TYPE, 0),
478 /* Prototype: Void push_narrow ();
479 * This function saves the current narrow context. This is useful when
480 * one wants to restore this context after widening the buffer.
481 * Related Functions: @pop_narrow@, @narrow@, @widen@, @widen_buffer@
482 */
483 MAKE_INTRINSIC("pop_narrow", jed_pop_narrow, VOID_TYPE, 0),
484 /* Prototype: Void pop_narrow ();
485 * The purpose of this function is to restore the last narrow
486 * context that was saved via @push_narrow@.
487 * Related Functions: @push_narrow@, @widen@, @widen_buffer@
488 */
489 #endif
490 #if JED_HAS_BUFFER_LOCAL_VARS
491 MAKE_INTRINSIC_S("blocal_var_exists", jed_blocal_var_exists, SLANG_INT_TYPE),
492
493 MAKE_INTRINSIC_S("set_blocal_var", jed_set_blocal_var, VOID_TYPE),
494 /* Prototype: Void set_blocal_var (val, String v);
495 * This function sets the value of the buffer local variable with name @v@
496 * to value @val@. The buffer local variable specified by @v@ must have
497 * been previously created by the @create_blocal_var@ function. @val@ must
498 * have the type that was declared when @create_blocal_var@ was called.
499 * Related Functions: @get_blocal_var@, @create_blocal_var@
500 */
501 MAKE_INTRINSIC_S("get_blocal_var", jed_get_blocal_var, VOID_TYPE),
502 /* Prototype: get_blocal_var (String name);
503 * This function returns the value of the buffer local variable specified
504 * by @name@.
505 * Related Functions: @set_blocal_var@, @create_blocal_var@
506 */
507 MAKE_INTRINSIC_S("create_blocal_var", jed_make_blocal_var, VOID_TYPE),
508 #endif
509 MAKE_INTRINSIC("count_narrows", jed_count_narrows, INT_TYPE, 0),
510 /* Prototype: Integer count_narrows ();
511 * This function returns the narrow depth of the current buffer.
512 * Related Functions: @narrow@, @widen@, @widen_buffer@, @push_narrow@
513 */
514 MAKE_INTRINSIC("widen_buffer", widen_this_buffer, VOID_TYPE, 0),
515 /* Prototype: Void widen_buffer ();
516 * This function widens the whole buffer. If one intends to restore the
517 * narrow context after calling this function, the narrow context should be
518 * saved via @push_narrow@.
519 * Related Functions: @narrow@, @widen@, @push_narrow@, @pop_narrow@
520 */
521 MAKE_INTRINSIC ("get_jed_library_path", get_jed_library_path, STRING_TYPE, 0),
522 /* Prototype: String get_jed_library_path ();
523 * This function returns the current search path for jed library files.
524 * The path may be set using the function @set_jed_library_path@.
525 * Related Functions: @set_jed_library_path@
526 */
527 MAKE_INTRINSIC ("set_jed_library_path", set_jed_library_path, VOID_TYPE, 0),
528 /* Prototype: Void set_jed_library_path (String p);
529 * This function may be used to set the search path for library files.
530 * Its parameter @p@ may be a comma separated list of directories to
531 * search. When the editor is first started, the path is initialized
532 * from the @JED_ROOT@, or @JED_LIBRARY@ environment variables.
533 * Related Functions: @get_jed_library_path@
534 */
535
536 SLANG_END_TABLE
537 };
538
539 /*}}}*/
540