(*~\Глагол\Отделы\Поле\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                             ОТДЕЛ Поле;
(*============================================================================*
 * НАЗНАЧЕНИЕ: на поле располагаются наделы ввода/вывода текстовых данных
 * Поле следит за передачей посылок от клавиатуры и мышки к выбранному наделу.
 *============================================================================*)

ИСПОЛЬЗУЕТ 
  Рамка,
  Надел,
        (*  \Глагол\               *)
  Окно    ИЗ "..\..\Отделы\Обмен\",
  Ввод    ИЗ "..\..\Отделы\Обмен\";

ПОСТ                                     (* встроенные состояния поля (<= 0): *)
  состРабота-   =  0;
  состДалее-    = -1;
  состОтмена-   = -2;

ВИД
  Доступ- = ДОСТУП К Вид;                      (* Поле.Доступ <- Рамка.Доступ *)

  Задача = ЗАДАЧА(поле:Поле.Доступ; посылка+:Ввод.нПосылка);

                     Вид- =                    (* Поле.Вид    <- Рамка.Вид    *)
  НАБОР (Рамка.Вид)
    наделыД        :Надел.Доступ;  (* связка наделов поля - доступ к цепному списку *)
    выбранныйНаделД:Надел.Доступ;  (* надел, выбранный человеком - доступ к звену списка *)

    Приём          :Задача;        (* оставшийся ввод и управление  *)

    состояние+     :ЦЕЛ;           (* м.б. как выше, так и др.      *)
  КОН;
                                   (* наборы-посылки к наделам, т.е. расширения Ввод.нПосылка *)
  нОтрисовка- = НАБОР (Ввод.нПосылка)
                КОН;
  нБуквица-   = НАБОР (Ввод.нПосылка)
                  буквица+:ЦЕЛ
                КОН;


(*-оооооооооооооо- опережающие определения/заготовки задач -ооооооооооооооооо-*)


(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА^                                                           (*(Поле.Вид)*)
        ПереместитьВвод(полеД:Поле.Доступ;
                       дальше:КЛЮЧ);


(*=рррррррррррррррррррррррр= реализация задач =рррррррррррррррррррррррррррррр=*)


(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                            (*(Поле.Вид)*)
       Рисовать-(полеД:Поле.Доступ);
(*
 * Перерисовывает все наделы поля
 *)
ПЕР
        наделД,
  первыйНаделД :Надел.Доступ;
      отрисовка: Поле.нОтрисовка;
УКАЗ
                             (* убираем указку *)
  Окно.РазмерУказки(0);
                             (* при необходимости наделы сами нарисуют указку *)
          первыйНаделД:=полеД.наделыД;
  наделД:=первыйНаделД;
  ПОВТОРЯТЬ
    Рамка.Выставить(наделД,полеД);
                    наделД.Приём(наделД,отрисовка);
     наделД:=наделД.слеД
  ДО наделД = первыйНаделД
КОН Рисовать;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                            (*(Поле.Вид)*)
       ОкноНаВсёПоле-(полеД:Поле.Доступ);
(*
 * Выравнивает окно по границе поля
 *)
УКАЗ
  Окно.ИзменитьРазмер(полеД.нс+1,полеД.пк+1)
КОН ОкноНаВсёПоле;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                            (*(Поле.Вид)*)
       СостояниеНадела-(наделД:Надел.Доступ; состояние:ЦЕЛ);
(*
 * изменить состояние  <наделД>
 *)
ПЕР
  отрисовка:Поле.нОтрисовка;
      полеД:Поле.Доступ;
УКАЗ
  ЕСЛИ
       (наделД = ПУСТО)
      ИЛИ
       (наделД.состояние = состояние)
  ТО
    ВОЗВРАТ
  КОН;
                                                             (* преобразование
                полеД              из Рамка.Доступ в
                      Поле.Доступ  <- Рамка.Доступ            *)
  полеД:=наделД.полеД(Поле.Доступ);

  ВЫБРАТЬ
          состояние
  ИЗ
  | Надел.состОбычный:
      ЕСЛИ 
           наделД.состояние = Надел.состВыбран
      ТО                                      (* уберём указку *)
        Окно.РазмерУказки(0)
      КОН
  | Надел.состВыбран:
      ЕСЛИ
           (наделД.состояние # Надел.состОтключён)
          И
           (Надел.признакВыбираемый В наделД.признаки)
          И 
           (наделД # полеД.выбранныйНаделД)
      ТО                                     (*  р е к у р с и в н ы й  вызов *)
        Поле.СостояниеНадела(полеД.выбранныйНаделД,
                             Надел.состОбычный
                            );
        полеД.выбранныйНаделД:=наделД
      ИНАЧЕ
        ВОЗВРАТ
      КОН
  | Надел.состОтключён:
      ЕСЛИ
           наделД = полеД.выбранныйНаделД
      ТО
        ПереместитьВвод(полеД,ВКЛ)
      КОН
  ИНАЧЕ
  КОН;
  наделД.состояние:=состояние;
  наделД.Приём(наделД,отрисовка)
КОН СостояниеНадела;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА                                                            (*(Поле.Вид)*)
       ПереместитьВвод(полеД:Поле.Доступ;
                      дальше:КЛЮЧ);
ПЕР
        наделД,
  первыйНаделД :Надел.Доступ;
УКАЗ
                первыйНаделД:=полеД.выбранныйНаделД;
        наделД:=первыйНаделД;
  ПОВТОРЯТЬ
    ЕСЛИ
         дальше
    ТО
      наделД:=наделД.слеД
    ИНАЧЕ
      наделД:=наделД.преД
    КОН;
    ЕСЛИ 
         (Надел.признакВыбираемый В наделД.признаки)
        И
         (наделД.состояние # Надел.состОтключён)
    ТО
      Поле.СостояниеНадела(наделД,Надел.состВыбран);
      ВОЗВРАТ
    КОН
  ДО наделД = первыйНаделД
КОН ПереместитьВвод;
 
(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                            (*(Поле.Вид)*)
       Проверить-(полеД:Поле.Доступ);
ПЕР
           наделД,
  выбранныйНаделД,
     первыйНаделД :Надел.Доступ;

  родп:ЦЕЛ; (* род посылки *)
                             (* посылки *)
  отКлавиш:Ввод.нОтКлавиш;
   отМышки:Ввод.нОтМышки;
   буквица:Поле.нБуквица;

УКАЗ
  родп:=Окно.Опрос(отКлавиш,отМышки);
  выбранныйНаделД:=полеД.выбранныйНаделД;

(*.жжжжжжжжжжжжжжжжжжжжж.*)
  ЕСЛИ
       родп = Ввод.клавиши
  ТО                                          (* пришла посылка от клавиатуры *)
(*..........................сначало её обрабатывает <наделД> с текущим вводом *)
    ЕСЛИ
         выбранныйНаделД # ПУСТО
    ТО 
         выбранныйНаделД.Приём(выбранныйНаделД,отКлавиш);
      ЕСЛИ
           отКлавиш.код = 0
      ТО
        ВОЗВРАТ
      КОН
    КОН;
(*.....................................остаток обрабатывает пользователь поля *)
    полеД.Приём(полеД,отКлавиш);
    ЕСЛИ
         отКлавиш.код = 0
    ТО
      ВОЗВРАТ
    КОН;
(*.................................................опрашиваем буквицы наделов *)
    буквица.буквица:=отКлавиш.код;

            первыйНаделД:=полеД.наделыД;
    наделД:=первыйНаделД;
    КОЛЬЦО
      ЕСЛИ
             НЕ (Надел.признакГлухой В наделД.признаки)
           И
             (наделД.состояние # Надел.состОтключён)
      ТО
           наделД.Приём(наделД,буквица);
        ЕСЛИ
             буквица.буквица = 0
        ТО                                                 (* надел отозвался *)
          Поле.СостояниеНадела(наделД,Надел.состВыбран);
          ВОЗВРАТ
        КОН
      КОН;
           наделД:=наделД.слеД;
      ЕСЛИ
           наделД = первыйНаделД
      ТО
        ВЫХОД
      КОН
    КОН;
(*............................................под конец проверяем смену ввода *)
    ЕСЛИ
         выбранныйНаделД # ПУСТО
    ТО
      ЕСЛИ
           отКлавиш.код = 9
      ТО                                                            (* по Tab *)
        ПереместитьВвод(полеД,НЕ отКлавиш.упрШифт)
      АЕСЛИ
           НЕ (отКлавиш.упрШифт ИЛИ отКлавиш.упрКонтр) 
      ТО
        ВЫБРАТЬ отКлавиш.код ИЗ                                (* по стрелкам *)
(* <- ^ *) | 25H,26H: ПереместитьВвод(полеД,ОТКЛ)
(* -> V *) | 27H,28H: ПереместитьВвод(полеД,ВКЛ)
        ИНАЧЕ
        КОН
      КОН
    КОН

(*.жжжжжжжжжжжжжжжжжжжжж.*)
  АЕСЛИ
        родп = Ввод.мышка
  ТО                                               (* пришла посылка от мышки *)
    ЕСЛИ
         Ввод.прокрут В отМышки.события
    ТО                                                      (* прокрут колеса *)
      ЕСЛИ
           выбранныйНаделД # ПУСТО
      ТО 
        выбранныйНаделД.Приём(выбранныйНаделД,отМышки)
      КОН
    ИНАЧЕ                                      (* нажатие и отпускание кнопки *)
      ЕСЛИ
           (отМышки.к < полеД.лк)
          ИЛИ
           (отМышки.к > полеД.пк)
          ИЛИ
           (отМышки.с < полеД.вс)
          ИЛИ
           (отМышки.с > полеД.нс)
      ТО                                                         (* мимо поля *)
        ВОЗВРАТ
      КОН;
                                     (*-- ищем надел в который попала мышка --*)
      ЕСЛИ
           выбранныйНаделД # ПУСТО
      ТО                               (* скорее всего она попала в выбранный *)
        первыйНаделД:=выбранныйНаделД
      ИНАЧЕ
        первыйНаделД:=полеД.наделыД
      КОН;
             наделД:=первыйНаделД;
      КОЛЬЦО
        ЕСЛИ
             НЕ (Надел.признакГлухой В наделД.признаки)
           И
            (наделД.состояние # Надел.состОтключён)
           И
            (отМышки.к >= наделД.лк) И (отМышки.к <= наделД.пк)
           И
            (отМышки.с >= наделД.вс) И (отМышки.с <= наделД.нс)
        ТО                                                        (* попалась *)
          ЕСЛИ
               выбранныйНаделД # ПУСТО
          ТО
            Поле.СостояниеНадела(наделД,Надел.состВыбран)
          КОН;
                                         (* преобразуем к местным координатам *)
          УМЕНЬШИТЬ(отМышки.к,наделД.лк);
          УМЕНЬШИТЬ(отМышки.с,наделД.вс);
          ЕСЛИ 
               (отМышки.события = {})
              И
               (отМышки.кнопки = {})
          ТО                                               (* отпущена кнопка *)
            наделД.Приём(наделД,отМышки)
          КОН;
          ВЫХОД                      (* поиск прекратить *)
        КОН;
             наделД:=наделД.слеД;
        ЕСЛИ
             наделД = первыйНаделД
        ТО
          ВЫХОД
        КОН
      КОН
    КОН;
    ЕСЛИ
         НЕ отМышки.отработана
    ТО                        (* что осталось, обрабатывает пользователь поля *)
      полеД.Приём(полеД,отМышки)
    КОН

(*.жжжжжжжжжжжжжжжжжжжжж.*)
  АЕСЛИ
        родп = Ввод.закрыт
  ТО
      полеД.состояние:=Поле.состОтмена
  КОН
КОН Проверить;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                            (*(Поле.Вид)*)
       ДобавитьНадел-( полеД: Поле.Доступ;
                      наделД:Надел.Доступ);
(*
 * Добавляет <надел> в <полеД>
 *)
УКАЗ
                                                 (* добавляем в связку *)
  Надел.ДобавитьВКонец(полеД.наделыД,наделД);
                                                 (* обратная связь для надела *)
        наделД.полеД:=полеД; 
                                  (* поиск первого возможного надела с вводом *)
  ЕСЛИ
       (полеД.выбранныйНаделД = ПУСТО)
      И 
       (наделД.состояние # Надел.состОтключён)
      И
       (Надел.признакВыбираемый В наделД.признаки)
  ТО
                           наделД.состояние:=Надел.состВыбран;
    полеД.выбранныйНаделД:=наделД
  КОН;
КОН ДобавитьНадел;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА                                                            (*(Поле.Вид)*)
       Создать-(верх, лево,
                строк,колонок:ЦЕЛ;
                   окружениеД:Поле.Доступ;
                     середина:КЛЮЧ;
                        Приём:Поле.Задача):Поле.Доступ;
ПЕР
  полеД:Доступ; 
УКАЗ
  СОЗДАТЬ(полеД);
  ЕСЛИ
            окружениеД = ПУСТО
  ТО                                   (* окружением является всё окно экрана *)
    СОЗДАТЬ(окружениеД);
    Рамка.Подготовить(окружениеД,0,0,строк,колонок)
  КОН;
  ЕСЛИ середина ТО
                                        (* помещаем поле в середину окружения *)
    верх:=(окружениеД.нс - окружениеД.вс - строк+1) ДЕЛИТЬ 2;
    лево:=(окружениеД.пк - окружениеД.лк - колонок+1) ДЕЛИТЬ 2
  КОН;
  Рамка.Подготовить(полеД,верх,лево,строк,колонок);
  Рамка.Выставить(полеД,окружениеД);
                  полеД.Приём:=Приём;
          ВОЗВРАТ полеД
КОН Создать;

КОН Поле.
