(syms_of_ntproc) <w32-get-true-file-attributes>: Doc fix.
[bpt/emacs.git] / src / casetab.c
CommitLineData
dcfdbac7 1/* GNU Emacs routines to deal with case tables.
429ab54e 2 Copyright (C) 1993, 1994, 2001, 2002, 2003, 2004,
8cabe764 3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
dcfdbac7
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
684d6f5b 9the Free Software Foundation; either version 3, or (at your option)
dcfdbac7
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
dcfdbac7 21
48bbe3a8 22/* Written by Howard Gayle. */
dcfdbac7 23
18160b98 24#include <config.h>
dcfdbac7
JB
25#include "lisp.h"
26#include "buffer.h"
e961d439 27#include "character.h"
dcfdbac7 28
7f7fef04 29Lisp_Object Qcase_table_p, Qcase_table;
dcfdbac7
JB
30Lisp_Object Vascii_downcase_table, Vascii_upcase_table;
31Lisp_Object Vascii_canon_table, Vascii_eqv_table;
32
da2795b2
KH
33/* Used as a temporary in DOWNCASE and other macros in lisp.h. No
34 need to mark it, since it is used only very temporarily. */
2e34157c
RS
35int case_temp1;
36Lisp_Object case_temp2;
da2795b2
KH
37
38static void set_canon ();
39static void set_identity ();
40static void shuffle ();
dcfdbac7
JB
41
42DEFUN ("case-table-p", Fcase_table_p, Scase_table_p, 1, 1, 0,
e0f24100 43 doc: /* Return t if OBJECT is a case table.
fdb82f93
PJ
44See `set-case-table' for more information on these data structures. */)
45 (object)
2858a1c1 46 Lisp_Object object;
dcfdbac7 47{
4b3bd052 48 Lisp_Object up, canon, eqv;
dcfdbac7 49
2858a1c1 50 if (! CHAR_TABLE_P (object))
7f7fef04 51 return Qnil;
2858a1c1 52 if (! EQ (XCHAR_TABLE (object)->purpose, Qcase_table))
7f7fef04 53 return Qnil;
dcfdbac7 54
2858a1c1
EN
55 up = XCHAR_TABLE (object)->extras[0];
56 canon = XCHAR_TABLE (object)->extras[1];
57 eqv = XCHAR_TABLE (object)->extras[2];
7f7fef04
RS
58
59 return ((NILP (up) || CHAR_TABLE_P (up))
d427b66a 60 && ((NILP (canon) && NILP (eqv))
7f7fef04
RS
61 || (CHAR_TABLE_P (canon)
62 && (NILP (eqv) || CHAR_TABLE_P (eqv))))
dcfdbac7
JB
63 ? Qt : Qnil);
64}
65
66static Lisp_Object
67check_case_table (obj)
68 Lisp_Object obj;
69{
a5f07f6d 70 CHECK_TYPE (!NILP (Fcase_table_p (obj)), Qcase_table_p, obj);
dcfdbac7 71 return (obj);
177c0ea7 72}
dcfdbac7
JB
73
74DEFUN ("current-case-table", Fcurrent_case_table, Scurrent_case_table, 0, 0, 0,
fdb82f93
PJ
75 doc: /* Return the case table of the current buffer. */)
76 ()
dcfdbac7 77{
7f7fef04 78 return current_buffer->downcase_table;
dcfdbac7
JB
79}
80
a1de6b4b 81DEFUN ("standard-case-table", Fstandard_case_table, Sstandard_case_table, 0, 0, 0,
fdb82f93
PJ
82 doc: /* Return the standard case table.
83This is the one used for new buffers. */)
84 ()
dcfdbac7 85{
7f7fef04 86 return Vascii_downcase_table;
dcfdbac7
JB
87}
88
d9da9451
JB
89static Lisp_Object set_case_table ();
90
dcfdbac7 91DEFUN ("set-case-table", Fset_case_table, Sset_case_table, 1, 1, 0,
fdb82f93
PJ
92 doc: /* Select a new case table for the current buffer.
93A case table is a char-table which maps characters
94to their lower-case equivalents. It also has three \"extra\" slots
95which may be additional char-tables or nil.
96These slots are called UPCASE, CANONICALIZE and EQUIVALENCES.
f6a18aa2
RS
97UPCASE maps each non-upper-case character to its upper-case equivalent.
98 (The value in UPCASE for an upper-case character is never used.)
99 If lower and upper case characters are in 1-1 correspondence,
fdb82f93
PJ
100 you may use nil and the upcase table will be deduced from DOWNCASE.
101CANONICALIZE maps each character to a canonical equivalent;
102 any two characters that are related by case-conversion have the same
103 canonical equivalent character; it may be nil, in which case it is
104 deduced from DOWNCASE and UPCASE.
105EQUIVALENCES is a map that cyclicly permutes each equivalence class
106 (of characters with the same canonical equivalent); it may be nil,
107 in which case it is deduced from CANONICALIZE. */)
108 (table)
dcfdbac7
JB
109 Lisp_Object table;
110{
d9da9451 111 return set_case_table (table, 0);
dcfdbac7
JB
112}
113
a1de6b4b 114DEFUN ("set-standard-case-table", Fset_standard_case_table, Sset_standard_case_table, 1, 1, 0,
fdb82f93
PJ
115 doc: /* Select a new standard case table for new buffers.
116See `set-case-table' for more info on case tables. */)
117 (table)
dcfdbac7
JB
118 Lisp_Object table;
119{
d9da9451 120 return set_case_table (table, 1);
dcfdbac7
JB
121}
122
d9da9451 123static Lisp_Object
dcfdbac7
JB
124set_case_table (table, standard)
125 Lisp_Object table;
126 int standard;
127{
4b3bd052 128 Lisp_Object up, canon, eqv;
dcfdbac7
JB
129
130 check_case_table (table);
131
7f7fef04
RS
132 up = XCHAR_TABLE (table)->extras[0];
133 canon = XCHAR_TABLE (table)->extras[1];
134 eqv = XCHAR_TABLE (table)->extras[2];
dcfdbac7 135
d427b66a 136 if (NILP (up))
dcfdbac7 137 {
7f7fef04 138 up = Fmake_char_table (Qcase_table, Qnil);
8f924df7
KH
139 map_char_table (set_identity, Qnil, table, up);
140 map_char_table (shuffle, Qnil, table, up);
7f7fef04 141 XCHAR_TABLE (table)->extras[0] = up;
dcfdbac7
JB
142 }
143
d427b66a 144 if (NILP (canon))
dcfdbac7 145 {
4b3bd052 146 canon = Fmake_char_table (Qcase_table, Qnil);
7f7fef04 147 XCHAR_TABLE (table)->extras[1] = canon;
8f924df7 148 map_char_table (set_canon, Qnil, table, table);
5a0fd72f
RS
149 }
150
151 if (NILP (eqv))
152 {
7f7fef04 153 eqv = Fmake_char_table (Qcase_table, Qnil);
8f924df7
KH
154 map_char_table (set_identity, Qnil, canon, eqv);
155 map_char_table (shuffle, Qnil, canon, eqv);
4b3bd052 156 XCHAR_TABLE (table)->extras[2] = eqv;
dcfdbac7
JB
157 }
158
426f6c23
RS
159 /* This is so set_image_of_range_1 in regex.c can find the EQV table. */
160 XCHAR_TABLE (canon)->extras[2] = eqv;
161
dcfdbac7 162 if (standard)
f79609dc
KH
163 {
164 Vascii_downcase_table = table;
165 Vascii_upcase_table = up;
166 Vascii_canon_table = canon;
167 Vascii_eqv_table = eqv;
168 }
dcfdbac7 169 else
6c6fcbf8
RS
170 {
171 current_buffer->downcase_table = table;
172 current_buffer->upcase_table = up;
173 current_buffer->case_canon_table = canon;
174 current_buffer->case_eqv_table = eqv;
175 }
7f7fef04 176
dcfdbac7
JB
177 return table;
178}
179\f
da2795b2
KH
180/* The following functions are called in map_char_table. */
181
8f924df7
KH
182/* Set CANON char-table element for characters in RANGE to a
183 translated ELT by UP and DOWN char-tables. This is done only when
184 ELT is a character. The char-tables CANON, UP, and DOWN are in
185 CASE_TABLE. */
e16696ba 186
c0c15b93 187static void
e961d439
KH
188set_canon (case_table, range, elt)
189 Lisp_Object case_table, range, elt;
c0c15b93 190{
da2795b2
KH
191 Lisp_Object up = XCHAR_TABLE (case_table)->extras[0];
192 Lisp_Object canon = XCHAR_TABLE (case_table)->extras[1];
c0c15b93 193
da2795b2 194 if (NATNUMP (elt))
405b0b5a 195 Fset_char_table_range (canon, range, Faref (case_table, Faref (up, elt)));
c0c15b93 196}
dcfdbac7 197
8f924df7
KH
198/* Set elements of char-table TABLE for C to C itself. C may be a
199 cons specifying a character range. In that case, set characters in
200 that range to themselves. This is done only when ELT is a
201 character. This is called in map_char_table. */
e16696ba 202
7f7fef04 203static void
da2795b2
KH
204set_identity (table, c, elt)
205 Lisp_Object table, c, elt;
dcfdbac7 206{
da2795b2 207 if (NATNUMP (elt))
e961d439 208 {
8f924df7
KH
209 int from, to;
210
211 if (CONSP (c))
e961d439 212 {
8f924df7
KH
213 from = XINT (XCAR (c));
214 to = XINT (XCDR (c));
e961d439
KH
215 }
216 else
8f924df7 217 from = to = XINT (c);
e961d439 218 for (; from <= to; from++)
405b0b5a 219 CHAR_TABLE_SET (table, from, make_number (from));
e961d439 220 }
dcfdbac7 221}
c0c15b93 222
da2795b2
KH
223/* Permute the elements of TABLE (which is initially an identity
224 mapping) so that it has one cycle for each equivalence class
225 induced by the translation table on which map_char_table is
226 operated. */
c0c15b93
KH
227
228static void
da2795b2
KH
229shuffle (table, c, elt)
230 Lisp_Object table, c, elt;
c0c15b93 231{
e961d439 232 if (NATNUMP (elt))
da2795b2
KH
233 {
234 Lisp_Object tem = Faref (table, elt);
8f924df7 235 int from, to;
e961d439 236
8f924df7 237 if (CONSP (c))
e961d439 238 {
8f924df7
KH
239 from = XINT (XCAR (c));
240 to = XINT (XCDR (c));
e961d439
KH
241 }
242 else
8f924df7 243 from = to = XINT (c);
e961d439
KH
244
245 for (; from <= to; from++)
246 if (from != XINT (elt))
247 {
e961d439
KH
248 Faset (table, elt, make_number (from));
249 Faset (table, make_number (from), tem);
250 }
da2795b2 251 }
c0c15b93 252}
dcfdbac7 253\f
dfcf069d 254void
dcfdbac7
JB
255init_casetab_once ()
256{
257 register int i;
7f7fef04
RS
258 Lisp_Object down, up;
259 Qcase_table = intern ("case-table");
260 staticpro (&Qcase_table);
261
262 /* Intern this now in case it isn't already done.
263 Setting this variable twice is harmless.
264 But don't staticpro it here--that is done in alloc.c. */
265 Qchar_table_extra_slots = intern ("char-table-extra-slots");
dcfdbac7 266
7f7fef04
RS
267 /* Now we are ready to set up this property, so we can
268 create char tables. */
4b3bd052 269 Fput (Qcase_table, Qchar_table_extra_slots, make_number (3));
7f7fef04
RS
270
271 down = Fmake_char_table (Qcase_table, Qnil);
272 Vascii_downcase_table = down;
e1b490ca 273 XCHAR_TABLE (down)->purpose = Qcase_table;
dcfdbac7 274
e961d439 275 for (i = 0; i < 128; i++)
8f924df7
KH
276 {
277 int c = (i >= 'A' && i <= 'Z') ? i + ('a' - 'A') : i;
278 CHAR_TABLE_SET (down, i, make_number (c));
279 }
7f7fef04
RS
280
281 XCHAR_TABLE (down)->extras[1] = Fcopy_sequence (down);
dcfdbac7 282
7f7fef04
RS
283 up = Fmake_char_table (Qcase_table, Qnil);
284 XCHAR_TABLE (down)->extras[0] = up;
dcfdbac7 285
e961d439 286 for (i = 0; i < 128; i++)
8f924df7
KH
287 {
288 int c = ((i >= 'A' && i <= 'Z') ? i + ('a' - 'A')
289 : ((i >= 'a' && i <= 'z') ? i + ('A' - 'a')
290 : i));;
291 CHAR_TABLE_SET (up, i, make_number (c));
292 }
7f7fef04
RS
293
294 XCHAR_TABLE (down)->extras[2] = Fcopy_sequence (up);
66aa138d
RS
295
296 /* Fill in what isn't filled in. */
297 set_case_table (down, 1);
dcfdbac7
JB
298}
299
dfcf069d 300void
dcfdbac7
JB
301syms_of_casetab ()
302{
303 Qcase_table_p = intern ("case-table-p");
304 staticpro (&Qcase_table_p);
7f7fef04 305
8f84b1a1 306 staticpro (&Vascii_canon_table);
dcfdbac7 307 staticpro (&Vascii_downcase_table);
8f84b1a1
EN
308 staticpro (&Vascii_eqv_table);
309 staticpro (&Vascii_upcase_table);
dcfdbac7
JB
310
311 defsubr (&Scase_table_p);
312 defsubr (&Scurrent_case_table);
313 defsubr (&Sstandard_case_table);
314 defsubr (&Sset_case_table);
315 defsubr (&Sset_standard_case_table);
dcfdbac7 316}
6b61353c
KH
317
318/* arch-tag: e06388ad-99fe-40ec-ba67-9d010fcc4916
319 (do not change this comment) */