31.2.5 Перемещение по экранным строкам

Функции работы со строками из предыдущего раздела считают текстовые строки, ограниченные только символами новой строки. Напротив, эти функции считают экранные строки, которые определяются тем, как текст отображается на экране. Текстовая строка является одной экранной строкой, если она достаточно коротка, чтобы поместиться в ширину выбранного окна, но в противном случае она может занимать несколько экранных строк.

В некоторых случаях текстовые строки на экране обрезаются, а не продолжаются на дополнительные экранные строки. В таких случаях vertical-motion перемещает точку почти так же, как forward-line. См. Обрезание.

Поскольку ширина заданной строки зависит от флагов, управляющих отображением определённых символов, vertical-motion для одного и того же фрагмента текста ведёт себя по-разному в зависимости от буфера, в котором он находится, и даже от выбранного окна (поскольку ширина, флаг обрезания и таблица отображения могут различаться между окнами). См. Обычные соглашения по отображению.

Эти функции сканируют текст, чтобы определить, где разрываются экранные строки, и поэтому требуют времени, пропорционального пройденному расстоянию.

Функция: vertical-motion count &optional window cur-col

Эта функция перемещает точку в начало экранной строки, отстоящей на count экранных строк вниз от экранной строки, содержащей точку. Если count отрицателен, она перемещается вверх. Если count равен нулю, точка перемещается к визуальному началу текущей экранной строки.

Аргумент count может быть точечной парой (cols . lines) вместо целого числа. Тогда функция перемещается на lines экранных строк, как описано для count выше, и помещает точку на cols колонок от визуального начала этой экранной строки. Значение cols может быть числом с плавающей запятой и интерпретируется в единицах канонической ширины символа фрейма (см. Шрифт фрейма); это позволяет задавать точное горизонтальное положение точки, когда целевая экранная строка использует вариативные шрифты. Обратите внимание, что cols отсчитываются от визуального начала строки; если окно прокручено по горизонтали (см. Горизонтальная прокрутка), колонка, в которой окажется точка, добавляется к числу колонок, на которые прокручен текст, а если целевая строка является продолженной, её крайняя левая колонка считается нулевой (в отличие от функций, ориентированных на колонки, см. Подсчёт колонок).

Возвращаемое значение — это число экранных строк, на которое была перемещена точка. Значение может быть меньше по абсолютной величине, чем count, если достигнуто начало или конец буфера.

Окно window используется для получения таких параметров, как ширина, горизонтальная прокрутка и таблица отображения. Но vertical-motion всегда работает с текущим буфером, даже если в window в данный момент отображается какой-то другой буфер.

Необязательный аргумент cur-col задаёт текущую колонку в момент вызова функции. Это горизонтальная координата точки относительно окна, измеряемая в единицах ширины шрифта стандартного лица фрейма. Его указание ускоряет работу функции, особенно в очень длинных строках, поскольку функции не нужно возвращаться назад по буферу, чтобы определить текущую колонку. Обратите внимание, что cur-col также отсчитывается от визуального начала строки.

Функция: count-screen-lines &optional beg end count-final-newline window

Эта функция возвращает количество экранных строк в тексте от beg до end. Количество экранных строк может отличаться от количества фактических строк из-за продолжения строк, таблицы отображения и т.п. Если beg и end равны nil или опущены, они по умолчанию равны началу и концу доступной части буфера.

Если область заканчивается символом новой строки, он игнорируется, если только необязательный третий аргумент count-final-newline не равен nil.

Необязательный четвёртый аргумент window задаёт окно для получения таких параметров, как ширина, горизонтальная прокрутка и т.д. По умолчанию используются параметры выбранного окна.

Как и vertical-motion, count-screen-lines всегда использует текущий буфер, независимо от того, какой буфер отображается в window. Это позволяет использовать count-screen-lines в любом буфере, независимо от того, отображается ли он в данный момент в каком-либо окне.

Команда: move-to-window-line count

Эта функция перемещает точку относительно текста, отображаемого в данный момент в выбранном окне. Она перемещает точку в начало экранной строки, отстоящей на count экранных строк от верхней части окна; ноль означает самую верхнюю строку. Если count отрицателен, это задаёт позицию на −count строк от нижней части (или последней строки буфера, если буфер заканчивается выше указанной экранной позиции); таким образом, count равное −1 задаёт последнюю полностью видимую экранную строку окна.

Если count равен nil, точка перемещается в начало строки в середине окна. Если абсолютное значение count превышает размер окна, точка перемещается в место, которое отображалось бы на этой экранной строке, если бы окно было достаточно высоким. Это, вероятно, приведёт к тому, что при следующей перерисовке окно прокрутится, чтобы вывести это место на экран.

При интерактивном вызове count — это числовой префиксный аргумент.

Возвращаемое значение — это номер экранной строки, на которую переместилась точка, относительно верхней строки окна.

Функция: move-to-window-group-line count

Эта функция подобна move-to-window-line, за исключением того, что когда выбранное окно является частью группы окон (см. Группа окон), move-to-window-group-line перемещает точку относительно всей группы, а не только отдельного окна. Это условие выполняется, когда локальная переменная буфера move-to-window-group-line-function установлена в функцию. В этом случае move-to-window-group-line вызывает эту функцию с аргументом count и возвращает её результат.

Функция: compute-motion from frompos to topos width offsets window

Эта функция сканирует текущий буфер, вычисляя экранные позиции. Она сканирует буфер вперёд от позиции from, предполагая, что она находится на экранных координатах frompos, до позиции to или координат topos, в зависимости от того, что встретится раньше. Она возвращает конечную позицию в буфере и экранные координаты.

Координатные аргументы frompos и topos являются точечными парами вида (hpos . vpos).

Аргумент width — это количество колонок, доступных для отображения текста; он влияет на обработку продолженных строк. nil означает фактическое количество доступных текстовых колонок в окне, что эквивалентно значению, возвращаемому (window-width window).

Аргумент offsets — это либо nil, либо точечная пара вида (hscroll . tab-offset). Здесь hscroll — это количество колонок, не отображаемых на левом поле; большинство вызывающих получает это значение через window-hscroll. В то же время tab-offset — это смещение между номерами колонок на экране и номерами колонок в буфере. Оно может быть ненулевым в продолженной строке, когда ширина предыдущих экранных строк не даёт в сумме числа, кратного tab-width. В непродолженной строке оно всегда равно нулю.

Окно window служит только для указания, какую таблицу отображения использовать. compute-motion всегда работает с текущим буфером, независимо от того, какой буфер отображается в window.

Возвращаемое значение — это список из пяти элементов:

(pos hpos vpos prevhpos contin)

Здесь pos — это позиция в буфере, на которой остановилось сканирование, vpos — вертикальная экранная позиция, а hpos — горизонтальная экранная позиция.

Результат prevhpos — это горизонтальная позиция на один символ назад от pos. Результат contin равен t, если последняя строка была продолжена после (или внутри) предыдущего символа.

Например, чтобы найти позицию в буфере для колонки col экранной строки line некоторого окна, передайте стартовую позицию отображения окна как from и координаты верхнего левого угла окна как frompos. Передайте (point-max) буфера как to, чтобы ограничить сканирование концом доступной части буфера, и передайте line и col как topos. Вот функция, которая это делает:

(defun coordinates-of-position (col line)
  (car (compute-motion (window-start)
                       '(0 . 0)
                       (point-max)
                       (cons col line)
                       (window-width)
                       (cons (window-hscroll) 0)
                       (selected-window))))

При использовании compute-motion для минибуфера необходимо использовать minibuffer-prompt-width, чтобы получить горизонтальную позицию начала первой экранной строки. См. Содержимое минибуфера.