(insert_from_buffer, insert_from_buffer_1): New functions.
[bpt/emacs.git] / src / editfns.c
1 /* Lisp functions pertaining to editing.
2 Copyright (C) 1985,86,87,89,93,94 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 #include <sys/types.h>
22
23 #include <config.h>
24
25 #ifdef VMS
26 #include "vms-pwd.h"
27 #else
28 #include <pwd.h>
29 #endif
30
31 #include "lisp.h"
32 #include "intervals.h"
33 #include "buffer.h"
34 #include "window.h"
35
36 #include "systime.h"
37
38 #define min(a, b) ((a) < (b) ? (a) : (b))
39 #define max(a, b) ((a) > (b) ? (a) : (b))
40
41 /* Some static data, and a function to initialize it for each run */
42
43 Lisp_Object Vsystem_name;
44 Lisp_Object Vuser_real_name; /* login name of current user ID */
45 Lisp_Object Vuser_full_name; /* full name of current user */
46 Lisp_Object Vuser_name; /* user name from LOGNAME or USER */
47
48 void
49 init_editfns ()
50 {
51 char *user_name;
52 register unsigned char *p, *q, *r;
53 struct passwd *pw; /* password entry for the current user */
54 extern char *index ();
55 Lisp_Object tem;
56
57 /* Set up system_name even when dumping. */
58 init_system_name ();
59
60 #ifndef CANNOT_DUMP
61 /* Don't bother with this on initial start when just dumping out */
62 if (!initialized)
63 return;
64 #endif /* not CANNOT_DUMP */
65
66 pw = (struct passwd *) getpwuid (getuid ());
67 #ifdef MSDOS
68 /* We let the real user name default to "root" because that's quite
69 accurate on MSDOG and because it lets Emacs find the init file.
70 (The DVX libraries override the Djgpp libraries here.) */
71 Vuser_real_name = build_string (pw ? pw->pw_name : "root");
72 #else
73 Vuser_real_name = build_string (pw ? pw->pw_name : "unknown");
74 #endif
75
76 /* Get the effective user name, by consulting environment variables,
77 or the effective uid if those are unset. */
78 user_name = (char *) getenv ("LOGNAME");
79 if (!user_name)
80 user_name = (char *) getenv ("USER");
81 if (!user_name)
82 {
83 pw = (struct passwd *) getpwuid (geteuid ());
84 user_name = (char *) (pw ? pw->pw_name : "unknown");
85 }
86 Vuser_name = build_string (user_name);
87
88 /* If the user name claimed in the environment vars differs from
89 the real uid, use the claimed name to find the full name. */
90 tem = Fstring_equal (Vuser_name, Vuser_real_name);
91 if (NILP (tem))
92 pw = (struct passwd *) getpwnam (XSTRING (Vuser_name)->data);
93
94 p = (unsigned char *) (pw ? USER_FULL_NAME : "unknown");
95 q = (unsigned char *) index (p, ',');
96 Vuser_full_name = make_string (p, q ? q - p : strlen (p));
97
98 #ifdef AMPERSAND_FULL_NAME
99 p = XSTRING (Vuser_full_name)->data;
100 q = (char *) index (p, '&');
101 /* Substitute the login name for the &, upcasing the first character. */
102 if (q)
103 {
104 r = (char *) alloca (strlen (p) + XSTRING (Vuser_name)->size + 1);
105 bcopy (p, r, q - p);
106 r[q - p] = 0;
107 strcat (r, XSTRING (Vuser_name)->data);
108 r[q - p] = UPCASE (r[q - p]);
109 strcat (r, q + 1);
110 Vuser_full_name = build_string (r);
111 }
112 #endif /* AMPERSAND_FULL_NAME */
113 }
114 \f
115 DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
116 "Convert arg CHAR to a one-character string containing that character.")
117 (n)
118 Lisp_Object n;
119 {
120 char c;
121 CHECK_NUMBER (n, 0);
122
123 c = XINT (n);
124 return make_string (&c, 1);
125 }
126
127 DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
128 "Convert arg STRING to a character, the first character of that string.")
129 (str)
130 register Lisp_Object str;
131 {
132 register Lisp_Object val;
133 register struct Lisp_String *p;
134 CHECK_STRING (str, 0);
135
136 p = XSTRING (str);
137 if (p->size)
138 XSETFASTINT (val, ((unsigned char *) p->data)[0]);
139 else
140 XSETFASTINT (val, 0);
141 return val;
142 }
143 \f
144 static Lisp_Object
145 buildmark (val)
146 int val;
147 {
148 register Lisp_Object mark;
149 mark = Fmake_marker ();
150 Fset_marker (mark, make_number (val), Qnil);
151 return mark;
152 }
153
154 DEFUN ("point", Fpoint, Spoint, 0, 0, 0,
155 "Return value of point, as an integer.\n\
156 Beginning of buffer is position (point-min)")
157 ()
158 {
159 Lisp_Object temp;
160 XSETFASTINT (temp, point);
161 return temp;
162 }
163
164 DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
165 "Return value of point, as a marker object.")
166 ()
167 {
168 return buildmark (point);
169 }
170
171 int
172 clip_to_bounds (lower, num, upper)
173 int lower, num, upper;
174 {
175 if (num < lower)
176 return lower;
177 else if (num > upper)
178 return upper;
179 else
180 return num;
181 }
182
183 DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
184 "Set point to POSITION, a number or marker.\n\
185 Beginning of buffer is position (point-min), end is (point-max).")
186 (n)
187 register Lisp_Object n;
188 {
189 CHECK_NUMBER_COERCE_MARKER (n, 0);
190
191 SET_PT (clip_to_bounds (BEGV, XINT (n), ZV));
192 return n;
193 }
194
195 static Lisp_Object
196 region_limit (beginningp)
197 int beginningp;
198 {
199 extern Lisp_Object Vmark_even_if_inactive; /* Defined in callint.c. */
200 register Lisp_Object m;
201 if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
202 && NILP (current_buffer->mark_active))
203 Fsignal (Qmark_inactive, Qnil);
204 m = Fmarker_position (current_buffer->mark);
205 if (NILP (m)) error ("There is no region now");
206 if ((point < XFASTINT (m)) == beginningp)
207 return (make_number (point));
208 else
209 return (m);
210 }
211
212 DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 0, 0,
213 "Return position of beginning of region, as an integer.")
214 ()
215 {
216 return (region_limit (1));
217 }
218
219 DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
220 "Return position of end of region, as an integer.")
221 ()
222 {
223 return (region_limit (0));
224 }
225
226 #if 0 /* now in lisp code */
227 DEFUN ("mark", Fmark, Smark, 0, 0, 0,
228 "Return this buffer's mark value as integer, or nil if no mark.\n\
229 If you are using this in an editing command, you are most likely making\n\
230 a mistake; see the documentation of `set-mark'.")
231 ()
232 {
233 return Fmarker_position (current_buffer->mark);
234 }
235 #endif /* commented out code */
236
237 DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
238 "Return this buffer's mark, as a marker object.\n\
239 Watch out! Moving this marker changes the mark position.\n\
240 If you set the marker not to point anywhere, the buffer will have no mark.")
241 ()
242 {
243 return current_buffer->mark;
244 }
245
246 #if 0 /* this is now in lisp code */
247 DEFUN ("set-mark", Fset_mark, Sset_mark, 1, 1, 0,
248 "Set this buffer's mark to POS. Don't use this function!\n\
249 That is to say, don't use this function unless you want\n\
250 the user to see that the mark has moved, and you want the previous\n\
251 mark position to be lost.\n\
252 \n\
253 Normally, when a new mark is set, the old one should go on the stack.\n\
254 This is why most applications should use push-mark, not set-mark.\n\
255 \n\
256 Novice programmers often try to use the mark for the wrong purposes.\n\
257 The mark saves a location for the user's convenience.\n\
258 Most editing commands should not alter the mark.\n\
259 To remember a location for internal use in the Lisp program,\n\
260 store it in a Lisp variable. Example:\n\
261 \n\
262 (let ((beg (point))) (forward-line 1) (delete-region beg (point))).")
263 (pos)
264 Lisp_Object pos;
265 {
266 if (NILP (pos))
267 {
268 current_buffer->mark = Qnil;
269 return Qnil;
270 }
271 CHECK_NUMBER_COERCE_MARKER (pos, 0);
272
273 if (NILP (current_buffer->mark))
274 current_buffer->mark = Fmake_marker ();
275
276 Fset_marker (current_buffer->mark, pos, Qnil);
277 return pos;
278 }
279 #endif /* commented-out code */
280
281 Lisp_Object
282 save_excursion_save ()
283 {
284 register int visible = (XBUFFER (XWINDOW (selected_window)->buffer)
285 == current_buffer);
286
287 return Fcons (Fpoint_marker (),
288 Fcons (Fcopy_marker (current_buffer->mark),
289 Fcons (visible ? Qt : Qnil,
290 current_buffer->mark_active)));
291 }
292
293 Lisp_Object
294 save_excursion_restore (info)
295 register Lisp_Object info;
296 {
297 register Lisp_Object tem, tem1, omark, nmark;
298
299 tem = Fmarker_buffer (Fcar (info));
300 /* If buffer being returned to is now deleted, avoid error */
301 /* Otherwise could get error here while unwinding to top level
302 and crash */
303 /* In that case, Fmarker_buffer returns nil now. */
304 if (NILP (tem))
305 return Qnil;
306 Fset_buffer (tem);
307 tem = Fcar (info);
308 Fgoto_char (tem);
309 unchain_marker (tem);
310 tem = Fcar (Fcdr (info));
311 omark = Fmarker_position (current_buffer->mark);
312 Fset_marker (current_buffer->mark, tem, Fcurrent_buffer ());
313 nmark = Fmarker_position (tem);
314 unchain_marker (tem);
315 tem = Fcdr (Fcdr (info));
316 #if 0 /* We used to make the current buffer visible in the selected window
317 if that was true previously. That avoids some anomalies.
318 But it creates others, and it wasn't documented, and it is simpler
319 and cleaner never to alter the window/buffer connections. */
320 tem1 = Fcar (tem);
321 if (!NILP (tem1)
322 && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
323 Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
324 #endif /* 0 */
325
326 tem1 = current_buffer->mark_active;
327 current_buffer->mark_active = Fcdr (tem);
328 if (!NILP (Vrun_hooks))
329 {
330 /* If mark is active now, and either was not active
331 or was at a different place, run the activate hook. */
332 if (! NILP (current_buffer->mark_active))
333 {
334 if (! EQ (omark, nmark))
335 call1 (Vrun_hooks, intern ("activate-mark-hook"));
336 }
337 /* If mark has ceased to be active, run deactivate hook. */
338 else if (! NILP (tem1))
339 call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
340 }
341 return Qnil;
342 }
343
344 DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
345 "Save point, mark, and current buffer; execute BODY; restore those things.\n\
346 Executes BODY just like `progn'.\n\
347 The values of point, mark and the current buffer are restored\n\
348 even in case of abnormal exit (throw or error).\n\
349 The state of activation of the mark is also restored.")
350 (args)
351 Lisp_Object args;
352 {
353 register Lisp_Object val;
354 int count = specpdl_ptr - specpdl;
355
356 record_unwind_protect (save_excursion_restore, save_excursion_save ());
357
358 val = Fprogn (args);
359 return unbind_to (count, val);
360 }
361 \f
362 DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 0, 0,
363 "Return the number of characters in the current buffer.")
364 ()
365 {
366 Lisp_Object temp;
367 XSETFASTINT (temp, Z - BEG);
368 return temp;
369 }
370
371 DEFUN ("point-min", Fpoint_min, Spoint_min, 0, 0, 0,
372 "Return the minimum permissible value of point in the current buffer.\n\
373 This is 1, unless narrowing (a buffer restriction) is in effect.")
374 ()
375 {
376 Lisp_Object temp;
377 XSETFASTINT (temp, BEGV);
378 return temp;
379 }
380
381 DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
382 "Return a marker to the minimum permissible value of point in this buffer.\n\
383 This is the beginning, unless narrowing (a buffer restriction) is in effect.")
384 ()
385 {
386 return buildmark (BEGV);
387 }
388
389 DEFUN ("point-max", Fpoint_max, Spoint_max, 0, 0, 0,
390 "Return the maximum permissible value of point in the current buffer.\n\
391 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
392 is in effect, in which case it is less.")
393 ()
394 {
395 Lisp_Object temp;
396 XSETFASTINT (temp, ZV);
397 return temp;
398 }
399
400 DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
401 "Return a marker to the maximum permissible value of point in this buffer.\n\
402 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
403 is in effect, in which case it is less.")
404 ()
405 {
406 return buildmark (ZV);
407 }
408
409 DEFUN ("following-char", Ffollowing_char, Sfollowing_char, 0, 0, 0,
410 "Return the character following point, as a number.\n\
411 At the end of the buffer or accessible region, return 0.")
412 ()
413 {
414 Lisp_Object temp;
415 if (point >= ZV)
416 XSETFASTINT (temp, 0);
417 else
418 XSETFASTINT (temp, FETCH_CHAR (point));
419 return temp;
420 }
421
422 DEFUN ("preceding-char", Fprevious_char, Sprevious_char, 0, 0, 0,
423 "Return the character preceding point, as a number.\n\
424 At the beginning of the buffer or accessible region, return 0.")
425 ()
426 {
427 Lisp_Object temp;
428 if (point <= BEGV)
429 XSETFASTINT (temp, 0);
430 else
431 XSETFASTINT (temp, FETCH_CHAR (point - 1));
432 return temp;
433 }
434
435 DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0,
436 "Return T if point is at the beginning of the buffer.\n\
437 If the buffer is narrowed, this means the beginning of the narrowed part.")
438 ()
439 {
440 if (point == BEGV)
441 return Qt;
442 return Qnil;
443 }
444
445 DEFUN ("eobp", Feobp, Seobp, 0, 0, 0,
446 "Return T if point is at the end of the buffer.\n\
447 If the buffer is narrowed, this means the end of the narrowed part.")
448 ()
449 {
450 if (point == ZV)
451 return Qt;
452 return Qnil;
453 }
454
455 DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0,
456 "Return T if point is at the beginning of a line.")
457 ()
458 {
459 if (point == BEGV || FETCH_CHAR (point - 1) == '\n')
460 return Qt;
461 return Qnil;
462 }
463
464 DEFUN ("eolp", Feolp, Seolp, 0, 0, 0,
465 "Return T if point is at the end of a line.\n\
466 `End of a line' includes point being at the end of the buffer.")
467 ()
468 {
469 if (point == ZV || FETCH_CHAR (point) == '\n')
470 return Qt;
471 return Qnil;
472 }
473
474 DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
475 "Return character in current buffer at position POS.\n\
476 POS is an integer or a buffer pointer.\n\
477 If POS is out of range, the value is nil.")
478 (pos)
479 Lisp_Object pos;
480 {
481 register Lisp_Object val;
482 register int n;
483
484 CHECK_NUMBER_COERCE_MARKER (pos, 0);
485
486 n = XINT (pos);
487 if (n < BEGV || n >= ZV) return Qnil;
488
489 XSETFASTINT (val, FETCH_CHAR (n));
490 return val;
491 }
492 \f
493 DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 1, 0,
494 "Return the name under which the user logged in, as a string.\n\
495 This is based on the effective uid, not the real uid.\n\
496 Also, if the environment variable LOGNAME or USER is set,\n\
497 that determines the value of this function.\n\n\
498 If optional argument UID is an integer, return the login name of the user\n\
499 with that uid, or nil if there is no such user.")
500 (uid)
501 Lisp_Object uid;
502 {
503 struct passwd *pw;
504
505 /* Set up the user name info if we didn't do it before.
506 (That can happen if Emacs is dumpable
507 but you decide to run `temacs -l loadup' and not dump. */
508 if (INTEGERP (Vuser_name))
509 init_editfns ();
510
511 if (NILP (uid))
512 return Vuser_name;
513
514 CHECK_NUMBER (uid, 0);
515 pw = (struct passwd *) getpwuid (XINT (uid));
516 return (pw ? build_string (pw->pw_name) : Qnil);
517 }
518
519 DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
520 0, 0, 0,
521 "Return the name of the user's real uid, as a string.\n\
522 This ignores the environment variables LOGNAME and USER, so it differs from\n\
523 `user-login-name' when running under `su'.")
524 ()
525 {
526 /* Set up the user name info if we didn't do it before.
527 (That can happen if Emacs is dumpable
528 but you decide to run `temacs -l loadup' and not dump. */
529 if (INTEGERP (Vuser_name))
530 init_editfns ();
531 return Vuser_real_name;
532 }
533
534 DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
535 "Return the effective uid of Emacs, as an integer.")
536 ()
537 {
538 return make_number (geteuid ());
539 }
540
541 DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
542 "Return the real uid of Emacs, as an integer.")
543 ()
544 {
545 return make_number (getuid ());
546 }
547
548 DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 0, 0,
549 "Return the full name of the user logged in, as a string.")
550 ()
551 {
552 return Vuser_full_name;
553 }
554
555 DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
556 "Return the name of the machine you are running on, as a string.")
557 ()
558 {
559 return Vsystem_name;
560 }
561
562 /* For the benefit of callers who don't want to include lisp.h */
563 char *
564 get_system_name ()
565 {
566 return (char *) XSTRING (Vsystem_name)->data;
567 }
568
569 DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
570 "Return the process ID of Emacs, as an integer.")
571 ()
572 {
573 return make_number (getpid ());
574 }
575
576 DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
577 "Return the current time, as the number of seconds since 12:00 AM January 1970.\n\
578 The time is returned as a list of three integers. The first has the\n\
579 most significant 16 bits of the seconds, while the second has the\n\
580 least significant 16 bits. The third integer gives the microsecond\n\
581 count.\n\
582 \n\
583 The microsecond count is zero on systems that do not provide\n\
584 resolution finer than a second.")
585 ()
586 {
587 EMACS_TIME t;
588 Lisp_Object result[3];
589
590 EMACS_GET_TIME (t);
591 XSETINT (result[0], (EMACS_SECS (t) >> 16) & 0xffff);
592 XSETINT (result[1], (EMACS_SECS (t) >> 0) & 0xffff);
593 XSETINT (result[2], EMACS_USECS (t));
594
595 return Flist (3, result);
596 }
597 \f
598
599 static int
600 lisp_time_argument (specified_time, result)
601 Lisp_Object specified_time;
602 time_t *result;
603 {
604 if (NILP (specified_time))
605 return time (result) != -1;
606 else
607 {
608 Lisp_Object high, low;
609 high = Fcar (specified_time);
610 CHECK_NUMBER (high, 0);
611 low = Fcdr (specified_time);
612 if (CONSP (low))
613 low = Fcar (low);
614 CHECK_NUMBER (low, 0);
615 *result = (XINT (high) << 16) + (XINT (low) & 0xffff);
616 return *result >> 16 == XINT (high);
617 }
618 }
619
620 DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 2, 2, 0,
621 "Use FORMAT-STRING to format the time TIME.\n\
622 TIME is specified as (HIGH LOW . IGNORED) or (HIGH . LOW), as from\n\
623 `current-time' and `file-attributes'.\n\
624 FORMAT-STRING may contain %-sequences to substitute parts of the time.\n\
625 %a is replaced by the abbreviated name of the day of week.\n\
626 %A is replaced by the full name of the day of week.\n\
627 %b is replaced by the abbreviated name of the month.\n\
628 %B is replaced by the full name of the month.\n\
629 %c is a synonym for \"%x %X\".\n\
630 %C is a locale-specific synonym, which defaults to \"%A, %B %e, %Y\" in the C locale.\n\
631 %d is replaced by the day of month, zero-padded.\n\
632 %D is a synonym for \"%m/%d/%y\".\n\
633 %e is replaced by the day of month, blank-padded.\n\
634 %h is a synonym for \"%b\".\n\
635 %H is replaced by the hour (00-23).\n\
636 %I is replaced by the hour (00-12).\n\
637 %j is replaced by the day of the year (001-366).\n\
638 %k is replaced by the hour (0-23), blank padded.\n\
639 %l is replaced by the hour (1-12), blank padded.\n\
640 %m is replaced by the month (01-12).\n\
641 %M is replaced by the minut (00-59).\n\
642 %n is a synonym for \"\\n\".\n\
643 %p is replaced by AM or PM, as appropriate.\n\
644 %r is a synonym for \"%I:%M:%S %p\".\n\
645 %R is a synonym for \"%H:%M\".\n\
646 %S is replaced by the seconds (00-60).\n\
647 %t is a synonym for \"\\t\".\n\
648 %T is a synonym for \"%H:%M:%S\".\n\
649 %U is replaced by the week of the year (01-52), first day of week is Sunday.\n\
650 %w is replaced by the day of week (0-6), Sunday is day 0.\n\
651 %W is replaced by the week of the year (01-52), first day of week is Monday.\n\
652 %x is a locale-specific synonym, which defaults to \"%D\" in the C locale.\n\
653 %X is a locale-specific synonym, which defaults to \"%T\" in the C locale.\n\
654 %y is replaced by the year without century (00-99).\n\
655 %Y is replaced by the year with century.\n\
656 %Z is replaced by the time zone abbreviation.\n\
657 \n\
658 The number of options reflects the strftime(3) function.")
659 (format_string, time)
660 Lisp_Object format_string, time;
661 {
662 time_t value;
663 int size;
664
665 CHECK_STRING (format_string, 1);
666
667 if (! lisp_time_argument (time, &value))
668 error ("Invalid time specification");
669
670 /* This is probably enough. */
671 size = XSTRING (format_string)->size * 6 + 50;
672
673 while (1)
674 {
675 char *buf = (char *) alloca (size);
676 if (strftime (buf, size, XSTRING (format_string)->data,
677 localtime (&value)))
678 return build_string (buf);
679 /* If buffer was too small, make it bigger. */
680 size *= 2;
681 }
682 }
683
684 DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
685 "Return the current time, as a human-readable string.\n\
686 Programs can use this function to decode a time,\n\
687 since the number of columns in each field is fixed.\n\
688 The format is `Sun Sep 16 01:03:52 1973'.\n\
689 If an argument is given, it specifies a time to format\n\
690 instead of the current time. The argument should have the form:\n\
691 (HIGH . LOW)\n\
692 or the form:\n\
693 (HIGH LOW . IGNORED).\n\
694 Thus, you can use times obtained from `current-time'\n\
695 and from `file-attributes'.")
696 (specified_time)
697 Lisp_Object specified_time;
698 {
699 time_t value;
700 char buf[30];
701 register char *tem;
702
703 if (! lisp_time_argument (specified_time, &value))
704 value = -1;
705 tem = (char *) ctime (&value);
706
707 strncpy (buf, tem, 24);
708 buf[24] = 0;
709
710 return build_string (buf);
711 }
712
713 #define TM_YEAR_ORIGIN 1900
714
715 /* Yield A - B, measured in seconds. */
716 static long
717 difftm (a, b)
718 struct tm *a, *b;
719 {
720 int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
721 int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
722 /* Some compilers can't handle this as a single return statement. */
723 long days = (
724 /* difference in day of year */
725 a->tm_yday - b->tm_yday
726 /* + intervening leap days */
727 + ((ay >> 2) - (by >> 2))
728 - (ay/100 - by/100)
729 + ((ay/100 >> 2) - (by/100 >> 2))
730 /* + difference in years * 365 */
731 + (long)(ay-by) * 365
732 );
733 return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
734 + (a->tm_min - b->tm_min))
735 + (a->tm_sec - b->tm_sec));
736 }
737
738 DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0,
739 "Return the offset and name for the local time zone.\n\
740 This returns a list of the form (OFFSET NAME).\n\
741 OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).\n\
742 A negative value means west of Greenwich.\n\
743 NAME is a string giving the name of the time zone.\n\
744 If an argument is given, it specifies when the time zone offset is determined\n\
745 instead of using the current time. The argument should have the form:\n\
746 (HIGH . LOW)\n\
747 or the form:\n\
748 (HIGH LOW . IGNORED).\n\
749 Thus, you can use times obtained from `current-time'\n\
750 and from `file-attributes'.\n\
751 \n\
752 Some operating systems cannot provide all this information to Emacs;\n\
753 in this case, `current-time-zone' returns a list containing nil for\n\
754 the data it can't find.")
755 (specified_time)
756 Lisp_Object specified_time;
757 {
758 time_t value;
759 struct tm *t;
760
761 if (lisp_time_argument (specified_time, &value)
762 && (t = gmtime (&value)) != 0)
763 {
764 struct tm gmt;
765 long offset;
766 char *s, buf[6];
767
768 gmt = *t; /* Make a copy, in case localtime modifies *t. */
769 t = localtime (&value);
770 offset = difftm (t, &gmt);
771 s = 0;
772 #ifdef HAVE_TM_ZONE
773 if (t->tm_zone)
774 s = (char *)t->tm_zone;
775 #else /* not HAVE_TM_ZONE */
776 #ifdef HAVE_TZNAME
777 if (t->tm_isdst == 0 || t->tm_isdst == 1)
778 s = tzname[t->tm_isdst];
779 #endif
780 #endif /* not HAVE_TM_ZONE */
781 if (!s)
782 {
783 /* No local time zone name is available; use "+-NNNN" instead. */
784 int am = (offset < 0 ? -offset : offset) / 60;
785 sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
786 s = buf;
787 }
788 return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
789 }
790 else
791 return Fmake_list (2, Qnil);
792 }
793
794 \f
795 void
796 insert1 (arg)
797 Lisp_Object arg;
798 {
799 Finsert (1, &arg);
800 }
801
802
803 /* Callers passing one argument to Finsert need not gcpro the
804 argument "array", since the only element of the array will
805 not be used after calling insert or insert_from_string, so
806 we don't care if it gets trashed. */
807
808 DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
809 "Insert the arguments, either strings or characters, at point.\n\
810 Point moves forward so that it ends up after the inserted text.\n\
811 Any other markers at the point of insertion remain before the text.")
812 (nargs, args)
813 int nargs;
814 register Lisp_Object *args;
815 {
816 register int argnum;
817 register Lisp_Object tem;
818 char str[1];
819
820 for (argnum = 0; argnum < nargs; argnum++)
821 {
822 tem = args[argnum];
823 retry:
824 if (INTEGERP (tem))
825 {
826 str[0] = XINT (tem);
827 insert (str, 1);
828 }
829 else if (STRINGP (tem))
830 {
831 insert_from_string (tem, 0, XSTRING (tem)->size, 0);
832 }
833 else
834 {
835 tem = wrong_type_argument (Qchar_or_string_p, tem);
836 goto retry;
837 }
838 }
839
840 return Qnil;
841 }
842
843 DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit,
844 0, MANY, 0,
845 "Insert the arguments at point, inheriting properties from adjoining text.\n\
846 Point moves forward so that it ends up after the inserted text.\n\
847 Any other markers at the point of insertion remain before the text.")
848 (nargs, args)
849 int nargs;
850 register Lisp_Object *args;
851 {
852 register int argnum;
853 register Lisp_Object tem;
854 char str[1];
855
856 for (argnum = 0; argnum < nargs; argnum++)
857 {
858 tem = args[argnum];
859 retry:
860 if (INTEGERP (tem))
861 {
862 str[0] = XINT (tem);
863 insert_and_inherit (str, 1);
864 }
865 else if (STRINGP (tem))
866 {
867 insert_from_string (tem, 0, XSTRING (tem)->size, 1);
868 }
869 else
870 {
871 tem = wrong_type_argument (Qchar_or_string_p, tem);
872 goto retry;
873 }
874 }
875
876 return Qnil;
877 }
878
879 DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
880 "Insert strings or characters at point, relocating markers after the text.\n\
881 Point moves forward so that it ends up after the inserted text.\n\
882 Any other markers at the point of insertion also end up after the text.")
883 (nargs, args)
884 int nargs;
885 register Lisp_Object *args;
886 {
887 register int argnum;
888 register Lisp_Object tem;
889 char str[1];
890
891 for (argnum = 0; argnum < nargs; argnum++)
892 {
893 tem = args[argnum];
894 retry:
895 if (INTEGERP (tem))
896 {
897 str[0] = XINT (tem);
898 insert_before_markers (str, 1);
899 }
900 else if (STRINGP (tem))
901 {
902 insert_from_string_before_markers (tem, 0, XSTRING (tem)->size, 0);
903 }
904 else
905 {
906 tem = wrong_type_argument (Qchar_or_string_p, tem);
907 goto retry;
908 }
909 }
910
911 return Qnil;
912 }
913
914 DEFUN ("insert-before-markers-and-inherit",
915 Finsert_and_inherit_before_markers, Sinsert_and_inherit_before_markers,
916 0, MANY, 0,
917 "Insert text at point, relocating markers and inheriting properties.\n\
918 Point moves forward so that it ends up after the inserted text.\n\
919 Any other markers at the point of insertion also end up after the text.")
920 (nargs, args)
921 int nargs;
922 register Lisp_Object *args;
923 {
924 register int argnum;
925 register Lisp_Object tem;
926 char str[1];
927
928 for (argnum = 0; argnum < nargs; argnum++)
929 {
930 tem = args[argnum];
931 retry:
932 if (INTEGERP (tem))
933 {
934 str[0] = XINT (tem);
935 insert_before_markers_and_inherit (str, 1);
936 }
937 else if (STRINGP (tem))
938 {
939 insert_from_string_before_markers (tem, 0, XSTRING (tem)->size, 1);
940 }
941 else
942 {
943 tem = wrong_type_argument (Qchar_or_string_p, tem);
944 goto retry;
945 }
946 }
947
948 return Qnil;
949 }
950 \f
951 DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 3, 0,
952 "Insert COUNT (second arg) copies of CHAR (first arg).\n\
953 Point and all markers are affected as in the function `insert'.\n\
954 Both arguments are required.\n\
955 The optional third arg INHERIT, if non-nil, says to inherit text properties\n\
956 from adjoining text, if those properties are sticky.")
957 (chr, count, inherit)
958 Lisp_Object chr, count, inherit;
959 {
960 register unsigned char *string;
961 register int strlen;
962 register int i, n;
963
964 CHECK_NUMBER (chr, 0);
965 CHECK_NUMBER (count, 1);
966
967 n = XINT (count);
968 if (n <= 0)
969 return Qnil;
970 strlen = min (n, 256);
971 string = (unsigned char *) alloca (strlen);
972 for (i = 0; i < strlen; i++)
973 string[i] = XFASTINT (chr);
974 while (n >= strlen)
975 {
976 if (!NILP (inherit))
977 insert_and_inherit (string, strlen);
978 else
979 insert (string, strlen);
980 n -= strlen;
981 }
982 if (n > 0)
983 insert (string, n);
984 return Qnil;
985 }
986
987 \f
988 /* Making strings from buffer contents. */
989
990 /* Return a Lisp_String containing the text of the current buffer from
991 START to END. If text properties are in use and the current buffer
992 has properties in the range specified, the resulting string will also
993 have them.
994
995 We don't want to use plain old make_string here, because it calls
996 make_uninit_string, which can cause the buffer arena to be
997 compacted. make_string has no way of knowing that the data has
998 been moved, and thus copies the wrong data into the string. This
999 doesn't effect most of the other users of make_string, so it should
1000 be left as is. But we should use this function when conjuring
1001 buffer substrings. */
1002
1003 Lisp_Object
1004 make_buffer_string (start, end)
1005 int start, end;
1006 {
1007 Lisp_Object result, tem, tem1;
1008
1009 if (start < GPT && GPT < end)
1010 move_gap (start);
1011
1012 result = make_uninit_string (end - start);
1013 bcopy (&FETCH_CHAR (start), XSTRING (result)->data, end - start);
1014
1015 tem = Fnext_property_change (make_number (start), Qnil, make_number (end));
1016 tem1 = Ftext_properties_at (make_number (start), Qnil);
1017
1018 #ifdef USE_TEXT_PROPERTIES
1019 if (XINT (tem) != end || !NILP (tem1))
1020 copy_intervals_to_string (result, current_buffer, start, end - start);
1021 #endif
1022
1023 return result;
1024 }
1025
1026 DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
1027 "Return the contents of part of the current buffer as a string.\n\
1028 The two arguments START and END are character positions;\n\
1029 they can be in either order.")
1030 (b, e)
1031 Lisp_Object b, e;
1032 {
1033 register int beg, end;
1034
1035 validate_region (&b, &e);
1036 beg = XINT (b);
1037 end = XINT (e);
1038
1039 return make_buffer_string (beg, end);
1040 }
1041
1042 DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
1043 "Return the contents of the current buffer as a string.")
1044 ()
1045 {
1046 return make_buffer_string (BEGV, ZV);
1047 }
1048
1049 DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
1050 1, 3, 0,
1051 "Insert before point a substring of the contents of buffer BUFFER.\n\
1052 BUFFER may be a buffer or a buffer name.\n\
1053 Arguments START and END are character numbers specifying the substring.\n\
1054 They default to the beginning and the end of BUFFER.")
1055 (buf, b, e)
1056 Lisp_Object buf, b, e;
1057 {
1058 register int beg, end, temp, len, opoint, start;
1059 register struct buffer *bp;
1060 Lisp_Object buffer;
1061
1062 buffer = Fget_buffer (buf);
1063 if (NILP (buffer))
1064 nsberror (buf);
1065 bp = XBUFFER (buffer);
1066
1067 if (NILP (b))
1068 beg = BUF_BEGV (bp);
1069 else
1070 {
1071 CHECK_NUMBER_COERCE_MARKER (b, 0);
1072 beg = XINT (b);
1073 }
1074 if (NILP (e))
1075 end = BUF_ZV (bp);
1076 else
1077 {
1078 CHECK_NUMBER_COERCE_MARKER (e, 1);
1079 end = XINT (e);
1080 }
1081
1082 if (beg > end)
1083 temp = beg, beg = end, end = temp;
1084
1085 /* Move the gap or create enough gap in the current buffer. */
1086
1087 if (point != GPT)
1088 move_gap (point);
1089 if (GAP_SIZE < end - beg)
1090 make_gap (end - beg - GAP_SIZE);
1091
1092 len = end - beg;
1093 start = beg;
1094 opoint = point;
1095
1096 if (!(BUF_BEGV (bp) <= beg
1097 && beg <= end
1098 && end <= BUF_ZV (bp)))
1099 args_out_of_range (b, e);
1100
1101 /* Now the actual insertion will not do any gap motion,
1102 so it matters not if BUF is the current buffer. */
1103 if (beg < BUF_GPT (bp))
1104 {
1105 insert (BUF_CHAR_ADDRESS (bp, beg), min (end, BUF_GPT (bp)) - beg);
1106 beg = min (end, BUF_GPT (bp));
1107 }
1108 if (beg < end)
1109 insert (BUF_CHAR_ADDRESS (bp, beg), end - beg);
1110
1111 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
1112 graft_intervals_into_buffer (copy_intervals (bp->intervals, start, len),
1113 opoint, len, current_buffer, 0);
1114
1115 return Qnil;
1116 }
1117
1118 DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
1119 6, 6, 0,
1120 "Compare two substrings of two buffers; return result as number.\n\
1121 the value is -N if first string is less after N-1 chars,\n\
1122 +N if first string is greater after N-1 chars, or 0 if strings match.\n\
1123 Each substring is represented as three arguments: BUFFER, START and END.\n\
1124 That makes six args in all, three for each substring.\n\n\
1125 The value of `case-fold-search' in the current buffer\n\
1126 determines whether case is significant or ignored.")
1127 (buffer1, start1, end1, buffer2, start2, end2)
1128 Lisp_Object buffer1, start1, end1, buffer2, start2, end2;
1129 {
1130 register int begp1, endp1, begp2, endp2, temp, len1, len2, length, i;
1131 register struct buffer *bp1, *bp2;
1132 register unsigned char *trt
1133 = (!NILP (current_buffer->case_fold_search)
1134 ? XSTRING (current_buffer->case_canon_table)->data : 0);
1135
1136 /* Find the first buffer and its substring. */
1137
1138 if (NILP (buffer1))
1139 bp1 = current_buffer;
1140 else
1141 {
1142 Lisp_Object buf1;
1143 buf1 = Fget_buffer (buffer1);
1144 if (NILP (buf1))
1145 nsberror (buffer1);
1146 bp1 = XBUFFER (buf1);
1147 }
1148
1149 if (NILP (start1))
1150 begp1 = BUF_BEGV (bp1);
1151 else
1152 {
1153 CHECK_NUMBER_COERCE_MARKER (start1, 1);
1154 begp1 = XINT (start1);
1155 }
1156 if (NILP (end1))
1157 endp1 = BUF_ZV (bp1);
1158 else
1159 {
1160 CHECK_NUMBER_COERCE_MARKER (end1, 2);
1161 endp1 = XINT (end1);
1162 }
1163
1164 if (begp1 > endp1)
1165 temp = begp1, begp1 = endp1, endp1 = temp;
1166
1167 if (!(BUF_BEGV (bp1) <= begp1
1168 && begp1 <= endp1
1169 && endp1 <= BUF_ZV (bp1)))
1170 args_out_of_range (start1, end1);
1171
1172 /* Likewise for second substring. */
1173
1174 if (NILP (buffer2))
1175 bp2 = current_buffer;
1176 else
1177 {
1178 Lisp_Object buf2;
1179 buf2 = Fget_buffer (buffer2);
1180 if (NILP (buf2))
1181 nsberror (buffer2);
1182 bp2 = XBUFFER (buffer2);
1183 }
1184
1185 if (NILP (start2))
1186 begp2 = BUF_BEGV (bp2);
1187 else
1188 {
1189 CHECK_NUMBER_COERCE_MARKER (start2, 4);
1190 begp2 = XINT (start2);
1191 }
1192 if (NILP (end2))
1193 endp2 = BUF_ZV (bp2);
1194 else
1195 {
1196 CHECK_NUMBER_COERCE_MARKER (end2, 5);
1197 endp2 = XINT (end2);
1198 }
1199
1200 if (begp2 > endp2)
1201 temp = begp2, begp2 = endp2, endp2 = temp;
1202
1203 if (!(BUF_BEGV (bp2) <= begp2
1204 && begp2 <= endp2
1205 && endp2 <= BUF_ZV (bp2)))
1206 args_out_of_range (start2, end2);
1207
1208 len1 = endp1 - begp1;
1209 len2 = endp2 - begp2;
1210 length = len1;
1211 if (len2 < length)
1212 length = len2;
1213
1214 for (i = 0; i < length; i++)
1215 {
1216 int c1 = *BUF_CHAR_ADDRESS (bp1, begp1 + i);
1217 int c2 = *BUF_CHAR_ADDRESS (bp2, begp2 + i);
1218 if (trt)
1219 {
1220 c1 = trt[c1];
1221 c2 = trt[c2];
1222 }
1223 if (c1 < c2)
1224 return make_number (- 1 - i);
1225 if (c1 > c2)
1226 return make_number (i + 1);
1227 }
1228
1229 /* The strings match as far as they go.
1230 If one is shorter, that one is less. */
1231 if (length < len1)
1232 return make_number (length + 1);
1233 else if (length < len2)
1234 return make_number (- length - 1);
1235
1236 /* Same length too => they are equal. */
1237 return make_number (0);
1238 }
1239 \f
1240 DEFUN ("subst-char-in-region", Fsubst_char_in_region,
1241 Ssubst_char_in_region, 4, 5, 0,
1242 "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
1243 If optional arg NOUNDO is non-nil, don't record this change for undo\n\
1244 and don't mark the buffer as really changed.")
1245 (start, end, fromchar, tochar, noundo)
1246 Lisp_Object start, end, fromchar, tochar, noundo;
1247 {
1248 register int pos, stop, look;
1249 int changed = 0;
1250
1251 validate_region (&start, &end);
1252 CHECK_NUMBER (fromchar, 2);
1253 CHECK_NUMBER (tochar, 3);
1254
1255 pos = XINT (start);
1256 stop = XINT (end);
1257 look = XINT (fromchar);
1258
1259 while (pos < stop)
1260 {
1261 if (FETCH_CHAR (pos) == look)
1262 {
1263 if (! changed)
1264 {
1265 modify_region (current_buffer, XINT (start), stop);
1266
1267 if (! NILP (noundo))
1268 {
1269 if (MODIFF - 1 == current_buffer->save_modified)
1270 current_buffer->save_modified++;
1271 if (MODIFF - 1 == current_buffer->auto_save_modified)
1272 current_buffer->auto_save_modified++;
1273 }
1274
1275 changed = 1;
1276 }
1277
1278 if (NILP (noundo))
1279 record_change (pos, 1);
1280 FETCH_CHAR (pos) = XINT (tochar);
1281 }
1282 pos++;
1283 }
1284
1285 if (changed)
1286 signal_after_change (XINT (start),
1287 stop - XINT (start), stop - XINT (start));
1288
1289 return Qnil;
1290 }
1291
1292 DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0,
1293 "From START to END, translate characters according to TABLE.\n\
1294 TABLE is a string; the Nth character in it is the mapping\n\
1295 for the character with code N. Returns the number of characters changed.")
1296 (start, end, table)
1297 Lisp_Object start;
1298 Lisp_Object end;
1299 register Lisp_Object table;
1300 {
1301 register int pos, stop; /* Limits of the region. */
1302 register unsigned char *tt; /* Trans table. */
1303 register int oc; /* Old character. */
1304 register int nc; /* New character. */
1305 int cnt; /* Number of changes made. */
1306 Lisp_Object z; /* Return. */
1307 int size; /* Size of translate table. */
1308
1309 validate_region (&start, &end);
1310 CHECK_STRING (table, 2);
1311
1312 size = XSTRING (table)->size;
1313 tt = XSTRING (table)->data;
1314
1315 pos = XINT (start);
1316 stop = XINT (end);
1317 modify_region (current_buffer, pos, stop);
1318
1319 cnt = 0;
1320 for (; pos < stop; ++pos)
1321 {
1322 oc = FETCH_CHAR (pos);
1323 if (oc < size)
1324 {
1325 nc = tt[oc];
1326 if (nc != oc)
1327 {
1328 record_change (pos, 1);
1329 FETCH_CHAR (pos) = nc;
1330 signal_after_change (pos, 1, 1);
1331 ++cnt;
1332 }
1333 }
1334 }
1335
1336 XSETFASTINT (z, cnt);
1337 return (z);
1338 }
1339
1340 DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
1341 "Delete the text between point and mark.\n\
1342 When called from a program, expects two arguments,\n\
1343 positions (integers or markers) specifying the stretch to be deleted.")
1344 (b, e)
1345 Lisp_Object b, e;
1346 {
1347 validate_region (&b, &e);
1348 del_range (XINT (b), XINT (e));
1349 return Qnil;
1350 }
1351 \f
1352 DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
1353 "Remove restrictions (narrowing) from current buffer.\n\
1354 This allows the buffer's full text to be seen and edited.")
1355 ()
1356 {
1357 BEGV = BEG;
1358 SET_BUF_ZV (current_buffer, Z);
1359 clip_changed = 1;
1360 /* Changing the buffer bounds invalidates any recorded current column. */
1361 invalidate_current_column ();
1362 return Qnil;
1363 }
1364
1365 DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
1366 "Restrict editing in this buffer to the current region.\n\
1367 The rest of the text becomes temporarily invisible and untouchable\n\
1368 but is not deleted; if you save the buffer in a file, the invisible\n\
1369 text is included in the file. \\[widen] makes all visible again.\n\
1370 See also `save-restriction'.\n\
1371 \n\
1372 When calling from a program, pass two arguments; positions (integers\n\
1373 or markers) bounding the text that should remain visible.")
1374 (b, e)
1375 register Lisp_Object b, e;
1376 {
1377 register EMACS_INT i;
1378
1379 CHECK_NUMBER_COERCE_MARKER (b, 0);
1380 CHECK_NUMBER_COERCE_MARKER (e, 1);
1381
1382 if (XINT (b) > XINT (e))
1383 {
1384 i = XFASTINT (b);
1385 b = e;
1386 XSETFASTINT (e, i);
1387 }
1388
1389 if (!(BEG <= XINT (b) && XINT (b) <= XINT (e) && XINT (e) <= Z))
1390 args_out_of_range (b, e);
1391
1392 BEGV = XFASTINT (b);
1393 SET_BUF_ZV (current_buffer, XFASTINT (e));
1394 if (point < XFASTINT (b))
1395 SET_PT (XFASTINT (b));
1396 if (point > XFASTINT (e))
1397 SET_PT (XFASTINT (e));
1398 clip_changed = 1;
1399 /* Changing the buffer bounds invalidates any recorded current column. */
1400 invalidate_current_column ();
1401 return Qnil;
1402 }
1403
1404 Lisp_Object
1405 save_restriction_save ()
1406 {
1407 register Lisp_Object bottom, top;
1408 /* Note: I tried using markers here, but it does not win
1409 because insertion at the end of the saved region
1410 does not advance mh and is considered "outside" the saved region. */
1411 XSETFASTINT (bottom, BEGV - BEG);
1412 XSETFASTINT (top, Z - ZV);
1413
1414 return Fcons (Fcurrent_buffer (), Fcons (bottom, top));
1415 }
1416
1417 Lisp_Object
1418 save_restriction_restore (data)
1419 Lisp_Object data;
1420 {
1421 register struct buffer *buf;
1422 register int newhead, newtail;
1423 register Lisp_Object tem;
1424
1425 buf = XBUFFER (XCONS (data)->car);
1426
1427 data = XCONS (data)->cdr;
1428
1429 tem = XCONS (data)->car;
1430 newhead = XINT (tem);
1431 tem = XCONS (data)->cdr;
1432 newtail = XINT (tem);
1433 if (newhead + newtail > BUF_Z (buf) - BUF_BEG (buf))
1434 {
1435 newhead = 0;
1436 newtail = 0;
1437 }
1438 BUF_BEGV (buf) = BUF_BEG (buf) + newhead;
1439 SET_BUF_ZV (buf, BUF_Z (buf) - newtail);
1440 clip_changed = 1;
1441
1442 /* If point is outside the new visible range, move it inside. */
1443 SET_BUF_PT (buf,
1444 clip_to_bounds (BUF_BEGV (buf), BUF_PT (buf), BUF_ZV (buf)));
1445
1446 return Qnil;
1447 }
1448
1449 DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
1450 "Execute BODY, saving and restoring current buffer's restrictions.\n\
1451 The buffer's restrictions make parts of the beginning and end invisible.\n\
1452 \(They are set up with `narrow-to-region' and eliminated with `widen'.)\n\
1453 This special form, `save-restriction', saves the current buffer's restrictions\n\
1454 when it is entered, and restores them when it is exited.\n\
1455 So any `narrow-to-region' within BODY lasts only until the end of the form.\n\
1456 The old restrictions settings are restored\n\
1457 even in case of abnormal exit (throw or error).\n\
1458 \n\
1459 The value returned is the value of the last form in BODY.\n\
1460 \n\
1461 `save-restriction' can get confused if, within the BODY, you widen\n\
1462 and then make changes outside the area within the saved restrictions.\n\
1463 \n\
1464 Note: if you are using both `save-excursion' and `save-restriction',\n\
1465 use `save-excursion' outermost:\n\
1466 (save-excursion (save-restriction ...))")
1467 (body)
1468 Lisp_Object body;
1469 {
1470 register Lisp_Object val;
1471 int count = specpdl_ptr - specpdl;
1472
1473 record_unwind_protect (save_restriction_restore, save_restriction_save ());
1474 val = Fprogn (body);
1475 return unbind_to (count, val);
1476 }
1477 \f
1478 /* Buffer for the most recent text displayed by Fmessage. */
1479 static char *message_text;
1480
1481 /* Allocated length of that buffer. */
1482 static int message_length;
1483
1484 DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
1485 "Print a one-line message at the bottom of the screen.\n\
1486 The first argument is a control string.\n\
1487 It may contain %s or %d or %c to print successive following arguments.\n\
1488 %s means print an argument as a string, %d means print as number in decimal,\n\
1489 %c means print a number as a single character.\n\
1490 The argument used by %s must be a string or a symbol;\n\
1491 the argument used by %d or %c must be a number.\n\
1492 If the first argument is nil, clear any existing message; let the\n\
1493 minibuffer contents show.")
1494 (nargs, args)
1495 int nargs;
1496 Lisp_Object *args;
1497 {
1498 if (NILP (args[0]))
1499 {
1500 message (0);
1501 return Qnil;
1502 }
1503 else
1504 {
1505 register Lisp_Object val;
1506 val = Fformat (nargs, args);
1507 /* Copy the data so that it won't move when we GC. */
1508 if (! message_text)
1509 {
1510 message_text = (char *)xmalloc (80);
1511 message_length = 80;
1512 }
1513 if (XSTRING (val)->size > message_length)
1514 {
1515 message_length = XSTRING (val)->size;
1516 message_text = (char *)xrealloc (message_text, message_length);
1517 }
1518 bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size);
1519 message2 (message_text, XSTRING (val)->size);
1520 return val;
1521 }
1522 }
1523
1524 DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0,
1525 "Display a message, in a dialog box if possible.\n\
1526 If a dialog box is not available, use the echo area.\n\
1527 The first argument is a control string.\n\
1528 It may contain %s or %d or %c to print successive following arguments.\n\
1529 %s means print an argument as a string, %d means print as number in decimal,\n\
1530 %c means print a number as a single character.\n\
1531 The argument used by %s must be a string or a symbol;\n\
1532 the argument used by %d or %c must be a number.\n\
1533 If the first argument is nil, clear any existing message; let the\n\
1534 minibuffer contents show.")
1535 (nargs, args)
1536 int nargs;
1537 Lisp_Object *args;
1538 {
1539 if (NILP (args[0]))
1540 {
1541 message (0);
1542 return Qnil;
1543 }
1544 else
1545 {
1546 register Lisp_Object val;
1547 val = Fformat (nargs, args);
1548 #ifdef HAVE_X_MENU
1549 {
1550 Lisp_Object pane, menu, obj;
1551 struct gcpro gcpro1;
1552 pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
1553 GCPRO1 (pane);
1554 menu = Fcons (val, pane);
1555 obj = Fx_popup_dialog (Qt, menu);
1556 UNGCPRO;
1557 return val;
1558 }
1559 #else
1560 /* Copy the data so that it won't move when we GC. */
1561 if (! message_text)
1562 {
1563 message_text = (char *)xmalloc (80);
1564 message_length = 80;
1565 }
1566 if (XSTRING (val)->size > message_length)
1567 {
1568 message_length = XSTRING (val)->size;
1569 message_text = (char *)xrealloc (message_text, message_length);
1570 }
1571 bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size);
1572 message2 (message_text, XSTRING (val)->size);
1573 return val;
1574 #endif
1575 }
1576 }
1577 #ifdef HAVE_X_MENU
1578 extern Lisp_Object last_nonmenu_event;
1579 #endif
1580 DEFUN ("message-or-box", Fmessage_or_box, Smessage_or_box, 1, MANY, 0,
1581 "Display a message in a dialog box or in the echo area.\n\
1582 If this command was invoked with the mouse, use a dialog box.\n\
1583 Otherwise, use the echo area.\n\
1584 \n\
1585 The first argument is a control string.\n\
1586 It may contain %s or %d or %c to print successive following arguments.\n\
1587 %s means print an argument as a string, %d means print as number in decimal,\n\
1588 %c means print a number as a single character.\n\
1589 The argument used by %s must be a string or a symbol;\n\
1590 the argument used by %d or %c must be a number.\n\
1591 If the first argument is nil, clear any existing message; let the\n\
1592 minibuffer contents show.")
1593 (nargs, args)
1594 int nargs;
1595 Lisp_Object *args;
1596 {
1597 #ifdef HAVE_X_MENU
1598 if (NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
1599 return Fmessage_box (nargs, args);
1600 #endif
1601 return Fmessage (nargs, args);
1602 }
1603
1604 DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
1605 "Format a string out of a control-string and arguments.\n\
1606 The first argument is a control string.\n\
1607 The other arguments are substituted into it to make the result, a string.\n\
1608 It may contain %-sequences meaning to substitute the next argument.\n\
1609 %s means print a string argument. Actually, prints any object, with `princ'.\n\
1610 %d means print as number in decimal (%o octal, %x hex).\n\
1611 %c means print a number as a single character.\n\
1612 %S means print any object as an s-expression (using prin1).\n\
1613 The argument used for %d, %o, %x or %c must be a number.\n\
1614 Use %% to put a single % into the output.")
1615 (nargs, args)
1616 int nargs;
1617 register Lisp_Object *args;
1618 {
1619 register int n; /* The number of the next arg to substitute */
1620 register int total = 5; /* An estimate of the final length */
1621 char *buf;
1622 register unsigned char *format, *end;
1623 int length;
1624 extern char *index ();
1625 /* It should not be necessary to GCPRO ARGS, because
1626 the caller in the interpreter should take care of that. */
1627
1628 CHECK_STRING (args[0], 0);
1629 format = XSTRING (args[0])->data;
1630 end = format + XSTRING (args[0])->size;
1631
1632 n = 0;
1633 while (format != end)
1634 if (*format++ == '%')
1635 {
1636 int minlen;
1637
1638 /* Process a numeric arg and skip it. */
1639 minlen = atoi (format);
1640 if (minlen > 0)
1641 total += minlen;
1642 else
1643 total -= minlen;
1644 while ((*format >= '0' && *format <= '9')
1645 || *format == '-' || *format == ' ' || *format == '.')
1646 format++;
1647
1648 if (*format == '%')
1649 format++;
1650 else if (++n >= nargs)
1651 error ("not enough arguments for format string");
1652 else if (*format == 'S')
1653 {
1654 /* For `S', prin1 the argument and then treat like a string. */
1655 register Lisp_Object tem;
1656 tem = Fprin1_to_string (args[n], Qnil);
1657 args[n] = tem;
1658 goto string;
1659 }
1660 else if (SYMBOLP (args[n]))
1661 {
1662 XSETSTRING (args[n], XSYMBOL (args[n])->name);
1663 goto string;
1664 }
1665 else if (STRINGP (args[n]))
1666 {
1667 string:
1668 if (*format != 's' && *format != 'S')
1669 error ("format specifier doesn't match argument type");
1670 total += XSTRING (args[n])->size;
1671 }
1672 /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
1673 else if (INTEGERP (args[n]) && *format != 's')
1674 {
1675 #ifdef LISP_FLOAT_TYPE
1676 /* The following loop assumes the Lisp type indicates
1677 the proper way to pass the argument.
1678 So make sure we have a flonum if the argument should
1679 be a double. */
1680 if (*format == 'e' || *format == 'f' || *format == 'g')
1681 args[n] = Ffloat (args[n]);
1682 #endif
1683 total += 10;
1684 }
1685 #ifdef LISP_FLOAT_TYPE
1686 else if (FLOATP (args[n]) && *format != 's')
1687 {
1688 if (! (*format == 'e' || *format == 'f' || *format == 'g'))
1689 args[n] = Ftruncate (args[n]);
1690 total += 20;
1691 }
1692 #endif
1693 else
1694 {
1695 /* Anything but a string, convert to a string using princ. */
1696 register Lisp_Object tem;
1697 tem = Fprin1_to_string (args[n], Qt);
1698 args[n] = tem;
1699 goto string;
1700 }
1701 }
1702
1703 {
1704 register int nstrings = n + 1;
1705
1706 /* Allocate twice as many strings as we have %-escapes; floats occupy
1707 two slots, and we're not sure how many of those we have. */
1708 register unsigned char **strings
1709 = (unsigned char **) alloca (2 * nstrings * sizeof (unsigned char *));
1710 int i;
1711
1712 i = 0;
1713 for (n = 0; n < nstrings; n++)
1714 {
1715 if (n >= nargs)
1716 strings[i++] = (unsigned char *) "";
1717 else if (INTEGERP (args[n]))
1718 /* We checked above that the corresponding format effector
1719 isn't %s, which would cause MPV. */
1720 strings[i++] = (unsigned char *) XINT (args[n]);
1721 #ifdef LISP_FLOAT_TYPE
1722 else if (FLOATP (args[n]))
1723 {
1724 union { double d; int half[2]; } u;
1725
1726 u.d = XFLOAT (args[n])->data;
1727 strings[i++] = (unsigned char *) u.half[0];
1728 strings[i++] = (unsigned char *) u.half[1];
1729 }
1730 #endif
1731 else
1732 strings[i++] = XSTRING (args[n])->data;
1733 }
1734
1735 /* Format it in bigger and bigger buf's until it all fits. */
1736 while (1)
1737 {
1738 buf = (char *) alloca (total + 1);
1739 buf[total - 1] = 0;
1740
1741 length = doprnt (buf, total + 1, strings[0], end, i-1, strings + 1);
1742 if (buf[total - 1] == 0)
1743 break;
1744
1745 total *= 2;
1746 }
1747 }
1748
1749 /* UNGCPRO; */
1750 return make_string (buf, length);
1751 }
1752
1753 /* VARARGS 1 */
1754 Lisp_Object
1755 #ifdef NO_ARG_ARRAY
1756 format1 (string1, arg0, arg1, arg2, arg3, arg4)
1757 EMACS_INT arg0, arg1, arg2, arg3, arg4;
1758 #else
1759 format1 (string1)
1760 #endif
1761 char *string1;
1762 {
1763 char buf[100];
1764 #ifdef NO_ARG_ARRAY
1765 EMACS_INT args[5];
1766 args[0] = arg0;
1767 args[1] = arg1;
1768 args[2] = arg2;
1769 args[3] = arg3;
1770 args[4] = arg4;
1771 doprnt (buf, sizeof buf, string1, 0, 5, args);
1772 #else
1773 doprnt (buf, sizeof buf, string1, 0, 5, &string1 + 1);
1774 #endif
1775 return build_string (buf);
1776 }
1777 \f
1778 DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
1779 "Return t if two characters match, optionally ignoring case.\n\
1780 Both arguments must be characters (i.e. integers).\n\
1781 Case is ignored if `case-fold-search' is non-nil in the current buffer.")
1782 (c1, c2)
1783 register Lisp_Object c1, c2;
1784 {
1785 unsigned char *downcase = DOWNCASE_TABLE;
1786 CHECK_NUMBER (c1, 0);
1787 CHECK_NUMBER (c2, 1);
1788
1789 if (!NILP (current_buffer->case_fold_search)
1790 ? (downcase[0xff & XFASTINT (c1)] == downcase[0xff & XFASTINT (c2)]
1791 && (XFASTINT (c1) & ~0xff) == (XFASTINT (c2) & ~0xff))
1792 : XINT (c1) == XINT (c2))
1793 return Qt;
1794 return Qnil;
1795 }
1796 \f
1797 /* Transpose the markers in two regions of the current buffer, and
1798 adjust the ones between them if necessary (i.e.: if the regions
1799 differ in size).
1800
1801 Traverses the entire marker list of the buffer to do so, adding an
1802 appropriate amount to some, subtracting from some, and leaving the
1803 rest untouched. Most of this is copied from adjust_markers in insdel.c.
1804
1805 It's the caller's job to see that (start1 <= end1 <= start2 <= end2). */
1806
1807 void
1808 transpose_markers (start1, end1, start2, end2)
1809 register int start1, end1, start2, end2;
1810 {
1811 register int amt1, amt2, diff, mpos;
1812 register Lisp_Object marker;
1813
1814 /* Update point as if it were a marker. */
1815 if (PT < start1)
1816 ;
1817 else if (PT < end1)
1818 TEMP_SET_PT (PT + (end2 - end1));
1819 else if (PT < start2)
1820 TEMP_SET_PT (PT + (end2 - start2) - (end1 - start1));
1821 else if (PT < end2)
1822 TEMP_SET_PT (PT - (start2 - start1));
1823
1824 /* We used to adjust the endpoints here to account for the gap, but that
1825 isn't good enough. Even if we assume the caller has tried to move the
1826 gap out of our way, it might still be at start1 exactly, for example;
1827 and that places it `inside' the interval, for our purposes. The amount
1828 of adjustment is nontrivial if there's a `denormalized' marker whose
1829 position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
1830 the dirty work to Fmarker_position, below. */
1831
1832 /* The difference between the region's lengths */
1833 diff = (end2 - start2) - (end1 - start1);
1834
1835 /* For shifting each marker in a region by the length of the other
1836 * region plus the distance between the regions.
1837 */
1838 amt1 = (end2 - start2) + (start2 - end1);
1839 amt2 = (end1 - start1) + (start2 - end1);
1840
1841 for (marker = current_buffer->markers; !NILP (marker);
1842 marker = XMARKER (marker)->chain)
1843 {
1844 mpos = Fmarker_position (marker);
1845 if (mpos >= start1 && mpos < end2)
1846 {
1847 if (mpos < end1)
1848 mpos += amt1;
1849 else if (mpos < start2)
1850 mpos += diff;
1851 else
1852 mpos -= amt2;
1853 if (mpos > GPT) mpos += GAP_SIZE;
1854 XMARKER (marker)->bufpos = mpos;
1855 }
1856 }
1857 }
1858
1859 DEFUN ("transpose-regions", Ftranspose_regions, Stranspose_regions, 4, 5, 0,
1860 "Transpose region START1 to END1 with START2 to END2.\n\
1861 The regions may not be overlapping, because the size of the buffer is\n\
1862 never changed in a transposition.\n\
1863 \n\
1864 Optional fifth arg LEAVE_MARKERS, if non-nil, means don't transpose\n\
1865 any markers that happen to be located in the regions.\n\
1866 \n\
1867 Transposing beyond buffer boundaries is an error.")
1868 (startr1, endr1, startr2, endr2, leave_markers)
1869 Lisp_Object startr1, endr1, startr2, endr2, leave_markers;
1870 {
1871 register int start1, end1, start2, end2,
1872 gap, len1, len_mid, len2;
1873 unsigned char *start1_addr, *start2_addr, *temp;
1874
1875 #ifdef USE_TEXT_PROPERTIES
1876 INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2;
1877 cur_intv = current_buffer->intervals;
1878 #endif /* USE_TEXT_PROPERTIES */
1879
1880 validate_region (&startr1, &endr1);
1881 validate_region (&startr2, &endr2);
1882
1883 start1 = XFASTINT (startr1);
1884 end1 = XFASTINT (endr1);
1885 start2 = XFASTINT (startr2);
1886 end2 = XFASTINT (endr2);
1887 gap = GPT;
1888
1889 /* Swap the regions if they're reversed. */
1890 if (start2 < end1)
1891 {
1892 register int glumph = start1;
1893 start1 = start2;
1894 start2 = glumph;
1895 glumph = end1;
1896 end1 = end2;
1897 end2 = glumph;
1898 }
1899
1900 len1 = end1 - start1;
1901 len2 = end2 - start2;
1902
1903 if (start2 < end1)
1904 error ("transposed regions not properly ordered");
1905 else if (start1 == end1 || start2 == end2)
1906 error ("transposed region may not be of length 0");
1907
1908 /* The possibilities are:
1909 1. Adjacent (contiguous) regions, or separate but equal regions
1910 (no, really equal, in this case!), or
1911 2. Separate regions of unequal size.
1912
1913 The worst case is usually No. 2. It means that (aside from
1914 potential need for getting the gap out of the way), there also
1915 needs to be a shifting of the text between the two regions. So
1916 if they are spread far apart, we are that much slower... sigh. */
1917
1918 /* It must be pointed out that the really studly thing to do would
1919 be not to move the gap at all, but to leave it in place and work
1920 around it if necessary. This would be extremely efficient,
1921 especially considering that people are likely to do
1922 transpositions near where they are working interactively, which
1923 is exactly where the gap would be found. However, such code
1924 would be much harder to write and to read. So, if you are
1925 reading this comment and are feeling squirrely, by all means have
1926 a go! I just didn't feel like doing it, so I will simply move
1927 the gap the minimum distance to get it out of the way, and then
1928 deal with an unbroken array. */
1929
1930 /* Make sure the gap won't interfere, by moving it out of the text
1931 we will operate on. */
1932 if (start1 < gap && gap < end2)
1933 {
1934 if (gap - start1 < end2 - gap)
1935 move_gap (start1);
1936 else
1937 move_gap (end2);
1938 }
1939
1940 /* Hmmm... how about checking to see if the gap is large
1941 enough to use as the temporary storage? That would avoid an
1942 allocation... interesting. Later, don't fool with it now. */
1943
1944 /* Working without memmove, for portability (sigh), so must be
1945 careful of overlapping subsections of the array... */
1946
1947 if (end1 == start2) /* adjacent regions */
1948 {
1949 modify_region (current_buffer, start1, end2);
1950 record_change (start1, len1 + len2);
1951
1952 #ifdef USE_TEXT_PROPERTIES
1953 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
1954 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
1955 Fset_text_properties (start1, end2, Qnil, Qnil);
1956 #endif /* USE_TEXT_PROPERTIES */
1957
1958 /* First region smaller than second. */
1959 if (len1 < len2)
1960 {
1961 /* We use alloca only if it is small,
1962 because we want to avoid stack overflow. */
1963 if (len2 > 20000)
1964 temp = (unsigned char *) xmalloc (len2);
1965 else
1966 temp = (unsigned char *) alloca (len2);
1967
1968 /* Don't precompute these addresses. We have to compute them
1969 at the last minute, because the relocating allocator might
1970 have moved the buffer around during the xmalloc. */
1971 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
1972 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
1973
1974 bcopy (start2_addr, temp, len2);
1975 bcopy (start1_addr, start1_addr + len2, len1);
1976 bcopy (temp, start1_addr, len2);
1977 if (len2 > 20000)
1978 free (temp);
1979 }
1980 else
1981 /* First region not smaller than second. */
1982 {
1983 if (len1 > 20000)
1984 temp = (unsigned char *) xmalloc (len1);
1985 else
1986 temp = (unsigned char *) alloca (len1);
1987 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
1988 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
1989 bcopy (start1_addr, temp, len1);
1990 bcopy (start2_addr, start1_addr, len2);
1991 bcopy (temp, start1_addr + len2, len1);
1992 if (len1 > 20000)
1993 free (temp);
1994 }
1995 #ifdef USE_TEXT_PROPERTIES
1996 graft_intervals_into_buffer (tmp_interval1, start1 + len2,
1997 len1, current_buffer, 0);
1998 graft_intervals_into_buffer (tmp_interval2, start1,
1999 len2, current_buffer, 0);
2000 #endif /* USE_TEXT_PROPERTIES */
2001 }
2002 /* Non-adjacent regions, because end1 != start2, bleagh... */
2003 else
2004 {
2005 if (len1 == len2)
2006 /* Regions are same size, though, how nice. */
2007 {
2008 modify_region (current_buffer, start1, end1);
2009 modify_region (current_buffer, start2, end2);
2010 record_change (start1, len1);
2011 record_change (start2, len2);
2012 #ifdef USE_TEXT_PROPERTIES
2013 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
2014 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
2015 Fset_text_properties (start1, end1, Qnil, Qnil);
2016 Fset_text_properties (start2, end2, Qnil, Qnil);
2017 #endif /* USE_TEXT_PROPERTIES */
2018
2019 if (len1 > 20000)
2020 temp = (unsigned char *) xmalloc (len1);
2021 else
2022 temp = (unsigned char *) alloca (len1);
2023 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2024 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2025 bcopy (start1_addr, temp, len1);
2026 bcopy (start2_addr, start1_addr, len2);
2027 bcopy (temp, start2_addr, len1);
2028 if (len1 > 20000)
2029 free (temp);
2030 #ifdef USE_TEXT_PROPERTIES
2031 graft_intervals_into_buffer (tmp_interval1, start2,
2032 len1, current_buffer, 0);
2033 graft_intervals_into_buffer (tmp_interval2, start1,
2034 len2, current_buffer, 0);
2035 #endif /* USE_TEXT_PROPERTIES */
2036 }
2037
2038 else if (len1 < len2) /* Second region larger than first */
2039 /* Non-adjacent & unequal size, area between must also be shifted. */
2040 {
2041 len_mid = start2 - end1;
2042 modify_region (current_buffer, start1, end2);
2043 record_change (start1, (end2 - start1));
2044 #ifdef USE_TEXT_PROPERTIES
2045 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
2046 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
2047 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
2048 Fset_text_properties (start1, end2, Qnil, Qnil);
2049 #endif /* USE_TEXT_PROPERTIES */
2050
2051 /* holds region 2 */
2052 if (len2 > 20000)
2053 temp = (unsigned char *) xmalloc (len2);
2054 else
2055 temp = (unsigned char *) alloca (len2);
2056 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2057 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2058 bcopy (start2_addr, temp, len2);
2059 bcopy (start1_addr, start1_addr + len_mid + len2, len1);
2060 safe_bcopy (start1_addr + len1, start1_addr + len2, len_mid);
2061 bcopy (temp, start1_addr, len2);
2062 if (len2 > 20000)
2063 free (temp);
2064 #ifdef USE_TEXT_PROPERTIES
2065 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
2066 len1, current_buffer, 0);
2067 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
2068 len_mid, current_buffer, 0);
2069 graft_intervals_into_buffer (tmp_interval2, start1,
2070 len2, current_buffer, 0);
2071 #endif /* USE_TEXT_PROPERTIES */
2072 }
2073 else
2074 /* Second region smaller than first. */
2075 {
2076 len_mid = start2 - end1;
2077 record_change (start1, (end2 - start1));
2078 modify_region (current_buffer, start1, end2);
2079
2080 #ifdef USE_TEXT_PROPERTIES
2081 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
2082 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
2083 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
2084 Fset_text_properties (start1, end2, Qnil, Qnil);
2085 #endif /* USE_TEXT_PROPERTIES */
2086
2087 /* holds region 1 */
2088 if (len1 > 20000)
2089 temp = (unsigned char *) xmalloc (len1);
2090 else
2091 temp = (unsigned char *) alloca (len1);
2092 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2093 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2094 bcopy (start1_addr, temp, len1);
2095 bcopy (start2_addr, start1_addr, len2);
2096 bcopy (start1_addr + len1, start1_addr + len2, len_mid);
2097 bcopy (temp, start1_addr + len2 + len_mid, len1);
2098 if (len1 > 20000)
2099 free (temp);
2100 #ifdef USE_TEXT_PROPERTIES
2101 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
2102 len1, current_buffer, 0);
2103 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
2104 len_mid, current_buffer, 0);
2105 graft_intervals_into_buffer (tmp_interval2, start1,
2106 len2, current_buffer, 0);
2107 #endif /* USE_TEXT_PROPERTIES */
2108 }
2109 }
2110
2111 /* todo: this will be slow, because for every transposition, we
2112 traverse the whole friggin marker list. Possible solutions:
2113 somehow get a list of *all* the markers across multiple
2114 transpositions and do it all in one swell phoop. Or maybe modify
2115 Emacs' marker code to keep an ordered list or tree. This might
2116 be nicer, and more beneficial in the long run, but would be a
2117 bunch of work. Plus the way they're arranged now is nice. */
2118 if (NILP (leave_markers))
2119 {
2120 transpose_markers (start1, end1, start2, end2);
2121 fix_overlays_in_range (start1, end2);
2122 }
2123
2124 return Qnil;
2125 }
2126
2127 \f
2128 void
2129 syms_of_editfns ()
2130 {
2131 DEFVAR_LISP ("system-name", &Vsystem_name,
2132 "The name of the machine Emacs is running on.");
2133
2134 DEFVAR_LISP ("user-full-name", &Vuser_full_name,
2135 "The full name of the user logged in.");
2136
2137 DEFVAR_LISP ("user-name", &Vuser_name,
2138 "The user's name, taken from environment variables if possible.");
2139
2140 DEFVAR_LISP ("user-real-name", &Vuser_real_name,
2141 "The user's name, based upon the real uid only.");
2142
2143 defsubr (&Schar_equal);
2144 defsubr (&Sgoto_char);
2145 defsubr (&Sstring_to_char);
2146 defsubr (&Schar_to_string);
2147 defsubr (&Sbuffer_substring);
2148 defsubr (&Sbuffer_string);
2149
2150 defsubr (&Spoint_marker);
2151 defsubr (&Smark_marker);
2152 defsubr (&Spoint);
2153 defsubr (&Sregion_beginning);
2154 defsubr (&Sregion_end);
2155 /* defsubr (&Smark); */
2156 /* defsubr (&Sset_mark); */
2157 defsubr (&Ssave_excursion);
2158
2159 defsubr (&Sbufsize);
2160 defsubr (&Spoint_max);
2161 defsubr (&Spoint_min);
2162 defsubr (&Spoint_min_marker);
2163 defsubr (&Spoint_max_marker);
2164
2165 defsubr (&Sbobp);
2166 defsubr (&Seobp);
2167 defsubr (&Sbolp);
2168 defsubr (&Seolp);
2169 defsubr (&Sfollowing_char);
2170 defsubr (&Sprevious_char);
2171 defsubr (&Schar_after);
2172 defsubr (&Sinsert);
2173 defsubr (&Sinsert_before_markers);
2174 defsubr (&Sinsert_and_inherit);
2175 defsubr (&Sinsert_and_inherit_before_markers);
2176 defsubr (&Sinsert_char);
2177
2178 defsubr (&Suser_login_name);
2179 defsubr (&Suser_real_login_name);
2180 defsubr (&Suser_uid);
2181 defsubr (&Suser_real_uid);
2182 defsubr (&Suser_full_name);
2183 defsubr (&Semacs_pid);
2184 defsubr (&Scurrent_time);
2185 defsubr (&Sformat_time_string);
2186 defsubr (&Scurrent_time_string);
2187 defsubr (&Scurrent_time_zone);
2188 defsubr (&Ssystem_name);
2189 defsubr (&Smessage);
2190 defsubr (&Smessage_box);
2191 defsubr (&Smessage_or_box);
2192 defsubr (&Sformat);
2193
2194 defsubr (&Sinsert_buffer_substring);
2195 defsubr (&Scompare_buffer_substrings);
2196 defsubr (&Ssubst_char_in_region);
2197 defsubr (&Stranslate_region);
2198 defsubr (&Sdelete_region);
2199 defsubr (&Swiden);
2200 defsubr (&Snarrow_to_region);
2201 defsubr (&Ssave_restriction);
2202 defsubr (&Stranspose_regions);
2203 }