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