(rmail-edit-current-message, rmail-cease-edit):
[bpt/emacs.git] / src / fns.c
CommitLineData
7b863bd5 1/* Random utility Lisp functions.
31c8f881 2 Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
7b863bd5
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
4ff1aed9 8the Free Software Foundation; either version 2, or (at your option)
7b863bd5
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
7b863bd5
JB
20
21
18160b98 22#include <config.h>
7b863bd5 23
dfcf069d
AS
24#ifdef HAVE_UNISTD_H
25#include <unistd.h>
26#endif
58edb572 27#include <time.h>
dfcf069d 28
7b863bd5
JB
29/* Note on some machines this defines `vector' as a typedef,
30 so make sure we don't use that name in this file. */
31#undef vector
32#define vector *****
33
7b863bd5
JB
34#include "lisp.h"
35#include "commands.h"
a8283a4a 36#include "charset.h"
7b863bd5 37
7b863bd5 38#include "buffer.h"
f812877e 39#include "keyboard.h"
ac811a55 40#include "intervals.h"
2d8e7e1f
RS
41#include "frame.h"
42#include "window.h"
d73c6532 43#if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS)
dfcf069d
AS
44#include "xterm.h"
45#endif
7b863bd5 46
bc937db7
KH
47#ifndef NULL
48#define NULL (void *)0
49#endif
50
bdd8d692
RS
51/* Nonzero enables use of dialog boxes for questions
52 asked by mouse commands. */
53int use_dialog_box;
54
2d8e7e1f
RS
55extern int minibuffer_auto_raise;
56extern Lisp_Object minibuf_window;
57
68732608 58Lisp_Object Qstring_lessp, Qprovide, Qrequire;
0ce830bc 59Lisp_Object Qyes_or_no_p_history;
eb4ffa4e 60Lisp_Object Qcursor_in_echo_area;
b4f334f7 61Lisp_Object Qwidget_type;
7b863bd5 62
6cb9cafb 63static int internal_equal ();
49bdcd3e
RS
64
65extern long get_random ();
66extern void seed_random ();
67
68#ifndef HAVE_UNISTD_H
69extern long time ();
70#endif
e0f5cf5a 71\f
7b863bd5
JB
72DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
73 "Return the argument unchanged.")
74 (arg)
75 Lisp_Object arg;
76{
77 return arg;
78}
79
80DEFUN ("random", Frandom, Srandom, 0, 1, 0,
81 "Return a pseudo-random number.\n\
4cab5074
KH
82All integers representable in Lisp are equally likely.\n\
83 On most systems, this is 28 bits' worth.\n\
99175c23 84With positive integer argument N, return random number in interval [0,N).\n\
7b863bd5 85With argument t, set the random number seed from the current time and pid.")
88fe8140
EN
86 (n)
87 Lisp_Object n;
7b863bd5 88{
e2d6972a
KH
89 EMACS_INT val;
90 Lisp_Object lispy_val;
78217ef1 91 unsigned long denominator;
7b863bd5 92
88fe8140 93 if (EQ (n, Qt))
e2d6972a 94 seed_random (getpid () + time (NULL));
88fe8140 95 if (NATNUMP (n) && XFASTINT (n) != 0)
7b863bd5 96 {
4cab5074
KH
97 /* Try to take our random number from the higher bits of VAL,
98 not the lower, since (says Gentzel) the low bits of `random'
99 are less random than the higher ones. We do this by using the
100 quotient rather than the remainder. At the high end of the RNG
88fe8140 101 it's possible to get a quotient larger than n; discarding
4cab5074 102 these values eliminates the bias that would otherwise appear
88fe8140
EN
103 when using a large n. */
104 denominator = ((unsigned long)1 << VALBITS) / XFASTINT (n);
4cab5074 105 do
99175c23 106 val = get_random () / denominator;
88fe8140 107 while (val >= XFASTINT (n));
7b863bd5 108 }
78217ef1 109 else
99175c23 110 val = get_random ();
e2d6972a
KH
111 XSETINT (lispy_val, val);
112 return lispy_val;
7b863bd5
JB
113}
114\f
115/* Random data-structure functions */
116
117DEFUN ("length", Flength, Slength, 1, 1, 0,
118 "Return the length of vector, list or string SEQUENCE.\n\
0c57d6fd
RS
119A byte-code function object is also allowed.\n\
120If the string contains multibyte characters, this is not the necessarily\n\
96ced23c
AS
121the number of bytes in the string; it is the number of characters.\n\
122To get the number of bytes, use `string-bytes'")
88fe8140
EN
123 (sequence)
124 register Lisp_Object sequence;
7b863bd5
JB
125{
126 register Lisp_Object tail, val;
127 register int i;
128
129 retry:
88fe8140
EN
130 if (STRINGP (sequence))
131 XSETFASTINT (val, XSTRING (sequence)->size);
132 else if (VECTORP (sequence))
133 XSETFASTINT (val, XVECTOR (sequence)->size);
134 else if (CHAR_TABLE_P (sequence))
33aa0881
KH
135 XSETFASTINT (val, (MIN_CHAR_COMPOSITION
136 + (CHAR_FIELD2_MASK | CHAR_FIELD3_MASK)
137 - 1));
88fe8140
EN
138 else if (BOOL_VECTOR_P (sequence))
139 XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
140 else if (COMPILEDP (sequence))
141 XSETFASTINT (val, XVECTOR (sequence)->size & PSEUDOVECTOR_SIZE_MASK);
142 else if (CONSP (sequence))
7b863bd5 143 {
88fe8140 144 for (i = 0, tail = sequence; !NILP (tail); i++)
7b863bd5
JB
145 {
146 QUIT;
147 tail = Fcdr (tail);
148 }
149
ad17573a 150 XSETFASTINT (val, i);
7b863bd5 151 }
88fe8140 152 else if (NILP (sequence))
a2ad3e19 153 XSETFASTINT (val, 0);
7b863bd5
JB
154 else
155 {
88fe8140 156 sequence = wrong_type_argument (Qsequencep, sequence);
7b863bd5
JB
157 goto retry;
158 }
a2ad3e19 159 return val;
7b863bd5
JB
160}
161
5a30fab8
RS
162/* This does not check for quits. That is safe
163 since it must terminate. */
164
165DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
166 "Return the length of a list, but avoid error or infinite loop.\n\
167This function never gets an error. If LIST is not really a list,\n\
168it returns 0. If LIST is circular, it returns a finite value\n\
169which is at least the number of distinct elements.")
b4f334f7 170 (list)
5a30fab8
RS
171 Lisp_Object list;
172{
173 Lisp_Object tail, halftail, length;
174 int len = 0;
175
176 /* halftail is used to detect circular lists. */
177 halftail = list;
178 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
179 {
180 if (EQ (tail, halftail) && len != 0)
cb3d1a0a 181 break;
5a30fab8 182 len++;
3a61aeb4 183 if ((len & 1) == 0)
5a30fab8
RS
184 halftail = XCONS (halftail)->cdr;
185 }
186
187 XSETINT (length, len);
188 return length;
189}
190
026f59ce
RS
191DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
192 "Return the number of bytes in STRING.\n\
193If STRING is a multibyte string, this is greater than the length of STRING.")
194 (string)
eaf17c6b 195 Lisp_Object string;
026f59ce
RS
196{
197 CHECK_STRING (string, 1);
fc932ac6 198 return make_number (STRING_BYTES (XSTRING (string)));
026f59ce
RS
199}
200
7b863bd5 201DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
ea35ce3d 202 "Return t if two strings have identical contents.\n\
76d0f732 203Case is significant, but text properties are ignored.\n\
7b863bd5
JB
204Symbols are also allowed; their print names are used instead.")
205 (s1, s2)
206 register Lisp_Object s1, s2;
207{
7650760e 208 if (SYMBOLP (s1))
b2791413 209 XSETSTRING (s1, XSYMBOL (s1)->name);
7650760e 210 if (SYMBOLP (s2))
b2791413 211 XSETSTRING (s2, XSYMBOL (s2)->name);
7b863bd5
JB
212 CHECK_STRING (s1, 0);
213 CHECK_STRING (s2, 1);
214
ea35ce3d 215 if (XSTRING (s1)->size != XSTRING (s2)->size
fc932ac6
RS
216 || STRING_BYTES (XSTRING (s1)) != STRING_BYTES (XSTRING (s2))
217 || bcmp (XSTRING (s1)->data, XSTRING (s2)->data, STRING_BYTES (XSTRING (s1))))
7b863bd5
JB
218 return Qnil;
219 return Qt;
220}
221
0e1e9f8d 222DEFUN ("compare-strings", Fcompare_strings,
f95837d0 223 Scompare_strings, 6, 7, 0,
0e1e9f8d
RS
224 "Compare the contents of two strings, converting to multibyte if needed.\n\
225In string STR1, skip the first START1 characters and stop at END1.\n\
226In string STR2, skip the first START2 characters and stop at END2.\n\
d68cc14c
RS
227END1 and END2 default to the full lengths of the respective strings.\n\
228\n\
0e1e9f8d
RS
229Case is significant in this comparison if IGNORE-CASE is nil.\n\
230Unibyte strings are converted to multibyte for comparison.\n\
231\n\
232The value is t if the strings (or specified portions) match.\n\
233If string STR1 is less, the value is a negative number N;\n\
234 - 1 - N is the number of characters that match at the beginning.\n\
235If string STR1 is greater, the value is a positive number N;\n\
236 N - 1 is the number of characters that match at the beginning.")
237 (str1, start1, end1, str2, start2, end2, ignore_case)
238 Lisp_Object str1, start1, end1, start2, str2, end2, ignore_case;
239{
240 register int end1_char, end2_char;
241 register int i1, i1_byte, i2, i2_byte;
242
243 CHECK_STRING (str1, 0);
244 CHECK_STRING (str2, 1);
245 if (NILP (start1))
246 start1 = make_number (0);
247 if (NILP (start2))
248 start2 = make_number (0);
249 CHECK_NATNUM (start1, 2);
250 CHECK_NATNUM (start2, 3);
251 if (! NILP (end1))
252 CHECK_NATNUM (end1, 4);
253 if (! NILP (end2))
254 CHECK_NATNUM (end2, 4);
255
256 i1 = XINT (start1);
257 i2 = XINT (start2);
258
259 i1_byte = string_char_to_byte (str1, i1);
260 i2_byte = string_char_to_byte (str2, i2);
261
262 end1_char = XSTRING (str1)->size;
263 if (! NILP (end1) && end1_char > XINT (end1))
264 end1_char = XINT (end1);
265
266 end2_char = XSTRING (str2)->size;
267 if (! NILP (end2) && end2_char > XINT (end2))
268 end2_char = XINT (end2);
269
270 while (i1 < end1_char && i2 < end2_char)
271 {
272 /* When we find a mismatch, we must compare the
273 characters, not just the bytes. */
274 int c1, c2;
275
276 if (STRING_MULTIBYTE (str1))
277 FETCH_STRING_CHAR_ADVANCE (c1, str1, i1, i1_byte);
278 else
279 {
280 c1 = XSTRING (str1)->data[i1++];
281 c1 = unibyte_char_to_multibyte (c1);
282 }
283
284 if (STRING_MULTIBYTE (str2))
285 FETCH_STRING_CHAR_ADVANCE (c2, str2, i2, i2_byte);
286 else
287 {
288 c2 = XSTRING (str2)->data[i2++];
289 c2 = unibyte_char_to_multibyte (c2);
290 }
291
292 if (c1 == c2)
293 continue;
294
295 if (! NILP (ignore_case))
296 {
297 Lisp_Object tem;
298
299 tem = Fupcase (make_number (c1));
300 c1 = XINT (tem);
301 tem = Fupcase (make_number (c2));
302 c2 = XINT (tem);
303 }
304
305 if (c1 == c2)
306 continue;
307
308 /* Note that I1 has already been incremented
309 past the character that we are comparing;
310 hence we don't add or subtract 1 here. */
311 if (c1 < c2)
312 return make_number (- i1);
313 else
314 return make_number (i1);
315 }
316
317 if (i1 < end1_char)
318 return make_number (i1 - XINT (start1) + 1);
319 if (i2 < end2_char)
320 return make_number (- i1 + XINT (start1) - 1);
321
322 return Qt;
323}
324
7b863bd5 325DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
ea35ce3d 326 "Return t if first arg string is less than second in lexicographic order.\n\
7b863bd5
JB
327Case is significant.\n\
328Symbols are also allowed; their print names are used instead.")
329 (s1, s2)
330 register Lisp_Object s1, s2;
331{
7b863bd5 332 register int end;
09ab3c3b 333 register int i1, i1_byte, i2, i2_byte;
7b863bd5 334
7650760e 335 if (SYMBOLP (s1))
b2791413 336 XSETSTRING (s1, XSYMBOL (s1)->name);
7650760e 337 if (SYMBOLP (s2))
b2791413 338 XSETSTRING (s2, XSYMBOL (s2)->name);
7b863bd5
JB
339 CHECK_STRING (s1, 0);
340 CHECK_STRING (s2, 1);
341
09ab3c3b
KH
342 i1 = i1_byte = i2 = i2_byte = 0;
343
344 end = XSTRING (s1)->size;
345 if (end > XSTRING (s2)->size)
346 end = XSTRING (s2)->size;
7b863bd5 347
09ab3c3b 348 while (i1 < end)
7b863bd5 349 {
09ab3c3b
KH
350 /* When we find a mismatch, we must compare the
351 characters, not just the bytes. */
352 int c1, c2;
353
354 if (STRING_MULTIBYTE (s1))
355 FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte);
356 else
357 c1 = XSTRING (s1)->data[i1++];
358
359 if (STRING_MULTIBYTE (s2))
360 FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte);
361 else
362 c2 = XSTRING (s2)->data[i2++];
363
364 if (c1 != c2)
365 return c1 < c2 ? Qt : Qnil;
7b863bd5 366 }
09ab3c3b 367 return i1 < XSTRING (s2)->size ? Qt : Qnil;
7b863bd5
JB
368}
369\f
370static Lisp_Object concat ();
371
372/* ARGSUSED */
373Lisp_Object
374concat2 (s1, s2)
375 Lisp_Object s1, s2;
376{
377#ifdef NO_ARG_ARRAY
378 Lisp_Object args[2];
379 args[0] = s1;
380 args[1] = s2;
381 return concat (2, args, Lisp_String, 0);
382#else
383 return concat (2, &s1, Lisp_String, 0);
384#endif /* NO_ARG_ARRAY */
385}
386
d4af3687
RS
387/* ARGSUSED */
388Lisp_Object
389concat3 (s1, s2, s3)
390 Lisp_Object s1, s2, s3;
391{
392#ifdef NO_ARG_ARRAY
393 Lisp_Object args[3];
394 args[0] = s1;
395 args[1] = s2;
396 args[2] = s3;
397 return concat (3, args, Lisp_String, 0);
398#else
399 return concat (3, &s1, Lisp_String, 0);
400#endif /* NO_ARG_ARRAY */
401}
402
7b863bd5
JB
403DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
404 "Concatenate all the arguments and make the result a list.\n\
405The result is a list whose elements are the elements of all the arguments.\n\
406Each argument may be a list, vector or string.\n\
aec1184c 407The last argument is not copied, just used as the tail of the new list.")
7b863bd5
JB
408 (nargs, args)
409 int nargs;
410 Lisp_Object *args;
411{
412 return concat (nargs, args, Lisp_Cons, 1);
413}
414
415DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
416 "Concatenate all the arguments and make the result a string.\n\
417The result is a string whose elements are the elements of all the arguments.\n\
37d40ae9
RS
418Each argument may be a string or a list or vector of characters (integers).\n\
419\n\
420Do not use individual integers as arguments!\n\
421The behavior of `concat' in that case will be changed later!\n\
422If your program passes an integer as an argument to `concat',\n\
423you should change it right away not to do so.")
7b863bd5
JB
424 (nargs, args)
425 int nargs;
426 Lisp_Object *args;
427{
428 return concat (nargs, args, Lisp_String, 0);
429}
430
431DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
432 "Concatenate all the arguments and make the result a vector.\n\
433The result is a vector whose elements are the elements of all the arguments.\n\
434Each argument may be a list, vector or string.")
435 (nargs, args)
436 int nargs;
437 Lisp_Object *args;
438{
3e7383eb 439 return concat (nargs, args, Lisp_Vectorlike, 0);
7b863bd5
JB
440}
441
3720677d
KH
442/* Retrun a copy of a sub char table ARG. The elements except for a
443 nested sub char table are not copied. */
444static Lisp_Object
445copy_sub_char_table (arg)
e1335ba2 446 Lisp_Object arg;
3720677d
KH
447{
448 Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
449 int i;
450
451 /* Copy all the contents. */
452 bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
453 SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
454 /* Recursively copy any sub char-tables in the ordinary slots. */
455 for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++)
456 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
457 XCHAR_TABLE (copy)->contents[i]
458 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
459
460 return copy;
461}
462
463
7b863bd5
JB
464DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
465 "Return a copy of a list, vector or string.\n\
466The elements of a list or vector are not copied; they are shared\n\
467with the original.")
468 (arg)
469 Lisp_Object arg;
470{
265a9e55 471 if (NILP (arg)) return arg;
e03f7933
RS
472
473 if (CHAR_TABLE_P (arg))
474 {
25c30748 475 int i;
e03f7933
RS
476 Lisp_Object copy;
477
c8640abf 478 copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
e03f7933 479 /* Copy all the slots, including the extra ones. */
69b3a14b 480 bcopy (XVECTOR (arg)->contents, XVECTOR (copy)->contents,
25c30748
KH
481 ((XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK)
482 * sizeof (Lisp_Object)));
e03f7933 483
3720677d
KH
484 /* Recursively copy any sub char tables in the ordinary slots
485 for multibyte characters. */
486 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS;
487 i < CHAR_TABLE_ORDINARY_SLOTS; i++)
488 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
e03f7933 489 XCHAR_TABLE (copy)->contents[i]
3720677d 490 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
e03f7933
RS
491
492 return copy;
493 }
494
495 if (BOOL_VECTOR_P (arg))
496 {
497 Lisp_Object val;
e03f7933 498 int size_in_chars
e22e4283 499 = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
500
501 val = Fmake_bool_vector (Flength (arg), Qnil);
502 bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
503 size_in_chars);
504 return val;
505 }
506
7650760e 507 if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
7b863bd5
JB
508 arg = wrong_type_argument (Qsequencep, arg);
509 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
510}
511
512static Lisp_Object
513concat (nargs, args, target_type, last_special)
514 int nargs;
515 Lisp_Object *args;
516 enum Lisp_Type target_type;
517 int last_special;
518{
519 Lisp_Object val;
7b863bd5
JB
520 register Lisp_Object tail;
521 register Lisp_Object this;
522 int toindex;
ea35ce3d
RS
523 int toindex_byte;
524 register int result_len;
525 register int result_len_byte;
7b863bd5
JB
526 register int argnum;
527 Lisp_Object last_tail;
528 Lisp_Object prev;
ea35ce3d 529 int some_multibyte;
18cc260b
KH
530 /* When we make a multibyte string, we must pay attention to the
531 byte combining problem, i.e., a byte may be combined with a
532 multibyte charcter of the previous string. This flag tells if we
533 must consider such a situation or not. */
534 int maybe_combine_byte;
7b863bd5
JB
535
536 /* In append, the last arg isn't treated like the others */
537 if (last_special && nargs > 0)
538 {
539 nargs--;
540 last_tail = args[nargs];
541 }
542 else
543 last_tail = Qnil;
544
ea35ce3d 545 /* Canonicalize each argument. */
7b863bd5
JB
546 for (argnum = 0; argnum < nargs; argnum++)
547 {
548 this = args[argnum];
7650760e 549 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
e03f7933 550 || COMPILEDP (this) || BOOL_VECTOR_P (this)))
7b863bd5 551 {
7650760e 552 if (INTEGERP (this))
37d40ae9 553 args[argnum] = Fnumber_to_string (this);
7b863bd5
JB
554 else
555 args[argnum] = wrong_type_argument (Qsequencep, this);
556 }
557 }
558
ea35ce3d
RS
559 /* Compute total length in chars of arguments in RESULT_LEN.
560 If desired output is a string, also compute length in bytes
561 in RESULT_LEN_BYTE, and determine in SOME_MULTIBYTE
562 whether the result should be a multibyte string. */
563 result_len_byte = 0;
564 result_len = 0;
565 some_multibyte = 0;
566 for (argnum = 0; argnum < nargs; argnum++)
7b863bd5 567 {
ea35ce3d 568 int len;
7b863bd5 569 this = args[argnum];
ea35ce3d
RS
570 len = XFASTINT (Flength (this));
571 if (target_type == Lisp_String)
5b6dddaa 572 {
09ab3c3b
KH
573 /* We must count the number of bytes needed in the string
574 as well as the number of characters. */
5b6dddaa
KH
575 int i;
576 Lisp_Object ch;
ea35ce3d 577 int this_len_byte;
5b6dddaa 578
dec58e65 579 if (VECTORP (this))
ea35ce3d 580 for (i = 0; i < len; i++)
dec58e65
KH
581 {
582 ch = XVECTOR (this)->contents[i];
583 if (! INTEGERP (ch))
584 wrong_type_argument (Qintegerp, ch);
ea35ce3d
RS
585 this_len_byte = XFASTINT (Fchar_bytes (ch));
586 result_len_byte += this_len_byte;
587 if (this_len_byte > 1)
588 some_multibyte = 1;
dec58e65 589 }
6d475204
RS
590 else if (BOOL_VECTOR_P (this) && XBOOL_VECTOR (this)->size > 0)
591 wrong_type_argument (Qintegerp, Faref (this, make_number (0)));
ea35ce3d 592 else if (CONSP (this))
dec58e65
KH
593 for (; CONSP (this); this = XCONS (this)->cdr)
594 {
595 ch = XCONS (this)->car;
596 if (! INTEGERP (ch))
597 wrong_type_argument (Qintegerp, ch);
ea35ce3d
RS
598 this_len_byte = XFASTINT (Fchar_bytes (ch));
599 result_len_byte += this_len_byte;
600 if (this_len_byte > 1)
601 some_multibyte = 1;
dec58e65 602 }
470730a8 603 else if (STRINGP (this))
ea35ce3d 604 {
06f57aa7 605 if (STRING_MULTIBYTE (this))
09ab3c3b
KH
606 {
607 some_multibyte = 1;
fc932ac6 608 result_len_byte += STRING_BYTES (XSTRING (this));
09ab3c3b
KH
609 }
610 else
611 result_len_byte += count_size_as_multibyte (XSTRING (this)->data,
612 XSTRING (this)->size);
ea35ce3d 613 }
5b6dddaa 614 }
ea35ce3d
RS
615
616 result_len += len;
7b863bd5
JB
617 }
618
09ab3c3b
KH
619 if (! some_multibyte)
620 result_len_byte = result_len;
7b863bd5 621
ea35ce3d 622 /* Create the output object. */
7b863bd5 623 if (target_type == Lisp_Cons)
ea35ce3d 624 val = Fmake_list (make_number (result_len), Qnil);
3e7383eb 625 else if (target_type == Lisp_Vectorlike)
ea35ce3d 626 val = Fmake_vector (make_number (result_len), Qnil);
b10b2daa 627 else if (some_multibyte)
ea35ce3d 628 val = make_uninit_multibyte_string (result_len, result_len_byte);
b10b2daa
RS
629 else
630 val = make_uninit_string (result_len);
7b863bd5 631
09ab3c3b
KH
632 /* In `append', if all but last arg are nil, return last arg. */
633 if (target_type == Lisp_Cons && EQ (val, Qnil))
634 return last_tail;
7b863bd5 635
ea35ce3d 636 /* Copy the contents of the args into the result. */
7b863bd5
JB
637 if (CONSP (val))
638 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
639 else
ea35ce3d 640 toindex = 0, toindex_byte = 0;
7b863bd5
JB
641
642 prev = Qnil;
643
18cc260b 644 maybe_combine_byte = 0;
7b863bd5
JB
645 for (argnum = 0; argnum < nargs; argnum++)
646 {
647 Lisp_Object thislen;
648 int thisleni;
de712da3 649 register unsigned int thisindex = 0;
ea35ce3d 650 register unsigned int thisindex_byte = 0;
7b863bd5
JB
651
652 this = args[argnum];
653 if (!CONSP (this))
654 thislen = Flength (this), thisleni = XINT (thislen);
655
7650760e 656 if (STRINGP (this) && STRINGP (val)
ac811a55 657 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
ea35ce3d
RS
658 copy_text_properties (make_number (0), thislen, this,
659 make_number (toindex), val, Qnil);
ac811a55 660
ea35ce3d
RS
661 /* Between strings of the same kind, copy fast. */
662 if (STRINGP (this) && STRINGP (val)
663 && STRING_MULTIBYTE (this) == some_multibyte)
7b863bd5 664 {
fc932ac6 665 int thislen_byte = STRING_BYTES (XSTRING (this));
ea35ce3d 666 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
fc932ac6 667 STRING_BYTES (XSTRING (this)));
18cc260b
KH
668 if (some_multibyte
669 && toindex_byte > 0
8b542479
KH
670 && !ASCII_BYTE_P (XSTRING (val)->data[toindex_byte - 1])
671 && !CHAR_HEAD_P (XSTRING (this)->data[0] >= 0xA0))
18cc260b 672 maybe_combine_byte = 1;
ea35ce3d
RS
673 toindex_byte += thislen_byte;
674 toindex += thisleni;
675 }
09ab3c3b
KH
676 /* Copy a single-byte string to a multibyte string. */
677 else if (STRINGP (this) && STRINGP (val))
678 {
679 toindex_byte += copy_text (XSTRING (this)->data,
680 XSTRING (val)->data + toindex_byte,
681 XSTRING (this)->size, 0, 1);
682 toindex += thisleni;
683 }
ea35ce3d
RS
684 else
685 /* Copy element by element. */
686 while (1)
687 {
688 register Lisp_Object elt;
689
690 /* Fetch next element of `this' arg into `elt', or break if
691 `this' is exhausted. */
692 if (NILP (this)) break;
693 if (CONSP (this))
694 elt = XCONS (this)->car, this = XCONS (this)->cdr;
6a7df83b
RS
695 else if (thisindex >= thisleni)
696 break;
697 else if (STRINGP (this))
ea35ce3d 698 {
2cef5737 699 int c;
6a7df83b 700 if (STRING_MULTIBYTE (this))
ea35ce3d 701 {
6a7df83b
RS
702 FETCH_STRING_CHAR_ADVANCE (c, this,
703 thisindex,
704 thisindex_byte);
705 XSETFASTINT (elt, c);
ea35ce3d 706 }
6a7df83b 707 else
ea35ce3d 708 {
6a7df83b
RS
709 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
710 if (some_multibyte && XINT (elt) >= 0200
711 && XINT (elt) < 0400)
712 {
2cef5737 713 c = unibyte_char_to_multibyte (XINT (elt));
6a7df83b
RS
714 XSETINT (elt, c);
715 }
ea35ce3d 716 }
6a7df83b
RS
717 }
718 else if (BOOL_VECTOR_P (this))
719 {
720 int byte;
721 byte = XBOOL_VECTOR (this)->data[thisindex / BITS_PER_CHAR];
722 if (byte & (1 << (thisindex % BITS_PER_CHAR)))
723 elt = Qt;
ea35ce3d 724 else
6a7df83b
RS
725 elt = Qnil;
726 thisindex++;
ea35ce3d 727 }
6a7df83b
RS
728 else
729 elt = XVECTOR (this)->contents[thisindex++];
7b863bd5 730
ea35ce3d
RS
731 /* Store this element into the result. */
732 if (toindex < 0)
7b863bd5 733 {
ea35ce3d
RS
734 XCONS (tail)->car = elt;
735 prev = tail;
736 tail = XCONS (tail)->cdr;
7b863bd5 737 }
ea35ce3d
RS
738 else if (VECTORP (val))
739 XVECTOR (val)->contents[toindex++] = elt;
740 else
741 {
742 CHECK_NUMBER (elt, 0);
743 if (SINGLE_BYTE_CHAR_P (XINT (elt)))
744 {
18cc260b
KH
745 if (some_multibyte
746 && toindex_byte > 0
8b542479
KH
747 && !ASCII_BYTE_P (XSTRING (val)->data[toindex_byte - 1])
748 && !CHAR_HEAD_P (XINT (elt)))
18cc260b 749 maybe_combine_byte = 1;
44893c8f
KH
750 XSTRING (val)->data[toindex_byte++] = XINT (elt);
751 toindex++;
ea35ce3d
RS
752 }
753 else
754 /* If we have any multibyte characters,
755 we already decided to make a multibyte string. */
756 {
757 int c = XINT (elt);
758 unsigned char work[4], *str;
759 int i = CHAR_STRING (c, work, str);
760
761 /* P exists as a variable
762 to avoid a bug on the Masscomp C compiler. */
763 unsigned char *p = & XSTRING (val)->data[toindex_byte];
764 bcopy (str, p, i);
765 toindex_byte += i;
766 toindex++;
767 }
768 }
769 }
7b863bd5 770 }
265a9e55 771 if (!NILP (prev))
7b863bd5
JB
772 XCONS (prev)->cdr = last_tail;
773
18cc260b 774 if (maybe_combine_byte)
262c8cea 775 /* Character counter of the multibyte string VAL may be wrong
18cc260b
KH
776 because of byte combining problem. We must re-calculate it. */
777 XSTRING (val)->size = multibyte_chars_in_text (XSTRING (val)->data,
778 XSTRING (val)->size_byte);
779
b4f334f7 780 return val;
7b863bd5
JB
781}
782\f
09ab3c3b
KH
783static Lisp_Object string_char_byte_cache_string;
784static int string_char_byte_cache_charpos;
785static int string_char_byte_cache_bytepos;
786
ea35ce3d
RS
787/* Return the character index corresponding to CHAR_INDEX in STRING. */
788
789int
790string_char_to_byte (string, char_index)
791 Lisp_Object string;
792 int char_index;
793{
09ab3c3b
KH
794 int i, i_byte;
795 int best_below, best_below_byte;
796 int best_above, best_above_byte;
ea35ce3d
RS
797
798 if (! STRING_MULTIBYTE (string))
799 return char_index;
800
09ab3c3b
KH
801 best_below = best_below_byte = 0;
802 best_above = XSTRING (string)->size;
fc932ac6 803 best_above_byte = STRING_BYTES (XSTRING (string));
09ab3c3b
KH
804
805 if (EQ (string, string_char_byte_cache_string))
806 {
807 if (string_char_byte_cache_charpos < char_index)
808 {
809 best_below = string_char_byte_cache_charpos;
810 best_below_byte = string_char_byte_cache_bytepos;
811 }
812 else
813 {
814 best_above = string_char_byte_cache_charpos;
815 best_above_byte = string_char_byte_cache_bytepos;
816 }
817 }
818
819 if (char_index - best_below < best_above - char_index)
820 {
821 while (best_below < char_index)
822 {
823 int c;
824 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
825 }
826 i = best_below;
827 i_byte = best_below_byte;
828 }
829 else
ea35ce3d 830 {
09ab3c3b
KH
831 while (best_above > char_index)
832 {
833 int best_above_byte_saved = --best_above_byte;
834
835 while (best_above_byte > 0
836 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
837 best_above_byte--;
838 if (XSTRING (string)->data[best_above_byte] < 0x80)
839 best_above_byte = best_above_byte_saved;
840 best_above--;
841 }
842 i = best_above;
843 i_byte = best_above_byte;
ea35ce3d
RS
844 }
845
09ab3c3b
KH
846 string_char_byte_cache_bytepos = i_byte;
847 string_char_byte_cache_charpos = i;
848 string_char_byte_cache_string = string;
849
ea35ce3d
RS
850 return i_byte;
851}
09ab3c3b 852\f
ea35ce3d
RS
853/* Return the character index corresponding to BYTE_INDEX in STRING. */
854
855int
856string_byte_to_char (string, byte_index)
857 Lisp_Object string;
858 int byte_index;
859{
09ab3c3b
KH
860 int i, i_byte;
861 int best_below, best_below_byte;
862 int best_above, best_above_byte;
ea35ce3d
RS
863
864 if (! STRING_MULTIBYTE (string))
865 return byte_index;
866
09ab3c3b
KH
867 best_below = best_below_byte = 0;
868 best_above = XSTRING (string)->size;
fc932ac6 869 best_above_byte = STRING_BYTES (XSTRING (string));
09ab3c3b
KH
870
871 if (EQ (string, string_char_byte_cache_string))
872 {
873 if (string_char_byte_cache_bytepos < byte_index)
874 {
875 best_below = string_char_byte_cache_charpos;
876 best_below_byte = string_char_byte_cache_bytepos;
877 }
878 else
879 {
880 best_above = string_char_byte_cache_charpos;
881 best_above_byte = string_char_byte_cache_bytepos;
882 }
883 }
884
885 if (byte_index - best_below_byte < best_above_byte - byte_index)
886 {
887 while (best_below_byte < byte_index)
888 {
889 int c;
890 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
891 }
892 i = best_below;
893 i_byte = best_below_byte;
894 }
895 else
ea35ce3d 896 {
09ab3c3b
KH
897 while (best_above_byte > byte_index)
898 {
899 int best_above_byte_saved = --best_above_byte;
900
901 while (best_above_byte > 0
902 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
903 best_above_byte--;
904 if (XSTRING (string)->data[best_above_byte] < 0x80)
905 best_above_byte = best_above_byte_saved;
906 best_above--;
907 }
908 i = best_above;
909 i_byte = best_above_byte;
ea35ce3d
RS
910 }
911
09ab3c3b
KH
912 string_char_byte_cache_bytepos = i_byte;
913 string_char_byte_cache_charpos = i;
914 string_char_byte_cache_string = string;
915
ea35ce3d
RS
916 return i;
917}
09ab3c3b 918\f
ea35ce3d 919/* Convert STRING to a multibyte string.
2cef5737 920 Single-byte characters 0240 through 0377 are converted
ea35ce3d
RS
921 by adding nonascii_insert_offset to each. */
922
923Lisp_Object
924string_make_multibyte (string)
925 Lisp_Object string;
926{
927 unsigned char *buf;
928 int nbytes;
929
930 if (STRING_MULTIBYTE (string))
931 return string;
932
933 nbytes = count_size_as_multibyte (XSTRING (string)->data,
934 XSTRING (string)->size);
6d475204
RS
935 /* If all the chars are ASCII, they won't need any more bytes
936 once converted. In that case, we can return STRING itself. */
fc932ac6 937 if (nbytes == STRING_BYTES (XSTRING (string)))
6d475204
RS
938 return string;
939
ea35ce3d 940 buf = (unsigned char *) alloca (nbytes);
fc932ac6 941 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
ea35ce3d
RS
942 0, 1);
943
944 return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
945}
946
947/* Convert STRING to a single-byte string. */
948
949Lisp_Object
950string_make_unibyte (string)
951 Lisp_Object string;
952{
953 unsigned char *buf;
954
955 if (! STRING_MULTIBYTE (string))
956 return string;
957
958 buf = (unsigned char *) alloca (XSTRING (string)->size);
959
fc932ac6 960 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
ea35ce3d
RS
961 1, 0);
962
963 return make_unibyte_string (buf, XSTRING (string)->size);
964}
09ab3c3b
KH
965
966DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
967 1, 1, 0,
a6ee6aa4
RS
968 "Return the multibyte equivalent of STRING.\n\
969The function `unibyte-char-to-multibyte' is used to convert\n\
970each unibyte character to a multibyte character.")
09ab3c3b
KH
971 (string)
972 Lisp_Object string;
973{
aabd38ec
KH
974 CHECK_STRING (string, 0);
975
09ab3c3b
KH
976 return string_make_multibyte (string);
977}
978
979DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
980 1, 1, 0,
a6ee6aa4
RS
981 "Return the unibyte equivalent of STRING.\n\
982Multibyte character codes are converted to unibyte\n\
983by using just the low 8 bits.")
09ab3c3b
KH
984 (string)
985 Lisp_Object string;
986{
aabd38ec
KH
987 CHECK_STRING (string, 0);
988
09ab3c3b
KH
989 return string_make_unibyte (string);
990}
6d475204
RS
991
992DEFUN ("string-as-unibyte", Fstring_as_unibyte, Sstring_as_unibyte,
993 1, 1, 0,
994 "Return a unibyte string with the same individual bytes as STRING.\n\
995If STRING is unibyte, the result is STRING itself.")
996 (string)
997 Lisp_Object string;
998{
aabd38ec
KH
999 CHECK_STRING (string, 0);
1000
6d475204
RS
1001 if (STRING_MULTIBYTE (string))
1002 {
1003 string = Fcopy_sequence (string);
fc932ac6 1004 XSTRING (string)->size = STRING_BYTES (XSTRING (string));
fa251740 1005 SET_STRING_BYTES (XSTRING (string), -1);
6d475204
RS
1006 }
1007 return string;
1008}
1009
1010DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
1011 1, 1, 0,
1012 "Return a multibyte string with the same individual bytes as STRING.\n\
1013If STRING is multibyte, the result is STRING itself.")
1014 (string)
1015 Lisp_Object string;
1016{
aabd38ec
KH
1017 CHECK_STRING (string, 0);
1018
6d475204
RS
1019 if (! STRING_MULTIBYTE (string))
1020 {
9658795c
RS
1021 int nbytes = STRING_BYTES (XSTRING (string));
1022 int newlen = multibyte_chars_in_text (XSTRING (string)->data, nbytes);
1023
1024 string = Fcopy_sequence (string);
1025 XSTRING (string)->size = newlen;
1026 XSTRING (string)->size_byte = nbytes;
6d475204
RS
1027 }
1028 return string;
1029}
ea35ce3d 1030\f
7b863bd5
JB
1031DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
1032 "Return a copy of ALIST.\n\
1033This is an alist which represents the same mapping from objects to objects,\n\
1034but does not share the alist structure with ALIST.\n\
1035The objects mapped (cars and cdrs of elements of the alist)\n\
1036are shared, however.\n\
1037Elements of ALIST that are not conses are also shared.")
1038 (alist)
1039 Lisp_Object alist;
1040{
1041 register Lisp_Object tem;
1042
1043 CHECK_LIST (alist, 0);
265a9e55 1044 if (NILP (alist))
7b863bd5
JB
1045 return alist;
1046 alist = concat (1, &alist, Lisp_Cons, 0);
1047 for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
1048 {
1049 register Lisp_Object car;
1050 car = XCONS (tem)->car;
1051
1052 if (CONSP (car))
1053 XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
1054 }
1055 return alist;
1056}
1057
1058DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
1059 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
1060TO may be nil or omitted; then the substring runs to the end of STRING.\n\
21fbc8e5
RS
1061If FROM or TO is negative, it counts from the end.\n\
1062\n\
1063This function allows vectors as well as strings.")
7b863bd5
JB
1064 (string, from, to)
1065 Lisp_Object string;
1066 register Lisp_Object from, to;
1067{
ac811a55 1068 Lisp_Object res;
21fbc8e5 1069 int size;
ea35ce3d
RS
1070 int size_byte;
1071 int from_char, to_char;
1072 int from_byte, to_byte;
21fbc8e5
RS
1073
1074 if (! (STRINGP (string) || VECTORP (string)))
1075 wrong_type_argument (Qarrayp, string);
ac811a55 1076
7b863bd5 1077 CHECK_NUMBER (from, 1);
21fbc8e5
RS
1078
1079 if (STRINGP (string))
ea35ce3d
RS
1080 {
1081 size = XSTRING (string)->size;
fc932ac6 1082 size_byte = STRING_BYTES (XSTRING (string));
ea35ce3d 1083 }
21fbc8e5
RS
1084 else
1085 size = XVECTOR (string)->size;
1086
265a9e55 1087 if (NILP (to))
ea35ce3d
RS
1088 {
1089 to_char = size;
1090 to_byte = size_byte;
1091 }
7b863bd5 1092 else
ea35ce3d
RS
1093 {
1094 CHECK_NUMBER (to, 2);
1095
1096 to_char = XINT (to);
1097 if (to_char < 0)
1098 to_char += size;
1099
1100 if (STRINGP (string))
1101 to_byte = string_char_to_byte (string, to_char);
1102 }
1103
1104 from_char = XINT (from);
1105 if (from_char < 0)
1106 from_char += size;
1107 if (STRINGP (string))
1108 from_byte = string_char_to_byte (string, from_char);
7b863bd5 1109
ea35ce3d
RS
1110 if (!(0 <= from_char && from_char <= to_char && to_char <= size))
1111 args_out_of_range_3 (string, make_number (from_char),
1112 make_number (to_char));
7b863bd5 1113
21fbc8e5
RS
1114 if (STRINGP (string))
1115 {
b10b2daa
RS
1116 res = make_specified_string (XSTRING (string)->data + from_byte,
1117 to_char - from_char, to_byte - from_byte,
1118 STRING_MULTIBYTE (string));
21ab867f
AS
1119 copy_text_properties (make_number (from_char), make_number (to_char),
1120 string, make_number (0), res, Qnil);
ea35ce3d
RS
1121 }
1122 else
1123 res = Fvector (to_char - from_char,
1124 XVECTOR (string)->contents + from_char);
1125
1126 return res;
1127}
1128
1129/* Extract a substring of STRING, giving start and end positions
1130 both in characters and in bytes. */
1131
1132Lisp_Object
1133substring_both (string, from, from_byte, to, to_byte)
1134 Lisp_Object string;
1135 int from, from_byte, to, to_byte;
1136{
1137 Lisp_Object res;
1138 int size;
1139 int size_byte;
1140
1141 if (! (STRINGP (string) || VECTORP (string)))
1142 wrong_type_argument (Qarrayp, string);
1143
1144 if (STRINGP (string))
1145 {
1146 size = XSTRING (string)->size;
fc932ac6 1147 size_byte = STRING_BYTES (XSTRING (string));
ea35ce3d
RS
1148 }
1149 else
1150 size = XVECTOR (string)->size;
1151
1152 if (!(0 <= from && from <= to && to <= size))
1153 args_out_of_range_3 (string, make_number (from), make_number (to));
1154
1155 if (STRINGP (string))
1156 {
b10b2daa
RS
1157 res = make_specified_string (XSTRING (string)->data + from_byte,
1158 to - from, to_byte - from_byte,
1159 STRING_MULTIBYTE (string));
21ab867f
AS
1160 copy_text_properties (make_number (from), make_number (to),
1161 string, make_number (0), res, Qnil);
21fbc8e5
RS
1162 }
1163 else
ea35ce3d
RS
1164 res = Fvector (to - from,
1165 XVECTOR (string)->contents + from);
b4f334f7 1166
ac811a55 1167 return res;
7b863bd5
JB
1168}
1169\f
1170DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1171 "Take cdr N times on LIST, returns the result.")
1172 (n, list)
1173 Lisp_Object n;
1174 register Lisp_Object list;
1175{
1176 register int i, num;
1177 CHECK_NUMBER (n, 0);
1178 num = XINT (n);
265a9e55 1179 for (i = 0; i < num && !NILP (list); i++)
7b863bd5
JB
1180 {
1181 QUIT;
1182 list = Fcdr (list);
1183 }
1184 return list;
1185}
1186
1187DEFUN ("nth", Fnth, Snth, 2, 2, 0,
1188 "Return the Nth element of LIST.\n\
1189N counts from zero. If LIST is not that long, nil is returned.")
1190 (n, list)
1191 Lisp_Object n, list;
1192{
1193 return Fcar (Fnthcdr (n, list));
1194}
1195
1196DEFUN ("elt", Felt, Selt, 2, 2, 0,
1197 "Return element of SEQUENCE at index N.")
88fe8140
EN
1198 (sequence, n)
1199 register Lisp_Object sequence, n;
7b863bd5
JB
1200{
1201 CHECK_NUMBER (n, 0);
1202 while (1)
1203 {
88fe8140
EN
1204 if (CONSP (sequence) || NILP (sequence))
1205 return Fcar (Fnthcdr (n, sequence));
1206 else if (STRINGP (sequence) || VECTORP (sequence)
1207 || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
1208 return Faref (sequence, n);
7b863bd5 1209 else
88fe8140 1210 sequence = wrong_type_argument (Qsequencep, sequence);
7b863bd5
JB
1211 }
1212}
1213
1214DEFUN ("member", Fmember, Smember, 2, 2, 0,
1d58e36f 1215 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
7b863bd5
JB
1216The value is actually the tail of LIST whose car is ELT.")
1217 (elt, list)
1218 register Lisp_Object elt;
1219 Lisp_Object list;
1220{
1221 register Lisp_Object tail;
bdd8d692 1222 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1223 {
1224 register Lisp_Object tem;
1225 tem = Fcar (tail);
265a9e55 1226 if (! NILP (Fequal (elt, tem)))
7b863bd5
JB
1227 return tail;
1228 QUIT;
1229 }
1230 return Qnil;
1231}
1232
1233DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
1234 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
1235The value is actually the tail of LIST whose car is ELT.")
1236 (elt, list)
1237 register Lisp_Object elt;
1238 Lisp_Object list;
1239{
1240 register Lisp_Object tail;
bdd8d692 1241 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1242 {
1243 register Lisp_Object tem;
1244 tem = Fcar (tail);
1245 if (EQ (elt, tem)) return tail;
1246 QUIT;
1247 }
1248 return Qnil;
1249}
1250
1251DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
3797b4c3
RS
1252 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
1253The value is actually the element of LIST whose car is KEY.\n\
7b863bd5
JB
1254Elements of LIST that are not conses are ignored.")
1255 (key, list)
1256 register Lisp_Object key;
1257 Lisp_Object list;
1258{
1259 register Lisp_Object tail;
bdd8d692 1260 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1261 {
1262 register Lisp_Object elt, tem;
1263 elt = Fcar (tail);
1264 if (!CONSP (elt)) continue;
bdd8d692 1265 tem = XCONS (elt)->car;
7b863bd5
JB
1266 if (EQ (key, tem)) return elt;
1267 QUIT;
1268 }
1269 return Qnil;
1270}
1271
1272/* Like Fassq but never report an error and do not allow quits.
1273 Use only on lists known never to be circular. */
1274
1275Lisp_Object
1276assq_no_quit (key, list)
1277 register Lisp_Object key;
1278 Lisp_Object list;
1279{
1280 register Lisp_Object tail;
bdd8d692 1281 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1282 {
1283 register Lisp_Object elt, tem;
1284 elt = Fcar (tail);
1285 if (!CONSP (elt)) continue;
bdd8d692 1286 tem = XCONS (elt)->car;
7b863bd5
JB
1287 if (EQ (key, tem)) return elt;
1288 }
1289 return Qnil;
1290}
1291
1292DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
3797b4c3 1293 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
0fb5a19c 1294The value is actually the element of LIST whose car equals KEY.")
7b863bd5
JB
1295 (key, list)
1296 register Lisp_Object key;
1297 Lisp_Object list;
1298{
1299 register Lisp_Object tail;
bdd8d692 1300 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1301 {
1302 register Lisp_Object elt, tem;
1303 elt = Fcar (tail);
1304 if (!CONSP (elt)) continue;
bdd8d692 1305 tem = Fequal (XCONS (elt)->car, key);
265a9e55 1306 if (!NILP (tem)) return elt;
7b863bd5
JB
1307 QUIT;
1308 }
1309 return Qnil;
1310}
1311
1312DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
1313 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
1314The value is actually the element of LIST whose cdr is ELT.")
1315 (key, list)
1316 register Lisp_Object key;
1317 Lisp_Object list;
1318{
1319 register Lisp_Object tail;
bdd8d692 1320 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1321 {
1322 register Lisp_Object elt, tem;
1323 elt = Fcar (tail);
1324 if (!CONSP (elt)) continue;
bdd8d692 1325 tem = XCONS (elt)->cdr;
7b863bd5
JB
1326 if (EQ (key, tem)) return elt;
1327 QUIT;
1328 }
1329 return Qnil;
1330}
0fb5a19c
RS
1331
1332DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1333 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
1334The value is actually the element of LIST whose cdr equals KEY.")
1335 (key, list)
1336 register Lisp_Object key;
1337 Lisp_Object list;
1338{
1339 register Lisp_Object tail;
bdd8d692 1340 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
0fb5a19c
RS
1341 {
1342 register Lisp_Object elt, tem;
1343 elt = Fcar (tail);
1344 if (!CONSP (elt)) continue;
bdd8d692 1345 tem = Fequal (XCONS (elt)->cdr, key);
0fb5a19c
RS
1346 if (!NILP (tem)) return elt;
1347 QUIT;
1348 }
1349 return Qnil;
1350}
7b863bd5
JB
1351\f
1352DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
1353 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1354The modified LIST is returned. Comparison is done with `eq'.\n\
1355If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
1356therefore, write `(setq foo (delq element foo))'\n\
1357to be sure of changing the value of `foo'.")
1358 (elt, list)
1359 register Lisp_Object elt;
1360 Lisp_Object list;
1361{
1362 register Lisp_Object tail, prev;
1363 register Lisp_Object tem;
1364
1365 tail = list;
1366 prev = Qnil;
265a9e55 1367 while (!NILP (tail))
7b863bd5
JB
1368 {
1369 tem = Fcar (tail);
1370 if (EQ (elt, tem))
1371 {
265a9e55 1372 if (NILP (prev))
bdd8d692 1373 list = XCONS (tail)->cdr;
7b863bd5 1374 else
bdd8d692 1375 Fsetcdr (prev, XCONS (tail)->cdr);
7b863bd5
JB
1376 }
1377 else
1378 prev = tail;
bdd8d692 1379 tail = XCONS (tail)->cdr;
7b863bd5
JB
1380 QUIT;
1381 }
1382 return list;
1383}
1384
ca8dd546 1385DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
1e134a5f
RM
1386 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1387The modified LIST is returned. Comparison is done with `equal'.\n\
1d58e36f
RS
1388If the first member of LIST is ELT, deleting it is not a side effect;\n\
1389it is simply using a different list.\n\
1390Therefore, write `(setq foo (delete element foo))'\n\
1e134a5f
RM
1391to be sure of changing the value of `foo'.")
1392 (elt, list)
1393 register Lisp_Object elt;
1394 Lisp_Object list;
1395{
1396 register Lisp_Object tail, prev;
1397 register Lisp_Object tem;
1398
1399 tail = list;
1400 prev = Qnil;
265a9e55 1401 while (!NILP (tail))
1e134a5f
RM
1402 {
1403 tem = Fcar (tail);
f812877e 1404 if (! NILP (Fequal (elt, tem)))
1e134a5f 1405 {
265a9e55 1406 if (NILP (prev))
bdd8d692 1407 list = XCONS (tail)->cdr;
1e134a5f 1408 else
bdd8d692 1409 Fsetcdr (prev, XCONS (tail)->cdr);
1e134a5f
RM
1410 }
1411 else
1412 prev = tail;
bdd8d692 1413 tail = XCONS (tail)->cdr;
1e134a5f
RM
1414 QUIT;
1415 }
1416 return list;
1417}
1418
7b863bd5
JB
1419DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
1420 "Reverse LIST by modifying cdr pointers.\n\
1421Returns the beginning of the reversed list.")
1422 (list)
1423 Lisp_Object list;
1424{
1425 register Lisp_Object prev, tail, next;
1426
265a9e55 1427 if (NILP (list)) return list;
7b863bd5
JB
1428 prev = Qnil;
1429 tail = list;
265a9e55 1430 while (!NILP (tail))
7b863bd5
JB
1431 {
1432 QUIT;
1433 next = Fcdr (tail);
1434 Fsetcdr (tail, prev);
1435 prev = tail;
1436 tail = next;
1437 }
1438 return prev;
1439}
1440
1441DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
1442 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
1443See also the function `nreverse', which is used more often.")
1444 (list)
1445 Lisp_Object list;
1446{
9d14ae76 1447 Lisp_Object new;
7b863bd5 1448
9d14ae76
RS
1449 for (new = Qnil; CONSP (list); list = XCONS (list)->cdr)
1450 new = Fcons (XCONS (list)->car, new);
1451 if (!NILP (list))
1452 wrong_type_argument (Qconsp, list);
1453 return new;
7b863bd5
JB
1454}
1455\f
1456Lisp_Object merge ();
1457
1458DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
1459 "Sort LIST, stably, comparing elements using PREDICATE.\n\
1460Returns the sorted list. LIST is modified by side effects.\n\
1461PREDICATE is called with two elements of LIST, and should return T\n\
1462if the first element is \"less\" than the second.")
88fe8140
EN
1463 (list, predicate)
1464 Lisp_Object list, predicate;
7b863bd5
JB
1465{
1466 Lisp_Object front, back;
1467 register Lisp_Object len, tem;
1468 struct gcpro gcpro1, gcpro2;
1469 register int length;
1470
1471 front = list;
1472 len = Flength (list);
1473 length = XINT (len);
1474 if (length < 2)
1475 return list;
1476
1477 XSETINT (len, (length / 2) - 1);
1478 tem = Fnthcdr (len, list);
1479 back = Fcdr (tem);
1480 Fsetcdr (tem, Qnil);
1481
1482 GCPRO2 (front, back);
88fe8140
EN
1483 front = Fsort (front, predicate);
1484 back = Fsort (back, predicate);
7b863bd5 1485 UNGCPRO;
88fe8140 1486 return merge (front, back, predicate);
7b863bd5
JB
1487}
1488
1489Lisp_Object
1490merge (org_l1, org_l2, pred)
1491 Lisp_Object org_l1, org_l2;
1492 Lisp_Object pred;
1493{
1494 Lisp_Object value;
1495 register Lisp_Object tail;
1496 Lisp_Object tem;
1497 register Lisp_Object l1, l2;
1498 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1499
1500 l1 = org_l1;
1501 l2 = org_l2;
1502 tail = Qnil;
1503 value = Qnil;
1504
1505 /* It is sufficient to protect org_l1 and org_l2.
1506 When l1 and l2 are updated, we copy the new values
1507 back into the org_ vars. */
1508 GCPRO4 (org_l1, org_l2, pred, value);
1509
1510 while (1)
1511 {
265a9e55 1512 if (NILP (l1))
7b863bd5
JB
1513 {
1514 UNGCPRO;
265a9e55 1515 if (NILP (tail))
7b863bd5
JB
1516 return l2;
1517 Fsetcdr (tail, l2);
1518 return value;
1519 }
265a9e55 1520 if (NILP (l2))
7b863bd5
JB
1521 {
1522 UNGCPRO;
265a9e55 1523 if (NILP (tail))
7b863bd5
JB
1524 return l1;
1525 Fsetcdr (tail, l1);
1526 return value;
1527 }
1528 tem = call2 (pred, Fcar (l2), Fcar (l1));
265a9e55 1529 if (NILP (tem))
7b863bd5
JB
1530 {
1531 tem = l1;
1532 l1 = Fcdr (l1);
1533 org_l1 = l1;
1534 }
1535 else
1536 {
1537 tem = l2;
1538 l2 = Fcdr (l2);
1539 org_l2 = l2;
1540 }
265a9e55 1541 if (NILP (tail))
7b863bd5
JB
1542 value = tem;
1543 else
1544 Fsetcdr (tail, tem);
1545 tail = tem;
1546 }
1547}
1548\f
be9d483d
BG
1549
1550DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
1fbb64aa 1551 "Extract a value from a property list.\n\
be9d483d 1552PLIST is a property list, which is a list of the form\n\
c07289e0 1553\(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
be9d483d
BG
1554corresponding to the given PROP, or nil if PROP is not\n\
1555one of the properties on the list.")
1fbb64aa
EN
1556 (plist, prop)
1557 Lisp_Object plist;
7b863bd5
JB
1558 register Lisp_Object prop;
1559{
1560 register Lisp_Object tail;
bdd8d692 1561 for (tail = plist; !NILP (tail); tail = Fcdr (XCONS (tail)->cdr))
7b863bd5
JB
1562 {
1563 register Lisp_Object tem;
1564 tem = Fcar (tail);
1565 if (EQ (prop, tem))
bdd8d692 1566 return Fcar (XCONS (tail)->cdr);
7b863bd5
JB
1567 }
1568 return Qnil;
1569}
1570
be9d483d
BG
1571DEFUN ("get", Fget, Sget, 2, 2, 0,
1572 "Return the value of SYMBOL's PROPNAME property.\n\
c07289e0
RS
1573This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
1574 (symbol, propname)
1575 Lisp_Object symbol, propname;
be9d483d 1576{
c07289e0
RS
1577 CHECK_SYMBOL (symbol, 0);
1578 return Fplist_get (XSYMBOL (symbol)->plist, propname);
be9d483d
BG
1579}
1580
1581DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
1582 "Change value in PLIST of PROP to VAL.\n\
1583PLIST is a property list, which is a list of the form\n\
c07289e0 1584\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
be9d483d 1585If PROP is already a property on the list, its value is set to VAL,\n\
88435890 1586otherwise the new PROP VAL pair is added. The new plist is returned;\n\
be9d483d
BG
1587use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
1588The PLIST is modified by side effects.")
1589 (plist, prop, val)
b4f334f7
KH
1590 Lisp_Object plist;
1591 register Lisp_Object prop;
1592 Lisp_Object val;
7b863bd5
JB
1593{
1594 register Lisp_Object tail, prev;
1595 Lisp_Object newcell;
1596 prev = Qnil;
f8307c0c
KH
1597 for (tail = plist; CONSP (tail) && CONSP (XCONS (tail)->cdr);
1598 tail = XCONS (XCONS (tail)->cdr)->cdr)
7b863bd5 1599 {
f8307c0c 1600 if (EQ (prop, XCONS (tail)->car))
be9d483d 1601 {
f8307c0c 1602 Fsetcar (XCONS (tail)->cdr, val);
be9d483d
BG
1603 return plist;
1604 }
7b863bd5
JB
1605 prev = tail;
1606 }
1607 newcell = Fcons (prop, Fcons (val, Qnil));
265a9e55 1608 if (NILP (prev))
be9d483d 1609 return newcell;
7b863bd5 1610 else
f8307c0c 1611 Fsetcdr (XCONS (prev)->cdr, newcell);
be9d483d
BG
1612 return plist;
1613}
1614
1615DEFUN ("put", Fput, Sput, 3, 3, 0,
1616 "Store SYMBOL's PROPNAME property with value VALUE.\n\
1617It can be retrieved with `(get SYMBOL PROPNAME)'.")
c07289e0
RS
1618 (symbol, propname, value)
1619 Lisp_Object symbol, propname, value;
be9d483d 1620{
c07289e0
RS
1621 CHECK_SYMBOL (symbol, 0);
1622 XSYMBOL (symbol)->plist
1623 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
1624 return value;
7b863bd5
JB
1625}
1626
1627DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
ea35ce3d 1628 "Return t if two Lisp objects have similar structure and contents.\n\
7b863bd5
JB
1629They must have the same data type.\n\
1630Conses are compared by comparing the cars and the cdrs.\n\
1631Vectors and strings are compared element by element.\n\
d28c4332
RS
1632Numbers are compared by value, but integers cannot equal floats.\n\
1633 (Use `=' if you want integers and floats to be able to be equal.)\n\
1634Symbols must match exactly.")
7b863bd5
JB
1635 (o1, o2)
1636 register Lisp_Object o1, o2;
1637{
6cb9cafb 1638 return internal_equal (o1, o2, 0) ? Qt : Qnil;
e0f5cf5a
RS
1639}
1640
6cb9cafb 1641static int
e0f5cf5a
RS
1642internal_equal (o1, o2, depth)
1643 register Lisp_Object o1, o2;
1644 int depth;
1645{
1646 if (depth > 200)
1647 error ("Stack overflow in equal");
4ff1aed9 1648
6cb9cafb 1649 tail_recurse:
7b863bd5 1650 QUIT;
4ff1aed9
RS
1651 if (EQ (o1, o2))
1652 return 1;
1653 if (XTYPE (o1) != XTYPE (o2))
1654 return 0;
1655
1656 switch (XTYPE (o1))
1657 {
31ef7f7a 1658#ifdef LISP_FLOAT_TYPE
4ff1aed9
RS
1659 case Lisp_Float:
1660 return (extract_float (o1) == extract_float (o2));
31ef7f7a 1661#endif
4ff1aed9
RS
1662
1663 case Lisp_Cons:
4cab5074
KH
1664 if (!internal_equal (XCONS (o1)->car, XCONS (o2)->car, depth + 1))
1665 return 0;
1666 o1 = XCONS (o1)->cdr;
1667 o2 = XCONS (o2)->cdr;
1668 goto tail_recurse;
4ff1aed9
RS
1669
1670 case Lisp_Misc:
81d1fba6 1671 if (XMISCTYPE (o1) != XMISCTYPE (o2))
6cb9cafb 1672 return 0;
4ff1aed9 1673 if (OVERLAYP (o1))
7b863bd5 1674 {
4ff1aed9
RS
1675 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o1),
1676 depth + 1)
1677 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o1),
1678 depth + 1))
6cb9cafb 1679 return 0;
4ff1aed9
RS
1680 o1 = XOVERLAY (o1)->plist;
1681 o2 = XOVERLAY (o2)->plist;
1682 goto tail_recurse;
7b863bd5 1683 }
4ff1aed9
RS
1684 if (MARKERP (o1))
1685 {
1686 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
1687 && (XMARKER (o1)->buffer == 0
6ced1284 1688 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
4ff1aed9
RS
1689 }
1690 break;
1691
1692 case Lisp_Vectorlike:
4cab5074
KH
1693 {
1694 register int i, size;
1695 size = XVECTOR (o1)->size;
1696 /* Pseudovectors have the type encoded in the size field, so this test
1697 actually checks that the objects have the same type as well as the
1698 same size. */
1699 if (XVECTOR (o2)->size != size)
1700 return 0;
e03f7933
RS
1701 /* Boolvectors are compared much like strings. */
1702 if (BOOL_VECTOR_P (o1))
1703 {
e03f7933 1704 int size_in_chars
e22e4283 1705 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
1706
1707 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
1708 return 0;
1709 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
1710 size_in_chars))
1711 return 0;
1712 return 1;
1713 }
ed73fcc1 1714 if (WINDOW_CONFIGURATIONP (o1))
48646924 1715 return compare_window_configurations (o1, o2, 0);
e03f7933
RS
1716
1717 /* Aside from them, only true vectors, char-tables, and compiled
1718 functions are sensible to compare, so eliminate the others now. */
4cab5074
KH
1719 if (size & PSEUDOVECTOR_FLAG)
1720 {
e03f7933 1721 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
4cab5074
KH
1722 return 0;
1723 size &= PSEUDOVECTOR_SIZE_MASK;
1724 }
1725 for (i = 0; i < size; i++)
1726 {
1727 Lisp_Object v1, v2;
1728 v1 = XVECTOR (o1)->contents [i];
1729 v2 = XVECTOR (o2)->contents [i];
1730 if (!internal_equal (v1, v2, depth + 1))
1731 return 0;
1732 }
1733 return 1;
1734 }
4ff1aed9
RS
1735 break;
1736
1737 case Lisp_String:
4cab5074
KH
1738 if (XSTRING (o1)->size != XSTRING (o2)->size)
1739 return 0;
fc932ac6 1740 if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
ea35ce3d 1741 return 0;
4cab5074 1742 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
fc932ac6 1743 STRING_BYTES (XSTRING (o1))))
4cab5074 1744 return 0;
4cab5074 1745 return 1;
7b863bd5 1746 }
6cb9cafb 1747 return 0;
7b863bd5
JB
1748}
1749\f
2e34157c
RS
1750extern Lisp_Object Fmake_char_internal ();
1751
7b863bd5 1752DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
e03f7933
RS
1753 "Store each element of ARRAY with ITEM.\n\
1754ARRAY is a vector, string, char-table, or bool-vector.")
7b863bd5
JB
1755 (array, item)
1756 Lisp_Object array, item;
1757{
1758 register int size, index, charval;
1759 retry:
7650760e 1760 if (VECTORP (array))
7b863bd5
JB
1761 {
1762 register Lisp_Object *p = XVECTOR (array)->contents;
1763 size = XVECTOR (array)->size;
1764 for (index = 0; index < size; index++)
1765 p[index] = item;
1766 }
e03f7933
RS
1767 else if (CHAR_TABLE_P (array))
1768 {
1769 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
1770 size = CHAR_TABLE_ORDINARY_SLOTS;
1771 for (index = 0; index < size; index++)
1772 p[index] = item;
1773 XCHAR_TABLE (array)->defalt = Qnil;
1774 }
7650760e 1775 else if (STRINGP (array))
7b863bd5
JB
1776 {
1777 register unsigned char *p = XSTRING (array)->data;
1778 CHECK_NUMBER (item, 1);
1779 charval = XINT (item);
1780 size = XSTRING (array)->size;
1781 for (index = 0; index < size; index++)
1782 p[index] = charval;
1783 }
e03f7933
RS
1784 else if (BOOL_VECTOR_P (array))
1785 {
1786 register unsigned char *p = XBOOL_VECTOR (array)->data;
e03f7933 1787 int size_in_chars
e22e4283 1788 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
1789
1790 charval = (! NILP (item) ? -1 : 0);
1791 for (index = 0; index < size_in_chars; index++)
1792 p[index] = charval;
1793 }
7b863bd5
JB
1794 else
1795 {
1796 array = wrong_type_argument (Qarrayp, array);
1797 goto retry;
1798 }
1799 return array;
1800}
ea35ce3d 1801\f
999de246
RS
1802DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
1803 1, 1, 0,
1804 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
88fe8140
EN
1805 (char_table)
1806 Lisp_Object char_table;
999de246 1807{
b4f334f7 1808 CHECK_CHAR_TABLE (char_table, 0);
999de246 1809
88fe8140 1810 return XCHAR_TABLE (char_table)->purpose;
999de246
RS
1811}
1812
e03f7933
RS
1813DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
1814 1, 1, 0,
1815 "Return the parent char-table of CHAR-TABLE.\n\
1816The value is either nil or another char-table.\n\
1817If CHAR-TABLE holds nil for a given character,\n\
1818then the actual applicable value is inherited from the parent char-table\n\
1819\(or from its parents, if necessary).")
88fe8140
EN
1820 (char_table)
1821 Lisp_Object char_table;
e03f7933 1822{
b4f334f7 1823 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 1824
88fe8140 1825 return XCHAR_TABLE (char_table)->parent;
e03f7933
RS
1826}
1827
1828DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
1829 2, 2, 0,
1830 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
1831PARENT must be either nil or another char-table.")
88fe8140
EN
1832 (char_table, parent)
1833 Lisp_Object char_table, parent;
e03f7933
RS
1834{
1835 Lisp_Object temp;
1836
b4f334f7 1837 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 1838
c8640abf
RS
1839 if (!NILP (parent))
1840 {
b4f334f7 1841 CHECK_CHAR_TABLE (parent, 0);
c8640abf
RS
1842
1843 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
55cc974d 1844 if (EQ (temp, char_table))
c8640abf
RS
1845 error ("Attempt to make a chartable be its own parent");
1846 }
e03f7933 1847
88fe8140 1848 XCHAR_TABLE (char_table)->parent = parent;
e03f7933
RS
1849
1850 return parent;
1851}
1852
1853DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
1854 2, 2, 0,
25c30748 1855 "Return the value of CHAR-TABLE's extra-slot number N.")
88fe8140
EN
1856 (char_table, n)
1857 Lisp_Object char_table, n;
e03f7933 1858{
88fe8140 1859 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
1860 CHECK_NUMBER (n, 2);
1861 if (XINT (n) < 0
88fe8140
EN
1862 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1863 args_out_of_range (char_table, n);
e03f7933 1864
88fe8140 1865 return XCHAR_TABLE (char_table)->extras[XINT (n)];
e03f7933
RS
1866}
1867
1868DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
1869 Sset_char_table_extra_slot,
1870 3, 3, 0,
25c30748 1871 "Set CHAR-TABLE's extra-slot number N to VALUE.")
88fe8140
EN
1872 (char_table, n, value)
1873 Lisp_Object char_table, n, value;
e03f7933 1874{
88fe8140 1875 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
1876 CHECK_NUMBER (n, 2);
1877 if (XINT (n) < 0
88fe8140
EN
1878 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1879 args_out_of_range (char_table, n);
e03f7933 1880
88fe8140 1881 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
e03f7933 1882}
ea35ce3d 1883\f
999de246
RS
1884DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
1885 2, 2, 0,
88fe8140 1886 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
6d475204 1887RANGE should be nil (for the default value)\n\
999de246 1888a vector which identifies a character set or a row of a character set,\n\
6d475204 1889a character set name, or a character code.")
88fe8140
EN
1890 (char_table, range)
1891 Lisp_Object char_table, range;
999de246
RS
1892{
1893 int i;
1894
88fe8140 1895 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 1896
999de246 1897 if (EQ (range, Qnil))
88fe8140 1898 return XCHAR_TABLE (char_table)->defalt;
999de246 1899 else if (INTEGERP (range))
88fe8140 1900 return Faref (char_table, range);
6d475204
RS
1901 else if (SYMBOLP (range))
1902 {
1903 Lisp_Object charset_info;
1904
1905 charset_info = Fget (range, Qcharset);
1906 CHECK_VECTOR (charset_info, 0);
1907
21ab867f
AS
1908 return Faref (char_table,
1909 make_number (XINT (XVECTOR (charset_info)->contents[0])
1910 + 128));
6d475204 1911 }
999de246
RS
1912 else if (VECTORP (range))
1913 {
e814a159 1914 if (XVECTOR (range)->size == 1)
21ab867f
AS
1915 return Faref (char_table,
1916 make_number (XINT (XVECTOR (range)->contents[0]) + 128));
e814a159
RS
1917 else
1918 {
1919 int size = XVECTOR (range)->size;
1920 Lisp_Object *val = XVECTOR (range)->contents;
1921 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1922 size <= 1 ? Qnil : val[1],
1923 size <= 2 ? Qnil : val[2]);
1924 return Faref (char_table, ch);
1925 }
999de246
RS
1926 }
1927 else
1928 error ("Invalid RANGE argument to `char-table-range'");
1929}
1930
e03f7933
RS
1931DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
1932 3, 3, 0,
88fe8140 1933 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
e03f7933
RS
1934RANGE should be t (for all characters), nil (for the default value)\n\
1935a vector which identifies a character set or a row of a character set,\n\
6d475204 1936a coding system, or a character code.")
88fe8140
EN
1937 (char_table, range, value)
1938 Lisp_Object char_table, range, value;
e03f7933
RS
1939{
1940 int i;
1941
88fe8140 1942 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 1943
e03f7933
RS
1944 if (EQ (range, Qt))
1945 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
88fe8140 1946 XCHAR_TABLE (char_table)->contents[i] = value;
e03f7933 1947 else if (EQ (range, Qnil))
88fe8140 1948 XCHAR_TABLE (char_table)->defalt = value;
6d475204
RS
1949 else if (SYMBOLP (range))
1950 {
1951 Lisp_Object charset_info;
1952
1953 charset_info = Fget (range, Qcharset);
1954 CHECK_VECTOR (charset_info, 0);
1955
21ab867f
AS
1956 return Faset (char_table,
1957 make_number (XINT (XVECTOR (charset_info)->contents[0])
1958 + 128),
6d475204
RS
1959 value);
1960 }
e03f7933 1961 else if (INTEGERP (range))
88fe8140 1962 Faset (char_table, range, value);
e03f7933
RS
1963 else if (VECTORP (range))
1964 {
e814a159 1965 if (XVECTOR (range)->size == 1)
21ab867f
AS
1966 return Faset (char_table,
1967 make_number (XINT (XVECTOR (range)->contents[0]) + 128),
1968 value);
e814a159
RS
1969 else
1970 {
1971 int size = XVECTOR (range)->size;
1972 Lisp_Object *val = XVECTOR (range)->contents;
1973 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1974 size <= 1 ? Qnil : val[1],
1975 size <= 2 ? Qnil : val[2]);
1976 return Faset (char_table, ch, value);
1977 }
e03f7933
RS
1978 }
1979 else
1980 error ("Invalid RANGE argument to `set-char-table-range'");
1981
1982 return value;
1983}
e1335ba2
KH
1984
1985DEFUN ("set-char-table-default", Fset_char_table_default,
1986 Sset_char_table_default, 3, 3, 0,
1987 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
1988The generic character specifies the group of characters.\n\
1989See also the documentation of make-char.")
1990 (char_table, ch, value)
1991 Lisp_Object char_table, ch, value;
1992{
1993 int c, i, charset, code1, code2;
1994 Lisp_Object temp;
1995
1996 CHECK_CHAR_TABLE (char_table, 0);
1997 CHECK_NUMBER (ch, 1);
1998
1999 c = XINT (ch);
2000 SPLIT_NON_ASCII_CHAR (c, charset, code1, code2);
0da528a9
KH
2001
2002 /* Since we may want to set the default value for a character set
2003 not yet defined, we check only if the character set is in the
2004 valid range or not, instead of it is already defined or not. */
2005 if (! CHARSET_VALID_P (charset))
f71599f4 2006 invalid_character (c);
e1335ba2
KH
2007
2008 if (charset == CHARSET_ASCII)
2009 return (XCHAR_TABLE (char_table)->defalt = value);
2010
2011 /* Even if C is not a generic char, we had better behave as if a
2012 generic char is specified. */
0da528a9 2013 if (charset == CHARSET_COMPOSITION || CHARSET_DIMENSION (charset) == 1)
e1335ba2
KH
2014 code1 = 0;
2015 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
2016 if (!code1)
2017 {
2018 if (SUB_CHAR_TABLE_P (temp))
2019 XCHAR_TABLE (temp)->defalt = value;
2020 else
2021 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
2022 return value;
2023 }
2024 char_table = temp;
2025 if (! SUB_CHAR_TABLE_P (char_table))
2026 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
2027 = make_sub_char_table (temp));
2028 temp = XCHAR_TABLE (char_table)->contents[code1];
2029 if (SUB_CHAR_TABLE_P (temp))
2030 XCHAR_TABLE (temp)->defalt = value;
2031 else
2032 XCHAR_TABLE (char_table)->contents[code1] = value;
2033 return value;
2034}
1d969a23
RS
2035
2036/* Look up the element in TABLE at index CH,
2037 and return it as an integer.
2038 If the element is nil, return CH itself.
2039 (Actually we do that for any non-integer.) */
2040
2041int
2042char_table_translate (table, ch)
2043 Lisp_Object table;
2044 int ch;
2045{
2046 Lisp_Object value;
2047 value = Faref (table, make_number (ch));
2048 if (! INTEGERP (value))
2049 return ch;
2050 return XINT (value);
2051}
e03f7933 2052\f
46ed603f 2053/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
c8640abf
RS
2054 character or group of characters that share a value.
2055 DEPTH is the current depth in the originally specified
2056 chartable, and INDICES contains the vector indices
46ed603f
RS
2057 for the levels our callers have descended.
2058
2059 ARG is passed to C_FUNCTION when that is called. */
c8640abf
RS
2060
2061void
46ed603f 2062map_char_table (c_function, function, subtable, arg, depth, indices)
22e6f12b
AS
2063 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2064 Lisp_Object function, subtable, arg, *indices;
1847b19b 2065 int depth;
e03f7933 2066{
3720677d 2067 int i, to;
e03f7933 2068
a8283a4a 2069 if (depth == 0)
3720677d
KH
2070 {
2071 /* At first, handle ASCII and 8-bit European characters. */
2072 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
2073 {
46ed603f 2074 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2075 if (c_function)
46ed603f 2076 (*c_function) (arg, make_number (i), elt);
3720677d
KH
2077 else
2078 call2 (function, make_number (i), elt);
2079 }
ea35ce3d
RS
2080#if 0 /* If the char table has entries for higher characters,
2081 we should report them. */
de86fcba
KH
2082 if (NILP (current_buffer->enable_multibyte_characters))
2083 return;
ea35ce3d 2084#endif
3720677d
KH
2085 to = CHAR_TABLE_ORDINARY_SLOTS;
2086 }
a8283a4a 2087 else
e03f7933 2088 {
de86fcba 2089 i = 32;
3720677d 2090 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
e03f7933
RS
2091 }
2092
7e798f25 2093 for (; i < to; i++)
e03f7933 2094 {
46ed603f 2095 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2096
09ee221d 2097 XSETFASTINT (indices[depth], i);
3720677d
KH
2098
2099 if (SUB_CHAR_TABLE_P (elt))
2100 {
2101 if (depth >= 3)
2102 error ("Too deep char table");
7e798f25 2103 map_char_table (c_function, function, elt, arg, depth + 1, indices);
3720677d 2104 }
e03f7933 2105 else
a8283a4a 2106 {
3720677d
KH
2107 int charset = XFASTINT (indices[0]) - 128, c1, c2, c;
2108
a8283a4a
KH
2109 if (CHARSET_DEFINED_P (charset))
2110 {
3720677d
KH
2111 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
2112 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
a8283a4a 2113 c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
3720677d 2114 if (c_function)
46ed603f 2115 (*c_function) (arg, make_number (c), elt);
3720677d
KH
2116 else
2117 call2 (function, make_number (c), elt);
a8283a4a 2118 }
b4f334f7 2119 }
e03f7933
RS
2120 }
2121}
2122
2123DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
2124 2, 2, 0,
7e798f25 2125 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
e03f7933 2126FUNCTION is called with two arguments--a key and a value.\n\
7e798f25 2127The key is always a possible IDX argument to `aref'.")
88fe8140
EN
2128 (function, char_table)
2129 Lisp_Object function, char_table;
e03f7933 2130{
3720677d 2131 /* The depth of char table is at most 3. */
7e798f25
KH
2132 Lisp_Object indices[3];
2133
2134 CHECK_CHAR_TABLE (char_table, 1);
e03f7933 2135
46ed603f 2136 map_char_table (NULL, function, char_table, char_table, 0, indices);
e03f7933
RS
2137 return Qnil;
2138}
2139\f
7b863bd5
JB
2140/* ARGSUSED */
2141Lisp_Object
2142nconc2 (s1, s2)
2143 Lisp_Object s1, s2;
2144{
2145#ifdef NO_ARG_ARRAY
2146 Lisp_Object args[2];
2147 args[0] = s1;
2148 args[1] = s2;
2149 return Fnconc (2, args);
2150#else
2151 return Fnconc (2, &s1);
2152#endif /* NO_ARG_ARRAY */
2153}
2154
2155DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
2156 "Concatenate any number of lists by altering them.\n\
2157Only the last argument is not altered, and need not be a list.")
2158 (nargs, args)
2159 int nargs;
2160 Lisp_Object *args;
2161{
2162 register int argnum;
2163 register Lisp_Object tail, tem, val;
2164
2165 val = Qnil;
2166
2167 for (argnum = 0; argnum < nargs; argnum++)
2168 {
2169 tem = args[argnum];
265a9e55 2170 if (NILP (tem)) continue;
7b863bd5 2171
265a9e55 2172 if (NILP (val))
7b863bd5
JB
2173 val = tem;
2174
2175 if (argnum + 1 == nargs) break;
2176
2177 if (!CONSP (tem))
2178 tem = wrong_type_argument (Qlistp, tem);
2179
2180 while (CONSP (tem))
2181 {
2182 tail = tem;
2183 tem = Fcdr (tail);
2184 QUIT;
2185 }
2186
2187 tem = args[argnum + 1];
2188 Fsetcdr (tail, tem);
265a9e55 2189 if (NILP (tem))
7b863bd5
JB
2190 args[argnum + 1] = tail;
2191 }
2192
2193 return val;
2194}
2195\f
2196/* This is the guts of all mapping functions.
ea35ce3d
RS
2197 Apply FN to each element of SEQ, one by one,
2198 storing the results into elements of VALS, a C vector of Lisp_Objects.
2199 LENI is the length of VALS, which should also be the length of SEQ. */
7b863bd5
JB
2200
2201static void
2202mapcar1 (leni, vals, fn, seq)
2203 int leni;
2204 Lisp_Object *vals;
2205 Lisp_Object fn, seq;
2206{
2207 register Lisp_Object tail;
2208 Lisp_Object dummy;
2209 register int i;
2210 struct gcpro gcpro1, gcpro2, gcpro3;
2211
2212 /* Don't let vals contain any garbage when GC happens. */
2213 for (i = 0; i < leni; i++)
2214 vals[i] = Qnil;
2215
2216 GCPRO3 (dummy, fn, seq);
2217 gcpro1.var = vals;
2218 gcpro1.nvars = leni;
2219 /* We need not explicitly protect `tail' because it is used only on lists, and
2220 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
2221
7650760e 2222 if (VECTORP (seq))
7b863bd5
JB
2223 {
2224 for (i = 0; i < leni; i++)
2225 {
2226 dummy = XVECTOR (seq)->contents[i];
2227 vals[i] = call1 (fn, dummy);
2228 }
2229 }
33aa0881
KH
2230 else if (BOOL_VECTOR_P (seq))
2231 {
2232 for (i = 0; i < leni; i++)
2233 {
2234 int byte;
2235 byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
2236 if (byte & (1 << (i % BITS_PER_CHAR)))
2237 dummy = Qt;
2238 else
2239 dummy = Qnil;
2240
2241 vals[i] = call1 (fn, dummy);
2242 }
2243 }
ea35ce3d 2244 else if (STRINGP (seq) && ! STRING_MULTIBYTE (seq))
7b863bd5 2245 {
ea35ce3d 2246 /* Single-byte string. */
7b863bd5
JB
2247 for (i = 0; i < leni; i++)
2248 {
ad17573a 2249 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
7b863bd5
JB
2250 vals[i] = call1 (fn, dummy);
2251 }
2252 }
ea35ce3d
RS
2253 else if (STRINGP (seq))
2254 {
2255 /* Multi-byte string. */
fc932ac6 2256 int len_byte = STRING_BYTES (XSTRING (seq));
ea35ce3d
RS
2257 int i_byte;
2258
2259 for (i = 0, i_byte = 0; i < leni;)
2260 {
2261 int c;
0ab6a3d8
KH
2262 int i_before = i;
2263
2264 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
ea35ce3d 2265 XSETFASTINT (dummy, c);
0ab6a3d8 2266 vals[i_before] = call1 (fn, dummy);
ea35ce3d
RS
2267 }
2268 }
7b863bd5
JB
2269 else /* Must be a list, since Flength did not get an error */
2270 {
2271 tail = seq;
2272 for (i = 0; i < leni; i++)
2273 {
2274 vals[i] = call1 (fn, Fcar (tail));
bdd8d692 2275 tail = XCONS (tail)->cdr;
7b863bd5
JB
2276 }
2277 }
2278
2279 UNGCPRO;
2280}
2281
2282DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
88fe8140
EN
2283 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2284In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
33aa0881
KH
2285SEPARATOR results in spaces between the values returned by FUNCTION.\n\
2286SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2287 (function, sequence, separator)
2288 Lisp_Object function, sequence, separator;
7b863bd5
JB
2289{
2290 Lisp_Object len;
2291 register int leni;
2292 int nargs;
2293 register Lisp_Object *args;
2294 register int i;
2295 struct gcpro gcpro1;
2296
88fe8140 2297 len = Flength (sequence);
7b863bd5
JB
2298 leni = XINT (len);
2299 nargs = leni + leni - 1;
2300 if (nargs < 0) return build_string ("");
2301
2302 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2303
88fe8140
EN
2304 GCPRO1 (separator);
2305 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2306 UNGCPRO;
2307
2308 for (i = leni - 1; i >= 0; i--)
2309 args[i + i] = args[i];
b4f334f7 2310
7b863bd5 2311 for (i = 1; i < nargs; i += 2)
88fe8140 2312 args[i] = separator;
7b863bd5
JB
2313
2314 return Fconcat (nargs, args);
2315}
2316
2317DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2318 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2319The result is a list just as long as SEQUENCE.\n\
33aa0881 2320SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2321 (function, sequence)
2322 Lisp_Object function, sequence;
7b863bd5
JB
2323{
2324 register Lisp_Object len;
2325 register int leni;
2326 register Lisp_Object *args;
2327
88fe8140 2328 len = Flength (sequence);
7b863bd5
JB
2329 leni = XFASTINT (len);
2330 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2331
88fe8140 2332 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2333
2334 return Flist (leni, args);
2335}
2336\f
2337/* Anything that calls this function must protect from GC! */
2338
2339DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2340 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
c763f396
RS
2341Takes one argument, which is the string to display to ask the question.\n\
2342It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
7b863bd5
JB
2343No confirmation of the answer is requested; a single character is enough.\n\
2344Also accepts Space to mean yes, or Delete to mean no.")
2345 (prompt)
2346 Lisp_Object prompt;
2347{
f5313ed9
RS
2348 register Lisp_Object obj, key, def, answer_string, map;
2349 register int answer;
7b863bd5
JB
2350 Lisp_Object xprompt;
2351 Lisp_Object args[2];
7b863bd5 2352 struct gcpro gcpro1, gcpro2;
eb4ffa4e
RS
2353 int count = specpdl_ptr - specpdl;
2354
2355 specbind (Qcursor_in_echo_area, Qt);
7b863bd5 2356
f5313ed9
RS
2357 map = Fsymbol_value (intern ("query-replace-map"));
2358
7b863bd5
JB
2359 CHECK_STRING (prompt, 0);
2360 xprompt = prompt;
2361 GCPRO2 (prompt, xprompt);
2362
2363 while (1)
2364 {
eb4ffa4e 2365
0ef68e8a 2366#ifdef HAVE_MENUS
588064ce 2367 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2368 && use_dialog_box
0ef68e8a 2369 && have_menus_p ())
1db4cfb2
RS
2370 {
2371 Lisp_Object pane, menu;
a3b14a45 2372 redisplay_preserve_echo_area ();
1db4cfb2
RS
2373 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2374 Fcons (Fcons (build_string ("No"), Qnil),
2375 Qnil));
ec26e1b9 2376 menu = Fcons (prompt, pane);
d2f28f78 2377 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2378 answer = !NILP (obj);
2379 break;
2380 }
0ef68e8a 2381#endif /* HAVE_MENUS */
dfa89228 2382 cursor_in_echo_area = 1;
b312cc52 2383 choose_minibuf_frame ();
ea35ce3d 2384 message_with_string ("%s(y or n) ", xprompt, 0);
7b863bd5 2385
2d8e7e1f
RS
2386 if (minibuffer_auto_raise)
2387 {
2388 Lisp_Object mini_frame;
2389
2390 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2391
2392 Fraise_frame (mini_frame);
2393 }
2394
dfa89228
KH
2395 obj = read_filtered_event (1, 0, 0);
2396 cursor_in_echo_area = 0;
2397 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2398 QUIT;
a63f658b 2399
f5313ed9 2400 key = Fmake_vector (make_number (1), obj);
aad2a123 2401 def = Flookup_key (map, key, Qt);
f5313ed9 2402 answer_string = Fsingle_key_description (obj);
7b863bd5 2403
f5313ed9
RS
2404 if (EQ (def, intern ("skip")))
2405 {
2406 answer = 0;
2407 break;
2408 }
2409 else if (EQ (def, intern ("act")))
2410 {
2411 answer = 1;
2412 break;
2413 }
29944b73
RS
2414 else if (EQ (def, intern ("recenter")))
2415 {
2416 Frecenter (Qnil);
2417 xprompt = prompt;
2418 continue;
2419 }
f5313ed9 2420 else if (EQ (def, intern ("quit")))
7b863bd5 2421 Vquit_flag = Qt;
ec63af1b
RS
2422 /* We want to exit this command for exit-prefix,
2423 and this is the only way to do it. */
2424 else if (EQ (def, intern ("exit-prefix")))
2425 Vquit_flag = Qt;
f5313ed9 2426
7b863bd5 2427 QUIT;
20aa96aa
JB
2428
2429 /* If we don't clear this, then the next call to read_char will
2430 return quit_char again, and we'll enter an infinite loop. */
088880f1 2431 Vquit_flag = Qnil;
7b863bd5
JB
2432
2433 Fding (Qnil);
2434 Fdiscard_input ();
2435 if (EQ (xprompt, prompt))
2436 {
2437 args[0] = build_string ("Please answer y or n. ");
2438 args[1] = prompt;
2439 xprompt = Fconcat (2, args);
2440 }
2441 }
2442 UNGCPRO;
6a8a9750 2443
09c95874
RS
2444 if (! noninteractive)
2445 {
2446 cursor_in_echo_area = -1;
ea35ce3d
RS
2447 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2448 xprompt, 0);
09c95874 2449 }
6a8a9750 2450
eb4ffa4e 2451 unbind_to (count, Qnil);
f5313ed9 2452 return answer ? Qt : Qnil;
7b863bd5
JB
2453}
2454\f
2455/* This is how C code calls `yes-or-no-p' and allows the user
2456 to redefined it.
2457
2458 Anything that calls this function must protect from GC! */
2459
2460Lisp_Object
2461do_yes_or_no_p (prompt)
2462 Lisp_Object prompt;
2463{
2464 return call1 (intern ("yes-or-no-p"), prompt);
2465}
2466
2467/* Anything that calls this function must protect from GC! */
2468
2469DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
c763f396
RS
2470 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2471Takes one argument, which is the string to display to ask the question.\n\
2472It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2473The user must confirm the answer with RET,\n\
d8616fc1 2474and can edit it until it has been confirmed.")
7b863bd5
JB
2475 (prompt)
2476 Lisp_Object prompt;
2477{
2478 register Lisp_Object ans;
2479 Lisp_Object args[2];
2480 struct gcpro gcpro1;
1db4cfb2 2481 Lisp_Object menu;
7b863bd5
JB
2482
2483 CHECK_STRING (prompt, 0);
2484
0ef68e8a 2485#ifdef HAVE_MENUS
b4f334f7 2486 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2487 && use_dialog_box
0ef68e8a 2488 && have_menus_p ())
1db4cfb2
RS
2489 {
2490 Lisp_Object pane, menu, obj;
a3b14a45 2491 redisplay_preserve_echo_area ();
1db4cfb2
RS
2492 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2493 Fcons (Fcons (build_string ("No"), Qnil),
2494 Qnil));
2495 GCPRO1 (pane);
ec26e1b9 2496 menu = Fcons (prompt, pane);
b5ccb0a9 2497 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2498 UNGCPRO;
2499 return obj;
2500 }
0ef68e8a 2501#endif /* HAVE_MENUS */
1db4cfb2 2502
7b863bd5
JB
2503 args[0] = prompt;
2504 args[1] = build_string ("(yes or no) ");
2505 prompt = Fconcat (2, args);
2506
2507 GCPRO1 (prompt);
1db4cfb2 2508
7b863bd5
JB
2509 while (1)
2510 {
0ce830bc 2511 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
b24014d4
KH
2512 Qyes_or_no_p_history, Qnil,
2513 Qnil));
7b863bd5
JB
2514 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2515 {
2516 UNGCPRO;
2517 return Qt;
2518 }
2519 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2520 {
2521 UNGCPRO;
2522 return Qnil;
2523 }
2524
2525 Fding (Qnil);
2526 Fdiscard_input ();
2527 message ("Please answer yes or no.");
99dc4745 2528 Fsleep_for (make_number (2), Qnil);
7b863bd5 2529 }
7b863bd5
JB
2530}
2531\f
f4b50f66 2532DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
7b863bd5
JB
2533 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2534Each of the three load averages is multiplied by 100,\n\
daa37602 2535then converted to integer.\n\
f4b50f66
RS
2536When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
2537These floats are not multiplied by 100.\n\n\
daa37602
JB
2538If the 5-minute or 15-minute load averages are not available, return a\n\
2539shortened list, containing only those averages which are available.")
f4b50f66
RS
2540 (use_floats)
2541 Lisp_Object use_floats;
7b863bd5 2542{
daa37602
JB
2543 double load_ave[3];
2544 int loads = getloadavg (load_ave, 3);
f4b50f66 2545 Lisp_Object ret = Qnil;
7b863bd5 2546
daa37602
JB
2547 if (loads < 0)
2548 error ("load-average not implemented for this operating system");
2549
f4b50f66
RS
2550 while (loads-- > 0)
2551 {
2552 Lisp_Object load = (NILP (use_floats) ?
2553 make_number ((int) (100.0 * load_ave[loads]))
2554 : make_float (load_ave[loads]));
2555 ret = Fcons (load, ret);
2556 }
daa37602
JB
2557
2558 return ret;
2559}
7b863bd5
JB
2560\f
2561Lisp_Object Vfeatures;
2562
2563DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2564 "Returns t if FEATURE is present in this Emacs.\n\
2565Use this to conditionalize execution of lisp code based on the presence or\n\
2566absence of emacs or environment extensions.\n\
2567Use `provide' to declare that a feature is available.\n\
2568This function looks at the value of the variable `features'.")
b4f334f7 2569 (feature)
7b863bd5
JB
2570 Lisp_Object feature;
2571{
2572 register Lisp_Object tem;
2573 CHECK_SYMBOL (feature, 0);
2574 tem = Fmemq (feature, Vfeatures);
265a9e55 2575 return (NILP (tem)) ? Qnil : Qt;
7b863bd5
JB
2576}
2577
2578DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2579 "Announce that FEATURE is a feature of the current Emacs.")
b4f334f7 2580 (feature)
7b863bd5
JB
2581 Lisp_Object feature;
2582{
2583 register Lisp_Object tem;
2584 CHECK_SYMBOL (feature, 0);
265a9e55 2585 if (!NILP (Vautoload_queue))
7b863bd5
JB
2586 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2587 tem = Fmemq (feature, Vfeatures);
265a9e55 2588 if (NILP (tem))
7b863bd5 2589 Vfeatures = Fcons (feature, Vfeatures);
68732608 2590 LOADHIST_ATTACH (Fcons (Qprovide, feature));
7b863bd5
JB
2591 return feature;
2592}
2593
2594DEFUN ("require", Frequire, Srequire, 1, 2, 0,
2595 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2596If FEATURE is not a member of the list `features', then the feature\n\
2597is not loaded; so load the file FILENAME.\n\
f0c030b3
RS
2598If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
2599but in this case `load' insists on adding the suffix `.el' or `.elc'.")
b4f334f7 2600 (feature, file_name)
7b863bd5
JB
2601 Lisp_Object feature, file_name;
2602{
2603 register Lisp_Object tem;
2604 CHECK_SYMBOL (feature, 0);
2605 tem = Fmemq (feature, Vfeatures);
68732608 2606 LOADHIST_ATTACH (Fcons (Qrequire, feature));
265a9e55 2607 if (NILP (tem))
7b863bd5
JB
2608 {
2609 int count = specpdl_ptr - specpdl;
2610
2611 /* Value saved here is to be restored into Vautoload_queue */
2612 record_unwind_protect (un_autoload, Vautoload_queue);
2613 Vautoload_queue = Qt;
2614
265a9e55 2615 Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
fdb5bec0 2616 Qnil, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
7b863bd5
JB
2617
2618 tem = Fmemq (feature, Vfeatures);
265a9e55 2619 if (NILP (tem))
7b863bd5 2620 error ("Required feature %s was not provided",
fdb5bec0 2621 XSYMBOL (feature)->name->data);
7b863bd5
JB
2622
2623 /* Once loading finishes, don't undo it. */
2624 Vautoload_queue = Qt;
2625 feature = unbind_to (count, feature);
2626 }
2627 return feature;
2628}
2629\f
b4f334f7
KH
2630/* Primitives for work of the "widget" library.
2631 In an ideal world, this section would not have been necessary.
2632 However, lisp function calls being as slow as they are, it turns
2633 out that some functions in the widget library (wid-edit.el) are the
2634 bottleneck of Widget operation. Here is their translation to C,
2635 for the sole reason of efficiency. */
2636
2637DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2638 "Return non-nil if PLIST has the property PROP.\n\
2639PLIST is a property list, which is a list of the form\n\
2640\(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2641Unlike `plist-get', this allows you to distinguish between a missing\n\
2642property and a property with the value nil.\n\
2643The value is actually the tail of PLIST whose car is PROP.")
2644 (plist, prop)
2645 Lisp_Object plist, prop;
2646{
2647 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2648 {
2649 QUIT;
2650 plist = XCDR (plist);
2651 plist = CDR (plist);
2652 }
2653 return plist;
2654}
2655
2656DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2657 "In WIDGET, set PROPERTY to VALUE.\n\
2658The value can later be retrieved with `widget-get'.")
2659 (widget, property, value)
2660 Lisp_Object widget, property, value;
2661{
2662 CHECK_CONS (widget, 1);
2663 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
2664}
2665
2666DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2667 "In WIDGET, get the value of PROPERTY.\n\
2668The value could either be specified when the widget was created, or\n\
2669later with `widget-put'.")
2670 (widget, property)
2671 Lisp_Object widget, property;
2672{
2673 Lisp_Object tmp;
2674
2675 while (1)
2676 {
2677 if (NILP (widget))
2678 return Qnil;
2679 CHECK_CONS (widget, 1);
2680 tmp = Fwidget_plist_member (XCDR (widget), property);
2681 if (CONSP (tmp))
2682 {
2683 tmp = XCDR (tmp);
2684 return CAR (tmp);
2685 }
2686 tmp = XCAR (widget);
2687 if (NILP (tmp))
2688 return Qnil;
2689 widget = Fget (tmp, Qwidget_type);
2690 }
2691}
2692
2693DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
2694 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
2695ARGS are passed as extra arguments to the function.")
2696 (nargs, args)
2697 int nargs;
2698 Lisp_Object *args;
2699{
2700 /* This function can GC. */
2701 Lisp_Object newargs[3];
2702 struct gcpro gcpro1, gcpro2;
2703 Lisp_Object result;
2704
2705 newargs[0] = Fwidget_get (args[0], args[1]);
2706 newargs[1] = args[0];
2707 newargs[2] = Flist (nargs - 2, args + 2);
2708 GCPRO2 (newargs[0], newargs[2]);
2709 result = Fapply (3, newargs);
2710 UNGCPRO;
2711 return result;
2712}
2713\f
dfcf069d 2714void
7b863bd5
JB
2715syms_of_fns ()
2716{
2717 Qstring_lessp = intern ("string-lessp");
2718 staticpro (&Qstring_lessp);
68732608
RS
2719 Qprovide = intern ("provide");
2720 staticpro (&Qprovide);
2721 Qrequire = intern ("require");
2722 staticpro (&Qrequire);
0ce830bc
RS
2723 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
2724 staticpro (&Qyes_or_no_p_history);
eb4ffa4e
RS
2725 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
2726 staticpro (&Qcursor_in_echo_area);
b4f334f7
KH
2727 Qwidget_type = intern ("widget-type");
2728 staticpro (&Qwidget_type);
7b863bd5 2729
09ab3c3b
KH
2730 staticpro (&string_char_byte_cache_string);
2731 string_char_byte_cache_string = Qnil;
2732
52a9879b
RS
2733 Fset (Qyes_or_no_p_history, Qnil);
2734
7b863bd5
JB
2735 DEFVAR_LISP ("features", &Vfeatures,
2736 "A list of symbols which are the features of the executing emacs.\n\
2737Used by `featurep' and `require', and altered by `provide'.");
2738 Vfeatures = Qnil;
2739
bdd8d692
RS
2740 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
2741 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
1eb569c5 2742This applies to y-or-n and yes-or-no questions asked by commands\n\
bdd8d692
RS
2743invoked by mouse clicks and mouse menu items.");
2744 use_dialog_box = 1;
2745
7b863bd5
JB
2746 defsubr (&Sidentity);
2747 defsubr (&Srandom);
2748 defsubr (&Slength);
5a30fab8 2749 defsubr (&Ssafe_length);
026f59ce 2750 defsubr (&Sstring_bytes);
7b863bd5 2751 defsubr (&Sstring_equal);
0e1e9f8d 2752 defsubr (&Scompare_strings);
7b863bd5
JB
2753 defsubr (&Sstring_lessp);
2754 defsubr (&Sappend);
2755 defsubr (&Sconcat);
2756 defsubr (&Svconcat);
2757 defsubr (&Scopy_sequence);
09ab3c3b
KH
2758 defsubr (&Sstring_make_multibyte);
2759 defsubr (&Sstring_make_unibyte);
6d475204
RS
2760 defsubr (&Sstring_as_multibyte);
2761 defsubr (&Sstring_as_unibyte);
7b863bd5
JB
2762 defsubr (&Scopy_alist);
2763 defsubr (&Ssubstring);
2764 defsubr (&Snthcdr);
2765 defsubr (&Snth);
2766 defsubr (&Selt);
2767 defsubr (&Smember);
2768 defsubr (&Smemq);
2769 defsubr (&Sassq);
2770 defsubr (&Sassoc);
2771 defsubr (&Srassq);
0fb5a19c 2772 defsubr (&Srassoc);
7b863bd5 2773 defsubr (&Sdelq);
ca8dd546 2774 defsubr (&Sdelete);
7b863bd5
JB
2775 defsubr (&Snreverse);
2776 defsubr (&Sreverse);
2777 defsubr (&Ssort);
be9d483d 2778 defsubr (&Splist_get);
7b863bd5 2779 defsubr (&Sget);
be9d483d 2780 defsubr (&Splist_put);
7b863bd5
JB
2781 defsubr (&Sput);
2782 defsubr (&Sequal);
2783 defsubr (&Sfillarray);
999de246 2784 defsubr (&Schar_table_subtype);
e03f7933
RS
2785 defsubr (&Schar_table_parent);
2786 defsubr (&Sset_char_table_parent);
2787 defsubr (&Schar_table_extra_slot);
2788 defsubr (&Sset_char_table_extra_slot);
999de246 2789 defsubr (&Schar_table_range);
e03f7933 2790 defsubr (&Sset_char_table_range);
e1335ba2 2791 defsubr (&Sset_char_table_default);
e03f7933 2792 defsubr (&Smap_char_table);
7b863bd5
JB
2793 defsubr (&Snconc);
2794 defsubr (&Smapcar);
2795 defsubr (&Smapconcat);
2796 defsubr (&Sy_or_n_p);
2797 defsubr (&Syes_or_no_p);
2798 defsubr (&Sload_average);
2799 defsubr (&Sfeaturep);
2800 defsubr (&Srequire);
2801 defsubr (&Sprovide);
b4f334f7
KH
2802 defsubr (&Swidget_plist_member);
2803 defsubr (&Swidget_put);
2804 defsubr (&Swidget_get);
2805 defsubr (&Swidget_apply);
7b863bd5 2806}