4. ФОРМАТИРОВАННЫЙ ТЕКСТ

Текстовый массив t() - это массив символов, но не старых ASCII символов, а уникодов (двухбайтовых символов). Его элементам можно присваивать (вписывать) символы любого языка (уникоды), числа в текстовом формате, просто текст и многое другое. Для записи в текстовый массив существует команда #print или короче #pri.
#pri FT
Она имеет один агрумент, называемый formatted text (FT). FT - это в общем случае сложный форматированный текст, состоящий из большого числа фрагментов текста, записанных разным способом. Это может быть просто текст, а может быть и текст, генерируемый текстовой командой (форматом). Форматы, как в языке Fortran, на Java отсутствуют, это мелкое дело и создатели Java считают, что форматы должны делать сами программисты. Но не всем интересно делать форматы, да это и неудобно в языках быстрого программирования, каким является ACL. Поэтому я сделал много разных форматов, на все случаи, но если кто-то скажет, что ему нехватает, могу без труда сделать и другие форматы. Пока есть все, что лично мне нужно для тех программ, которые я уже написал.

Прежде всего важно знать, что FT всегда заканчивается командой окончания. Все команды форматов начинаются с символа [\], после которого стоит одна буква (имя команды) и вслед за ней могут быть аргументы. Команда окончания имеет вид \E без аргументов, например команда
#pri ab cde \E
напечатает в текстовый массив t() текст "ab cde ". Как вы уже догадались, простой текст начинается с любого символа, отличного от пробела. То есть в таком режиме невозможно записать пробелы в начале текста. Как это делать будет сказано позже. Каждая команда #pri печатает в t() последовательно запись за записью, записи начинаются с t(1). Но такой естественный порядок можно изменить. Реально номер элемента массива t(), начиная с которого будет сделана очередная запись, определяется элементом служебного массива s(3) без имени. Значение этого элемента, в отличие от элементов с именем, автоматически меняется при каждой записи, все время указывая на начало следующей записи. Но это значение можно изменить и в программе, присваивая s(3) любой индекс перед выполнением команды #pri. Кроме того, для удобства использования записей после каждого выполнения команды #pri элемент служебного массива s(4) содержит начало произведенной записи, то есть индекс первого элемента текстового массива, а s(5) - число записанных символов. Следующая команда - это команда записи в текстовый массив элементов самого текстового массива. Она имеет два аргумента
#pri ab \T<b> <l> cd\E
Здесь аргументы <b> (beginning) и <l> (length) -- это числа, которые указывают на первой индекс элементов текстового массива (имя записи) и о длине текстовой строки для записи, то есть число символов. Аргументами могут быть просто целые числа, переменные или элементы числовых массивов. Опять отмечу, что после команды \T (а точнее после всех команд) пробелы игнорируются и последующий простой текст начинается с любого символа, отличного от пробела. Например,
#pri ab \T121 10 cd\E
запишет следующий текст [ab t(121)...t(130)cd]. Вы уже догадались, что такая текстовая команда позволяет выполнять любые манипуляции со строками текста, хотя самого понятия текстовой строки в языке ACL нет. Это особенно полезно при автоматической генерации текста в циклах.

Следующая серия команд - это команды записи в текстовый массив значений числовых переменных. Самая простая из них \G не имеет форматных аргументов, но может иметь сколько угодно аргументов, разделенных пробелами, которые как раз выводятся на печать. Список аргументов заканчивается знаком [;]. Например, правильная команда
#pri \G a b c d;\E
Здесь a, b, c, d - это числовые переменные. Пусть например, a=345; b=0.001; c=2.E-4; d=0; После выполнения указанной выше команды будет записан следующий текст
  3.4500+02  1.0000-03  2.0000-04         0.
Как следует из этого примера, формат \G - это общий (general) или стандартный формат, который все числа записывает в строку из 11 символов с пятью значащими цифрами, с десятичным разделителем в виде точки и с показателем степени без знака E. Я заметил, что знак E необходим при задании чисел в математических выражениях, но при распечатке чисел через пробел он является лишним и его можно опустить, что и сделано. Такой формат удобен, если вам нужно получить значения чисел, а фасон вам не важен. Однако если фасон важен, есть другая команда
\N<t> <f> a b c; ,
имеющая два дополнительных форматных аргумента. Здесь <t> -- число, указывающее полное число символов при печати чисел, а <f> - число, указывающее число символов (размер) в дробной части при записи чисел. Показатель степени при этом отсутствует. Все остальное как в команде \G. Очевидно, что <t> должно быть больше чем <f> не менее чем, на две позиции + длина целой части числа. Однако есть специальные случаи. Если <t> равно 0, то длина записи числа минимальна и зависит лишь от величины целой части. Если <t> равно -1, то данная команда эквивалентна \G. Так исторически сложилось, что команда \G была введена позднее как замена этому режиму. Дополнительно есть еще формат
\B<t> <f> a b c; ,
где аргументы имеют то же самое значение, как в и команде \N, но число записывается с одним целым разрядом и с показателем степени десяти после буквы E. Этот формат необходим для совместимости записи данных с другими программами. В некоторых программах удобно вставлять в текст целые числа с фиксированным числом разрядов. Для этого есть команда
\I<n> a b c; ,
где форматный аргумент n есть полное число разрядов, отводимое для числа. Если оно положительное, то лишние разряды слева заполняются пробелами, а если отрицательное, то нулями. В последнем случае число разрядов показывает модуль аргумента n. В отдельных специальных случаях используется команда
\S a; ,
которая записывает число с минимальным числом разрядов и, кроме того, округляет последнюю значащую цифру, чтобы ликвидировать ошибки расчетов. Например, число 2.49999234 будет заменено на 2.5 так же, как и число 2.50000123. Формально эта команда тоже применяется к списку переменных, но реально разумно ее использовать только для одного значения, так как два значения напишутся слитно (без пробелов). Эта команда полезна для разметки осей графиков и вообще на графических рисунках, а также в окнах ввода.

Следующая команда -- это печать символов по их уникоду. Уникоды, как известно, описывают знаки любого языка. Будут ли они напечатаны, зависит от возможностей используемого фонта. Но они точно будут введены и ими можно манипулировать. Первые 128 уникодов совпадают с ASCII кодами. Команда выглядит так
\U n n n*m n n; .
Она не имеет форматных аргументов. Пробел после буквы U необязателен. Конструкция n*m означает, что юникод с номером n будет напечатан m раз. Список заканчивается [;]. Вот теперь ясно, что 5 пробелов в самом начале текста можно ввести как \U32*5; . В команде \U аргументами могут быть целые числа, переменные и элементы массивов. При этом аргументы преобразуются в символы, а число повторений округляется до ближайшего целого. Есть, однако, модификация этой команды \u, записываемая также
\u n n n*m n n; .
Но у нее аргументами могут быть только целые числа и они считываются именно как целые числа. Иногда это может оказаться существенным.
Есть также система более простых команд для ввода в текст служебных символов, а именно
\b (backspace) 
\t (tab) 
\n (line feed) 
\r (carriage return) 
\' (символ ') 
\" (символ ")
\\ (символ \) 
\@ (символ @) 
\# (символ #) 
\[ (символ [) 
\] (символ ]) 
\- (ничего).
Эти команды за исключением последней вводят те символы, которые указаны вторыми, так как непосредственная запись этих символов будет приводить к неправильной интерпретации и ошибкам. Все эти символы можно ввести через уникоды, но они были в языке C и часто более наглядно их записывать так. Последняя команда \- совсем ничего не делает. Но она все же необходима, так как не только пробелы, но и невидимые знаки конца строки игнорируются после каждой команды. Очень длинный текст в аргументе команды #print набивать в одной строке неудобно и его разумно переносить. Но тогда запишется признак переноса строки. Чтобы этого не случилось, перед переносом нужно набить \- и тогда знаки переноса строки в текст не запишутся, а сама команда ничего не добавит. А если на самом деле нужно, чтобы признак конца строки записался, то пишите смело в несколько строк -- так и будет напечатано.

Наконец, есть еще специальные служебные команды, специфические только для языка ACL. Первая из них
\D ,
вставляет в текст текущие дату и время по данным на компьютере, следующая команда
\P<n> ,
вставляет значение текстового параметра по его номеру n. Текстовых параметров 4, но изначально было 6, поэтому они имеют номера со скачком. Можно сказать, что два номера зарезервированы. Так [fir] (first) имеет номер 1, [op] (operation) имеет номер 4, [file] и [form] (format, formed) имеют номера 5 и 6 соответственно. Есть также команда
\F ,
которая вставляет в текст имя программы-интерпретатора. После того, как появился интерпретатор в виде проигрывателя, он может иметь любое имя и это имя иногда необходимо печатать. Наконец есть совсем специальные команды. Так
\H ,
вставляет в текст имя папки, в которой находится работающая в данный момент ACL программа вместе с символом "/"в конце текста. Обычно эта папка известна при написании программы и ее можно заказать (сделать рабочей, см. далее) в явном виде. Но затем, при переименовании папки или переносе программы, ее текст придется переписывать. Используя данный формат папку можно указать неявным образом, получая строку прямо от интерпретатора. Но надо иметь в виду, что если одна программа вызывает другую программу из файла, то новая программа может находиться в другой папке, этот формат указывает только имя самой первой запущенной программы. В специальном варианте интерпретатора (см. главу 25) эта команда просто ничего не делает, так как в нем одна программа запускается из главной папки и вставлять ничего не надо. Это удобно для совместимости ACL программ при работе в среде разработки и в спец. варианте. Иногда необходимо знать также полный путь к папке самого интерпретатора (среды разработки). Этот путь вместе с символом "/" в конце дает формат
\M ,
Наконец формат
\L ,
имеет специальное назначение. Он передает в программу специальную строку из среды разработки. В данной версии эта строка заполняется при выборе в меню среды разработки кнопки [Run/File Viewer]. Пользователь может выбрать файл в любой папке любого жесткого диска компьютера с расширениями wma, wmv, mp3, mp4, avi, flv. После этого автоматически запускается ACL программа со специальным именем "pro/runext.acl", которая может производить с этим файлом некоторые действия. Она получает строку с именем файла с добавлением буквы m в первой позиции. Вот этот формат как раз и используется для передачи в программу полного имени выбранного файла. ACL программа проверяет наличие буквы m и если она есть, то формирует bat-файл с именем файла, а затем запускает его. При этом автоматически запустится проигрыватель, связанный с этими расширениями. Использование ACL программы упрощает программирование данной операции. В дальнейшем возможны другие применения этого формата.
Есть еще скобки комментария
![...]! .
Как сами эти скобки, так и текст внутри них игнорируется и не записывается. Комментарий можно ставить после любой команды перед обычным текстом. Но реально это уже излишество и необходимо только в очень редких случаях. Я сам такие комментарии не ставлю. Впрочем была бы возможность, а как ее использовать каждый придумает сам.

Как я уже отмечал, такая совокупность форматов позволяет охватить все необходимые ситуации. Текстовый массив можно просмотреть после выполнения программы из меню оболочки [Exec/Show textarr], так как после выполнения программы записанная часть текстового массива спасается в файл с названием "textarr.txt". Вот этот файл и показывается в редакторе текста. Размер записанной части текстового массива определяется параметром s(6). Если в текстовый массив записано очень много текста и нежелательно его записывать в файл "textarr.txt", так как это занимает время, особенно для КПК, то можно просто обнулить этот параметр перед окончанием программы. Это удобно для КПК, например, при чтении книг. Ну и такой файл не нужен при использовании проигрывателя.

Есть другая возможность показа форматированного текста без записи в текстовый массив. Для этого служит команда #message или короче #m. Эта команда показывает форматированный текст различным образом в зависимости от значения параметра [op]. Все режимы этой команды показывают текст в процессе работы программы как раз при ее выполнении. Если задана команда
#m [op=txt;] FT,
то текст будет показан в окне текстового редактора, который сопровождает работу программы и называется "Терминалом". Замечу, что в нормальном режиме работы программы окно терминала не появляется сразу и открывается только при первой записи в него. Если записей нет, то окно совсем не видно. А после выполнения программы окно терминала автоматически закрывается. Если необходимо блокировать закрытие терминала, то перед окончанием программы надо выполнить команду #rob [mo=2;]. Если
#m [op=rtt; n=1;] FT,
то в тексте, ранее набитом в терминале будет удалено столько символов, сколько указывает значение параметра [n] (number) (в показанном варианте 1). В этом случае аргумент не используется, но он все же должен присутствовать хотя бы в пустом виде \E для соблюдения синтаксиса. Этот режим позволяет контролировать степень выполнения некоторой процедуры в цикле. Можно сначала напечатать некую строку текста, а затем по мере выполнения цикла вычеркивать символы, то есть делать обратный отсчет. Если
#m [op=win;] FT,
то текст будет показан в отдельном окне и работа программы будет остановлена до тех пор пока пользователь не нажмет клавишу [OK]. Если
#m [op=oce;] FT,
то текст будет показан в специальном окне, содержащем три клавиши [OK] [Cancel] [Edit] и номер нажатой клавиши будет равен значению специальной переменной [&]. Если
#m [op=yno;] FT,
то текст будет показан в специальном окне, содержащем две клавиши[Yes] [No] и номер нажатой клавиши будет равен значению специальной переменной [&]. Команда
#m [op=uni;] FT FT, 
имеет два аргумента FT и показывает сообщение в окне, атрибуты которого определяются вторым аргументом FT. Первый аргумент FT, как обычно, задает сам текст сообщения. Второй аргумент FT должен содержать несколько текстов, разделенных знаком вертикальной черты [|]. При этом первый текст - это заголовок самого окна, а остальные - это заголовки кнопок, число кнопок будет зависеть от числа записанных текстов. Номер нажатой кнопки в диапазоне от 1 и до номера последней кнопки возвращается в [&]. Все кнопки располагаются в один ряд.

В октябре 2010 года введена более сложная команда
#m [op=gen; b=; nx=; ny=; siz=; n=;] tit\E  text\E  butt\E  
Она выставляет окно сообщения на экране вместе с произвольным числом кнопок, которые могут располагаться в несколько рядов. Аргументы команды очевидны: первый задает название окна, второй - текст сообщения, третий названия кнопок. В тексте сообщения может присутствовать символ \n разделяющий строки, но строки не должны быть пустыми. Пустую строку надо задавать в виде \u32;\n. Названия кнопок разделяются символом "|". Параметр [b] указывает индекс первого элемента целого массива i(), в котором должны быть записаны числа, регулирующие расположение элементов в окне. Число таких чисел должно быть согласовано с аргументами. Так, если в аргументе text есть n1 строк, а параметр [n] равен n2, то чисел должно быть N=n1+2*n2. Первые n1 чисел задают размеры твердого пустого пространства, устанавливаемого после каждой строки текста сообщения. Дело в том, что строки автоматически центрируются. Если же необходимо их выравнивать по левому краю, то нужно удлинять короткие строки справа. Если же это не нужно, то можно задавать нули. Параметр [n] указывает число строк, в которые будут размещены кнопки. Поэтому следующие за n1 ровно n2 чисел, указывают сколько кнопок надо разместить в каждом ряду. Очевидно, что сумма этих чисел должна быть равна полному числу кнопок. Наконец последние n2 числа указывают размер полей справа и слева в каждом ряду кнопок. Это полезно, чтобы длина кнопок не заполняла весь ряд, что часто выглядит некрасиво. Параметры nx, ny задают позицию верхнего левого угла окна относительно левого верхнего угла экрана. Если хотя бы один параметр отрицателен, то окно помещается в центре. Наконец параметр [siz] указывает размер полей со всех сторон окна, куда не могут попасть ни текст, ни кнопки. Как обычно, команда возвращает в [&] номер нажатой кнопки

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

Аргумент в виде форматированного текста используется практически во всех командах, в которых надо определить текстовую строку. Это общая конструкция, которая не ограничивается описанными в этом разделе командами ACL. Поэтому полезно здесь привести условную формулу для форматированного текста, включающую все форматы
FT == ...\b ...\t ...\n ...\r ...\" ...\' ...\\ ...\- 
   ...\# ...\@ ...\[ ...\] ... \D ...\T<ifc> <nc>
   ...\U n n n*m ; ...\u n n*m ; ...\I<nt> n n n;
   ...\N<nt> <nf> n n ; ...\G n n ; ...\B<nt> <nf> n n ;
   ...\S n; ...\P<nt> ...\F ...\H ...\L ...\E