@@ -231,102 +231,115 @@ The argument object is not altered--the value is a copy. */)
231
231
return casify_object (CASE_CAPITALIZE_UP , obj );
232
232
}
233
233
234
- /* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP.
235
- b and e specify range of buffer to operate on. */
236
-
237
- static void
238
- casify_region (enum case_action flag , Lisp_Object b , Lisp_Object e )
234
+ /* Based on CTX, case region in a unibyte buffer from POS to *ENDP. Return
235
+ first position that has changed and save last position in *ENDP. If no
236
+ characters were changed, return -1 and *ENDP is unspecified. */
237
+ static ptrdiff_t
238
+ do_casify_unibyte_region (struct casing_context * ctx ,
239
+ ptrdiff_t pos , ptrdiff_t * endp )
239
240
{
240
- bool multibyte = ! NILP ( BVAR ( current_buffer , enable_multibyte_characters ));
241
- ptrdiff_t start , end ;
242
- ptrdiff_t start_byte ;
241
+ ptrdiff_t first = -1 , last = -1 ; /* Position of first and last changes. */
242
+ ptrdiff_t end = * endp ;
243
+ int ch , cased ;
243
244
244
- /* Position of first and last changes. */
245
- ptrdiff_t first = -1 , last ;
245
+ for (; pos < end ; ++ pos )
246
+ {
247
+ ch = FETCH_BYTE (pos );
248
+ MAKE_CHAR_MULTIBYTE (ch );
246
249
247
- ptrdiff_t opoint = PT ;
248
- ptrdiff_t opoint_byte = PT_BYTE ;
250
+ cased = case_character (ctx , ch );
251
+ if (cased == ch )
252
+ continue ;
249
253
250
- struct casing_context ctx ;
254
+ last = pos ;
255
+ if (first < 0 )
256
+ first = pos ;
251
257
252
- if ( EQ ( b , e ))
253
- /* Not modifying because nothing marked */
254
- return ;
258
+ MAKE_CHAR_UNIBYTE ( cased );
259
+ FETCH_BYTE ( pos ) = cased ;
260
+ }
255
261
256
- validate_region (& b , & e );
257
- start = XFASTINT (b );
258
- end = XFASTINT (e );
259
- modify_text (start , end );
260
- record_change (start , end - start );
261
- start_byte = CHAR_TO_BYTE (start );
262
+ * endp = last + 1 ;
263
+ return first ;
264
+ }
262
265
263
- prepare_casing_context (& ctx , flag , true);
266
+ /* Based on CTX, case region in a multibyte buffer from POS to *ENDP. Return
267
+ first position that has changed and save last position in *ENDP. If no
268
+ characters were changed, return -1 and *ENDP is unspecified. */
269
+ static ptrdiff_t
270
+ do_casify_multibyte_region (struct casing_context * ctx ,
271
+ ptrdiff_t pos , ptrdiff_t * endp )
272
+ {
273
+ ptrdiff_t first = -1 , last = -1 ; /* Position of first and last changes. */
274
+ ptrdiff_t pos_byte = CHAR_TO_BYTE (pos ), end = * endp ;
275
+ ptrdiff_t opoint = PT ;
276
+ int ch , cased , len ;
264
277
265
- while (start < end )
278
+ while (pos < end )
266
279
{
267
- int ch , cased , len ;
268
-
269
- if (multibyte )
270
- {
271
- ch = FETCH_MULTIBYTE_CHAR (start_byte );
272
- len = CHAR_BYTES (ch );
273
- }
274
- else
275
- {
276
- ch = FETCH_BYTE (start_byte );
277
- MAKE_CHAR_MULTIBYTE (ch );
278
- len = 1 ;
279
- }
280
- cased = case_character (& ctx , ch );
281
- if (ch != cased )
280
+ ch = STRING_CHAR_AND_LENGTH (BYTE_POS_ADDR (pos_byte ), len );
281
+ cased = case_character (ctx , ch );
282
+ if (cased != ch )
282
283
{
283
- last = start ;
284
+ last = pos ;
284
285
if (first < 0 )
285
- first = start ;
286
+ first = pos ;
286
287
287
- if (! multibyte )
288
- {
289
- MAKE_CHAR_UNIBYTE (cased );
290
- FETCH_BYTE (start_byte ) = cased ;
291
- }
292
- else if (ASCII_CHAR_P (cased ) && ASCII_CHAR_P (ch ))
293
- FETCH_BYTE (start_byte ) = cased ;
288
+ if (ASCII_CHAR_P (cased ) && ASCII_CHAR_P (ch ))
289
+ FETCH_BYTE (pos_byte ) = cased ;
294
290
else
295
291
{
296
- int tolen = CHAR_BYTES (cased );
297
- int j ;
298
292
unsigned char str [MAX_MULTIBYTE_LENGTH ];
299
-
300
- CHAR_STRING (cased , str );
301
- if (len == tolen )
302
- {
303
- /* Length is unchanged. */
304
- for (j = 0 ; j < len ; ++ j )
305
- FETCH_BYTE (start_byte + j ) = str [j ];
306
- }
293
+ int totlen = CHAR_STRING (cased , str );
294
+ if (len == totlen )
295
+ memcpy (BYTE_POS_ADDR (pos_byte ), str , len );
307
296
else
308
- {
309
- /* Replace one character with the other,
310
- keeping text properties the same. */
311
- replace_range_2 (start , start_byte ,
312
- start + 1 , start_byte + len ,
313
- (char * ) str , 1 , tolen ,
314
- 0 );
315
- len = tolen ;
316
- }
297
+ /* Replace one character with the other(s), keeping text
298
+ properties the same. */
299
+ replace_range_2 (pos , pos_byte , pos + 1 , pos_byte + len ,
300
+ (char * ) str , 9 , totlen , 0 );
301
+ len = totlen ;
317
302
}
318
303
}
319
- start ++ ;
320
- start_byte += len ;
304
+ pos ++ ;
305
+ pos_byte += len ;
321
306
}
322
307
323
308
if (PT != opoint )
324
- TEMP_SET_PT_BOTH (opoint , opoint_byte );
309
+ TEMP_SET_PT_BOTH (opoint , CHAR_TO_BYTE (opoint ));
310
+
311
+ * endp = last ;
312
+ return first ;
313
+ }
314
+
315
+ /* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP.
316
+ b and e specify range of buffer to operate on. */
317
+ static void
318
+ casify_region (enum case_action flag , Lisp_Object b , Lisp_Object e )
319
+ {
320
+ struct casing_context ctx ;
321
+ ptrdiff_t start , end ;
322
+
323
+ if (EQ (b , e ))
324
+ /* Not modifying because nothing marked */
325
+ return ;
326
+
327
+ validate_region (& b , & e );
328
+ start = XFASTINT (b );
329
+ end = XFASTINT (e );
330
+ modify_text (start , end );
331
+ record_change (start , end - start );
332
+ prepare_casing_context (& ctx , flag , true);
333
+
334
+ if (NILP (BVAR (current_buffer , enable_multibyte_characters )))
335
+ start = do_casify_unibyte_region (& ctx , start , & end );
336
+ else
337
+ start = do_casify_multibyte_region (& ctx , start , & end );
325
338
326
- if (first >= 0 )
339
+ if (start >= 0 )
327
340
{
328
- signal_after_change (first , last + 1 - first , last + 1 - first );
329
- update_compositions (first , last + 1 , CHECK_ALL );
341
+ signal_after_change (start , end + 1 - start , end + 1 - start );
342
+ update_compositions (start , end + 1 , CHECK_ALL );
330
343
}
331
344
}
332
345
0 commit comments