ОБОЛОЧКА (SHELL.SYS)
Это самый верхний уровень стандартной конфигурации
системы iS-DOS. Выше него могут устанавливаться дополнительно еще три. Обычно
это два уровня баз данных или уровень отладчика ВиОС.sys, 7-ой уровень временно
занимается текстовым редактором. Замечу при этом, что уровни iSDOS не должны
обязательно находиться в памяти один рядом с другим. Редактор, например,
содержит 7-ой уровень прямо в себе, т.е. в файле edit+.com, и всего лишь
помещает адрес своей таблицы рестартов в таблицу уровней, находящуюся в 0-ом
уровне (DOS).
4-ый уровень, или уровень SHELL, содержит рестарты,
позволяющие передавать управление нортонообразной оболочке, вызывать некоторые
из ее функций, а также включает такие полезные подпрограммы, как редактирование
десятичного числа и меню. Программы, не использующие данные функции, могут
временно снимать верхние 2 уровня (3-ий и 4-ый) для увеличения свободной памяти
в iSDOS Classic. Так поступает, скажем
FORTH. Так работал копировщик copy_all.com.
Обе программы запускались из bat-файла, в самом начале которых вызывалась программа
set.com, снимавшая все лишние резиденты и эти 2 уровня. На выходе эти уровни
можно было поставить обратно. Но, поскольку 4-й уровень (shell.sys) после
установки необходимо инициализировать программой shell.com, то проще обычно
перезагрузиться. В системе iSDOS Chic необходимость снимать верхние уровни
отпала, да и выигрыш там был бы при этом очень небольшим - всего 1063 байта
shel.sys + 764 байта twira.sys. Их адреса Вы можете посмотреть сами в программе
show.com. Да и панелью пользоваться удобно во многих программах. Работать с
отмеченными файлами, например, или открыть какой-нибудь файл, не выходя из
программы, с помощью панели куда удобнее слепого ввода его пути и имени. Я уже
не говорю про рестарт $menu. Покажите мне хоть одну программу сложности чуть
выше минимальной, не использующую эту удобную вещь! Итак, рестарты один за
другим:
#80 - $shel0, #81 - $shel1, #82 - $shel2
Эти три рестарта перехватывают стек и отдают
управление в 4-й уровень iSDOS, т.е. возвращают его 2‑панельному
файл-менеджеру. Пользуются им программы крайне редко, т.к. такой выход в систему,
естественно, прерывает выполнение "вышестоящей" программы, которой
была вызвана текущая программа, например, bat-файла, mon.com или mon.res,
menu.com и т.д. Т.е. Вы вернётесь, но не туда, откуда Вас вызывали, а прямо в
систему. Причём, флаг C в этом случае роли не играет, т.е. по ошибке Вы
вернулись или ещё как, система не узнает, и пользователя проинформировать не
сможет. Нормальный выход в систему - это всегда выход по RET. Печатать же
панели из своей программы для временного "выхода" в файл-менеджер
надо рестартами $shpan(#90) и $shsub(#8e) (см. для примера zB_shsub.asm).
Главный
выход в оболочку: создание виртуального диска. (Размер: g_cnfg(#10): HL'-6)
*) Все 3 shel-рестарта перехватывают стек и принудительно задают pnCSR=%01010, nLOG=1 (см. ПРИЛОЖЕНИЯ 16,17),
причем shel1 является точкой входа в shel0, а shel2 - в shel1.
Выход
с очисткой экрана, инициализацией ERDEV, QUEST (см. ПРИЛОЖЕНИЕ 3), USPNL, PAPER, BORD (см. ПРИЛОЖЕНИЕ 14), переключением на основное (0-ое) устройство печати /swtyp(#1B)/
в прямом режиме /prcpl(#0B)/. В блочном драйвере устанавливается 7-ой бит в
9-ом байте (см. ПРИЛОЖЕНИЯ 3,6).
*) Все 3 shel-рестарта перехватывают стек и принудительно задают pnCSR=%01010, nLOG=1 (см. ПРИЛОЖЕНИЯ 16,17),
причем shel1 является точкой входа в shel0, а shel2 - в shel1.
Выход
с перерисовкой и подкраской верхней строки подсказок и печатью обеих панелей.
*) Все 3 shel-рестарта перехватывают стек и принудительно задают pnCSR=%01010, nLOG=1 (см. ПРИЛОЖЕНИЯ 16,17),
причем shel1 является точкой входа в shel0, а shel2 - в shel1.
Сей рестарт предназначен для подготовки грамотного
выхода в систему по RET. Например, Вы сотворили нечто в каталоге своей
программой (создали новый файл, скажем) и хотите, выходя перепечатать из чувств
минимализма лишь текущую панель. Имеете полное право, если рисовали все окна
только на ней или вообще их не рисовали. Но что делать, если две панели
одинаковые? Тогда надо перепечатать их обе. Вот этой проверкой на их одинаковость
и занимается данная точка входа в систему. Заодно, она ожидает отпуска клавиш.
Если панели одинаковые, в регистре A получите код cshel2 (#F2), а ежели разные
- код cvwpnl (#F0). (Список всех подобных кодов см. в ПРИЛОЖЕНИИ 16) Флаги,
по идее, уже должны быть все установлены. Останется лишь дописать RET и
вывалиться в систему.
Пример из программы delete.com:
LD C,$menu ;Единственное меню
RST 16 ;программы
RET C ;Error?
QUIT
STACK LD
SP,0 ;возвращаем на место
EXCSR LD A,0 ;20,
если удалялся файл
OR A ;0, если
каталог или отказ
JR NZ,PNVW
;Если удалялся каталог, на всякий пожарный
перепечатаем обе панели (f2):
AQUI LD
A,#F8 ;c_sh Если отказ - f8
RET ; Если
каталог - f2
PNVW
;Удалялся файл.
LD C,$pnvw ;<-- ВОТ ОНА!
RST 16
RET ; выход из
delete.com
Пример из программы rename.com:
;После переименовывания файла
CALL $SVSTL ;Сохраняем стиль в
RET C ;файле
rename.com
LD C,$flush ;Сохраняем
блоки
RST 16 ;кэша на
диске
RET C
LD A,#F2 ;Перепечатка
2 панелей
LD (AQUI+1),A
EXIT
;Сюда прыгаем по отказу или после меню
LD C,$kwait ;Ждём отпуска
клавиатуры
RST 16
EXCSR LD A,0 ;0, если каталог
OR A
JR NZ,PNVW
AQUI LD
A,0 ;F2, если были в меню или меняли имя каталога (см. выше)
0, т.е. "ничего не перепечатывать", если ничего не делали
RET
PNVW
;файл
LD C,$pnvw ;<-- ВОТ ОН!
RST 16
CP #F2 ;если панели
разные
RET Z ;то обе и
перепечатывать
XOR A ;ИНАЧЕ:
ничего не делать
RET
Выход в оболочку с выполнением команды shell. Если
флаг C установлен, то в регистре A - код ошибки, если же Carry флаг сброшен, а
флаг Z поднят, то регистр A воспринимается как код команды. Например:
AF=5245: Флаг C поднят, A=#52, получите сообщение:
"Error 82". Или: AF=#F244: флаг C сброшен, флаг Z поднят, выполняется
команда "Перепечатать 2 панели".
Данный рестарт, как и рестарты #80-82, перехватывает
стек, поэтому пользоваться им надо лишь в исключительных случаях, когда по RET,
выходить просто некуда. Не шагать же, в самом деле, в открытый космос! Или
когда возвращаться уже просто незачем. Все мосты сожжены. Однако всё, что было
здесь сказано про флаги и регистр A, будет работать и при выходе по RET.
Правда, лишь в том случае, когда Вы при выходе попадаете прямо в shell, а
скажем, не в bat-файл. exebat.com, получив от Вас код в регистре A, передаст
его оболочке только при поднятом флаге C, т.е. вывалится далее с кодом ошибки.
Т.о. весь этот интерфейс предназначен для обычного вызова com-файлов по Enter
или через extent.txt либо extkey.txt. Тем не менее, эти коды широко применяются
во многих программах и их полезно знать. Полностью они приведены в ПРИЛОЖЕНИИ 16.
Пример из программы uni_boot.sys, загрузчика iSDOS
Chic с HDD для машин KAY:
...
CALL READ ;читаем is_dos.sys
RET C
LD A,(BUFF+32+22) ;Регистр I
LD I,A ;из
описателя файла
;Система загружена. Теперь можно пользоваться её
рестартами:
;Создаём cache:
LD C,$g_cnf ;Главный
вектор
RST 16 ;конфигурации
EXX ;системы
LD BC,-6
ADD HL,BC
LD A,(HL) ;Размер cache
LD C,$creat ;Создать
Кэш
RST 16
JR C,ERROR ;C означает
ошибку
;Берём дату с диска и устанавливаем её в систему:
LD C,$g_com
RST 16
EXX
DEC HL
DEC HL
LD DE,(BUFF+30) ;Дата из
0-го
LD (HL),D ;блока диска
DEC HL
LD (HL),E
;Open disk "S":
LD A,"S"
LD C,$dvtrn ;Преобразуем в A=0..7
RST 16
LD B,A
LD C,$swblk ;Переключаемся
на S
RST 16
JR C,ERROR
LD C,$open ;...и открываем
RST 16
JR C,ERROR
;BASIC & TR-DOS variables:
LD HL,TRDBUF ;Загружаем 2 блока
LD DE,#5C00 ;переменных TR-DOS'а
LD BC,#200
LDIR
;Вот ещё один редкостный RST 4-го уровня.
;Запускаем autoexec.bat и, если всё ОК, то управления
нам он уже не отдаст...
LD C,$shexe
IM 2
JR NC,1$
;А ВОТ И ОН! Сюда попадаем по ошибке
LD C,$shout
1$ EI
RST 16
ERROR
;Или сюда:
LD C,$shout
RST 16
;-----
TRDBUF DEFS #200
Устанавливает
маску состояния файла в панели для пометки и проверки файла.
Вход: А= маска.
По
умолчанию маска=1, т.е. уровень SHELL метит файлы, поднимая 0-ой бит.
По
номеру файла в каталоге (в регистре Е) возвращает: A=(HL')= байт состояния
отметки файла,
(HL'-1)= порядковый номер отметки.
Запрос
о состоянии текущей панели.
Выход: А - число отмеченных файлов на
текущей панели,
L' и H' - минимальный и максимальный
номера файлов, а именно: L'=0, H'= где-то между общим числом файлов в каталоге,
включая удаленные, но без каталогов, и числом неудалённых файлов, но с каталогами.
DE' - адрес вектора рабочей панели -48,
BC' - адрес вектора оболочки (см. ПРИЛОЖЕНИЯ
17,18).
Редактирование
десятичного числа в окне (для menu, например).
Вход: A - число цифр,
DE - координаты для wtpos,
HL - начальное значение числа,
IX - вектор окна.
Выход: Флаг C: ошибка (переполнение числа,
ввода/вывода и пр.);
NC, Z: HL'= новое значение числа;
NZ: выход по одной из 5 специальных
клавиш (см. smbgt(#6E).
Перерисовка
верхней строки подсказок оболочки с подкраской или без в зависимости от 0-го
бита nLOG (см. ПРИЛОЖЕНИЕ 17).
Возвращает
параметры панельного курсора.
Выход: A=E'=
номер файла,
D'= позиция Y в окне (=H
для wtpos),
B' - номер текущей панели (0 - левая, 1 - правая),
HL' - адрес вектора окна панели (ПРИЛОЖЕНИЯ 17,18).
Пишет
"Please Wait" на месте курсора
Переключение
устройств. Ввод символа с клавиатуры с миганием курсора в окне.
Вход: HL=смещение
для wtpos,
Carry Set: A=номер устройства,
NC: иначе: текущее.
Флаг Z: Выход через
RST dvtrn(#4A),
NZ: через smbgt(#6E).
Не
используется.
Выполнение
команд из прикладных задач.
Вход: А - код команды (ПРИЛОЖЕНИЕ
16).
Сравнение
11-байтового шаблона(DE), (например результата RST trans(#46)), с 11-байтовым
описателем(HL) файла (имя и расширение). Если равны, то флаг Z иначе NZ.
Выполнение
команд работы с панелями:
Вход: В - регистр состояния pnCSR
(ПРИЛОЖЕНИЕ 17).
А=0 -аналог shel0, А=1 -аналог shel1,
А=2 -аналог shel2, А=3 - движение курсора по панели,
А=5 -pnDR - печать обеих панелей, А=6
-TYPNL- печать одной панели.
Меню.
Перепечатывает окно. После стандартного wt-окна необходимо положить буфер CSR
строк длиной исходя из расчета по 1 байту на строку. CSR: 0 - проскакивать
строку, 1 - останавливаться на ней.
Вход: IX - адрес вектора окна: байты
0..7 - стандартное окно.
В отрицательную сторону:
-12(1)
Цвет курсора при отработке Enter
-11(1)
Управляющий регистр меню. Биты 0/1:
0 - awt/awtc
- Тип курсора
1 - старый/новый стандарт вектора.
(По новому стандарту: 8(2) - Адрес
CSR-массива минус 1, 10(2) - Адрес текста.)
7 - Вызывать программу пользователя
-6(2) до/после ожидания клавиши.
-10(1)
Цвет курсора
-9(1)
Позиция курсора (от 1)
-8(2) Адрес программы инициализации
символьного массива, вызываемой при входе в меню и при каждом выходе из
строковой функции с NZ,A=1.
-6(2)
Адрес программы пользователя, выполняющейся при нажатии любой клавиши.
-4(2) Адрес списка дополнительных
функций (т.н. "горячих клавиш"). Этот список должен состоять из
3-байтовых значений:
0(1) код клавиши,
1(2) адрес дополнительной процедуры.
В этом случае на входе в процедуру B=код
клавиши, курсор (IX-9) не перемещается.
Если 2(1)=0, то 1(1) означает номер
строки и данная клавиша обрабатывается как Enter на строке с указанным номером,
(IX-9) принимает соответствующее значение.
Если адрес списка дополнительных функций
в векторе = 0, то дополнительно отрабатываемых клавиш нет.
-2(2) Адрес списка функций отработки
клавиши Enter. Список должен состоять из 2-байтовых адресов функций, количество
которых должно соответствовать количеству строк в меню. Если один из адресов
функций или адрес всего списка = 0, то при нажатии ENTER ничего не произойдет.
0(8) Стандартный вектор окна.
(По новому стандарту:)
8(2) Адрес CSR-массива минус 1
10(2) Адрес текста
(По
старому стандарту:)
с
8-го байта: CSR-строка, затем - текст окна.)
Функции, выполняемые по нажатию клавиши Enter могут
управлять дальнейшими событиями флагом Z/NZ и содержимым регистра A: Z: ничего
не делать,
NZ: A=255 - выйти из меню,
A=1 - вызвать процедуру инициализации.
Если функция отработки дополнительных клавиш выходит
с флагом Z, то выполнится та строка в меню, номер которой будет на выходе в
регистре A (Если 0, то ничего не выполняется). При нажатии SS/A
происходит выход из меню, причем происходит установка: регистра A =
255 и флаг NZ.
Выполнение
функций-утилит по текстовому файлу.
Вход: HL=путь файла,
A=код функции.
Используется
оболочкой для отработки нажатых клавиш (файл S:SHELLextkey.txt). Среда
сохраняется. Для обозначения служебных символов используется десятичное число,
начинающееся с одиночной кавычки. Так сама кавычка будет выглядеть как '39.
путь и ключи функции отделяются пробелом. (см. extkey.hlp).
Выход
в оболочку с запуском RST exebat(#44) с A=0 (см. ПРИЛОЖЕНИЕ 17).