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