Text/Docu/ru/Models.odc

TextModels

DEFINITION TextModels;

	IMPORT Fonts, Ports, Stores, Models, Views, Properties, Containers;

	CONST
		viewcode = 2X;
		tab = 9X; line = 0DX; para = 0EX;
		zwspace = 8BX; nbspace = 0A0X; digitspace = 8FX;
		hyphen = 90X; nbhyphen = 91X; softhyphen = 0ADX;
		maskChar = 0; hideable = 1;
		offset = 0; code = 1;
		store = 0;
		replace = 0; insert = 1; delete = 2;

	TYPE
		Model = POINTER TO ABSTRACT RECORD (Containers.Model)
			(m: Model) Length (): INTEGER, NEW, ABSTRACT;
			(m: Model) NewReader (old: Reader): Reader, NEW, ABSTRACT;
			(m: Model) NewWriter (old: Writer): Writer, NEW, ABSTRACT;
			(m: Model) Insert (pos: INTEGER; m0: Model; beg0, end0: INTEGER), NEW, ABSTRACT;
			(m: Model) InsertCopy (pos: INTEGER; m0: Model; beg0, end0: INTEGER), NEW, ABSTRACT;
			(m: Model) Delete (beg, end: INTEGER), NEW, ABSTRACT;
			(m: Model) Append (m0: Model), NEW, ABSTRACT;
			(m: Model) Replace (beg, end: INTEGER; m0: Model; beg0, end0: INTEGER), NEW, ABSTRACT
			(m: Model) SetAttr (beg, end: INTEGER; attr: Attributes), NEW, EXTENSIBLE;
			(m: Model) Prop (beg, end: INTEGER): Properties.Property, NEW, ABSTRACT;
			(m: Model) Modify (beg, end: INTEGER; old, p: Properties.Property), NEW, ABSTRACT;
			(m: Model) ReplaceView (old, new: Views.View), ABSTRACT;
		END;

		Attributes = POINTER TO EXTENSIBLE RECORD (Stores.Store)
			init-: BOOLEAN;
			color-: Ports.Color;
			font-: Fonts.Font;
			offset-: INTEGER;
			(a: Attributes) Equals (b: Attributes): BOOLEAN, NEW, EXTENSIBLE;
			(a: Attributes) Prop (): Properties.Property, NEW, EXTENSIBLE;
			(a: Attributes) InitFromProp (p: Properties.Property), NEW, EXTENSIBLE;
			(a: Attributes) ModifyFromProp- (p: Properties.Property), NEW, EXTENSIBLE
		END;

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

		Prop = POINTER TO RECORD (Properties.Property)
			offset: INTEGER;
			code: CHAR
		END;

		Context = POINTER TO ABSTRACT RECORD (Models.Context)
			(c: Context) ThisModel (): Model, ABSTRACT;
			(c: Context) Pos (): INTEGER, NEW, ABSTRACT;
			(c: Context) Attr (): Attributes, NEW, ABSTRACT
		END;

		Pref = RECORD (Properties.Preference)
			opts: SET;
			mask: CHAR
		END;

		Reader = POINTER TO ABSTRACT RECORD
			eot: BOOLEAN;
			attr: Attributes;
			char: CHAR;
			view: Views.View;
			w, h: INTEGER;
			(rd: Reader) Base (): Model, NEW, ABSTRACT;
			(rd: Reader) SetPos (pos: INTEGER), NEW, ABSTRACT;
			(rd: Reader) Pos (): INTEGER, NEW, ABSTRACT;
			(rd: Reader) Read, NEW, ABSTRACT;
			(rd: Reader) ReadChar (OUT ch: CHAR), NEW, ABSTRACT;
			(rd: Reader) ReadView (OUT v: Views.View), NEW, ABSTRACT;
			(rd: Reader) ReadRun (OUT attr: Attributes), NEW, ABSTRACT;
			(rd: Reader) ReadPrev, NEW, ABSTRACT;
			(rd: Reader) ReadPrevChar (OUT ch: CHAR), NEW, ABSTRACT;
			(rd: Reader) ReadPrevView (OUT v: Views.View), NEW, ABSTRACT;
			(rd: Reader) ReadPrevRun (OUT attr: Attributes), NEW, ABSTRACT
		END;

		Writer = POINTER TO ABSTRACT RECORD
			attr-: Attributes;
			(wr: Writer) Base (): Model, NEW, ABSTRACT;
			(wr: Writer) Pos (): INTEGER, NEW, ABSTRACT;
			(wr: Writer) SetPos (pos: INTEGER), NEW, ABSTRACT;
			(wr: Writer) SetAttr (attr: Attributes), NEW;
			(wr: Writer) WriteChar (ch: CHAR), NEW, ABSTRACT;
			(wr: Writer) WriteView (view: Views.View; w, h: INTEGER), NEW, ABSTRACT
		END;

		InfoMsg = RECORD (Models.Message)
			op: INTEGER
		END;

		UpdateMsg = RECORD (Models.UpdateMsg)
			op: INTEGER;
			beg, end, delta: INTEGER
		END;

		Directory = POINTER TO ABSTRACT RECORD
			attr-: Attributes;
			(d: Directory) New (): Model, NEW, ABSTRACT;
			(d: Directory) NewFromString (s: ARRAY OF CHAR): Model, NEW, EXTENSIBLE;
			(d: Directory) SetAttr (attr: Attributes), NEW, EXTENSIBLE
		END;

	VAR dir-, stdDir-: Directory;

	PROCEDURE NewColor (a: Attributes; color: Ports.Color): Attributes;
	PROCEDURE NewFont (a: Attributes; font: Fonts.Font): Attributes;
	PROCEDURE NewOffset (a: Attributes; offset: INTEGER): Attributes;
	PROCEDURE NewTypeface (a: Attributes; typeface: Fonts.Typeface): Attributes;
	PROCEDURE NewSize (a: Attributes; size: INTEGER): Attributes;
	PROCEDURE NewStyle (a: Attributes; style: SET): Attributes;
	PROCEDURE NewWeight (a: Attributes; weight: INTEGER): Attributes;

	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 CloneOf (source: Model): Model;

	PROCEDURE WriteableChar (ch: CHAR): BOOLEAN;

	PROCEDURE SetDir (d: Directory);

END TextModels.

Модуль TextModels определяет текстовые модели, которые являются моделями-контейнерами и содержат форматированный текст, в который могут быть внедрены произвольные отображения. Текст может содержать символы из набора Блэкбокc, которые соответствуют кодовой таблице Unicode. Однако, текущая реализация поддерживает только символы из кодовой таблицы ASCII и её расширения Windows-1251 (русифицированная версия) и Latin-1 (оригинальная версия).


CONST viewcode
Означает, что считанный символ на самом деле является внедренным отображением. Константа viewcode используется как основное значение типа CHAR, которое подставляется вместо внедренного отображения при чтении текста посимвольно.

CONST tab
Символ табуляции. При форматировании текста означает, что размещение текста надо продолжить со следующией позиции табуляции. Позиции табуляции задаются каким-либо образом, например, отмечаются на линейке. (Для текстовых отображений именно так и делается - позиции табуляции отмечаются на специальном внедренном в текст отображении - текстовой линейке. См. TextRulers.)

CONST line
Символ-разделитель строк. Для наборщика текста означает, что набор надо продолжить со следующей строки. Заметьте, что символ line не означает начало нового абзаца (см. para ниже).

CONST para
Символ-разделитель абзацев. Для наборщика текста означает, что набор надо продолжить со следующей строки и начать на ней новый абзац (см. line выше).

CONST zwspace
Пробельный символ нулевой ширины. Является разделителем слов, однако сам по себе места не занимает и не виден.

CONST nbspace
Неразрывный пробел. Его ширина такая же, как и у обычного пробела, оданко, в отличие от него, символ nbspace не является разделителем слов.

CONST digitspace
Цифровой пробел. В большинстве шрифтов его ширина равна ширине цифры ноль (0), которая, в свою очередь, в большинстве шрифтов эквивалентна ширине всех остальных цифр. Символ digitspace не является разделителем слов. (Замечание: Рекомендация об использовании digitspace для форматирования чисел, данная в предыдущих версиях, устарела. Используйте позиции табуляции с выравниванием по правому краю. См. TextRulers.)

CONST hyphen
Символ переноса или дефиса. Предназначен для явного и видимого разбиения слова на слоги или разделения слов. Наборщик может начать новую строку только после символа hyphen.

CONST nbhyphen
Неразрывный дефис. Смысл такой же как у символа hyphen, однако наборщик не будет начинать новую строку после него.

CONST softhyphen
Мягкий перенос. Смысл такой же как у символа hyphen, с тем отличием, что softhyphen отображается только в том случае, если после него начинается новая строка. Символ softhyphen можно использовать в качестве подсказки наборщику о местах разрыва наиболее длинных слов.


CONST maskChar
Элемент множества опций
Может быть элементом множества Pref.opts. Означает, что внедренное отображение предпочитает замаскироваться под обычный символ. В большинстве случаев замаскированное отображение ведет себя как этот символ. Главное назначение маскировки - упрощение обработки текста при его сканировании. (Например, текстовая линейка может быть замаскирована под символ para. В этом случае текстовый сканер может определить число абзацев в тексте просто подсчитав число символов para, обнаруженных при сканировании.)

CONST hideable
Элемент множества опций
Может быть элементом множества Pref.opts. Означает, что внедренное отображение разрешает показать или скрыть себя в зависимости от режима текстового отображения. (Например, текстовые линейки могут быть скрыты, позволяя пользователю скрыть или показать их в отображаемом тексте.)

CONST offset, code
Выборщики поля свойства
Означают, что соответствующее поле свойства Prop известно, определено, доступно только для чтения.

CONST store
Возможное значение InfoMsg.op, означающее, что текст, рассылающий сообщение, был сохранен. Это единственное значение, которое сейчас определено для этого поля.

CONST replace
Возможное значение UpdateMsg.op, говорящее об успешной замене участка в тексте, рассылающем сообщение.

CONST insert
Возможное значение UpdateMsg.op, говорящее об успешной вставке участка в текст, рассылающий сообщение.

CONST delete
Возможное значение UpdateMsg.op, говорящее об успешном удалении участка в тексте, рассылающем сообщение.


TYPE Model (Containers.Model)
ABSTRACT
Текстовая модель - модель-контейнер, содержащая форматированный текст с внедренными в него отображениями.

PROCEDURE (m: Model) Length (): INTEGER
NEW, ABSTRACT
Длина текста в m, равная общему числу символов и внедренных отображений.

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

PROCEDURE (m: Model) NewReader (old: Reader): Reader
NEW, ABSTRACT
Возвращает считыватель, подсоединенный к m. В качестве входного параметра может быть указан уже существующий считыватель, который более не используется. Отметьте, что NewReader не меняет положения в считывателе old, если это положение корректно для m и будет принято решение об его повторном использовании. (Решение о повторном использовании считывателя NewReader принимает на основе внутреннего критерия совместимости old и m.)

Постусловия
result # NIL
result = old  &  old'.Base() = m  &  old'.Pos() <= m.Length()
	result.Pos() = old'.Pos()
~(result = old  &  old'.Base() = m  &  old'.Pos() <= m.Length())
	result.Pos() = 0

PROCEDURE (m: Model) NewWriter (old: Writer): Writer
NEW, ABSTRACT
Возвращает записыватель, подсоединенный к m. В качестве входного параметра может быть указан уже существующий записыватель, который более не используется. Отметьте, что NewWriter не меняет положения в записывателе old, если это положение корректно для m и будет принято решение об его повторном использовании. (Решение о повторном использовании записывателя NewWriter принимает на основе внутреннего критерия совместимости old и m.)

Постусловия
result # NIL
result.attr = dir.attr
result = old  &  old'.Base() = m  &  old'.Pos() <= m.Length()
	result.Pos() = old'.Pos()
~(result = old  &  old'.Base() = m  &  old'.Pos() <= m.Length())
	result.Pos() = m.Length()

PROCEDURE (m: Model) Insert (pos: INTEGER; m0: Model; beg0, end0: INTEGER)
NEW, ABSTRACT, Операция
Вырезает участок текста [beg0, end0) из m0 и вставляет его в текст m с позиции pos. В случае, если реализации m0 и m различаются, участок текста m0 преобразуется к реализации m при помощи считывателя. Длина m0 уменьшается, в то время как длина m увеличивается на (end0 - beg0).

Предусловия
0 <= pos	21
pos <= Length(m)	22
0 <= beg0	23
beg0 <= end0	24
end0 <= Length(m0)	25
m0 # NIL	явно не проверяется

Постусловия
m = m0
	Length(m) = Length(m0) = Length(m') = Length(m0')
m # m0
	Length(m) = Length(m') + (end0 - beg0)
	Length(m0) = Length(m0') - (end0 - beg0)

PROCEDURE (m: Model) InsertCopy (pos: INTEGER; m0: Model; beg0, end0: INTEGER)
NEW, ABSTRACT, Операция
Копирует участок текста [beg0, end0) из m0 и вставляет его в текст m с позиции pos. В случае, если реализации m0 и m различаются, участок текста m0 преобразуется к реализации m при помощи считывателя.

Предусловия
0 <= pos	21
pos <= Length(m)	22
0 <= beg0	23
beg0 <= end0	24
end0 <= Length(m0)	25
m0 # NIL	явно не проверяется

Постусловия
Length(m) = Length(m') + (end0 - beg0)
m0 = m
	Length(m0) = Length(m)
m0 # m
	Length(m0) = Length(m0')

PROCEDURE (m: Model) Delete (beg, end: INTEGER);
NEW, ABSTRACT, Операция
Удаляет отрезок текста [beg, end) в m.

Предусловия
0 <= beg	20
beg <= end	21
end <= Length(m)	22

Постусловия
Length(m) = Length(m') - (end - beg)

PROCEDURE (m: Model) Append (m0: Model)
NEW, ABSTRACT, Операция
Добавляет m0 к m.

За исключением быстродействия, равносильно:
	m.Insert(m.Length(), m0, 0, m0.Length())

PROCEDURE (m: Model) Replace (beg, end: INTEGER; m0: Model; beg0, end0: INTEGER)
NEW, ABSTRACT, Операция
Вырезает участок текста [beg0, end0) из m0 и замещает участок [beg, end) в m на участок, вырезанный из m0.

Предусловия
0 <= beg	20
beg <= end	21
end <= Length(m)	22
0 <= beg0	23
beg0 <= end0	24
end0 <= Length(m0)	25
m # m0	26
m0 # NIL	явно не проверяется

За исключением быстродействия, равносильно:
	VAR script: Stores.Operation;
	Models.BeginScript(m, "#System:Replacing", script);
	m.Delete(beg, end); m.Insert(beg, m0, beg0, end0);
	Models.EndScript(m, script)

PROCEDURE (m: Model) SetAttr (beg, end: INTEGER; attr: Attributes)
NEW, ABSTRACT, Операция
Устанавливает атрибуты всех элементов на участке [beg, end) в m равными attr.

Предусловия
0 <= beg	20
beg <= end	21
end <= Length(m)	22
attr # NIL	явно не проверяется
attr.init	23

PROCEDURE (m: Model) Prop (beg, end: INTEGER): Properties.Property
NEW, ABSTRACT
Возвращает список свойств, описывающий свойства всех элементов на отрезке [beg, end) в m. В списке содержатся только свойства атрибутов текста и свойства, описываемые типом Prop. Рекурсивных запросов свойств внедренных отображений не производится.
Результатом будет пересечение свойств атрибутов текста из однородных по свойствам участков в [beg, end). Например, если первая половина участка выделена полужирным и курсивом, а вторая курсивом, то Prop вернет свойство "курсив", т. е. однородное подмножество.

Предусловия
0 <= beg	20
beg <= end	21
end <= Length(m)	22

PROCEDURE (m: Model) Modify (beg, end: INTEGER; old, p: Properties.Property)
NEW, ABSTRACT, Операция
Изменяет свойства на участке [beg, end) в m согласно заданному в p списку свойств. Если дан old, то изменение выполняется только в случае когда участок однороден по свойствам, указанным в old, и значения этих свойств совпадают со значениями данными в old.

Предусловия
0 <= beg	20
beg <= end	21
end <= Length(m)	22

Постусловия
old = NIL  OR  old = Intersect(m'.Prop(beg, end), old)
	m.Prop(beg, end) = p

PROCEDURE (m: Model) ReplaceView (old, new: Views.View)
NEW, ABSTRACT, Операция
Сохраняет контекст old, заменяя при этом old на new.

Предусловия
old # NIL	20
new # NIL	21
old.context # NIL	22
new.context = NIL OR new.context = old.context	23

Постусловия
new.context = old.context


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

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

color-: Ports.Color
Хранимое (поле)
Цвет, которым должен отображаться объект, обладающий данным атрибутом. Для символов в тексте - это цвет "переднего плана", т. е. цвет самих символов. Для внедренных отображений этот атрибут либо игнорируется, либо используется особым образом самим отображением. (Обычно он используется специфическими для текста отображениями - отображениями, которые знают, что они внедрены в текст.)

font-: Fonts.Font
Хранимое
Шрифт, которым должен отображаться объект, обладающий данным атрибутом. Для символов - это шрифт, из которого извлекается изорбражение символа. Для внедреных отображений этот атрибут либо игнорируется, либо используется особым образом самим отображением.

offset-: INTEGER
Хранимое
Вертикальное смещение относительно базовой линии (в универсальных единицах), которое используется для отображения объекта, обладающего данным атрибутом.

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

Предусловия
a.init	20
(b # NIL) & b.init	21

Постусловия
result = (TypeOf(a) = TypeOf(b)) & (a.color = b.color) & (a.font = b.font) & (a.offset = b.offset)

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
Инициализация согласно списку свойств.

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

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


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

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


TYPE Prop (Properties.Property)
Особые свойства текста: вертикальное смещение и коды символа.

offset: INTEGER
Вертикальное смещение.

code: CHAR
Код символа.


TYPE Context (Models.Context)
ABSTRACT
Контекст для отображений, внедренных в тексты.

PROCEDURE (c: Context) ThisModel (): Model
ABSTRACT
Тип результата говорит сам за себя.

PROCEDURE (c: Context) Pos (): INTEGER
NEW, ABSTRACT
Положение внедренного отображения в тексте.

PROCEDURE (c: Context) Attr (): Attributes
NEW, ABSTRACT
Атрибуты, определенные для внедренного отображения.


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

opts: SET
Множество опций предпочтений, изначально равное {}. Возможные значения - подмножества {maskChar, hideable}.

mask: CHAR
Если maskChar IN opts, mask - символ, которым желает замаскироваться отображение.


TYPE Reader
ABSTRACT
Считыватель текста - для чтения символов и внедренных отображений.

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

attr: Attributes	~eot => attr # NIL
Атрибуты последнего прочитанного элемента.

char: CHAR
Последний прочитанный символ. Равен viewcode, если последний считанный элемент был отображением, которое не маскирует себя каким-либо другим символом (см. Pref).

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

w, h: INTEGER	определено, если view # NIL
Ширина и высота последнего считанного отображения.

PROCEDURE (rd: Reader) Base (): Model
NEW, ABSTRACT
Носитель курьера: текст, к которому он подключен.

PROCEDURE (rd: Reader) Pos (): INTEGER
NEW, ABSTRACT
Положение считывателя в тектсте.

Постусловия
0 <= result
result <= rd.Base().Length()

PROCEDURE (rd: Reader) SetPos (pos: INTEGER)
NEW, ABSTRACT
Установка положения считывателя.

Предусловия
0 <= pos	20
rd.Base() # NIL	21
pos <= rd.Base().Length()	22

Постусловия
rd.Pos() = pos

PROCEDURE (rd: Reader) Read
NEW, ABSTRACT
Чтение следующего элемента текста.

Постусловия
~rd.eot
	rd.Pos() = rd'.Pos() + 1, rd.attr # NIL, rd.attr.init
	rd.view # NIL
		maskChar IN Prefs(view).opts, ch = Prefs(view).mask
			rd.char = ch
		~(maskChar IN Prefs(view).opts)
			rd.char = viewcode
rd.eot
	rd.Pos() = rd'.Pos(), rd.attr = NIL, rd.char = 0X, rd.view = NIL

PROCEDURE (rd: Reader) ReadPrev
NEW, ABSTRACT
Чтение предыдущего элемента в тексте: сначала уменьшает rd.Pos(), затем читает элемент в положении rd.Pos().

Постусловия
~rd.eot
	rd.Pos() = rd'.Pos() - 1, rd.attr # NIL, rd.attr.init
	rd.view # NIL
		maskChar IN Prefs(view).opts, ch = Prefs(view).mask
			rd.char = ch
		~(maskChar IN Prefs(view).opts)
			rd.char = viewcode
rd.eot
	rd.Pos() = rd'.Pos(), rd.attr = NIL, rd.char = 0X, rd.lchar = 0, rd.view = NIL

PROCEDURE (rd: Reader) ReadChar (OUT ch: CHAR)
NEW, ABSTRACT
Чтение следующего символа или символа-проекции для внедренного отображения.

За исключением производительности, равносильно:
	rd.Read; ch := rd.char

PROCEDURE (rd: Reader) ReadPrevChar (OUT ch: CHAR)
NEW, ABSTRACT
Чтение предыдущего символа или символа-проекции для внедренного отображения.

За исключением производительности, равносильно:
	rd.ReadPrev; ch := rd.char

PROCEDURE (rd: Reader) ReadView (OUT v: Views.View)
NEW, ABSTRACT
Чтение следующего отображения.

За исключением производительности, равносильно:
	REPEAT rd.Read UNTIL (rd.view # NIL) OR rd.eot;
	v := rd.view

PROCEDURE (rd: Reader) ReadPrevView (OUT v: Views.View)
NEW, ABSTRACT
Чтение предыдущего отображения.

За исключением производительности, равносильно:
	REPEAT rd.ReadPrev UNTIL (rd.view # NIL) OR rd.eot;
	v := rd.view

PROCEDURE (rd: Reader) ReadRun (OUT attr: Attributes)
NEW, ABSTRACT
Чтение следующего набора атрибутов, остановка если попадается отображение.

За исключением производительности, равносильно:
	VAR a: Attributes;
	a := rd.attr;
	REPEAT rd.Read UNTIL (rd.attr # a) OR (rd.view # NIL) OR rd.eot;
	IF rd.eot THEN attr := NIL ELSE attr := rd.attr END

Постусловия
~rd.eot
	attr # NIL, rd.attr.init
	rd.view = ViewAt(rd.Pos() - 1)

PROCEDURE (rd: Reader) ReadPrevRun (OUT attr: Attributes)
NEW, ABSTRACT
Чтение предыдущего набора атрибутов, остановка если попадается отображение.

За исключением производительности, равносильно:
	VAR a: Attributes;
	a := rd.attr;
	REPEAT rd.ReadPrev UNTIL (rd.attr # a) OR (rd.view # NIL) OR rd.eot;
	IF rd.eot THEN attr := NIL ELSE attr := rd.attr END

Постусловия
~rd.eot
	attr # NIL, rd.attr.init
	rd.view = ViewAt(rd.Pos())


TYPE Writer
ABSTRACT
Записыватель - пишет символы или внедряет отображения в текст.

attr-: Attributes	attr # NIL, attr.init
Объект-атрибут, который приписывается следующему записываемому элементу. (Атрибуты неизменны, поэтому они разделяемы, т. е. нет необходимости копировать их при использовании где-либо еще в том же домене.)

PROCEDURE (wr: Writer) Base (): Model
NEW, ABSTRACT
Носитель курьера, т. е. текст, к которому подключен записыватель.

PROCEDURE (wr: Writer) Pos (): INTEGER
NEW, ABSTRACT
Положение записывателя в тексте.

Постусловия
0 <= result
result <= wr.Base().Length()

PROCEDURE (wr: Writer) SetPos (pos: INTEGER)
NEW, ABSTRACT
Установка положения записывателя.

Предусловия
0 <= pos	20
wr.Base() # NIL	21
pos <= wr.Base.Length()	22

Постусловия
wr.Pos() = pos

PROCEDURE (wr: Writer) SetAttr (attr: Attributes)
NEW
Установка текущего набора атрибутов записывателя.

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

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

PROCEDURE (wr: Writer) WriteChar (ch: CHAR)
NEW, ABSTRACT, Операция
Записывает символ с атрибутами wr.attr. Ничего не происходит, если ch не печатный (см. процедуру WriteableChar).

Постусловия
WriteableChar(ch)
	wr.Pos() = wr.Pos'() + 1
~WriteableChar(ch)
	wr.Pos() = wr.Pos'()

PROCEDURE (wr: Writer) WriteView (view: Views.View; w, h: INTEGER)
NEW, ABSTRACT, Операция
Записывает отображение с шириной w, высотой h, и атрибутами wr.attr. w и h могут быть равны Views.undefined.

Предусловия
view # NIL	20
view.context = NIL	21

Постусловия
view.context # NIL
view.context.Pos() = wr.Pos()'
view.context.Attr() = w	[ w.Equals(wr.attr) ]


TYPE InfoMsg (Models.Message)
Сообщение, уведомляющее о выполнении операции, не изменяющей текст.

op: INTEGER
Для стандартных текстов определен единственный код операции: store.


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

op: INTEGER
Тип выполненной операции. Для стандартных текстов, op IN {replace, insert, delete}.

beg, end, delta: INTEGER
Операция была выполнена на участке [beg, end), определенном после выполнения операции, и изменила длину текста на delta. Для удалений длины l, end = beg + 1, delta = -l; для вставок длины l, end = beg + l, delta = l; для замен длины l, не изменяющих длины текста, end = beg + l, delta = 0.


TYPE Directory
ABSTRACT
Фабрика текстовых моделей.

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

PROCEDURE (d: Directory) New (): Model;
NEW, ABSTRACT
Возвращает новую текстовую модель.

PROCEDURE (d: Directory) NewFromString (s: ARRAY OF CHAR): Model
NEW, EXTENSIBLE
Возвращает новую текстовую модель, содержащую текст из s, записанный с атрибутами по умолчанию.

За исключением производительности, равносильно:
	VAR m: Model; w: Writer; i: INTEGER;
	m := d.New(); w := m.NewWriter(NIL);
	i := 0; WHILE s[i] # 0X DO w.WriteChar(s[i]); INC(i) END;
	RETURN m

PROCEDURE (d: Directory) SetAttr (attr: Attributes)
NEW, EXTENSIBLE
Установка атрибутов по умолчанию.

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

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


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


PROCEDURE  NewColor (a: Attributes; color: Ports.Color): Attributes
PROCEDURE  NewTypeface (a: Attributes; typeface: Fonts.Typeface): Attributes
PROCEDURE  NewSize (a: Attributes; size: INTEGER): Attributes
PROCEDURE  NewStyle (a: Attributes; style: SET): Attributes
PROCEDURE  NewWeight (a: Attributes; weight: INTEGER): Attributes
PROCEDURE  NewOffset (a: Attributes; offset: INTEGER): Attributes
Получают существующий объект-атрибут и возвращают новый с такими же атрибутами, за исключением одного указанного.

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

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

PROCEDURE  NewFont (a: Attributes; font: Fonts.Font): Attributes
Полностью изменят шрифт в атрибуте, т. е. насыщенность, начертание, размер и гарнитуру.

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

За исключением производительности, равносильно:
	NewTypeface(NewSize(NewStyle(NewWeight(
		a, font.weight), font.style), font.size), font.typeface)

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

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

Постусловия
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  WriteableChar (ch: CHAR): BOOLEAN
Определяет, является ли символ ch печатным, т. е. можно ли его записать в текст.

Постусловия
result =
	ch = tab  OR  ch = line  OR  ch = para  OR
	ch >= " "  &  ch < 07FX  OR
	ch = zwspace  OR  ch = digitspace  OR  ch = hyphen  OR  ch = nbhyphen  OR
	ch >= 0A0X	20

PROCEDURE  CloneOf (source: Model): Model
Это процедура предназначена для получения нового текста, тип которого равен типу уже существующего текста source.

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

За исключением производительности, равносильно:
		RETURN Containers.CloneOf(source)(Model)

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

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