TURBO PASCAL |
Новости
|
ТЕКСТЫ ПРОГРАММ П1 МОДУЛЬ ПОДДЕРЖКИ ТЕКСТОВОГО ВЫВОДА F_TEXTЭтот модуль не описан в книге, т.к. мне показалось, что реализуемая в нем техника мно— гостраничног'--- текстового ввода/вывода не представляет интереса для широкого круга читателей. Тем не менее его полный текст приводится ниже, т.к. некоторые тестовые программы и модули использует его для создания текстовых окон. ^«""~~"==-====; Unit F_Text; {==«=====.,===„} {+~ --———------————------—--—————————-------- --"-./- I В этот модуль входят подпрограммы поддержки ¦ I многостраничного вывода а текстовом режиме ¦ +——————— ———_—_——____--__————_—_-__+; INTERFACE {—— ——————.—— _——_-__——_——_——_._————__, Oses CRT, DOS; {Следующие константа используются для указания типа рамки при обращении к процедурам BORDER, SETWINDO» и PUTWINDOW.} const EmptyBorder =0; {Стереть рамку} SingleBorder =1; {Рачка из одинарных линий} DoubleBorder =2; (Рамка из двойных линий} {Следующий массив определяет символы псевдографики для вычерчивания рамок (альтернативная кодировка)} BorderChar: array [0..2,1..6] of Char = ((#32, #32, #32, #32, *32, #32), (#218, #196, #191, #179, #192, #217), 1*201, #205, #187, #186, #200, #188)); type PageType = record {Описатель страницы} case Byte of 0:(Attrib Byte; {Атрибут символов} CLineUp Byte; {Верхняя строка курсора} CLineDown Byte; {Нижняя строка курсора} CVisible Boolean; (Признак видимого курсора} WBondUp Word; {Левый верхний угол окна} WBondDown Word); {Правый нижний угол} 1:(РадеРаг: array [1..8] of Byte) end; const Pages: array [O..7] of PageType - ((PagePar: (7,6,7,1,0,0,79,24)), (PagePar: (7,6,7,1,0,0,79,24)), (PagePar: (7,6,7,1,0,0,79,24)), (PagePar: (7,6,7,1,0,0,79,24)), (PagePar: (7,6,7,1,0,0,79,24)), (PagePar: (7,6,7,1,0,0,79,24)), (PagePar: (7,6,7,1,0,0,79,24)), (PagePar: (7,6,7,1,0,0,79,24))); {Адрес регистра статуса адаптера CGAf PortCGA = $3DA; (Начало видеопамяти для CGA/EGA/VGA) BegVideo = $В800; (Следующие константы зависят от режима работы и типа адаптера. Значения по умолчанию соответствуют CGA/EGA/VGA в режиме С080. Эти значения можно переопределить с помощью процедуры InitText} const MaxPage : Byte =3; {Максимальный номер страницы) MaxChar : Byte = 80; (Количество символов в строке} MaxLine : Byte = 25; (Количество строк на экране} PageSize: Word = 4000; {Размер видимой страницы) VSize : Word = 4096; {Полный размер страницы} VMemory : Word = BegVideo; {Адрес видеопамяти} VMW: array [O..15] of Word = ($0000,BegVideo,$1000,BegVideo,$2000,BegVideo, $3000,BegVideo,$4000,BegVideo,$5000,BegVideo, $6000,BegVideo,$7 О О 0,BegVideo) ; {Массив VMP содержит адреса всех видеостраниц. Значения по умолчанию соответствуют адаптерам CGA/EGA/VGA в режиме С080. Эти значения можно переопределить с помощью процедуры InitText) •wax VMP: array [O..7] of Pointer absolute VMW; / I Подпрограммы управления цветом } procedure ChangeAttribute(Page,Xl,Yl,X2,Y2,01dAtt,NewAtt: Byte); {Меняет атрибут OLDATT на значение NEWATT в прямоугольнике XI...Y2 страницы PAGE} Procedure Colors(Text,Back: Byte); {Устанавливает цвет текста TEXT и фона BACK в текущей странице} Procedure PageColors (Page,Text,Back: Byte); {Устанавливает цвет текста TEXT и фона BACK в странице PAGE} Function PackAttribute(Text,Back: Byte): Byte; {Упаковывает два цвета в байт атрибута} procedure SetAttribute(Page,XI,Y1,X2,Y2,Attr: Byte); {Заменяет атрибут всех символов в прямоугольнике XI...Y2 страницы PAGE на значение Attr} Procedure OnPackAttribute(Attr: Byte; var Text,Back: Byte); {Распаковывает байт атрибута и возвращает два цвета} { Подпрограммы управления курсором > Procedure CursorOff; {Отключает курсор в активной странице} Procedure CursorOn; (Включает курсор в активной странице} Procedure CursorOnOff (Page: Byte; Vis: Boolean); {Устанавливает признак видимости курсора: PAGE - номер страницы; VIS - признак видимости} procedure GetCursor (Page: Byte; var X, .г. Up, Down: Byte); {Возвращает координаты курсора: PAGE - номер страницы; X,Y - возвращаемые координаты (отсчет от 1,1); Up, Down - размер курсора в строках развертки) Function GetCursorVisible(Page: Byte): Boolean; /Возвращает признак видимости курсора} Procedure PutCursor(Page,X,Y: Byte); {Устанавливает требуемое положение курсора. PAGE - номер страницы/ Х,У - координаты курсора (отсчет от 1,1)} Procedure SetCursorLine(Page,Up,Down: Byte); {Устанавливает размер курсора/ Подпрограммы управления текстовым выводом \ } Procedure Border (Page,Xl,Yl,X2,Y2,Bord: Byte); {Обводит рамкой заданную прямоугольную область страницы PAGE: X1..Y2 - координаты окна; BORD - константа 0..2, указывающая тип рамки. Символы рамки выводятся с текущими атрибутами} Procedure CopyChar (Page: Byte; Cr: Char; Attr: Byte; Count: Word); {Записывает несколько копий символа, начиная с позиции, на которую указывает курсор: PAGE - номер 0..MaxPage страницы; CR - копируемый символ; ATTR - его атрибуты; COUNT - количество копий символа. Символ записывается с указанными атрибутами, курсор не меняет своего положения) Procedure GetChar (Page: Byte; var Cr: Char; var Attr: Byte); (Читает символ и его атрибуты: PAGE - номер 0..ManPage страницы, откуда нужно прочитать символ; CR - прочитанный символ; ATTR - его атрибуты} Procedure InitText; {Переопределяет константы, зависящие от адаптера и режима его работы. Содержимое экрана не меняется} Procedure MoveFromScreen (var Source, Destin; Count: Word); {Читает данные из видеопамяти: SOURCE - адрес считываемой видеопамяти; DESTIN - имя переменной, куда будут прочитаны данные; COUNT - объем считываемой информации в байтах} Procedure MoveToScreen (var Source, Destin; Count: Word); {Записывает данные в видеопамять: SOURCE - переменная, содержащая записываемую информацию; DESTIN - адрес фрагмента видеопамяти; COUNT - объем записываемой информации} Procedure PageWriteOn; {Переназначает стандартный канал вывода на процедуру PAGEWRITE, поддерживающую вывод в любую страницу} Procedure PageWriteOff; {Восстанавливает стандартный канал вывода} Procedure PutChar (Page: Byte; Cr: Char); {Записывает символ на место, указываемое курсором: PAGE - номер 0..MaxPage страницы; CR - записываемый символ; Символ записывается с текущими атрибутами, курсор не меняет своего положения} Procedure WriteChar (Page: Byte; Cr: Char); {Выводит символ и сдвигает курсор. Используются текущие атрибуты} г ;(•________________—_*-____^__—.._«—-——--.•.--——•——* ¦Многостраничные варианты подпрограмм модуля CRT\ *_—————---—-——-—---——————————----*; Procedure CIrEOL; {Удаляет остаток строки справа от курсора в активной странице} Procedure CIrScr; {Очищает текущее окно (страницу)} Procedure DelLine; {Удаляет строку в активной странице} Procedure GotoXY(X,Y: Byte); {Устанавливает курсор в активной странице} Procedure InsLine; {Вставляет пустую строку в активной странице} Procedure TextBackGround(Color: Byte); {Устанавливает цвет фона а активной странице} Procedure TextColor(Color: Byte); (Устанавливает цвет символов в активной странице} Function WhereX: Byte; /'Возвращает- горизонтальную координату курсора в активной странице} Function WhereY: Byte; {Возвращает вертикальную координату курсора в активной странице} Procedure Window(XI,Y1,X2,Y2: Byte); {Устанавливает окно в активной странице} _'*_________________—--_____-„_-____-_--__------* I Подпрограммы управления страницами \ *——————————————_-_-.——__——————————^ Function GetActivePage: Byte; {Возвращает номер активной текстовой страницы} Procedure GetPage (Page: Byte; var Destin); {Копирует текстовую страницу в оперативную память: PAGE - номер копируемой страницы; DESTIN - переменная, куда будет копироваться страница} Procedure SwapPage (Source, Destin: Byte); {Копирует одну текстовую страницу в другую: SOURCE - номер страницы-источника информации; DESTIN - номер страницы-приемника} Function PageSaveSize: Word; {Возвращает размер буфера, необходимый для сохранения текущего состояния видеостраницы} Procedure PutPage (var Source; Page: Byte); {Пересылает копию текстовой страницы из оперативной памяти в видеопамять: SOURCE - имя переменной, хранящей копию страницы; PAGE - номер страницы-приемника информации} Procedure RestorePage(Page: Byte; var Buf); {Восстанавливает текущее состояние страницы PAGE по содержимому буфера BUF} Procedure SetActivePage(Page: Byte); {Устанавливает активной, заданную текстовую страницу. PAGE - номер страницы} Procedure SavePage(Page: Byte; var Buf); (Сохраняет текущее состояние страницы PAGE в буфере BOF} ^——————————————————————————————» I Подпрограммы управления окнами I *—————————————.————————————————*; Procedure ChangeWindAttribute(Page,01dAtt,NewAtt: Byte); {Заменяет в окне PAGE атрибут OLDATT на значение МЕИАТТ} Procedure CopyWind(Page,X,Y: Byte; var Buf; LX,LY: Byte); (Переносит копию окна из памяти на страницу} Procedure GetWindow (Pac-e: Byte); (Восстанавливает состояние экрана, бывшее перед обращением к процедуре PUTWINDOff: PAGE - номер страницы, куда была скопирована активная} Procedure PutWindow(Xl,Yl,X2,Y2,Text,Back,Bord,Page: Byte; Header: String;Clip,Build,Play: Boolean); (Сохраняет активную страницу в заданной текстовой странице, создает в активной странице окно с заданными атрибутами, очищает его и обводит рамкой: XI...Y2 - координаты окна; TEXT - цвет символов; BACK - цвет фона; BORD - константа, указывающая тип рамки; PAGE - номер 0. .Ma.xPa.ge страницы, куда будет скопирована активная страница; HEADER - заголовок окна; CLIP - признак границ (TRUE - исключая XI...Y2, FALSE - включая границы XI...Y2); BUILD- признак развертывания окна; PLAY - надо ли сопровождать звуком} Procedure SaveWind(Page: Byte; var Buf; var LX,LY: Byte); (Сохраняет копию окна в буфере BUF} Procedure SetPageWindow (Page,XI,Y1,X2,Y2,Bord: Byte; Header: String; Clip: Boolean); (Создает окно в странице PAGE и обводит его рамкой: PAGE - номер страницы; XI...Y2 - координаты окна; BORD - константа, указывающая тип рамки; HEADER - заголовок окна; CLIP - признак границ (TRUE - внутри XI...Y2, FALSE - включая границы XI...Y2). Символы рамки выводятся с текущими атрибутами, окно очищается} Procedure SetWindAttribute(Page,Attr: Byte); (Устанавливает новый атрибут окна} Procedure SetWindow (Xl,Yl,X2,Y2,Bord: Byte; Header: String; Clip,Build,Play: Boolean); {Создает окно в активной странице и обводит его рамкой: XI...Y2 - координаты окна; BORD - константа, указывающая тип рамки; HEADER - заголовок окна; CLIP - признак границ (TRUE - внутри XI...Y2, FALSE - включая границы XI...Y2); BUILD- признак развертывания окна; PLAY - надо ли сопровождать звуком. Символы рамки выводятся с текущими атрибутами, окно очищается} Procedure WindMoveTo(Page,X,Y: Byte; var Buf; ClipW: Boolean); (Перемещает окно в новое положение: PAGE - номер страницы; X,Y - новые координаты левого верхнего угла; BUF - вид экрана без окна; CLIPW- признак отсечки изображения} Procedure WindMoveRel(Page: Byte; DX,DY: Integer; var Buf; ClipW: Boolean); (Смещает окно относительно прежнего положения: PAGE - номер страницы; DX,DY- приращения координат левого верхнего угла; BUF - вид экрана без окна; CLIPW- признак отсечки изображения/ Function WindSize(Page: Byte): Word; (Возвращает размер буфера для сохранения окна} IMPLEMENTATION ^—————————————————..-————————————-/ var Reg: registers; const ActivePage: Byte =0; (Номер активной страницы} { Подпрограммы управления цветом } Procedure ChangeAttribute(Page,Xl,Yl,X2,Y2,01dAtt,NewAtt: Byte) ; {Меняет атрибут OLDATT на значение NEHATT в прямоугольнике XI...У2 страницы PAGE} var Buf: array [1..80,1..2] of Byte; k,j,Size: Byte; begin {Проверяем параметры обращения} if (Page<=MaxPage) and (XI in [1..MaxChar]) and (Yl in [1..MaxLine]) and (X2 in [1..MaxChar]) and (Y2 in [1..MaxLine]) and (X2>Xl) and (Y2>Y1) then begin Size := (X2-X1+1)*2; {Размер строки видеобуфера} for k := Yl •to Y2 do {цикл по строкам} begin (Получаем копию видеопамяти} MoveFromScreen(Mem[VMemory:Page*VSi2e+ (pred(k)*MaxChar+Xl-l)*2],Buf,Size) ; {Меняем атрибут} for j := 1 to Size div 2 do if Buf[j,2] ° OldAtt then Buf[j,2] := NewAtt; {Возвращаем в видеопамять} MoveToScreen(Buf,Mem[VMemory:Page*VSize+ (pred(k)*MaxChar+Xl-l)*2],Size) end end end; (ChangeAttniluce' ;———————————————; Procedure Colors (Text,Back: Byte); {Устанавливает цвет текста TEXT и цвет фона BACK для активной страницы} begin PageColors(ActivePage,Text,Back) end; ^———————————————.^ Procedure PageColors (Page,Text,Back: Byte); (Устанавливает цвет текста TEXT и цвет фона BACK для страницы PAGE) begin if Page<=MaxPage then begin PagesiPage].Attrib := (Text and $8F) or ((Back and ^7) shi 4) or (Back and $80); if Page=0 then begin CRT.TextColor(Text); CRT.TextBackGround(Back) end end end {Colors}; ;•————————— ——————^ Procedure SetAttribute(Page,X1,Y1,X2,Y2,Attr: Byte); {Заменяет атрибут всех символов в прямоугольнике XI...Y2 страницы PAGE на значение Attr} var Buf: array [1..80,1..2] of Byte; k,j,Size: Byte; begin {Проверяем параметры обращения) if (Page<=MaxPage) and (Xl in [1..MaxChar]) and (Yl in [1..MaxLine]) and (X2 in [1..MaxChar]) and (Y2 in [1..MaxLine]) and (X2>X1) and (Y2>Y1) then begin Size := (X2-X1+1)*2; for It := Yl to Y2 do begin MoveFromScreen(Mem[VMemory:Page*VSize+ (pred(k)*MaxChar+Xl-l)*2],Buf,Size) ; for j := 1 to Size div 2 do Buf[j,2] := Attr; MoveToScreen(Buf,Mem[VMemory:Page*VSize+ (pred(k)*MaxChar+Xl-l)*2],Size) end end end; {SetAttribute} _—————————————; Function PackAttribute(Text,Back: Byte): Byte; {Упаковывает два цвета в байт атрибута} begin PackAttribute := (Text and $8F) or ((Back and 7) shi 4) or (Back and $80) end; {PackAttnnute} ^—————————————; Procedure UnPackAttribute(Attr: Byte; var Text,Back: Byte); {Распаковывает байт атрибута и возвращает два цвета} begin Text := Attr and $8F; Back := (Attr shr 4) and 7 end; {UnPackAttribute) /*_—____—_——^__-«—_———_---—-———-——-----—_------_* 1 Подпрограммы управления курсором 1 Procedure CursorOff; {Отключает курсор в активной странице} begin with Reg do begin AH := 1; {Управление курсором} СН := $20 {Убрать курсор} end; lntr($10,Reg); Pages[ActivePage].CVisible := False enu {CursorOff}; /———————————————; Procedure CursorON; {Включает курсор в активной странице} begin with Reg,Pages[ActirePage] do begin AH := 1; {Управление курсором} СН := CLineUp; {Верхняя строка развертки} CL := CLineDown {Нижняя строка} end; Intr($10,Reg) ; Pages[ActivePage].CVisible := True end {CursorOn/ ; ^—————————————————_. Procedure CursorOnOff(Page: Byte; Vis: Boolean); {Устанавливает признак видимости курсора} begin if Page<=MaxPage then if Page-ActivePage then case Vis of True : Cursor-Off; False: CursorOn end else Pages[Page].CVisible := Vis end; (CursorOnOff} /————————„——————; Procedure GetCursor (Page: Byte; var X,Y,Up,Down: Byte); /'Возвращает координаты и размер курсора: PAGE - номер страницы; X, Y - координаты (отсчет от 1,1); Up, Down - размер курсора} begin if Page<=MaxPage then with Reg,Pages[Page] do begin AH := 3; {Получаем положение курсора) ВН := Page; {Номер страницы} Intr($10,Reg) ; Х := succ(DL); {Преобразуем координаты} Y := succ(DH); {к началу в 1,1} Up := CLineUp; (Верхняя строка развертки} Down := CLineDown (Нижняя строка} end end {GetCursor}; ^———————————————; Function GetCursorVisible (Page: Byte): Boolean; {Возвращает признак видимости курсора} begin GetCursorVisible := Pages[Page].CVisible end; (GetCursorVisible} ^———————————————; Procedure PutCursor(Page,X,Y: Byte); (Устанавливает требуемое положение курсора. PAGE - номер страницы; X, Y - координаты курсора (отсчет от 1,1)} begin {Проверяем параметры обращения} if (Page<=MaxPage) and (X in [1..MaxChar]) and (Y in [1..MaxLine]) then wxth Reg do begin AH := 2; {Установить курсор} DH := pred(Y); {Преобразуем координаты} DL := pred(X); {к началу в 0,0} ВН := Page; {Страница} Intr($10,Reg) end end {PutCursor}; ^———————————————-; Procedure SetCursorLine (Pi-.ge,Up, Down: Byte); {Устанавливает размер курсора} begin if Page in [O..MaxPage] then with Pages[Page] do begin CLineUp := Up; CLineDown := Down; if Page=ActivePage then SetActivePage(Page) end end; {SetCursorLine) /*_--_--•-______-__•-_-•-_•---•----.--———---«----* ] Подпрограммы управления текстовый выводом ¦ *——————————————————————————————*; var OldOutput: Text; (Сохраняет стандартный канал вывода} const ChangeOut: Boolean = False; {Флаг замены канала вывода) Procedure WriteCharXY(Page,X,Y: Byte; Cr: Char); (Выводит символ на указанное место. Атрибуты берутся из пассива Attrib. Курсор остается на месте} var Loc: Word; {Старое положение курсора} begin Loc := MemW[$0040:$0050+P?ge]; with Reg do begin AH := 2; DL := X-1; DH := У-1; BH := Page; Intr($10,Reg); {Переводим курсор} АН := $9; AL :° ord(Cr) ; BL := Pages[Page].Attrib; BH := Page; CX := 1; Intr($lO,Reg); (Выводим, символ} АН := 2; DX := Loc; BH := Page; Intr($10,Reg) {Курсор - на старое место} end; MemW[$0040:$005O+Page] := Loc end; {WriteChavXYf /—————————————————; Function ZeroFunc(var F: TextRec): Integer; Far; {Пустая процедура для операций OPEN/CLOSE} begin ZeroFunc := 0 end; {ZeroFunc} (———...———— ————————; Procedure Border (Page,Xl,Yl,X2,Y2,Bord: Byte); {Обводит ранкой заданную прямоугольную область экрана/ var i : Integer; begin {Проверяем параметры обращения) if not ((Page>MaxPage) or (X1<1) or (X2<=X1) or (Y1<1) or (Y2<-Y1) or (X2>MaxChar) or (Y2>MaxLine) or (Bord>2)) then begin WnteCharXY(Page,Xl,Yl,BorderChar[Bord,l]) ; for i := 1 to X2-X1-1 do {Верхняя рамка} WriteCharXY(Page,Xl+i,Yl,BorderChar[Bord,2]); WnteCharXY(Page,X2,yi,BorderChar[Bord,3]) ; for i := 1 to Y2-Y1-1 do {Боковые стороны} begin WriteCharXY(Page,Xl,Yl+i,BorderChar[Bord,4]) ; WriteCharXY(Page,X2,Yl+i,BorderChar[Bord,4]) end; WnteCharXY(Page,Xl,Y2,BorderChar[Bord,5]); for i := 1 to x2-xl-l do {Нижняя рамка} WriteCharXY(Page,Xl+i,Y2,BorderChar[Bord,2]) ; WriteCharXY(Page,X2,Y2,BorderChar[Bord,6]) end end {Border}; {— —.—————-.————————; Procedure CopyChar(Page:Byte; Cr:Char;Attr:Byte; Count:Word); {Выводит несколько копий символа} begin if (Count>0) and (Page<=MaxPage) then with Reg do begin AH :== 9; (Вывод символа} AL := ord(Cr); {Код символа} BL := Attr; {Атрибут} BH := Page; {Страница} СХ := Count; (Количество копий} Intr($lO,Reg) end end /CopyChar}; ^—————————————————J Procedure GetChar (Page: Byte; var Cr: Char; var Attr; Byte); {Читает символ, на который указывает курсор, и его атрибуты) begin if Page<=MaxPage then with Reg do begin AH := 8; {Читать символ) ' BH := Page; {Страница) Intr($10,Reg) ; Cr := chr(AL); {Символ} Attr := АН {Его атрибут) end else {Неверная страница) begin Cr :» chr(O); Attr := 0 end end {GetChar); Procedure InitText; {Переопределяет константы, зависящие or адаптера и режима его работы. Содержимое экрана не меняется) var i : Integer; begin {Проверяем параметры обращения) if not ((Page>MaxPage) or (X1<1) or (X2<=X1) or (Y1<1) or (Y2<-Y1) or (X2>MaxChar) or (Y2>MaxLine) or (Bord>2)) then begin WnteCharXY(Page,Xl,Yl,BorderChar[Bord,l]) ; for i := 1 to X2-X1-1 do {Верхняя рамка} WriteCharXY(Page,Xl+i,Yl,BorderChar[Bord,2]); WnteCharXY(Page,X2,yi,BorderChar[Bord,3]) ; for i := 1 to Y2-Y1-1 do {Боковые стороны} begin WriteCharXY(Page,Xl,Yl+i,BorderChar[Bord,4]) ; WriteCharXY(Page,X2,Yl+i,BorderChar[Bord,4]) end; WnteCharXY(Page,Xl,Y2,BorderChar[Bord,5]); for i := 1 to x2-xl-l do {Нижняя рамка} WriteCharXY(Page,Xl+i,Y2,BorderChar[Bord,2]) ; WriteCharXY(Page,X2,Y2,BorderChar[Bord,6]) end end {Border}; {— —.—————-.————————; Procedure CopyChar(Page:Byte; Cr:Char;Attr:Byte; Count:Word); {Выводит несколько копий символа} begin if (Count>0) and (Page<=MaxPage) then with Reg do begin AH :== 9; (Вывод символа} AL := ord(Cr); {Код символа} BL := Attr; {Атрибут} BH := Page; {Страница} СХ := Count; (Количество копий} Intr($lO,Reg) end end /CopyChar}; ^—————————————————J Procedure GetChar (Page: Byte; var Cr: Char; var Attr; Byte); {Читает символ, на который указывает курсор, и его атрибуты) begin if Page<=MaxPage then with Reg do begin AH := 8; {Читать символ) ' BH := Page; {Страница) Intr($10,Reg) ; Cr := chr(AL); {Символ} Attr := АН {Его атрибут) end else {Неверная страница) begin Cr :» chr(O); Attr := 0 end end {GetChar); Procedure InitText; {Переопределяет константы, зависящие or адаптера и режима его работы. Содержимое экрана не меняется) test al,l {проверяем наличие обратного хода} jne @2 (Ждем обратный ход} lodsw (Получаем видеослово} sti (Открываем прерывания} stosw (Пишем видеослово в приемник} loop 81 {Продолжаем цикл} end end; {MoveFromScreen} {,-. —————————— ————; Procedure MoveToScreen (var Source, Destin;Count: Word); {Записывает данные в видеопамять} begin if Count>0 then if not CheckSnow then Move (Source,Destin,Count) else {Синхронизация переноса для адаптера CGA} asm Ids si,[Source] {DS:SI = адрес источника} les di,[Destin] {ES:DI = адрес приемник} mov ex,Count {Грузим в CX счетчик} eld (Направление передачи} shr ex, 1 {Переводим байты в слова) mov dx,PortCGA {Получаем в ОХстатус CGA-порта} mov Ы,9 {Готовим a BL маску проверки готовности} {Отсюда начинается цикл записи в видеопамять, который продолжается во время обратного хода луча при горизонтальной развертке. Запись проходит при закрытых прерываниях.} @3: lodsw {Получаем в ВР} mov Ьр,ах (очередное видеослово} cli /Закрываем прерывания) @4: in al,dx (Получаем статус видеопорта} test al,l {Конец горизонтального хода?} jne @4 {Нет - ждем} mov ax,bp (Переносим в АХ видеослово} stosw (Пишем его в видеопамять) sti (Открываем прерывания} loop @3 {Продолжаем цикл} end end; {MoveToScreen} _•__—————————————; Function pagewrite(var F: TextRec): Integer; Far; {Осуществляет вывод строки, подготовленной процедурами HRITE/WRITELN, в активную видеостраницу} var k: Integer; begin with F,Pages[ActivePage] do if (Mode=fm0utput) and (BufPos>0) then begin for k := 0 to BufPos-1 do with Reg do WriteChar(ActivePage,BufPtr'^ [k]) ; BufPos := 0 {Обнуляем буфер.вывода} end; PageWrite :° О end; (PageWrite} /————————————————; Procedure PageWriteOff; (Восстанавливает стандартный канал вывода} begin it ChangeOut then begin move(OldOutput,Output,SizeOf(Output)); , ChangeOut :° False end end; {PagefirlteOff} ^——————_——_——————; Procedure PageWriteOn; (Переназначает стандартный канал выведана процедуру PAGEWRITE, поддерживающую вывод в любую страницу} begin if ChangeOut then Exit; (Блокируем повторную установку} ChangeOut := True; (Сохраняем старый драйвер:} move(Output,OldOutput,SizeOf(Output) ) ; with TextRec(Output) do begin (Назначаем новый драйвер:} OpenFunc := @ZeroFunc; InOutFunc := @PageWrite; FluahFunc := BPageWrite; CloseFunc := @ZeroFunc; end end; {PageWriteOn} _•—————_——_-———————; procedure PutChar (Page: Byte; Cr: Char); (Записывает символ на место, указываемое курсором в заданной странице. Курсор не меняет положения. Атрибуты берутся из массива Attrib} begin if Page<°MaxPage then with Reg do begin AH := $9; AL := ord(Cr) ; BH := Page; BL := Pages[Page].Attrib; CX := 1; Intr($10,Reg) end end (PutChar}; ^————————_————————; Procedure WriteChar (Page: Byte; Cr: Char); {Выводит символ и сдвигает курсор. Используются атрибуты из массива Attrib} var X,Y,Xl,Yl,X2,Y2,Size: Byte; Buf: array [1..80,1..2] of Char; VW,k: Word; P: Pointer; begin if Page<=MaxPage then with Reg,Pages[Page] do begin GetCursor(Page,X,Y,Xl,Yl) ; {Смещение в странице} k := (Pred(Y)*MaxChar+Pred(X))*2; P := ptr(VMemory,VMW[Page*2]+k) ; VW := Pages[Page].Attrib shi 8+ord(Cr); case Cr of (Обрабатываем спецсимволы} #7: begin /Звук/ Sound(900) ; Delay(150); NoSound; Exit end; #8: if X>Lo(WBondOp)+2 then (Back Space} dec(X,2) else if Y>Hi(WBondUp)+2 then begin X := Lo(WBondDown); dec(Y) end; #10: inc(X,80); {LF} #13: X :» Lo(WBondUp); {CR} else MoveToScreen(VW,Pл,2); end; Inc(X); {Сдвигаема строке) if X-l>Lo(WBondDown) then {Достигнута правая граница окна} begin X := Lo(WBondOp)+1; (Возвращаем к левой} inc(Y); {границе на новой строке} if Y-l>Hi(WBondDown) then begin {Достигли нижнюю границу} {Делаем прокрутку с помощью прямого обращениях видеопамяти, т.к. функцич б работает только с активной страницей) dec (Y) ; XI := Lo(WBondOp); Yl :° Hi<WBondUp) ; X2 := Lo(WBondDown); Y2 := Hi(WBondDown); Size := 2*(X2-X1+1); for k :- Yl+1 to Y2 do begin MoveFromScreen(Mem[VMemory:Page* VSize+(k*MaxChar+Xl)*2],But,Size) ; MoveToScreen(Buf,Mem[VMemory:Page* VSize+((k-l)*MaxChar+Xl)*2],Size) end; for k := 1 to 1+X2-X1 do Buf[k,l] := ' •; MoveToScreen(Buf,Mem[VMemory:Page* VSize+(Y2*MaxChar+Xl)*2],Size) end end; PutCursor(Page,X,Y) end end; {WriteChac} ^————.———————————————————————————* I Многостраничные варианты подпрограмм модуля CRT I *———————————————————————————————*; Procedure CIrEOL; {Удаляет остаток строки справа от курсора в активной странице} var XI,X2: Byte; Р: Pointer; X,Y: Byte; Buf: array [1..80] of Word; begin GetCursor(ActivePage,X,Y,Xl,X2); with Pages[ActivePage] do begin P := Ptr(VMemory,VMW[ActivePage*2]+ (Pred(Y)*MaxChar+Pred(X))*2) ; X2 := PagePar[7]-X+2; for X := 1 to X2 do Buf[X] := 32+Attrib shi 8; MoveToScreen(Buf,P^,X*2) end end; {CIrEOLf f—— _____————__——————; Procedure CIrScr; {Очищает текущее окно (страницу)} begin with Pages[ActivePage],Reg do begin AH := 6; 1 С помощью прокрутки} AL := 0; {очищаем все окно} ВН := Attrib; CL := Lo(WBondUp) ; СН := Hi(WBondUp); DL :» Lo(HBondDown); DH := Hi(HBondDown) ; Intr($10,Reg) ; AH :•= 2; f Устанавливаем курсор} ВН := ActivePage; /'в левый верхний угол} DX :° WBondUp; Intr($10,Reg) end end; {CIrScr} /—————————————————^ Procedure DelLine; (Удаляет строку в активной странице) var k, S, {Длина строки окна} У: Byte; (Номер строки с курсором} С: Word; {Смещение в памяти для левой границы окна} Buf: array [1..80,1..2] of Char; {Буфер строк) P: Pointer; begin {Стираем строку прокруткой окна вверх} with Pages[ActivePage] do begin {Определяем положение в видеопамяти левой верхней границы окна) С := VMW[ActivePage*2]+PagePar[5]*2; Y := PagePar[6]+Pred(HhereY); S := (PagePar[7]-PagePar[5]+l)*2; {Переносим по строкам} for К := 1+1 to PagePar[8] do begin P := Ptr(VMemory,C+K*MaxChar*2); MoveFromScreen (P",Q\if, a) •i P := Ptr(VMemory,C+(K-l)*MaxChar*2); MoveToScreen(Buf,P",s) end; {Готовим пустую строку} for К := 1 to 80 do begin Buf[k,l] :" ' '; Buf[k,2] := chr(Attrib) end; {Выводим ее} Р :- Ptr(VMemory,C+FagePai-[8]*MaxChar*2); MoveToScreen(Buf,P",s) end end; (DelLine} /————————————————; Procedure GotoXY(X,Y: Byte); {Устанавливает курсор в активной странице! begin with Pages[ActivePage] do PutCursor(ActivePage,Lo(WBondUp)+X,Hi(WBondUp)+Y) end; {GotoXYf ^————————————————; Procedure InsLine; (Вставляет пустую строку в активной странице} var k, S, {Длина строки окна} Y: Byte; ' (Номер строки с курсором} С: Word; {Смещение а памяти для левой границы окна) Buf: array [1..80,1..2] of Char; {Буфер строк! Р: Pointer; begin with Pages[ActivePage] do begin {Определяем положение в видеопамяти левой верхней границы окна} С := VMW[ActivePage*2]+PagePar[5]*2; Y := PagePar[6]+Pred(WhereY) ; S := (PagePar[7]-PagePar[5]+l)*2; {Переносим по строкам} for К :•= PagePar[8]-l downfco Y do begin Р := Ptr(VMemory,C+K*MaxChar*2) ; MoveFromScreen(P'',Buf,s); P := Ptr(VMemory,C+(K+l)*MaxChar*2); MoveToScreen(Buf,Р",з) end; {Готовим пустую строку} for К :° 1 to 80 do begin Buf[k,l] := ' '; Buf [It, 2] := chr(Attrib) end; {Выводим ее} Р :- Ptr(VMeroory,C+Y*MaxChar*2) ; MoveToScreen(Buf,V,s) end end; {InsLine} ^—.———————————————; Procedure TextBackGround(Color: Byte); (Устанавливает цвет фона в активной странице} begin Pages[ActivePage].Attrib :~ (Pages[ActivePage].Attrib and $8F) or (Color and $7) shi 4); it ActivePage=0 then CRT.TextBackGround(Color) •nd; fPageTextBackGround} ^———————————_—.———; Procedure TextColor(Color: Byte); (Устанавливает цвет символов s активной странице) begin Pages[ActivePage].Attrib := (Pages[ActivePage].Attrib and $70) or (Color and $8F) ; if ActivePage=O then CRT.TextColor(Color) end; {PageTextColor} {-.- ————.—————— ————/ Function WhereX: Byte; {Возвращает горизонтальную координату курсора в активной странице} var X,Y,U,D: Byte; begin GetCursor(ActivePage,X,Y,U,D) ; WhereX := X-Lo(Pages[ActivePage].WBondUp) end; {WhereX} ^—.——————————————; Function WhereY: Byte; (Возвращает вертикальную координату курсора в активной странице} var X,Y,U,D: Byte; begin GetCursor(ActivePage,X,Y,П,D); WhereY := Y-Hi(Pages[ActivePage].WBondUp; end; (WhereY} ^——.————————.————.———; Procedure Window(XI,Y1,X2,Y2: Byte); {Устанавливает окно в активной странице} begin {Проверяем параметры обращения} if (XI in [1..MaxChar]) and (X2 in [1..MaxChar]) and (X2>X1) and (Yl in [1..MaxLine]) and (Y2 in [1..MaxLine]) and (Y2>Y1) then with Pages[ActivePage] do begin WBondUp := pred(Xl)+pred(Yl) shi 8; WBondDown :» pred(X2)+pred(Y2) shi 8; PutCursor(ActivePage,XI,Yl); if ActivePage=0 then CRT.Window(XI,Y1,X2,Y2) end end; / ^_—________________----—•._»_•----------»——-----^.А- I Подпрограммы управления страницами \ ii-----------.--.---------------------------—-----'^ Function GetActivePage: Byte; (Возвращает номер активной текстовой страницы} begin GetActivePage := ActivePage end (GetActivePage}; ——————————————————/ Procedure GetPage (Page: Byte; var Destin); ^Копирует текстовую страницу в оперативную память} begin if Раде<-МахРаде then MoveFromScreen(Mem[VMemory:VSize*page],Destin,MaxChar*MaxLine*2) end (GetPage}; I ——...—.——————————— • Function PageSaveSize: Word; {Возвращает размер буфера, необходимый для сохранения текущего состояния видеостраницы} begin PageSaveSize :« PageSize+SizeOf(PageType) end; {PageSaveSize} /————————————————; Procedure PutPage (var Source; Page: Byte); {Пересылает содержимое оперативной памяти в страницу видеопамяти! begin if Page<=MaxPage then MoveToScreen(Source,Mem[VMemory:VSize*Page],MaxChar*MaxLine*2) end {PutPage}; ;-———————————————; Procedure RestorePage(Page: Byte; var Buf); {Восстанавливает текущее состояние страницы PAGE по содержимому буфера BUF} var В: array [O.-MaxInt] of Byte absolute Buf; begin if Page>MaxPage then Exit; MoveToScreen(B,VMP[Page]",PageSize) ; Move(B[PageSize],Pages[Page],SizeOf(PageType)); if Page=ActivePage then SetActivePage(ActivePage) end; {RestorePage} {.....—————————————} Procedure SavePage(Page: Byte; var Buf); {Сохраняет текущее состояние страницы PAGE в буфере BUF} var В: array [O.-MaxInt] of Byte absolute Buf; begin if Page>MaxPage then Exit; MoveFromScreen (VHP [Page] ",B, PageSize); Move(Pages[Page],В[PageSize],SizeOf(PageType)) end; {SavePage} _•——__———————— ..,-——} Procedure SetActivePage (Page : Byte); (Активизирует заданную текстовую страницу} begin if Page<-MaxPage then with Reg,Pages[Page] do begin AH := 5; {Установить страницу} AL := Page; {Номер страницы} ActivePage :=' Page; lКорректируем ActivePage} Intr ($10,Reg); if CVisible then {Включаем/отключаем} CursorOn {курсор} else CursorOff; TextAttr :== Attrib; {Устанавливаем атрибут} WindMin := WBondUp; {Текущее окно} WindMax := WBondDown end; end {SetActivePage}; /————————————————; Procedure SwapPage (Source, Destin: Byte); { Копирует одну текстовую страницу в другую } var buf : array [1..2, 1..80] of Byte; i : integer; begin if (Source<=MaxPage) and (Destin<=MaxPage) then for i := 0 to MaxLine-1 do begin MoveFromScreen (Mem [VMemory :VSi2e*Source+i*Ma.xChar*2] ,buf,MaxChar*2) ; MoveToScreen(buf,Mem[VMemory:VSize*Destin+i*MaxChar*21,MaxChar*2) end end /SwapPage]; I Подпрограммы управления окнами 1 *———————————————————.——————————*; Procedure ChangeWindAttribute(Page,01dAtt,NewAtt: Byte); {Заменяет в окне атрибут OLDATT на значение NEWATTf var X1,Y1,X2,Y2: Byte; begin if Page<=MaxPage then with Pages[Page] do begin XI :° Lo(WBondUp) ; Yl := Hi(WBondUp) ; X2 := Lo(WBondDown)+2; Y2 := Hi(HBondDown)+2; ChangeAttribute(Page,XI,Yl,X2,Y2,OldAtt,NewAtt) end end; {ChangeWindAttribute} ^———————————————/ Procedure CopyWind(Page,X,Y: Byte; var Buf;,LX,LY: Byte); {Переносит копию окна из яамяги на страницу} var X2,Y2,k: Byte; Size: Word; В: array [O.-MaxInt] of Byte absolute Buf; begin if (X in [1..MaxChar]) and (Y in [1..MaxLine]) and (Page<=MaxPage) then with Pages[Page] do begin X2 := X+LX-1; if X2>MaxChar then X2 := MaxChar; Y2 := Y+LY-1; if Y2>MaxLine then У2 := MaxLine; Size := (X2-X+1)*2; for k := У to Y2 do MoveToScreen(B[(k-Y)*LX*2],Mem[VMemory:Page*VSize+ (pred(k)*MaxChar+X-l)*2],Size) ; WBondUp := X+Y shi 8; WBondDown := X2-2+(Y2-2) shi 8; if Page=ActivePage than SetActivePage(Page) end end; (Copy Wind} ^_————_————————_—; Procedure GetWindow (Page: Byte); (Восстанавливает состояние экрана, бывшее перед обращением к процедуре PUTWIVDOW} var X,Y,U,D: Byte; begin if (Page<-MaxPage) and (PagaoActivePage) then begin SwapPage(Page,ActivePage); Move(Pages[Page],Pages[ActivePage],SiaeOf(PageType)); GetCursor(Page,X,Y,U,D) ; PutCursor(ActivePage,X,Y); SetCursorLine(ActivePage,U,D); SetActivePage(ActivePage) end end {GetSfindow}; ^-.___—————————————; Procedure PutHindow(Xl,Yl,X2,Y2,Text,Back,Bord,Page: Byte; Header: String; Clip,Build,Play: Boolean); {Сохраняет текущий экран в текстовой странице PAGE и организует окно с заданными атрибутами и рамкой} var X,Y,U,D: Byte; begin if not ((Page>MaxPage) or (XK1) or (X2<-X1) or (Y1<1) or (Y2<=Y1) or (X2>MaxChar) or (Y2>MaxI»ine) or (Bord>2)> then begin SwapPage(ActivePage,Page); Move(Pages[ActivePage],Pages[Page),SizeOf(PageType)); GetCursor(ActivePage,X,Y,U,D); PutCursor(Page,X,Y) ; SetCursorLine(Page,U,D); Colors(Text,Back); SetWindow(XI,XI,X2,Y2,Bord,Header,Clip,Build,Play) end; end {PutWindo»); _-.——————————————; Procedure SaveWind(Page: Byte; var Buf; var LX,LY: Byte); {Сохраняет копию окна в буфере BUF} var X1,Y1,X2,Y2: Byte; В: array [O-.MaxInt] of pyte absolute Buf; k: Byte; begin if Page<=-MaxPage then with Pages [Page] do begin XI » Lo(WBondUp) ; Yl = Hi(WBondUp) ; X2 = Lo(WBondDown)+2; Y2 ° Hi(WBondDown)+2; LX = X2-X1+1; LY = Y2-Y1+1; for k :== Yl to Y2 do MoveFromScreen (Mein[VMemory:Page*VSi2e+ (pred(k)*MaxChar+Xl-l)*2],B[(k-Yl)*LX*2],LX*2) end end; {SaveWind) ^_———————————————; Procedure SetPageWindow (Page,XI,Y1,X2,Y2,Bord: Byte; Header: String;Clip: Boolean); (Создает окно в странице PAGE и обводит его рамкой} var buf: array [1..80,1..2] of Byte; X,Y,Size,k: Byte; begin i? not ( (Page>MaxPage) or (X1<1) or (X2<-X1) or (УК1) or (Y2<=Y1) or (X2>MaxChar) or (Y2>MaxLine) or (Bord>2)) then begin (Очищаем прямоугольное окно на экране} Size := Х2-Х1+1; for Y := 1 to Size do begin buf[Y,ll := ordC •); bu?[Y,2] :» Pages[Page].Attrib end; Size := Size+Size; for Y := Yl to Y2 do MoveToScreen(Buf,Mem[VMemory:Page*VSize+ (pred(Y)*MaxChar+pred(Xl))*2],Size) ; {Обводим его рамкой и выводим заголовок} if BordOEmptyBorder then Border(Page,XI,Yl,X2,Y2,Bord); if Length(Header)>0 then begin if Length(Header)>X2-X1-2 then Header[0] :» chr(X2-Xl-2); X := Xl+(X2-Xl-Length(Header)) div 2; for k := 1 to Length(Header) do WriteCharXY(Page,X+k,Yl,Header W); end; {Корректируем границы внутрь прямоугольника XI...Y2, если признак Clip равен Гrue^ if Clip then begin inc(XI) ; inc (YD ; dec(X2); dec(Y2) end; {Устанавливаем курсор в левую вершину ft запоминаем координаты} dec(XI); (Преобразуем координаты} dec(Yl); {к началу в точке 0,0} dec(X2); dec(Y2) ; PutCursor(Page,Xl+l,Yl+l); Pages[Page 1.WBondUp :-X1+Y1 shi 8; Pages[Page 1.WBondDown :=X2+Y2 shi 8; if page=ActivePage then SetActivePage(Page) end end {SetPageWindow}; ^———————————————————————-.Jl Procedure SetWindAttribute(Page,Attr: Byte); {Устанавливает новый атрибут окна} var X1,Y1,X2,Y2: Byte; begin if page<-MaxPage then with Pages[Page] do begin XI :° Lo(WBondUp) ; XI := Hi(WBondUp) ; X2 :- Lo(WBondDown)+2; Y2 :» Hi(WBondDown)+2; SetAttribute(Page,Xl,Yl,X2,Y2,Attr) end end; {SetWindAttribute} ^——————————————/ Procedure SetWindow (Xl,Yl,X2,Y2,Bord: Byte; Header: String; Clip,Build,Play: Boolean); {Создает окно в активной странице и обводит его рамкой} var xxl,yyl,xx2, yy2,x,y,dx,dy,k: Byte; dt: Integer; const TonBeg = 400; {Начальный тон I TonEnd •" 800; {Конечный тон} Pause - 5; N = 10; begin if Build and ((x2-xl>-4) or (y2-yl>=4)) then begin {Начальное положение левого верхнего угла окна} х := (x2-xl) div 2; у := (у2-у1) div 2; (Количество промежуточных окон} dx := ((x2-xl) div 2) div N; dy := ((y2-yl) div 2) div N; if dx=0 then inc(dx) ; if dy-0 then inc(dy); if x>l then begin xxl := xl+x-1; xx2 :" x2-x+l end else begin xxl :- xl; xx2 :- x2 end; if y>l then begin yyl :- yl+y-1; yy2 := y2-y+l end else begin yyl :» yl; yy2 :- y2 end; (Изменение тона} dt := (TonEnd-TonBeg) div N; for k :» 0 to N-1 do {Цикл построения} begin if Play then Sound (TonBeg+dt*k) ; (Включаем э-вук/ SetPageWindow(ActivePage,xxl,yyl,xx2,yy2,Bord,Header,Clip); (Увеличиваем границы окна} if xxl>xl then dec(xxl,dx) ; if xx2<x2 then inc (xx2,dx) ; if yyl>yl then dec(yyl,dy); if yy2<y2.then inc(yy2,dy) ; Delay(Pause) end; if Play then NoSound; end; SetPageWindow(ActivePage,XI,Yl,X2,Y2,Bord,Header,Clip) end; {SetWindow} /—————_———_—____——; Procedure WindMoveRel(Page: Byte; DX,DY: Integer; var Buf; ClipW: Boolean); {Смещает окно относительно прежнего положения: PAGE - номер страницы; DX,DY- приращения координат левого верхнего угла; BUF - вид экрана без окна; CLIPW- признак отсечки изображения} чах X,Y: Byte; begin if Page<=MaxPage then with Pages[Page] do begin X := Lo(WBondUp) ; Y := Hi(WBondUp) ; if X+DX<1 then X := 1 else if X+DX>MaxChar then X := MaxChar else X := X+DX; if Y+DY<1 then Y := 1 else if Y+DY>MaxLine then Y := MaxLine else Y := Y+DY; WindMoveTo(Page,X,Y,Buf,ClipW) end end; {WIndMovRel} ^_____________________——; Procedure WindMoveTo(Page,X,Y: Byte; var Buf; ClipW: Boolean); {Перемещает окно в новое положение: PAGE - номер страницы,' X,Y - новые координаты левого верхнего угла; BUF - вид экрана без окна; CLIPW- признак отсечки изображения} var X2,Y2,LX,LY: Byte; Сор: array [1..4OOO] of Byte; begin if (X in [1..MaxChar]) and (Y in [1..MaxLine]) and (Page<=MaxPage) then with Pages[Page] do begin {Копируем окно в буфер Сор} SaveWind(Page,Cop,LX,LY); {Восстанавливаем вид страницы} MoveToScreen (Buf, VMP [Page] ^PageSize); if not ClipW then {Корректируем положение} begin while X+LX-l>MaxChar do dec (X) ; while Y+LY-l>MaxLine do dec(Y) end; {Переносим окно на новое место} CopyWind(Page,X,Y,Cop,LX,LY) ; {Запоминаем новые границы окна} it Page=ActivePage then SetActivePage(Page) end end; {WindMoveTo} f—— ——-.————————-.————; Function WindSize(Page: Byte): Word; {Возвращает размер буфера для сохранения окна} var X1,Y1,X2,Y2: Byte; begin if Page<=MaxPage then with Pages[Page] do begin XI := Lo(WBondUp) ; Yl := Hi(WBondUp) ; X2 := Lo(WBondDown)+2; У2 :» Hi(WBondDown)+2; WindSize := (X2-X1+1) * (Х2-П+1) *2 end else WindSize := 0 end; {WindSize} /===»====»=.==; end. {TextCRT} /==.=====-..«——/ |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |