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