procedure PutX(X: Word); {задание координат X -абсолютной и смещения начала экрана, если Х=0, координата не меняется}
procedure PutY(Y: Word); {задание координат Y - абсолютной и смещения начала экрана, если Y=0 или больше максимального числа, координата не меняется}
procedure IncX; {увеличение координат Х на 1}
procedure DecX; {уменьшение координат Х на 1, если Xabs=0, координата не меняется}
procedure IncY; {увеличение координат Y на 1 и получение следующего текущего указателя на строку, если след. строки нет, координата неменяется}
procedure DecY; {уменьшение координат Y на 1 и получение предыдущего текущего указателя на строку, если Yabs=0, координата не меняется}
function GetX: Word; {получение координаты Xabs}
function GetY: Word; {получение координаты Yabs}
function GetPointLine(Y: Word): pLine;
{получение указателя на строку с координатой Y}
procedure PutSymb;{помещение символа в текст с текущими координатами}
function GetSymb: Char; {получение символа с текущими координатами}
procedure PutEkran; {вывод текста на экран}
procedure PutCursor; {вывод курсора на экран}
end;
{ * * Объект - выполнение операции * * }
TYPE
pOperation =^tOperation;
tOperation = object {предок последующих объектов}
constructor Init;
procedure PutNewSymb; {обработка введенного символа}
procedure Ins; virtual; {размещение символа в тексте}
end;
{* Объект - размещение символа с кодом больше 30 *}
pInsertSymbol = ^tInsertSymbol;
tInsertSymbol = object(tOperation) {потомок типа tOperation}
Symb: Char; {размещаемый символ}
constructor Init; {конструктор объекта}
procedure Ins; virtual; {размещение символа}
end;
{* Объекты - перемещение курсора на одну позицию *}
pInsertUp = ^tInsertUp;
tInsertUp = object(tOperation)
constructor Init; {конструктор объекта}
procedure Ins; virtual;{перемещение курсора вверх}
end;
pInsertDn = ^tInsertDn;
tInsertDn = object(tOperation)
constructor Init; {конструктор объекта}
procedure Ins; virtual; {перемещение курсора вниз}
end;
pInsertLeft = ^tInsertLeft;
tInsertLeft = object(tOperation)
constructor Init; {конструктор объекта}
procedure Ins; virtual;{перемещение курсора влево}
end;
pInsertRight = ^tInsertRight;
tInsertRight = object(tOperation)
constructor Init; {конструктор объекта}
procedure Ins; virtual; {перемещение курсора вправо}
end;
{* * Объект - обработка клавиши Enter * *}
pInsertEnter = ^tInsertEnter;
tInsertEnter = object(tOperation)
constructor Init; {конструктор объекта}
procedure Ins; virtual; {формирование новой строки}
end;
{** Объект -обработка клавиши Backspace **}
pInsertBackSpace =^tInsertBackSpace;
tInsertBackSpace =object(tOperation)
constructor Init; {конструктор объекта}
procedure Ins; virtual; {удаление символа или объединение двух строи}
end;
var
PointText: pText; {указатель создаваемого текста}
Symbol: pInsertSymbol;{указатель на объект - размещение символа}
Up: pInsertUp; {указатель на объект - курсор вверх}
Dn: pInsertDn; {указатель на объект - курсор вниз }
Left: pInsertLeft; {указатель на объект - курсор влево}
Right: pInsertRight; {указатель на объект - курсор вправо}
Enter: pInsertEnter; {указатель на объект - обработка клавиши Enter}
BackSpace: pInsertBackSpace;{указатель на объект-обработка клавиши Backspace}
StringOfBlanks: tStringLen; {строка пробелов}
{* * * Исполнительная часть модуля * * *}
IMPLEMENTATION
USES Crt;
{** Подпрограммы tConnection **}
Procedure tConnection.PutPredElem (PredEl : Pointer) ;
Begin
PredElem := PredEl
End;
procedure tConnection.PutNextElem(NextEl: Pointer);
begin
NextElem := NextEl
end;
function tConnection.GetPredElem: Pointer;
begin
GetPredElem := PredElem
end;
function tConnection.GetNextElem: Pointer;
begin
GetNextElem := NextElem
end;
{* * Подпрограммы tStructure * *}
constructor tStructure.Init;
begin {фиктивная подпрограмма}
end;
procedure tStructure.PutFirstElem(FirstEl:Pointer);
begin
FirstElem := FirstEl
end;
procedure tStructure.PutLastElem(LastEl: Pointer);
begin
LastElem := LastEl
end;
function tStructure.GetFirstElem: Pointer;
begin
GetFirstElem := FirstElem
end;
function tStrUcture.GetLastElem: Pointer;
begin
GetLastElem := LastElem
end;
function tStructure.InitElem: Pointer;
begin {фиктивная подпрограмма}
end;
procedure tStructure.DispElem(PointDel: Pointer);
begin {фиктивная подпрограмма}
end;
procedure tStructure.PutConnection(FirstPoint, SecondPoint:Pointer);
begin
if FirstPoint<>nil then {первый элемент существует - связь со вторым}
pLine(FirstPoint)^.PutNextElem(SecondPoint)
else {нет - второй элемент - начальный}
PutFirstElem(SecondPoint);
if SecondPoint<>nil then {второй элемент существует - связь с первым}
pLine(SecondPoint) ^.PutPredElem(FirstPoint)
else {нет - первый элемент - конечный}
PutLastElem(FirstPoint);
end;
procedure tStructure.NewEl(PointPredEl, PointNextEl: Pointer);
var NewPoint: Pointer;
begin
NewPoint :=InitElem; {новый элемент}
PutConnection(PointPredEl, NewPoint); {связь с предыдущим элементом}
PutConnection(NewPoint, PointNextEl); {связь со следующим элементом}
end;
procedure tStructure.DelEl(PointDel: Pointer);
var Point: pLine;
begin
Point := PointDel;
PutConnection(Point^.GetPredElem, Point^.GetNextElem);
{установление связей минуя удаленный элемент}
DispElem (PointDel) {удаление элемента}
end;
{** Подпрограммы tElLine **}
constructor tElLine.Init;
begin
Info:=StringOfBlanks; {заполнение строки пробелами}
end;
procedure tElLine.PutSymb(Ch: Char; NomInEl: Byte; var OldSym: Char);
begin
if (NomInEl > 0) and (NomInEl <= Len) then
{допустимый номер символа}
begin
OldSym := Info [Len] ; {сохранение последнего символа}
Insert (Ch, Info, NomInEl) {размещение символа}
end;
end;
function tElLine.GetSymb(NomInEl: Byte): Char;
begin
if (NomInEl > 0) and (NomInEl <= Len) then
{допустимый номер символа}
GetSymb := Info[NomInEl]
Else
GetSymb := ' ' {нет - помещение пробела}
end;
procedure tElLine.PutString(Str: tStringLen; BegNom: Byte);
begin
Insert (Str, Info, BegNom) {размещение строки}
end;
function tElLine.GetString(BegNom: Byte): tStringLen;
begin
GetString := Copy(Info,BegNom,Len) {получение части строки}
end;
{* * Подпрограммы tLine *}
constructor tLine.Init;
begin
NewEl(nil,nil){задание связей первого элемента}
end;
destructor tLine.Done;
var P1,P2: pElLine;
begin
P1:= GetFirstElem; {указатель на первый элемент}
while P1<> nil do {пока есть очередной элемент...}
begin
P2:=P1^.GetNextElem;{указатель на следующий элемент}
Dispose(P1); {удаление элемента строки}
P1:= P2
end;
end;
function tLine.InitElem;
begin
InitElem:=New(pElLine, Init);{создание нового элемента строки}
end;
procedure tLine.DispElem(PointDel:Pointer);
begin
Dispose(pElLine(PointDel)); {удаление элемента строки}
end;
procedure tLine.GetPointElLineAndNomInEl(Nom: Word;
var PointElLine: PElLine;
var NomInEl: Byte; NewLine: Boolean);
begin
PointElLine := GetFirstElem; {первый элемент строки}
while (Nom > Len) do {если номер символа больше размера строки...}
begin
if NewLine and (PointElLine^.GetNextElem=nil) then {если нет следующего элемента, а его следует создать...}
NewEl(PointElLine, nil);{создание нового элемента}
if PointElLine <>nil then {если нет следующего элемента...}
PointElLine := PointElLine^.GetNextElem;
{указатель на следующий элемент}
Nom:= Nom-Len {уменьшение порядкового номера символа на размер элемента строки}
end;
if NewLine and (PointElLine=nil) then {если нет следующего элемента, а его следует создать...}
NewEl(GetLastElem, nil);{создание нового элемента}
if PointElLine <>nil then {если есть элемент строки...}
NomInEl := Nom {получение номера}
else
NomInEl :=0 {иначе номер равен нулю}
end;
procedure tLine.PutSymb(Nom: Word);
var PointElLine: pElLine;
OldSym: Char;
NomInEl: Byte;
NewPointElLine: pElLine;
begin
GetPointElLineAndNomInEl(Nom,PointElLine,NomInEl,True);
{получение указателя на элемент строки и номера позиции символа}
PointElLine^.PutSymb(Ch,NomInEl,OldSym);
{размещение символа в элементе строки}
while (OldSym<> ' ') or (PointElLine^.GetNextElem<>nil)
do {пока последний символ не пробел или есть следующий элемент строки...}
begin
if PointElLine^.GetNextElem=nil then
{если нет следующего элемента строки...}
NewEl(PointElLine,nil); {создать его}
PointElLine:=PointElLine^.GetNextElem;{следующий элемент}
PointElLine^.PutSymb(OldSym, 1, OldSym)
{последний символ в первую позицию}
end;
end;
function tLine.GetSymb(Nom:Word):Char;
var PointElLine:pElLine;
NomInEl:Byte;
begin
GetPointElLineAndNomInEl(Nom,PointElLine,NomInEl,False);
{получение указателя на элемент строки и номера позиции символа}
if PointElLine<>nil then {если есть символ}
GetSymb:=PointElLine^.GetSymb(NomInEl)
else
GetSymb:=' '{иначе пробел}
end;
procedure tLine.LastNotBlank(var PointElLine:PElLine;
var NomAbs:Word; var NomInEl:byte);
var Point:pElLine;
TekNom:Word;
i:Byte;
begin
Point:=GetFirstElem;{указатель на первый элемент строки}
NomAbs:=0;
TekNom:=0;
repeat
for i:=1 to Len do
begin
Inc(TekNom);
if Point^.GetSymb(i)<> ' ' then
NomAbs:=TekNom {последний символ - непробел}
end;
Point:=Point^.GetNextElem
until Point=nil;{пока есть очередной элемент}
GetPointElLineAndNomInEl(NomAbs,PointElLine,NomInEl,False);
end;
{* * Подпрограммы tText * *}
constructor tText.Init;
begin
NewEl(nil, nil); {задание связей первой строки}
Xabs := 1; {абсолютные координаты}
Yabs := 1; {курсора}
SmX := 0; {смещение начала экрана}
SmY := 0;
CurrentPointLine:=GetFirstElem; {текущий указатель}
OnlyLine :=False; {признаки вывода на экран}
FullEkran :=False;
New(Symbol, Init); {объект - размещение символа}
New(Up, Init); {объект - курсор вверх}
New(Dn, Init); {объект - курсор вниз}
New(Left, Init); {объект - курсор влево}
New(Right, Init); {объект - курсор вправо}
New(Enter, Init); {объект - обработка Enter}
New(Backspace, Init); {объект - обработка Backspace}
end;
destructor tText.Done;
var P1, P2: pLine;
begin
P1 := GetFirstElem; {указатель на первую строку}
while P1 <> nil do
begin
P2 := P1^.GetNextElem; {следующая строка}
Dispose(P1,Done); {удаление строки}
P1 := P2
end;
Dispose(Symbol); {удаление объекта - размещение символа}
Dispose(Up); {удаление объекта - курсор вверх}
Dispose(Dn); {удаление объекта - курсор вниз}
Dispose(Left); {удаление объекта - курсор влево}
Dispose(Right); {удаление объекта - курсор вправо}
Dispose(Enter); {удаление объекта - обработка Enter}
Dispose(BackSpace); {удаление объекта - обработка Backspace}
end;
function tText.InitElem: Pointer;
begin
InitElem := New(pLine,Init)
end;
procedure tText.DispElem(PointDel: Pointer);
begin
Dispose(pLine(PointDel) ,Done)
end;
procedure tText.PutX(X: Word);
begin
if X <> 0 then
begin
Xabs := X;
if SmX >= Xabs then
begin
SmX := Xabs - 1;
FullEkran := True
end
else if SmX + 80 < Xabs then
begin
SmX := Xabs - 80;
FullEkran := True
end
end
end;
procedure tText.PutY(Y: Word);
var P: pLine;
begin
if Y <> 0 then
begin
P := GetPointLine(Y);
if P <>nil then
begin
Yabs := Y;
if SmY >= Yabs then
begin
SmY :=Yabs-1;
FullEkran := True
end
else if SmY + 25 < Yabs then
begin
SmY := Yabs - 25;
FullEkran := True
end;
CurrentPointLine :=P
end
end
end;
procedure tText.IncX;
begin
Inc(Xabs);
if SmX + 80 < Xabs then
begin
SmX := Xabs - 80;
FullEkran:= True
end
end;
procedure tText.DecX;
begin
if Xabs > 1 then
begin
Dec(Xabs);
if SmX >= Xabs then
begin
SmX := Xabs - 1;
FullEkran:= True
end
end
end;
procedure tText.IncY;
begin
if CurrentPointLine^.NextElem<>nil then
begin
Inc(Yabs);
if SmY + 25 < Yabs then
begin
SmY := Yabs - 25;
FullEkran := True
end;
CurrentPointLine :=CurrentPointLine^.NextElem
end
end;
procedure tText.DecY;
begin
if Yabs > 1 then
begin
Dec(Yabs);
if SmY >= Yabs then
begin
SmY := Yabs - 1;
FullEkran :=True
end;
CurrentPointLine :=CurrentPointLine^. PredElem
end
end;
function tText.GetX: Word;
begin
GetX := Xabs
end;
function tText.GetY: Word;
begin
GetY := Yabs
end;
function tText.GetPointLine(Y: Word): pLine;
var PointLine: pLine;
i: Word;
begin
PointLine :=GetFirstElem; {указатель на первую строку}
for i := 2 to Y do
if PointLine <>nil then {если есть текущая строка...}
PointLine :=PointLine^.GetNextElem;{взять следующую строку}
GetPointLine := PointLine
end;
procedure tText.PutSymb;
begin
CurrentPointLine^.PutSymb(Xabs)
end;
function tText.GetSymb:Char;
begin
GetSymb := CurrentPointLine^.GetSymb(Xabs)
end;
procedure tText.PutEkran;
var PointLine: pLine;
i, j : Byte;
XRez, YRez: Word;
XSmRez, YSmRez: Word;
begin
XRez := Xabs; YRez:=Yabs;
XSmRez:=SmX; YSmRez:=SmY;
if FullEkran then {если выводить весь экран...}
begin
PutY(SmY + 1);
for i:=1 to 25 do
begin
PutX(SmX +1);
if CurrentPointLine <>nil then {есть очередная строка}
begin
for j:=1 to 80 do
begin
S[i, j, 1] := GetSymb;
IncX
end;
CurrentPointLine:= CurrentPointLine^.NextElem
end
else {нет строки - поместить пробелы}
for j := i to 80 do
begin
S[i, j, 1] := ' ';
IncX
end;
SmX := XSmRez;
end;
FullEkran :=False;{сбросить признак вывода}
SmY := YSmRez;
PutX(XRez);
PutY(YRez)
end
else if OnlyLine then{если выводить одну строку}
begin
PutX(SmX +1);
for j := 1 to 80 do
begin
S[Yabs - SmY, j, 1] := GetSymb;
IncX
end;
OnlyLine := False;
SmX :=XSmRez;
PutX(XRez)
end
end;
procedure tText.PutCursor;
begin
GotoXY(Xabs - SmX, Yabs - SmY);
end;
{** Подпрограммы tOperatin **}
constructor tOperation.Init;
begin {фиктивная подпрограмма}
end;
procedure tOperation.Ins;
begin
end;
procedure tOperation.PutNewSymb;
begin
Ins;
with PointText^ do
begin
PutEkran;
PutCursor
end
end;
{* * Подпрограммы tInsertSymbol * *}
constructor tInsertSymbol.Init;
begin {фиктивная подпрограмма}
end;
procedure tInsertSymbol.Ins;
var PointLine: pLine;
begin
with PointText^ do
begin
PutSymb; {размещение символа}
IncX; {сдвиг курсора вправо}
if not FullEkran then {если выводится не весь экран...}
OnlyLine := True {выводится одна строка}
end
end;
{* * Подпрограммы перемещения курсора * *}
constructor tInsertUp.Init;
begin {фиктивная подпрограмма}
end;
procedure tInsertUp.Ins;
begin
with PointText^ do
DecY
end;
constructor tInsertDn.Init;
begin
end; {фиктивная подпрограммa }
procedure tInsertDn.Ins;
begin
with PointText^ do
IncY
end;
constructor tInsertLeft.Init;
begin
end; {фиктивная подпрограммa}
procedure tInsertLeft.Ins;
begin
with PointText^ do
DecX
end;
constructor tInsertRight.Init;
begin
end; {фиктивная подпрограмма}
procedure tInsertRight. Ins;
begin
with PointText^ do
IncX
end;
{** Подпрограммы tInsertEnter **}
constructor tInsertEnter.Init;
begin
end; {фиктивная подпрограмма}
procedure tInsertEnter.Ins;
var PointElLine: pElLine;
NomAbs: Word;
NomInEl: Byte;
NewPoint: pLine;
Point: pElLine;
PointOldElLine: pelLine;
begin
with PointText^ do
begin
CurrentPointLine^.LastNotBlank(PointElLine, NomAbs, NomInEl);
{координаты последнего символа строки, не являющегося пробелом}
CurrentPointLine^.GetPointElLineAndNomInEl(GetX,
PointElLine, NomInEl, False);{внутренние координаты курсора}
if GetX = 1 then {если начало строки...}
begin
NewEl(CurrentPointLine^.GetPredElem, CurrentPointLine);
{новая строка перед текущей}
CurrentPointLine := CurrentPointLine^.GetPredElem
end
else {иначе...}
begin
NewEl(CurrentPointLine,CurrentPointLine^.GetNextElem);{новая строка после текущей}
if (NomInEl <>0) and (GetX <= NomAbs) then
{если символ существует и не является заключительным пробелом...}
begin
NewPoint := CurrentPointLine^.GetNextElem;
{следующая строка}
NewPoint^.PutLastElem(CurrentPointLine^. GetLastElem);
{указатель на последний элемент -из предыдущей строки}
if NomInEl = 1 then
{если начало элемента строки...}
begin
Dispose(NewPoint^.FirstElem);
{удаление строки из нового объекта}
CurrentPointLine^.PutConnection(
PointElLine^.GetPredElem, nil);
{удаление остатка предыдущей строки}
NewPoint^.PutConnection(nil, PointElLine)
{помещение остатка предыдущей строки в следующую строку}
end
else {иначе...}
begin
Point := NewPoint^.GetFirstElem;
{первый элемент новой строки}
PointOldElLine :=
PointElLine^.GetNextElem;
{удаляемая часть текущей строки}
CurrentPointLine^.PutConnection( PointElLine, nil);
{оформление конца текущей строки}
NewPoint^.PutConnection(Point, PointOldElLine);
{добавление остатка текущей строки к новой строке}
Point^.PutString(
PointElLine^.GetString(NomInEl), 1); {добавление конца последнего элемента в конец первого новой строки}
PointElLine^. PutString(StringOfBlanks, NomInEl);
{пробелы в конец последнего элемента}
while Point^.GetNextElem <> nil do
{пока есть следующий элемент }
begin PointOldElLine:=Point^.GetNextElem;
{следующий элемент}
Point^.PutString(PointOldElLine^.GetString(1),
Len - NomInEl +2);
{начало следующего элемента - в конец предыдущего}
Point := PointOldElLine;
{следующий элемент}
Point^.PutString(
Point^.GetString(NomInEl), 1);
{конец элемента - в начало}
end;
Point^.PutString(StringOfBlanks, Len - NomInEl + 2);
{пробелы в конец последнего элемента}
end
end
end;
PutX(1);
IncY; {новые координаты}
FullEkran:=True{обновить весь экран}
end
end;
{** Подпрограммы tInsertBackSpace **}
constructor tInsertBackSpace.Init;
begin
end; {фиктивная подпрограмма}
procedure tInsertBackSpace.Ins;
var PointElLine:pElLine;
PointNextElLine:pElLine;
NomInEl: Byte;
NewPoint,OldPoint: pLine;
NomAbs: Word;
Point,Point1: pElLine;
Ch: Char;
begin
with PointText^ do
if (GetX <> 1) or (GetY <> 1) then
{если не начало текста...}
begin
CurrentPointLine^.GetPointElLineAndNomInEl(GetX,
PointElLine, NomInEl, False);
{внутренние координаты курсора}
if NomInEl = 0 then {если нет символа... }
DecX {сдвиг курсора влево}
else
if GetX <> 1 then {если не начало строки...}
begin
if NomInEl = 1 then {если начало элемента...}
begin
PointElLine :=
PointElLine^.GetPredElem;
{указатель на предыдущий элемент}
NomInEl := Len + 1
{корректировка номера элемента в строке}
end;
PointElLine^.PutString(PointElLine^.
GetString(NomInEl), NomInEl - 1);
{удаление текущего символа}
PointNextElLine := PointElLine^.GetNextElem;
{следующий элемент строки}
while PointNextElLine <>nil do
{пока есть следующий элемент...}
begin
PointElLine^.PutSymb(PointNextElLine^.GetSymb(1), Len, Ch); {первый символ следующего элемента в конец предыдущего}
PointElLine := PointNextElLine;
{следующий элемент строки}
PointNextElLine := PointNextElLine^.GetNextElem;
{следующий элемент строки}
PointElLine^.PutString(PointElLine^. GetString(2), 1);
{сдвиг новой строки на символ влево}
end;
PointElLine^.PutSymb(' ', Len, Ch);
{пробел в последнюю позицию последнего элемента}
DecX; {задание новых координат}
if not FullEkran then
{если не выводить весь экран...}
OnlyLine := True
{то выводить текущую строку}
end
else {начало строки - объединение строк}
begin
NewPoint := CurrentPointLine^.GetPredElem;
{предыдущая строка}
OldPoint := CurrentPointLine^.GetNextElem;
{последующая строка}
PointNextElLine:= PointElLine;
{последующий элемент строки}
NewPoint^.LastNotBlank(PointElLine, NomAbs, NomInEl);
{последний символ предыдущей строки, не являющийся пробелом }
NewPoint^.PutLastElem(CurrentPointLine^. GetLastElem);
{конец предыдущей строки - конец текущей строки}
PutConnection(NewPoint, OldPoint);
{связь предыдущей строки с последующей минуя текущую}
Point := PointElLine^.GetNextElem;
{следующий элемент текущей строки }
while Point <> nil do {пока есть следующий элемент...}
begin
Point :=Point^.GetNextElem;
{следующий элемент }
Dispose(Point); {удаление элемента}
Point := Point1{следующий элемент}
end;
PutConnection(PointElLine,PointNextElLine);
{связь элементов предыдущей строки с элементами текущей}
Dispose(CurrentPointLine);
{удаление текущей строки}
if NomInEl <> Len then
{если присоединение не к концу предыдущего элемента...}
while PointElLine^.GetNextElem <> nil do
{пока есть следующий элемент...}
begin
PointNextElLine :=PointElLine^.GetNextElem;
PointElLine^.PutString(
PointNextElLine^.GetString(1),
NomInEl + 1); {начало следующего элемента - в конец текущего элемента}
PointNextElLine^.PutString(
PointNextElLine^.GetString(Len -NomInEl+1), 1);
{конец следующей строки - в ее начало}
PointElLine := PointNextElLine
{следующий элемент }
end;
PointElLine^.PutString(StringOfBlanks,
NomInEl + 1);
{пробелы в конец последнего элемента}
PutX(NomAbs + 1);
PutY(GetY - 1);
FullEkran:= True
end
end
end;
{* * Секция инициализации * *}
var i: Byte;
begin
for i := 1 to Len do
StringOfBlanks[i] :=' ';
StringOfBlanks[0]:= Chr(Len);
New(PointText, Init); {создание объекта}
end.
2. Задания для самостоятельной работы:
1. Привести рассмотренную программу к рабочему виду.
2. В основной программе изменить цвет фона и цвет выводимых символов.
3. Написать подробный отчет о проделанной работе.
3. Контрольные вопросы:
1. Что означает ООП?
2. Что такое объект? Каков формат объекта?
3. Что можно отнести к свойствам ООП? Кратко охарактеризуйте
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.