a8e04a057087e76e135a03973db65fc71535cfd0
[chise/xemacs-chise.git.1] / src / editfns.c
1 /* Lisp functions pertaining to editing.
2    Copyright (C) 1985-1987, 1989, 1992-1995 Free Software Foundation, Inc.
3    Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
4    Copyright (C) 1996 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Mule 2.0, FSF 19.30. */
24
25 /* This file has been Mule-ized. */
26
27 /* Hacked on for Mule by Ben Wing, December 1994. */
28
29 #include <config.h>
30 #include "lisp.h"
31
32 #include "buffer.h"
33 #include "commands.h"
34 #include "events.h"             /* for EVENTP */
35 #include "extents.h"
36 #include "frame.h"
37 #include "insdel.h"
38 #include "window.h"
39 #include "casetab.h"
40 #include "chartab.h"
41 #include "line-number.h"
42
43 #include "systime.h"
44 #include "sysdep.h"
45 #include "syspwd.h"
46 #include "sysfile.h"                    /* for getcwd */
47
48 /* Some static data, and a function to initialize it for each run */
49
50 Lisp_Object Vsystem_name;       /* #### - I don't see why this should be */
51                                 /* static, either...  --Stig */
52 #if 0                           /* XEmacs - this is now dynamic */
53                                 /* if at some point it's deemed desirable to
54                                    use lisp variables here, then they can be
55                                    initialized to nil and then set to their
56                                    real values upon the first call to the
57                                    functions that generate them. --stig */
58 Lisp_Object Vuser_real_login_name; /* login name of current user ID */
59 Lisp_Object Vuser_login_name;   /* user name from LOGNAME or USER.  */
60 #endif
61
62 /* It's useful to be able to set this as user customization, so we'll
63    keep it. */
64 Lisp_Object Vuser_full_name;
65 EXFUN (Fuser_full_name, 1);
66
67 Lisp_Object Qformat;
68
69 Lisp_Object Qpoint, Qmark, Qregion_beginning, Qregion_end;
70
71 Lisp_Object Quser_files_and_directories;
72
73 /* This holds the value of `environ' produced by the previous
74    call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
75    has never been called.  */
76 static char **environbuf;
77
78 void
79 init_editfns (void)
80 {
81 /* Only used in removed code below. */
82   char *p;
83
84   environbuf = 0;
85
86   /* Set up system_name even when dumping.  */
87   init_system_name ();
88
89 #ifndef CANNOT_DUMP
90   if (!initialized)
91     return;
92 #endif
93
94   if ((p = getenv ("NAME")))
95     /* I don't think it's the right thing to do the ampersand
96        modification on NAME.  Not that it matters anymore...  -hniksic */
97     Vuser_full_name = build_ext_string (p, Qnative);
98   else
99     Vuser_full_name = Fuser_full_name (Qnil);
100 }
101 \f
102 DEFUN ("char-to-string", Fchar_to_string, 1, 1, 0, /*
103 Convert CHARACTER to a one-character string containing that character.
104 */
105        (character))
106 {
107   Bytecount len;
108   Bufbyte str[MAX_EMCHAR_LEN];
109
110   if (EVENTP (character))
111     {
112       Lisp_Object ch2 = Fevent_to_character (character, Qt, Qnil, Qnil);
113       if (NILP (ch2))
114         return
115           signal_simple_continuable_error
116             ("character has no ASCII equivalent:", Fcopy_event (character, Qnil));
117       character = ch2;
118     }
119
120   CHECK_CHAR_COERCE_INT (character);
121
122   len = set_charptr_emchar (str, XCHAR (character));
123   return make_string (str, len);
124 }
125
126 DEFUN ("string-to-char", Fstring_to_char, 1, 1, 0, /*
127 Convert arg STRING to a character, the first character of that string.
128 An empty string will return the constant `nil'.
129 */
130        (string))
131 {
132   Lisp_String *p;
133   CHECK_STRING (string);
134
135   p = XSTRING (string);
136   if (string_length (p) != 0)
137     return make_char (string_char (p, 0));
138   else
139     /* This used to return Qzero.  That is broken, broken, broken. */
140     /* It might be kinder to signal an error directly. -slb */
141     return Qnil;
142 }
143
144 \f
145 static Lisp_Object
146 buildmark (Bufpos val, Lisp_Object buffer)
147 {
148   Lisp_Object mark = Fmake_marker ();
149   Fset_marker (mark, make_int (val), buffer);
150   return mark;
151 }
152
153 DEFUN ("point", Fpoint, 0, 1, 0, /*
154 Return value of point, as an integer.
155 Beginning of buffer is position (point-min).
156 If BUFFER is nil, the current buffer is assumed.
157 */
158        (buffer))
159 {
160   struct buffer *b = decode_buffer (buffer, 1);
161   return make_int (BUF_PT (b));
162 }
163
164 DEFUN ("point-marker", Fpoint_marker, 0, 2, 0, /*
165 Return value of point, as a marker object.
166 This marker is a copy; you may modify it with reckless abandon.
167 If optional argument DONT-COPY-P is non-nil, then it returns the real
168 point-marker; modifying the position of this marker will move point.
169 It is illegal to change the buffer of it, or make it point nowhere.
170 If BUFFER is nil, the current buffer is assumed.
171 */
172        (dont_copy_p, buffer))
173 {
174   struct buffer *b = decode_buffer (buffer, 1);
175   if (NILP (dont_copy_p))
176     return Fcopy_marker (b->point_marker, Qnil);
177   else
178     return b->point_marker;
179 }
180
181 /* The following two functions end up being identical but it's
182    cleaner to declare them separately. */
183
184 Bufpos
185 bufpos_clip_to_bounds (Bufpos lower, Bufpos num, Bufpos upper)
186 {
187   return (num < lower ? lower :
188           num > upper ? upper :
189           num);
190 }
191
192 Bytind
193 bytind_clip_to_bounds (Bytind lower, Bytind num, Bytind upper)
194 {
195   return (num < lower ? lower :
196           num > upper ? upper :
197           num);
198 }
199
200 /*
201  * Chuck says:
202  * There is no absolute way to determine if goto-char is the function
203  * being run.  this-command doesn't work because it is often eval'd
204  * and this-command ends up set to eval-expression.  So this flag gets
205  * added for now.
206  *
207  * Jamie thinks he's wrong, but we'll leave this in for now.
208  */
209 int atomic_extent_goto_char_p;
210
211 DEFUN ("goto-char", Fgoto_char, 1, 2, "NGoto char: ", /*
212 Set point to POSITION, a number or marker.
213 Beginning of buffer is position (point-min), end is (point-max).
214 If BUFFER is nil, the current buffer is assumed.
215 Return value of POSITION, as an integer.
216 */
217        (position, buffer))
218 {
219   struct buffer *b = decode_buffer (buffer, 1);
220   Bufpos n = get_buffer_pos_char (b, position, GB_COERCE_RANGE);
221   BUF_SET_PT (b, n);
222   atomic_extent_goto_char_p = 1;
223   return make_int (n);
224 }
225
226 static Lisp_Object
227 region_limit (int beginningp, struct buffer *b)
228 {
229   Lisp_Object m;
230
231 #if 0 /* FSFmacs */
232   if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
233       && NILP (b->mark_active))
234     Fsignal (Qmark_inactive, Qnil);
235 #endif
236   m = Fmarker_position (b->mark);
237   if (NILP (m)) error ("There is no region now");
238   if (!!(BUF_PT (b) < XINT (m)) == !!beginningp)
239     return make_int (BUF_PT (b));
240   else
241     return m;
242 }
243
244 DEFUN ("region-beginning", Fregion_beginning, 0, 1, 0, /*
245 Return position of beginning of region in BUFFER, as an integer.
246 If BUFFER is nil, the current buffer is assumed.
247 */
248        (buffer))
249 {
250   return region_limit (1, decode_buffer (buffer, 1));
251 }
252
253 DEFUN ("region-end", Fregion_end, 0, 1, 0, /*
254 Return position of end of region in BUFFER, as an integer.
255 If BUFFER is nil, the current buffer is assumed.
256 */
257        (buffer))
258 {
259   return region_limit (0, decode_buffer (buffer, 1));
260 }
261
262 /* Whether to use lispm-style active-regions */
263 int zmacs_regions;
264
265 /* Whether the zmacs region is active.  This is not per-buffer because
266    there can be only one active region at a time.  #### Now that the
267    zmacs region are not directly tied to the X selections this may not
268    necessarily have to be true.  */
269 int zmacs_region_active_p;
270
271 int zmacs_region_stays;
272
273 Lisp_Object Qzmacs_update_region, Qzmacs_deactivate_region;
274 Lisp_Object Qzmacs_region_buffer;
275
276 void
277 zmacs_update_region (void)
278 {
279   /* This function can GC */
280   if (zmacs_region_active_p)
281     call0 (Qzmacs_update_region);
282 }
283
284 void
285 zmacs_deactivate_region (void)
286 {
287   /* This function can GC */
288   if (zmacs_region_active_p)
289     call0 (Qzmacs_deactivate_region);
290 }
291
292 Lisp_Object
293 zmacs_region_buffer (void)
294 {
295   if (zmacs_region_active_p)
296     return call0 (Qzmacs_region_buffer);
297   else
298     return Qnil;
299 }
300
301 DEFUN ("mark-marker", Fmark_marker, 0, 2, 0, /*
302 Return this buffer's mark, as a marker object.
303 If `zmacs-regions' is true, then this returns nil unless the region is
304 currently in the active (highlighted) state.  If optional argument FORCE
305 is t, this returns the mark (if there is one) regardless of the zmacs-region
306 state.  You should *generally* not use the mark unless the region is active,
307 if the user has expressed a preference for the zmacs-region model.
308 Watch out!  Moving this marker changes the mark position.
309 If you set the marker not to point anywhere, the buffer will have no mark.
310 If BUFFER is nil, the current buffer is assumed.
311 */
312        (force, buffer))
313 {
314   struct buffer *b = decode_buffer (buffer, 1);
315   if (! zmacs_regions || zmacs_region_active_p || !NILP (force))
316     return b->mark;
317   return Qnil;
318 }
319
320 \f
321 /* The saved object is a cons:
322
323    (COPY-OF-POINT-MARKER . COPY-OF-MARK)
324
325    We used to have another cons for a VISIBLE-P element, which was t
326    if `(eq (current-buffer) (window-buffer (selected-window)))' but it
327    was unused for a long time, so I removed it.  --hniksic */
328 Lisp_Object
329 save_excursion_save (void)
330 {
331   struct buffer *b;
332
333   /* #### Huh?  --hniksic */
334   /*if (preparing_for_armageddon) return Qnil;*/
335
336 #ifdef ERROR_CHECK_BUFPOS
337   assert (XINT (Fpoint (Qnil)) ==
338           XINT (Fmarker_position (Fpoint_marker (Qt, Qnil))));
339 #endif
340
341   b = current_buffer;
342
343   return noseeum_cons (noseeum_copy_marker (b->point_marker, Qnil),
344                        noseeum_copy_marker (b->mark, Qnil));
345 }
346
347 Lisp_Object
348 save_excursion_restore (Lisp_Object info)
349 {
350   Lisp_Object buffer = Fmarker_buffer (XCAR (info));
351
352   /* If buffer being returned to is now deleted, avoid error --
353      otherwise could get error here while unwinding to top level and
354      crash.  In that case, Fmarker_buffer returns nil now.  */
355   if (!NILP (buffer))
356     {
357       struct buffer *buf = XBUFFER (buffer);
358       struct gcpro gcpro1;
359       GCPRO1 (info);
360       set_buffer_internal (buf);
361       Fgoto_char (XCAR (info), buffer);
362       Fset_marker (buf->mark, XCDR (info), buffer);
363
364 #if 0 /* We used to make the current buffer visible in the selected window
365          if that was true previously.  That avoids some anomalies.
366          But it creates others, and it wasn't documented, and it is simpler
367          and cleaner never to alter the window/buffer connections.  */
368       /* I'm certain some code somewhere depends on this behavior. --jwz */
369       /* Even if it did, it certainly doesn't matter anymore, because
370          this has been the behavior for countless XEmacs releases
371          now.  --hniksic */
372       if (visible
373           && (current_buffer != XBUFFER (XWINDOW (selected_window)->buffer)))
374         switch_to_buffer (Fcurrent_buffer (), Qnil);
375 #endif
376
377       UNGCPRO;
378     }
379
380   /* Free all the junk we allocated, so that a `save-excursion' comes
381      for free in terms of GC junk. */
382   free_marker (XMARKER (XCAR (info)));
383   free_marker (XMARKER (XCDR (info)));
384   free_cons (XCONS (info));
385   return Qnil;
386 }
387
388 DEFUN ("save-excursion", Fsave_excursion, 0, UNEVALLED, 0, /*
389 Save point, mark, and current buffer; execute BODY; restore those things.
390 Executes BODY just like `progn'.
391 The values of point, mark and the current buffer are restored
392 even in case of abnormal exit (throw or error).
393 */
394        (args))
395 {
396   /* This function can GC */
397   int speccount = specpdl_depth ();
398
399   record_unwind_protect (save_excursion_restore, save_excursion_save ());
400
401   return unbind_to (speccount, Fprogn (args));
402 }
403
404 Lisp_Object
405 save_current_buffer_restore (Lisp_Object buffer)
406 {
407   struct buffer *buf = XBUFFER (buffer);
408   /* Avoid signaling an error if the buffer is no longer alive.  This
409      is for consistency with save-excursion.  */
410   if (BUFFER_LIVE_P (buf))
411     set_buffer_internal (buf);
412   return Qnil;
413 }
414
415 DEFUN ("save-current-buffer", Fsave_current_buffer, 0, UNEVALLED, 0, /*
416 Save the current buffer; execute BODY; restore the current buffer.
417 Executes BODY just like `progn'.
418 */
419        (args))
420 {
421   /* This function can GC */
422   int speccount = specpdl_depth ();
423
424   record_unwind_protect (save_current_buffer_restore, Fcurrent_buffer ());
425
426   return unbind_to (speccount, Fprogn (args));
427 }
428 \f
429 DEFUN ("buffer-size", Fbuffer_size, 0, 1, 0, /*
430 Return the number of characters in BUFFER.
431 If BUFFER is nil, the current buffer is assumed.
432 */
433        (buffer))
434 {
435   struct buffer *b = decode_buffer (buffer, 1);
436   return make_int (BUF_SIZE (b));
437 }
438
439 DEFUN ("point-min", Fpoint_min, 0, 1, 0, /*
440 Return the minimum permissible value of point in BUFFER.
441 This is 1, unless narrowing (a buffer restriction)
442 is in effect, in which case it may be greater.
443 If BUFFER is nil, the current buffer is assumed.
444 */
445        (buffer))
446 {
447   struct buffer *b = decode_buffer (buffer, 1);
448   return make_int (BUF_BEGV (b));
449 }
450
451 DEFUN ("point-min-marker", Fpoint_min_marker, 0, 1, 0, /*
452 Return a marker to the minimum permissible value of point in BUFFER.
453 This is the beginning, unless narrowing (a buffer restriction)
454 is in effect, in which case it may be greater.
455 If BUFFER is nil, the current buffer is assumed.
456 */
457        (buffer))
458 {
459   struct buffer *b = decode_buffer (buffer, 1);
460   return buildmark (BUF_BEGV (b), make_buffer (b));
461 }
462
463 DEFUN ("point-max", Fpoint_max, 0, 1, 0, /*
464 Return the maximum permissible value of point in BUFFER.
465 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)
466 is in effect, in which case it may be less.
467 If BUFFER is nil, the current buffer is assumed.
468 */
469        (buffer))
470 {
471   struct buffer *b = decode_buffer (buffer, 1);
472   return make_int (BUF_ZV (b));
473 }
474
475 DEFUN ("point-max-marker", Fpoint_max_marker, 0, 1, 0, /*
476 Return a marker to the maximum permissible value of point in BUFFER.
477 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)
478 is in effect, in which case it may be less.
479 If BUFFER is nil, the current buffer is assumed.
480 */
481        (buffer))
482 {
483   struct buffer *b = decode_buffer (buffer, 1);
484   return buildmark (BUF_ZV (b), make_buffer (b));
485 }
486
487 DEFUN ("following-char", Ffollowing_char, 0, 1, 0, /*
488 Return the character following point.
489 At the end of the buffer or accessible region, return 0.
490 If BUFFER is nil, the current buffer is assumed.
491 */
492        (buffer))
493 {
494   struct buffer *b = decode_buffer (buffer, 1);
495   if (BUF_PT (b) >= BUF_ZV (b))
496     return Qzero;             /* #### Gag me! */
497   else
498     return make_char (BUF_FETCH_CHAR (b, BUF_PT (b)));
499 }
500
501 DEFUN ("preceding-char", Fpreceding_char, 0, 1, 0, /*
502 Return the character preceding point.
503 At the beginning of the buffer or accessible region, return 0.
504 If BUFFER is nil, the current buffer is assumed.
505 */
506        (buffer))
507 {
508   struct buffer *b = decode_buffer (buffer, 1);
509   if (BUF_PT (b) <= BUF_BEGV (b))
510     return Qzero;             /* #### Gag me! */
511   else
512     return make_char (BUF_FETCH_CHAR (b, BUF_PT (b) - 1));
513 }
514
515 DEFUN ("bobp", Fbobp, 0, 1, 0, /*
516 Return t if point is at the beginning of the buffer.
517 If the buffer is narrowed, this means the beginning of the narrowed part.
518 If BUFFER is nil, the current buffer is assumed.
519 */
520        (buffer))
521 {
522   struct buffer *b = decode_buffer (buffer, 1);
523   return BUF_PT (b) == BUF_BEGV (b) ? Qt : Qnil;
524 }
525
526 DEFUN ("eobp", Feobp, 0, 1, 0, /*
527 Return t if point is at the end of the buffer.
528 If the buffer is narrowed, this means the end of the narrowed part.
529 If BUFFER is nil, the current buffer is assumed.
530 */
531        (buffer))
532 {
533   struct buffer *b = decode_buffer (buffer, 1);
534   return BUF_PT (b) == BUF_ZV (b) ? Qt : Qnil;
535 }
536
537 int
538 beginning_of_line_p (struct buffer *b, Bufpos pt)
539 {
540   return pt <= BUF_BEGV (b) || BUF_FETCH_CHAR (b, pt - 1) == '\n';
541 }
542
543
544 DEFUN ("bolp", Fbolp, 0, 1, 0, /*
545 Return t if point is at the beginning of a line.
546 If BUFFER is nil, the current buffer is assumed.
547 */
548        (buffer))
549 {
550   struct buffer *b = decode_buffer (buffer, 1);
551   return beginning_of_line_p (b, BUF_PT (b)) ? Qt : Qnil;
552 }
553
554 DEFUN ("eolp", Feolp, 0, 1, 0, /*
555 Return t if point is at the end of a line.
556 `End of a line' includes point being at the end of the buffer.
557 If BUFFER is nil, the current buffer is assumed.
558 */
559        (buffer))
560 {
561   struct buffer *b = decode_buffer (buffer, 1);
562   return (BUF_PT (b) == BUF_ZV (b) || BUF_FETCH_CHAR (b, BUF_PT (b)) == '\n')
563     ? Qt : Qnil;
564 }
565
566 DEFUN ("char-after", Fchar_after, 0, 2, 0, /*
567 Return the character at position POS in BUFFER.
568 POS is an integer or a marker.
569 If POS is out of range, the value is nil.
570 if POS is nil, the value of point is assumed.
571 If BUFFER is nil, the current buffer is assumed.
572 */
573        (pos, buffer))
574 {
575   struct buffer *b = decode_buffer (buffer, 1);
576   Bufpos n = (NILP (pos) ? BUF_PT (b) :
577               get_buffer_pos_char (b, pos, GB_NO_ERROR_IF_BAD));
578
579   if (n < 0 || n == BUF_ZV (b))
580     return Qnil;
581   return make_char (BUF_FETCH_CHAR (b, n));
582 }
583
584 DEFUN ("char-before", Fchar_before, 0, 2, 0, /*
585 Return the character preceding position POS in BUFFER.
586 POS is an integer or a marker.
587 If POS is out of range, the value is nil.
588 if POS is nil, the value of point is assumed.
589 If BUFFER is nil, the current buffer is assumed.
590 */
591        (pos, buffer))
592 {
593   struct buffer *b = decode_buffer (buffer, 1);
594   Bufpos n = (NILP (pos) ? BUF_PT (b) :
595               get_buffer_pos_char (b, pos, GB_NO_ERROR_IF_BAD));
596
597   n--;
598
599   if (n < BUF_BEGV (b))
600     return Qnil;
601   return make_char (BUF_FETCH_CHAR (b, n));
602 }
603
604 #if !defined(WINDOWSNT) && !defined(MSDOS)
605 #include <sys/stat.h>
606 #include <fcntl.h>
607 #include <errno.h>
608 #include <limits.h>
609 #endif
610 \f
611 DEFUN ("temp-directory", Ftemp_directory, 0, 0, 0, /*
612 Return the pathname to the directory to use for temporary files.
613 On MS Windows, this is obtained from the TEMP or TMP environment variables,
614 defaulting to / if they are both undefined.
615 On Unix it is obtained from TMPDIR, with /tmp as the default.
616 */
617        ())
618 {
619   char *tmpdir;
620 #if defined(WIN32_NATIVE)
621   tmpdir = getenv ("TEMP");
622   if (!tmpdir)
623     tmpdir = getenv ("TMP");
624   if (!tmpdir)
625     tmpdir = "/";
626 #else /* WIN32_NATIVE */
627  tmpdir = getenv ("TMPDIR");
628  if (!tmpdir)
629     {
630       struct stat st;
631       int myuid = getuid();
632       static char path[5 /* strlen ("/tmp/") */ + 1 + _POSIX_PATH_MAX];
633
634       strcpy (path, "/tmp/");
635       strncat (path, user_login_name (NULL), _POSIX_PATH_MAX);
636       if (lstat(path, &st) < 0 && errno == ENOENT)
637         {
638           mkdir(path, 0700);    /* ignore retval -- checked next anyway. */
639         }
640       if (lstat(path, &st) == 0 && st.st_uid == myuid && S_ISDIR(st.st_mode))
641         {
642           tmpdir = path;
643         }
644       else
645         {
646           strcpy(path, getenv("HOME")); strncat(path, "/tmp/", _POSIX_PATH_MAX);
647           if (stat(path, &st) < 0 && errno == ENOENT)
648             {
649               int fd;
650               char warnpath[1+_POSIX_PATH_MAX];
651               mkdir(path, 0700);        /* ignore retvals */
652               strcpy(warnpath, path);
653               strncat(warnpath, ".created_by_xemacs", _POSIX_PATH_MAX);
654               if ((fd = open(warnpath, O_WRONLY|O_CREAT, 0644)) > 0)
655                 {
656                   write(fd, "XEmacs created this directory because /tmp/<yourname> was unavailable -- \nPlease check !\n", 89);
657                   close(fd);
658                 }
659             }
660           if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
661             {
662               tmpdir = path;
663             }
664           else
665             {
666    tmpdir = "/tmp";
667             }
668         }
669     }
670 #endif
671
672   return build_ext_string (tmpdir, Qfile_name);
673 }
674
675 DEFUN ("user-login-name", Fuser_login_name, 0, 1, 0, /*
676 Return the name under which the user logged in, as a string.
677 This is based on the effective uid, not the real uid.
678 Also, if the environment variable LOGNAME or USER is set,
679 that determines the value of this function.
680 If the optional argument UID is present, then environment variables are
681 ignored and this function returns the login name for that UID, or nil.
682 */
683        (uid))
684 {
685   char *returned_name;
686   uid_t local_uid;
687
688   if (!NILP (uid))
689     {
690       CHECK_INT (uid);
691       local_uid = XINT (uid);
692       returned_name = user_login_name (&local_uid);
693     }
694   else
695     {
696       returned_name = user_login_name (NULL);
697     }
698   /* #### - I believe this should return nil instead of "unknown" when pw==0
699      pw=0 is indicated by a null return from user_login_name
700   */
701   return returned_name ? build_string (returned_name) : Qnil;
702 }
703
704 /* This function may be called from other C routines when a
705    character string representation of the user_login_name is
706    needed but a Lisp Object is not.  The UID is passed by
707    reference.  If UID == NULL, then the USER name
708    for the user running XEmacs will be returned.  This
709    corresponds to a nil argument to Fuser_login_name.
710 */
711 char*
712 user_login_name (uid_t *uid)
713 {
714   /* uid == NULL to return name of this user */
715   if (uid != NULL)
716     {
717       struct passwd *pw = getpwuid (*uid);
718       return pw ? pw->pw_name : NULL;
719     }
720   else
721     {
722       /* #### - when euid != uid, then LOGNAME and USER are leftovers from the
723          old environment (I site observed behavior on sunos and linux), so the
724          environment variables should be disregarded in that case.  --Stig */
725       char *user_name = getenv ("LOGNAME");
726       if (!user_name)
727         user_name = getenv (
728 #ifdef WIN32_NATIVE
729                             "USERNAME" /* it's USERNAME on NT */
730 #else
731                             "USER"
732 #endif
733                             );
734       if (user_name)
735         return (user_name);
736       else
737         {
738           struct passwd *pw = getpwuid (geteuid ());
739 #ifdef CYGWIN
740           /* Since the Cygwin environment may not have an /etc/passwd,
741              return "unknown" instead of the null if the username
742              cannot be determined.
743           */
744           return pw ? pw->pw_name : "unknown";
745 #else
746           /* For all but Cygwin return NULL (nil) */
747           return pw ? pw->pw_name : NULL;
748 #endif
749         }
750     }
751 }
752
753 DEFUN ("user-real-login-name", Fuser_real_login_name, 0, 0, 0, /*
754 Return the name of the user's real uid, as a string.
755 This ignores the environment variables LOGNAME and USER, so it differs from
756 `user-login-name' when running under `su'.
757 */
758        ())
759 {
760   struct passwd *pw = getpwuid (getuid ());
761   /* #### - I believe this should return nil instead of "unknown" when pw==0 */
762
763   Lisp_Object tem = build_string (pw ? pw->pw_name : "unknown");/* no gettext */
764   return tem;
765 }
766
767 DEFUN ("user-uid", Fuser_uid, 0, 0, 0, /*
768 Return the effective uid of Emacs, as an integer.
769 */
770        ())
771 {
772   return make_int (geteuid ());
773 }
774
775 DEFUN ("user-real-uid", Fuser_real_uid, 0, 0, 0, /*
776 Return the real uid of Emacs, as an integer.
777 */
778        ())
779 {
780   return make_int (getuid ());
781 }
782
783 DEFUN ("user-full-name", Fuser_full_name, 0, 1, 0, /*
784 Return the full name of the user logged in, as a string.
785 If the optional argument USER is given, then the full name for that
786 user is returned, or nil.  USER may be either a login name or a uid.
787
788 If USER is nil, and `user-full-name' contains a string, the
789 value of `user-full-name' is returned.
790 */
791        (user))
792 {
793   Lisp_Object user_name;
794   struct passwd *pw = NULL;
795   Lisp_Object tem;
796   const char *p, *q;
797
798   if (NILP (user) && STRINGP (Vuser_full_name))
799     return Vuser_full_name;
800
801   user_name = (STRINGP (user) ? user : Fuser_login_name (user));
802   if (!NILP (user_name))        /* nil when nonexistent UID passed as arg */
803     {
804       const char *user_name_ext;
805
806       /* Fuck me.  getpwnam() can call select() and (under IRIX at least)
807          things get wedged if a SIGIO arrives during this time. */
808       TO_EXTERNAL_FORMAT (LISP_STRING, user_name,
809                           C_STRING_ALLOCA, user_name_ext,
810                           Qnative);
811       slow_down_interrupts ();
812       pw = (struct passwd *) getpwnam (user_name_ext);
813       speed_up_interrupts ();
814     }
815
816   /* #### - Stig sez: this should return nil instead of "unknown" when pw==0 */
817   /* Ben sez: bad idea because it's likely to break something */
818 #ifndef AMPERSAND_FULL_NAME
819   p = pw ? USER_FULL_NAME : "unknown"; /* don't gettext */
820   q = strchr (p, ',');
821 #else
822   p = pw ? USER_FULL_NAME : "unknown"; /* don't gettext */
823   q = strchr (p, ',');
824 #endif
825   tem = ((!NILP (user) && !pw)
826          ? Qnil
827          : make_ext_string ((Extbyte *) p, (q ? q - p : strlen (p)),
828                             Qnative));
829
830 #ifdef AMPERSAND_FULL_NAME
831   if (!NILP (tem))
832     {
833       p = (char *) XSTRING_DATA (tem);
834       q = strchr (p, '&');
835       /* Substitute the login name for the &, upcasing the first character.  */
836       if (q)
837         {
838           char *r = (char *) alloca (strlen (p) + XSTRING_LENGTH (user_name) + 1);
839           memcpy (r, p, q - p);
840           r[q - p] = 0;
841           strcat (r, (char *) XSTRING_DATA (user_name));
842           /* #### current_buffer dependency! */
843           r[q - p] = UPCASE (current_buffer, r[q - p]);
844           strcat (r, q + 1);
845           tem = build_string (r);
846         }
847     }
848 #endif /* AMPERSAND_FULL_NAME */
849
850   return tem;
851 }
852
853 static Extbyte *cached_home_directory;
854
855 void
856 uncache_home_directory (void)
857 {
858   cached_home_directory = NULL; /* in some cases, this may cause the leaking
859                                    of a few bytes */
860 }
861
862 /* !!#### not Mule correct. */
863
864 /* Returns the home directory, in external format */
865 Extbyte *
866 get_home_directory (void)
867 {
868   /* !!#### this is hopelessly bogus.  Rule #1: Do not make any assumptions
869      about what format an external string is in.  Could be Unicode, for all
870      we know, and then all the operations below are totally bogus.
871      Instead, convert all data to internal format *right* at the juncture
872      between XEmacs and the outside world, the very moment we first get
873      the data.  --ben */
874   int output_home_warning = 0;
875
876   if (cached_home_directory == NULL)
877     {
878       if ((cached_home_directory = (Extbyte *) getenv("HOME")) == NULL)
879         {
880 #if defined(WIN32_NATIVE)
881           char *homedrive, *homepath;
882
883           if ((homedrive = getenv("HOMEDRIVE")) != NULL &&
884               (homepath = getenv("HOMEPATH")) != NULL)
885             {
886               cached_home_directory =
887                 (Extbyte *) xmalloc (strlen (homedrive) +
888                                      strlen (homepath) + 1);
889               sprintf((char *) cached_home_directory, "%s%s",
890                       homedrive,
891                       homepath);
892             }
893           else
894             {
895 # if 0 /* changed by ben.  This behavior absolutely stinks, and the
896           possibility being addressed here occurs quite commonly.
897           Using the current directory makes absolutely no sense. */
898               /*
899                * Use the current directory.
900                * This preserves the existing XEmacs behavior, but is different
901                * from NT Emacs.
902                */
903               if (initial_directory[0] != '\0')
904                 {
905                   cached_home_directory = (Extbyte*) initial_directory;
906                 }
907               else
908                 {
909                   /* This will probably give the wrong value */
910                   cached_home_directory = (Extbyte*) getcwd (NULL, 0);
911                 }
912 # else
913               /*
914                * This is NT Emacs behavior
915                */
916               cached_home_directory = (Extbyte *) "C:\\";
917               output_home_warning = 1;
918 # endif
919             }
920 #else   /* !WIN32_NATIVE */
921           /*
922            * Unix, typically.
923            * Using "/" isn't quite right, but what should we do?
924            * We probably should try to extract pw_dir from /etc/passwd,
925            * before falling back to this.
926            */
927           cached_home_directory = (Extbyte *) "/";
928           output_home_warning = 1;
929 #endif  /* !WIN32_NATIVE */
930         }
931       if (initialized && output_home_warning)
932         {
933           warn_when_safe (Quser_files_and_directories, Qwarning, "\n"
934 "       XEmacs was unable to determine a good value for the user's $HOME\n"
935 "       directory, and will be using the value:\n"
936 "               %s\n"
937 "       This is probably incorrect.",
938                           cached_home_directory
939                           );
940         }
941     }
942   return cached_home_directory;
943 }
944
945 DEFUN ("user-home-directory", Fuser_home_directory, 0, 0, 0, /*
946 Return the user's home directory, as a string.
947 */
948        ())
949 {
950   Extbyte *path = get_home_directory ();
951
952   return path == NULL ? Qnil :
953     Fexpand_file_name (Fsubstitute_in_file_name
954                        (build_ext_string ((char *) path, Qfile_name)),
955                        Qnil);
956 }
957
958 DEFUN ("system-name", Fsystem_name, 0, 0, 0, /*
959 Return the name of the machine you are running on, as a string.
960 */
961        ())
962 {
963     return Fcopy_sequence (Vsystem_name);
964 }
965
966 DEFUN ("emacs-pid", Femacs_pid, 0, 0, 0, /*
967 Return the process ID of Emacs, as an integer.
968 */
969        ())
970 {
971   return make_int (getpid ());
972 }
973
974 DEFUN ("current-time", Fcurrent_time, 0, 0, 0, /*
975 Return the current time, as the number of seconds since 1970-01-01 00:00:00.
976 The time is returned as a list of three integers.  The first has the
977 most significant 16 bits of the seconds, while the second has the
978 least significant 16 bits.  The third integer gives the microsecond
979 count.
980
981 The microsecond count is zero on systems that do not provide
982 resolution finer than a second.
983 */
984        ())
985 {
986   EMACS_TIME t;
987
988   EMACS_GET_TIME (t);
989   return list3 (make_int ((EMACS_SECS (t) >> 16) & 0xffff),
990                 make_int ((EMACS_SECS (t) >> 0)  & 0xffff),
991                 make_int (EMACS_USECS (t)));
992 }
993
994 DEFUN ("current-process-time", Fcurrent_process_time, 0, 0, 0, /*
995 Return the amount of time used by this XEmacs process so far.
996 The return value is a list of three floating-point numbers, expressing
997 the user, system, and real times used by the process.  The user time
998 measures the time actually spent by the CPU executing the code in this
999 process.  The system time measures time spent by the CPU executing kernel
1000 code on behalf of this process (e.g. I/O requests made by the process).
1001
1002 Note that the user and system times measure processor time, as opposed
1003 to real time, and only accrue when the processor is actually doing
1004 something: Time spent in an idle wait (waiting for user events to come
1005 in or for I/O on a disk drive or other device to complete) does not
1006 count.  Thus, the user and system times will often be considerably
1007 less than the real time.
1008
1009 Some systems do not allow the user and system times to be distinguished.
1010 In this case, the user time will be the total processor time used by
1011 the process, and the system time will be 0.
1012
1013 Some systems do not allow the real and processor times to be distinguished.
1014 In this case, the user and real times will be the same and the system
1015 time will be 0.
1016 */
1017        ())
1018 {
1019   double user, sys, real;
1020
1021   get_process_times (&user, &sys, &real);
1022   return list3 (make_float (user), make_float (sys), make_float (real));
1023 }
1024
1025 \f
1026 int lisp_to_time (Lisp_Object specified_time, time_t *result);
1027 int
1028 lisp_to_time (Lisp_Object specified_time, time_t *result)
1029 {
1030   Lisp_Object high, low;
1031
1032   if (NILP (specified_time))
1033     return time (result) != -1;
1034
1035   CHECK_CONS (specified_time);
1036   high = XCAR (specified_time);
1037   low  = XCDR (specified_time);
1038   if (CONSP (low))
1039     low = XCAR (low);
1040   CHECK_INT (high);
1041   CHECK_INT (low);
1042   *result = (XINT (high) << 16) + (XINT (low) & 0xffff);
1043   return *result >> 16 == XINT (high);
1044 }
1045
1046 Lisp_Object time_to_lisp (time_t the_time);
1047 Lisp_Object
1048 time_to_lisp (time_t the_time)
1049 {
1050   unsigned int item = (unsigned int) the_time;
1051   return Fcons (make_int (item >> 16), make_int (item & 0xffff));
1052 }
1053
1054 size_t emacs_strftime (char *string, size_t max, const char *format,
1055                        const struct tm *tm);
1056 static long difftm (const struct tm *a, const struct tm *b);
1057
1058
1059 DEFUN ("format-time-string", Fformat_time_string, 1, 2, 0, /*
1060 Use FORMAT-STRING to format the time TIME.
1061 TIME is specified as (HIGH LOW . IGNORED) or (HIGH . LOW), as from
1062 `current-time' and `file-attributes'.  If TIME is not specified it
1063 defaults to the current time.
1064 FORMAT-STRING may contain %-sequences to substitute parts of the time.
1065 %a is replaced by the abbreviated name of the day of week.
1066 %A is replaced by the full name of the day of week.
1067 %b is replaced by the abbreviated name of the month.
1068 %B is replaced by the full name of the month.
1069 %c is a synonym for "%x %X".
1070 %C is a locale-specific synonym, which defaults to "%A, %B %e, %Y" in the C locale.
1071 %d is replaced by the day of month, zero-padded.
1072 %D is a synonym for "%m/%d/%y".
1073 %e is replaced by the day of month, blank-padded.
1074 %h is a synonym for "%b".
1075 %H is replaced by the hour (00-23).
1076 %I is replaced by the hour (00-12).
1077 %j is replaced by the day of the year (001-366).
1078 %k is replaced by the hour (0-23), blank padded.
1079 %l is replaced by the hour (1-12), blank padded.
1080 %m is replaced by the month (01-12).
1081 %M is replaced by the minute (00-59).
1082 %n is a synonym for "\\n".
1083 %p is replaced by AM or PM, as appropriate.
1084 %r is a synonym for "%I:%M:%S %p".
1085 %R is a synonym for "%H:%M".
1086 %s is replaced by the time in seconds since 00:00:00, Jan 1, 1970 (a
1087       nonstandard extension)
1088 %S is replaced by the second (00-60).
1089 %t is a synonym for "\\t".
1090 %T is a synonym for "%H:%M:%S".
1091 %U is replaced by the week of the year (00-53), first day of week is Sunday.
1092 %w is replaced by the day of week (0-6), Sunday is day 0.
1093 %W is replaced by the week of the year (00-53), first day of week is Monday.
1094 %x is a locale-specific synonym, which defaults to "%D" in the C locale.
1095 %X is a locale-specific synonym, which defaults to "%T" in the C locale.
1096 %y is replaced by the year without century (00-99).
1097 %Y is replaced by the year with century.
1098 %Z is replaced by the time zone abbreviation.
1099
1100 The number of options reflects the `strftime' function.
1101
1102 BUG: If the charset used by the current locale is not ISO 8859-1, the
1103 characters appearing in the day and month names may be incorrect.
1104 */
1105        (format_string, time_))
1106 {
1107   time_t value;
1108   size_t size;
1109
1110   CHECK_STRING (format_string);
1111
1112   if (! lisp_to_time (time_, &value))
1113     error ("Invalid time specification");
1114
1115   /* This is probably enough.  */
1116   size = XSTRING_LENGTH (format_string) * 6 + 50;
1117
1118   while (1)
1119     {
1120       char *buf = (char *) alloca (size);
1121       *buf = 1;
1122       if (emacs_strftime (buf, size,
1123                           (const char *) XSTRING_DATA (format_string),
1124                           localtime (&value))
1125           || !*buf)
1126         return build_ext_string (buf, Qbinary);
1127       /* If buffer was too small, make it bigger.  */
1128       size *= 2;
1129     }
1130 }
1131
1132 DEFUN ("decode-time", Fdecode_time, 0, 1, 0, /*
1133 Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).
1134 The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED)
1135 or (HIGH . LOW), as from `current-time' and `file-attributes', or `nil'
1136 to use the current time.  The list has the following nine members:
1137 SEC is an integer between 0 and 60; SEC is 60 for a leap second, which
1138 only some operating systems support.  MINUTE is an integer between 0 and 59.
1139 HOUR is an integer between 0 and 23.  DAY is an integer between 1 and 31.
1140 MONTH is an integer between 1 and 12.  YEAR is an integer indicating the
1141 four-digit year.  DOW is the day of week, an integer between 0 and 6, where
1142 0 is Sunday.  DST is t if daylight savings time is effect, otherwise nil.
1143 ZONE is an integer indicating the number of seconds east of Greenwich.
1144 \(Note that Common Lisp has different meanings for DOW and ZONE.)
1145 */
1146        (specified_time))
1147 {
1148   time_t time_spec;
1149   struct tm save_tm;
1150   struct tm *decoded_time;
1151   Lisp_Object list_args[9];
1152
1153   if (! lisp_to_time (specified_time, &time_spec))
1154     error ("Invalid time specification");
1155
1156   decoded_time = localtime (&time_spec);
1157   list_args[0] = make_int (decoded_time->tm_sec);
1158   list_args[1] = make_int (decoded_time->tm_min);
1159   list_args[2] = make_int (decoded_time->tm_hour);
1160   list_args[3] = make_int (decoded_time->tm_mday);
1161   list_args[4] = make_int (decoded_time->tm_mon + 1);
1162   list_args[5] = make_int (decoded_time->tm_year + 1900);
1163   list_args[6] = make_int (decoded_time->tm_wday);
1164   list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil;
1165
1166   /* Make a copy, in case gmtime modifies the struct.  */
1167   save_tm = *decoded_time;
1168   decoded_time = gmtime (&time_spec);
1169   if (decoded_time == 0)
1170     list_args[8] = Qnil;
1171   else
1172     list_args[8] = make_int (difftm (&save_tm, decoded_time));
1173   return Flist (9, list_args);
1174 }
1175
1176 static void set_time_zone_rule (char *tzstring);
1177
1178 DEFUN ("encode-time", Fencode_time, 6, MANY, 0, /*
1179   Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.
1180 This is the reverse operation of `decode-time', which see.
1181 ZONE defaults to the current time zone rule.  This can
1182 be a string (as from `set-time-zone-rule'), or it can be a list
1183 \(as from `current-time-zone') or an integer (as from `decode-time')
1184 applied without consideration for daylight savings time.
1185
1186 You can pass more than 7 arguments; then the first six arguments
1187 are used as SECOND through YEAR, and the *last* argument is used as ZONE.
1188 The intervening arguments are ignored.
1189 This feature lets (apply 'encode-time (decode-time ...)) work.
1190
1191 Out-of-range values for SEC, MINUTE, HOUR, DAY, or MONTH are allowed;
1192 for example, a DAY of 0 means the day preceding the given month.
1193 Year numbers less than 100 are treated just like other year numbers.
1194 If you want them to stand for years in this century, you must do that yourself.
1195 */
1196        (int nargs, Lisp_Object *args))
1197 {
1198   time_t the_time;
1199   struct tm tm;
1200   Lisp_Object zone = (nargs > 6) ? args[nargs - 1] : Qnil;
1201
1202   CHECK_INT (*args); tm.tm_sec  = XINT (*args++);       /* second */
1203   CHECK_INT (*args); tm.tm_min  = XINT (*args++);       /* minute */
1204   CHECK_INT (*args); tm.tm_hour = XINT (*args++);       /* hour */
1205   CHECK_INT (*args); tm.tm_mday = XINT (*args++);       /* day */
1206   CHECK_INT (*args); tm.tm_mon  = XINT (*args++) - 1;   /* month */
1207   CHECK_INT (*args); tm.tm_year = XINT (*args++) - 1900;/* year */
1208
1209   tm.tm_isdst = -1;
1210
1211   if (CONSP (zone))
1212     zone = XCAR (zone);
1213   if (NILP (zone))
1214     the_time = mktime (&tm);
1215   else
1216     {
1217       char tzbuf[100];
1218       char *tzstring;
1219       char **oldenv = environ, **newenv;
1220
1221       if (STRINGP (zone))
1222         tzstring = (char *) XSTRING_DATA (zone);
1223       else if (INTP (zone))
1224         {
1225           int abszone = abs (XINT (zone));
1226           sprintf (tzbuf, "XXX%s%d:%02d:%02d", "-" + (XINT (zone) < 0),
1227                    abszone / (60*60), (abszone/60) % 60, abszone % 60);
1228           tzstring = tzbuf;
1229         }
1230       else
1231         error ("Invalid time zone specification");
1232
1233       /* Set TZ before calling mktime; merely adjusting mktime's returned
1234          value doesn't suffice, since that would mishandle leap seconds.  */
1235       set_time_zone_rule (tzstring);
1236
1237       the_time = mktime (&tm);
1238
1239       /* Restore TZ to previous value.  */
1240       newenv = environ;
1241       environ = oldenv;
1242       free (newenv);
1243 #ifdef LOCALTIME_CACHE
1244       tzset ();
1245 #endif
1246     }
1247
1248   if (the_time == (time_t) -1)
1249     error ("Specified time is not representable");
1250
1251   return wasteful_word_to_lisp (the_time);
1252 }
1253
1254 DEFUN ("current-time-string", Fcurrent_time_string, 0, 1, 0, /*
1255 Return the current time, as a human-readable string.
1256 Programs can use this function to decode a time,
1257 since the number of columns in each field is fixed.
1258 The format is `Sun Sep 16 01:03:52 1973'.
1259 If an argument is given, it specifies a time to format
1260 instead of the current time.  The argument should have the form:
1261   (HIGH . LOW)
1262 or the form:
1263   (HIGH LOW . IGNORED).
1264 Thus, you can use times obtained from `current-time'
1265 and from `file-attributes'.
1266 */
1267        (specified_time))
1268 {
1269   time_t value;
1270   char *the_ctime;
1271   size_t len;
1272
1273   if (! lisp_to_time (specified_time, &value))
1274     value = -1;
1275   the_ctime = ctime (&value);
1276
1277   /* ctime is documented as always returning a "\n\0"-terminated
1278      26-byte American time string, but let's be careful anyways. */
1279   for (len = 0; the_ctime[len] != '\n' && the_ctime[len] != '\0'; len++)
1280     ;
1281
1282   return make_ext_string ((Extbyte *) the_ctime, len, Qbinary);
1283 }
1284
1285 #define TM_YEAR_ORIGIN 1900
1286
1287 /* Yield A - B, measured in seconds.  */
1288 static long
1289 difftm (const struct tm *a, const struct tm *b)
1290 {
1291   int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
1292   int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
1293   /* Some compilers can't handle this as a single return statement.  */
1294   long days = (
1295               /* difference in day of year */
1296               a->tm_yday - b->tm_yday
1297               /* + intervening leap days */
1298               +  ((ay >> 2) - (by >> 2))
1299               -  (ay/100 - by/100)
1300               +  ((ay/100 >> 2) - (by/100 >> 2))
1301               /* + difference in years * 365 */
1302               +  (long)(ay-by) * 365
1303               );
1304   return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
1305               + (a->tm_min - b->tm_min))
1306           + (a->tm_sec - b->tm_sec));
1307 }
1308
1309 DEFUN ("current-time-zone", Fcurrent_time_zone, 0, 1, 0, /*
1310 Return the offset and name for the local time zone.
1311 This returns a list of the form (OFFSET NAME).
1312 OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).
1313     A negative value means west of Greenwich.
1314 NAME is a string giving the name of the time zone.
1315 If an argument is given, it specifies when the time zone offset is determined
1316 instead of using the current time.  The argument should have the form:
1317   (HIGH . LOW)
1318 or the form:
1319   (HIGH LOW . IGNORED).
1320 Thus, you can use times obtained from `current-time'
1321 and from `file-attributes'.
1322
1323 Some operating systems cannot provide all this information to Emacs;
1324 in this case, `current-time-zone' returns a list containing nil for
1325 the data it can't find.
1326 */
1327        (specified_time))
1328 {
1329   time_t value;
1330   struct tm *t = NULL;
1331
1332   if (lisp_to_time (specified_time, &value)
1333       && (t = gmtime (&value)) != 0)
1334     {
1335       struct tm gmt = *t;       /* Make a copy, in case localtime modifies *t.  */
1336       long offset;
1337       char *s, buf[6];
1338
1339       t = localtime (&value);
1340       offset = difftm (t, &gmt);
1341       s = 0;
1342 #ifdef HAVE_TM_ZONE
1343       if (t->tm_zone)
1344         s = (char *)t->tm_zone;
1345 #else /* not HAVE_TM_ZONE */
1346 #ifdef HAVE_TZNAME
1347       if (t->tm_isdst == 0 || t->tm_isdst == 1)
1348         s = tzname[t->tm_isdst];
1349 #endif
1350 #endif /* not HAVE_TM_ZONE */
1351       if (!s)
1352         {
1353           /* No local time zone name is available; use "+-NNNN" instead.  */
1354           int am = (offset < 0 ? -offset : offset) / 60;
1355           sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
1356           s = buf;
1357         }
1358       return list2 (make_int (offset), build_string (s));
1359     }
1360   else
1361     return list2 (Qnil, Qnil);
1362 }
1363
1364 #ifdef LOCALTIME_CACHE
1365
1366 /* These two values are known to load tz files in buggy implementations,
1367    i.e. Solaris 1 executables running under either Solaris 1 or Solaris 2.
1368    Their values shouldn't matter in non-buggy implementations.
1369    We don't use string literals for these strings,
1370    since if a string in the environment is in readonly
1371    storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
1372    See Sun bugs 1113095 and 1114114, ``Timezone routines
1373    improperly modify environment''.  */
1374
1375 static char set_time_zone_rule_tz1[] = "TZ=GMT+0";
1376 static char set_time_zone_rule_tz2[] = "TZ=GMT+1";
1377
1378 #endif
1379
1380 /* Set the local time zone rule to TZSTRING.
1381    This allocates memory into `environ', which it is the caller's
1382    responsibility to free.  */
1383 static void
1384 set_time_zone_rule (char *tzstring)
1385 {
1386   int envptrs;
1387   char **from, **to, **newenv;
1388
1389   for (from = environ; *from; from++)
1390     continue;
1391   envptrs = from - environ + 2;
1392   newenv = to = (char **) xmalloc (envptrs * sizeof (char *)
1393                                    + (tzstring ? strlen (tzstring) + 4 : 0));
1394   if (tzstring)
1395     {
1396       char *t = (char *) (to + envptrs);
1397       strcpy (t, "TZ=");
1398       strcat (t, tzstring);
1399       *to++ = t;
1400     }
1401
1402   for (from = environ; *from; from++)
1403     if (strncmp (*from, "TZ=", 3) != 0)
1404       *to++ = *from;
1405   *to = 0;
1406
1407   environ = newenv;
1408
1409 #ifdef LOCALTIME_CACHE
1410   {
1411     /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
1412        "US/Pacific" that loads a tz file, then changes to a value like
1413        "XXX0" that does not load a tz file, and then changes back to
1414        its original value, the last change is (incorrectly) ignored.
1415        Also, if TZ changes twice in succession to values that do
1416        not load a tz file, tzset can dump core (see Sun bug#1225179).
1417        The following code works around these bugs.  */
1418
1419     if (tzstring)
1420       {
1421         /* Temporarily set TZ to a value that loads a tz file
1422            and that differs from tzstring.  */
1423         char *tz = *newenv;
1424         *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
1425                    ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
1426         tzset ();
1427         *newenv = tz;
1428       }
1429     else
1430       {
1431         /* The implied tzstring is unknown, so temporarily set TZ to
1432            two different values that each load a tz file.  */
1433         *to = set_time_zone_rule_tz1;
1434         to[1] = 0;
1435         tzset ();
1436         *to = set_time_zone_rule_tz2;
1437         tzset ();
1438         *to = 0;
1439       }
1440
1441     /* Now TZ has the desired value, and tzset can be invoked safely.  */
1442   }
1443
1444   tzset ();
1445 #endif
1446 }
1447
1448 DEFUN ("set-time-zone-rule", Fset_time_zone_rule, 1, 1, 0, /*
1449 Set the local time zone using TZ, a string specifying a time zone rule.
1450 If TZ is nil, use implementation-defined default time zone information.
1451 */
1452        (tz))
1453 {
1454   char *tzstring;
1455
1456   if (NILP (tz))
1457     tzstring = 0;
1458   else
1459     {
1460       CHECK_STRING (tz);
1461       tzstring = (char *) XSTRING_DATA (tz);
1462     }
1463
1464   set_time_zone_rule (tzstring);
1465   if (environbuf)
1466     xfree (environbuf);
1467   environbuf = environ;
1468
1469   return Qnil;
1470 }
1471
1472 \f
1473 void
1474 buffer_insert1 (struct buffer *buf, Lisp_Object arg)
1475 {
1476   /* This function can GC */
1477   struct gcpro gcpro1;
1478   GCPRO1 (arg);
1479  retry:
1480   if (CHAR_OR_CHAR_INTP (arg))
1481     {
1482       buffer_insert_emacs_char (buf, XCHAR_OR_CHAR_INT (arg));
1483     }
1484   else if (STRINGP (arg))
1485     {
1486       buffer_insert_lisp_string (buf, arg);
1487     }
1488   else
1489     {
1490       arg = wrong_type_argument (Qchar_or_string_p, arg);
1491       goto retry;
1492     }
1493   zmacs_region_stays = 0;
1494   UNGCPRO;
1495 }
1496
1497
1498 /* Callers passing one argument to Finsert need not gcpro the
1499    argument "array", since the only element of the array will
1500    not be used after calling insert_emacs_char or insert_lisp_string,
1501    so we don't care if it gets trashed.  */
1502
1503 DEFUN ("insert", Finsert, 0, MANY, 0, /*
1504 Insert the arguments, either strings or characters, at point.
1505 Point moves forward so that it ends up after the inserted text.
1506 Any other markers at the point of insertion remain before the text.
1507 If a string has non-null string-extent-data, new extents will be created.
1508 */
1509        (int nargs, Lisp_Object *args))
1510 {
1511   /* This function can GC */
1512   REGISTER int argnum;
1513
1514   for (argnum = 0; argnum < nargs; argnum++)
1515     {
1516       buffer_insert1 (current_buffer, args[argnum]);
1517     }
1518
1519   return Qnil;
1520 }
1521
1522 DEFUN ("insert-before-markers", Finsert_before_markers, 0, MANY, 0, /*
1523 Insert strings or characters at point, relocating markers after the text.
1524 Point moves forward so that it ends up after the inserted text.
1525 Any other markers at the point of insertion also end up after the text.
1526 */
1527        (int nargs, Lisp_Object *args))
1528 {
1529   /* This function can GC */
1530   REGISTER int argnum;
1531   REGISTER Lisp_Object tem;
1532
1533   for (argnum = 0; argnum < nargs; argnum++)
1534     {
1535       tem = args[argnum];
1536     retry:
1537       if (CHAR_OR_CHAR_INTP (tem))
1538         {
1539           buffer_insert_emacs_char_1 (current_buffer, -1,
1540                                       XCHAR_OR_CHAR_INT (tem),
1541                                       INSDEL_BEFORE_MARKERS);
1542         }
1543       else if (STRINGP (tem))
1544         {
1545           buffer_insert_lisp_string_1 (current_buffer, -1, tem,
1546                                        INSDEL_BEFORE_MARKERS);
1547         }
1548       else
1549         {
1550           tem = wrong_type_argument (Qchar_or_string_p, tem);
1551           goto retry;
1552         }
1553     }
1554   zmacs_region_stays = 0;
1555   return Qnil;
1556 }
1557
1558 DEFUN ("insert-string", Finsert_string, 1, 2, 0, /*
1559 Insert STRING into BUFFER at BUFFER's point.
1560 Point moves forward so that it ends up after the inserted text.
1561 Any other markers at the point of insertion remain before the text.
1562 If a string has non-null string-extent-data, new extents will be created.
1563 BUFFER defaults to the current buffer.
1564 */
1565        (string, buffer))
1566 {
1567   struct buffer *b = decode_buffer (buffer, 1);
1568   CHECK_STRING (string);
1569   buffer_insert_lisp_string (b, string);
1570   zmacs_region_stays = 0;
1571   return Qnil;
1572 }
1573
1574 /* Third argument in FSF is INHERIT:
1575
1576 "The optional third arg INHERIT, if non-nil, says to inherit text properties
1577 from adjoining text, if those properties are sticky."
1578
1579 Jamie thinks this is bogus. */
1580
1581 \f
1582 DEFUN ("insert-char", Finsert_char, 1, 4, 0, /*
1583 Insert COUNT copies of CHARACTER into BUFFER.
1584 Point and all markers are affected as in the function `insert'.
1585 COUNT defaults to 1 if omitted.
1586 The optional third arg IGNORED is INHERIT under FSF Emacs.
1587 This is highly bogus, however, and XEmacs always behaves as if
1588 `t' were passed to INHERIT.
1589 The optional fourth arg BUFFER specifies the buffer to insert the
1590 text into.  If BUFFER is nil, the current buffer is assumed.
1591 */
1592        (character, count, ignored, buffer))
1593 {
1594   /* This function can GC */
1595   REGISTER Bufbyte *string;
1596   REGISTER int slen;
1597   REGISTER int i, j;
1598   REGISTER Bytecount n;
1599   REGISTER Bytecount charlen;
1600   Bufbyte str[MAX_EMCHAR_LEN];
1601   struct buffer *b = decode_buffer (buffer, 1);
1602   int cou;
1603
1604   CHECK_CHAR_COERCE_INT (character);
1605   if (NILP (count))
1606     cou = 1;
1607   else
1608     {
1609       CHECK_INT (count);
1610       cou = XINT (count);
1611     }
1612
1613   charlen = set_charptr_emchar (str, XCHAR (character));
1614   n = cou * charlen;
1615   if (n <= 0)
1616     return Qnil;
1617   slen = min (n, 768);
1618   string = alloca_array (Bufbyte, slen);
1619   /* Write as many copies of the character into the temp string as will fit. */
1620   for (i = 0; i + charlen <= slen; i += charlen)
1621     for (j = 0; j < charlen; j++)
1622       string[i + j] = str[j];
1623   slen = i;
1624   while (n >= slen)
1625     {
1626       buffer_insert_raw_string (b, string, slen);
1627       n -= slen;
1628     }
1629   if (n > 0)
1630 #if 0 /* FSFmacs bogosity */
1631     {
1632       if (!NILP (inherit))
1633         insert_and_inherit (string, n);
1634       else
1635         insert (string, n);
1636     }
1637 #else
1638     buffer_insert_raw_string (b, string, n);
1639 #endif
1640
1641   zmacs_region_stays = 0;
1642   return Qnil;
1643 }
1644
1645 \f
1646 /* Making strings from buffer contents.  */
1647
1648 DEFUN ("buffer-substring", Fbuffer_substring, 0, 3, 0, /*
1649 Return the contents of part of BUFFER as a string.
1650 The two arguments START and END are character positions;
1651 they can be in either order.  If omitted, they default to the beginning
1652 and end of BUFFER, respectively.
1653 If there are duplicable extents in the region, the string remembers
1654 them in its extent data.
1655 If BUFFER is nil, the current buffer is assumed.
1656 */
1657        (start, end, buffer))
1658 {
1659   /* This function can GC */
1660   Bufpos begv, zv;
1661   struct buffer *b = decode_buffer (buffer, 1);
1662
1663   get_buffer_range_char (b, start, end, &begv, &zv, GB_ALLOW_NIL);
1664   return make_string_from_buffer (b, begv, zv - begv);
1665 }
1666
1667 /* It might make more sense to name this
1668    `buffer-substring-no-extents', but this name is FSFmacs-compatible,
1669    and what the function does is probably good enough for what the
1670    user-code will typically want to use it for. */
1671 DEFUN ("buffer-substring-no-properties", Fbuffer_substring_no_properties, 0, 3, 0, /*
1672 Return the text from START to END as a string, without copying the extents.
1673 */
1674        (start, end, buffer))
1675 {
1676   /* This function can GC */
1677   Bufpos begv, zv;
1678   struct buffer *b = decode_buffer (buffer, 1);
1679
1680   get_buffer_range_char (b, start, end, &begv, &zv, GB_ALLOW_NIL);
1681   return make_string_from_buffer_no_extents (b, begv, zv - begv);
1682 }
1683
1684 DEFUN ("insert-buffer-substring", Finsert_buffer_substring, 1, 3, 0, /*
1685 Insert before point a substring of the contents of buffer BUFFER.
1686 BUFFER may be a buffer or a buffer name.
1687 Arguments START and END are character numbers specifying the substring.
1688 They default to the beginning and the end of BUFFER.
1689 */
1690        (buffer, start, end))
1691 {
1692   /* This function can GC */
1693   Bufpos b, e;
1694   struct buffer *bp;
1695
1696   bp = XBUFFER (get_buffer (buffer, 1));
1697   get_buffer_range_char (bp, start, end, &b, &e, GB_ALLOW_NIL);
1698
1699   if (b < e)
1700     buffer_insert_from_buffer (current_buffer, bp, b, e - b);
1701
1702   return Qnil;
1703 }
1704 \f
1705 DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, 6, 6, 0, /*
1706 Compare two substrings of two buffers; return result as number.
1707 the value is -N if first string is less after N-1 chars,
1708 +N if first string is greater after N-1 chars, or 0 if strings match.
1709 Each substring is represented as three arguments: BUFFER, START and END.
1710 That makes six args in all, three for each substring.
1711
1712 The value of `case-fold-search' in the current buffer
1713 determines whether case is significant or ignored.
1714 */
1715        (buffer1, start1, end1, buffer2, start2, end2))
1716 {
1717   Bufpos begp1, endp1, begp2, endp2;
1718   REGISTER Charcount len1, len2, length, i;
1719   struct buffer *bp1, *bp2;
1720   Lisp_Object trt = ((!NILP (current_buffer->case_fold_search)) ?
1721                      XCASE_TABLE_CANON (current_buffer->case_table) : Qnil);
1722
1723   /* Find the first buffer and its substring.  */
1724
1725   bp1 = decode_buffer (buffer1, 1);
1726   get_buffer_range_char (bp1, start1, end1, &begp1, &endp1, GB_ALLOW_NIL);
1727
1728   /* Likewise for second substring.  */
1729
1730   bp2 = decode_buffer (buffer2, 1);
1731   get_buffer_range_char (bp2, start2, end2, &begp2, &endp2, GB_ALLOW_NIL);
1732
1733   len1 = endp1 - begp1;
1734   len2 = endp2 - begp2;
1735   length = len1;
1736   if (len2 < length)
1737     length = len2;
1738
1739   for (i = 0; i < length; i++)
1740     {
1741       Emchar c1 = BUF_FETCH_CHAR (bp1, begp1 + i);
1742       Emchar c2 = BUF_FETCH_CHAR (bp2, begp2 + i);
1743       if (!NILP (trt))
1744         {
1745           c1 = TRT_TABLE_OF (trt, c1);
1746           c2 = TRT_TABLE_OF (trt, c2);
1747         }
1748       if (c1 < c2)
1749         return make_int (- 1 - i);
1750       if (c1 > c2)
1751         return make_int (i + 1);
1752     }
1753
1754   /* The strings match as far as they go.
1755      If one is shorter, that one is less.  */
1756   if (length < len1)
1757     return make_int (length + 1);
1758   else if (length < len2)
1759     return make_int (- length - 1);
1760
1761   /* Same length too => they are equal.  */
1762   return Qzero;
1763 }
1764
1765 \f
1766 static Lisp_Object
1767 subst_char_in_region_unwind (Lisp_Object arg)
1768 {
1769   XBUFFER (XCAR (arg))->undo_list = XCDR (arg);
1770   return Qnil;
1771 }
1772
1773 static Lisp_Object
1774 subst_char_in_region_unwind_1 (Lisp_Object arg)
1775 {
1776   XBUFFER (XCAR (arg))->filename = XCDR (arg);
1777   return Qnil;
1778 }
1779
1780 DEFUN ("subst-char-in-region", Fsubst_char_in_region, 4, 5, 0, /*
1781 From START to END, replace FROMCHAR with TOCHAR each time it occurs.
1782 If optional arg NOUNDO is non-nil, don't record this change for undo
1783 and don't mark the buffer as really changed.
1784 */
1785   (start, end, fromchar, tochar, noundo))
1786 {
1787   /* This function can GC */
1788   Bufpos pos, stop;
1789   Emchar fromc, toc;
1790   int mc_count;
1791   struct buffer *buf = current_buffer;
1792   int count = specpdl_depth ();
1793
1794   get_buffer_range_char (buf, start, end, &pos, &stop, 0);
1795   CHECK_CHAR_COERCE_INT (fromchar);
1796   CHECK_CHAR_COERCE_INT (tochar);
1797
1798   fromc = XCHAR (fromchar);
1799   toc = XCHAR (tochar);
1800
1801   /* If we don't want undo, turn off putting stuff on the list.
1802      That's faster than getting rid of things,
1803      and it prevents even the entry for a first change.
1804      Also inhibit locking the file.  */
1805   if (!NILP (noundo))
1806     {
1807       record_unwind_protect (subst_char_in_region_unwind,
1808                              Fcons (Fcurrent_buffer (), buf->undo_list));
1809       buf->undo_list = Qt;
1810       /* Don't do file-locking.  */
1811       record_unwind_protect (subst_char_in_region_unwind_1,
1812                              Fcons (Fcurrent_buffer (), buf->filename));
1813       buf->filename = Qnil;
1814     }
1815
1816   mc_count = begin_multiple_change (buf, pos, stop);
1817   while (pos < stop)
1818     {
1819       if (BUF_FETCH_CHAR (buf, pos) == fromc)
1820         {
1821           /* There used to be some code here that set the buffer to
1822              unmodified if NOUNDO was specified and there was only
1823              one change to the buffer since it was last saved.
1824              This is a crock of shit, so I'm not duplicating this
1825              behavior.  I think this was left over from when
1826              prepare_to_modify_buffer() actually bumped MODIFF,
1827              so that code was supposed to undo this change. --ben */
1828           buffer_replace_char (buf, pos, toc, !NILP (noundo), 0);
1829
1830           /* If noundo is not nil then we don't mark the buffer as
1831              modified.  In reality that needs to happen externally
1832              only.  Internally redisplay needs to know that the actual
1833              contents it should be displaying have changed. */
1834           if (!NILP (noundo))
1835             Fset_buffer_modified_p (Fbuffer_modified_p (Qnil), Qnil);
1836         }
1837       pos++;
1838     }
1839   end_multiple_change (buf, mc_count);
1840
1841   unbind_to (count, Qnil);
1842   return Qnil;
1843 }
1844
1845 /* #### Shouldn't this also accept a BUFFER argument, in the good old
1846    XEmacs tradition?  */
1847 DEFUN ("translate-region", Ftranslate_region, 3, 3, 0, /*
1848 Translate characters from START to END according to TABLE.
1849
1850 If TABLE is a string, the Nth character in it is the mapping for the
1851 character with code N.
1852
1853 If TABLE is a vector, its Nth element is the mapping for character
1854 with code N.  The values of elements may be characters, strings, or
1855 nil (nil meaning don't replace.)
1856
1857 If TABLE is a char-table, its elements describe the mapping between
1858 characters and their replacements.  The char-table should be of type
1859 `char' or `generic'.
1860
1861 Returns the number of substitutions performed.
1862 */
1863        (start, end, table))
1864 {
1865   /* This function can GC */
1866   Bufpos pos, stop;     /* Limits of the region. */
1867   int cnt = 0;          /* Number of changes made. */
1868   int mc_count;
1869   struct buffer *buf = current_buffer;
1870   Emchar oc;
1871
1872   get_buffer_range_char (buf, start, end, &pos, &stop, 0);
1873   mc_count = begin_multiple_change (buf, pos, stop);
1874   if (STRINGP (table))
1875     {
1876       Lisp_String *stable = XSTRING (table);
1877       Charcount size = string_char_length (stable);
1878 #ifdef MULE
1879       /* Under Mule, string_char(n) is O(n), so for large tables or
1880          large regions it makes sense to create an array of Emchars.  */
1881       if (size * (stop - pos) > 65536)
1882         {
1883           Emchar *etable = alloca_array (Emchar, size);
1884           convert_bufbyte_string_into_emchar_string
1885             (string_data (stable), string_length (stable), etable);
1886           for (; pos < stop && (oc = BUF_FETCH_CHAR (buf, pos), 1); pos++)
1887             {
1888               if (oc < size)
1889                 {
1890                   Emchar nc = etable[oc];
1891                   if (nc != oc)
1892                     {
1893                       buffer_replace_char (buf, pos, nc, 0, 0);
1894                       ++cnt;
1895                     }
1896                 }
1897             }
1898         }
1899       else
1900 #endif /* MULE */
1901         {
1902           for (; pos < stop && (oc = BUF_FETCH_CHAR (buf, pos), 1); pos++)
1903             {
1904               if (oc < size)
1905                 {
1906                   Emchar nc = string_char (stable, oc);
1907                   if (nc != oc)
1908                     {
1909                       buffer_replace_char (buf, pos, nc, 0, 0);
1910                       ++cnt;
1911                     }
1912                 }
1913             }
1914         }
1915     }
1916   else if (VECTORP (table))
1917     {
1918       Charcount size = XVECTOR_LENGTH (table);
1919       Lisp_Object *vtable = XVECTOR_DATA (table);
1920
1921       for (; pos < stop && (oc = BUF_FETCH_CHAR (buf, pos), 1); pos++)
1922         {
1923           if (oc < size)
1924             {
1925               Lisp_Object replacement = vtable[oc];
1926             retry:
1927               if (CHAR_OR_CHAR_INTP (replacement))
1928                 {
1929                   Emchar nc = XCHAR_OR_CHAR_INT (replacement);
1930                   if (nc != oc)
1931                     {
1932                       buffer_replace_char (buf, pos, nc, 0, 0);
1933                       ++cnt;
1934                     }
1935                 }
1936               else if (STRINGP (replacement))
1937                 {
1938                   Charcount incr = XSTRING_CHAR_LENGTH (replacement) - 1;
1939                   buffer_delete_range (buf, pos, pos + 1, 0);
1940                   buffer_insert_lisp_string_1 (buf, pos, replacement, 0);
1941                   pos += incr, stop += incr;
1942                   ++cnt;
1943                 }
1944               else if (!NILP (replacement))
1945                 {
1946                   replacement = wrong_type_argument (Qchar_or_string_p, replacement);
1947                   goto retry;
1948                 }
1949             }
1950         }
1951     }
1952   else if (CHAR_TABLEP (table)
1953            && (XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_GENERIC
1954                || XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_CHAR))
1955     {
1956       Lisp_Char_Table *ctable = XCHAR_TABLE (table);
1957
1958       for (; pos < stop && (oc = BUF_FETCH_CHAR (buf, pos), 1); pos++)
1959         {
1960           Lisp_Object replacement = get_char_table (oc, ctable);
1961         retry2:
1962           if (CHAR_OR_CHAR_INTP (replacement))
1963             {
1964               Emchar nc = XCHAR_OR_CHAR_INT (replacement);
1965               if (nc != oc)
1966                 {
1967                   buffer_replace_char (buf, pos, nc, 0, 0);
1968                   ++cnt;
1969                 }
1970             }
1971           else if (STRINGP (replacement))
1972             {
1973               Charcount incr = XSTRING_CHAR_LENGTH (replacement) - 1;
1974               buffer_delete_range (buf, pos, pos + 1, 0);
1975               buffer_insert_lisp_string_1 (buf, pos, replacement, 0);
1976               pos += incr, stop += incr;
1977               ++cnt;
1978             }
1979           else if (!NILP (replacement))
1980             {
1981               replacement = wrong_type_argument (Qchar_or_string_p, replacement);
1982               goto retry2;
1983             }
1984         }
1985     }
1986   else
1987     dead_wrong_type_argument (Qstringp, table);
1988   end_multiple_change (buf, mc_count);
1989
1990   return make_int (cnt);
1991 }
1992
1993 DEFUN ("delete-region", Fdelete_region, 2, 3, "r", /*
1994 Delete the text between point and mark.
1995 When called from a program, expects two arguments START and END
1996 \(integers or markers) specifying the stretch to be deleted.
1997 If optional third arg BUFFER is nil, the current buffer is assumed.
1998 */
1999        (start, end, buffer))
2000 {
2001   /* This function can GC */
2002   Bufpos bp_start, bp_end;
2003   struct buffer *buf = decode_buffer (buffer, 1);
2004
2005   get_buffer_range_char (buf, start, end, &bp_start, &bp_end, 0);
2006   buffer_delete_range (buf, bp_start, bp_end, 0);
2007   zmacs_region_stays = 0;
2008   return Qnil;
2009 }
2010 \f
2011 void
2012 widen_buffer (struct buffer *b, int no_clip)
2013 {
2014   if (BUF_BEGV (b) != BUF_BEG (b))
2015     {
2016       clip_changed = 1;
2017       SET_BOTH_BUF_BEGV (b, BUF_BEG (b), BI_BUF_BEG (b));
2018     }
2019   if (BUF_ZV (b) != BUF_Z (b))
2020     {
2021       clip_changed = 1;
2022       SET_BOTH_BUF_ZV (b, BUF_Z (b), BI_BUF_Z (b));
2023     }
2024   if (clip_changed)
2025     {
2026       if (!no_clip)
2027         MARK_CLIP_CHANGED;
2028       /* Changing the buffer bounds invalidates any recorded current
2029          column.  */
2030       invalidate_current_column ();
2031       narrow_line_number_cache (b);
2032     }
2033 }
2034
2035 DEFUN ("widen", Fwiden, 0, 1, "", /*
2036 Remove restrictions (narrowing) from BUFFER.
2037 This allows the buffer's full text to be seen and edited.
2038 If BUFFER is nil, the current buffer is assumed.
2039 */
2040        (buffer))
2041 {
2042   struct buffer *b = decode_buffer (buffer, 1);
2043   widen_buffer (b, 0);
2044   zmacs_region_stays = 0;
2045   return Qnil;
2046 }
2047
2048 DEFUN ("narrow-to-region", Fnarrow_to_region, 2, 3, "r", /*
2049 Restrict editing in BUFFER to the current region.
2050 The rest of the text becomes temporarily invisible and untouchable
2051 but is not deleted; if you save the buffer in a file, the invisible
2052 text is included in the file.  \\[widen] makes all visible again.
2053 If BUFFER is nil, the current buffer is assumed.
2054 See also `save-restriction'.
2055
2056 When calling from a program, pass two arguments; positions (integers
2057 or markers) bounding the text that should remain visible.
2058 */
2059        (start, end, buffer))
2060 {
2061   Bufpos bp_start, bp_end;
2062   struct buffer *buf = decode_buffer (buffer, 1);
2063   Bytind bi_start, bi_end;
2064
2065   get_buffer_range_char (buf, start, end, &bp_start, &bp_end,
2066                          GB_ALLOW_PAST_ACCESSIBLE);
2067   bi_start = bufpos_to_bytind (buf, bp_start);
2068   bi_end = bufpos_to_bytind (buf, bp_end);
2069
2070   SET_BOTH_BUF_BEGV (buf, bp_start, bi_start);
2071   SET_BOTH_BUF_ZV (buf, bp_end, bi_end);
2072   if (BUF_PT (buf) < bp_start)
2073     BUF_SET_PT (buf, bp_start);
2074   if (BUF_PT (buf) > bp_end)
2075     BUF_SET_PT (buf, bp_end);
2076   MARK_CLIP_CHANGED;
2077   /* Changing the buffer bounds invalidates any recorded current column.  */
2078   invalidate_current_column ();
2079   narrow_line_number_cache (buf);
2080   zmacs_region_stays = 0;
2081   return Qnil;
2082 }
2083
2084 Lisp_Object
2085 save_restriction_save (void)
2086 {
2087   Lisp_Object bottom, top;
2088   /* Note: I tried using markers here, but it does not win
2089      because insertion at the end of the saved region
2090      does not advance mh and is considered "outside" the saved region. */
2091   bottom = make_int (BUF_BEGV (current_buffer) - BUF_BEG (current_buffer));
2092   top = make_int (BUF_Z (current_buffer) - BUF_ZV (current_buffer));
2093
2094   return noseeum_cons (Fcurrent_buffer (), noseeum_cons (bottom, top));
2095 }
2096
2097 Lisp_Object
2098 save_restriction_restore (Lisp_Object data)
2099 {
2100   struct buffer *buf;
2101   Charcount newhead, newtail;
2102   Lisp_Object tem;
2103   int local_clip_changed = 0;
2104
2105   buf = XBUFFER (XCAR (data));
2106   if (!BUFFER_LIVE_P (buf))
2107     {
2108       /* someone could have killed the buffer in the meantime ... */
2109       free_cons (XCONS (XCDR (data)));
2110       free_cons (XCONS (data));
2111       return Qnil;
2112     }
2113   tem = XCDR (data);
2114   newhead = XINT (XCAR (tem));
2115   newtail = XINT (XCDR (tem));
2116
2117   free_cons (XCONS (XCDR (data)));
2118   free_cons (XCONS (data));
2119
2120   if (newhead + newtail > BUF_Z (buf) - BUF_BEG (buf))
2121     {
2122       newhead = 0;
2123       newtail = 0;
2124     }
2125
2126   {
2127     Bufpos start, end;
2128     Bytind bi_start, bi_end;
2129
2130     start = BUF_BEG (buf) + newhead;
2131     end = BUF_Z (buf) - newtail;
2132
2133     bi_start = bufpos_to_bytind (buf, start);
2134     bi_end = bufpos_to_bytind (buf, end);
2135
2136     if (BUF_BEGV (buf) != start)
2137       {
2138         local_clip_changed = 1;
2139         SET_BOTH_BUF_BEGV (buf, start, bi_start);
2140         narrow_line_number_cache (buf);
2141       }
2142     if (BUF_ZV (buf) != end)
2143       {
2144         local_clip_changed = 1;
2145         SET_BOTH_BUF_ZV (buf, end, bi_end);
2146       }
2147   }
2148   if (local_clip_changed)
2149     MARK_CLIP_CHANGED;
2150
2151   /* If point is outside the new visible range, move it inside. */
2152   BUF_SET_PT (buf,
2153               bufpos_clip_to_bounds (BUF_BEGV (buf),
2154                                      BUF_PT (buf),
2155                                      BUF_ZV (buf)));
2156
2157   return Qnil;
2158 }
2159
2160 DEFUN ("save-restriction", Fsave_restriction, 0, UNEVALLED, 0, /*
2161 Execute BODY, saving and restoring current buffer's restrictions.
2162 The buffer's restrictions make parts of the beginning and end invisible.
2163 \(They are set up with `narrow-to-region' and eliminated with `widen'.)
2164 This special form, `save-restriction', saves the current buffer's restrictions
2165 when it is entered, and restores them when it is exited.
2166 So any `narrow-to-region' within BODY lasts only until the end of the form.
2167 The old restrictions settings are restored
2168 even in case of abnormal exit (throw or error).
2169
2170 The value returned is the value of the last form in BODY.
2171
2172 `save-restriction' can get confused if, within the BODY, you widen
2173 and then make changes outside the area within the saved restrictions.
2174
2175 Note: if you are using both `save-excursion' and `save-restriction',
2176 use `save-excursion' outermost:
2177     (save-excursion (save-restriction ...))
2178 */
2179        (body))
2180 {
2181   /* This function can GC */
2182   int speccount = specpdl_depth ();
2183
2184   record_unwind_protect (save_restriction_restore, save_restriction_save ());
2185
2186   return unbind_to (speccount, Fprogn (body));
2187 }
2188
2189 \f
2190 DEFUN ("format", Fformat, 1, MANY, 0, /*
2191 Format a string out of a control-string and arguments.
2192 The first argument is a control string.
2193 The other arguments are substituted into it to make the result, a string.
2194 It may contain %-sequences meaning to substitute the next argument.
2195 %s means print all objects as-is, using `princ'.
2196 %S means print all objects as s-expressions, using `prin1'.
2197 %d or %i means print as an integer in decimal (%o octal, %x lowercase hex,
2198   %X uppercase hex).
2199 %c means print as a single character.
2200 %f means print as a floating-point number in fixed notation (e.g. 785.200).
2201 %e or %E means print as a floating-point number in scientific notation
2202   (e.g. 7.85200e+03).
2203 %g or %G means print as a floating-point number in "pretty format";
2204   depending on the number, either %f or %e/%E format will be used, and
2205   trailing zeroes are removed from the fractional part.
2206 The argument used for all but %s and %S must be a number.  It will be
2207   converted to an integer or a floating-point number as necessary.
2208
2209 %$ means reposition to read a specific numbered argument; for example,
2210   %3$s would apply the `%s' to the third argument after the control string,
2211   and the next format directive would use the fourth argument, the
2212   following one the fifth argument, etc. (There must be a positive integer
2213   between the % and the $).
2214 Zero or more of the flag characters `-', `+', ` ', `0', and `#' may be
2215   specified between the optional repositioning spec and the conversion
2216   character; see below.
2217 An optional minimum field width may be specified after any flag characters
2218   and before the conversion character; it specifies the minimum number of
2219   characters that the converted argument will take up.  Padding will be
2220   added on the left (or on the right, if the `-' flag is specified), as
2221   necessary.  Padding is done with spaces, or with zeroes if the `0' flag
2222   is specified.
2223 If the field width is specified as `*', the field width is assumed to have
2224   been specified as an argument.  Any repositioning specification that
2225   would normally specify the argument to be converted will now specify
2226   where to find this field width argument, not where to find the argument
2227   to be converted.  If there is no repositioning specification, the normal
2228   next argument is used.  The argument to be converted will be the next
2229   argument after the field width argument unless the precision is also
2230   specified as `*' (see below).
2231
2232 An optional period character and precision may be specified after any
2233   minimum field width.  It specifies the minimum number of digits to
2234   appear in %d, %i, %o, %x, and %X conversions (the number is padded
2235   on the left with zeroes as necessary); the number of digits printed
2236   after the decimal point for %f, %e, and %E conversions; the number
2237   of significant digits printed in %g and %G conversions; and the
2238   maximum number of non-padding characters printed in %s and %S
2239   conversions.  The default precision for floating-point conversions
2240   is six.
2241 If the precision is specified as `*', the precision is assumed to have been
2242   specified as an argument.  The argument used will be the next argument
2243   after the field width argument, if any.  If the field width was not
2244   specified as an argument, any repositioning specification that would
2245   normally specify the argument to be converted will now specify where to
2246   find the precision argument.  If there is no repositioning specification,
2247   the normal next argument is used.
2248
2249 The ` ' and `+' flags mean prefix non-negative numbers with a space or
2250   plus sign, respectively.
2251 The `#' flag means print numbers in an alternate, more verbose format:
2252   octal numbers begin with zero; hex numbers begin with a 0x or 0X;
2253   a decimal point is printed in %f, %e, and %E conversions even if no
2254   numbers are printed after it; and trailing zeroes are not omitted in
2255    %g and %G conversions.
2256
2257 Use %% to put a single % into the output.
2258 */
2259        (int nargs, Lisp_Object *args))
2260 {
2261   /* It should not be necessary to GCPRO ARGS, because
2262      the caller in the interpreter should take care of that.  */
2263
2264   CHECK_STRING (args[0]);
2265   return emacs_doprnt_string_lisp (0, args[0], 0, nargs - 1, args + 1);
2266 }
2267
2268 \f
2269 DEFUN ("char-equal", Fchar_equal, 2, 3, 0, /*
2270 Return t if two characters match, optionally ignoring case.
2271 Both arguments must be characters (i.e. NOT integers).
2272 Case is ignored if `case-fold-search' is non-nil in BUFFER.
2273 If BUFFER is nil, the current buffer is assumed.
2274 */
2275        (character1, character2, buffer))
2276 {
2277   Emchar x1, x2;
2278   struct buffer *b = decode_buffer (buffer, 1);
2279
2280   CHECK_CHAR_COERCE_INT (character1);
2281   CHECK_CHAR_COERCE_INT (character2);
2282   x1 = XCHAR (character1);
2283   x2 = XCHAR (character2);
2284
2285   return (!NILP (b->case_fold_search)
2286           ? DOWNCASE (b, x1) == DOWNCASE (b, x2)
2287           : x1 == x2)
2288     ? Qt : Qnil;
2289 }
2290
2291 DEFUN ("char=", Fchar_Equal, 2, 2, 0, /*
2292 Return t if two characters match, case is significant.
2293 Both arguments must be characters (i.e. NOT integers).
2294 */
2295        (character1, character2))
2296 {
2297   CHECK_CHAR_COERCE_INT (character1);
2298   CHECK_CHAR_COERCE_INT (character2);
2299
2300   return EQ (character1, character2) ? Qt : Qnil;
2301 }
2302 \f
2303 #if 0 /* Undebugged FSFmacs code */
2304 /* Transpose the markers in two regions of the current buffer, and
2305    adjust the ones between them if necessary (i.e.: if the regions
2306    differ in size).
2307
2308    Traverses the entire marker list of the buffer to do so, adding an
2309    appropriate amount to some, subtracting from some, and leaving the
2310    rest untouched.  Most of this is copied from adjust_markers in insdel.c.
2311
2312    It's the caller's job to see that (start1 <= end1 <= start2 <= end2).  */
2313
2314 void
2315 transpose_markers (Bufpos start1, Bufpos end1, Bufpos start2, Bufpos end2)
2316 {
2317   Charcount amt1, amt2, diff;
2318   Lisp_Object marker;
2319   struct buffer *buf = current_buffer;
2320
2321   /* Update point as if it were a marker.  */
2322   if (BUF_PT (buf) < start1)
2323     ;
2324   else if (BUF_PT (buf) < end1)
2325     BUF_SET_PT (buf, BUF_PT (buf) + (end2 - end1));
2326   else if (BUF_PT (buf) < start2)
2327     BUF_SET_PT (buf, BUF_PT (buf) + (end2 - start2) - (end1 - start1));
2328   else if (BUF_PT (buf) < end2)
2329     BUF_SET_PT (buf, BUF_PT (buf) - (start2 - start1));
2330
2331   /* We used to adjust the endpoints here to account for the gap, but that
2332      isn't good enough.  Even if we assume the caller has tried to move the
2333      gap out of our way, it might still be at start1 exactly, for example;
2334      and that places it `inside' the interval, for our purposes.  The amount
2335      of adjustment is nontrivial if there's a `denormalized' marker whose
2336      position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
2337      the dirty work to Fmarker_position, below.  */
2338
2339   /* The difference between the region's lengths */
2340   diff = (end2 - start2) - (end1 - start1);
2341
2342   /* For shifting each marker in a region by the length of the other
2343    * region plus the distance between the regions.
2344    */
2345   amt1 = (end2 - start2) + (start2 - end1);
2346   amt2 = (end1 - start1) + (start2 - end1);
2347
2348   for (marker = BUF_MARKERS (buf); !NILP (marker);
2349        marker = XMARKER (marker)->chain)
2350     {
2351       Bufpos mpos = marker_position (marker);
2352       if (mpos >= start1 && mpos < end2)
2353         {
2354           if (mpos < end1)
2355             mpos += amt1;
2356           else if (mpos < start2)
2357             mpos += diff;
2358           else
2359             mpos -= amt2;
2360           set_marker_position (marker, mpos);
2361         }
2362     }
2363 }
2364
2365 #endif /* 0 */
2366
2367 DEFUN ("transpose-regions", Ftranspose_regions, 4, 5, 0, /*
2368 Transpose region START1 to END1 with START2 to END2.
2369 The regions may not be overlapping, because the size of the buffer is
2370 never changed in a transposition.
2371
2372 Optional fifth arg LEAVE-MARKERS, if non-nil, means don't transpose
2373 any markers that happen to be located in the regions. (#### BUG: currently
2374 this function always acts as if LEAVE-MARKERS is non-nil.)
2375
2376 Transposing beyond buffer boundaries is an error.
2377 */
2378   (start1, end1, start2, end2, leave_markers))
2379 {
2380   Bufpos startr1, endr1, startr2, endr2;
2381   Charcount len1, len2;
2382   Lisp_Object string1, string2;
2383   struct buffer *buf = current_buffer;
2384
2385   get_buffer_range_char (buf, start1, end1, &startr1, &endr1, 0);
2386   get_buffer_range_char (buf, start2, end2, &startr2, &endr2, 0);
2387
2388   len1 = endr1 - startr1;
2389   len2 = endr2 - startr2;
2390
2391   if (startr2 < endr1)
2392     error ("transposed regions not properly ordered");
2393   else if (startr1 == endr1 || startr2 == endr2)
2394     error ("transposed region may not be of length 0");
2395
2396   string1 = make_string_from_buffer (buf, startr1, len1);
2397   string2 = make_string_from_buffer (buf, startr2, len2);
2398   buffer_delete_range (buf, startr2, endr2, 0);
2399   buffer_insert_lisp_string_1 (buf, startr2, string1, 0);
2400   buffer_delete_range (buf, startr1, endr1, 0);
2401   buffer_insert_lisp_string_1 (buf, startr1, string2, 0);
2402
2403   /* In FSFmacs there is a whole bunch of really ugly code here
2404      to attempt to transpose the regions without using up any
2405      extra memory.  Although the intent may be good, the result
2406      was highly bogus. */
2407
2408   return Qnil;
2409 }
2410
2411 \f
2412 /************************************************************************/
2413 /*                            initialization                            */
2414 /************************************************************************/
2415
2416 void
2417 syms_of_editfns (void)
2418 {
2419   defsymbol (&Qpoint, "point");
2420   defsymbol (&Qmark, "mark");
2421   defsymbol (&Qregion_beginning, "region-beginning");
2422   defsymbol (&Qregion_end, "region-end");
2423   defsymbol (&Qformat, "format");
2424   defsymbol (&Quser_files_and_directories, "user-files-and-directories");
2425
2426   DEFSUBR (Fchar_equal);
2427   DEFSUBR (Fchar_Equal);
2428   DEFSUBR (Fgoto_char);
2429   DEFSUBR (Fstring_to_char);
2430   DEFSUBR (Fchar_to_string);
2431   DEFSUBR (Fbuffer_substring);
2432   DEFSUBR (Fbuffer_substring_no_properties);
2433
2434   DEFSUBR (Fpoint_marker);
2435   DEFSUBR (Fmark_marker);
2436   DEFSUBR (Fpoint);
2437   DEFSUBR (Fregion_beginning);
2438   DEFSUBR (Fregion_end);
2439   DEFSUBR (Fsave_excursion);
2440   DEFSUBR (Fsave_current_buffer);
2441
2442   DEFSUBR (Fbuffer_size);
2443   DEFSUBR (Fpoint_max);
2444   DEFSUBR (Fpoint_min);
2445   DEFSUBR (Fpoint_min_marker);
2446   DEFSUBR (Fpoint_max_marker);
2447
2448   DEFSUBR (Fbobp);
2449   DEFSUBR (Feobp);
2450   DEFSUBR (Fbolp);
2451   DEFSUBR (Feolp);
2452   DEFSUBR (Ffollowing_char);
2453   DEFSUBR (Fpreceding_char);
2454   DEFSUBR (Fchar_after);
2455   DEFSUBR (Fchar_before);
2456   DEFSUBR (Finsert);
2457   DEFSUBR (Finsert_string);
2458   DEFSUBR (Finsert_before_markers);
2459   DEFSUBR (Finsert_char);
2460
2461   DEFSUBR (Ftemp_directory);
2462   DEFSUBR (Fuser_login_name);
2463   DEFSUBR (Fuser_real_login_name);
2464   DEFSUBR (Fuser_uid);
2465   DEFSUBR (Fuser_real_uid);
2466   DEFSUBR (Fuser_full_name);
2467   DEFSUBR (Fuser_home_directory);
2468   DEFSUBR (Femacs_pid);
2469   DEFSUBR (Fcurrent_time);
2470   DEFSUBR (Fcurrent_process_time);
2471   DEFSUBR (Fformat_time_string);
2472   DEFSUBR (Fdecode_time);
2473   DEFSUBR (Fencode_time);
2474   DEFSUBR (Fcurrent_time_string);
2475   DEFSUBR (Fcurrent_time_zone);
2476   DEFSUBR (Fset_time_zone_rule);
2477   DEFSUBR (Fsystem_name);
2478   DEFSUBR (Fformat);
2479
2480   DEFSUBR (Finsert_buffer_substring);
2481   DEFSUBR (Fcompare_buffer_substrings);
2482   DEFSUBR (Fsubst_char_in_region);
2483   DEFSUBR (Ftranslate_region);
2484   DEFSUBR (Fdelete_region);
2485   DEFSUBR (Fwiden);
2486   DEFSUBR (Fnarrow_to_region);
2487   DEFSUBR (Fsave_restriction);
2488   DEFSUBR (Ftranspose_regions);
2489
2490   defsymbol (&Qzmacs_update_region, "zmacs-update-region");
2491   defsymbol (&Qzmacs_deactivate_region, "zmacs-deactivate-region");
2492   defsymbol (&Qzmacs_region_buffer, "zmacs-region-buffer");
2493 }
2494
2495 void
2496 vars_of_editfns (void)
2497 {
2498   staticpro (&Vsystem_name);
2499 #if 0
2500   staticpro (&Vuser_name);
2501   staticpro (&Vuser_real_name);
2502 #endif
2503   DEFVAR_BOOL ("zmacs-regions", &zmacs_regions /*
2504 *Whether LISPM-style active regions should be used.
2505 This means that commands which operate on the region (the area between the
2506 point and the mark) will only work while the region is in the ``active''
2507 state, which is indicated by highlighting.  Executing most commands causes
2508 the region to not be in the active state, so (for example) \\[kill-region] will only
2509 work immediately after activating the region.
2510
2511 More specifically:
2512
2513  - Commands which operate on the region only work if the region is active.
2514  - Only a very small set of commands cause the region to become active:
2515    Those commands whose semantics are to mark an area, like `mark-defun'.
2516  - The region is deactivated after each command that is executed, except that:
2517  - "Motion" commands do not change whether the region is active or not.
2518
2519 set-mark-command (C-SPC) pushes a mark and activates the region.  Moving the
2520 cursor with normal motion commands (C-n, C-p, etc) will cause the region
2521 between point and the recently-pushed mark to be highlighted.  It will
2522 remain highlighted until some non-motion command is executed.
2523
2524 exchange-point-and-mark (\\[exchange-point-and-mark]) activates the region.  So if you mark a
2525 region and execute a command that operates on it, you can reactivate the
2526 same region with \\[exchange-point-and-mark] (or perhaps \\[exchange-point-and-mark] \\[exchange-point-and-mark]) to operate on it
2527 again.
2528
2529 Generally, commands which push marks as a means of navigation (like
2530 beginning-of-buffer and end-of-buffer (M-< and M->)) do not activate the
2531 region.  But commands which push marks as a means of marking an area of
2532 text (like mark-defun (\\[mark-defun]), mark-word (\\[mark-word]) or mark-whole-buffer (\\[mark-whole-buffer]))
2533 do activate the region.
2534
2535 The way the command loop actually works with regard to deactivating the
2536 region is as follows:
2537
2538 - If the variable `zmacs-region-stays' has been set to t during the command
2539   just executed, the region is left alone (this is how the motion commands
2540   make the region stay around; see the `_' flag in the `interactive'
2541   specification).  `zmacs-region-stays' is reset to nil before each command
2542   is executed.
2543 - If the function `zmacs-activate-region' has been called during the command
2544   just executed, the region is left alone.  Very few functions should
2545   actually call this function.
2546 - Otherwise, if the region is active, the region is deactivated and
2547   the `zmacs-deactivate-region-hook' is called.
2548 */ );
2549   /* Zmacs style active regions are now ON by default */
2550   zmacs_regions = 1;
2551
2552   DEFVAR_BOOL ("zmacs-region-active-p", &zmacs_region_active_p /*
2553 Do not alter this.  It is for internal use only.
2554 */ );
2555   zmacs_region_active_p = 0;
2556
2557   DEFVAR_BOOL ("zmacs-region-stays", &zmacs_region_stays /*
2558 Whether the current command will deactivate the region.
2559 Commands which do not wish to affect whether the region is currently
2560 highlighted should set this to t.  Normally, the region is turned off after
2561 executing each command that did not explicitly turn it on with the function
2562 zmacs-activate-region. Setting this to true lets a command be non-intrusive.
2563 See the variable `zmacs-regions'.
2564
2565 The same effect can be achieved using the `_' interactive specification.
2566
2567 `zmacs-region-stays' is reset to nil before each command is executed.
2568 */ );
2569   zmacs_region_stays = 0;
2570
2571   DEFVAR_BOOL ("atomic-extent-goto-char-p", &atomic_extent_goto_char_p /*
2572 Do not use this -- it will be going away soon.
2573 Indicates if `goto-char' has just been run.  This information is allegedly
2574 needed to get the desired behavior for atomic extents and unfortunately
2575 is not available by any other means.
2576 */ );
2577   atomic_extent_goto_char_p = 0;
2578 #ifdef AMPERSAND_FULL_NAME
2579   Fprovide(intern("ampersand-full-name"));
2580 #endif
2581
2582   DEFVAR_LISP ("user-full-name", &Vuser_full_name /*
2583 *The name of the user.
2584 The function `user-full-name', which will return the value of this
2585  variable, when called without arguments.
2586 This is initialized to the value of the NAME environment variable.
2587 */ );
2588   /* Initialized at run-time. */
2589   Vuser_full_name = Qnil;
2590 }