1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <setjmp.h>
24
25 #include "lisp.h"
26 #include "buffer.h"
27 #include "character.h"
28 #include "category.h"
29 #include "composite.h"
30 #include "indent.h"
31 #include "keyboard.h"
32 #include "frame.h"
33 #include "window.h"
34 #include "termchar.h"
35 #include "termopts.h"
36 #include "disptab.h"
37 #include "intervals.h"
38 #include "dispextern.h"
39 #include "region-cache.h"
40
41 42
43
44 static int indent_tabs_mode;
45
46 #define CR 015
47
48
49
50 51 52
53
54 static double last_known_column;
55
56
57
58 EMACS_INT last_known_column_point;
59
60
61
62 static int last_known_column_modified;
63
64 static double current_column_1 P_ ((void));
65 static double position_indentation P_ ((int));
66
67 68
69
70 static EMACS_INT current_column_bol_cache;
71
72
73
74 struct Lisp_Char_Table *
75 buffer_display_table ()
76 {
77 Lisp_Object thisbuf;
78
79 thisbuf = current_buffer->display_table;
80 if (DISP_TABLE_P (thisbuf))
81 return XCHAR_TABLE (thisbuf);
82 if (DISP_TABLE_P (Vstandard_display_table))
83 return XCHAR_TABLE (Vstandard_display_table);
84 return 0;
85 }
86
87
88
89
90
91 static int
92 character_width (c, dp)
93 int c;
94 struct Lisp_Char_Table *dp;
95 {
96 Lisp_Object elt;
97
98 99
100
101 102
103 if (dp && (elt = DISP_CHAR_VECTOR (dp, c), VECTORP (elt)))
104 return XVECTOR (elt)->size;
105
106
107 if (c == '\n' || c == '\t' || c == '\015')
108 return 0;
109
110
111 else if (c >= 040 && c < 0177)
112 return 1;
113
114 115 116 117 118
119 else
120 return 0;
121 }
122
123 124 125
126
127 int
128 disptab_matches_widthtab (disptab, widthtab)
129 struct Lisp_Char_Table *disptab;
130 struct Lisp_Vector *widthtab;
131 {
132 int i;
133
134 if (widthtab->size != 256)
135 abort ();
136
137 for (i = 0; i < 256; i++)
138 if (character_width (i, disptab)
139 != XFASTINT (widthtab->contents[i]))
140 return 0;
141
142 return 1;
143 }
144
145
146
147 void
148 recompute_width_table (buf, disptab)
149 struct buffer *buf;
150 struct Lisp_Char_Table *disptab;
151 {
152 int i;
153 struct Lisp_Vector *widthtab;
154
155 if (!VECTORP (buf->width_table))
156 buf->width_table = Fmake_vector (make_number (256), make_number (0));
157 widthtab = XVECTOR (buf->width_table);
158 if (widthtab->size != 256)
159 abort ();
160
161 for (i = 0; i < 256; i++)
162 XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
163 }
164
165 166
167
168 static void
169 width_run_cache_on_off ()
170 {
171 if (NILP (current_buffer->cache_long_line_scans)
172 173
174 || !NILP (current_buffer->enable_multibyte_characters))
175 {
176
177 if (current_buffer->width_run_cache)
178 {
179 free_region_cache (current_buffer->width_run_cache);
180 current_buffer->width_run_cache = 0;
181 current_buffer->width_table = Qnil;
182 }
183 }
184 else
185 {
186
187 if (current_buffer->width_run_cache == 0)
188 {
189 current_buffer->width_run_cache = new_region_cache ();
190 recompute_width_table (current_buffer, buffer_display_table ());
191 }
192 }
193 }
194
195
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
218
219 EMACS_INT
220 skip_invisible (pos, next_boundary_p, to, window)
221 EMACS_INT pos;
222 EMACS_INT *next_boundary_p;
223 EMACS_INT to;
224 Lisp_Object window;
225 {
226 Lisp_Object prop, position, overlay_limit, proplimit;
227 Lisp_Object buffer, tmp;
228 EMACS_INT end;
229 int inv_p;
230
231 XSETFASTINT (position, pos);
232 XSETBUFFER (buffer, current_buffer);
233
234
235 recenter_overlay_lists (current_buffer, pos);
236
237 238 239
240 overlay_limit = Fnext_overlay_change (position);
241 242
243 proplimit = Fnext_property_change (position, buffer, Qt);
244 if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
245 proplimit = overlay_limit;
246 247 248
249 if (XFASTINT (proplimit) > pos + 100 || XFASTINT (proplimit) >= to)
250 *next_boundary_p = XFASTINT (proplimit);
251
252 else
253 {
254
255 XSETFASTINT (proplimit, min (pos + 100, to));
256
257 if (XFASTINT (overlay_limit) < XFASTINT (proplimit))
258 proplimit = overlay_limit;
259 tmp = Fnext_single_property_change (position, Qinvisible,
260 buffer, proplimit);
261 end = XFASTINT (tmp);
262 #if 0
263 264
265 if (end == pos + 100
266 && !NILP (current_buffer->enable_multibyte_characters)
267 && end < ZV)
268 while (pos < end && !CHAR_HEAD_P (POS_ADDR (end)))
269 end--;
270 #endif
271 *next_boundary_p = end;
272 }
273 274
275 prop = Fget_char_property (position, Qinvisible,
276 (!NILP (window)
277 && EQ (XWINDOW (window)->buffer, buffer))
278 ? window : buffer);
279 inv_p = TEXT_PROP_MEANS_INVISIBLE (prop);
280
281 if (NILP (window) ? inv_p == 1 : inv_p)
282 return *next_boundary_p;
283 return pos;
284 }
285
286 287 288 289 290 291
292
293 #define MULTIBYTE_BYTES_WIDTH(p, dp) \
294 do { \
295 int c; \
296 \
297 wide_column = 0; \
298 c = STRING_CHAR_AND_LENGTH (p, bytes); \
299 if (BYTES_BY_CHAR_HEAD (*p) != bytes) \
300 width = bytes * 4; \
301 else \
302 { \
303 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) \
304 width = XVECTOR (DISP_CHAR_VECTOR (dp, c))->size; \
305 else \
306 width = CHAR_WIDTH (c); \
307 if (width > 1) \
308 wide_column = width; \
309 } \
310 } while (0)
311
312
313 DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
314 doc: 315 316 317 318 319 320 321 322 323 324 )
325 ()
326 {
327 Lisp_Object temp;
328 XSETFASTINT (temp, (int) current_column ());
329 return temp;
330 }
331
332
333
334 void
335 invalidate_current_column ()
336 {
337 last_known_column_point = 0;
338 }
339
340 double
341 current_column ()
342 {
343 register int col;
344 register unsigned char *ptr, *stop;
345 register int tab_seen;
346 int post_tab;
347 register int c;
348 register int tab_width = XINT (current_buffer->tab_width);
349 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
350 register struct Lisp_Char_Table *dp = buffer_display_table ();
351
352 if (PT == last_known_column_point
353 && MODIFF == last_known_column_modified)
354 return last_known_column;
355
356 357
358 if (BUF_INTERVALS (current_buffer)
359 || current_buffer->overlays_before
360 || current_buffer->overlays_after
361 || Z != Z_BYTE)
362 return current_column_1 ();
363
364 365
366
367
368 ptr = BYTE_POS_ADDR (PT_BYTE - 1) + 1;
369 370
371 if (PT == BEGV)
372 stop = ptr;
373 else if (PT <= GPT || BEGV > GPT)
374 stop = BEGV_ADDR;
375 else
376 stop = GAP_END_ADDR;
377
378 if (tab_width <= 0 || tab_width > 1000)
379 tab_width = 8;
380
381 col = 0, tab_seen = 0, post_tab = 0;
382
383 while (1)
384 {
385 EMACS_INT i, n;
386 Lisp_Object charvec;
387
388 if (ptr == stop)
389 {
390 391
392 if (ptr == BEGV_ADDR)
393 break;
394
395
396 stop = BEGV_ADDR;
397 ptr = GPT_ADDR;
398
399
400 if (BEGV >= GPT)
401 break;
402 }
403
404 c = *--ptr;
405
406 if (dp && VECTORP (DISP_CHAR_VECTOR (dp, c)))
407 {
408 charvec = DISP_CHAR_VECTOR (dp, c);
409 n = ASIZE (charvec);
410 }
411 else
412 {
413 charvec = Qnil;
414 n = 1;
415 }
416
417 for (i = n - 1; i >= 0; --i)
418 {
419 if (VECTORP (charvec))
420 {
421 422
423 Lisp_Object entry = AREF (charvec, i);
424
425 if (GLYPH_CODE_P (entry)
426 && GLYPH_CODE_CHAR_VALID_P (entry))
427 c = GLYPH_CODE_CHAR (entry);
428 else
429 c = ' ';
430 }
431
432 if (c >= 040 && c < 0177)
433 col++;
434 else if (c == '\n'
435 || (c == '\r'
436 && EQ (current_buffer->selective_display, Qt)))
437 {
438 ptr++;
439 goto start_of_line_found;
440 }
441 else if (c == '\t')
442 {
443 if (tab_seen)
444 col = ((col + tab_width) / tab_width) * tab_width;
445
446 post_tab += col;
447 col = 0;
448 tab_seen = 1;
449 }
450 else if (VECTORP (charvec))
451 452 453 454 455
456 ++col;
457 else
458 col += (ctl_arrow && c < 0200) ? 2 : 4;
459 }
460 }
461
462 start_of_line_found:
463
464 if (tab_seen)
465 {
466 col = ((col + tab_width) / tab_width) * tab_width;
467 col += post_tab;
468 }
469
470 if (ptr == BEGV_ADDR)
471 current_column_bol_cache = BEGV;
472 else
473 current_column_bol_cache = BYTE_TO_CHAR (PTR_BYTE_POS (ptr));
474
475 last_known_column = col;
476 last_known_column_point = PT;
477 last_known_column_modified = MODIFF;
478
479 return col;
480 }
481
482 extern Lisp_Object Qspace, QCwidth, QCalign_to;
483
484 485 486 487 488
489 static int
490 check_display_width (EMACS_INT pos, EMACS_INT col, EMACS_INT *endpos)
491 {
492 Lisp_Object val, overlay;
493
494 if (CONSP (val = get_char_property_and_overlay
495 (make_number (pos), Qdisplay, Qnil, &overlay))
496 && EQ (Qspace, XCAR (val)))
497 {
498 Lisp_Object plist = XCDR (val), prop;
499 int width = -1;
500
501 if ((prop = Fplist_get (plist, QCwidth), NATNUMP (prop)))
502 width = XINT (prop);
503 else if (FLOATP (prop))
504 width = (int)(XFLOAT_DATA (prop) + 0.5);
505 else if ((prop = Fplist_get (plist, QCalign_to), NATNUMP (prop)))
506 width = XINT (prop) - col;
507 else if (FLOATP (prop))
508 width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
509
510 if (width >= 0)
511 {
512 EMACS_INT start;
513 if (OVERLAYP (overlay))
514 *endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
515 else
516 get_property_and_range (pos, Qdisplay, &val, &start, endpos, Qnil);
517 return width;
518 }
519 }
520 return -1;
521 }
522
523 524 525 526 527 528
529 static void
530 scan_for_column (EMACS_INT *endpos, EMACS_INT *goalcol, EMACS_INT *prevcol)
531 {
532 register EMACS_INT tab_width = XINT (current_buffer->tab_width);
533 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
534 register struct Lisp_Char_Table *dp = buffer_display_table ();
535 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
536 struct composition_it cmp_it;
537 Lisp_Object window;
538 struct window *w;
539
540
541 register EMACS_INT col = 0, prev_col = 0;
542 EMACS_INT goal = goalcol ? *goalcol : MOST_POSITIVE_FIXNUM;
543 EMACS_INT end = endpos ? *endpos : PT;
544 EMACS_INT scan, scan_byte;
545 EMACS_INT next_boundary;
546 {
547 EMACS_INT opoint = PT, opoint_byte = PT_BYTE;
548 scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
549 current_column_bol_cache = PT;
550 scan = PT, scan_byte = PT_BYTE;
551 SET_PT_BOTH (opoint, opoint_byte);
552 next_boundary = scan;
553 }
554
555 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
556 w = ! NILP (window) ? XWINDOW (window) : NULL;
557
558 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
559 bzero (&cmp_it, sizeof cmp_it);
560 cmp_it.id = -1;
561 composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil);
562
563
564 while (scan < end)
565 {
566 int c;
567
568
569 while (scan == next_boundary)
570 {
571 EMACS_INT old_scan = scan;
572 573
574 scan = skip_invisible (scan, &next_boundary, end, Qnil);
575 if (scan != old_scan)
576 scan_byte = CHAR_TO_BYTE (scan);
577 if (scan >= end)
578 goto endloop;
579 }
580
581 582 583
584 if (col >= goal)
585 break;
586 prev_col = col;
587
588 {
589 EMACS_INT end;
590 int width = check_display_width (scan, col, &end);
591 if (width >= 0)
592 {
593 col += width;
594 if (end > scan)
595 {
596 scan = end; scan_byte = charpos_to_bytepos (scan);
597 continue;
598 }
599 }
600 }
601
602
603 if (cmp_it.id >= 0
604 || (scan == cmp_it.stop_pos
605 && composition_reseat_it (&cmp_it, scan, scan_byte, end,
606 w, NULL, Qnil)))
607 composition_update_it (&cmp_it, scan, scan_byte, Qnil);
608 if (cmp_it.id >= 0)
609 {
610 scan += cmp_it.nchars;
611 scan_byte += cmp_it.nbytes;
612 if (scan <= end)
613 col += cmp_it.width;
614 if (cmp_it.to == cmp_it.nglyphs)
615 {
616 cmp_it.id = -1;
617 composition_compute_stop_pos (&cmp_it, scan, scan_byte, end,
618 Qnil);
619 }
620 else
621 cmp_it.from = cmp_it.to;
622 continue;
623 }
624
625 c = FETCH_BYTE (scan_byte);
626
627 628
629
630 if (dp != 0
631 && ! (multibyte && BASE_LEADING_CODE_P (c))
632 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
633 {
634 Lisp_Object charvec;
635 EMACS_INT i, n;
636
637 638
639
640 charvec = DISP_CHAR_VECTOR (dp, c);
641 n = ASIZE (charvec);
642
643 for (i = 0; i < n; i++)
644 {
645 646
647 Lisp_Object entry = AREF (charvec, i);
648
649 if (GLYPH_CODE_P (entry)
650 && GLYPH_CODE_CHAR_VALID_P (entry))
651 c = GLYPH_CODE_CHAR (entry);
652 else
653 c = ' ';
654
655 if (c == '\n')
656 goto endloop;
657 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
658 goto endloop;
659 if (c == '\t')
660 {
661 col += tab_width;
662 col = col / tab_width * tab_width;
663 }
664 else
665 ++col;
666 }
667 }
668 else
669 {
670 671
672
673 if (c == '\n')
674 goto endloop;
675 if (c == '\r' && EQ (current_buffer->selective_display, Qt))
676 goto endloop;
677 if (c == '\t')
678 {
679 col += tab_width;
680 col = col / tab_width * tab_width;
681 }
682 else if (multibyte && BASE_LEADING_CODE_P (c))
683 {
684
685 unsigned char *ptr;
686 int bytes, width, wide_column;
687
688 ptr = BYTE_POS_ADDR (scan_byte);
689 MULTIBYTE_BYTES_WIDTH (ptr, dp);
690 691
692 scan_byte += bytes - 1;
693 col += width;
694 }
695 else if (ctl_arrow && (c < 040 || c == 0177))
696 col += 2;
697 else if (c < 040 || c >= 0177)
698 col += 4;
699 else
700 col++;
701 }
702 scan++;
703 scan_byte++;
704
705 }
706 endloop:
707
708 last_known_column = col;
709 last_known_column_point = PT;
710 last_known_column_modified = MODIFF;
711
712 if (goalcol)
713 *goalcol = col;
714 if (endpos)
715 *endpos = scan;
716 if (prevcol)
717 *prevcol = prev_col;
718 }
719
720 721 722 723
724
725 static double
726 current_column_1 ()
727 {
728 EMACS_INT col = MOST_POSITIVE_FIXNUM;
729 EMACS_INT opoint = PT;
730
731 scan_for_column (&opoint, &col, NULL);
732 return col;
733 }
734
735
736 #if 0
737
738 739 740
741
742 static double
743 string_display_width (string, beg, end)
744 Lisp_Object string, beg, end;
745 {
746 register int col;
747 register unsigned char *ptr, *stop;
748 register int tab_seen;
749 int post_tab;
750 register int c;
751 register int tab_width = XINT (current_buffer->tab_width);
752 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
753 register struct Lisp_Char_Table *dp = buffer_display_table ();
754 int b, e;
755
756 if (NILP (end))
757 e = SCHARS (string);
758 else
759 {
760 CHECK_NUMBER (end);
761 e = XINT (end);
762 }
763
764 if (NILP (beg))
765 b = 0;
766 else
767 {
768 CHECK_NUMBER (beg);
769 b = XINT (beg);
770 }
771
772
773 ptr = SDATA (string) + e;
774 775
776 stop = SDATA (string) + b;
777
778 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
779
780 col = 0, tab_seen = 0, post_tab = 0;
781
782 while (1)
783 {
784 if (ptr == stop)
785 break;
786
787 c = *--ptr;
788 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
789 col += XVECTOR (DISP_CHAR_VECTOR (dp, c))->size;
790 else if (c >= 040 && c < 0177)
791 col++;
792 else if (c == '\n')
793 break;
794 else if (c == '\t')
795 {
796 if (tab_seen)
797 col = ((col + tab_width) / tab_width) * tab_width;
798
799 post_tab += col;
800 col = 0;
801 tab_seen = 1;
802 }
803 else
804 col += (ctl_arrow && c < 0200) ? 2 : 4;
805 }
806
807 if (tab_seen)
808 {
809 col = ((col + tab_width) / tab_width) * tab_width;
810 col += post_tab;
811 }
812
813 return col;
814 }
815
816 #endif
817
818
819 DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
820 doc: 821 822 823 824 )
825 (column, minimum)
826 Lisp_Object column, minimum;
827 {
828 int mincol;
829 register int fromcol;
830 register int tab_width = XINT (current_buffer->tab_width);
831
832 CHECK_NUMBER (column);
833 if (NILP (minimum))
834 XSETFASTINT (minimum, 0);
835 CHECK_NUMBER (minimum);
836
837 fromcol = current_column ();
838 mincol = fromcol + XINT (minimum);
839 if (mincol < XINT (column)) mincol = XINT (column);
840
841 if (fromcol == mincol)
842 return make_number (mincol);
843
844 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
845
846 if (indent_tabs_mode)
847 {
848 Lisp_Object n;
849 XSETFASTINT (n, mincol / tab_width - fromcol / tab_width);
850 if (XFASTINT (n) != 0)
851 {
852 Finsert_char (make_number ('\t'), n, Qt);
853
854 fromcol = (mincol / tab_width) * tab_width;
855 }
856 }
857
858 XSETFASTINT (column, mincol - fromcol);
859 Finsert_char (make_number (' '), column, Qt);
860
861 last_known_column = mincol;
862 last_known_column_point = PT;
863 last_known_column_modified = MODIFF;
864
865 XSETINT (column, mincol);
866 return column;
867 }
868
869
870 static double position_indentation P_ ((int));
871
872 DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
873 0, 0, 0,
874 doc: 875 876 )
877 ()
878 {
879 Lisp_Object val;
880 int opoint = PT, opoint_byte = PT_BYTE;
881
882 scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, 1);
883
884 XSETFASTINT (val, (int) position_indentation (PT_BYTE));
885 SET_PT_BOTH (opoint, opoint_byte);
886 return val;
887 }
888
889 static double
890 position_indentation (pos_byte)
891 register int pos_byte;
892 {
893 register EMACS_INT column = 0;
894 register EMACS_INT tab_width = XINT (current_buffer->tab_width);
895 register unsigned char *p;
896 register unsigned char *stop;
897 unsigned char *start;
898 EMACS_INT next_boundary_byte = pos_byte;
899 EMACS_INT ceiling = next_boundary_byte;
900
901 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
902
903 p = BYTE_POS_ADDR (pos_byte);
904 905 906
907 stop = p;
908
909 start = p;
910 while (1)
911 {
912 while (p == stop)
913 {
914 EMACS_INT stop_pos_byte;
915
916 917
918 if (p != start)
919 pos_byte = PTR_BYTE_POS (p);
920
921 if (pos_byte == ZV_BYTE)
922 return column;
923 if (pos_byte == next_boundary_byte)
924 {
925 EMACS_INT next_boundary;
926 EMACS_INT pos = BYTE_TO_CHAR (pos_byte);
927 pos = skip_invisible (pos, &next_boundary, ZV, Qnil);
928 pos_byte = CHAR_TO_BYTE (pos);
929 next_boundary_byte = CHAR_TO_BYTE (next_boundary);
930 }
931 if (pos_byte >= ceiling)
932 ceiling = BUFFER_CEILING_OF (pos_byte) + 1;
933 934
935 stop_pos_byte = min (ceiling, next_boundary_byte);
936 937 938
939
940 stop = BYTE_POS_ADDR (stop_pos_byte - 1) + 1;
941 p = BYTE_POS_ADDR (pos_byte);
942 }
943 switch (*p++)
944 {
945 case 0240:
946 if (! NILP (current_buffer->enable_multibyte_characters))
947 return column;
948 case ' ':
949 column++;
950 break;
951 case '\t':
952 column += tab_width - column % tab_width;
953 break;
954 default:
955 if (ASCII_BYTE_P (p[-1])
956 || NILP (current_buffer->enable_multibyte_characters))
957 return column;
958 {
959 int c;
960 pos_byte = PTR_BYTE_POS (p - 1);
961 c = FETCH_MULTIBYTE_CHAR (pos_byte);
962 if (CHAR_HAS_CATEGORY (c, ' '))
963 {
964 column++;
965 INC_POS (pos_byte);
966 p = BYTE_POS_ADDR (pos_byte);
967 }
968 else
969 return column;
970 }
971 }
972 }
973 }
974
975 976 977
978
979 int
980 indented_beyond_p (pos, pos_byte, column)
981 int pos, pos_byte;
982 double column;
983 {
984 double val;
985 int opoint = PT, opoint_byte = PT_BYTE;
986
987 SET_PT_BOTH (pos, pos_byte);
988 while (PT > BEGV && FETCH_BYTE (PT_BYTE) == '\n')
989 scan_newline (PT - 1, PT_BYTE - 1, BEGV, BEGV_BYTE, -1, 0);
990
991 val = position_indentation (PT_BYTE);
992 SET_PT_BOTH (opoint, opoint_byte);
993 return val >= column;
994 }
995
996 DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 2, "p",
997 doc: 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 )
1014 (column, force)
1015 Lisp_Object column, force;
1016 {
1017 EMACS_INT pos;
1018 EMACS_INT col, prev_col;
1019 EMACS_INT goal;
1020
1021 CHECK_NATNUM (column);
1022 goal = XINT (column);
1023
1024 col = goal;
1025 pos = ZV;
1026 scan_for_column (&pos, &col, &prev_col);
1027
1028 SET_PT (pos);
1029
1030 1031
1032 if (!NILP (force) && col > goal)
1033 {
1034 int c;
1035 EMACS_INT pos_byte = PT_BYTE;
1036
1037 DEC_POS (pos_byte);
1038 c = FETCH_CHAR (pos_byte);
1039 if (c == '\t' && prev_col < goal)
1040 {
1041 EMACS_INT goal_pt, goal_pt_byte;
1042
1043 1044 1045
1046 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
1047 Finsert_char (make_number (' '), make_number (goal - prev_col), Qt);
1048
1049
1050 del_range (PT, PT + 1);
1051 goal_pt = PT;
1052 goal_pt_byte = PT_BYTE;
1053 Findent_to (make_number (col), Qnil);
1054 SET_PT_BOTH (goal_pt, goal_pt_byte);
1055
1056
1057 col = goal;
1058 }
1059 }
1060
1061
1062 if (col < goal && EQ (force, Qt))
1063 Findent_to (make_number (col = goal), Qnil);
1064
1065 last_known_column = col;
1066 last_known_column_point = PT;
1067 last_known_column_modified = MODIFF;
1068
1069 return make_number (col);
1070 }
1071
1072
1073
1074 struct position val_compute_motion;
1075
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
1138
1139 struct position *
1140 compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos, width, hscroll, tab_offset, win)
1141 EMACS_INT from, fromvpos, fromhpos, to, tovpos, tohpos;
1142 int did_motion;
1143 EMACS_INT width;
1144 EMACS_INT hscroll, tab_offset;
1145 struct window *win;
1146 {
1147 register EMACS_INT hpos = fromhpos;
1148 register EMACS_INT vpos = fromvpos;
1149
1150 register EMACS_INT pos;
1151 EMACS_INT pos_byte;
1152 register int c = 0;
1153 register EMACS_INT tab_width = XFASTINT (current_buffer->tab_width);
1154 register int ctl_arrow = !NILP (current_buffer->ctl_arrow);
1155 register struct Lisp_Char_Table *dp = window_display_table (win);
1156 int selective
1157 = (INTEGERP (current_buffer->selective_display)
1158 ? XINT (current_buffer->selective_display)
1159 : !NILP (current_buffer->selective_display) ? -1 : 0);
1160 int selective_rlen
1161 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
1162 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : 0);
1163 1164
1165 EMACS_INT next_boundary = from;
1166
1167 1168 1169 1170
1171 EMACS_INT width_run_start = from;
1172 EMACS_INT width_run_end = from;
1173 EMACS_INT width_run_width = 0;
1174 Lisp_Object *width_table;
1175 Lisp_Object buffer;
1176
1177
1178 EMACS_INT next_width_run = from;
1179 Lisp_Object window;
1180
1181 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
1182 1183
1184 EMACS_INT wide_column_end_hpos = 0;
1185 EMACS_INT prev_pos;
1186 EMACS_INT prev_pos_byte;
1187 EMACS_INT prev_hpos = 0;
1188 EMACS_INT prev_vpos = 0;
1189 EMACS_INT contin_hpos;
1190 EMACS_INT prev_tab_offset;
1191 EMACS_INT continuation_glyph_width;
1192
1193 struct composition_it cmp_it;
1194
1195 XSETBUFFER (buffer, current_buffer);
1196 XSETWINDOW (window, win);
1197
1198 width_run_cache_on_off ();
1199 if (dp == buffer_display_table ())
1200 width_table = (VECTORP (current_buffer->width_table)
1201 ? XVECTOR (current_buffer->width_table)->contents
1202 : 0);
1203 else
1204 1205
1206 width_table = 0;
1207
1208 if (tab_width <= 0 || tab_width > 1000)
1209 tab_width = 8;
1210
1211
1212 if (width < 0)
1213 {
1214 width = window_box_text_cols (win);
1215
1216 #ifdef HAVE_WINDOW_SYSTEM
1217 if (!FRAME_WINDOW_P (XFRAME (win->frame)))
1218 #endif
1219 width -= 1;
1220 }
1221
1222 continuation_glyph_width = 1;
1223 #ifdef HAVE_WINDOW_SYSTEM
1224 if (FRAME_WINDOW_P (XFRAME (win->frame)))
1225 continuation_glyph_width = 0;
1226 #endif
1227
1228 immediate_quit = 1;
1229 QUIT;
1230
1231 pos = prev_pos = from;
1232 pos_byte = prev_pos_byte = CHAR_TO_BYTE (from);
1233 contin_hpos = 0;
1234 prev_tab_offset = tab_offset;
1235 bzero (&cmp_it, sizeof cmp_it);
1236 cmp_it.id = -1;
1237 composition_compute_stop_pos (&cmp_it, pos, pos_byte, to, Qnil);
1238
1239 while (1)
1240 {
1241 while (pos == next_boundary)
1242 {
1243 EMACS_INT pos_here = pos;
1244 EMACS_INT newpos;
1245
1246
1247 if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
1248 {
1249 if (contin_hpos && prev_hpos == 0
1250 && hpos > tohpos
1251 && (contin_hpos == width || wide_column_end_hpos > width))
1252 { 1253 1254 1255 1256 1257
1258 pos = prev_pos;
1259 pos_byte = prev_pos_byte;
1260 hpos = prev_hpos;
1261 vpos = prev_vpos;
1262 tab_offset = prev_tab_offset;
1263 }
1264 break;
1265 }
1266
1267 1268 1269 1270
1271 if (!did_motion)
1272 1273 1274 1275
1276 {
1277 unsigned char *ovstr;
1278 int ovlen = overlay_strings (pos, win, &ovstr);
1279 hpos += ((multibyte && ovlen > 0)
1280 ? strwidth (ovstr, ovlen) : ovlen);
1281 }
1282 did_motion = 0;
1283
1284 if (pos >= to)
1285 break;
1286
1287 1288 1289 1290
1291 newpos = skip_invisible (pos, &next_boundary, to, window);
1292
1293 if (newpos >= to)
1294 {
1295 pos = min (to, newpos);
1296 pos_byte = CHAR_TO_BYTE (pos);
1297 goto after_loop;
1298 }
1299
1300 if (newpos != pos_here)
1301 {
1302 pos = newpos;
1303 pos_byte = CHAR_TO_BYTE (pos);
1304 }
1305 }
1306
1307
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
1350
1351 if (hpos > width)
1352 {
1353 int total_width = width + continuation_glyph_width;
1354 int truncate = 0;
1355
1356 if (!NILP (Vtruncate_partial_width_windows)
1357 && (total_width < FRAME_COLS (XFRAME (WINDOW_FRAME (win)))))
1358 {
1359 if (INTEGERP (Vtruncate_partial_width_windows))
1360 truncate
1361 = total_width < XFASTINT (Vtruncate_partial_width_windows);
1362 else
1363 truncate = 1;
1364 }
1365
1366 if (hscroll || truncate
1367 || !NILP (current_buffer->truncate_lines))
1368 {
1369 1370
1371 if (pos <= to)
1372 {
1373 pos = find_before_next_newline (pos, to, 1);
1374 pos_byte = CHAR_TO_BYTE (pos);
1375 hpos = width;
1376 1377 1378
1379 if (pos >= next_boundary)
1380 next_boundary = pos + 1;
1381 prev_hpos = width;
1382 prev_vpos = vpos;
1383 prev_tab_offset = tab_offset;
1384 }
1385 }
1386 else
1387 {
1388
1389
1390 prev_tab_offset = tab_offset;
1391
1392 if (wide_column_end_hpos > width)
1393 {
1394 hpos -= prev_hpos;
1395 tab_offset += prev_hpos;
1396 }
1397 else
1398 {
1399 tab_offset += width;
1400 hpos -= width;
1401 }
1402 vpos++;
1403 contin_hpos = prev_hpos;
1404 prev_hpos = 0;
1405 prev_vpos = vpos;
1406 }
1407 }
1408
1409
1410 if (pos > to)
1411 {
1412
1413 pos = prev_pos;
1414 pos_byte = prev_pos_byte;
1415 hpos = prev_hpos;
1416 vpos = prev_vpos;
1417 tab_offset = prev_tab_offset;
1418
1419 1420 1421 1422 1423 1424 1425 1426 1427
1428
1429 if (contin_hpos && prev_hpos == 0
1430 && contin_hpos < width && !wide_column_end_hpos)
1431 {
1432 1433
1434 hpos = contin_hpos;
1435 vpos = vpos - 1;
1436 }
1437 break;
1438 }
1439
1440 if (vpos > tovpos || (vpos == tovpos && hpos >= tohpos))
1441 {
1442 if (contin_hpos && prev_hpos == 0
1443 && hpos > tohpos
1444 && (contin_hpos == width || wide_column_end_hpos > width))
1445 { 1446 1447 1448 1449 1450
1451 pos = prev_pos;
1452 pos_byte = prev_pos_byte;
1453 hpos = prev_hpos;
1454 vpos = prev_vpos;
1455 tab_offset = prev_tab_offset;
1456 }
1457 break;
1458 }
1459 if (pos == ZV)
1460 break;
1461
1462 prev_hpos = hpos;
1463 prev_vpos = vpos;
1464 prev_pos = pos;
1465 prev_pos_byte = pos_byte;
1466 wide_column_end_hpos = 0;
1467
1468 1469
1470 if (current_buffer->width_run_cache && pos >= next_width_run)
1471 {
1472 int run_end;
1473 int common_width
1474 = region_cache_forward (current_buffer,
1475 current_buffer->width_run_cache,
1476 pos, &run_end);
1477
1478 1479 1480
1481 if (common_width != 0)
1482 {
1483 int run_end_hpos;
1484
1485 1486
1487 if (run_end > to)
1488 run_end = to;
1489
1490 run_end_hpos = hpos + (run_end - pos) * common_width;
1491
1492 1493
1494 if (vpos == tovpos && run_end_hpos > tohpos)
1495 {
1496 run_end = pos + (tohpos - hpos) / common_width;
1497 run_end_hpos = hpos + (run_end - pos) * common_width;
1498 }
1499
1500
1501 if (run_end_hpos >= width)
1502 {
1503 run_end = pos + (width - hpos) / common_width;
1504 run_end_hpos = hpos + (run_end - pos) * common_width;
1505 }
1506
1507 hpos = run_end_hpos;
1508 if (run_end > pos)
1509 prev_hpos = hpos - common_width;
1510 if (pos != run_end)
1511 {
1512 pos = run_end;
1513 pos_byte = CHAR_TO_BYTE (pos);
1514 }
1515 }
1516
1517 next_width_run = run_end + 1;
1518 }
1519
1520
1521 else
1522 {
1523 EMACS_INT i, n;
1524 Lisp_Object charvec;
1525
1526
1527 if (cmp_it.id >= 0
1528 || (pos == cmp_it.stop_pos
1529 && composition_reseat_it (&cmp_it, pos, pos_byte, to, win,
1530 NULL, Qnil)))
1531 composition_update_it (&cmp_it, pos, pos_byte, Qnil);
1532 if (cmp_it.id >= 0)
1533 {
1534 pos += cmp_it.nchars;
1535 pos_byte += cmp_it.nbytes;
1536 hpos += cmp_it.width;
1537 if (cmp_it.to == cmp_it.nglyphs)
1538 {
1539 cmp_it.id = -1;
1540 composition_compute_stop_pos (&cmp_it, pos, pos_byte, to,
1541 Qnil);
1542 }
1543 else
1544 cmp_it.from = cmp_it.to;
1545 continue;
1546 }
1547
1548 c = FETCH_BYTE (pos_byte);
1549 pos++, pos_byte++;
1550
1551
1552 if (current_buffer->width_run_cache)
1553 {
1554 1555
1556 if (pos - 1 == width_run_end
1557 && XFASTINT (width_table[c]) == width_run_width)
1558 width_run_end = pos;
1559
1560 1561
1562 else
1563 {
1564 1565
1566 if (width_run_start < width_run_end
1567 && width_run_width == 1)
1568 know_region_cache (current_buffer,
1569 current_buffer->width_run_cache,
1570 width_run_start, width_run_end);
1571
1572
1573 width_run_width = XFASTINT (width_table[c]);
1574 width_run_start = pos - 1;
1575 width_run_end = pos;
1576 }
1577 }
1578
1579 if (dp != 0
1580 && ! (multibyte && BASE_LEADING_CODE_P (c))
1581 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
1582 {
1583 charvec = DISP_CHAR_VECTOR (dp, c);
1584 n = ASIZE (charvec);
1585 }
1586 else
1587 {
1588 charvec = Qnil;
1589 n = 1;
1590 }
1591
1592 for (i = n - 1; i >= 0; --i)
1593 {
1594 if (VECTORP (charvec))
1595 {
1596 1597
1598 Lisp_Object entry = AREF (charvec, i);
1599
1600 if (GLYPH_CODE_P (entry)
1601 && GLYPH_CODE_CHAR_VALID_P (entry))
1602 c = GLYPH_CODE_CHAR (entry);
1603 else
1604 c = ' ';
1605 }
1606
1607 if (c >= 040 && c < 0177)
1608 hpos++;
1609 else if (c == '\t')
1610 {
1611 int tem = ((hpos + tab_offset + hscroll - (hscroll > 0))
1612 % tab_width);
1613 if (tem < 0)
1614 tem += tab_width;
1615 hpos += tab_width - tem;
1616 }
1617 else if (c == '\n')
1618 {
1619 if (selective > 0
1620 && indented_beyond_p (pos, pos_byte,
1621 (double) selective))
1622 {
1623 1624
1625 if (pos < to)
1626 {
1627
1628 do
1629 {
1630 pos = find_before_next_newline (pos, to, 1);
1631 if (pos < to)
1632 pos++;
1633 pos_byte = CHAR_TO_BYTE (pos);
1634 }
1635 while (pos < to
1636 && indented_beyond_p (pos, pos_byte,
1637 (double) selective));
1638
1639 if (selective_rlen)
1640 {
1641 hpos += selective_rlen;
1642 if (hpos >= width)
1643 hpos = width;
1644 }
1645 DEC_BOTH (pos, pos_byte);
1646 1647
1648 }
1649 }
1650 else
1651 {
1652
1653 vpos++;
1654 hpos = 0;
1655 hpos -= hscroll;
1656
1657 if (hscroll > 0)
1658 hpos += continuation_glyph_width;
1659 tab_offset = 0;
1660 }
1661 contin_hpos = 0;
1662 }
1663 else if (c == CR && selective < 0)
1664 {
1665 1666 1667
1668 if (pos < to)
1669 {
1670 pos = find_before_next_newline (pos, to, 1);
1671 pos_byte = CHAR_TO_BYTE (pos);
1672 }
1673 1674 1675
1676 if (pos > next_boundary)
1677 next_boundary = pos;
1678
1679 if (selective_rlen)
1680 {
1681 hpos += selective_rlen;
1682 if (hpos >= width)
1683 hpos = width;
1684 }
1685 }
1686 else if (multibyte && BASE_LEADING_CODE_P (c))
1687 {
1688
1689 unsigned char *ptr;
1690 int bytes, width, wide_column;
1691
1692 pos_byte--;
1693 ptr = BYTE_POS_ADDR (pos_byte);
1694 MULTIBYTE_BYTES_WIDTH (ptr, dp);
1695 pos_byte += bytes;
1696 if (wide_column)
1697 wide_column_end_hpos = hpos + wide_column;
1698 hpos += width;
1699 }
1700 else if (VECTORP (charvec))
1701 ++hpos;
1702 else
1703 hpos += (ctl_arrow && c < 0200) ? 2 : 4;
1704 }
1705 }
1706 }
1707
1708 after_loop:
1709
1710
1711 if (current_buffer->width_run_cache
1712 && width_run_width == 1
1713 && width_run_start < width_run_end)
1714 know_region_cache (current_buffer, current_buffer->width_run_cache,
1715 width_run_start, width_run_end);
1716
1717 val_compute_motion.bufpos = pos;
1718 val_compute_motion.bytepos = pos_byte;
1719 val_compute_motion.hpos = hpos;
1720 val_compute_motion.vpos = vpos;
1721 if (contin_hpos && prev_hpos == 0)
1722 val_compute_motion.prevhpos = contin_hpos;
1723 else
1724 val_compute_motion.prevhpos = prev_hpos;
1725
1726 val_compute_motion.ovstring_chars_done = 0;
1727
1728
1729 val_compute_motion.contin = (contin_hpos && prev_hpos == 0);
1730
1731 immediate_quit = 0;
1732 return &val_compute_motion;
1733 }
1734
1735
1736 DEFUN ("compute-motion", Fcompute_motion, Scompute_motion, 7, 7, 0,
1737 doc: 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 )
1778 (from, frompos, to, topos, width, offsets, window)
1779 Lisp_Object from, frompos, to, topos;
1780 Lisp_Object width, offsets, window;
1781 {
1782 struct window *w;
1783 Lisp_Object bufpos, hpos, vpos, prevhpos;
1784 struct position *pos;
1785 int hscroll, tab_offset;
1786
1787 CHECK_NUMBER_COERCE_MARKER (from);
1788 CHECK_CONS (frompos);
1789 CHECK_NUMBER_CAR (frompos);
1790 CHECK_NUMBER_CDR (frompos);
1791 CHECK_NUMBER_COERCE_MARKER (to);
1792 if (!NILP (topos))
1793 {
1794 CHECK_CONS (topos);
1795 CHECK_NUMBER_CAR (topos);
1796 CHECK_NUMBER_CDR (topos);
1797 }
1798 if (!NILP (width))
1799 CHECK_NUMBER (width);
1800
1801 if (!NILP (offsets))
1802 {
1803 CHECK_CONS (offsets);
1804 CHECK_NUMBER_CAR (offsets);
1805 CHECK_NUMBER_CDR (offsets);
1806 hscroll = XINT (XCAR (offsets));
1807 tab_offset = XINT (XCDR (offsets));
1808 }
1809 else
1810 hscroll = tab_offset = 0;
1811
1812 if (NILP (window))
1813 window = Fselected_window ();
1814 else
1815 CHECK_LIVE_WINDOW (window);
1816 w = XWINDOW (window);
1817
1818 if (XINT (from) < BEGV || XINT (from) > ZV)
1819 args_out_of_range_3 (from, make_number (BEGV), make_number (ZV));
1820 if (XINT (to) < BEGV || XINT (to) > ZV)
1821 args_out_of_range_3 (to, make_number (BEGV), make_number (ZV));
1822
1823 pos = compute_motion (XINT (from), XINT (XCDR (frompos)),
1824 XINT (XCAR (frompos)), 0,
1825 XINT (to),
1826 (NILP (topos)
1827 ? window_internal_height (w)
1828 : XINT (XCDR (topos))),
1829 (NILP (topos)
1830 ? (window_box_text_cols (w)
1831 - (
1832 #ifdef HAVE_WINDOW_SYSTEM
1833 FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
1834 #endif
1835 1))
1836 : XINT (XCAR (topos))),
1837 (NILP (width) ? -1 : XINT (width)),
1838 hscroll, tab_offset,
1839 XWINDOW (window));
1840
1841 XSETFASTINT (bufpos, pos->bufpos);
1842 XSETINT (hpos, pos->hpos);
1843 XSETINT (vpos, pos->vpos);
1844 XSETINT (prevhpos, pos->prevhpos);
1845
1846 return Fcons (bufpos,
1847 Fcons (hpos,
1848 Fcons (vpos,
1849 Fcons (prevhpos,
1850 Fcons (pos->contin ? Qt : Qnil, Qnil)))));
1851
1852 }
1853
1854
1855
1856 struct position val_vmotion;
1857
1858 struct position *
1859 vmotion (from, vtarget, w)
1860 register EMACS_INT from, vtarget;
1861 struct window *w;
1862 {
1863 EMACS_INT hscroll = XINT (w->hscroll);
1864 struct position pos;
1865
1866 register int vpos = 0;
1867 EMACS_INT prevline;
1868 register EMACS_INT first;
1869 EMACS_INT from_byte;
1870 EMACS_INT lmargin = hscroll > 0 ? 1 - hscroll : 0;
1871 int selective
1872 = (INTEGERP (current_buffer->selective_display)
1873 ? XINT (current_buffer->selective_display)
1874 : !NILP (current_buffer->selective_display) ? -1 : 0);
1875 Lisp_Object window;
1876 EMACS_INT start_hpos = 0;
1877 int did_motion;
1878
1879 Lisp_Object text_prop_object;
1880
1881 XSETWINDOW (window, w);
1882
1883 1884
1885 if (EQ (w->buffer, Fcurrent_buffer ()))
1886 text_prop_object = window;
1887 else
1888 text_prop_object = Fcurrent_buffer ();
1889
1890 if (vpos >= vtarget)
1891 {
1892 1893
1894
1895 first = 1;
1896
1897 while ((vpos > vtarget || first) && from > BEGV)
1898 {
1899 Lisp_Object propval;
1900
1901 prevline = find_next_newline_no_quit (from - 1, -1);
1902 while (prevline > BEGV
1903 && ((selective > 0
1904 && indented_beyond_p (prevline,
1905 CHAR_TO_BYTE (prevline),
1906 (double) selective))
1907 1908
1909 || (propval = Fget_char_property (make_number (prevline - 1),
1910 Qinvisible,
1911 text_prop_object),
1912 TEXT_PROP_MEANS_INVISIBLE (propval))))
1913 prevline = find_next_newline_no_quit (prevline - 1, -1);
1914 pos = *compute_motion (prevline, 0,
1915 lmargin + (prevline == BEG ? start_hpos : 0),
1916 0,
1917 from,
1918
1919 1 << (BITS_PER_SHORT - 1),
1920
1921 1 << (BITS_PER_SHORT - 1),
1922 -1, hscroll,
1923 1924 1925
1926 (prevline == BEG ? -start_hpos : 0),
1927 w);
1928 vpos -= pos.vpos;
1929 first = 0;
1930 from = prevline;
1931 }
1932
1933 1934 1935
1936 if (vpos >= vtarget)
1937 {
1938 val_vmotion.bufpos = from;
1939 val_vmotion.bytepos = CHAR_TO_BYTE (from);
1940 val_vmotion.vpos = vpos;
1941 val_vmotion.hpos = lmargin;
1942 val_vmotion.contin = 0;
1943 val_vmotion.prevhpos = 0;
1944 val_vmotion.ovstring_chars_done = 0;
1945 val_vmotion.tab_offset = 0;
1946 return &val_vmotion;
1947 }
1948
1949
1950 }
1951 1952
1953 from_byte = CHAR_TO_BYTE (from);
1954 if (from > BEGV && FETCH_BYTE (from_byte - 1) != '\n')
1955 {
1956 Lisp_Object propval;
1957
1958 prevline = find_next_newline_no_quit (from, -1);
1959 while (prevline > BEGV
1960 && ((selective > 0
1961 && indented_beyond_p (prevline,
1962 CHAR_TO_BYTE (prevline),
1963 (double) selective))
1964 1965
1966 || (propval = Fget_char_property (make_number (prevline),
1967 Qinvisible,
1968 text_prop_object),
1969 TEXT_PROP_MEANS_INVISIBLE (propval))))
1970 prevline = find_next_newline_no_quit (prevline - 1, -1);
1971 pos = *compute_motion (prevline, 0,
1972 lmargin + (prevline == BEG
1973 ? start_hpos : 0),
1974 0,
1975 from,
1976
1977 1 << (BITS_PER_SHORT - 1),
1978
1979 1 << (BITS_PER_SHORT - 1),
1980 -1, hscroll,
1981 (prevline == BEG ? -start_hpos : 0),
1982 w);
1983 did_motion = 1;
1984 }
1985 else
1986 {
1987 pos.hpos = lmargin + (from == BEG ? start_hpos : 0);
1988 pos.vpos = 0;
1989 pos.tab_offset = 0;
1990 did_motion = 0;
1991 }
1992 return compute_motion (from, vpos, pos.hpos, did_motion,
1993 ZV, vtarget, - (1 << (BITS_PER_SHORT - 1)),
1994 -1, hscroll,
1995 pos.tab_offset - (from == BEG ? start_hpos : 0),
1996 w);
1997 }
1998
1999 DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 2, 0,
2000 doc: 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 )
2024 (lines, window)
2025 Lisp_Object lines, window;
2026 {
2027 struct it it;
2028 struct text_pos pt;
2029 struct window *w;
2030 Lisp_Object old_buffer;
2031 struct gcpro gcpro1;
2032 Lisp_Object lcols = Qnil;
2033 double cols;
2034
2035
2036 if (CONSP (lines) && (NUMBERP (XCAR (lines))))
2037 {
2038 lcols = XCAR (lines);
2039 cols = INTEGERP (lcols) ? (double) XINT (lcols) : XFLOAT_DATA (lcols);
2040 lines = XCDR (lines);
2041 }
2042
2043 CHECK_NUMBER (lines);
2044 if (! NILP (window))
2045 CHECK_WINDOW (window);
2046 else
2047 window = selected_window;
2048 w = XWINDOW (window);
2049
2050 old_buffer = Qnil;
2051 GCPRO1 (old_buffer);
2052 if (XBUFFER (w->buffer) != current_buffer)
2053 {
2054
2055 old_buffer = w->buffer;
2056 XSETBUFFER (w->buffer, current_buffer);
2057 }
2058
2059 if (noninteractive)
2060 {
2061 struct position pos;
2062 pos = *vmotion (PT, XINT (lines), w);
2063 SET_PT_BOTH (pos.bufpos, pos.bytepos);
2064 }
2065 else
2066 {
2067 int it_start, first_x, it_overshoot_expected;
2068
2069 SET_TEXT_POS (pt, PT, PT_BYTE);
2070 start_display (&it, w, pt);
2071 first_x = it.first_visible_x;
2072 it_start = IT_CHARPOS (it);
2073
2074
2075 if (XINT (lines) > 0)
2076 {
2077 if (it.cmp_it.id >= 0)
2078 it_overshoot_expected = 1;
2079 else if (it.method == GET_FROM_STRING)
2080 {
2081 const char *s = SDATA (it.string);
2082 const char *e = s + SBYTES (it.string);
2083 while (s < e && *s != '\n')
2084 ++s;
2085 it_overshoot_expected = (s == e) ? -1 : 0;
2086 }
2087 else
2088 it_overshoot_expected = (it.method == GET_FROM_IMAGE
2089 || it.method == GET_FROM_STRETCH);
2090 }
2091
2092 2093 2094
2095 reseat_at_previous_visible_line_start (&it);
2096 it.current_x = it.hpos = 0;
2097 if (IT_CHARPOS (it) != PT)
2098 2099 2100 2101
2102 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
2103
2104 if (XINT (lines) <= 0)
2105 {
2106 it.vpos = 0;
2107 2108
2109 if (XINT (lines) == 0 || IT_CHARPOS (it) > 0)
2110 move_it_by_lines (&it, XINT (lines), 0);
2111 }
2112 else
2113 {
2114 if (IT_CHARPOS (it) > it_start)
2115 {
2116 2117 2118 2119
2120 if (!it_overshoot_expected
2121 2122 2123 2124
2125 || (it_overshoot_expected < 0
2126 && it.method == GET_FROM_BUFFER
2127 && it.c == '\n'))
2128 move_it_by_lines (&it, -1, 0);
2129 it.vpos = 0;
2130 move_it_by_lines (&it, XINT (lines), 0);
2131 }
2132 else
2133 {
2134 2135 2136 2137
2138 if (it_start < ZV)
2139 {
2140 while (IT_CHARPOS (it) <= it_start)
2141 {
2142 it.vpos = 0;
2143 move_it_by_lines (&it, 1, 0);
2144 }
2145 if (XINT (lines) > 1)
2146 move_it_by_lines (&it, XINT (lines) - 1, 0);
2147 }
2148 else
2149 {
2150 it.vpos = 0;
2151 move_it_by_lines (&it, XINT (lines), 0);
2152 }
2153 }
2154 }
2155
2156
2157 if (!NILP (lcols))
2158 {
2159 2160
2161 if (first_x > 0)
2162 {
2163 move_it_in_display_line (&it, ZV, first_x, MOVE_TO_X);
2164 it.current_x = 0;
2165 }
2166 move_it_in_display_line
2167 (&it, ZV,
2168 (int)(cols * FRAME_COLUMN_WIDTH (XFRAME (w->frame)) + 0.5),
2169 MOVE_TO_X);
2170 }
2171
2172 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
2173 }
2174
2175 if (BUFFERP (old_buffer))
2176 w->buffer = old_buffer;
2177
2178 RETURN_UNGCPRO (make_number (it.vpos));
2179 }
2180
2181
2182
2183
2184
2185 void
2186 syms_of_indent ()
2187 {
2188 DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
2189 doc: );
2190 indent_tabs_mode = 1;
2191
2192 defsubr (&Scurrent_indentation);
2193 defsubr (&Sindent_to);
2194 defsubr (&Scurrent_column);
2195 defsubr (&Smove_to_column);
2196 defsubr (&Svertical_motion);
2197 defsubr (&Scompute_motion);
2198 }
2199
2200 2201