Text/Docu/ru/Setters.odc

TextSetters

DEFINITION TextSetters;

	IMPORT Stores, Views, Properties, TextModels, TextRulers;

	CONST lineBreak = 0; wordJoin = 1; wordPart = 2; flexWidth = 3;

	TYPE
		Pref = RECORD (Properties.Preference)
			opts: SET;
			endW: INTEGER;
			dsc: INTEGER
		END;

		Reader = POINTER TO ABSTRACT RECORD
			r-: TextModels.Reader;
			sString: ARRAY 64 OF SHORTCHAR;
			string: ARRAY 64 OF CHAR;
			view: Views.View;
			textOpts: SET;
			mask: CHAR;
			setterOpts: SET;
			w, endW, h, dsc: INTEGER;
			attr: TextModels.Attributes;
			eot: BOOLEAN;
			pos: INTEGER;
			x: INTEGER;
			adjStart: INTEGER;
			spaces: INTEGER;
			tabIndex: INTEGER;
			tabType: SET;
			vw: INTEGER;
			hideMarks: BOOLEAN;
			ruler: TextRulers.Ruler;
			rpos: INTEGER;
			(rd: Reader) Set (old: TextModels.Reader; text: TextModels.Model; x, pos: INTEGER;
										ruler: TextRulers.Ruler; rpos, vw: INTEGER; hideMarks: BOOLEAN),
										NEW, EXTENSIBLE;
			(rd: Reader) Read, NEW, EXTENSIBLE;
			(rd: Reader) AdjustWidth (start, pos: INTEGER; IN box: LineBox; VAR w: INTEGER),
										NEW, ABSTRACT;
			(rd: Reader) SplitWidth (w: INTEGER): INTEGER, NEW, ABSTRACT
		END;

		Setter = POINTER TO ABSTRACT RECORD (Stores.Store)
			text-: TextModels.Model;
			defRuler-: TextRulers.Ruler;
			vw-: INTEGER;
			hideMarks-: BOOLEAN;
			(s: Setter) ConnectTo (text: TextModels.Model; defRuler: TextRulers.Ruler;
										vw: INTEGER; hideMarks: BOOLEAN), NEW, EXTENSIBLE;
			(s: Setter) ThisPage (pageH: INTEGER; pageNo: INTEGER): INTEGER, NEW, ABSTRACT;
			(s: Setter) NextPage (pageH: INTEGER; start: INTEGER): INTEGER, NEW, ABSTRACT;
			(s: Setter) ThisSequence (pos: INTEGER): INTEGER, NEW, ABSTRACT;
			(s: Setter) NextSequence (start: INTEGER): INTEGER, NEW, ABSTRACT;
			(s: Setter) PreviousSequence (start: INTEGER): INTEGER, NEW, ABSTRACT;
			(s: Setter) GetWord (pos: INTEGER; OUT beg, end: INTEGER), NEW, ABSTRACT;
			(s: Setter) GetLine (start: INTEGER; OUT box: LineBox), NEW, ABSTRACT;
			(s: Setter) GetBox (start, end, maxW, maxH: INTEGER; OUT w, h: INTEGER), NEW, ABSTRACT;
			(s: Setter) NewReader (old: Reader): Reader, NEW, ABSTRACT;
			(s: Setter) GridOffset (dsc: INTEGER; IN box: LineBox): INTEGER, NEW, ABSTRACT
		END;

		LineBox = RECORD
			len: INTEGER;
			ruler: TextRulers.Ruler;
			rpos: INTEGER;
			left, right, asc, dsc: INTEGER;
			rbox, bop, adj, eot, views: BOOLEAN;
			skipOff: INTEGER;
			adjOff: INTEGER;
			spaces: INTEGER;
			adjW: INTEGER;
			tabW: ARRAY TextRulers.maxTabs OF INTEGER
		END;

		Directory = POINTER TO RECORD
			(d: Directory) New (): Setter, NEW, ABSTRACT
		END;

	VAR dir-, stdDir-: Directory;

	PROCEDURE SetDir (d: Directory);

END TextSetters.


Модуль TextSetters выполняет наборку (размещение) текста (одномерного потока символов и внедренных отображений) на двумерные колонки или страницы. Особые внедренные отображения, называемые линейками, распознаются при наборке и определяют способ размещения текста.


CONST lineBreak, wordJoin, wordPart, flexWidth
Элементы множества Pref.opts, определяющие предпочтения внедренных отображений касательно наборки текста. Включение в множество lineBreak аннулирует действие wordJoin.
Включение lineBreak является запросом к наборщику о разрыве сроки сразу после отображения.
Включение wordJoin означает, что отображение не должно рассматриваться как разделитель слов, расположенных слева и справа от него. (Т. е. трактуется как неразрывный пробел.)
Включение wordPart означает, что отображение должно рассматриваться как часть слова, в которое он внедрено (что отражается на промежутке, выделяемом операцией "выделить слово").
Включение flexWidth означает, что отображение должно рассматриваться аналогично обычным пробелам, т. е. его ширина будет подгоняться под нужную величину, если наборка выполняется в режиме выравнивания по ширине.


TYPE Pref (Properties.Preference)
Возможные предпочтения внедренных отображений касательно наборки текста.

opts: SET
Параметры наборки, из множества {lineBreak, wordJoin, wordPart, flexWidth}, согласно определенным выше правилам.

endW: INTEGER	[универсальные единицы]	изначально равно ширине отображения
Если отображение оказывается в конце строки, т. е. разрыв строки оказывается непосредственно за ним, отображение может запросить ширину, отличную от его обычной ширины. (Например, мягий перенос имеет положительную ширину в конце сторки, при обычной нулевой; обычная ширина пробела - положительна, в конце строки же - нулевая.)

dsc: INTEGER	[универсальные единицы]	изначально = преобладающему подстрочному элементу
Отображение может запросить особое значение подстрочного элемента, которое повлияет на его размещение относительно базовой линии.


TYPE Reader
ABSTRACT
Считыватель для чтения построчно, возвращаемый наборщиком. 
A reader to read through lines returned by a setter. Этот считыватель - концептуальное расширение TextModels.Reader, он не только возвращает считываемые элементы потока, но и размещает их в строке, возвращая их координаты относительно базовой линии строки.

r-: TextModels.Reader
Текстовый считыватель, используемый для подключения считывателя к тексту. Состояние текстового считывателя соответствует состоянию считывателя через одно чтение.

sString: ARRAY 64 OF SHORTCHAR
Если sString # "", то последний считанный элемент был символом типа SHORTCHAR или строкой таких символов. Одиночный символ возвращается в sString[0]. Если view # NIL, то последний считанный элемент был отображением, замаскированным символом типа SHORTCHAR.

string: ARRAY 64 OF CHAR
Если string # "", то последний считанный элемент был символом или строкой символов. Одиночный символ возвращается в string[0]. Если view # NIL, то последний считанный элемент - отображение, замаскированное данным символом.

view: Views.View
Последний считанный элемент был внедренным отображением.

textOpts: SET
mask: CHAR
setterOpts: SET
w, endW, h, dsc: INTEGER	[универсальные единицы]
attr: TextModels.Attributes
Свойства и текстовые атрибуты последнего считанного элемента. Все свойства выставляются в значения по умолчанию. Они могут быть переопределены либо элементом-отображением, высказавшим особые предпочтения (т. е. обработавшим соответствующие сообщения), либо особыми свойствами специальных символов (таких как табуляция и проч.).

eot: BOOLEAN
Устанавливается, если последнее чтение выполнялось в конце текста.

pos: INTEGER
Положение считывателя в тексте (следующая позиция за конечным положением последнего считанного элемента).

x: INTEGER	[универсальные единицы]
Горизонтальное положение считывателя в строке. Должно смещаться клиентом считывателя. Если наборка выполняется без выравнивания, увеличивайте на w, иначе используйте AdjustWidth, описываемую ниже.

adjStart: INTEGER	[универсальные единицы]
Начальное положение (включительно) области, в которой выполняется выравнивание. Используется, чтобы подавить выравнивание во всех частях строки, кроме последней, на которые она разбивается символами табуляции.

spaces: INTEGER
Число пробелов, обнаруженных считывателем. (Сбрасывается в 0, когда adjStart выставляется при прочтении символа tab.)

tabIndex: INTEGER
Индекс последней обработанной позиции табуляции (изначально -1).

tabType: SET
Тип послденей обработанной позиции табуляции (изначально {}).

vw: INTEGER	[универсальные единицы]
Ширина, относительно которой выполняется наборка текста.

hideMarks: BOOLEAN
Запрос о скрытии скрываемых отметок в набираемой строке. Если считыватель обнаруживает внедренное отображение, которое согласно его текстовых предпочтений является скрываемым (hideable) и hideMarks установлено, то ширина и высота отображения уменьшаются до 0.

ruler: TextRulers.Ruler
Линейка, по которой выполняется набор текущей строки.

rpos: INTEGER
Положение в тексте линейки, по которой выполняется набор строки. (rpos = -1 если таковая линейка в тексте отсутствует. Обычно это имеет место, если в самом начале (в положении 0) текста нет линейки и правила набора определяются линейкой по умолчанию.)

PROCEDURE (rd: Reader) Set (old: TextModels.Reader;
														text: TextModels.Model; x, pos: INTEGER;
														ruler: TextRulers.Ruler; rpos, vw: INTEGER;
														hideMarks: BOOLEAN)
NEW, EXTENSIBLE
Подключает считыватель к строке текста с возможным повторным использованием уже существующего текстового считывателя, который более ни где не нужен. Считывателю даются text, горизонтальная координата левой границы строки x, начало строки в тексте pos, определяющая правила набора линейка ruler и ее положение в тексте rpos, и hideMarks, определяющее будут ли скрыты или нет скрываемые пометки. vw - ширина области в которой будет выполняться наборка текста.

Предусловия
text # NIL	20
0 <= pos	21
pos <= text.Length()	22
ruler # NIL	23
-1 <= rpos	24
rpos <= pos	25

Постусловия
rd.r # NIL
rd.r.Base() = text
rd.r.eot OR rd.r.Pos() = pos + 1
rd.sString = ""
rd.string = ""
rd.view = NIL
rd.textOpts = {}
rd.setterOpts = {}
rd.w = 0, rd.endW = 0, rd.h = 0, rd.dsc = 0
rd.attr = NIL
rd.eot = FALSE
rd.pos = pos
rd.x = x
rd.adjStart = pos, rd.spaces = 0
rd.tabIndex = -1, rd.tabType = {}
rd.ruler = ruler, rd.rpos = rpos
rd.hideMarks = hideMarks

PROCEDURE (rd: Reader) Read
NEW, EXTENSIBLE (для вызова в начале переопределяющего метода в расширении Reader)
Чтение следующего элемента в строке.

Постусловия
~rd.r.eot
	rd.r.Pos() = rd.r'.Pos() + 1
~rd.eot
	view # NIL
		rd.pos = rd'.pos + 1
	string # ""
		rd.pos = rd'.pos + Length(rd.string)
	lstring # ""
		rd.pos = rd'.pos + Length(rd.string)
rd.eot
	rd.w = rd.endW = 0
	rd.h = ruler.style.attr.asc + ruler.style.attr.dsc
	rd.dsc = ruler.style.attr.dsc

PROCEDURE (rd: Reader) AdjustWidth (start, pos: INTEGER; IN box: LineBox;
																		VAR w: INTEGER)
NEW, ABSTRACT
Даны параметры box набираемой строки, её начальное положение start, положение pos последнего прочитанного считывателем элемента (обычно pos = rd.pos). AdjustWidth берет ширину w этого элемента (обычно w = rd.w) и подгоняет её согласно требуемому форматированию строки.

PROCEDURE (rd: Reader) SplitWidth (w: INTEGER): INTEGER
NEW, ABSTRACT
Вычисляет ширину разбиения для последнего считанного элемента. Применяется в интерактивных целях, когда ширина разбиения делит координаты на два полуинтервала: все координаты слева от точки разбиения принадлежат к левой границе элемента, все координаты справа от точки разбиения принадлежат правой границе.

Постусловия
0 <= result <= w


TYPE Setter (Stores.Store)
ABSTRACT
Наборщик, который может быть использован для наборки текста в строки, абзацы, колонки и страницы.

text-: TextModels.Model	наборщик подключен если text # NIL
Набираемый текст.

defRuler-: TextRulers.Ruler
Линейка по умолчанию, определяющая правила набора в начале текста - до первой линейки в тексте.

vw-: INTEGER	[универсальные единицы]
Полная ширина строки, в которой наборщик будет набирать текст.

hideMarks-: BOOLEAN
Если установлено, все внедренные отображения, которые согласно их предпочтениям скрываемы, будут уменьшены до нулевой ширины и высоты.

PROCEDURE (s: Setter) ConnectTo (text: TextModels.Model; defRuler: TextRulers.Ruler;
																vw: INTEGER; hideMarks: BOOLEAN)
NEW, EXTENSIBLE
Если наборщик был подключен к некоторому тексту, он отключается от него. После наборщик подключается к данному тексту (если text # NIL), используя линейку по умолчанию defRuler и установку о скрытии меток hideMarks. vw - ширина области в которой будет набираться текст.

Предусловия
text # NIL
	defRuler # NIL	явно не проверяется

Постусловия
text = NIL
	s.text = NIL
	s.defRuler = NIL
text # NIL
	s.text = text
	s.defRuler = defRuler
	s.vw = vw
	s.hideMarks = hideMarks

PROCEDURE (s: Setter) ThisPage (pageH: INTEGER; pageNo: INTEGER): INTEGER
NEW, ABSTRACT
Определяет начальное положение в тексте страницы с номером pageNo (при нумерации страниц с 0) при высоте страницы pageH. 

Предусловия
Connected(s)	20
0 <= pageNo	21

Постусловия
pageNo > LastPageNo(s.text, pageH)
	result = -1
pageNo <= LastPageNo(s.text, pageH)
	result = PageStart(pageNo)

PROCEDURE (s: Setter) NextPage (pageH: INTEGER; start: INTEGER): INTEGER
NEW, ABSTRACT
Находит положение в тексте следующей страницы для данных высоты страницы pageH и начального положения текущей страницы start.

Предусловия
Connected(s)	20
0 <= start	21
start <= s.text.Length()	22
Существует pNo: s.ThisPage(pageH, pNo) = start	явно не проверяется

Постусловия
start = LastPage(s.text, pageH)
	result = s.text.Length()
start < LastPage(s.text, pageH)
	result = PageStart(PageNo(s.text, start) + 1)

PROCEDURE (s: Setter) ThisSequence (pos: INTEGER): INTEGER
NEW, ABSTRACT
Находит начальное положение последовательности (ограниченной символами line или para), содержащей позицию pos.

Предусловия
Connected(s)	20
0 <= pos	21
pos <= s.text.Length()	22

Постусловия
result = 0  OR  char[result - 1] IN {line, para}

PROCEDURE (s: Setter) NextSequence (start: INTEGER): INTEGER
NEW, ABSTRACT
Находит начальное положение следующей последовательности (ограниченной символами line или para), используя начальное положение start текущей последовательности.

Предусловия
Connected(s)	20
0 <= start	21
start <= s.text.Length()	22
s.ThisSequence(start) = start	23

Постусловия
Для любых pos: start < pos < s.text.Length(): s.ThisSequence(pos) = start
	result = start
s.ThisSequence(result - 1) = start
	result > start
	s.ThisSequence(result) = result

PROCEDURE (s: Setter) PreviousSequence (start: INTEGER): INTEGER
Находит начальное положение предыдущей последовательности (ограниченной символами line или para), используя начальное положение start текущей последовательности.

Предусловия
Connected(s)	20
0 <= start	21
start <= s.text.Length()	22
s.ThisSequence(start) = start	23

Постусловия
start = 0
	result = 0
start > 0
	result = s.ThisSequence(start - 1)

PROCEDURE (s: Setter) ThisLine (pos: INTEGER): INTEGER
Находит начальное положение строки, содержащей позицию pos.

Предусловия
Connected(s)	20
0 <= pos	21
pos <= s.text.Length()	22

Постусловия
result <= pos
pos < s.NextLine(result)  OR  LastLine(result)

PROCEDURE (s: Setter) NextLine (start: INTEGER): INTEGER
NEW, ABSTRACT
Находит начальное положение следующей строки, используя начальное положение start текущей строки.

Предусловия
Connected(s)	20
0 <= start	21
start <= s.text.Length()	22
s.ThisLine(start) = start	23

Постусловия
LastLine(start)
	result = start
~LastLine(start)
	result > start
	s.ThisLine(result - 1) = start

PROCEDURE (s: Setter) PreviousLine (start: INTEGER): INTEGER
NEW, ABSTRACT
Находит начальное положение предыдущей строки, используя начальное положение start текущей строки.

Предусловия
Connected(s)	20
0 <= start	21
start <= s.text.Length()	22
s.ThisLine(start) = start	23

Постусловия
start = 0
	result = 0
start > 0
	result < start
	result = s.ThisLine(start - 1)

PROCEDURE (s: Setter) GetWord (pos: INTEGER; OUT beg, end: INTEGER)
Находит начальную beg и конечную end позиции слова, содержащего позицию pos. Словом считается последовательность символов с кодами > " ", или отображений с маской > " ", или отображений с предпочтением wordPart.

Предусловия
Connected(s)	20
0 <= pos	21
pos <= s.text.Length()	22

Постусловия
beg <= pos <= end

PROCEDURE (s: Setter) GetLine (start: INTEGER; OUT box: LineBox)
NEW, ABSTRACT
Вычисляет параметры строки, начинающейся с позиции start. (См. ниже тип LineBox.)

Предусловия
Connected(s)	20
0 <= start	21
start <= s.text.Length()	22
s.ThisLine(start) = start	23

Постусловия
min{box.left, box.first} <= box.left <= box.right <= ruler.right
~box.eot
	box.ruler # NIL
	box.len > 0

PROCEDURE (s: Setter) GetBox (start, end, maxW, maxH: INTEGER; OUT w, h: INTEGER)
NEW, ABSTRACT
Вычисляет размеры прямоугольной области, ограничивающей участок текста с начальным положением start, которое является также началом строки, и конечным положением end. Вычисление заканчивается, если участок текста был набран полностью, либо если были достигнуты предельные значения по ширине maxW или по высоте maxH.

Предусловия
Connected(s)	20
0 <= start	21
start <= end	22
end <= s.text.Length()	23

Постусловия
maxW > Views.undefined
	w <= maxW
maxH > Views.undefined
	h <= maxH

PROCEDURE (s: Setter) NewReader (old: Reader): Reader
Возвращает новый считыватель, по возможности используя повторно данный существующий считыватель, который более нигде не используется. (Будет или нет использован повторно считыватель old определяется на основе внутренних условий совместимости.)

Предусловия
Connected(s)	20

Постусловия
result # NIL

PROCEDURE (s: Setter) GridOffset (dsc: INTEGER; VAR box: LineBox): INTEGER
Используя данные подстрочный элемент предыдущей строки dsc и параметры текущей строки box, вычисляет коррекцию для сетки таким образом, чтобы текущая строка оказалась на линии сетки. Если текущая строка является первой (в тексте или на текущей странице), должен передаваться dsc = -1.

Предусловия
Connected(s)
dsc >= -1

Постусловия
~box.rbox
	Существует k: k >= 0: dsc + GridOffset(dsc, box) + box.asc =
									k * ruler.grid >= ruler.asc + ruler.grid
box.rbox
	result = 0


TYPE LineBox
Параметры строки, набираемой наборщиком.

len: INTEGER
Длина строки.

ruler: TextRulers.Ruler
rpos: INTEGER
Линейка, по которой выполняется набор строки, и ее положение в тексте. (rpos = -1 означает, что правила набора определяет линейка по умолчанию.)

left, right, asc, dsc: INTEGER	[универсальные единицы]
Левая и правая границы, надстрочный и подстрочный элементы строки.

rbox: BOOLEAN
Строка содержит исключительно линейку или разделитель абзацев (непосредственно символ para или его же в качестве маски внедренного отображения).

bop: BOOLEAN
Строка - первая в абзаце, её левое поле равно ruler.first; иначе левое поле равно ruler.left.

adj: BOOLEAN
Окончательное формирование строки требует установки интервалов: ширина хотя бы одного элемента строки должна быть искуственно изменена, чтобы достигнуть требуемого форматом эффетка.

eot: BOOLEAN
Строка либо пустая, либо содержит последний элемент текста, который не является ни символом line, ни символом para, ни соответствующей маской.

views: BOOLEAN
Строка содержит хотя бы одно внедренное отображение.

skipOff: INTEGER	0 <= skipOff <= len
В качестве ширины символов на участвке [skipOff, len) должна браться endW.

adjOff: INTEGER	0 <= adjOff <= len
Смещение последнего блока (последовательности, не ограниченной символом tab). Если строка выравнивается (по центру, по правому краю или по ширине), то это позиция в строке, с которой должно начинаться выравнивание.

spaces: INTEGER	определено и > 0 если adj
Число пробелов, подлежащих выравниванию.

adjW: INTEGER	[универсальные единицы]	определено и > 0 если adj
Выравнивающее значение, которое должно быть добавлено либо к началу последнего блока при выравнивании по центру и по правому краю, либо к каждому пробельному элементу (пробел, отображение замаскированное под пробел или отображение с предпочтением flexWidth) при выравнивании по ширине.

tabW: ARRAY TextRulers.maxTabs OF INTEGER	[унив-е ед.]	диапазон [0 .. ruler.style.attr.tabs.len)
Ширина промежутков перед позициями табуляции.


TYPE Directory
ABSTRACT
Фабрика наборщиков.

PROCEDURE (d: Directory) New (): Setter
NEW, ABSTRACT
Возвращает новый наборщик.


VAR dir-, stdDir-: Directory	dir # NIL, stdDir # NIL, stable stdDir = d
Фабрика и стандартная фабрика наборщиков.


PROCEDURE SetDir (d: Directory)
Установка фабрики наборщиков.

Предусловия
d # NIL	20

Постусловия
dir = d