@@ -33,51 +33,61 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33
33
enum case_action {CASE_UP , CASE_DOWN , CASE_CAPITALIZE , CASE_CAPITALIZE_UP };
34
34
35
35
/* State for casing individual characters. */
36
- struct casing_context {
36
+ struct casing_context
37
+ {
37
38
/* A char-table with title-case character mappings or nil. Non-nil implies
38
39
flag is CASE_CAPITALIZE or CASE_CAPITALIZE_UP. */
39
40
Lisp_Object titlecase_char_table ;
41
+
40
42
/* The unconditional special-casing Unicode property char tables for upper
41
- casing, lower casing and title casing respectively. */
43
+ casing, lower casing and title casing respectively. */
42
44
Lisp_Object specialcase_char_tables [3 ];
43
- /* User-requested action. */
45
+
46
+ /* User-requested action. */
44
47
enum case_action flag ;
45
- /* If true, function operates on a buffer as opposed to a string or character.
46
- When run on a buffer, syntax_prefix_flag_p is taken into account when
47
- determined inword flag. */
48
+
49
+ /* If true, the function operates on a buffer as opposed to a string
50
+ or character. When run on a buffer, syntax_prefix_flag_p is
51
+ taken into account when determining whether the context is within
52
+ a word. */
48
53
bool inbuffer ;
49
- /* Whether we are inside of a word. */
54
+
55
+ /* Whether the context is within a word. */
50
56
bool inword ;
51
57
};
52
58
53
- /* Initialise CTX structure for casing characters. */
59
+ /* Initialize CTX structure for casing characters. */
54
60
static void
55
61
prepare_casing_context (struct casing_context * ctx ,
56
62
enum case_action flag , bool inbuffer )
57
63
{
58
64
ctx -> flag = flag ;
59
65
ctx -> inbuffer = inbuffer ;
60
66
ctx -> inword = false;
61
- ctx -> titlecase_char_table = (int )flag < (int )CASE_CAPITALIZE ? Qnil :
62
- uniprop_table (intern_c_string ("titlecase" ));
63
- ctx -> specialcase_char_tables [CASE_UP ] = flag == CASE_DOWN ? Qnil :
64
- uniprop_table (intern_c_string ("special-uppercase" ));
65
- ctx -> specialcase_char_tables [CASE_DOWN ] = flag == CASE_UP ? Qnil :
66
- uniprop_table (intern_c_string ("special-lowercase" ));
67
- ctx -> specialcase_char_tables [CASE_CAPITALIZE ] =
68
- (int )flag < (int )CASE_CAPITALIZE ? Qnil :
69
- uniprop_table (intern_c_string ("special-titlecase" ));
67
+ ctx -> titlecase_char_table
68
+ = (flag < CASE_CAPITALIZE ? Qnil
69
+ : uniprop_table (intern_c_string ("titlecase" )));
70
+ ctx -> specialcase_char_tables [CASE_UP ]
71
+ = (flag == CASE_DOWN ? Qnil
72
+ : uniprop_table (intern_c_string ("special-uppercase" )));
73
+ ctx -> specialcase_char_tables [CASE_DOWN ]
74
+ = (flag == CASE_UP ? Qnil
75
+ : uniprop_table (intern_c_string ("special-lowercase" )));
76
+ ctx -> specialcase_char_tables [CASE_CAPITALIZE ]
77
+ = (flag < CASE_CAPITALIZE ? Qnil
78
+ : uniprop_table (intern_c_string ("special-titlecase" )));
70
79
71
80
/* If the case table is flagged as modified, rescan it. */
72
81
if (NILP (XCHAR_TABLE (BVAR (current_buffer , downcase_table ))-> extras [1 ]))
73
82
Fset_case_table (BVAR (current_buffer , downcase_table ));
74
83
75
- if (inbuffer && ( int ) flag >= ( int ) CASE_CAPITALIZE )
84
+ if (inbuffer && flag >= CASE_CAPITALIZE )
76
85
SETUP_BUFFER_SYNTAX_TABLE (); /* For syntax_prefix_flag_p. */
77
86
}
78
87
79
- struct casing_str_buf {
80
- unsigned char data [MAX_MULTIBYTE_LENGTH > 6 ? MAX_MULTIBYTE_LENGTH : 6 ];
88
+ struct casing_str_buf
89
+ {
90
+ unsigned char data [max (6 , MAX_MULTIBYTE_LENGTH )];
81
91
unsigned char len_chars ;
82
92
unsigned char len_bytes ;
83
93
};
@@ -87,24 +97,23 @@ struct casing_str_buf {
87
97
character has been changed.
88
98
89
99
Since meaning of return value depends on arguments, it’s more convenient to
90
- use case_single_character or case_character instead. */
100
+ use case_single_character or case_character instead. */
91
101
static int
92
102
case_character_impl (struct casing_str_buf * buf ,
93
103
struct casing_context * ctx , int ch )
94
104
{
95
105
enum case_action flag ;
96
106
Lisp_Object prop ;
97
- bool was_inword ;
98
107
int cased ;
99
108
100
109
/* Update inword state */
101
- was_inword = ctx -> inword ;
110
+ bool was_inword = ctx -> inword ;
102
111
ctx -> inword = SYNTAX (ch ) == Sword &&
103
112
(!ctx -> inbuffer || was_inword || !syntax_prefix_flag_p (ch ));
104
113
105
- /* Normalise flag so its one of CASE_UP, CASE_DOWN or CASE_CAPITALIZE. */
114
+ /* Normalize flag so its one of CASE_UP, CASE_DOWN or CASE_CAPITALIZE. */
106
115
if (ctx -> flag == CASE_CAPITALIZE )
107
- flag = ( enum case_action )(( int ) ctx -> flag - was_inword ) ;
116
+ flag = ctx -> flag - was_inword ;
108
117
else if (ctx -> flag != CASE_CAPITALIZE_UP )
109
118
flag = ctx -> flag ;
110
119
else if (!was_inword )
@@ -115,33 +124,34 @@ case_character_impl (struct casing_str_buf *buf,
115
124
goto done ;
116
125
}
117
126
118
- /* Look through the special casing entries. */
119
- if (buf && !NILP (ctx -> specialcase_char_tables [(int )flag ]))
127
+ /* Look through the special casing entries. */
128
+ if (buf && !NILP (ctx -> specialcase_char_tables [(int )flag ]))
120
129
{
121
- prop = CHAR_TABLE_REF (ctx -> specialcase_char_tables [(int )flag ], ch );
122
- if (STRINGP (prop ))
130
+ prop = CHAR_TABLE_REF (ctx -> specialcase_char_tables [(int )flag ], ch );
131
+ if (STRINGP (prop ))
123
132
{
124
- struct Lisp_String * str = XSTRING (prop );
125
- if (STRING_BYTES (str ) <= sizeof buf -> data )
133
+ struct Lisp_String * str = XSTRING (prop );
134
+ if (STRING_BYTES (str ) <= sizeof buf -> data )
126
135
{
127
136
buf -> len_chars = str -> size ;
128
- buf -> len_bytes = STRING_BYTES (str );
129
- memcpy (buf -> data , str -> data , buf -> len_bytes );
137
+ buf -> len_bytes = STRING_BYTES (str );
138
+ memcpy (buf -> data , str -> data , buf -> len_bytes );
130
139
return 1 ;
131
140
}
132
141
}
133
142
}
134
143
135
- /* Handle simple, one-to-one case. */
144
+ /* Handle simple, one-to-one case. */
136
145
if (flag == CASE_DOWN )
137
146
cased = downcase (ch );
138
- else if (!NILP (ctx -> titlecase_char_table ) &&
139
- CHARACTERP (prop = CHAR_TABLE_REF (ctx -> titlecase_char_table , ch )))
147
+ else if (!NILP (ctx -> titlecase_char_table )
148
+ && CHARACTERP (prop
149
+ = CHAR_TABLE_REF (ctx -> titlecase_char_table , ch )))
140
150
cased = XFASTINT (prop );
141
151
else
142
- cased = upcase (ch );
152
+ cased = upcase (ch );
143
153
144
- /* And we’re done. */
154
+ /* And we’re done. */
145
155
done :
146
156
if (!buf )
147
157
return cased ;
@@ -155,18 +165,17 @@ case_character_impl (struct casing_str_buf *buf,
155
165
casing.
156
166
157
167
The rule does not conflict with any other casing rules so while it is
158
- a conditional one, it is independent on language. */
168
+ a conditional one, it is independent of language. */
159
169
160
- #define CAPITAL_SIGMA 0x03A3
161
- #define SMALL_SIGMA 0x03C3
162
- #define SMALL_FINAL_SIGMA 0x03C2
170
+ enum { GREEK_CAPITAL_LETTER_SIGMA = 0x03A }; /* Σ */
171
+ enum { GREEK_SMALL_LETTER_FINAL_SIGMA = 0x03C2 }; /* ς */
163
172
164
173
/* Based on CTX, case character CH accordingly. Update CTX as necessary.
165
174
Return cased character.
166
175
167
176
Special casing rules (such as upcase(fi) = FI) are not handled. For
168
177
characters whose casing results in multiple code points, the character is
169
- returned unchanged. */
178
+ returned unchanged. */
170
179
static inline int
171
180
case_single_character (struct casing_context * ctx , int ch )
172
181
{
@@ -181,23 +190,21 @@ case_single_character (struct casing_context *ctx, int ch)
181
190
apply some rules which depend on proceeding state.
182
191
183
192
This is like case_single_character but also handles one-to-many casing
184
- rules. */
193
+ rules. */
185
194
static bool
186
195
case_character (struct casing_str_buf * buf , struct casing_context * ctx ,
187
196
int ch , const unsigned char * next )
188
197
{
189
- bool changed , was_inword ;
190
-
191
- was_inword = ctx -> inword ;
192
- changed = case_character_impl (buf , ctx , ch );
198
+ bool was_inword = ctx -> inword ;
199
+ bool changed = case_character_impl (buf , ctx , ch );
193
200
194
201
/* If we have just down-cased a capital sigma and the next character no longer
195
202
has a word syntax (i.e. current character is end of word), use final
196
- sigma. */
197
- if (was_inword && ch == CAPITAL_SIGMA && changed &&
198
- (!next || SYNTAX (STRING_CHAR (next )) != Sword ))
203
+ sigma. */
204
+ if (was_inword && ch == GREEK_CAPITAL_LETTER_SIGMA && changed
205
+ && (!next || SYNTAX (STRING_CHAR (next )) != Sword ))
199
206
{
200
- buf -> len_bytes = CHAR_STRING (SMALL_FINAL_SIGMA , buf -> data );
207
+ buf -> len_bytes = CHAR_STRING (GREEK_SMALL_LETTER_FINAL_SIGMA , buf -> data );
201
208
buf -> len_chars = 1 ;
202
209
}
203
210
@@ -209,63 +216,64 @@ do_casify_natnum (struct casing_context *ctx, Lisp_Object obj)
209
216
{
210
217
int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
211
218
| CHAR_SHIFT | CHAR_CTL | CHAR_META );
212
- int flags , ch = XFASTINT (obj ), cased ;
213
- bool multibyte ;
219
+ int ch = XFASTINT (obj );
214
220
215
221
/* If the character has higher bits set above the flags, return it unchanged.
216
222
It is not a real character. */
217
223
if (UNSIGNED_CMP (ch , > , flagbits ))
218
224
return obj ;
219
225
220
- flags = ch & flagbits ;
226
+ int flags = ch & flagbits ;
221
227
ch = ch & ~flagbits ;
222
228
223
229
/* FIXME: Even if enable-multibyte-characters is nil, we may manipulate
224
230
multibyte chars. This means we have a bug for latin-1 chars since when we
225
231
receive an int 128-255 we can't tell whether it's an eight-bit byte or
226
232
a latin-1 char. */
227
- multibyte = ch >= 256
228
- || !NILP (BVAR (current_buffer , enable_multibyte_characters ));
233
+ bool multibyte = (ch >= 256
234
+ || !NILP (BVAR (current_buffer ,
235
+ enable_multibyte_characters )));
229
236
if (! multibyte )
230
237
MAKE_CHAR_MULTIBYTE (ch );
231
- cased = case_single_character (ctx , ch );
238
+ int cased = case_single_character (ctx , ch );
232
239
if (cased == ch )
233
240
return obj ;
234
241
235
242
if (! multibyte )
236
243
MAKE_CHAR_UNIBYTE (cased );
237
- XSETFASTINT (obj , cased | flags );
238
- return obj ;
244
+ return make_natnum (cased | flags );
239
245
}
240
246
241
247
static Lisp_Object
242
248
do_casify_multibyte_string (struct casing_context * ctx , Lisp_Object obj )
243
249
{
244
- /* We assume data is the first member of casing_str_buf structure so that if
245
- we cast a (char *) into (struct casing_str_buf *) the representation of the
246
- character is at the beginning of the buffer. This is why we don’t need
247
- separate struct casing_str_buf object but rather write directly to o. */
248
- typedef char static_assertion [offsetof(struct casing_str_buf , data ) ? -1 : 1 ];
250
+ /* Verify that ‘data’ is the first member of struct casing_str_buf
251
+ so that when casting char * to struct casing_str_buf *, the
252
+ representation of the character is at the beginning of the
253
+ buffer. This is why we don’t need a separate struct
254
+ casing_str_buf object, and can write directly to the destination. */
255
+ verify (offsetof (struct casing_str_buf , data ) == 0 );
249
256
250
257
ptrdiff_t size = SCHARS (obj ), n ;
251
- int ch ;
252
258
USE_SAFE_ALLOCA ;
253
- if (INT_MULTIPLY_WRAPV (size , MAX_MULTIBYTE_LENGTH , & n ) ||
254
- INT_ADD_WRAPV (n , sizeof (struct casing_str_buf ), & n ))
259
+ if (INT_MULTIPLY_WRAPV (size , MAX_MULTIBYTE_LENGTH , & n )
260
+ || INT_ADD_WRAPV (n , sizeof (struct casing_str_buf ), & n ))
255
261
n = PTRDIFF_MAX ;
256
- unsigned char * const dst = SAFE_ALLOCA (n ), * const dst_end = dst + n ;
262
+ unsigned char * dst = SAFE_ALLOCA (n );
263
+ unsigned char * dst_end = dst + n ;
257
264
unsigned char * o = dst ;
258
265
259
266
const unsigned char * src = SDATA (obj );
260
267
261
268
for (n = 0 ; size ; -- size )
262
269
{
263
- if (dst_end - o < sizeof (struct casing_str_buf ))
270
+ if (dst_end - o < sizeof (struct casing_str_buf ))
264
271
string_overflow ();
265
- ch = STRING_CHAR_ADVANCE (src );
266
- case_character ((void * )o , ctx , ch , size > 1 ? src : NULL );
267
- n += ((struct casing_str_buf * )o )-> len_chars ;
268
- o += ((struct casing_str_buf * )o )-> len_bytes ;
272
+ int ch = STRING_CHAR_ADVANCE (src );
273
+ case_character ((struct casing_str_buf * ) o , ctx , ch ,
274
+ size > 1 ? src : NULL );
275
+ n += ((struct casing_str_buf * ) o )-> len_chars ;
276
+ o += ((struct casing_str_buf * ) o )-> len_bytes ;
269
277
}
270
278
eassert (o <= dst_end );
271
279
obj = make_multibyte_string ((char * ) dst , n , o - dst );
@@ -288,7 +296,8 @@ do_casify_unibyte_string (struct casing_context *ctx, Lisp_Object obj)
288
296
if (ch == cased )
289
297
continue ;
290
298
MAKE_CHAR_UNIBYTE (cased );
291
- /* If the char can't be converted to a valid byte, just don't change it */
299
+ /* If the char can't be converted to a valid byte, just don't
300
+ change it. */
292
301
if (cased >= 0 && cased < 256 )
293
302
SSET (obj , i , cased );
294
303
}
@@ -369,21 +378,20 @@ cased, e.g. fi, are returned unchanged. */)
369
378
*ENDP unspecified.
370
379
371
380
Always return 0. This is so that interface of this function is the same as
372
- do_casify_multibyte_region. */
381
+ do_casify_multibyte_region. */
373
382
static ptrdiff_t
374
383
do_casify_unibyte_region (struct casing_context * ctx ,
375
384
ptrdiff_t * startp , ptrdiff_t * endp )
376
385
{
377
- ptrdiff_t first = -1 , last = -1 ; /* Position of first and last changes. */
378
- ptrdiff_t pos = * startp , end = * endp ;
379
- int ch , cased ;
386
+ ptrdiff_t first = -1 , last = -1 ; /* Position of first and last changes. */
387
+ ptrdiff_t end = * endp ;
380
388
381
- for (; pos < end ; ++ pos )
389
+ for (ptrdiff_t pos = * startp ; pos < end ; ++ pos )
382
390
{
383
- ch = FETCH_BYTE (pos );
391
+ int ch = FETCH_BYTE (pos );
384
392
MAKE_CHAR_MULTIBYTE (ch );
385
393
386
- cased = case_single_character (ctx , ch );
394
+ int cased = case_single_character (ctx , ch );
387
395
if (cased == ch )
388
396
continue ;
389
397
@@ -405,26 +413,22 @@ do_casify_unibyte_region (struct casing_context *ctx,
405
413
Return number of added characters (may be negative if more characters were
406
414
deleted then inserted), save first and last positions that has changed in
407
415
*STARTP and *ENDP respectively. If no characters were changed, return 0,
408
- save -1 to *STARTP and leave *ENDP unspecified. */
416
+ save -1 to *STARTP and leave *ENDP unspecified. */
409
417
static ptrdiff_t
410
418
do_casify_multibyte_region (struct casing_context * ctx ,
411
419
ptrdiff_t * startp , ptrdiff_t * endp )
412
420
{
413
- ptrdiff_t first = -1 , last = -1 ; /* Position of first and last changes. */
421
+ ptrdiff_t first = -1 , last = -1 ; /* Position of first and last changes. */
414
422
ptrdiff_t pos = * startp , pos_byte = CHAR_TO_BYTE (pos ), size = * endp - pos ;
415
423
ptrdiff_t opoint = PT , added = 0 ;
416
- struct casing_str_buf buf ;
417
- bool changed ;
418
- int ch , len ;
419
424
420
425
for (; size ; -- size )
421
426
{
422
- ch = STRING_CHAR_AND_LENGTH (BYTE_POS_ADDR (pos_byte ), len );
423
- changed = case_character (
424
- & buf , ctx , ch ,
425
- size > 1 ? BYTE_POS_ADDR (pos_byte + len ) : NULL );
426
-
427
- if (!changed )
427
+ int len ;
428
+ int ch = STRING_CHAR_AND_LENGTH (BYTE_POS_ADDR (pos_byte ), len );
429
+ struct casing_str_buf buf ;
430
+ if (!case_character (& buf , ctx , ch ,
431
+ size > 1 ? BYTE_POS_ADDR (pos_byte + len ) : NULL ))
428
432
{
429
433
pos_byte += len ;
430
434
++ pos ;
@@ -468,19 +472,19 @@ do_casify_multibyte_region (struct casing_context *ctx,
468
472
static ptrdiff_t
469
473
casify_region (enum case_action flag , Lisp_Object b , Lisp_Object e )
470
474
{
471
- ptrdiff_t start , end , orig_end , added ;
475
+ ptrdiff_t added ;
472
476
struct casing_context ctx ;
473
477
474
478
validate_region (& b , & e );
475
- start = XFASTINT (b );
476
- end = XFASTINT (e );
479
+ ptrdiff_t start = XFASTINT (b );
480
+ ptrdiff_t end = XFASTINT (e );
477
481
if (start == end )
478
- /* Not modifying because nothing marked */
482
+ /* Not modifying because nothing marked. */
479
483
return end ;
480
484
modify_text (start , end );
481
485
prepare_casing_context (& ctx , flag , true);
482
486
483
- orig_end = end ;
487
+ ptrdiff_t orig_end = end ;
484
488
record_delete (start , make_buffer_string (start , end , true), false);
485
489
if (NILP (BVAR (current_buffer , enable_multibyte_characters )))
486
490
{
0 commit comments