hodza/BlackBox.Shkola.2014 huggingface dataset:
i21sys/Mod/Script.odc

MODULE  i21sysScript;  (* Fyodor Tkachov 2009-10-21 *)
	IMPORT  Log := StdLog,  Files,  HostFiles,  i21sysFiles,  Stores,  Dialog,  i21sysCalls;
	
	PROCEDURE CreateVbs*;
		CONST
			vbsname = '#i21sys:StartupBlackBox'; 
			cannotCreate = '#i21sys:CannotCreateVbs';
			type = 'vbs';
		VAR  loc, rsrc: Files.Locator;  f, new: Files.File;  rd: Stores.Reader;  wr: Stores.Writer;  
			path: ARRAY 2000 OF CHAR;  fi: Files.FileInfo;  res: INTEGER;  b: BYTE;
			string: ARRAY 200 OF CHAR;
	BEGIN
		loc := Files.dir.This('');
		path := loc( HostFiles.Locator ).path$;
		loc := Files.dir.This( path ); (* to prevent BB from looking for files in the primary BlackBox directory *)
		
(* this is a nuisance of little help
		fi := Files.dir.FileList( loc );
		WHILE ( fi # NIL ) & ( fi.name # (vbsname + '.' + type) ) DO
			fi := fi.next
		END;
		IF  fi # NIL  THEN
			Dialog.GetOK( vbsname + ' already exists -- cannot continue', '','','', {Dialog.ok}, res );
			HALT( 128 );
		END;
*)
		
		fi := Files.dir.FileList( loc );
		WHILE  ( fi # NIL ) & ( fi.name # 'BlackBox.exe' )  DO
			fi := fi.next
		END;
		
		IF  fi = NIL  THEN
			Dialog.GetOK( cannotCreate, '', '', '', {Dialog.ok}, res );
			HALT( 128 );
		END;
		
		path := loc( HostFiles.Locator ).path$ + '\BlackBox.exe';
		
		new := Files.dir.New( loc, Files.dontAsk );
		wr.ConnectTo( new );
		
		rsrc := loc.This( 'i21sys/Rsrc' );
		f := Files.dir.Old( rsrc, '1', Files.shared );
		rd.ConnectTo( f );
		rd.ReadByte( b );
		WHILE  ~rd.rider.eof  DO
			wr.WriteByte( b );
			rd.ReadByte( b );
		END;
		rd.ConnectTo( NIL );
		
		wr.WriteSString( SHORT( path ) );  wr.SetPos( wr.Pos() - 1 );

		f := Files.dir.Old( rsrc, '2', Files.shared );
		rd.ConnectTo( f );
		rd.ReadByte( b );
		WHILE  ~rd.rider.eof  DO
			wr.WriteByte( b );
			rd.ReadByte( b );
		END;
		rd.ConnectTo( NIL );
		
		wr.ConnectTo( NIL );
		Dialog.MapString( vbsname, string );
		new.Register( string$, 'vbs', Files.ask, res );  ASSERT( res = 0 );
	END CreateVbs; 
	
END  i21sysScript.

i21sysScript.CreateVbs
i21sys/Mod/Text.odc

MODULE i21sysText;
	IMPORT  Log := StdLog,  In := i21sysIn,  Ports,  Strings,  TextControllers,  M := TextModels;
	
	PROCEDURE Offset0*;
	(** guard: TextCmds.SelectionGuard **)
		VAR  c: TextControllers.Controller;  t: M.Model;  rd: M.Reader;
			beg, end: INTEGER;  a, new: M.Attributes;  ch: CHAR;  
	BEGIN
		c := TextControllers.Focus();
		IF (c # NIL) & c.HasSelection() THEN
			c.GetSelection(beg, end);
			t := c.text;  
			rd := t.NewReader(rd);
			rd.SetPos(end - 1);
			rd.ReadChar(ch);
			a := rd.attr;
			new := M.NewOffset(a, 0);
			t.SetAttr(beg, end, new);
			c.SetSelection(beg, end);
		END
	END Offset0;

	PROCEDURE Raise*;
	(** guard: TextCmds.SelectionGuard **)
		VAR  c: TextControllers.Controller;  t: M.Model;  rd: M.Reader;
			beg, end: INTEGER;  a, new: M.Attributes;  ch: CHAR;
	BEGIN
		c := TextControllers.Focus();
		IF (c # NIL) & c.HasSelection() THEN
			c.GetSelection(beg, end);
			t := c.text;  rd := t.NewReader(rd);
			rd.SetPos(end - 1);
			rd.ReadChar(ch);
			a := rd.attr;
			new := M.NewOffset(a, a.offset + Ports.point DIV 2);
			t.SetAttr(beg, end, new);
			c.SetSelection(beg, end)
		END
	END Raise;

	PROCEDURE Lower*;
	(** guard: TextCmds.SelectionGuard **)
		VAR  c: TextControllers.Controller;  t: M.Model;  rd: M.Reader;
			beg, end: INTEGER;  a, new: M.Attributes;  ch: CHAR;
	BEGIN
		c := TextControllers.Focus();
		IF  (c # NIL) & c.HasSelection()  THEN
			c.GetSelection(beg, end);
			t := c.text;
			rd := t.NewReader(rd);
			rd.SetPos(end - 1);
			rd.ReadChar(ch);
			a := rd.attr;
			new := M.NewOffset(a, a.offset - Ports.point DIV 2);
			t.SetAttr(beg, end, new);
			c.SetSelection(beg, end);
		END
	END Lower;
	
	
END i21sysText.
i21sys/Mod/VocabularyTest.odc

MODULE i21sysVocabularyTest;
	IMPORT  Log := StdLog,
		S := i21sysScanner,  V := i21sysVocabulary;
	
	TYPE
		Entry = POINTER TO RECORD ( V.Entry )
			s: S.String;
		END;
	
	PROCEDURE ( e: Entry ) Log;
	BEGIN  Log.Tab;  Log.String( e.s );
	END Log;
	
	PROCEDURE Do*;
		VAR  v: V.Vocabulary;  e, f: Entry;  f0: V.Entry;
	BEGIN
		v.Init;
	
		S.Open('', 'keywords');

		S.Next;  ASSERT( S.done );
		NEW( e );
		v.Insert( e, S.string );
		S.Next;  ASSERT( S.done );
		e.s := S.string;
		
		S.Next;  ASSERT( S.done );
		NEW( e );
		v.Insert( e, S.string );
		S.Next;  ASSERT( S.done );
		e.s := S.string;
		
		v.Log;
		
		V.silent := FALSE;
		
		NEW( e );
		v.Insert( e, 'ABS' );
		e.s := '00000';
		
		v.Log;
		
		f0 := v.Find('A', FALSE);
		IF f0 # NIL THEN
			f := f0(Entry)
		END;
		Log.String( 'non-exact search: ' + f.key );  Log.Ln;
		
		f0 := v.Find('A', TRUE);
		IF f0 # NIL THEN
			f := f0(Entry);
			Log.String( 'exact search: ' + f.key );  Log.Ln;
		ELSE
			Log.String( 'exact search failed' );  Log.Ln;
		END;
		
		v.Init;
		Log.String('after Init: ');  Log.Ln;
		v.Log;
		
		HALT( 7 );
	END Do;

END i21sysVocabularyTest.Do
i21sys/Rsrc/hints.odc

% Словарик подсказок.
% F5 пытается угадать ключевое слово по первым буквам. 
% Однако может быть несколько ключевых слов, начинающихся одинаково.
%
% Например, одинаковая первая буква есть у пяти слов: IF, IN, INC, INCL и INTEGER.
% Из них у четырех одинаковые первые две, а у двух  первые две.
% Однако из них намного чаще встречается слово INTEGER, поэтому хотелось бы гарантировать, чтобы именно INTEGER "угадывалось" по первой букве i клавишей F5.
% Для этого и служит список подсказок:
%
% Первой идет комбинация начальных букв.
% Затем то слово, которое хотелось бы "угадать" именно по этим начальным буквам. 
% В комментарии после % указано, с каким ключевым словом может быть путаница.
%
% Не требуется, чтобы список был упорядочен по алфавиту.
% В обоих позициях могуть быть любые литерные цепочки в кавычках  см. пример в конце.
%
% О синтаксических правилах записи словариков см. русскую документацию к модулю i21sysAuxScanner.
% 2012-04-27  info21
	A	ARRAY
	AS	ASSERT  	% ASH 
	B	BOOLEAN  	% BITS
	C	CHAR  	% CHR
	CH	CHAR  
	D	DIV  	% DIJKSTRA
	DI	DIV  	% DIJKSTRA
	EN	ENTIER  	% END
	END	END  	% чтобы исключить раскрытие в ENDASH
	EX	EXTENSIBLE	% EXIT  
	F	FALSE  	% FOR
	I	INTEGER  	% IN 
	IN	IN  	% иначе in может раскрыться в INTEGER
	INC	INC  	% INCL
	M	MODULE  	% MOD
	P	PROCEDURE  	% POINTER   
	R	REAL  	% RECORD, REPEAT 
	RE	REAL  
	T	TRUE	% TO
	W	WHILE  	% WITH
	INFO	"Информатика-21"  	% пример цепочки литер
	INFO21	"Информатика-21"  	% пример цепочки литер
	"21"	"Информатика-21"  	% пример цепочки литер
i21sys/Rsrc/keywords.odc

% Список английских ключевых слов для угадывания по первым буквам в алгоритмах модуля i21sysEdit (раскрытие синтаксических конструкций с помощью F5). 
% Алфавитный порядок не важен.
%
% О синтаксических правилах записи словариков см. русскую документацию к модулю i21sysScanner.
% 2012-04-27  info21;  последние правки 2012-11-06
ABS
ABSTRACT
ANYPTR
ANYREC
ARRAY
ASSERT
BEGIN
BITS
BOOLEAN
BYTE
CASE
CHAR
CLOSE
CONST
DIV
ELSE
ELSIF
EMPTY
END 
ENTIER
EXIT
EXTENSIBLE
FALSE
FINALIZE
FOR
HALT
IMPORT
IN
INC
INTEGER
IS
LEN
LIMITED
LONG
LONGINT
LOOP
MAX
MIN
MOD
MODULE
NEW
ODD
OR
ORD
OUT
POINTER
PROCEDURE
REAL
RECORD
REPEAT
RETURN
SET
SHORT
SHORTCHAR
SHORTINT
SHORTREAL
SIZE
THEN
TRUE
TYPE
UNTIL
VAR
WHILE
WITH
DIJKSTRA	% не принадлежит языку Компонентный Паскаль, но включить можно
"BlackBox Component Builder"	% на самом деле сюда много чего можно навключать
i21sys/Rsrc/simples.odc

% Словарик подстановки простых синтаксических конструкций.
% Позиция, где курсор должен стоять после раскрытия, указывается литерой |. Если ее нет, то в конце.
% Сама эта литера при подстановке удаляется.
% Подробней о синтаксических правилах записи словариков 
% см. русскую документацию к модулю i21sysScanner.
%
% Нужно помнить, что прежде чем слово будет сопоставляться со словами в левой колонке, 
% с ним произойдет следующее:
%  сначала будет сделана попытка угадать полное слово по подсказкам (hints);
%  если подсказки не нашлось, то будет сделана попытка заменить его 
% на первое подходящее слово в keywords, начало которого совпадает с раскрываемым словом.
% Этим объясняется, почему здесь можно включить подстановки вида H126 или Q1: 
% они проходят сквозь два описанных шага "угадывания" без изменений.
%
% Если слово не раскрывается по одной из вышеперечисленных простых подстановок, 
% то для него делается попытка сложной замены с помощью процедур, зашитых в Edit.
% 
% Алфавитный порядок соблюдать не обязательно.
% 2012-02-10 info21

ABS	'ABS( | );'
ARRAY	'ARRAY OF '
ASH	'ASH( | );'
ASSERT	'ASSERT( | );'
DEC	'DEC( | );'
ELSIF	'ELSIF | THEN'
EMDASH	''
ENDASH	''
ENTIER	'ENTIER( | );'
EXCL	'EXCL( |, );'
H126	'HALT( 126 );'	% еще не реализовано
H128	'HALT( 128 );'	% молчаливая остановка (без окошка Трапа)
HALT	'HALT( | );'
INC	'INC( | );'
INCL	'INCL( |, );'
LEN	'LEN( | );'
LONG	'LONG( | );'
MAX	'MAX( | );'
MIN	'MIN( | );'
NA	'NEW, ABSTRACT'
NEW	'NEW( | );'
ODD	'ODD( | );'
ORD	'ORD( | );'
POINTER	'POINTER TO '
Q	'|'	% одинарные английские кавычки
Q1	'|'	% одинарные английские кавычки
Q2	'|'	% двойные английские кавычки
QUOTE	'|'	% двойные английские кавычки
SHORT	'SHORT( | );'
SIZE	'SIZE( | );'
VAR	'VAR '
i21sys/Rsrc/Strings.odc

STRINGS
CharacterSet	CP identifier characters: ^0
UnableToRestoreDocument	Не удалось восстановить документ ^0
IndentChecksOn	Проверки отступов включены
IndentChecksOff	Проверки отступов отключены
IndentMenuOn	Включить проверки отступов
IndentMenuOff	Отключить проверки отступов
KeywordsLanguage	Словарик редактора: ^0
i21sysKoi8r.ImportKoi8rText	Текст (кодировка KOI8-R)
StartupBlackBox	пускач Блэкбокса
CannotCreateVbs	Чтобы сделать пускач, нужно запустить BlackBox.exe в основной папке
CannotSave	Нужно сохранить документы!
CannotClose	Нужно сохранить документы!
CannotExit	Нужно сохранить документы!
SilentModeOn	cистемные звуковые сигналы отключены
i21диал/Создание простых диалогов.odc

Создание простых диалогов

Нигде в примерах (кроме ***) не предполагается знание типов RECORD.

Простыекомандныекнопки.
Полевводадляцепочкилитер.
Полевводадляцелого.
Диалогсобновляемымрезультатом.
Уведомитель (обновление результата "на лету", без нажатия кнопок).
Флажки,связанныеслогическими(BOOLEAN)переменными.
*** Тоже,нообновлениевсехполейодниммахом.
Флажки,связанныесSET.
Переключатель.
Список.
Списоксвыбором.
Комбинированныйсписок.

________________________________________________
Первоначальная версия: 2003-10-23 при активном участии А.И.Попкова.
Версия 2010-10-01: Ф.В.Ткачев.
Исправления диалоговых форм 2011-02-13: Ф.В.Ткачев, список ошибок: Александр Шостак.
i21диал/Mod/ВводЦелого.odc

(* То же, что и в предыдущем примере i21диалТекст, но в поле ввода предназначено для ввода целого числа. *)

MODULE  i21диалВводЦелого;
	IMPORT  StdLog;

	VAR  целое*: INTEGER;
	
	PROCEDURE Напечатать*;
	BEGIN
		(* напечатать в Рабочий журнал, чтобы видеть, что хранится в переменной целое *)
		StdLog.Int( целое );
		StdLog.Ln
	END Напечатать;
	
BEGIN  целое := 9876 (* начальное значение, устанавливаемое при свежей загрузке модуля *)
END  i21диалВводЦелого.

Создаем диалог (Диалоги, Новая форма...),
сохраняем в i21диал/Rsrc/ВводЦелого.odc.
Мышкой увеличить кнопку, правый клик, Свойства.. 

"StdCmds.OpenAuxDialog('i21диал/Rsrc/ВводЦелого','Поле ввода целого')"

Заметим, что в поле для ввода целого Блэкбокс не дает напечатать ничего, кроме цифр! (Блэкбокс умный...)

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/ВводЦелого')"
i21диал/Mod/ВводЦелого2.odc

(* Ввод целого числа через текстовое поле [Field]. В этом примере будем вычислять и обновлять значение в новом поле диалога. *)

MODULE  i21диалВводЦелого2;
	IMPORT  StdLog, Math, Dialog;

	VAR  
		целое*: INTEGER;
		результат-: REAL; (* ограниченный экспорт -- значение переменной нельзя менять извне модуля: будет показано в диалоге серым цветом. *)
	
	PROCEDURE ПечататьЦелое*;
	BEGIN
		StdLog.Int( целое );
		StdLog.Ln
	END ПечататьЦелое;
	
	PROCEDURE ВычКвадрКорень*;
		VAR  
	BEGIN
		(* вычисляем и заносим значение в глобальную переменную: *)
		результат := Math.Sqrt( целое ); (* здесь могло бы быть очень сложное вычисление *)

		(* Теперь нужно обновить диалог, в котором показывается переменная результат: *)
		Dialog.UpdateReal( результат )  (* Update = обновить. *)
		(* Без этого будет по-прежнему показываться старое значение корня. *)
		
		(* На самом деле одна и та же переменная может показываться 
			в нескольких разных диалогах одновременно,
			и по данному вызову умный Блэкбокс обновит все диалоги, 
			где показывается эта переменная. *)
	END ВычКвадрКорень;
	
BEGIN
	(* начальные значения сразу после свежей загрузки модуля: *)
	целое := 144;
	ВычКвадрКорень (* вызываем, чтобы правильно заполнить переменную результат *)
END  i21диалВводЦелого2.


"StdCmds.OpenAuxDialog('i21диал/Rsrc/ВводЦелого2','Ввод целого 2')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/ВводЦелого2')"

Упражнение. Изменить названия кнопок в диалоговой форме.

Упражнение. Добавить в модуль процедуру, а в диалог соответствующую кнопку, для печати в рабочий журнал значения переменной результат.

Замечание.
В модуле Dialog есть отдельные процедуры для переменых основных типов (BOOLEAN, INTEGER, LONGINT, REAL). Вот их сигнатуры:

	PROCEDURE UpdateBool (VAR b: BOOLEAN);
	PROCEDURE UpdateInt (VAR i: INTEGER);
	PROCEDURE UpdateLInt (VAR l: LONGINT);
	PROCEDURE UpdateReal (VAR r: REAL);

Можно делать обновление сразу для группы переменных разных типов, но для этого надо знать, что такое RECORD.

Упражнение. Изменить диалог так, чтобы одновременно с корнем вычислялось наибольшее целое число, квадрат которого не превосходит значения переменной целое.
i21диал/Mod/Выбор.odc

(* Выбор [SelectionBox]. В диалоге можно выбрать одновременно несколько вариантов из списка (Ctrl+щелк или Shift+щелк). *)

MODULE  i21диалВыбор;
	IMPORT  StdLog, Dialog;

	CONST  прог = 0;  матем = 1;  муз = 2;  худож = 3;  англ = 4;

	VAR  доп_занятия*: Dialog.Selection;
	
	PROCEDURE Показать*;
		VAR  i: INTEGER;  есть: BOOLEAN;
	BEGIN
		StdLog.String('дополнительные занятия:');  StdLog.Ln;
		есть := FALSE;
		FOR  i := 0  TO  доп_занятия.len - 1  DO
			IF  доп_занятия.In( i )  THEN
				есть := TRUE;
				StdLog.Tab;
				CASE  i  OF
				|0:  StdLog.String('программирование')
				|1:  StdLog.String('математика')
				|2:  StdLog.String('музыкальная школа')
				END;
				StdLog.Ln
			END
		END;
		IF  ~есть  THEN
			StdLog.Tab;  StdLog.String('не посещает');  StdLog.Ln
		END
	END Показать;
	
BEGIN
	доп_занятия.SetLen( 3 );
	доп_занятия.SetItem( 0, 'программирование' );
	доп_занятия.SetItem( 1, 'математика' );
	доп_занятия.SetItem( 2, 'музыкальная школа' );
END  i21диалВыбор.

Создание диалога:
Дважды щелкнуть по имени модуля, Диалог, Новый диалог... , OK.
Ctrl+S.

"StdCmds.OpenAuxDialog('i21диал/Rsrc/Выбор','Список с выбором')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/Выбор')"

Если названия (цепочки литер) для элементов списка переопределяются динамически (перевычисляются в программе) в зависимости от каких-то условий, задаваемых в диалоге,
то нужно вызвать Dialog.UpdateList( ... ), чтобы новые названия стали доступны в текущем диалоге.

Упражнение. Добавить "гуру" (3).

Замечание. В получившемся диалоге можно отметить любое число строк (Ctrl+клик)
i21диал/Mod/КомбиСписок.odc

(* Комбинированный список [ComboBox]. Можно выбрать один из предусмотренных вариантов или задать свой: например, напечатать Екатеринбург. *)

MODULE  i21диалКомбиСписок;
	IMPORT  StdLog, Dialog;

	VAR  город*: Dialog.Combo;
	
	PROCEDURE Показать*;
	BEGIN
		StdLog.String( город.item );  StdLog.Ln;
	END Показать;
	
BEGIN
	город.SetLen( 4 );
	город.SetItem( 0, 'Стрежевой' );
	город.SetItem( 1, 'Нижневартовск' );
	город.SetItem( 2, 'Томск' );
	город.SetItem( 3, 'Москва' );
	(* номера пропускать нельзя  должны идти подряд, начиная с нуля.*)
END  i21диалКомбиСписок.

Создание диалога: как обычно.

"StdCmds.OpenAuxDialog('i21диал/Rsrc/КомбиСписок','Комбинир. список')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/КомбиСписок')"

Если названия (цепочки литер) для элементов списка переопределяются динамически (перевычисляются в программе) в зависимости от каких-то условий, задаваемых в диалоге,
то нужно вызвать Dialog.UpdateList( ... ), чтобы новые названия стали доступны в текущем диалоге.
i21диал/Mod/Переключатель.odc

(* Переключатель [Radio Button]. *)

MODULE  i21диалПереключатель;
	IMPORT  StdLog, Dialog;

	CONST  нач = 0;  опытн = 1;  эксп = 2;

	VAR  уровень*: INTEGER;
	
	PROCEDURE Показать*;
	BEGIN
		CASE  уровень  OF
		|нач:
			StdLog.String('начинающий программист');  StdLog.Ln
		|опытн:
			StdLog.String('опытный программист');  StdLog.Ln
		|эксп:
			StdLog.String('эксперт высшего класса');  StdLog.Ln
		END;
	END Показать;
	
BEGIN
END  i21диалПереключатель.

Диалог создается как обычно.
Во вновь созданной диалоге:
Стереть элементы "уровень" и соотв. текстовое поле,
выполнить команду меню Диалоги, Вставить переключатель [Radio button], 
расположить как надо,
правый клик, Свойства.
Заполнить поля:
	Связан с: i21диалПереключатель.уровень
	Ярлык: начинающий
	Уровень: 0
OK
Повторить дважды для опытного и эксперта.


"StdCmds.OpenAuxDialog('i21диал/Rsrc/Переключатель','Переключатель')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/Переключатель')"

Упражнение. Добавить "гуру" (3).
i21диал/Mod/Список.odc

(* Список [ListBox]. *)

MODULE  i21диалСписок;
	IMPORT  StdLog, Dialog;

	CONST  нач = 0;  опытн = 1;  эксп = 2;

	VAR  уровень*: Dialog.List;
	
	PROCEDURE Показать*;
	BEGIN
		StdLog.String('численное значение уровня: ');  StdLog.Int( уровень.index );  StdLog.Ln;
		StdLog.String('словесное описание: ');
		CASE  уровень.index  OF
		|0:  StdLog.String('начинающий')
		|1:  StdLog.String('опытный')
		|2:  StdLog.String('эксперт')
		END;
		StdLog.Ln;
	END Показать;
	
BEGIN
	уровень.SetLen( 3 );
	уровень.SetItem( 0, 'начинающий' );
	уровень.SetItem( 1, 'опытный' );
	уровень.SetItem( 2, 'эксперт' );
	(* номера пропускать нельзя  должны идти подряд, начиная с нуля.*)
END  i21диалСписок.

Создание диалога:
Дважды щелкнуть по имени модуля, Диалоги, Новая форма..., OK.
Ctrl+S.

"StdCmds.OpenAuxDialog('i21диал/Rsrc/Список','Список')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/Список')"

Если названия (цепочки литер) для элементов списка переопределяются динамически (перевычисляются в программе) в зависимости от каких-то условий, задаваемых в диалоге,
то нужно вызвать Dialog.UpdateList( ... ), чтобы новые названия стали видны в текущем диалоге.

Упражнение. Добавить в диалог "гуру" (3).
i21диал/Mod/Текст.odc

(* Ввод строки литер через текстовое поле ввода [Field]. *)

MODULE  i21диалТекст;
	IMPORT  StdLog;

	VAR  текст*: ARRAY 20 OF CHAR;
		(* переменная должна быть экспортирована, т.к. нужно менять ее значение извне модуля. *)
	
	PROCEDURE ПоказатьТекст*;
	BEGIN
		(* напечатать в Рабочий журнал, чтобы видеть, что хранится в переменной текст *)
		StdLog.String( текст );
		StdLog.Ln
	END ПоказатьТекст;
	
BEGIN
	текст := "в начале..." (* начальное значение сразу после свежей загрузки модуля *)
END  i21диалТекст.

Создаем диалог (Диалоги, Новая форма...),
сохраняем в i21диал/Rsrc/Текст.odc.
Предварительно можно подвигать и увеличить кнопки, чтобы было видно название целиком. Для этого щелкнуть мышкой по кнопке и потянуть за черные квадратики, чтобы увеличить кнопку, или потянуть за середину, чтобы передвинуть кнопку в новое место.

Чтобы поменять текст на кнопке, нужно сделать 
правый клик по этой кнопке;
вызвать команду меню Свойства...;
в поле Ярлык: изменить текст по желанию.

Не забыть сохранить изменения в файле.

"StdCmds.OpenAuxDialog('i21диал/Rsrc/Текст','Текст')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/Текст')"
i21диал/Mod/Уведомитель.odc

(* Уведомитель [Notifier]. Позволяет обновлять результат "на лету", без нажатия спец. кнопки, т.е. диалог вообще без кнопок. *)

MODULE  i21диалУведомитель; (* notifier = тот, кто уведомляет другие поля, "уведомитель" *)
	IMPORT  StdLog,  Dialog,  Math;

	VAR  аргумент*, корень-: REAL;
	
	PROCEDURE Уведомитель* (op, from, to: INTEGER);  (* В простых ситуациях параметры не используются, но стоять должны именно так, как показано, иначе Блэкбокс заругается при создании диалога. *)
	BEGIN
		корень := Math.Sqrt( аргумент );
		Dialog.UpdateReal( корень )
	END Уведомитель;
	
BEGIN  аргумент := 0
END  i21диалУведомитель.

Создаем диалог (Диалоги, Новая форма...) и т.д.
Правый щелк по полю ввода аргумента (белый прямоугольник), Свойства...
в поле  набить (или скопировать) i21диалУведомитель.Уведомитель,
OK,
сохраняем в i21диал/Rsrc/Уведомитель.odc,
закрываем,
спасаем и закрываем форму диалога.

Вызываем диалог:
"StdCmds.OpenAuxDialog('i21диал/Rsrc/Уведомитель','Уведомитель')"

Если все сделано правильно, то значение корня будет обновляться на лету  сразу при любом изменении поля "аргумент".
(Если нужные вычисления сложные и долгие, то, естественно, придется ждать.)

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/Уведомитель')"
i21диал/Mod/Флажки.odc

(* Флажки [CheckBox], связанные с логическими (булевскими) переменными. *)

MODULE  i21диалФлажки;
	IMPORT  StdLog, Math, Dialog;

	VAR  
		a*, b*, and-, or-, xor-, implies-: BOOLEAN;
	
	PROCEDURE Вычислить*;
		VAR  
	BEGIN
		and := a & b;	Dialog.UpdateBool( and );
		or := a OR b;	Dialog.UpdateBool( or );
		xor := ~a & b OR a & ~b;	Dialog.UpdateBool( implies );
		implies := ~a OR b;	Dialog.UpdateBool( implies );
	END Вычислить;
	
BEGIN
END  i21диалФлажки.


"StdCmds.OpenAuxDialog('i21диал/Rsrc/Флажки','Логические операции')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/Флажки')"

Внимание! Обратить внимание на размер получающихся элементов диалога (размер соотв. рамки виден после щелчка мышкой): нужно их уменьшить так, чтобы после передвижения они не перекрывались.

Упражнение. Разобраться с порядком вычислений в правой части присваивания для xor (вспомнить приоритеты операций; ср. приоритеты и визуальный размер соотв. знака операции).

Упражнение. Добавить в диалог операцию отрицания.

Упражнение. Исключить кнопку из диалога так, чтобы результаты операций обновлялись "на лету".
i21диал/Mod/Флажки1.odc

(* Флажки [Check box]. То же, что и пример i21диалФлажки, но обновление всех полей одним махом. *)

MODULE  i21диалФлажки1;
	IMPORT  StdLog, Math, Dialog;

	VAR  
		a*, b*: BOOLEAN;
		рез*: RECORD
			and-, or-, implies-: BOOLEAN
		END;
	
	PROCEDURE Вычислить*;
		VAR  
	BEGIN
		рез.and := a & b;
		рез.or := a OR b;
		рез.implies := ~a OR b;

		Dialog.Update( рез ) (* не зависит от того, сколько и каких полей у записи рез *)
	END Вычислить;
	
BEGIN  Вычислить
END  i21диалФлажки1.

Обратить внимание на рамочку, которая появится вокруг полей для результатов.
Это самостоятельный диалоговый элемент, кликнув по нему и нажав Ctrl+Enter можно поменять текст вверху (содержимое поля "Ярлык:").

"StdCmds.OpenAuxDialog('i21диал/Rsrc/Флажки1','Логические операции')"

Открыть форму для модификации:
"StdCmds.OpenDoc('i21диал/Rsrc/Флажки1')"

Упражнение. Добавить в диалог операцию xor (вычисляется как в предыдущем примере).

Упражнение. Изменить программу так, чтобы переменные a, b были внутри RECORD.