1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #include <config.h>
23: #include "lisp.h"
24: #include "buffer.h"
25: #include "charset.h"
26: #include "category.h"
27: #include "indent.h"
28: #include "keyboard.h"
29: #include "frame.h"
30: #include "window.h"
31: #include "termchar.h"
32: #include "termopts.h"
33: #include "disptab.h"
34: #include "intervals.h"
35: #include "region-cache.h"
36:
37:
38:
39:
40: int indent_tabs_mode;
41:
42: #define CR 015
43:
44:
45:
46:
47:
48:
49:
50: double last_known_column;
51:
52:
53:
54: int last_known_column_point;
55:
56:
57:
58: int last_known_column_modified;
59:
60: static double current_column_1 P_ ((void));
61: static double position_indentation P_ ((int));
62:
63:
64:
65:
66: int current_column_bol_cache;
67:
68:
69:
70: struct Lisp_Char_Table *
71: buffer_display_table ()
72: {
73: Lisp_Object thisbuf;
74:
75: thisbuf = current_buffer->display_table;
76: if (DISP_TABLE_P (thisbuf))
77: return XCHAR_TABLE (thisbuf);
78: if (DISP_TABLE_P (Vstandard_display_table))
79: return XCHAR_TABLE (Vstandard_display_table);
80: return 0;
81: }
82: ^L
83:
84:
85:
86:
87: static int
88: character_width (c, dp)
89: int c;
90: struct Lisp_Char_Table *dp;
91: {
92: Lisp_Object elt;
93:
94:
95:
96:
97:
98:
99: if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
100: return XVECTOR (elt)->size;
101:
102:
103: if (c == '\n' || c == '\t' || c == '\015')
104: return 0;
105:
106:
107: else if (c >= 040 && c < 0177)
108: return 1;
109:
110:
111:
112:
113:
114:
115: else
116: return 0;
117: }
118:
119:
120:
121:
122:
123: int
124: disptab_matches_widthtab (disptab, widthtab)
125: struct Lisp_Char_Table *disptab;
126: struct Lisp_Vector *widthtab;
127: {
128: int i;
129:
130: if (widthtab->size != 256)
131: abort ();
132:
133: for (i = 0; i < 256; i++)
134: if (character_width (i, disptab)
135: != XFASTINT (widthtab->contents[i]))
136: return 0;
137:
138: return 1;
139: }
140:
141:
142:
143: void
144: recompute_width_table (buf, disptab)
145: struct buffer *buf;
146: struct Lisp_Char_Table *disptab;
147: {
148: int i;
149: struct Lisp_Vector *widthtab;
150:
151: if (!VECTORP (buf->width_table))
152: buf->width_table = Fmake_vector (make_number (256), make_number (0));
153: widthtab = XVECTOR (buf->width_table);
154: if (widthtab->size != 256)
155: abort ();
156:
157: for (i = 0; i < 256; i++)
158: XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
159: }
160:
161:
162:
163:
164: static void
165: width_run_cache_on_off ()
166: {
167: if (NILP (current_buffer->cache_long_line_scans)
168:
169:
170: || !NILP (current_buffer->enable_multibyte_characters))
171: {
172:
173: if (current_buffer->width_run_cache)
174: {
175: free_region_cache (current_buffer->width_run_cache);
176: current_buffer->width_run_cache = 0;
177: current_buffer->width_table = Qnil;
178: }
179: }
180: else
181: {
182:
183: if (current_buffer->width_run_cache == 0)
184: {
185: current_buffer->width_run_cache = new_region_cache ();
186: recompute_width_table (current_buffer, buffer_display_table ());
187: }
188: }
189: }
190:
191: ^L
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215: int
216: skip_invisible (pos, next_boundary_p, to, window)
217: int pos;
218: int *next_boundary_p;
219: int to;
220: Lisp_Object window;
221: {
222: Lisp_Object prop, position, overlay_limit, proplimit;
223: Lisp_Object buffer, tmp;
224: int end, inv_p;
225:
226: XSETFASTINT (position, pos);
227: XSETBUFFER (buffer, current_buffer);
228:
229:
230: recenter_overlay_lists (current_buffer, pos);
231:
232:
233:
234:
235: overlay_limit = Fnext_overlay_change (position);
236:
237:
238: proplimit = Fnext_property_change (position, buffer, Qt);
239: if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
240: proplimit = overlay_limit;
241:
242:
243:
244: if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
245: *next_boundary_p = XFASTINT (proplimit);
246:
247: else
248: {
249:
250: XSETFASTINT (proplimit, min (pos + 100, to));
251:
252: if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
253: proplimit = overlay_limit;
254: tmp = Fnext_single_property_change (position, Qinvisible,
255: buffer, proplimit);
256: end = XFASTINT (tmp);
257: #if 0
258:
259:
260: if (end == pos + 100
261: && !NILP (current_buffer->enable_multibyte_characters)
262: && end < ZV)
263: while (pos < end && !CHAR_HEAD_P (POS_ADDR (end)))
264: end--;
265: #endif
266: *next_boundary_p = end;
267: }
268:
269:
270: prop = Fget_char_property (position, Qinvisible,
271: (!NILP (window)
272: && EQ (XWINDOW (window)->buffer, buffer))
273: ? window : buffer);
274: inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
275:
276: if (NILP (window) ? inv_p == 1 : inv_p)
277: return *next_boundary_p;
278: return pos;
279: }
280: ^L
281:
282:
283:
284:
285: static int
286: check_composition (pos, pos_byte, point, len, len_byte, width)
287: int pos, pos_byte, point;
288: int *len, *len_byte, *width;
289: {
290: Lisp_Object prop;
291: int start, end;
292: int id;
293:
294: if (! find_composition (pos, -1, &start, &end, &prop, Qnil)
295: || pos != start || point < end
296: || !COMPOSITION_VALID_P (start, end, prop))
297: return 0;
298: if ((id = get_composition_id (pos, pos_byte, end - pos, prop, Qnil)) < 0)
299: return 0;
300:
301: *len = COMPOSITION_LENGTH (prop);
302: *len_byte = CHAR_TO_BYTE (end) - pos_byte;
303: *width = composition_table[id]->width;
304: return 1;
305: }
306: ^L
307:
308:
309:
310:
311:
312:
313:
314: #define MULTIBYTE_BYTES_WIDTH(p, dp) \
315: do { \
316: int c; \
317: \
318: wide_column = 0; \
319: c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, bytes); \
320: if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
321: width = bytes * 4; \
322: else \
323: { \
324: if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
325: width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
326: else \
327: width = WIDTH_BY_CHAR_HEAD (*p); \
328: if (width > 1) \
329: wide_column = width; \
330: } \
331: } while (0)
332:
333:
334: DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
335: doc:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345: )
346: ()
347: {
348: Lisp_Object temp;
349: XSETFASTINT (temp, (int) current_column ());
350: return temp;
351: }
352:
353:
354:
355: void
356: invalidate_current_column ()
357: {
358: last_known_column_point = 0;
359: }
360:
361: double
362: current_column ()
363: {
364: register int col;
365: register unsigned char *ptr, *stop;
366: register int tab_seen;
367: int post_tab;
368: register int c;
369: register int tab_width = XINT (current_buffer->tab_width);
370: int ctl_arrow = !NILP (current_buffer->ctl_arrow);
371: register struct Lisp_Char_Table *dp = buffer_display_table ();
372:
373: if (PT == last_known_column_point
374: && MODIFF == last_known_column_modified)
375: return last_known_column;
376:
377:
378:
379: if (BUF_INTERVALS (current_buffer)
380: || current_buffer->overlays_before
381: || current_buffer->overlays_after
382: || Z != Z_BYTE)
383: return current_column_1 ();
384:
385:
386:
387:
388:
389: ptr = BYTE_POS_ADDR (PT_BYTE - 1) + 1;
390:
391:
392: if (PT == BEGV)
393: stop = ptr;
394: else if (PT <= GPT || BEGV > GPT)
395: stop = BEGV_ADDR;
396: else
397: stop = GAP_END_ADDR;
398:
399: if (tab_width <= 0 || tab_width > 1000)
400: tab_width = 8;
401:
402: col = 0, tab_seen = 0, post_tab = 0;
403:
404: while (1)
405: {
406: EMACS_INT i, n;
407: Lisp_Object charvec;
408:
409: if (ptr == stop)
410: {
411:
412:
413: if (ptr == BEGV_ADDR)
414: break;
415:
416:
417: stop = BEGV_ADDR;
418: ptr = GPT_ADDR;
419:
420:
421: if (BEGV >= GPT)
422: break;
423: }
424:
425: c = *--ptr;
426:
427: if (dp && VECTORP (DISP_CHAR_VECTOR (dp, c)))
428: {
429: charvec = DISP_CHAR_VECTOR (dp, c);
430: n = ASIZE (charvec);
431: }
432: else
433: {
434: charvec = Qnil;
435: n = 1;
436: }
437:
438: for (i = n - 1; i >= 0; --i)
439: {
440: if (VECTORP (charvec))
441: {
442:
443:
444: Lisp_Object entry = AREF (charvec, i);
445:
446: if (INTEGERP (entry)
447: && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
448: c = FAST_GLYPH_CHAR (XFASTINT (entry));
449: else
450: c = ' ';
451: }
452:
453: if (c >= 040 && c < 0177)
454: col++;
455: else if (c == '\n'
456: || (c == '\r'
457: && EQ (current_buffer->selective_display, Qt)))
458: {
459: ptr++;
460: goto start_of_line_found;
461: }
462: else if (c == '\t')
463: {
464: if (tab_seen)
465: col = ((col + tab_width) / tab_width) * tab_width;
466:
467: post_tab += col;
468: col = 0;
469: tab_seen = 1;
470: }
471: else if (VECTORP (charvec))
472:
473:
474:
475:
476:
477: ++col;
478: else
479: col += (ctl_arrow && c < 0200) ? 2 : 4;
480: }
481: }
482:
483: start_of_line_found:
484:
485: if (tab_seen)
486: {
487: col = ((col + tab_width) / tab_width) * tab_width;
488: col += post_tab;
489: }
490:
491: if (ptr == BEGV_ADDR)
492: current_column_bol_cache = BEGV;
493: else
494: current_column_bol_cache = BYTE_TO_CHAR (PTR_BYTE_POS (ptr));
495:
496: last_known_column = col;
497: last_known_column_point = PT;
498: last_known_column_modified = MODIFF;
499:
500: return col;
501: }
502: ^L
503:
504:
505:
506:
507:
508: static double
509: current_column_1 ()
510: {
511: register int tab_width = XINT (current_buffer->tab_width);
512: register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
513: register struct Lisp_Char_Table *dp = buffer_display_table ();
514: int multibyte = !NILP (current_buffer->enable_multibyte_characters);
515:
516:
517: register int col = 0;
518: int scan, scan_byte;
519: int next_boundary;
520: int opoint = PT, opoint_byte = PT_BYTE;
521:
522: scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
523: current_column_bol_cache = PT;
524: scan = PT, scan_byte = PT_BYTE;
525: SET_PT_BOTH (opoint, opoint_byte);
526: next_boundary = scan;
527:
528: if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
529:
530:
531: while (scan < opoint)
532: {
533: int c;
534:
535:
536: while (scan == next_boundary)
537: {
538: int old_scan = scan;
539:
540:
541: scan = skip_invisible (scan, &next_boundary, opoint, Qnil);
542: if (scan >= opoint)
543: goto endloop;
544: if (scan != old_scan)
545: scan_byte = CHAR_TO_BYTE (scan);
546: }
547:
548:
549: {
550: int len, len_byte, width;
551:
552: if (check_composition (scan, scan_byte, opoint,
553: &len, &len_byte, &width))
554: {
555: scan += len;
556: scan_byte += len_byte;
557: if (scan <= opoint)
558: col += width;
559: continue;
560: }
561: }
562:
563: c = FETCH_BYTE (scan_byte);
564:
565: if (dp != 0
566: && ! (multibyte && BASE_LEADING_CODE_P (c))
567: && VECTORP (DISP_CHAR_VECTOR (dp, c)))
568: {
569: Lisp_Object charvec;
570: EMACS_INT i, n;
571:
572:
573:
574:
575: charvec = DISP_CHAR_VECTOR (dp, c);
576: n = ASIZE (charvec);
577:
578: for (i = 0; i < n; i++)
579: {
580:
581:
582: Lisp_Object entry;
583: entry = AREF (charvec, i);
584:
585: if (INTEGERP (entry)
586: && GLYPH_CHAR_VALID_P (XFASTINT (entry)))
587: c = FAST_GLYPH_CHAR (XFASTINT (entry));
588: else
589: c = ' ';
590:
591: if (c == '\n')
592: goto endloop;
593: if (c == '\r' && EQ (current_buffer->selective_display, Qt))
594: goto endloop;
595: if (c == '\t')
596: {
597: col += tab_width;
598: col = col / tab_width * tab_width;
599: }
600: else
601: ++col;
602: }
603: }
604: else
605: {
606:
607:
608:
609: if (c == '\n')
610: goto endloop;
611: if (c == '\r' && EQ (current_buffer->selective_display, Qt))
612: goto endloop;
<