Text/Docu/ru/Rulers.odc

TextRulers

DEFINITION TextRulers;

	IMPORT Stores, Models, Views, Properties, TextModels;

	CONST
		first = 0; left = 1; right = 2; lead = 3; asc = 4; dsc = 5; grid = 6; opts = 7; tabs = 8;
		leftAdjust = 0; rightAdjust = 1; noBreakInside = 2; pageBreak = 3; parJoin = 4;
		rightFixed = 5;
		maxTabs = 32;
		centerTab = 0; rightTab = 1; barTab = 2;

	TYPE
		Tab = RECORD 
			stop: INTEGER;
			type: SET
		END;

		TabArray = RECORD
			len: INTEGER;
			tab: ARRAY maxTabs OF Tab
		END;

		Attributes = POINTER TO EXTENSIBLE RECORD (Stores.Store)
			init-: BOOLEAN;
			first-, left-, right-, lead-, asc-, dsc-, grid-: INTEGER;
			opts-: SET;
			tabs-: TabArray;
			(a: Attributes) InitFromProp (p: Properties.Property), NEW, EXTENSIBLE;
			(a: Attributes) ModifyFromProp- (p: Properties.Property), NEW, EXTENSIBLE;
			(a: Attributes) Equals (b: Attributes): BOOLEAN, NEW, EXTENSIBLE;
			(a: Attributes) Prop (): Properties.Property, NEW, EXTENSIBLE
		END;

		AlienAttributes = POINTER TO RECORD (Attributes)
			store-: Stores.Alien
		END;

		Style = POINTER TO ABSTRACT RECORD (Models.Model)
			attr-: Attributes;
			(s: Style) SetAttr (attr: Attributes), NEW, EXTENSIBLE
		END;

		Ruler = POINTER TO ABSTRACT RECORD (Views.View)
			style-: Style
		END;

		Prop = POINTER TO  RECORD (Properties.Property)
			first, left, right, lead, asc, dsc, grid: INTEGER;
			opts: RECORD 
				val, mask: SET
			END;
			tabs: TabArray
		END;

		UpdateMsg = RECORD (Models.UpdateMsg)
			style: Style;
			oldAttr: Attributes
		END;

		Directory = POINTER TO RECORD
			attr-: Attributes;
			(d: Directory) New (style: Style): Ruler, NEW, ABSTRACT;
			(d: Directory) NewFromProp (p: Prop): Ruler, NEW, EXTENSIBLE;
			(d: Directory) NewStyle (attr: Attributes): Style, NEW, ABSTRACT;
			(d: Directory) SetAttr (attr: Attributes), NEW, EXTENSIBLE
		END;

	VAR dir-, stdDir-: Directory;

	PROCEDURE ReadAttr (VAR rd: Stores.Reader; VAR a: Attributes);
	PROCEDURE WriteAttr (VAR wr: Stores.Writer; a: Attributes);
	PROCEDURE ModifiedAttr (a: Attributes; p: Properties.Property): Attributes;

	PROCEDURE SetCentered (r: Ruler);
	PROCEDURE SetJustified (r: Ruler);
	PROCEDURE SetLeftFlush (r: Ruler);
	PROCEDURE SetRightFlush (r: Ruler);
	PROCEDURE SetNoBreakInside (r: Ruler);
	PROCEDURE SetPageBreak (r: Ruler);
	PROCEDURE SetParJoin (r: Ruler);
	PROCEDURE SetAsc (r: Ruler; h: INTEGER);
	PROCEDURE SetDsc (r: Ruler; h: INTEGER);
	PROCEDURE SetFirst (r: Ruler; x: INTEGER);
	PROCEDURE SetGrid (r: Ruler; h: INTEGER);
	PROCEDURE SetLead (r: Ruler; h: INTEGER);
	PROCEDURE SetLeft (r: Ruler; x: INTEGER);
	PROCEDURE SetRight (r: Ruler; x: INTEGER);
	PROCEDURE SetFixedRight (r: Ruler; x: INTEGER);
	PROCEDURE AddTab (r: Ruler; x: INTEGER);
	PROCEDURE MakeBarTab (r: Ruler);
	PROCEDURE MakeCenterTab (r: Ruler);
	PROCEDURE MakeRightTab (r: Ruler);

	PROCEDURE CopyOf (r: Ruler; shallow: BOOLEAN): Ruler;
	PROCEDURE GetValidRuler (text: TextModels.Model; pos, hint: INTEGER;
												VAR ruler: Ruler; VAR rpos: INTEGER);
	PROCEDURE Deposit;
	PROCEDURE SetDir (d: Directory);

END TextRulers.

Текстовые линейки (TextRulers) - специальные отображения для текстов, которые, будучи внедренными в текст, влияют на его наборку. Линейки поддерживают интерактивную и программно-контролируемую настройку формата абзаца и, частично, формата страницы. Однако, сами линейки не выполняют наборку текста согласно определяемому ими формату. Наборка текста выполняется наборщиками (см. Раздел 6.4; TextSetters).


CONST first, left, right, lead, asc, dsc, grid, opts, tabs
Выборщики поля свойства
Означают, что соответственно именованное поле свойства Prop известно, определно, доступно только для чтения.

CONST leftAdjust, rightAdjust
Элементы множества Attributes.opts. Отсутствие обоих элементов в множестве означает выравнивание по центру; присутствие только leftAdjust - выравнивание по левому краю; присутствие только rightAdjust - по правому; присутствие обоих - по ширине.

CONST noBreakInside, pageBreak, parJoin
Элементы множества Attributes.opts. Включение элемента pageBreak преобладает над действием parJoin (если он включен). Включение элемента noBreakInside говорит наборщику о необходимости набирать последующие абзацы (до следующей линейки или до конца текста) таким образом, чтобы ни один из этих абзацев не был пересечен разрывом страницы; разрыв страницы может быть вставлен между абзацами, см. также parJoin ниже. (Такая наборка текста не всегда невозможна, или может привести к недопустимо большому пустому пространству, в этом случае наборщик так или иначе может вставить разрыв страницы.) Включение pageBreak требует продолжить наборку со следующей, чистой страницы. (Если наборка уже выполняется вверху новой страницы, это требование игнорируется.) Включение parJoin означает, что текст, расположенный после линейки, должен быть набран на той же странице, что и текст, расположенный после следующей линейки. (Опять же, наборщик может быть не в состоянии выполнить это требование и будет вынужен так или иначе вставить разрыв страницы.)

CONST rightFixed
Элемент множества Attributes.opts. Его включение означает, что правая граница текста фиксируется линейкой. Иначе в качестве правой границы используется правая граница среды (обычно - текстового отображения), в которой набирается текст.

CONST maxTabs
Максимальное число позиций табуляции, которое может храниться в структуре TabArray. Оно ограничивает число позиций табуляции, которое может быть определено на линейке.

CONST centerTab, rightTab, barTab
Элементы множества Tab.type. Табуляция будет центрированной (текст центрирован относительно позиции табуляции), если centerTab IN type. Табуляция будет выровненной вправо (текст справа от позиции табуляции) если rightTab IN type. Если ни одно из этих значений не включено, табуляция будет выровненной влево (текст слева от позиции табуляции). Включение обоих значений не допустимо. Если barTab IN type, то вдоль позиции табуляции от линейки её содержащей до следующей линейки либо конца текста проводится вертикальная черта. (Отрисовка этой черты оставляется на долю отображения, выводящего текст, содержащий линейку.)


TYPE Tab
Определяет одиночную позицию табуляции как пару из собственно позиции и типа табуляции.

stop: INTEGER	[универсальные единицы]
Позиция табуляции, отмеряемая от левой границы среды, в которой идет наборка текста, обычно - отображения, выводящего набранный текст.

type: SET
Тип табуляции, задающий наборку текста, относящегося к этой позиции табуляции. Параметры наборки извлекаются из множества {centerTab, rightTab, и barTab}, как определено выше.


TYPE TabArray
len: INTEGER	0 <= len <= maxTabs
Число определенных позиций табуляции.

tab-: ARRAY 32 OF Tab	[универсальные единицы]	tab[0 .. len) определены
Массив, хранящий заданные позиции табуляции.


TYPE Attributes (Stores.Store)
EXTENSIBLE
Стиль линейки хранит объект-атрибут.
Будучи созданы и инициализированы, объекты-атрибуты не могут быть изменены, и, поэтому, могут  совместно использоваться различными линейками для описания их стиля (в пределах одного домена). Изменение атрибутов стиля выполняется путем полной замены объекта-атрибута с ним связанного. Обычно изменятся копия исходного объекта-атрибута. (Стили же, в свою очередь, могут совместно использоваться несколькими линейками, что влечет за собой одновременное изменение всех этих линеек при изменении атрибутов стиля.)

init-: BOOLEAN
Объект-атрибут был инициализирован и более не может изменяться.

first-, left-, right-: INTEGER	[универсальные единицы]
Отступ первой строки всех последующих абзацев, левая граница (для всех остальных строк абзаца кроме первой), и правая граница. Все величины задаются относительно левой границы отображения, выводящего текст.

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

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

grid-: INTEGER	[универсальные единицы]	1 <= grid < 10000 * Ports.mm
Шаг сетки (если 1, то сетки нет). Каждая строка последующих абзацев набирается таким образом, что ее базовая линия совпадает с линией сетки. (В зависимости от используемого наборщика, это может привести к перекрытию высоких строк, или к тому, что более высокие строки будут смещены на последующие линии сетки для избежания перекрытия.)

opts-: SET
Параметры форматирования, выбираемые из множества {leftAdjust, rightAdjust, noBreakInside, pageBreak, parJoin}. Требования noBreakInside и parJoin могут быть выполнены либо нет, в зависимости от эвристики наборщика.

tabs-: TabArray
Описание позиций табуляции.

PROCEDURE (a: Attributes) Equals (b: Attributes): BOOLEAN
NEW, EXTENSIBLE
Проверка равенства двух объектов-атрибутов.

Предусловия
a.init	20
b # NIL	явно не проверяется
b.init	21

Постусловия
result = TypeOf(a) = TypeOf(b)  &  a.first = b.first  & ... &  a.tabs = b.tabs

PROCEDURE (a: Attributes) Prop (): Properties.Property
NEW, EXTENSIBLE
Возвращает список свойств, отражающих значения атрибута.

Предусловия
a.init	20

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

PROCEDURE (a: Attributes) ModifyFromProp- (p: Properties.Property)
NEW, EXTENSIBLE
Инициализирует новый объект-атрибут согласно значениям исходного объекта, которые изменяются согласно списку свойств. (Из списка свойств берутся значения свойств, которые определены, остальные значения остаются неизменны.) Эта процедура вызывается процедурой ModifiedAttr.

PROCEDURE (a: Attributes) InitFromProp (p: Properties.Property)
NEW, EXTENSIBLE
Инициализация согласно списку свойств; в качестве значений по умолчанию используется dir.attr.

Предусловия
~a.init	20

Постусловия
a.init


TYPE AlienAttributes (Attributes)
Тип нелегального объекта-атрибута, возвращаемый ReadAttr.

store-: Stores.Alien
Хранилище нелегал, обернутое нелегальным объектом-атрибутом.


TYPE Style (Models.Model)
ABSTRACT
Стиль линейки является ее моделью (и, поэтому, может использоваться несколькими линейками совместно).

attr-: Attributes
Атрибуты, определяющие стиль форматирования.

PROCEDURE (s: Style) SetAttr (attr: Attributes)
NEW, EXTENSIBLE, Операция
Установка атрибутов стиля.

Предусловия
attr # NIL	явно не проверятся
attr.init	20

Постусловия
s'.attr.Equals(attr)
	s.attr = s'.attr
~s'.attr.Equals(attr)
	s.attr = a	[ a.Equals(attr) ]


TYPE Ruler (Views.View)
ABSTRACT
Линейки - стандартные отображения стилей.

style-: Style
Стиль линейки.


TYPE Prop (Properties.Property)
Свойства, описывающие атрибуты стиля.

first, left, right, lead, asc, dsc, grid: INTEGER
opts: SET
tabs: TabArray
Поля свойства
Каждое поле свойства соответствует полю атрибута с тем же именем.


TYPE UpdateMsg (Models.UpdateMsg)
Сообщение, уведомляющее об изменении атрибутов некоторого стиля. Это сообщение домену (domaincast), оно обычно обрабатывается всеми текстовыми отображениями, которые содрежат линейки, использующие данный измененный стиль.

style: Style
Измененный стиль.

oldAttr: Attributes
Предыдущие атрибуты стиля style.


TYPE Directory
ABSTRACT
Фабрика линеек и стилей.

attr-: Attributes	attr # NIL
Атрибуты по умолчанию, используемые для инициализации нового стиля.

PROCEDURE (d: Directory) SetAttr (attr: Attributes)
NEW, EXTENSIBLE
Установка атрибутов по умолчанию. Параметры табуляции и разрыва страниц в attr игнорируются. (Т. к. предопределенные параметры табуляции в линейках по умолчанию часто противоречат программно устанавливаемым настройкам табуляции. Аналогично, параметры разрыва страниц не будут полезны в качестве глобальной установки по умолчанию.)

Предусловия
attr # NIL	явно не проверяется
attr.init	20

Постусловия
d.attr = ModifiedAttr(attr, p)
	[ p.valid = {opts, tabs},
		p.tabs.len = 0, p.opts.mask = {noBreakInside, pageBreak, parJoin}, p.opts.val = {}
	]

PROCEDURE (d: Directory) NewStyle (attr: Attributes): Style
NEW, ABSTRACT
Возвращает новый стиль, инициализированный атрибутами attr.

Предусловия
attr # NIL
	attr.init	20

Постусловия
result # NIL
attr = NIL
	result.attr = d.attr
attr # NIL
	result.attr = attr

PROCEDURE (d: Directory) New (style: Style): Ruler
NEW, ABSTRACT
Возвращает новую линейку, инициализированную стилем style.

Постусловия
result # NIL
style = NIL
	result.style = d.NewStyle(NIL)
style # NIL
	result.style = style

PROCEDURE (d: Directory) NewFromProp (p: Prop): Ruler
NEW, EXTENSIBLE
Возращает новую линейку, стиль которой инициализирован атрибутами из данного списка свойств p и значений по умолчанию из d.attr.

За исключением производительности, равносильно:
	VAR st: Stores.Stores; a: Attributes;
	st := Stores.Clone(d.attr); a := st(Attributnes);
	a.ModifyFrom(d.attr, p);
	RETURN d.New(d.NewStyle(a))


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


PROCEDURE  ReadAttr (VAR rd: Stores.Reader; VAR a: Attributes)
Читает объект-атрибут. Если считыватель возвращает хранилище-нелегал, оно обертывается нелегальным объектом-атрибутом, и возвращается обертка.

Предусловия
~rd.rider.eof	20
NextStore(rd) IS Attributes	21

Постусловия
a # NIL
~MapsToAlien(NextStore(rd'))
	a = NextStore(rd')
MapsToAlien(NextStore(rd'))
	a IS AlienAttributes
	a.store = NextStore(rd')

PROCEDURE  WriteAttr (VAR wr: Stores.Writer; a: Attributes)
Записывает объект-атрибут. В случае, если a - нелегальный объект-атрибут, то записывается содержащееся в нем хранилище-нелегал.

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

За исключением производительности, равносильно:
	WITH a: AlienAttributes DO wr.WriteStore(a.store) ELSE wr.WriteStore(a) END

PROCEDURE ModifiedAttr (a: Attributes; p: Properties.Property): Attributes
Возвращает новый объект-атрибут, содержащий те же атрибуты, что и a, за исключением тех, которые переопределяются определенными в p.

Предусловия
a # NIL	явно не проверяется
a.init	20

Постусловия
x IN p.valid
	x-attr(result) = x-attr(p)
~(x IN p.valid)
	x-attr(result) = x-attr(a)

За исключением производительности, равносильно:
	VAR h: Attributes;
	h := Stores.CopyOf(a)(Attributes); h.ModifyFromProp(p);
	RETURN h

PROCEDURE SetCentered (r: Ruler)
PROCEDURE SetJustified (r: Ruler)
PROCEDURE SetLeftFlush (r: Ruler)
PROCEDURE SetRightFlush (r: Ruler)
Операция
Установка режима форматирования, определяемого линейкой, путем установки r.style.attr.opts * {leftAdjust, rightAdjust} равным {}, {leftAdjust, rightAdjust}, {leftAdjust}, or {rightAdjust}, соответственно.

Предусловия
r.style # NIL	20

PROCEDURE SetNoBreakInside (r: Ruler)
PROCEDURE SetPageBreak (r: Ruler)
PROCEDURE SetParJoin (r: Ruler)
Операция
Установка параметров разрыва страниц путем включения noBreakInside, pageBreak, или parJoin в r.style.attr.opts, соответственно.

Предусловия
r.style # NIL	20

PROCEDURE SetFirst (r: Ruler; x: INTEGER)
PROCEDURE SetLeft (r: Ruler; x: INTEGER)
PROCEDURE SetLead (r: Ruler; h: INTEGER)
PROCEDURE SetAsc (r: Ruler; h: INTEGER)
PROCEDURE SetDsc (r: Ruler; h: INTEGER)
PROCEDURE SetGrid (r: Ruler; h: INTEGER)
Операция
Установка атрибутов форматирования, определяемых линейкой, путем задания r.style.attr.first, left, lead, asc, dsc, или grid, соответственно.

Предусловия
r.style # NIL	20

PROCEDURE SetRight (r: Ruler; x: INTEGER)
PROCEDURE SetFixedRight (r: Ruler; x: INTEGER)
Операция
Установка на линейке правой границы путем установки r.style.attr.right = x и установкой (SetFixedRight) или сбрасыванием (SetRight) r.attr.opts * {rightFixed}.

Предусловия
r.style # NIL	20

PROCEDURE AddTab (r: Ruler; x: INTEGER)
Операция
Добавление на линейку r новой позиции табуляции справа от уже заданных на ней.

Предусловия
r.style # NIL	20
r.style.attr.tabs.len = i
	i < maxTabs	21
	i > 0
		r.style.attr.tabs.tab[i - 1].stop < x	22

Постусловия
r.style.attr.tabs.len = r.style'.attr.tabs.len + 1
r.style.attr.tabs.tab[r.style.attr.tabs.len - 1].stop = x

PROCEDURE MakeBarTab (r: Ruler)
Операция
Добавление параметра barTab (отрисовка вертикальной черты) к настройкам последней позиции табуляции на линейке r.

Предусловия
r.style # NIL	20
r.style.attr.tabs.len > 0	21

Постусловия
barTab IN r.style.attr.tabs.tab[r.style.attr.tabs.len - 1].type

PROCEDURE MakeCenterTab (r: Ruler)
Операция
Смена типа последней позиции табуляции на линейке r на "центрированная".

Предусловия
r.style # NIL	20
r.style.attr.tabs.len > 0	21

Постусловия
r.style.attr.tabs.tab[r.style.attr.tabs.len - 1].type * {centerTab, rightTab} = centerTab

PROCEDURE MakeRightTab (r: Ruler)
Операция
Смена типа последней позиции табуляции на линейке r на "выровненная вправо".

Предусловия
r.style # NIL	20
r.style.attr.tabs.len > 0	21

Постусловия
r.style.attr.tabs.tab[r.style.attr.tabs.len - 1].type * {centerTab, rightTab} = righTab

PROCEDURE CopyOf (r: Ruler; shallow: BOOLEAN): Ruler
Создание (поверхностной - shallow = TRUE, или полной - shallow = FALSE) копии линейки.

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

За исключением производительности, равносильно:
	VAR v: Views.View;
	v := Views.CopyOf(r, shallow); RETURN v(Ruler)

PROCEDURE GetValidRuler (text: TextModels.Model; pos, hint: INTEGER;
													VAR ruler: Ruler; VAR rpos: INTEGER);
Определение положения линейки в тексте text, которая задает правила набора в позиции pos. Если известно положение некоторой линейки, оно может быть передано в качестве подсказки следующим образом: (ruler, rpos) - первая линейка перед позицией hint. Иначе, передавайте hint = -1. При возврате, либо определяющая линейка передается в (ruler, rpos), либо ruler и rpos не изменяются.

Предусловия
hint < 0  OR  rpos = Pos(ruler) &  нет линеек в (rpos, hint]  &  0 <= pos <= t.Length()

Постусловия
hint < rpos <= pos  &  rpos = Pos(ruler)  &  нет линеек в (rpos, pos]  OR  (ruler, rpos) не изменились

За исключением производительности, равносильно:
	VAR view: Views.View; rd: TextModels.Reader;
	IF pos < text.Length() THEN INC(pos) END;	(* пусть линейка определяющая сама для себя! *)
	IF pos < hint THEN hint := -1 END;
	rd := text.NewReader(rd); rd.SetPos(pos);
	REPEAT
		rd.ReadPrevView(view)
	UNTIL rd.eot OR (view IS Ruler) OR (rd.Pos() < hint);
	IF (view # NIL) & (view IS Ruler) THEN
		ruler := view(Ruler); rpos := rd.Pos()
	END

PROCEDURE Deposit
Создает новую линейку и помещает её в очередь отображений.

За исключением производительности, равносильно:
	Views.Deposit(dir.New(NIL))

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

Предусловия
d # NIL	20
d.attr # NIL		явно не проверяется
d.attr.init	21