************
* PROGRAM....:  BEST
* FILE.......:  View.Prg
* PURPOSE....:  Утилита просмотра,редактирования и печати текстовых файлов
*               неограниченного размера
******

// Copyright (c) 1993-2005 "Компания БЭСТ". Все права сохраняются.

#include "fileio.ch"
#include "inkey.ch"
#include "s_public.ch"
#include "s_refer.ch"
#include "my.ch"

#DEFINE COL_BROWS1  IF(INST_COLOR,'w/b,n/w,,,w/b','w/n,n/w,,,w/n')

#define CR   chr(13)
#define LF   chr(10)
#define CRLF CR + LF

#define COL_VIEW     IF(INST_COLOR,'w/b,w+/b','w/n,w+/n')
#define COL_MAIN     IF(INST_COLOR,'w/b,w+/b,w/n,w+/n','w/n,w+/n,n/w,n+/w')
#define COL_SELECTED IF(INST_COLOR,'w/b,w+/n,w/n,w+/n','w/n,n+/w,n/w,n+/w')
#define COL_VBORDER  IF(INST_COLOR,'bg+/b,w+/n','w+/w,w+/n')
#define COL_VMSG     IF(INST_COLOR,'gr+/b','w+/n')
#define COL_ALERT_ERR  IF(INST_COLOR,"GR+/R,W+/B,,,W/R",'w+/n,n+/w,,,w/n')
#define COL_HELP1  IF(INST_COLOR,"N/BG,W+/N",'w+/n,n+/w')
#define COL_HEAD  IF(INST_COLOR,"N/W",'w+/n')
#define COL_EDIT  IF(INST_COLOR,"GR+/N,w+/n",'w+/n,w+/n')
#define COL_FIND  IF(INST_COLOR,"W+/BG,GR+/N","n/w,w+/n")
#DEFINE COL_SHEADR   IF(INST_COLOR,'gr+/b*,w+/n,,,w+/b*','n/w,w+/n,,,n/w')

//Текущая позиция в файле
#define FTELL(handle)  fseek(handle, 0, FS_RELATIVE)

#define MAX_LINE_LEN nMaxLineLen    // Максимальная шиpина пpосмотpа

#ifndef __HARBOUR__
#define MAX_EDIT  20                // Максимальная длина файла, кб для полного редактирования
#else
#define MAX_EDIT  200               // Максимальная длина файла, кб для полного редактирования
#endif

#DEFINE PRN_STR(cStr) IF( nBegPoz > 1, '~', '' )+SUBSTR(cStr,nBegPoz+IF(nBegPoz > 1, 1, 0 ),nLen)
#DEFINE IS_SPEC(x)    (("{\" $ x .AND. "\}" $ x).OR. ("{[" $ x .AND. "]}" $ x))





// Statics below are used in any function of this module

STATIC nMaxLineLen := 256
// Изменение 3.60
STATIC PR_PTYPE
STATIC PR_TYPE,PR_WIDTH,PR_PAPER,PR_STR,PR_PROBROS,PR_PAUSE,PR_DEVICE,;
       PR_PSEVDO, PR_E_YES,PR_E_PATH,PR_E_FILE, PR_WTYPE, PR_HEAD, ;
       PR_NUMSTR, PR_BEGSTR,PR_LCODE, PR_BCODE, PR_ECODE, PR_LSUM,;
       PR_WIN, PR_ORINT, PR_OTSTUP  // Изменение
STATIC PR_TDEVICE,PR_TVIEW,PR_TNAST,PR_TFILE,PR_TERROR,PR_TCOPY,PR_TWIN,PR_TEDIT
STATIC PR_HEAD_LINE := 0

STATIC PR_KOL:=1,lOkPrint:=.T.
STATIC PR_DBL_SPACE :=.F. ,;
          PR_OFFSET :=0
STATIC PR_PRECODE:="",TMP_CODE:='     ',cCpi:='10cpi',cCpi0:=''

STATIC nHandle          // File handle
STATIC cLine            // Current line(without CRLF and padded with blanks
                        // up to MAX_LINE_LEN)
STATIC nLinePos:=1                // cLine position in file
STATIC nLinePos0:=1                // cLine pre-position in file
STATIC nTopPos:=0                // cLine top position in file
STATIC oTbr                       // Главный объект
STATIC nLineNum:=1  // current line number
STATIC nLineNum0:=1
STATIC nRowAct                   // номер активной строки дисплея
STATIC nStart:=0,nEnd:=0          // File positions of selected block
STATIC aWidth     // Массив координат разбиений строки по ширине {{nPos,nLen}}
STATIC lIsSelected:=.F.           // TRUE if there is selected block
STATIC lRunningSelection:=.F.     // TRUE if selection is in progress
STATIC nPropusk := 1              // Пропустить страницу
STATIC lRealCode := .T.           // Выводить рельные коды на принтер

STATIC nY1:=1,nX1:=1,nY2:=22,nX2:=78  // View area (TBrowse itself)
STATIC xz:=0,yz:=0            //Координаты закрепления
STATIC aFixed                 //Массив для верхнего закрепления
STATIC cFindString:=''        //Строка для поиска
STATIC nMaxPos                // The last line file position
STATIC nHorOffset:=1          // Current offset of horizontal scroll
STATIC nHorStep:=10           // Step of horizontal scroll
STATIC nMaxLine:=0, nMaxCol:=0      // the last line and column of the file
STATIC cSaveName0
STATIC lLoad:=.F.
STATIC lSetCode := .T.

STATIC nPage:=1,   ;                 // Текущий номер страницы
       nLine:=0,   ;                 // Текущий номер строки внутри страницы
       lEndOrNoEnd := .F.,;          // Признак возможного завершения таблицы
       aBufferHead := {},;           // Буффер строк для хранения текущего заголовка (разрезанного по ширене листа)
       aBufferFullHead := {},;       // Буффер строк для хранения текущего заголовка (полного)
       lBeg := .F.,;                 // Признак начала чтения заголовка
       lEnd := .F.,;                 // Признак завершения чтения заголовка
       lEofORNoEof := .F.,;          // Признак возможного завершения заголовка
       lPrnBuffer := .F.,;           // Признак распечатки блока текста
       aBufferSum := {},;            // Массив сумм для итогов в конце листа
       lDelSumBuffer := .T.          // Флаг о удалении не нужных элементов из
                                     // массива сумирования
Static xMaxRow := 0
Static xMaxCol := 0
Static xDummy := ''
/** VOID View()
*  PURPOSE: Полноэкранный просмотр файла fname.
*   В процессе просмотра обеспечиваются следущие функции:
*    - выбор блока текста
*    - печать файла или выбранного блока с возможной настройкой принтера
*   Предполагается, что в fname все строки завершаются парой
*   возврат каретки/перевод строки (CR/LF) и максимальная строка не превышает
*   MAX_LINE_LEN=512
*  PARAMS: fname  - file to view
*          [nLines] - кол-во строк (пар CR/LF) в просматриваемом файле
*   если не указан то вместо счетчика строк используется процент продвижения
*          [nCols]  - не указывать (пережитки былых времен ?)
*          [bPrint] - дополнительный блок кода для печати (после основной печати)
                      в него передается nHandle печатаемого файла
*          [aPreCode] - массив открывающих кодов принтера
*          [aPostCode] -массив закрывающих кодов принтера (напр. {"17cpi","8lpi"}
*          [nPR_STR] - длина страницы
*          [aInterCode]-массив кодов,вставляемых внутрь документа,структура эл-та:
*          {nFilePos_n,cCode_n[,nFilPos_k,cCode_k[,cText]]}, например:
*          {{125,'17cpi'},;
*          {135,'10cpi'}}
*          если указано [nFilPos_k,cCode_k,[,cText]], то печать дополнительным пpоходом
*          текста cText, а если cText не указан или пуст то текстом
*          находящимся от nFilePos_n  до nFilePos_k
*          nFilePos-позиция в файле, если считать с 0 и включать CRLF
*          Массив aInterCode может представлять собой массив структуры
*          {aInterCode,......} - если требуется много эл-ов (для отчетов)
*
*          [nPR_KOL] - кол-во копий
*          [bLinePrint] - блок кода выполняемый при печати каждой строки
*          документа, ему передается по ссылке номер страницы и номер строки
*          [lErase] - .T. стирать файл при выходе
*                     .F. не стирать файл при выходе
*          [nCopyEl] - кол-во позиций в 1-ой копии для повтора aInterCode
*          [cHead]  - тип заголовока (по умолчанию из настройки)
*          [lNumStr] - нумерация страниц (по умолчанию из настройки)
*          [cId] - идентификатор для печати
*          [lSumKol] - суммирование колонок (по умолчанию из настройки)
*          [aKolSum] - масив номеров колонок для суммироания
*                      (по умолчанию все числовые колонки шириной более
*                       10 символов кроме  начинающихся на
*                       "НОМ","Н/НОМ","ЦЕНА","КОЛ","КОЭФ")
*          [bNameStr] - блок кода для вывода на печать итого по странице
*                       ему передается массив структуры
*                       {{;
*                         нач.позиция (по полной ширине отчета),;
*                         ширина колонки,;
*                         сумма,;
*                         шаблон для вывода;
*                         },;
*                         ......}
*                       и три параметра :
*                       1. начальная позиция отрезка (если отчет не по
*                          помещается по ширине в принтер)
*                       2. ширина отрезка
*                       3. левый отступ для первого сегмета
*                       если блок возвращает строку (полной длины),
*                       то она используется для вывода,
*                       а ели NIL, то предполагается,
*                       что вывод на принтер осуществлен в блоке кода
*                       (не более 2-х строк текста)
*      lCode - .F., то печать для термопринтеров (по умолчанию .T.)
*              отрабатывают установки с 'T' в начале (например PR_TCOPY,PRN0_TCOPY и т.п.)
*      lOptim - .T. оптимизация прогона листа
**/
FUNCTION View(fname, nLines, nCols,bPrint,aPreCode,;
              aPostCode,nPR_STR, aInterCode,nPR_KOL,bLinePrint,;
              lErase,nCopyEl,cHead,lNumStr,cId,;
              lSumKol,aKolSum,bNameStr,lCode,lOptim,;
              nHeadLine,cVarName ;
              )
  LOCAL oTbc
  LOCAL cViewColor, sScr, sCurs:=SetCursor(0)
  LOCAL i, cI:=''
  LOCAL sF1:=SETKEY(K_F1,NIL), sPR_STR, sPR_PAPER
  LOCAL sArea:=SELECT()
  LOCAL lBlink:=SETBLINK()
  LOCAL lUse1:=.F.,lUse2:=.F.
  LOCAL nWindows:=WSELECT()
  LOCAL aArray:={},aStri

  

  IF VALTYPE(fName)=="A" //и такое бывает :)
     aStri:=ACLONE(fName)
     fName:=TEMPFILE(m->GlobalTmpPath,"txt")
     nHandle:=FCreate(fName)
     AEVAL(aStri,{|x|Str2File(x,nHandle,.T.)})
     FClose(nHandle)
     nHandle:=NIL
  ELSEIF WinView(fName)=0
     RETURN 0
  ENDIF


  cViewColor:=SETCOLOR(COL_VIEW)


  PRIVATE nMassh := 1      // Масштаб печати в долях единицы

  PRIVATE lEndEndPage := .T.    // ставить конец страницы в конце текста
  PRIVATE aParamView :={nLines, nCols,bPrint,aPreCode,;
              aPostCode,nPR_STR, aInterCode,nPR_KOL,bLinePrint,;
              .F.,nCopyEl,cHead,lNumStr,cId,;
              lSumKol,aKolSum,bNameStr,lCode,lOptim,;
              nHeadLine}   // параметры вызова для запоминания

  IF ValType(nHeadLine)=='N'
    PR_HEAD_LINE := nHeadLine
  ENDIF

  WSELECT(0)
  sScr:=SAVESCREEN()

  nY2:=MaxRow()-2

  lSetCode:=IF(ValType(lCode) == "L",lCode,.T.)

  // Изменение 3.18
  IF !EMPTY(aInterCode) .AND. !EMPTY(aInterCode[1])
     IF ValType(aInterCode[1,1])  != 'A'
       aInterCode := {aInterCode}
     ENDIF
  ELSE
    aInterCode := {}
  ENDIF

  nCols := 10
  fName:=STRTRAN(fName,'\\','\')
  Width(0)
  nLine:=0
  nPage:=1
  nPropusk := 1
  IF  !(;
      (Select("RefP")!=0.OR.(lUse1:=NetUse('RefP'   ,'FCPRINT','FCPRINT'))) .AND.;
      (Select("RefC")!=0.OR.(lUse2:=NetUse('RefC','PRN_CODE','prn_code')));
       )
      Error_Use()
      SELECT(sArea)

      #ifdef __HARBOUR__
      ClearTotRepStatic()
      #endif

      RETURN(NIL)
  ENDIF
  SELECT (sArea)
  SETBLINK(.F.)
  IF EMPTY(cSaveName0)
    cSaveName0 := _PATH_REPORT
  ENDIF
  yz:=xz:=0
  nTopPos:=0
  aFixed:={}
  nMaxCol := 23     //IF(nCols==NIL, 256, MAX(nX2-nX1+1, nCols))
  MAX_LINE_LEN :=  nMaxCol
  nMaxLine:=IF(nLines==NIL, 0, nLines)
  PRIVATE GetList:={}


  IF !lLoad.OR.!lSetCode
     // Глобальные паpаметpы печати
     SaveParamPrint()
     VWidth(ROUND(PR_WIDTH/m->nMassh,0))
  ENDIF

IF VALTYPE(cHead)='C'
  PR_HEAD := cHead
ENDIF
IF VALTYPE(lSumKol)='L'
  PR_LSUM := lSumKol
ENDIF
IF VALTYPE(lNumStr)='L'
  PR_NUMSTR := lNumStr
ENDIF
IF VALTYPE(nPR_STR)='N'
   sPR_STR:=PR_STR
   PR_STR:=nPR_STR
ENDIF
IF VALTYPE(nPR_KOL)='N'
   PR_KOL:=nPR_KOL
ENDIF

IF PR_KOL <= 0
  PR_KOL := 1
ENDIF


IF PR_E_YES               // ВНЕШНИЙ РЕДАКТОР
    NewEdit( fname )

#ifndef __HARBOUR__
ELSE
#else
ELSEIF (TYPE("lFromMaker")="L".AND.lFromMaker.AND.!(TYPE("lHardKart")="L".AND.m->lHardKart).AND.;
       lFileInit(fname)).OR.(lFileInit(fname).AND.nMaxPos>0)
#endif



  IF lSetCode .OR. PR_TVIEW
//azat 25-31.08.2005 это попутно, вообще-то с термопринтером воюю
//    ScrTitul(MaxRow(),'F1:Помощь F2:Зап F5:Загол F7:Блок F9,Ctrl-F9:Печ Alt-F9:Наст ┘:Ред.Alt-S:Поиск')

    ScrTitul(MaxRow(),'F2:Зап F5:Загол F7:Блок F9,Ctrl-F9:Печ Alt-F9:Наст ┘:Ред Alt-S:Поиск')

    @ nY1-1,nX1-1 TO nY2+1,nX2+1 COLOR COL_VBORDER
    @ nY1-1,nX1+2 SAY STRTRAN(' '+fname+' ' ,'\\','\') COLOR COL_VMSG
    SAYSCREEN(' Строка:',nY2+1,nX1+2)

    SbAttach(nY1, nX2+1, nY2)
    SETCOLOR(COL_VIEW)
  ENDIF

  #ifndef __HARBOUR__
  IF lFileInit(fname)
  #endif


    IF !lSetCode .AND. !PR_TVIEW
      IF PR_TNAST
        Set_Termo()
      ENDIF
      IF !PR_TNAST.OR.LastKey() != K_ESC
        PrintIt(nHandle, aPreCode,aPostCode,aInterCode,bLinePrint,nCopyEl,cId,aKolSum,bNameStr,,lOptim,@aArray)
      ENDIF
    ELSE
      nLineNum:=1; nHorOffSet:=1
      nLineNum0:=1
      If nMaxLine > 0
        UpdRow(1)
      EndIF

      oTbr:=TBROWSENEW(nY1, nX1, nY2, nX2)
      oTbr:colorspec:=COL_MAIN
      oTbc:= tbColumnNew(, {|| ;
      SUBSTR(cLine, nHorOffSet, nX2-nX1+1)})
      oTbc:colorblock:={|| DispSelected()}
      oTbc:width := nX2-nX1+1
      oTbr:addcolumn(oTbc)
      oTbr:goTopBlock     := {|| GetFirst() }
      oTbr:goBottomBlock  := {|| GetLast() }
      oTbr:skipBlock      := {|n,how| nLineNum+=(how:=skipper(n)), how }
      nRowAct:=nY1
      FSeek(nHandle,0,FS_SET)      // take start position
      xMaxRow := 0
      While lnFReadLn(nHandle,@xDummy,MAX_LINE_LEN,64000)
            xDummy := ''
            xMaxRow++
      end



      FSeek(nHandle,0,FS_SET)
      DispOutAt(nY1-1,nX2-12,Str(xMaxRow,5)+'/'+Str(xMaxCol,5),COL_VBORDER)
#ifndef __PLATFORM__Linux
      ShowTime()
#endif
      ViewBrowse(fname,bPrint,aPreCode,aPostCode,aInterCode,bLinePrint,lErase,nCopyEl,cHead,lNumStr,cId,aKolSum,bNameStr,lSumKol,lOptim,@aArray,cVarName)
#ifndef __PLATFORM__Linux
      ShowTime(1,71,,"n/w")
#endif

    ENDIF

  #ifndef __HARBOUR__
  Else
    SayError('Ошибка открытия файла '+fname)
  ENDIF
  #endif

  SbDetach()
  IF VALTYPE(sPR_STR)='N'
     nPR_STR := PR_STR
     PR_STR := sPR_STR
  ENDIF
  nPR_KOL := IF(lSetCode,PR_KOL,PR_TCOPY)
ENDIF
SetColor(cViewColor)
SetCursor(sCurs)
RESTSCREEN(,,,,sScr)
SETKEY(K_F1,sF1)
IF lUse1
  SELECT RefP
  CLOSE
ENDIF
IF lUse2
  SELECT RefC
  CLOSE
ENDIF
SELECT (sArea)
SETBLINK(lBlink)
oTbr:=NIL
WSELECT(nWindows)
#ifdef __HARBOUR__
ClearTotRepStatic()
#endif

RETURN NIL

STATIC FUNCTION ViewBrowse(fname,bPrint,aPreCode,aPostCode,aInterCode,bLinePrint,lErase,nCopyEl,cHead,lNumStr,cId,aKolSum,bNameStr,lSumKol,lOptim,aArray,cVarName)
PLOCAL nKey, lKey, lExitRequested := .F.
PLOCAL nCurPos, aSet
PLOCAL cHorKeys:=CHR(K_LEFT)+CHR(K_RIGHT)+CHR(K_HOME)+CHR(K_END), ;
      cVerKeys:=CHR(K_UP)+CHR(K_DOWN)+CHR(K_PGUP)+CHR(K_PGDN)+CHR(K_CTRL_PGUP)+CHR(K_CTRL_PGDN)
PLOCAL cSaveName:='',nSaveHandle, xWriteMode:=.F., lSaveIt:=.F.
PLOCAL lUpd:=.F., nDescript
PLOCAL aSetKey:=SaveSetKey()
PLOCAL sRet:=SETKEY(K_RETURN,NIL)
PLOCAL sF1:=SETKEY(K_F1,NIL)
PLOCAL sAF5:=SETKEY(K_ALT_F5,NIL)
PLOCAL sAF7:=SETKEY(K_ALT_F7,NIL)
PLOCAL sAF9:=SETKEY(K_ALT_F9,NIL)
PLOCAL sAP:=SETKEY(K_ALT_P,NIL)
PLOCAL sAF8:=SETKEY(K_ALT_F8,NIL)
PLOCAL sCtrlL:=SETKEY(K_CTRL_L,NIL)
PLOCAL sAltS:=SETKEY(K_ALT_S,NIL)
PLOCAL sCtrlRet:=SETKEY(K_CTRL_RET,NIL)
PLOCAL sLeft:=SETKEY(K_LEFT,NIL)
PLOCAL sRight:=SETKEY(K_RIGHT,NIL)
PLOCAL sUp:=SETKEY(K_UP,NIL)
PLOCAL sDown:=SETKEY(K_DOWN,NIL)
PLOCAL sPgDn:=SETKEY(K_PGDN,NIL)
PLOCAL sPgUp:=SETKEY(K_PGUP,NIL),cc
//PLOCAL sAltX:=SETKEY(K_ALT_X,NIL),cc
PLOCAL bAllPrint := {|cSaveName|;
                   PrintIt(nHandle, aPreCode,aPostCode,aInterCode,bLinePrint,nCopyEl,cId,aKolSum,bNameStr,@cSaveName,lOptim,@aArray),;
                   cSaveName := '',;
                   IF(bPrint!=NIL,(GetFirst(),EVAL(bPrint,nHandle)),NIL),;
                   FSEEK(nHandle, nLinePos:=nCurPos, FS_SET),;
                   oTbr:RefreshAll();
                 }
PLOCAL cName1, cName2, nDesk1 , nDesk2, cCode, nSim, i, aWData


PLOCAL sAltW:=SETKEY(K_ALT_W),bKey //titov 20.09.03



PRIVATE pPrinter






IF(ValType(lErase) = "L",,lErase := .T.)

 DO WHILE !lExitRequested
   nKey:=NextKey()
   WHILE !oTbr:stabilize();ENDDO
   lKey:=LASTKEY()
   nCurPos:=nLinePos
   If lUpd.OR.CHR(lKey) $ cVerKeys
     UpdIndicator(nCurPos/nMaxPos)
     If nMaxLine>1
       UpdRow(nLineNum:=IF(lKey==K_CTRL_PGUP, nLineNum0, ;
                           IF(lKey==K_CTRL_PGDN, nMaxLine, nLineNum)))
       lUpd:=.F.
     EndIF
   EndIF
   If lRunningSelection
     nEnd:=nCurPos
     If lKey==K_PGDN .or. lKey==K_PGUP .or. lKey==K_CTRL_PGUP .or. lKey==K_CTRL_PGDN
       oTbr:RefreshAll()
       Keyboard CHR(127)    // force unused keystroke (K_ctrl_bs)
     EndIF
   EndIF
   nKey:=INKEYTRAP(0)  //- оно уже нормальное == titov
/*********
   While (nKey:=Inkey(.1))==0;EndDo
   If VALTYPE(bKey:=SetKey(nKey)) = "B"
      Eval(bKey, ProcName(1), ProcLine(1), "")
   EndIf
************/
   IF !stdMeth(nKey)
     DO CASE
       CASE nKey == K_F1
         DisplayHelp(1,cVarName)
       CASE nKey==K_ESC .OR. nKey==K_F10  // exit ViewBrowse
         nStart:=nEnd:=0; lRunningSelection:=lIsSelected:=.F.
         FCLOSE(nHandle)
         lExitRequested := .T.
         If Empty(cSaveName)
           IF lErase
             FERASE(fName)
             FERASE(GetXFile(fName))
             FERASE(cVarName)
           ENDIF
         Else
           If !lSaveIt
             COPY FILE (fName) TO (cSaveName)
             cSaveName0:=cSaveName
             If lErase .AND. FILE(cSaveName)
               FERASE(fName)
               FERASE(GetXFile(fName))
               FERASE(cVarName)
             EndIF
           EndIF
         EndIF

       CASE nKey == K_ALT_W.AND.IsWindows()
       ToWindows(GetXFile(fName),cVarName,0) //titov 20.09.03

       CASE (nKey == ASC("W").OR.nKey == ASC("Ц")).AND.IsWindows()
       ToWindows(GetXFile(fName),cVarName,1) //titov 20.09.03


       CASE nKey == K_ALT_F10
          FCLOSE(nHandle)
          aSet := SaveSet()
          NewEdit( fname )
          RestSet(aSet)
          IF !lFileInit(fname)
            SayError('Ошибка открытия файла '+fname)
            EXIT
          ENDIF
          oTbr:refreshAll()
       CASE  nKey == K_SH_F9 // Печать через WINDOWS
         IF TYPE('PRN0_Win_Print')='N' .AND. m->PRN0_Win_Print=0 //3.AND. (IsWindows().OR.SayError('Программа должна быть запущена из-под Windows') )
            SAYERROR('Выполните настройку рабочей станции')
           /* m->nMasSh:=GetMasSh()
            IF LASTKEY()#K_ESC
               IF empty(fileseek(GLOBALTMPP+"BESTREP", 16) )
                  DIRMAKE(LOWER(GLOBALTMPP+"BESTREP"))
               ENDIF
               IF !lSetCode .AND. PR_TDEVICE="ФАЙЛ"
                  cSaveName0 := ALLTRIM(PR_TFILE)
               ENDIF
               cSaveName := TEMPFILE( GLOBALTMPP+"BESTREP\", 'TXT',,.F. )
               lRealCode  := .F.
            //PR_TDEVICE :="ФАЙЛ"
               m->lEndEndPage := .F.
               lSaveIt:=.T.
               EVAL(bAllPrint,cSaveName)
               m->lEndEndPage := .T.
               lRealCode  := .T.
               IF LASTKEY()#K_ESC
                  BS_RUN('UTIL\B4Print.exe '+cSaveName+' '+STR(m->nMasSh*100,4,0))
               ELSE
                  ERASE (cSaveName)
               ENDIF
            ENDIF */
//            SayAndWait('UTIL\B4Print.exe '+cSaveName+' '+STR(m->nMasSh*100,4,0))
         ENDIF

         IF TYPE('PRN0_Win_Print')='N' .AND. m->PRN0_Win_Print=1
            IF empty(fileseek(PRN0_BEST_PRINT+"TMP", 16) )
               SayError('Укажите в настройке путь к программе "Сервер печати"!')
            ELSE

               IF !lSetCode .AND. PR_TDEVICE="ФАЙЛ"
                  cSaveName0 := ALLTRIM(PR_TFILE)
               ENDIF
               cSaveName := TEMPFILE( PRN0_BEST_PRINT+"TMP\", 'TXT',,.F. )
               lRealCode  := .F.
           //PR_TDEVICE :="ФАЙЛ"
               lSaveIt:=.T.
               EVAL(bAllPrint,cSaveName)
               lRealCode  := .T.
               IF NetUse( 'PrintWin', PRN0_BEST_PRINT+'Plateg',,,'SIXCDX') // V@
                  cc:=cSaveName
                  IF "\"$cc
                     cc:=SUBSTR(cc,RAT("\",cc)+1)
                  ENDIF
                  
                  PrintWin->(PutNetAdd({1,401,1,;
                               cc,,STR(m->nMassh*100,3,0)},,.F.),;
                               dbCloseArea() )
               ENDIF
            ENDIF
         ENDIF
         IF TYPE('PRN0_Win_Print')='N' .AND. m->PRN0_Win_Print=2  //Генератор Win-отчетов
            IF empty(fileseek(PRN0_BEST_PRINT+"BESTREP", 16) )
               SayError({'Укажите в настройке путь к файлу обмена',' для программы "Генератор отчетов для WINDOWS"!'})
            ELSE
               SetWPrinter(0,12,25,'pPrinter')
               m->nMasSh:=GetMasSh('Оставить F10','показ инф о принтере')
               SetWPrinter(2,12,25,'pPrinter')
               IF LASTKEY()#K_ESC
                  IF !lSetCode .AND. PR_TDEVICE="ФАЙЛ"
                     cSaveName0 := ALLTRIM(PR_TFILE)
                  ENDIF
                  cSaveName := TEMPFILE( PRN0_BEST_PRINT+"BESTREP\", 'TXT',,.F. )
                  lRealCode  := .F.
              //PR_TDEVICE :="ФАЙЛ"
                  m->lEndEndPage := .F.
                  lSaveIt:=.T.
                  EVAL(bAllPrint,cSaveName)
                  lRealCode  := .T.
                  m->lEndEndPage := .T.
                  IF LASTKEY()#K_ESC
                     aWData:= {;
                               {'ReportType','BEST4'},;
                               {'ReportName','Готовый отчет БЭСТ4'},;
                               {'PrinterCopies',1},;
                               {'BestReportScale',m->nMasSh*100},;
                               {'BestReportFile',SUBSTR(cSaveName,RAT('\',cSaveName)+1)};
                                 }
                     IF !EMPTY(m->pPrinter)
                        AADD(aWData,{'PrinterName',TRIM(m->pPrinter)})
                     ENDIF
                     PutWinPrint(aWData)
                  ELSE
                     ERASE (cSaveName)
                  ENDIF
               ENDIF
            ENDIF
         ENDIF
       CASE nKey == K_F2 .OR. nKey == K_CTRL_F9 // save or print to disk
         IF !lSetCode .AND. PR_TDEVICE="ФАЙЛ"
           cSaveName0 := ALLTRIM(PR_TFILE)
         ENDIF
         cSaveName=GetFileName(cSaveName0)
         If !EMPTY(cSaveName)
           If FILE(cSaveName).AND.FILESIZE(cSaveName)>0  // already exist
             If UPPER(Trim(cSaveName)) != STRTRAN(UPPER(fname),'\\','\')
               xWriteMode:=NoOrYes('   Указанный файл уже существует   ',,;
                 {' Переписать ', ' Дополнить ', ' Отказ '},,, COL_ALERT_ERR)

               If xWriteMode == 0 .Or. xWriteMode == 3
                 cSaveName:=''
               Else
                 If(xWriteMode == 2,, FERASE(cSaveName))
                 IF nKey = K_F2
                   SaveView(@cSaveName, xWriteMode == 2)
                 ELSE
                   EVAL(bAllPrint,@cSaveName)
                 ENDIF
               EndIf
             Else
               lSaveIt:=.T.
             EndIF
           Else
             IF nKey = K_F2
               SaveView( @cSaveName )
             ELSE
               EVAL(bAllPrint,@cSaveName)
             ENDIF
           EndIf
         EndIF
       CASE nKey == K_ALT_P // передать в готовые отчеты
         PRIVATE cNameRep := PADR('Отчет от '+DTOC(DATE())+' '+TIME(),70)
         //IF !lSetCode .AND. PR_TDEVICE="ФАЙЛ"
        //   cSaveName0 := ALLTRIM(PR_TFILE)
        // ENDIF
         cSaveName=GetAltPPar(cSaveName0,@cNameRep)
         If !EMPTY(cSaveName)
           If FILE(cSaveName).AND.FILESIZE(cSaveName)>0  // already exist
             If UPPER(Trim(cSaveName)) != STRTRAN(UPPER(TRIM(fname)),'\\','\')
               xWriteMode:=NoOrYes('   Указанный файл уже существует   ',,;
                 {' Переписать ', ' Дополнить ', ' Отказ '},,, COL_ALERT_ERR)

               If xWriteMode == 0 .Or. xWriteMode == 3
                 cSaveName:=''
               Else
                 If(xWriteMode == 2,, FERASE(cSaveName))
                 lSaveIt:=.T.
                 SaveView( cSaveName,xWriteMode == 2,'без перекод' )
               EndIf
             Else
               lSaveIt:=.T.
             EndIF
           Else
             lSaveIt:=.T.
             SaveView( cSaveName,,'без перекод' )
           EndIf
           PRIVATE lOpenInf_Rep, cFiltInf_Rep
           lOpenInf_Rep := .F.
           IF !EMPTY(cSaveName).AND. (ALIAS())->(IF(SELECT('inf_rep')>0,(cFiltInf_Rep:=dbFILTER(),.T.), (lOpenInf_Rep:=.T.,NetUse('inf_rep',LoadPath()+'REP\Inf_Rep'))))
              INF_REP->(dbSETFILTER({||UPPER(ALLTRIM(INF_REP->File))==UPPER(ALLTRIM(cSaveNAME))},'UPPER(ALLTRIM(INF_REP->File))==UPPER(ALLTRIM(cSaveNAME))'),dbGOTOP())
              IF INF_REP->((EOF().AND. ADDREC()).OR.(!EOF().AND.RecLock()) )
                 INF_REP->Data:=DATE()
                 INF_REP->Time:=TIME()
                 INF_REP->Name_Rep :=cNameRep
                 INF_REP->File:=cSaveName
                 INF_REP->User_Code := _USER_CODE
                 INF_REP->Arm:=GlobalTask
                 INF_REP->ParamView := m->aParamView
                 INF_REP->(dbUnLock())
              ENDIF
              IF lOpenInf_Rep
                 INF_REP->(dbCloseArea())
              ELSEIF !EMPTY(cFiltInf_Rep)
                 INF_REP->(dbSETFILTER(&('{||'+cFiltInf_Rep+'}'),cFiltInf_Rep),dbGOTOP())
              ENDIF
           ENDIF
         EndIF
         //cSaveName:=''

       CASE nKey==K_RETURN
         IF nMaxCol<=250
            Edit(fname)
            oTbr:refreshAll()
         ELSEIF nMaxCol>250
            SayError('Слишком широкий документ!')
         ELSE
            SayError({'Редактирование запрещено',;
                      'из-за наличия привязанных шрифтов!'})
         ENDIF
       CASE nKey == K_F5    //Отметка области закрепления
         SetDispArea()
         oTbr:refreshAll()
         lUpd:=.T.
       CASE nKey=K_ALT_F8  //Обработка для печати этикеток
         IF !EMPTY(cName1 := GetFileName(,,,"Имя файла источника ... ")) .AND. !EMPTY(cName2 := GetFileName(,,,"Имя файла приемника ... "))
           nDesk1 := FOPEN(cName1)
           nDesk2 := FCREATE(cName2)
           IF nDesk1 > 0 .AND. nDesk2 > 0
             fseek(nDesk1, 0, FS_SET) // Встали в начало
             cCode := " "
             nSim := 0
             i := fread( nDesk1,@cCode,1)
             WHILE i = 1
               IF(nSim = 0,FWRITE( nDesk2, "{\"),NIL)
               FWRITE( nDesk2, NTOC(ASC(cCode)))
               i := fread( nDesk1,@cCode,1)
               IF(nSim > 10 .OR. i != 1,( FWRITE( nDesk2, "\}"+CHR(13)+CHR(10)),nSim := 0),(FWRITE( nDesk2,","),nSim++))
             ENDDO
             FClose(nDesk1)
             FClose(nDesk2)
           ENDIF
         ENDIF
       CASE nKey=K_ALT_F5  //Отмена закрепления
         oTbr:nTop=nY1
         nRowAct:=nY1
         nTopPos:=0
         nLineNum:=1
         nLineNum0:=1
         oTbr:goTop()
         aFixed:={}
         yz:=xz:=0
         SetX()
         oTbr:refreshAll()
         lUpd:=.T.
       CASE nKey == K_F7
         If lRunningSelection
           // Finish selection process
           lRunningSelection:=!lRunningSelection // toggle running flag
           lIsSelected:=.T.
           nEnd:=MAX(nCurPos,nStart)
           nStart:=MIN(nStart,nCurPos)
           oTbr:colorspec:=COL_MAIN
         Else
           // Begin selection process
           lIsSelected:=.F.
           nStart:=nEnd:=nCurPos
           oTbr:colorspec:=COL_SELECTED
           lRunningSelection:=!lRunningSelection
         EndIF
       CASE nKey == K_ALT_F7
         // Clear all selection settings and fresh area
         lIsSelected:=lRunningSelection:=.F.
         nStart:=nEnd:=0
         oTbr:colorspec:=COL_MAIN
         oTbr:RefreshAll()

       CASE nKey == K_F9
         IF !lSetCode .AND. PR_TNAST
           Set_Termo()
         ENDIF
         EVAL(bAllPrint)
       CASE nKey == K_ALT_F9
         If GlobalTask != 'KP'
            IF lSetCode
              PrtSetup(cHead,lNumStr,cId,lSumKol)
            ELSE
              Set_Termo(cHead,lNumStr,cId,lSumKol)
            ENDIF
         Else
            SayAndWait("Настройка принтера в разделе 'Администратор'.")
         EndIf
       CASE nKey = K_ALT_S
         FirstFind()
         oTbr:RefreshAll()
         lUpd:=.T.
       CASE nKey = K_CTRL_L
         IF EMPTY(cFindString)
            FirstFind()
         ELSE
            NextFind()
         ENDIF
         oTbr:RefreshAll()
         lUpd:=.T.
     ENDCASE
   ENDIF
 ENDDO
 //TrapShift()
 SETKEY(K_RETURN,sRet)
 SETKEY(K_F1,sF1)
 SETKEY(K_ALT_F5,sAF5)
 SETKEY(K_ALT_F7,sAF7)
 SETKEY(K_ALT_F9,sAF9)
 SETKEY(K_ALT_P,sAP)
 SETKEY(K_ALT_F8,sAF8)
 SETKEY(K_CTRL_L,sCtrlL)
 SETKEY(K_ALT_S,sAltS)
 SETKEY(K_CTRL_RET,sCtrlRet)
 SETKEY(K_LEFT,sLeft)
 SETKEY(K_RIGHT,sRight)
 SETKEY(K_UP,sUp)
 SETKEY(K_DOWN,sDown)
 SETKEY(K_PGDN,sPgDn)
 SETKEY(K_PGUP,sPgUp)
 SETKEY(K_ALT_W,sAltW)
// SETKEY(K_ALT_X,sAltX)
 RestSetKey(aSetKey)
RETURN NIL

STATIC FUNCTION SaveView( cFile, xAdd, lNoPere )
 PLOCAL nSaveHandle, cSaveLine,nSaveLen

 lNoPere:=!EMPTY(lNoPere)
 If (nSaveHandle := If(Empty(xAdd),;
                     FCreate(cFile),;
                     FOpen(cFile, FO_READWRITE))) == -1
   SayError( 'Не могу записать файл!' )
   cFile := ""
 ELSE
   If(Empty(xAdd),, FSeek(nSaveHandle, 0, FS_END))
   FSeek(nHandle, 0, FS_SET)
   DO WHILE .T.
     cSaveLine := freadstr( nHandle, 15000 )
     nSaveLen := LEN( cSaveLine )
     FWRITE( nSaveHandle ,IF(lNoPere,cSaveLine,STRTRAN(cSaveLine,CHR(255),CHR(32))), nSaveLen )
     IF nSaveLen < 15000
       EXIT
     ENDIF
   ENDDO
   FClose(nSaveHandle)
   cFile := ''
   SayAndWait( {'Файл записан!'} )
 ENDIF

 fseek(nHandle, nTopPos, FS_SET) // ВЕРНЕМ ГДЕ ВЗЯЛИ
RETURN NIL

STATIC FUNCTION DispSelected()
  If lIsSelected .OR. lRunningSelection
    IF( nLinePos>=MIN(nStart, nEnd) .AND. nLinePos<=MAX(nStart, nEnd))
      RETURN {3,4}
    EndIf
  EndIF
RETURN {1,2}

STATIC FUNCTION stdMeth(nKey)
 PLOCAL lKeyHandled := .T.
 DO CASE
  // K_DOWN and K_UP don't refresh all area so that they need manual recoloring
  CASE nKey==K_DOWN
    oTbr:down()
    If lRunningSelection
       oTbr:ColorRect({oTbr:rowpos,oTbr:colCount(),oTbr:rowpos,oTbr:colCount()},;
                     IF(nLinePos>=nStart, {3,4}, {1,2}))
    EndIF

  CASE nKey==K_UP
    oTbr:up()
    If lRunningSelection
      oTbr:ColorRect({oTbr:rowpos,oTbr:colCount(),oTbr:rowpos,oTbr:colCount()}, ;
                     IF(nLinePos <= nStart, {3,4}, {1,2}))
    EndIF
  CASE nKey==K_PGDN;        oTbr:pagedown()
  CASE nKey==K_PGUP;        oTbr:pageup()
  CASE nKey==K_CTRL_PGUP;   oTbr:gotop()
  CASE nKey==K_CTRL_PGDN;   oTbr:gobottom()
  CASE nKey==K_RIGHT
    If !lRunningSelection
      nHorOffSet+=nHorStep
      If nHorOffSet > nMaxCol-(nX2-nX1)
        nHorOffSet:=nMaxCol-(nX2-nX1)
        CLEAR TYPEAHEAD
      EndIF
      DispFixed()
      oTbr:refreshAll()
    EndIF
  CASE nKey==K_LEFT
    If !lRunningSelection
      nHorOffSet-=nHorStep
      IF nHorOffSet <= 1
        nHorOffSet:=1
        CLEAR TYPEAHEAD
      ENDIF
      DispFixed()
      oTbr:refreshAll()
    EndIF
  CASE nKey==K_HOME
    If !lRunningSelection
      nHorOffSet:=1
      DispFixed()
      oTbr:refreshAll()
    EndIF
  CASE nKey==K_END
    If !lRunningSelection
      nHorOffSet:=nMaxCol-(nX2-nX1)
      DispFixed()
      oTbr:refreshAll()
    EndIF
  OTHERWISE
   lKeyHandled := .F.
 ENDCASE
RETURN lKeyHandled

/** VOID UpdRow()
*  PURPOSE: Освежает номер строки и колонки
*  PARAMS: nLine
**/
STATIC FUNCTION UpdRow(nLine,nCol)
DispOutAt(nY2+1,nX1+10,PADR(LTRIM(STR(nLine))+' ',6,'─'),COL_VBORDER)
IF nCol != NIL
  DispOutAt(nY2+1,nX1+15,' Колонка:',COL_VBORDER)
  DispOutAt(nY2+1,nX1+MaxRow(),PADR(LTRIM(STR(nCol))+' ',6,'─'),COL_VBORDER)
ELSE
  DispOutAt(nY2+1,nX1+15,'────────────────',COL_VBORDER)
ENDIF
RETURN NIL
//




FUNCTION Func1View(nMode,nRow,nCol) //HARBOUR
Local nLastKey

DrawFunc()
sRow:=nRow
nLastKey := LastKey()
if nLastKey == 255
     Return(0)
end

DO CASE

   CASE (nMode=3)
   RETURN(0)
   // Изменение
   CASE (nLastKey=K_ESC.OR.nLastKey=K_CTRL_RET)
        RETURN (K_CTRL_W)

   CASE nLastKey=K_F10
        KEYBOARD CHR(K_CTRL_W)

ENDCASE

IF nLASTKEY==K_F1
   DisplayHelp(IF(nMaxPos<=MAX_EDIT*1024,4,2))
ELSEIF LASTKEY()==K_CTRL_N
   HB_KeyPut(13)
ELSEIF nLastKey=K_DOWN.OR.nLastKey=K_UP.OR.;
   nLastKey=K_LEFT.OR.nLastKey=K_RIGHT.OR.;
   nLastKey=K_HOME.OR.nLastKey=K_END.OR.nLastKey=K_TAB
   UpdRow(nLineNum-nRowAct+nRow+yz,nCol+1)
ENDIF
RETURN(0)


/** VOID PrintIt() ->
*  PURPOSE: Печать пpосматpиваемого файла или выбранного блока
*  PARAMS: nFHandle -
**/
STATIC FUNCTION PrintIt(nFHandle,aPreCode,aPostCode,aInterCode,bLinePrint,nCopyEl,cId,aKolSum,bNameStr,cPrintFile,lOptim,aArray)
  PLOCAL cPLine:='',cLine0,nBegPos:=0, nWhilePos:=NIL    // stuff borders
  PLOCAL lPrintBlock:=.T.
  PLOCAL nArea:=SELECT(), cBusyScr:=SaveScreen(7,30,12,52)
  PLOCAL InitSeq:=CHR(24),i,j,k,l
  PLOCAL nKol,nWidth,nProces:=0,lProces:=(nMaxLine > 0)
  PLOCAL setPrinter:=set(_SET_PRINTER)
  PLOCAL setConsole:=set(_SET_CONSOLE)
  PLOCAL setPrintFile:=set(_SET_PRINTFILE)
  PLOCAL aInter,nPos1,nPos2,nPos,cCode,cScr,cLineCode, Pos_tek, Pos_n_stroki,Pos_k_stroki, nDelSimvol, Korekt_Pos_tek
  PLOCAL LastHandler, cLine1, cVar, Inter, nI, cLine2, nInsSimvol, Len_bak_string, Defaulte_string
  PLOCAL nInter1,cInter2,nInter3,cInter4,cInter5
  PLOCAL bakDevice := PR_DEVICE, bakPause := PR_PAUSE
  PLOCAL nPosition, bakProp := nPropusk, cDisk:=DiskName(),cDir:=DirName()

  nPropusk := 1

  IF(cPrintFile = NIL,,(PR_DEVICE := cPrintFile,PR_PAUSE := .F.))

  IF !lSetCode .AND. PR_TDEVICE="ФАЙЛ"
    PR_DEVICE := cPrintFile := ALLTRIM(PR_TFILE)
    IF !lSetCode .AND. PR_TERROR .AND. FILE(cPrintFile) .AND. (nPosition:=NoOrYes({'   Файл '+cPrintFile+' уже существует   '},3,{" Переписать "," Новое имя "," Отказ "})) = 3 .OR. nPosition = 0 .OR. (nPosition = 2 .AND. (EMPTY((cPrintFile := GetFileName(cPrintFile,,COL_INPUT,"Вывод в файл ..."))) .OR. FILE(cPrintFile)))
      RETURN NIL
    ENDIF
  ENDIF

  IF(ValType(cId) = "C",,cId := "")
  IF(ValType(aKolSum) = "A",,aKolSum := {})

  IF (nStart+nEnd>0.AND.nEnd>=nStart)
    lPrintBlock:=YesOrNo('      Вы хотите '+IF(EMPTY(cPrintFile),"распечатать ...","вывести в файл ...")+'      ',,;
      ' Выбранный блок ',' Весь файл ')
    If lPrintBlock
      nBegPos   := nStart
      nWhilePos := nEnd
      lProces:=.F.
     ElseIf LastKey()==K_ESC
      PR_DEVICE := bakDevice
      PR_PAUSE := bakPause
      RETURN (.F.)
    EndIf
  EndIF

#ifndef __PLATFORM__Linux
    #ifdef __HARBOUR__
    IF !DiskChange("C").AND.m->GlobalTmpPath[2]==":"
       DiskChange(GlobalTmpPath[1])
    ENDIF
    #endif
#endif

  BEGIN SEQUENCE
  IF PR_PTYPE=0
     LastHandler:=ERRORBLOCK({|oErr| IF(YesOrNo(RetStatus(),,' Повтоpить ',' Отказ ',,,COL_ALERT_ERR),.T.,BREAK(1)) })
  ENDIF

#ifdef __PLATFORM__Linux
  set(_SET_PRINTFILE,"|lpr -P " + Trim(PR_DEVICE) + " -l",.T.)
  set(_SET_PRINTER, .T.); set(_SET_CONSOLE, .F.)
#else
  set(_SET_PRINTER, .F.)
  set(_SET_CONSOLE, .F.)
  set(_SET_PRINTFILE,TRIM(iif(lSetCode,PR_DEVICE,PR_TDEVICE)/* azat PR_DEVICE*/),.T.)
  set(_SET_PRINTER, .T.)
#endif

#ifndef __PLATFORM__Linux
  #ifdef __HARBOUR__
  DiskChange(cDisk)
  DirChange(cDir)
  #endif
#endif

  AEVAL(aInterCode,{|x,k_| k:=k_,AEVAL(x,{|y,l_,n| l:=l_,IF(!EMPTY(n:=ASCAN(aArray,{|x| x[1]=k.AND.x[2]=l })).OR.(VALTYPE(y)=="A".AND.LEN(y) >=5.AND.VALTYPE(y[5])=="C".AND.IS_SPEC(y[5])),;
                                              (IF(EMPTY(n),AADD(aArray,{k,l,y[5]}),y[5]:=aArray[n,3]),y[5]:=ChangeLine(y[5],.T.)),NIL) }) })


  // Проход по базе для подсчета ширины отчета
  LoadHead(nFHandle,0,64000,,,.F.,.F.)

#ifndef __PLATFORM__Linux
    #ifdef __HARBOUR__
    IF !DiskChange("C").AND.m->GlobalTmpPath[2]==":"
       DiskChange(GlobalTmpPath[1])
    ENDIF
    #endif
#endif

  IF VWidth(ROUND(PR_WIDTH/m->nMassh,0),'Request').AND.(lOkPrint:=PrtInit())

#ifndef __PLATFORM__Linux
    #ifdef __HARBOUR__
    DiskChange(cDisk)
    DirChange(cDir)
    #endif
#endif

    IF LEN(PRN0_FONT) > 4 // Загрузка шрифтов
      BS_RUN(PRN0_FONT)
    ENDIF

#ifndef __PLATFORM__Linux
    #ifdef __HARBOUR__
    IF !DiskChange("C").AND.m->GlobalTmpPath[2]==":"
       DiskChange(GlobalTmpPath[1])
    ENDIF
    #endif
#endif

       IF lProces
          nProces:=Proces_Ini(nMaxLine*IF(lSetCode,PR_KOL,PR_TCOPY)*LEN(aWidth),15,,"")
       ENDIF
       // Вывод пред кодов
       IF PR_LCODE .AND. IsCode(@PR_BCODE,PR_TYPE,cId)
         Line2Prt(GetPreCode(xGetCode(@PR_BCODE,PR_TYPE,cId)), .F.)
       ENDIF
       If aPreCode!=NIL
         Line2Prt(GetPreCode(aPreCode), .F.)
       EndIf
       FOR nKol:=1 TO IF(lSetCode,PR_KOL,PR_TCOPY) //Цикл по кол-ву экземпляров

       FOR nWidth:=1 TO LEN(aWidth) //Цикл по кол-ву частей,разбитых по ширине

       // Сброс
       nLine := 0
       nPage := 1
       // Чтение заголовка или формирование массива для суммирования
       IF nBegPos != 0 .AND. ((PR_HEAD != "0" .AND. !EMPTY(PR_HEAD)) .OR. PR_LSUM)
         LoadHead(nFHandle,0,nBegPos-1,aWidth[nWidth,1],aWidth[nWidth,2],.F.,.T.)
       ENDIF

       FSeek(nFHandle,nBegPos,FS_SET)      // take start position

       ShadowBox('', 7, 30, 11, 50, 'n/g')
       @ 7, 37 Say ' ЖДИТЕ! ' COLOR 'n/g*'
       @ 9, 33 Say ' Идет печать ... ' COLOR 'n/g'
       @ 11, 33 Say ' <Esc> -отказ ' COLOR 'n/g'
       DO WHILE lFReadLn(nFHandle,@cPLine,MAX_LINE_LEN,nWhilePos)
         BEGIN SEQUENCE
         IF PR_PTYPE=0
            ERRORBLOCK({|oErr|MyHandler(setPrinter,setConsole,setPrintFile,nWidth,cLine0,aPreCode)})
         ENDIF
         IF lProces
            Proces_Update(nProces)
         ENDIF
         cPLine := TRIM(cPLine)

         cLine0:=IF( aWidth[nWidth,1] > 1, '~', '' )+;
                 SUBSTR(cPLine,;
                        aWidth[nWidth,1]+IF( aWidth[nWidth,1]>1, 1, 0 ),;
                        aWidth[nWidth,2] ;
                       )

         IF CHR(12) $ cPLine .AND. !(CHR(12) $ cLine0)
            IF AT(CHR(12),cPLine)<aWidth[nWidth,1]
               cLine0=CHR(12)+cLine0
            ELSE
               cLine0=cLine0+CHR(12)
            ENDIF
         ENDIF
         Pos_n_stroki := nLinePos0+aWidth[nWidth,1]-1
         Pos_k_stroki := Pos_n_stroki + LEN(cLine0)
         Pos_tek := 0        // тек. позиция в исходной стpоке
         nInsSimvol := 1     // кол-во вставл. символов
         IF !EMPTY(aInterCode)
          // Изменение 3.18
          AEVAL(aInterCode,{|aInterCode|;
                              AEVAL(aInterCode,{|Inter|;
                                ; // Сдвиг на требуемое кол-во копий
                                nInter1 := Inter[1] + IF(!EMPTY(nCopyEl),nCopyEl * INT(Pos_n_stroki/nCopyEl),0),;
                                ; // Проверка входимости
                                IF(nInter1 >= Pos_n_stroki .and. nInter1 <= Pos_k_stroki,(;
                                  Pos_tek := nInter1-Pos_n_stroki+nInsSimvol,;
                                  IF(LEN(Inter) >= 4,(;
                                     ; // Сдвиг на требуемое кол-во копий
                                     nInter3 := Inter[3] + IF(!EMPTY(nCopyEl),nCopyEl * INT(Pos_n_stroki/nCopyEl),0),;
                                     ; // В случае сжатого шpифта - печатаем новым пpоходом
                                     ; // Опpеделим длину заменяемого текста
                                     Len_bak_string := nInter3 - nInter1,;
                                     ; // Опpеделим текст для замены
                                     ; // стаpый текст - как было, только печать втоpым пpоходом
                                     Defaulte_string := SUBSTR(cLine0,Pos_tek,Len_bak_string),;  // Сохpаняем значение по умолчанию
                                     IF(LEN(Inter) >= 5 .and. !EMPTY((cInter5 := Inter[5])),;
                                       ; // новый текст
                                       Defaulte_string := cInter5,;
                                       NIL;
                                        ),;
                                     ;// Удалим видимую инфоpмацию в соотв. с cPict
                                     cLine0 := MyPosRepl(@cLine0,SPACE(Len_bak_string),Pos_tek),;
                                     ; // Вставим новую в соотв. с cPictShrift, пpичем новым пpоходом !!!
                                     cLine0 += CHR(13)+SPACE(nInter1-Pos_n_stroki+PR_OFFSET)+GetPreCode(Inter[2])+Defaulte_string+GetPreCode(Inter[4]);
                                                     ),;
                                                     (;
                                     ; // В случае ноpм. шpифта печатаем по стаpому
                                     cLineCode := GetPreCode(Inter[2]),;
                                     cLine0 := PosIns(cLine0,cLineCode,Pos_tek),;      // Вставим упpавл. код
                                     nInsSimvol += LEN(cLineCode);
                                                      );
                                    );
                                                                                           ),;
                                  NIL;
                                  );
                                               };
                                    );
                           };
               )
         ENDIF

         lOkPrint := Head(@cLine0,@cPLine,aWidth[nWidth,1],aWidth[nWidth,2],@bLinePrint,NIL,@aKolSum,@bNameStr,@nWhilePos,@nFHandle,lOptim)
         END SEQUENCE
         If !lOkPrint
           EXIT
         EndIF
       ENDDO


       If !lOkPrint
         RestScreen(7,30,11,52,cBusyScr)
         IF lProces
            Proces_End()
         ENDIF
         IF hisPrint()
           ?
           // Вывод пост кодов
           IF PR_LCODE .AND. IsCode(@PR_ECODE,PR_TYPE,cId)
             Line2Prt(GetPreCode(xGetCode(@PR_ECODE,PR_TYPE,cId)), .F.)
           ENDIF
         ENDIF
         set(_SET_PRINTER,.F.)
         set(_SET_CONSOLE,setConsole)
         set(_SET_PRINTFILE,TRIM(setPrintFile))
         set(_SET_PRINTER,setPrinter)
         PR_DEVICE := bakDevice
         PR_PAUSE := bakPause
         // Изменение 3.60
         BREAK
       EndIF
       IF nKol==IF(lSetCode,PR_KOL,PR_TCOPY).AND.nWidth==LEN(aWidth)
          IF lProces
            Proces_Update(nProces)
          ENDIF
          If aPostCode!=NIL
             Line2Prt(GetPreCode(aPostCode),.F.)
          EndIf
          IF EMPTY(cCpi0) .AND. lSetCode
             Line2Prt(GetPreCode('10Cpi'),.F.)
          ENDIF
          IF PR_PAPER.AND.!PR_PROBROS.AND.nLine>0  //Конечный проброс
            IF  m->lEndEndPage
             ? CHR(12)
            ENDIF
             nLine:=0
          ENDIF
       ENDIF

       IF PR_PAPER.AND.(PR_PROBROS.OR.LEN(aWidth) > 1).AND.nLine>0
         nPage++;nLine:=0
         // Дополним текущую полосу до конца листа
         ? CHR(12)
         IF PR_PAUSE.AND.!(nKol==IF(lSetCode,PR_KOL,PR_TCOPY).AND.nWidth==LEN(aWidth))
            nPropusk := NoOrYes( {'Смените бумагу'},nPropusk,;
                        {' Продолжить ',;
                         ' Пропустить лист ',;
                         ' Отказ '})
            IF LASTKEY() == K_ESC .OR. nPropusk == 3
               EXIT
            ENDIF
         ENDIF
       ENDIF

       IF nKol==IF(lSetCode,PR_KOL,PR_TCOPY)        .AND. ;
          nWidth==LEN(aWidth) .AND. ;
          (nLine>0.OR.!PR_PAPER) .AND. ;
          nPropusk == 1
          ?
       ENDIF

       NEXT
       NEXT
       IF lProces
          Proces_End()
       ENDIF
       RestScreen(10,30,15,52,cBusyScr)
 ENDIF

 // На всякий случай сброс буферов
 ClearHead()

 // Вывод пост кодов
 IF PR_LCODE .AND. IsCode(@PR_ECODE,PR_TYPE,cId)
   Line2Prt(GetPreCode(xGetCode(@PR_ECODE,PR_TYPE,cId)), .F.)
 ENDIF

 // Изменение 3.60

 END SEQUENCE

 IF PR_PTYPE=0
    ERRORBLOCK(LastHandler)
 ENDIF

#ifndef __PLATFORM__Linux
 #ifdef __HARBOUR__
 DiskChange(cDisk)
 DirChange(cDir)
 #endif
#endif

 set(_SET_PRINTER,.F.)
 set(_SET_CONSOLE,setConsole)
 set(_SET_PRINTFILE,TRIM(setPrintFile))
 set(_SET_PRINTER,setPrinter)

 PR_DEVICE := bakDevice
 PR_PAUSE := bakPause
 nPropusk := bakProp

RETURN (NIL)

//----------------------------------------------------------------------------//
       FUNCTION IsCode(cLongCode,cTypePrint,cId)
//----------------------------------------------------------------------------//
// Возвращает признак возможности выводов кодов принтера
RETURN HISPrint() .AND. "{"+GlobalTask+cTypePrint+cId+":" $ cLongCode

//----------------------------------------------------------------------------//
       FUNCTION xGetCode(cLongCode,cTypePrint,cId)
//----------------------------------------------------------------------------//
// Преобразование строки в массив кодов по соотв. индексу
PLOCAL aPrintCode := {}, cNext
PLOCAL cPrintCode := BEFORATNUM("}",AFTERATNUM("{"+GlobalTask+cTypePrint+cId+":",cLongCode,1),1)
TokenInit( @cPrintCode, ",")
WHILE !TokenEnd()
 IF !EMPTY((cNext := TokenNext(@cPrintCode)))
   AADD(aPrintCode,cNext)
 ENDIF
END
RETURN aPrintCode

//----------------------------------------------------------------------------//
STATIC FUNCTION LoadHead(nFHandle,nBegF,nEndF,nBegPoz,nLen,lRestPoz,lHead)
//----------------------------------------------------------------------------//
// Чтение заголовка с nBegF, nEndF. Куска с nBegPoz по nLen
// lRestPoz восстанавливать позицию в файле
PLOCAL nBakPoz, cPLine := '', cLine0
IF lRestPoz
 nBakPoz := FTELL(nFHandle)
ENDIF

FSeek(nFHandle,nBegF,FS_SET)      // take start position

DO WHILE lFReadLn(nFHandle,@cPLine,MAX_LINE_LEN,nEndF)
  IF lHead
    Head(SUBSTR(cPLine,nBegPoz,nLen),TRIM(cPLine),nBegPoz,nLen,,.T.)
  ENDIF
ENDDO
IF lHead
  // Признак печати блока (заголовок сразу на первом листе)
  lPrnBuffer := .T.
ENDIF
IF lRestPoz
 FSeek(nFHandle,nBakPoz,FS_SET)
ENDIF

RETURN NIL

//----------------------------------------------------------------------------//
       FUNCTION ClearHead()
//----------------------------------------------------------------------------//
// Очистка данных по заголовку
  aBufferFullHead := {}
  aBufferHead := {}
  aBufferSum := {}
  lDelSumBuffer := .T.
  lBeg := .F.
  lEnd := .F.
  lEofORNoEof := .F.
  lEndOrNoEnd := .F.
  lPrnBuffer := .F.
RETURN NIL

//----------------------------------------------------------------------------//
       FUNCTION DataRetCode(cCode,lPrnCode)
//----------------------------------------------------------------------------//
// Возвращает строку по кодам в cCode
PLOCAL cRet := ""
TokenInit( @cCode,",")
WHILE !TokenEnd()
  cRet += IF(!EMPTY(CHARREM(",1234567890", cCode)),GetPrnCode(TokenNext(@cCode)),CHR(VAL(TokenNext(@cCode))))
END
RETURN cRet

//----------------------------------------------------------------------------//
       FUNCTION IsRetCode(cCode)
//----------------------------------------------------------------------------//
// Возвращает строку по кодам в cCode
PLOCAL lRet := .F.
TokenInit( @cCode,",")
WHILE !TokenEnd() .AND. !lRet
  lRet := lRet .OR. !EMPTY(GetPrnCode(TokenNext(@cCode)))
END
RETURN lRet

//----------------------------------------------------------------------------//
FUNCTION ChangeLine(cFullLine,lPrnCode,lSumma,lOnly)
//----------------------------------------------------------------------------//
  LOCAL cCode, cZnBeg,cZnEnd
  lSumma:=.F.
  lOnly := RIGHT(TRIM(STRTRAN(cFullLine,CHR(255),CHR(32))),2) = "\}" .OR. ;
           RIGHT(TRIM(STRTRAN(cFullLine,CHR(255),CHR(32))),2) = "]}"
  WHILE (("{\" $ cFullLine .AND. "\}" $ cFullLine .AND.;
          !EMPTY((cZnBeg:='{\') + (cZnEnd:='\}'))) .OR. ;
         ("{[" $ cFullLine .AND. "]}" $ cFullLine .AND.;
          !EMPTY((cZnBeg:='{[') + (cZnEnd:=']}')))) .AND. ;
        (cCode := BEFORATNUM(cZnEnd,AFTERATNUM(cZnBeg,cFullLine,1),1),;
         IsRetCode(cCode).OR.EMPTY(CHARREM(",1234567890", cCode));
        )
     // Если одинарная конструкция то обрубим конечные пробелы
     IF !lPrnCode.AND.lOnly .AND. EMPTY(lSumma)
       cFullLine := TRIM(STRTRAN(cFullLine,CHR(255),CHR(32)))
     ENDIF
     lSumma := .T.
     cFullLine := BEFORATNUM(cZnBeg,cFullLine,1)+DataRetCode(cCode,lPrnCode)+AFTERATNUM(cZnEnd,AFTERATNUM(cZnBeg,cFullLine,1),1)
  ENDDO
RETURN cFullLine

//----------------------------------------------------------------------------//
       FUNCTION Head(cLine,cFullLine,nBegPoz,nLen,bLinePrint,lNoPrint,aKolSum,bNameStr,nWhilePos,nFHandle,lOptim)
//----------------------------------------------------------------------------//
// Обрабатывает вывод для :
// 1) выделения и вставки заголовка в текст при печати на новом листе
// 2) нумерации страниц
// 3) суммирование колонок
// 4) дата и время в нач. печати
// 5) для замены спец.конструкций типа {\n1,n2,n3....\}
//    на CHR(n1)+CHR(n2)+CHR(n3)+....
// cLine - текущая строка вывода со вставками шрифтов
// cFullLine  - полная строка вывода (без шрифтов)
// lNoPrint != NIL только формирование буфера
// aKolSumm - массив номеров колонок для суммирования
// bNameStr - блок кода для вывода итого по странице - ему передается
//            куча параметров (как нибуть позже опишу)
// nWhilePos - признак вывода суммы по блоку (при печати отмеченного блока)
//             при nWhilePos - выводит итог
// nFHandle - дескриптор файла вывода, nWhilePos и nFHandle
//            требуются только совместно при выводе суммы по блоку
// lOptim   - .T. оптимизация прогона листа
// Возвращает признак нормального завершения печати

PLOCAL cXLine, i, lHid := .F., lPOkPrint := (lNoPrint = NIL), nLenKol, lNumber := .F., lOnly
PLOCAL lNoHead := PR_HEAD = "0" .OR. EMPTY(PR_HEAD), cString, lPrint := .F., aDelKol := {}, lSumma  , nTPoz, nBegLine := 0
// Проверка на спец.конструкцию
IF IS_SPEC(cFullLine)
  IF "{[0]}"$cFullLine
     RETURN lPOkPrint
  ENDIF
  ChangeLine(@cFullLine,.F.,@lSumma,@lOnly)
  IF lSumma  // нашли ли конструкцию
    // Предпологается, что шрифтов нет
    cLine := PRN_STR(cFullLine)
    IF lOnly
      // Если строка целиком из спец. конструкции то возврат коретки не ставим
      RETURN lPOkPrint .AND. Line2Prt(cFullLine,.F.,,bLinePrint,lOptim,nFHandle)
    ENDIF
  ENDIF
ENDIF
// Проверка на конец таблицы или печати
IF lEndOrNoEnd .AND. (cLine = NIL .OR. !LIKE(CHARREPL("┌┬┐─ "+CHR(251)+CHR(255),aBufferFullHead[1],"│??????"),CHARREPL("└┘┌┐├─┤",cFullLine,"││││││")))
   ClearHead()
ELSE
   lEndOrNoEnd  := .F.
ENDIF
// Печать даты и времени
IF lSetCode .AND. CURR_DTIME .AND. nLine = 0 .AND. nPage = 1 .AND. lPOkPrint
 cXLine := IF(nBegPoz=1,SPACE(PR_OFFSET),'')+STRTRAN(RTRIM(STRTRAN(STRTRAN(CURR_FTIME,"&DATE",DTOC(DATE())),"&TIME",TIME())),"&CTLF",CHR(13)+CHR(10))
 TokenInit( @cXLine, CHR(13)+CHR(10))
 WHILE !TokenEnd()
   nBegLine++
   Line2Prt(TokenNext(@cXLine),,,bLinePrint,lOptim,nFHandle)
 END
ENDIF
IF lNoHead .AND. !PR_NUMSTR .AND. !PR_LSUM
 // Вывод заголовка,нумерации страниц,суммирования колонок не требуется
 RETURN lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+cLine,,,bLinePrint,lOptim,nFHandle)
ELSEIF PR_NUMSTR .AND. nLine = nBegLine .AND. nPage > 1 .AND. lNoHead
 // Нет заголовка, но есть нумерация страниц
 RETURN lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+RTRIM(PADC("- "+ ALLTRIM(STR(PR_BEGSTR + (nPage-1),5,0)) +" -",LEN(TRIM(PRN_STR(cFullLine))))),,,bLinePrint) .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+cLine,,,bLinePrint,lOptim,nFHandle)
ENDIF
IF "─" $ cLine.OR.Kolonki(cLine)
  // Определяем начало заголовка
  IF !lBeg .AND. !EMPTY(CHARONLY("┌┬┐",cFullLine)) .AND. !("│" $ cFullLine)
    ClearHead()                                          // отрубаем вложенные
    lBeg := .T.                                          // таблицы
    // Формируем буффер
    AADD(aBufferFullHead,cFullLine)            // нужен и для суммирования при
    AADD(aBufferHead,cLine)                    // определении конца таблицы и областей
                                               // вывода
  // Определяем конец заголовка если требуется
  ELSEIF lBeg .AND. LIKE(CHARREPL("┌┬┐─ "+CHR(255)+CHR(251),aBufferFullHead[1],"│││????"),CHARREPL("├┼┤",cFullLine,"│││"))
    // Предпологаем, что конец заговка сплошная линия типа "├───┼─┬─┤"  может быть ?
    // Возможно, это и есть конец заголовка, а может и
    // нет, тогда уточним по следущей строке
    lEofORNoEof := LEFT(CHARONLY("├",cFullLine),1) = "├" .AND.  RIGHT(CHARONLY("┤",cFullLine),1) = "┤"
    AADD(aBufferFullHead,cFullLine)   // !!! нужно и при суммировании
    AADD(aBufferHead,cLine)
  // Определяем конец таблицы
  ELSEIF lEnd
    // Предпологаем, что конец таблице, но уточним по следущей строке
    lEndOrNoEnd := LIKE(CHARREPL("┌┬┐─ "+CHR(251)+CHR(255),aBufferFullHead[1],"│││????"),CHARREPL("└┴┘",cFullLine,"│││"))
    IF !lNoHead
      // Скорректируем последнюю строку
      aBufferHead[LEN(aBufferHead)] := cLine
      aBufferFullHead[LEN(aBufferFullHead)] := cFullLine
    ENDIF
  ENDIF
ELSEIF lBeg .AND. !lEnd
// Заполнение тела заголовка
  cLine := STRTRAN(cLine,'√',' ')
  IF lEofORNoEof .AND. (!EMPTY(CHARONLY("1234567890",cFullLine)) .OR. ;
                        "....." $ cFullLine .OR. ;
                        "│┌" $ cFullLine;
                       ) .AND. (PR_HEAD_LINE == 0 .OR. ;
                                LEN(aBufferFullHead) >=PR_HEAD_LINE ;
                               )

                       // Предполагаем, что после сплошной линии
                       // если идут цифры или есть ".....",
                       // или есть "│┌" (вложенные таблицы),
                       //  то это и был конец заголовка
                       // или заголовок с нумерацией колонок
    lBeg := .F.
    lEnd := .T.
    // Формируем массив для суммирования
    IF PR_LSUM
      cString := ATAIL(aBufferFullHead)  // колонки выделяем по разделителям в
      TokenInit( @cString, "├┬┼┤")       // последней строке шапки
      WHILE !TokenEnd()
       // Анализ на наименование колонок
       // убираем колонки с наименование на "НОМ" или "Н/НОМ" и т.п.,
       // если не указано aKolSum
       // Галочки нужны для пометки суммируемых колонок
       lSumma := .F.
       lOnly := .F.
       IF (nLenKol := NUMAT("─",TokenNext(@cString))) != 0 .AND. (!EMPTY(aKolSum) .OR. ;
          ASCAN(aBufferFullHead,;
                {|cStr|;
                  cStr := UPPER(ALLTRIM(SUBSTR(cStr,TokenAt(),nLenKol))),;
                  lSumma := (lSumma .OR. cStr = "СУММА"),;
                  lOnly := (lOnly .OR. "√" $ cStr),;
                  !lSumma .AND.;
                  !lOnly  .AND.;
                                (;
                    cStr = "НОМ"   .OR.;
                    cStr = "Н/НОМ" .OR.;
                    cStr = "ЦЕНА"  .OR.;
                    cStr = "КОЛ"   .OR.;
                    cStr = "ДОКУМ" .OR.;
                    cStr = "ИНН" .OR.;
                    cStr = "КПП" .OR.;
                    cStr = "ДОГОВ" .OR.;
                    cStr = "КОЭФ";
                                 );
                  };
                ) = 0)

         AADD(aBufferSum,{TokenAt(),nLenKol,0,NIL,lSumma,0,lOnly})
         // 1. Позиция начала колонки
         // 2. Ширина колонки
         // 3. Накопительная сумма по странице
         // 4. Формат вывода сумм
         // 5. Признак принудительного подсчета сумм по колонке
         // 6. Накопительная сумма по буферу всего
         // 7. Признак исключительного подсчета сумм по этим колонкам
         //    т.е. если хотя бы один такой признак присутствует, то
         //    подсчет сумм ведется только по колонкам у которых выставлен
         //    признак
       ENDIF
      END
      IF ASCAN(aBufferSum,{|x| x[7] }) != 0
        // Удаление лишних колонок
        AEVAL(aBufferSum,{|x,y| IF(x[7],NIL,AADD(aDelKol,y)) })
        ASORT(aDelKol,,,{|x,y| x > y })
        AEVAL(aDelKol,{|x| ADEL(aBufferSum,x) })
        ASIZE(aBufferSum,LEN(aBufferSum)-LEN(aDelKol))
        aDelKol := {}
        AEVAL(aBufferFullHead,{|cStr,y| aBufferFullHead[y] := STRTRAN(cStr,'√',' ') })
      ENDIF
    ENDIF
    IF !lNoHead
      // Определяем - вывод заголовка с нумерацией колонок ?
      IF PR_HEAD = "1" .AND. PR_HEAD != "2" .AND. ("│%%│%%│%%│" $ (cString := CHARREPL("1234567890",CHARREM(" "+CHR(251)+CHR(255),cFullLine),"%%%%%%%%%%")) .OR. "│%│%│%│" $ cString)
        // Нумерация колонок если требуется или указано по умолчанию
        lNumber := .T.
        aBufferHead[1] := CHARREPL("├┼┤",ATAIL(aBufferHead),"┌┬┐")
        aBufferHead[2] := cLine
        aBufferHead[3] := ATAIL(aBufferHead)
        aBufferFullHead[1] := CHARREPL("├┼┤",ATAIL(aBufferFullHead),"┌┬┐")
        aBufferFullHead[2] := cFullLine
        aBufferFullHead[3] := ATAIL(aBufferFullHead)
        ASIZE(aBufferFullHead,3)
        ASIZE(aBufferHead,3)
      ELSEIF PR_HEAD = "3"
        // Нумерация колонок
        lNumber := .T.
        lHid := !("│%%│%%│%%│" $ (cString := CHARREPL("1234567890",CHARREM(" "+CHR(251)+CHR(255),cFullLine),"%%%%%%%%%%")) .OR. "│%│%│%│" $ cString)
        aBufferFullHead[1] := CHARREPL("├┼┤",ATAIL(aBufferFullHead),"┌┬┐")
        cXLine := CHARREPL("├┼┤─"+CHR(255)+CHR(251),ATAIL(aBufferFullHead),"│││   ")
        aBufferFullHead[2] := BEFORATNUM("│",cXLine,1)+"│"
        cXLine := ALLTRIM(cXLine)
        i := 1
        TokenInit( @cXLine, "│")
        WHILE !TokenEnd()
          TokenNext(@cXLine)
          i++
          IF i != 1
            aBufferFullHead[2] += PADC(PADL(ALLTRIM(STR(i-1,2,0)),2,"0"),TokenAt(cXLine,.T.)-TokenAt(cXLine,.F.))+"│"
          ENDIF
        END
        aBufferFullHead[3] := ATAIL(aBufferFullHead)
        aBufferHead[1] := CHARREPL("├┼┤",ATAIL(aBufferHead),"┌┬┐")
        // Предполагается, что в обрамлении таблицы незадействованы шрифты
        aBufferHead[2] := PRN_STR(aBufferFullHead[2])
        aBufferHead[3] := ATAIL(aBufferHead)
        ASIZE(aBufferFullHead,3)
        ASIZE(aBufferHead,3)
      ELSEIF PR_LSUM
        lNumber := "│%%│%%│%%│" $ (cString := CHARREPL("1234567890",CHARREM(" "+CHR(251)+CHR(255),cFullLine),"%%%%%%%%%%")) .OR. "│%│%│%│" $ cString
      ENDIF
    ELSEIF PR_LSUM
      lNumber := "│%%│%%│%%│" $ (cString := CHARREPL("1234567890",CHARREM(" "+CHR(251)+CHR(255),cFullLine),"%%%%%%%%%%")) .OR. "│%│%│%│" $ cString
    ENDIF
  ELSE
    lEofORNoEof := .F.
    AADD(aBufferFullHead,cFullLine)   // !! треб. для анализа наименований
    AADD(aBufferHead,cLine)           // шапки для суммирования
                                      // в часности для номенклатурного номера
    // Предполагаем, что заголовок не может быть более 30 строк
    IF LEN(aBufferHead) > 30
      ClearHead()
    ENDIF
  ENDIF
ENDIF

// Определяем возможность вывода заголовка
// Заголовок выводится если область вывода типа "│????│", где ? любые символы
// в кол-ве как и длина заголовока
// Суммирование производится в случае если область вывода типа "│?????│?????│...│"
// причем ширина и расположение колонок такое же как и в шапке

// Суммирование требуемых колонок если область вывода соотв. шапке
// и заначение колонки числовое и ее ширина >= 10 символов
IF PR_LSUM .AND. !lEndOrNoEnd .AND. lEnd .AND. lPOkPrint .AND. LIKE(CHARREPL("├┬┼┤─ "+CHR(251)+CHR(255),ATAIL(aBufferFullHead),"││││????"),cFullLine) .AND. !lNumber
  // так же чтение шаблона и анализ возможности суммирования Os@
  AEVAL(aBufferSum,{|x,y|;
                     cString := SUBSTR(cFullLine,x[1],x[2]),;
                     IF((!EMPTY(aKolSum) .OR. x[5] .OR. x[7] .OR. x[2] >= 10) .AND. (x[5] .OR. x[7] .OR. (!(".." $ cString) .AND. !("/" $ cString) .AND. POSRANGE(33,43,cString) = 0 .AND. POSRANGE(0,31,cString) = 0 .AND. POSRANGE(58,255,cString) = 0 .AND. !EMPTY(cString))),;
                        (;
                         cString := STRTRAN(cString,CHR(255),' '),;
                         x[3] += if(allTrim(cString)<>"01" .and. allTrim(cString)<>"02",VAL(CHARREM(",",cString)),0),;
                         IF(x[4] = NIL .OR. (!(x[4] $ ",") .AND. "," $ cString),;
                            (;
                              x[4] := CHARREPL("123456780",PADL(LTRIM(cString),x[2],"9"),"999999999"),;
                              x[4] := CHARREPL(" ",RTRIM(x[4]),"9"),;
                              IF("," $ cString,(cString := "",AEVAL(ARRAY(INT(IF("." $ x[4],ATNUM(".",CHARREM(",",x[4]))-1,LEN(CHARREM(",",x[4])))/3+0.9)),{|| cString += ",999" }),x[4] := PADL(REMLEFT(RIGHT(cString+IF("." $ x[4],"."+AFTERATNUM(".",x[4]),""),LEN(x[4])),','),LEN(x[4]))),NIL);
                             ),;
                            NIL;
                            );
                         ),;
                        IF(!EMPTY(cString) .AND. x[3] != NIL,AADD(aDelKol,y),NIL);
                        );
                     })
  IF !EMPTY(aDelKol)
    // Удаление  не указанных колонок и избыточных
    IF lDelSumBuffer .AND. !EMPTY(aKolSum)
      AEVAL(aBufferSum,;
            {|x,y|;
              cString := x,;
              IF(ASCAN(aKolSum,y) = 0,;
                AADD(aDelKol,y),;
                NIL;
                );
              };
            )
    ENDIF
    ASORT(aDelKol,,,{|x,y| x > y })
    AEVAL(aDelKol,{|x| ADEL(aBufferSum,x) })
    ASIZE(aBufferSum,LEN(aBufferSum)-LEN(aDelKol))
    lDelSumBuffer := .F.
  ENDIF
ENDIF

// Вывод заголовка с нумерацией
IF !lNoHead .AND. PR_NUMSTR .AND. ((nLine = nBegLine .OR. lHid) .AND. (nPage > 1 .OR. lPrnBuffer))
  IF lEnd .AND. LIKE(CHARREPL("┌┬┐─ "+CHR(251)+CHR(255),aBufferFullHead[1],"│??????"),cFullLine)
    IF !lHid .AND. nPage > 1
       // т.к. нумерация после первого заголовка не нужна
       lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+RTRIM(PADC("- "+ ALLTRIM(STR(PR_BEGSTR + (nPage-1),5,0)) +" -",LEN(TRIM(PRN_STR(cFullLine))))),,,bLinePrint,lOptim,nFHandle)
    ENDIF
    AEVAL(aBufferHead,{|cLine| lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+cLine,,,bLinePrint,lOptim,nFHandle) },IF(lHid,2,1))
    RETURN lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+cLine,,,bLinePrint,lOptim,nFHandle)
  ELSEIF nPage > 1
    // Нумерация без заголовка
    RETURN lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+RTRIM(PADC("- "+ ALLTRIM(STR(PR_BEGSTR + (nPage-1),5,0)) +" -",LEN(TRIM(PRN_STR(cFullLine))))),,,bLinePrint,lOptim,nFHandle) .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+cLine,,,bLinePrint,lOptim,nFHandle)
  ENDIF
ENDIF
// Вывод заголовка без нумерации
IF !lNoHead .AND. lEnd .AND. ((nLine = nBegLine .AND. (nPage > 1 .OR. lPrnBuffer)) .OR. lHid) .AND. LIKE(CHARREPL("┌┬┐─ "+CHR(255)+CHR(251),aBufferFullHead[1],"│??????"),cFullLine)
  AEVAL(aBufferHead,{|cLine| lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+cLine,,,bLinePrint,lOptim,nFHandle) },IF(lHid,2,1))
ENDIF
lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+cLine,,,bLinePrint,lOptim,nFHandle)
IF PR_LSUM .AND. lPOkPrint .AND. (lEndOrNoEnd .OR. ((nLine + 2 = PR_STR/m->nMassh.OR.(nWhilePos != NIL .AND. (nTPoz := FTELL(nFHandle)-MAX_LINE_LEN+10) > nWhilePos)) .AND. lEnd .AND. LIKE(CHARREPL("┌┬┐─ "+CHR(251)+CHR(255),aBufferFullHead[1],"│??????"),cFullLine) .AND. !("─" $ cFullLine)))
  // Вывод сумм по колонкам ! т.к. в конце листа, то не перекрываются нумерацией и шапками
  AEVAL(aBufferSum,{|x| x[6] += x[3] })
  IF !lEndOrNoEnd
    lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+PRN_STR(CHARREPL("├┬┼┤",ATAIL(aBufferFullHead),"└┴┴┘")),,,bLinePrint,lOptim,nFHandle)
  ENDIF
  IF ValType(bNameStr) = "B"
    IF ValType((cString := EVAL(bNameStr,aBufferSum,nBegPoz,nLen,PR_OFFSET,nWhilePos != NIL))) = "C"
      // Предполагается, что в обрамлении таблицы незадействованы шрифты
      lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+PRN_STR(cString),,,bLinePrint,lOptim,nFHandle)
    ENDIF
    AEVAL(aBufferSum,{|x| x[3] := 0 })
  ELSE
    // Итого в конце страницы
    IF !(nPage = 1 .AND. (nWhilePos != NIL .AND. nTPoz != NIL .AND. nTPoz > nWhilePos))
      cString := SPACE(LEN(aBufferFullHead[1]))
      AEVAL(aBufferSum,{|x| IF(!EMPTY(x[3]),(lPrint := .T.,MyPosRepl(@cString,PADL(LTRIM(TRANSFORM(x[3],PADL(x[4],"9",19))),x[2]),x[1]),x[3] := 0),NIL) })
      IF lPrint
        // Предполагается, что в обрамлении таблицы незадействованы шрифты
        IF EMPTY(LEFT(cString,22))
          MyPosRepl(@cString,"ИТОГО НА СТРАНИЦЕ:",3)
        ENDIF
        lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+PRN_STR(cString),,,bLinePrint,lOptim,nFHandle)
      ELSE
        lPOkPrint := lPOkPrint .AND. Line2Prt('',,,bLinePrint,lOptim,nFHandle)
      ENDIF
    ENDIF
    // Итого в конце буфера
    IF nWhilePos != NIL .AND. nTPoz != NIL .AND. nTPoz > nWhilePos
      cString := SPACE(LEN(aBufferFullHead[1]))
      lPrint := .F.
      AEVAL(aBufferSum,{|x| IF(!EMPTY(x[6]),(lPrint := .T.,MyPosRepl(@cString,PADL(TRIM(TRANSFORM(x[6],PADL(x[4],"9",19))),x[2]),x[1])),NIL) })
      IF lPrint
        // Предполагается, что в обрамлении таблицы незадействованы шрифты
        IF EMPTY(LEFT(cString,22))
          MyPosRepl(@cString,"ИТОГО ПО ОТЧЕТУ:",3)
        ENDIF
        lPOkPrint := lPOkPrint .AND. Line2Prt(IF(nBegPoz=1,SPACE(PR_OFFSET),'')+PRN_STR(cString),,,bLinePrint,lOptim,nFHandle)
      ENDIF
    ENDIF
  ENDIF
  IF nWhilePos != NIL .AND. nTPoz != NIL .AND. nTPoz > nWhilePos
      // Требуется т.к. предполагается, что отмеченный буффер
      // уже выведен - cброс всех установок
      ClearHead()
  ENDIF
ENDIF
RETURN lPOkPrint
//---------------------------------------------------------------------------//
            FUNCTION GetCondinsed()
//---------------------------------------------------------------------------//
// Возвращает массив структуры :
// {{наименование последов,код последовательности,ESC последовательность,коэфф.плотности},....}
PLOCAL aCond := {}, cPreCode
IF REFC->(FieldPos("PLOT"+ALLTRIM(PR_TYPE))) != 0
  REFC->(DBEVAL({||  AADD(aCond,{REFC->NAME,REFC->CODE,&(RefC->(FIELDGET(VAL(PR_TYPE)+2))),FieldGet(FieldPos("PLOT"+ALLTRIM(PR_TYPE)))}) },{|| !EMPTY(FieldGet(FieldPos("PLOT"+ALLTRIM(PR_TYPE)))) }))
ENDIF
IF EMPTY(aCond)
 cPreCode := GetPreCode(cCpi)
 AADD(aCond,{REFC->NAME,cCpi,cPreCode,1})
 cPreCode := GetPreCode("17cpi")
 AADD(aCond,{REFC->NAME,"17cpi",cPreCode,IF(CHR(15)$cPreCode,1.7,IF('16.67'$cPreCode,1.875,1.46))})
ENDIF
RETURN aCond
//---------------------------------------------------------------------------//
           FUNCTION GetPrnCode(cCode)
//---------------------------------------------------------------------------//
// Возвращает Esc последовательность по коду последовательности
LOCAL cRetEsc := "",cAlias:=ALIAS(),lRet:=.F.
 IF lRealCode // Реальные коды для принтера
  IF(EMPTY(SELECT("RefC")),(lRet:=.T.,NetUse("RefC","PRN_CODE")),)
  SELECT RefC
  ORDSETFOCUS("CODE")
  IF dbSeek(UPPER(cCode))
    cRetEsc := &(FIELDGET(VAL(IF(VALTYPE(PR_TYPE)=="C",PR_TYPE,PRN0_TYPE))+2))
  ENDIF
  IF(lRet,RefC->(dbCloseArea()),)
  SELECT (cAlias)
 ELSE
   cRetEsc := CHR(27)+ALLTRIM(cCode)
 ENDIF
RETURN cRetEsc
//---------------------------------------------------------------------------//
           FUNCTION SegCol(nCo,nWidth,nMaxCol)
//---------------------------------------------------------------------------//
// Возвращает кол-во полос для печати с плотностью nCo
PLOCAL i:=nCo*nWidth, n, nRet := 1
 n:=i-PR_OFFSET
 WHILE n < nMaxCol
   nRet++
   n+=i/*-4*/ //Lexx
 ENDDO
RETURN nRet
//---------------------------------------------------------------------------//
           FUNCTION SegNameCode(cCode,cName)
//---------------------------------------------------------------------------//
// Возвращает наименование строк меню выбора печати
IF cCode = "10cpi"
  RETURN ' - нормальным шрифтом : 10cpi - "'+ALLTRIM(cName)+'"'
ELSEIF cCode = "17cpi"
  RETURN ' - сжатым шрифтом.....: 17cpi - "'+ALLTRIM(cName)+'"'
ENDIF
RETURN   ' - шрифтом............: '+cCode+' - "'+ALLTRIM(cName)+'"'
//---------------------------------------------------------------------------//
           FUNCTION VWidth(nWidth,lRequest)
//---------------------------------------------------------------------------//
// Формирует массив разбиений для печати и возвращает признак удачного
// формирования массива
STATIC nMode1:=2
LOCAL nMode, i := 1, n, nCol, aSet := {SaveSet(),SaveSetKey()}, nMax := 1
LOCAL aSegment := GetCondinsed(), aItem := {}, aPoz := {}, j:=0
  AEVAL(aSegment,{|aSeg| AADD(aItem,SegNameCode(aSeg[2],aSeg[1])+IF((nCol := SegCol(aSeg[4],nWidth,nMaxCol)) > 1,' на '+NTOC(nCol)+IF(nCol <= 4," полосы "," полос "),"")),nMax := MAX(nCol,nMax) })
  AADD(aItem," - печатать полосу номер...........................")
  
//  IF (IF(lRequest != NIL .AND. nMax > 1,((nMode:=BoxMenu(' Отчет не помещается по ширине, печатать: ',5,5,aItem,,nMode1,,COL_INPUT,COL_INPUT,'NoClear',,'Wide')),IF(!EMPTY(nMode),nMode1:=nMode,)),nMode := 1))>0
  IF lRequest != NIL .AND. nMax > 1
      nMode:=BoxMenu(' Отчет не помещается по ширине, печатать: ',5,5,aItem,,nMode1,,COL_INPUT,COL_INPUT,'NoClear',,'Wide')
  ELSE
      nMode:=1
  ENDIF
  IF nMode>0
    nMode1:=nMode
    IF nMode = LEN(aItem)
      aItem := {}
      AEVAL(aSegment,{|aSeg,n| IF(SegCol(aSeg[4],nWidth,nMaxCol) > 1,(AADD(aItem,SegNameCode(aSeg[2],aSeg[1],MAX_LINE_LEN - 6,nWidth,aSeg[4])),AADD(aPoz,n)),NIL) })
      IF IF( LEN(aItem) > 1 ,(nMode:=BoxMenu(' Печать полосу шрифтом....: ',10,15,aItem,,2,,COL_INPUT,COL_INPUT,'NoClear',,'Wide')),IF(LEN(aItem) != 0,(nMode := 1),(nMode := 0)))>0 .AND.;
        GetAnyThing(@i,"99","Введите номер полосы для печати:",15,20,COL_INPUT)
        nWidth := nWidth * aSegment[aPoz[nMode],4]
        PR_PRECODE := aSegment[aPoz[nMode],3]
        TMP_CODE := aSegment[aPoz[nMode],2]
        aWidth := IF(i != 1,{{(nWidth-4)*(i-2)+nWidth-PR_OFFSET,nWidth}},{{1,nWidth-PR_OFFSET}})
      ENDIF
    ELSE
      IF lRealCode
        PR_PRECODE := aSegment[nMode,3 ]
      ELSE
        PR_PRECODE := CHR(27)+ALLTRIM(aSegment[nMode,2 ])
      ENDIF
      TMP_CODE := aSegment[nMode,2]
      nWidth := nWidth * aSegment[nMode,4]
      aWidth := {{1,nWidth-PR_OFFSET}}
      n:=nWidth-PR_OFFSET
      WHILE n < nMaxCol
         AADD(aWidth,{n,nWidth-1})
         j++
         n+=nWidth-j /*-4*/ //Lexx
      ENDDO
    ENDIF
  ENDIF
  RestSet(aSet[1])
  RestSetKey(aSet[2])
RETURN nMode != 0
//----------------------------------------------------------------------------//
        FUNCTION GetVarString(aInterCode,nI,cLine0,nPos1,cLine1)
//----------------------------------------------------------------------------//
PLOCAL nPos_n := aInterCode[nI][1]-nPos1
PLOCAL nKol := LEN(cLine0)-nPos_n
IF LEN(aInterCode[nI]) > 3 .and. aInterCode[nI,3] != NIL
  PosDel(cLine1,nPos_n,LEN(aInterCode[nI,4]))
  IF ValType(aInterCode[nI,3]) = "B"
    RETURN EVAL(aInterCode[nI,3])
  ENDIF
  RETURN aInterCode[nI,3]
ENDIF
RETURN SUBSTR(cLine0,nPos_n)

/*** LOGICAL Line2Prt(line) -> TRUE if printed succesfully
* PURPOSE: Посылает строку на принтер, управляя переводом страниц
* CHARACTER line   - Строка для печати
*           lNewLine - TRUE (default) - печатать с новой строки
***/
STATIC FUNCTION Line2Prt(line, lNewLine,lSpec,bLinePrint,lOptim,nFHandle)
//lSpec!=NIL - для выдачи спецкодов
  PLOCAL cScr:=SaveScreen(14,13,MaxRow()-5,67)
  PLOCAL nExitKey:=INKEY(),nCount
  PLOCAL sRet:=SETKEY(K_RETURN,NIL), lProgon
  PLOCAL cSymb1 //:="│┤┐└┴┬├─┼┘┌"
  PLOCAL cSymb2:="||||--|-||| " //последний пробел!
  cSymb1:="│┤┐└┴┬├─┼┘┌"+CHR(255)
  lNewLine:=IF(lNewLine==NIL, .T., lNewLine)
  WHILE .T.
  nCount:=20
    WHILE !(HISPrint()).AND.nCount-->0
       nExitKey:=Inkey(0.1)
    ENDDO
    If nExitKey==K_ESC
       SETKEY(K_RETURN,sRet)
       RETURN .F.
     EndIF

    IF nCount<=0
      If !YesOrNo(RetStatus(),,;
        ' Повтоpить ',' Отказ ',,,COL_ALERT_ERR)
        SETKEY(K_RETURN,sRet)
        RETURN (.F.)
      ELSE
        LOOP
      EndIf
    ENDIF
    EXIT
  ENDDO

  IF (lProgon := CHR(12)$line) .AND. lOptim != NIL .AND. nFHandle != NIL .AND. lOptim
    // Оптимизация прогона листа
    IF StrKolLine(nFHandle,nLine) < PR_STR/m->nMassh
       Line :=  STRTRAN(line,CHR(12),' ')
       lProgon := .F.
    ENDIF
  ENDIF

  IF (!lProgon.AND.!CHR(0)$line) .OR. EMPTY(lNewLine)

     IF ValType(bLinePrint) = "B"
       EVAL(bLinePrint,@nPage,@nLine)
     ENDIF

     IF !PR_PSEVDO ;       CHARREPL( cSymb1, @line, cSymb2 )
     ELSE          ;       CHARREPL( CHR(255), @line, ' '  )
     ENDIF

     //  перевод в WINDOWS формат
     IF IF(lSetCode,PR_WIN,PR_TWIN)  ;   DosToWindows( @line ) ;     ENDIF

     TRY

     If lNewLine
        IF nPropusk == 1 ;  ? Line ; ENDIF
        ++nLine
     Else
       IF nPropusk == 1  ; ?? Line ; ENDIF
     EndIF

     END



  ENDIF
  IF lSpec!=NIL
     SETKEY(K_RETURN,sRet)
     RETURN .T.
  ENDIF
  // Если включен двойной промежуток, пошлем лишнюю строку
  IF PR_DBL_SPACE
    IF nPropusk == 1 ;  ? ;    ENDIF
    ++nLine
  ENDIF
  IF PR_PAPER
     IF nLine >= PR_STR/m->nMassh .OR.  lProgon  // new page
        nPage++; nLine:=0
        IF lProgon.OR.PR_PROBROS
          TRY
          ?? CRLF+CHR(12)
          END
        ENDIF
        If PR_PAUSE
          nPropusk := NoOrYes( {'Смените бумагу'},nPropusk,;
                         {' Продолжить ',;
                          ' Пропустить лист ',;
                          ' Отказ '})
          If LASTKEY() == K_ESC .OR. nPropusk == 3
             SETKEY(K_RETURN,sRet)
             RETURN .F.
          EndIF
        Else
         nCount:=100
         WHILE (HISPrint()).AND.nCount-->0
         ENDDO
         DO WHILE !(HISPrint())
         ENDDO
        EndIF
     ENDIF
  ENDIF
  SETKEY(K_RETURN,sRet)
RETURN .T.


/*** LOGICAL PrtInit() -> TRUE if printer is ready
* PURPOSE: Инициализация принтера. Инициализация внешних STATIC
*          управляющих печатью
* PARAMS:
***/
STATIC FUNCTION PrtInit()

 DO While !HISPrint()

   set(_SET_PRINTER, .F.)
   set(_SET_CONSOLE, .T.)

   If !YesOrNo(RetStatus(),,' Повтоpить ',' Отказ ',,,COL_ALERT_ERR)
        RETURN (.F.)
   EndIf
 EndDO
  set(_SET_PRINTER, .T.); set(_SET_CONSOLE, .F.)

 nPage:=1
 nLine:=0

 If !Empty(PR_PRECODE) .AND. lSetCode
   Line2Prt(PR_PRECODE, .F.)
 EndIF
RETURN .T.

FUNCTION GetPreCode(cCode)
PLOCAL cEscSeq:='', i:=1, aList:={}
PRIVATE pSeq:=''
  If ValType(cCode)=='C'
    aList:={cCode}
  ElseIf ValType(cCode)=='A'
    aList:=cCode
  EndIF
  For i:=1 TO Len(aList)
   IF lRealCode  // REAL CODE PRINT
    If RefC->(dbSeek(Upper(aList[i])))               // !!! 04-21-94 12:49pm
      pSeq:=RefC->(FIELDGET(VAL(PR_TYPE)+2))
      If !Empty(Trim(pSeq))
        cEscSeq+=(&pSeq)
      EndIF
    EndIf
   ELSE
     cEscSeq +=CHR(27)+ALLTRIM(aList[i])
   ENDIF
  Next
RETURN (cEscSeq)


//--------------------------------------------------------------------------//
STATIC PROCEDURE PrtSetup(cHead,lNumStr,cId,lSumKol)
//--------------------------------------------------------------------------//
// cHead, lNumStr - для доступа к соотв. полям запретить/разрешить
//        lSumKol - суммирование колонок запретить/разрешить
  LOCAL aSet := SaveSet(), aSetKeys := SaveSetKey()
  LOCAL oGet, GetList:={},nArea,i,nI
#ifdef __PLATFORM__Linux
  LOCAL aDevice:={}
#else  
  LOCAL aDevice:={{'LPT1','LPT1'},{'LPT2','LPT2'},;
                  {'LPT3','LPT3'},{'LPT4','LPT4'},{'LPT5','LPT5'},;
                  {'COM1','COM1'},{'COM2','COM2'}}
#endif
  LOCAL aPWidth:={;
                  { '1', 'Узкая   (A4)' }, ;
                  { '2', 'Широкая (A3)' }, ;
                  { '3', 'Произвольная' }  ;
                }
  LOCAL aPType:={;
                  { 1, 'cетевой  ' }, ;
                  { 0, 'локальный' };
                }
  LOCAL aPHeads:={;
                  { '0', 'не печатать            ' }, ;
                  { '1', 'по умолчанию           ' }, ;
                  { '2', 'с наименованием колонок' }, ;
                  { '3', 'с нумерацией колонок   ' };
                 }
  LOCAL aYes:={'Да ','Нет'}
  LOCAL aPaper:={'Лист ','Рулон'}
  LOCAL aVidP:={'Качественная',;
                'Быстрая     '}

  LOCAL sF10:=SETKEY(K_F10,{||ControlCode()})

#ifdef __PLATFORM__Linux
  LOCAL arrp := hwg_getPrinters()

  IF arrp != Nil
     FOR i := 1 to Len( arrp )
        Aadd( aDevice,{ Padr(arrp[i],15),Padr(arrp[i],15) } )
     NEXT
  ENDIF
#endif

  ReferPush()

  PRIVATE aIn[22]
  PRIVATE cNamePrn

  IF(ValType(cId) = "C",,cId := "")

altd()


  nArea:=SELECT()
  USE (cProPath+"STATION.PRO") ALIAS STATION NEW SHARED
  nI:=FIELDSIZE(FIELDNUM("DEVICE"))
  FOR i:=1 TO LEN(aDevice)
  aDevice[i,1]:=PADR(aDevice[i,1],nI)
  aDevice[i,2]:=PADR(aDevice[i,2],nI)
  NEXT
  CLOSE
  IF !EMPTY(nArea)
     SELECT(nArea)
  ENDIF





  //Общие параметры
  aIn[1]   := PADR(IF(lSetCode,PR_DEVICE,PR_TDEVICE),nI)
  aIn[2]   := PR_TYPE
  aIn[3]   := PR_WIDTH
  aIn[4]   := PR_PAPER
  aIn[5]   := VAL(STR(PR_STR,3,0))
  aIn[6]   := PR_PROBROS
  aIn[7]   := PR_PAUSE
  aIn[11]  := PR_PSEVDO
  aIn[12]  := PR_WTYPE

  aIn[13]  := PR_HEAD
  aIn[14]  := PR_NUMSTR
  aIn[15]  := PR_BEGSTR

  aIn[16]  := PR_LCODE
  aIn[17]  := PR_BCODE
  aIn[18]  := PR_ECODE

  aIn[19]  := PR_LSUM
// Изменение 3.60
  aIn[20]  := PR_PTYPE
  aIn[21]  := IF(lSetCode,PR_WIN,PR_TWIN)
  aIn[22]  := PR_HEAD_LINE

  //Частные параметры
  aIn[8] := PR_OFFSET
  aIn[9] := PR_DBL_SPACE
  aIn[10] := PR_KOL

  SETCOLOR(COL_INPUT)
  ShadowBox(' Настройка параметров печати ',02,06,21,73,,,'Wide')
  SAYSCREEN(' F10:Выдача команд на принтер ',21,11)

  @ 04, 9 SAY "Имя устройства для печати............. :"
  @ 05, 9 SAY "Тип используемого принтера............ :"
  @ 06, 9 SAY "Ширина каретки........................ :"
  @ 07, 9 SAY "Вид бумаги............................ :"
  @ 08, 9 SAY "Строк на страницу..................... :"
  @ 09, 9 SAY "Проброс страницы...................... :"
  @ 10, 9 SAY "Пауза после печати страницы........... :"
  @ 11, 9 SAY "Вид печати............................ :"
  @ 12, 9 SAY "Выдача команд на принтер.............. :"
  @ 13, 9 SAY "Отступ слева.......................... :"
  @ 14, 9 SAY "Вставлять строку-разделитель.......... :"
  @ 15, 9 SAY "Количество экземпляров................ :"
  @ 16, 9 SAY "Печать заголовка в начале листа....... :"
  @ 17, 9 SAY "Количество строк заголовка............ :"
  @ 18, 9 SAY "Нумерация страниц..................... :"
  @ 18, 54 SAY "Начальный номер:"
  @ 19, 9 SAY "Итоги в конце страницы................ :"
  @ 20, 9 SAY "Вывод в Windows  формате.............. :"

  SetLastKey(K_UP)

  SELECT RefP
  SET FILTER TO !EMPTY(FIELD->Name)
  MakeRefer('RefP','Принтеры',1,{'Код','Наименование'},;
            {3,28,5},COL_REFER,{'NPRINTER','NAME'},{'aIn[2]','cNamePrn'},;
            'aIn[2]',{FIELDBLOCK('NPRINTER'),FIELDBLOCK('NAME')},;
            {{'','Код принтера?','NPRINTER','aIn[1]','X'}})

  SEEK PR_TYPE
  cNamePrn := RefP->NAME
// Изменение 3.60
  SayScreen(LEFT(cNamePrn,10),5,52)
//1 - имя устройства
  oGet := GETNEW(04,50,{|x|IF(x==NIL, aIn[1], aIn[1]:=x)} ,"aIn[1]")
  oGet:reader := {|oGet| RotateAndReader( oGet,aDevice,,oGet:col,COL_REF1)}
  AADD(GetList,oGet)
//2 - тип принтера
// Изменение 3.60
  @ 05, 50 REFER "RefP" GET aIn[2] ;
  WHEN{||ScrTitul(MAXROW(),"Ctrl-F1: Типы принтеров"),.T.} ;
  VALID {||SayScreen(LEFT(cNamePrn,10),5,52),ScrTitul(MAXROW(),""),.T.}
//3 - тип принтера сетевой/локальный
  oGet := GETNEW(05,63,{|x| RotateBlock(x,aPType,'aIn[20]') } ,"aIn[20]")
  oGet:reader := {|oGet| RotateAndReader( oGet,aPType,,oGet:col,COL_REF1)}
  AADD(GetList,oGet)
//3 - ширина каретки
   oGet := GETNEW(06, 50,  { |x| IF(aIn[12]=='1',aIn[3]:=80,IF(aIn[12]=='2',aIn[3]:=132,)),;
                                 ;  // Изменение 3.60
                                 GetList[5]:Display(),;
                                 RotateBlock(x,aPWidth,'aIn[12]')} )
   oGet:Reader := { |oGet| RotateAndReader( oGet,aPWidth, 7, 28 ) }
   AADD( GetList, oGet )
   @ 06, 64 GET aIn[3] PICTURE "999" WHEN {|| aIn[12] =='3' } VALID {||aIn[3]>0}
//4 - вид бумаги
  oGet := GETNEW(7,50,{|x| IF(x==NIL, aIn[4], aIn[4]:=(x==aPaper[1])),;
         IF(aIn[4],aPaper[1],aPaper[2])} ,"aIn[4]")
  oGet:reader := {|oGet| CondReader( oGet,,aPaper)}
  oGet:postBlock:={||IF(!aIn[4],;
  (aIn[5]:=0)=0.AND.(aIn[6]:=aIn[7]:=.F.),(aIn[5]:=IF(EMPTY(aIn[5]),58,aIn[5]))),;
  ;  // Изменение 3.60
  GetList[6]:display(),GetList[7]:display(),GetList[7]:display(),.T.}
  AADD(GetList,oGet)
//5 - строк на страницу
  @ 08, 50 GET aIn[5] WHEN {||aIn[4]} PICT '999'
//6 - проброс страницы
  oGet := GETNEW(09,50,{|x| IF(x==NIL, aIn[6], aIn[6]:=(x==aYes[1])),;
                            IF(aIn[6],aYes[1],aYes[2])} ,"aIn[6]")
  oGet:reader := {|oGet| CondReader( oGet,,)}
  oGet:preBlock:= {|oGet|aIn[4]}
  AADD(GetList, oGet)
  //7 - пауза
  oGet := GETNEW(10,50,{|x| IF(x==NIL, aIn[7], aIn[7]:=(x==aYes[1])),;
                            IF(aIn[7],aYes[1],aYes[2])} ,"aIn[7]")
  oGet:reader := {|oGet| CondReader( oGet,,)}
  oGet:preBlock:= {|oGet|aIn[4]}
  AADD(GetList, oGet)
  //11 - вид печати
  oGet := GETNEW(11,50,{|x| IF(x==NIL, aIn[11], aIn[11]:=(x==aVidP[1])),;
         IF(aIn[11],aVidP[1],aVidP[2])} ,"aIn[11]")
  oGet:reader := {|oGet| CondReader(oGet,,aVidP)}
  AADD(GetList,oGet)
//16 - выдача команд на принтер
  oGet := GETNEW(12,50,{|x| IF(x==NIL, aIn[16], aIn[16]:=(x==aYes[1])),;
                            IF(x == aYes[1],xEditPrintCode(GlobalTask,aIn[2],cId,{|x| IF(x != NIL,aIn[17] := x,aIn[17]) },{|x| IF(x != NIL,aIn[18] := x,aIn[18]) }),NIL),;
                            IF(aIn[16],aYes[1],aYes[2]) } ,"aIn[16]")
  oGet:postBlock:= {|| IF(LastKey() = K_ENTER .AND. aIn[16],xEditPrintCode(GlobalTask,aIn[2],cId,{|x| IF(x != NIL,aIn[17] := x,aIn[17]) },{|x| IF(x != NIL,aIn[18] := x,aIn[18]) }),NIL),.T. }
  oGet:reader := {|oGet| CondReader( oGet,,) }
  oGet:Display()
  AADD(GetList, oGet)
//8 - отступ слева
@ 13, 50 GET aIn[8] PICT '999'
//9 - разделитель
  oGet := GETNEW(14,50,{|x| IF(x==NIL, aIn[9], aIn[9]:=(x==aYes[1])),;
                            IF(aIn[9],aYes[1],aYes[2])} ,"aIn[9]")
  oGet:reader := {|oGet| CondReader( oGet,,)}
  AADD(GetList, oGet)
//10 - кол-во экземпляров
  @ 15, 50 GET aIn[10] VALID {|| aIn[10] >= 1 } PICT '99'
  AEval(GetList,{|Get| Get:Display() })
//13 - печать заголовка
   oGet := GETNEW(16, 50,  {|x| RotateBlock(x,aPHeads,'aIn[13]') } )
   oGet:Reader := { |oGet| RotateAndReader( oGet,aPHeads, 15, 18 ) }
   oGet:Display()
   oGet:PreBlock := {|| cHead = NIL }
   AADD( GetList, oGet )

//14
  @ 17, 50 GET aIn[22] PICTURE "99" WHEN {|| aIn[13] <> '0' }

//14 - нумерация страниц
  oGet := GETNEW(18,50,{|x| IF(x==NIL, aIn[14], aIn[14]:=(x==aYes[1])),;
                            IF(aIn[14],aYes[1],aYes[2])} ,"aIn[14]")
  oGet:reader := {|oGet| CondReader( oGet,,) }
  oGet:PreBlock := {|| lNumStr = NIL .OR. lNumStr }
  oGet:Display()
  AADD(GetList, oGet)
  @ 18, 70 GET aIn[15] PICTURE "999" WHEN {|| aIn[14] } VALID {|| aIn[15] > 0 }
//15 - итоги на странице
  oGet := GETNEW(19,50,{|x| IF(x==NIL, aIn[19], aIn[19]:=(x==aYes[1])),;
                            IF(aIn[19],aYes[1],aYes[2])} ,"aIn[19]")
  oGet:reader := {|oGet| CondReader( oGet,,) }
  oGet:PreBlock := {|| lSumKol = NIL .OR. lSumKol }
  oGet:Display()
  AADD(GetList, oGet)

// - windows
  oGet := GETNEW(20,50,{|x| IF(x==NIL, aIn[21], aIn[21]:=(x==aYes[1])),;
                            IF(aIn[21],aYes[1],aYes[2])} ,"aIn[21]")
  oGet:reader := {|oGet| CondReader( oGet,,)}
  AADD(GetList, oGet)
  oGet:Display()

  SET CURSOR ON
  READ
  SET CURSOR OFF

  PR_DEVICE:=  TRIM(aIn[1])
  PR_TYPE:=aIn[2]
  PR_WIDTH:=aIn[3]
  PR_PAPER:=aIn[4]
  PR_STR:=aIn[5]
  PR_PROBROS:=aIn[6]
  PR_PAUSE:=aIn[7]
  PR_PSEVDO:=aIn[11]
  PR_WTYPE := aIn[12]
  PR_OFFSET:=aIn[8]
  PR_DBL_SPACE:=aIn[9]
  PR_KOL:=aIn[10]

  PR_HEAD   := aIn[13]
  PR_NUMSTR := aIn[14]
  PR_BEGSTR := aIn[15]

  PR_LSUM := aIn[19]
// Изменение 3.60
  PR_PTYPE := aIn[20]
  PR_WIN    := aIn[21]

  PR_HEAD_LINE := aIn[22]

  IF PR_BCODE != aIn[17] .OR. PR_ECODE != aIn[18] .OR. PR_LCODE != aIn[16]
    SaveStation({{"PRN_LCODE",aIn[16]},{"PRN_BCODE",aIn[17]},{"PRN_ECODE",aIn[18]}})
    PR_BCODE := aIn[17]
    PR_ECODE := aIn[18]
    PR_LCODE := aIn[16]
  ENDIF


  VWidth(ROUND(PR_WIDTH/m->nMassh,0))
  RestSet(aSet)
  RestSetKey(aSetKeys)
  SETKEY(K_RETURN,sF10)

  ReferPop()

RETURN
//---------------------------------------------------------------------------//
                  FUNCTION xEditPrintCode(GlobalTask,cTypePrint,cId,bPreCode,bPostCode)
//---------------------------------------------------------------------------//
// Организует редактирование кодов принтера
// до и после печати в соотв. с идентификационным кодом
// cTypePrint - тип принтера
// cId - уникальный код
// bPredCode  - блок кода доступа к пред.строке
// bEndCode  - блок кода доступа к пост.строке
PLOCAL cPrintCode
PLOCAL cNext, bakSelect := ALIAS(), aKey := SaveSetKey(), aSet := SaveSet()
PLOCAL cNameDbf,cNameCdx,nVib := 1,i := 1

PLOCAL nLeftBrd := 23, aTSet
PLOCAL aBlockCols:={{{|| STR(__PRINT->NOM_PP,2,0) },1},{{|| __PRINT->CODE },4},{{|| EVAL(m->bNameCode,__PRINT->CODE) },10}}
PLOCAL nTop:=5,nBottom:=MaxRow()-6,cColHead:=;
      {" Ном.Код                            ",;
       " п/п ком.       Наименование        "}
PLOCAL aHeads:= { {"Номер п/п.............:","NOM_PP"},;
                 {"Код команды...........:","CODE"},;
                 {"Наименование команды..:",""};
                }

PLOCAL aPict:={"99","XXXXX","@S25"}, aRefer := {,"_RefCodeP",}
PLOCAL aSortSeek
PLOCAL cCurProc,aWhen := {{|oGet| QHelp( ,, 1,,"NOM_PP") },,{|| .F. }},aValid,nUniMode:=0,bDelInit,bScrInit
PLOCAL aPHeads:={"Настройка кодов принтера", {"Ном.п/п","NOM_PP","NN"},{"Код ком.","CODE","XXXXX"},{"Наименование ком.","EVAL(m->bNameCode,__PRINT->CODE)","XXXXXXXXXXXXXXXXXXXXXXXXX"} }
PLOCAL aGetBlock := {,,{|| EVAL(m->bNameCode,aIn[2]) }}, lNotUse
PLOCAL bMaxNomPP := {|cBakOrder,bakRec,nRet| __PRINT->(bakRec := RECNO(),cBakOrder := ORDSETFOCUS("TAG_NOMPP"),dbGoBottom(),nRet := Next(__PRINT->NOM_PP),dbGoTo(bakRec),ORDSETFOCUS(cBakOrder)),nRet }
PLOCAL aSaveRec,_nNom,bSavePPCode := {|cBakOrder,bakRec| _nNom := 1,aSaveRec := {},__PRINT->(bakRec := RECNO(),cBakOrder := ORDSETFOCUS("TAG_NOMPP"),DBEVAL({|| AADD(aSaveRec,{_nNom++,Recno()}) }),AEVAL(aSaveRec,{|x| dbGoto(x[2]),IF(RecLock(),(FIELD->NOM_PP := x[1],dbUnLock()),NIL) }),dbGoTo(bakRec),ORDSETFOCUS(cBakOrder)) }
PLOCAL bPreGet, bPost := {|| EVAL(bSavePPCode) }
PLOCAL nW := WSELECT(0)

ReferPush()

PRIVATE bNameCode := {|x| RefC->(dbSeek(Upper(x))),REFC->NAME }


IF (lNotUse := SELECT("REFC") != 0) .OR. NetUse('REFC','PRN_CODE')

Busy(.T.,"Подготовка структуры")
SELECT REFC
SET FILTER TO !EMPTY(FieldGet(FieldPos('PRINT'+LTRIM(STR(VAL(cTypePrint),2,0)))))
GO TOP

  SetKey(K_F10,{|| 0 })
  SetKey(K_ESC,NIL)
  SetKey(K_F4,NIL)
  SetKey(K_F8,NIL)
  SetKey(K_F9,{|| NIL })
  SetKey(K_SH_F6,{|| NIL })

  SetKey(K_TAB,{|aSet,aKey,bakRec,cBakOrder|;
      aSet := SaveSet(),;
      aKey := SaveSetKey(),;
      __PRINT->(bakRec := Recno(),cBakOrder := ORDSETFOCUS("TAG_CODE")),;
      SetKey(K_INS,{|| IF(__PRINT->(dbSeek(UPPER(REFC->CODE))),__PRINT->(IF(RecLock(),(dbDelete(),dbUnlock()),NIL)),__PRINT->(IF(AddRec(),(__PRINT->CODE := REFC->CODE,__PRINT->NOM_PP := EVAL(bMaxNomPP),dbUnlock()),NIL))),__Keyboard(CHR(K_DOWN)) }),;
      SetKey(K_F9,{|| NIL }),;
      SetKey(K_F8,{|| NIL }),;
      SetKey(K_SH_F6,{|| NIL }),;
      SetKey(K_TAB,{|| 0 }),;
      DispBox(8, 26, MaxRow()-2, 61, "╔═╗║╝═╚║ ", COL_REFER),;
      ShadowBox("", 8, 26, MaxRow()-2, 61, COL_REFER, "╔═╗║╝═╚║" ),;
      SetPos(8,28),;
      DispOut("[ Выбор кодов принтера ]",COL_REFER),;
      SetPos(MaxRow()-4,28),DispOut("────────────────────────────────",COL_REFER),;
      SetPos(MaxRow()-3,28),DispOut("    Ins : Выбор  Esc : Выход    ",COL_REFER),;
      SetColor(COL_REFER),;
      REFC->(dbGoTop(),;
      IF( GlobalTask = "07",(;
          SetPos(9,28),DispOut(' Код        Наименование        ',COL_REFER),;
         SetPos(10,28),DispOut("────────────────────────────────",COL_REFER),;
         Qbrowse(11,27,MaxRow()-5,60,{{{||FIELD->Code},27+1},{{||FIELD->Name},27+7},{{|| IF(__PRINT->(dbSeek(UPPER(REFC->CODE))),'√',' ')},27+33}},COL_REFER);
                             ),;
      InitList(9,MaxRow()-5,' Код        Наименование          ',{{{||FIELD->Code},1},{{||FIELD->Name},7},{{|| IF(__PRINT->(dbSeek(UPPER(REFC->CODE))),'√',' ')},33}},,,,,,,,,,,,,,,,,27,,,COL_REFER);
         );
            ),;
      EVAL(bSavePPCode),;
      __PRINT->(dbGoTo(bakRec),ORDSETFOCUS(cBakOrder)),;
      RestSet(aSet),;
      RestSetKey(aKey),2;
      })


    //  FRAME("[ Выбор кодов принтера ]",8,26,MaxRow()-2,61,COL_REFER,2,.T.,.T.),;

MakeRefer( '_RefCodeP', 'Справочник команд принтера', 1, ;
             {'Код','Наименование'}, {3,35,15},      ;
             COL_REFER, {'CODE'}, {'aIn[2]'}, 'UPPER(aIn[2])', ;
             {{|| FIELD->CODE },{|| FIELD->NAME }},             ;
            {{'','Код :','CODE','UPPER(aIn[1])','@K','!EMPTY(aIn[1])'} },;
             ,,,,,,,,,,"F2 : Справочник команд принтера";
          )

SELECT(0)
DBCREATE((cNameDbf := TEMPFILE(MemVar->GlobalTmpPath, "DBF")),;
          {             ;
           { 'NOM_PP',  'N',  2, 0 }, ;
           { 'CODE',   'C',  5, 0 } ;
           };
         )
cNameCdx := LEFT(cNameDbf,AT(".",cNameDbf))+"IDX"
NetUseExc("__PRINT",cNameDbf )
SELECT __PRINT
INDEX ON STR(FIELD->NOM_PP,2,0) TAG TAG_NOMPP TO (cNameCdx)
//ADDITIVE
INDEX ON UPPER(FIELD->CODE) TAG TAG_CODE TO (cNameCdx)
//ADDITIVE
SET INDEX TO (cNameCdx)
Busy(.F.)


WHILE (nVib := NoOrYes({" Настройка кодов принтера выдаваемых - "}, nVib,   {" До печати "," После печати "," Завершить "}, 10),nVib) != 0 .AND. nVib != 3

  Busy(.T.,"Загрузка данных")
  cPrintCode := BEFORATNUM("}",AFTERATNUM("{"+GlobalTask+cTypePrint+cId+":",EVAL(IF(nVib = 1,bPreCode,bPostCode)),1),1)

  SELECT __PRINT
  ZAP

  i := 1

  TokenInit( @cPrintCode, ",")
  WHILE !TokenEnd()
   IF !EMPTY((cNext := TokenNext(@cPrintCode)))
     APPEND BLANK
     __PRINT->NOM_PP := i++
     __PRINT->CODE := cNext
   ENDIF
  END


  Busy(.F.)

  SELECT __PRINT
  GO TOP

  aTSet := SaveSet()
  DispBox(4, 22, MaxRow()-5, 59, "╔═╗║╝═╚║ ", COL_BROWSE)
  ShadowBox("", 4, 22, MaxRow()-5, 59, COL_BROWSE, "╔═╗║╝═╚║" )
  SetPos(4,24)
  DispOut("[ Настройка кодов принтера ]",COL_BROWS1)
  SetColor(COL_BROWSE)

  IF GlobalTask = "07"
    SetPos(5,23);DispOut(" Ном.Код                            ",COL_HEADS)
    SetPos(6,23);DispOut(" п/п ком.       Наименование        ",COL_HEADS)
    SetPos(7,23);DispOut("────────────────────────────────────",COL_HEADS)
    ScrTitul(MaxRow(),"TAB:Выбор F8:Удалить F10:Запись",COL_REFER)
    Qbrowse(8,23,MaxRow()-6,58,AEVAL(ACLONE(aBlockCols),{|x| x[2] += nLeftBrd }),COL_BROWSE)
  ELSE
    ScrTitul(MaxRow(),"┘:Правка TAB:Выбор F4:Добавить F6,ALT-F6:Фильтр F8:Удалить F10:Запись",COL_REFER)
    InitList(nTop,nBottom,cColHead,aBlockCols,cCurProc,aHeads,aRefer,aPict,;
             aWhen,aValid,nUniMode,bDelInit,bScrInit,aSortSeek,aPHeads,bPost,,aGetBlock,,,nLeftBrd,,,,,bPreGet)
  ENDIF
  RestSet(aTSet)

  cPrintCode := "{"+GlobalTask+cTypePrint+cId+":"
  DBEVAL({|| cPrintCode += TRIM(__PRINT->CODE)+"," })
  cPrintCode := LEFT(cPrintCode,LEN(cPrintCode)-1)+"}"

  IF cPrintCode != "{"+GlobalTask+cTypePrint+cId+":"+"}" .AND. EVAL(IF(nVib = 1,bPreCode,bPostCode)) != cPrintCode .AND. (LastKey() = K_F10 .OR. YesOrNo("Сохранить настройку ?",,,,,,COL_YES_OR_NO))
     EVAL(IF(nVib = 1,bPreCode,bPostCode),cPrintCode)
  ENDIF

ENDDO

SetLastKey(K_DOWN)
dbCloseArea()
FERASE(cNameDbf)
FERASE(cNameCdx)

ENDIF

IF !lNotUse
  SELECT REFC
  dbCloseArea()
ELSE
  SELECT REFC
  SET FILTER TO
ENDIF

SELECT (bakSelect)
RestSetKey(aKey)
RestSet(aSet)
WSELECT(nW)
ReferPop()

RETURN NIL

STATIC FUNCTION ControlCode()
PLOCAL nArea:=SELECT()
PLOCAL cBoxHead:=' Команды принтера '
PLOCAL cLastColor:=SETCOLOR(COL_REFER)
PLOCAL nTop:=3,nLeft:=4,nBottom:=MaxRow()-4,nRight:=40,n
PLOCAL sRest:=SAVESCREEN(nTop,nLeft,nBottom+2,nRight+2)
PLOCAL sRest24:=SAVESCREEN(MAXROW(),0,MAXROW(),MAXCOL())
PLOCAL cHead:=;
' Код        Наименование       '
*12345 1234567890123456789012345
*1234567890123456789012345678901234567890123456789012345678901234567890123456789
PLOCAL aBlockCols:={{{||FIELD->Code},nLeft+2},{{||FIELD->Name},nLeft+8},;
{{||IF((n:=ASCAN(m->aCode,{|x|x=FIELD->Code}))>0,'√',' ')},nLeft+34}}
PLOCAL sF10:=SETKEY(K_F10,NIL)
PLOCAL sRet:=SETKEY(K_RETURN,{||CoCode()})
PRIVATE aCode:={}
SELECT RefC
SET FILTER TO !EMPTY(&('PRINT'+LTRIM(STR(VAL(aIn[2]),2,0))))
GO TOP
ScrTitul(MaxRow(),'Непосредственная выдача команд на принтер')
@ nTop,nLeft CLEAR TO nBottom,nRight
@ nTop,nLeft       TO nBottom,nRight
@ nBottom-2,nLeft SAY '├'+REPLICATE('─',nRight-nLeft-1)+'┤'
@ nTop,nLeft+2 SAY cBoxHead
@ nTop+1,nLeft+1 SAY cHead
@ nBottom-1,nLeft+2 SAY 'Enter:Выдача команды Esc:Выход'
QPush()
Qbrowse(nTop+2,nLeft+1,nBottom-3,nRight-1,aBlockCols,COL_REFER)
QPop()
RESTSCREEN(nTop,nLeft,nBottom+2,nRight+2,sRest)
RESTSCREEN(MAXROW(),0,MAXROW(),MAXCOL(),sRest24)
SET FILTER TO
SELECT (nArea)
SETKEY(K_F10,sF10)
SETKEY(K_RETURN,sRet)
RETURN(NIL)

STATIC FUNCTION CoCode()
PLOCAL cCode:=Refc->(FIELDGET(VAL(PR_TYPE)+2))
PLOCAL setPrinter:=set(_SET_PRINTER)
PLOCAL setConsole:=set(_SET_CONSOLE)
PLOCAL setPrintFile:=set(_SET_PRINTFILE)
set(_SET_PRINTER, .F.)
set(_SET_CONSOLE, .F.)
set(_SET_PRINTFILE,TRIM(PR_DEVICE))
set(_SET_PRINTER, .T.)

// создадим массив на случай печать через PBestPrn
//AADD( aPsevdoCode, ALLTRIM(Refc->(FIELDGET(1)) ) )

IF !EMPTY(cCode).AND.Line2Prt(&(cCode),.F.,'Спецкод')
   set(_SET_PRINTER,.F.)
   set(_SET_CONSOLE,setConsole)
   set(_SET_PRINTFILE,TRIM(setPrintFile))
   set(_SET_PRINTER,setPrinter)

   AADD(m->aCode,FIELD->Code)
   IF UPPER(FIELD->Code)='17CPI'.OR.UPPER(FIELD->Code)='12CPI'.OR.UPPER(FIELD->Code)='10CPI'
      cCpi:=cCpi0:=FIELD->Code //Непосредственно заданный код степени сжатия
   ENDIF
   RETURN(3)
ENDIF
set(_SET_PRINTER,.F.)
set(_SET_CONSOLE,setConsole)
set(_SET_PRINTFILE,TRIM(setPrintFile))
set(_SET_PRINTER,setPrinter)
RETURN(1)

// Изменение 3.22
STATIC FUNCTION GetFileName(cDefName, x, cColor,cHeads)
PLOCAL sWin, sColor
 x:=IF(x==NIL, 4, x)
 sWin:=SaveScreen(x, 0, x+3, MAXCOL())
 cColor:=IF(cColor==NIL, 'n/w,gr+/n', cColor)
 cDefName:=IF(cDefName==NIL, UPPER(DISKNAME()+':'+DIRNAME()+'\'), cDefName)
 cDefName:=STRTRAN(cDefName,'\\','\')
 sColor:=SETCOLOR(cColor)
 ShadowBox(IF(cHeads = NIL,' Записать на диск как ... ',cHeads), x, 10, x+2, 70, cColor)
 cDefName:=PADR(cDefName,45)
 @ x+1,12 SAY 'Имя файла:' GET cDefName PICTURE "@KS128"
 SETCURSOR(1); READ ; SETCURSOR(0)
 If LASTKEY() == K_ESC
   cDefName:=''
 EndIF
 RestScreen(x, 0, x+3, MAXCOL(),sWin)
 SETCOLOR(sColor)
RETURN TRIM(cDefName)

STATIC FUNCTION GetAltPPar(cDefName, cDefPrim)
PLOCAL sWin, sColor, x, cColor
 x:= 4
 sWin:=SaveScreen(x, 0, x+4, MAXCOL())
 cColor:='n/w,gr+/n'
 cDefName:=IF(cDefName==NIL, UPPER(DISKNAME()+':'+DIRNAME()+'\'), cDefName)
 cDefName:=STRTRAN(cDefName,'\\','\')
 sColor:=SETCOLOR(cColor)
 ShadowBox(' Параметры готового отчета ', x, 10, x+3, 70, cColor)
 cDefName:=PADR(cDefName,70)
 @ x+1,12 SAY 'Имя файла......:' GET cDefName PICTURE "@KS39"
 @ x+2,12 SAY 'Название отчета:' GET cDefPrim PICTURE "@KS39"
 SETCURSOR(1); READ ; SETCURSOR(0)
 If LASTKEY() == K_ESC
   cDefName:=''
 EndIF
 RestScreen(x, 0, x+4, MAXCOL(),sWin)
 SETCOLOR(sColor)
RETURN TRIM(cDefName)

STATIC FUNCTION lFileInit(cFname)

IF (nHandle := fopen(cFname,2)) !=  -1
    nMaxPos:=GetLast()
    GetFirst()
ENDIF
#ifndef __HARBOUR__
RETURN nHandle != -1
#else
RETURN nHandle != -1.AND.(nMaxPos>0.OR.(TYPE("lFromMaker")="L".AND.lFromMaker))
#endif


//--------------------------------------------------------------------------//
                FUNCTION LongBufferRead(cLongBuffer,nEol)
//--------------------------------------------------------------------------//
// аналог fread только без указания длины буфера - читает до первого CRLF
// (хотя возвращает длинную строку длинной > позиции CRLF)
// с коррекцией MAX_LINE_LEN и nMaxCol если позиция CRLF больше
// возвращет кол-во прочитанных байт
// и по ссылкам cLongBuffer и nEol
  PLOCAL nRead, nBRead := MAX_LINE_LEN, nLongRead := 0, cBuffer
  nBRead := MAX_LINE_LEN
  cBuffer :=SPACE(nBRead)
  cLongBuffer := ""
  // Скорректируем буффер если переполнение строки
  WHILE (nRead := fread(nHandle, @cBuffer, nBRead)) > 0
    cLongBuffer += LEFT(cBuffer,nRead)
    nLongRead += nRead
    IF nRead = nBRead .AND. !(CRLF $ cBuffer)
      nBRead := MAX_LINE_LEN
      cBuffer := SPACE(nBRead)
    ELSE
      EXIT
    ENDIF
  ENDDO
  MAX_LINE_LEN := MAX(MAX_LINE_LEN,(nEol := AT(CRLF,cLongBuffer))+4)
  nMaxCol := MAX(nMaxCol,LEN(REMRIGHT(REMRIGHT(LEFT(cLongBuffer,nEol-1),255),32)))
  // V@
  xMaxCol := Max(xMaxCol,AT(CRLF,cLongBuffer))
RETURN nLongRead

/** LOGICAL lfreadln() -> TRUE if succesful
*  PURPOSE: Чтение следующей строки файла в "cBuffer".
*   Функция возвращает .T. если строка считана и .F. в
*   противном случае (что указывает на EOF).
*   Кроме того если указан параметр nWhilePos возвращается .F.
*   если позиция в файле превысила этот параметр
*   Вызывающая программа должна передавать cBuffer по ссылке
*  PARAMS:  nHandle     -file handle
*           cBuffer     -pointer to buffer
*           [nMaxLen]   -max length of the string read
*           [nWhilePos] -file position where RETURN must be FALSE
*              (for using in selected block printing)
*  EXTERNAL(STATIC): nHandle, nLinePos,nLinePos0
**/
STATIC FUNCTION lfreadln(nHandle, cBuffer, nMaxLen, nWhilePos)
  PLOCAL nEol, nRead, nSaveFpos

  //Сначала сохраним текущий указатель файла
  nSaveFpos:= FTELL(nHandle)
  If nWhilePos != NIL
    If nSaveFpos > nWhilePos
      // We reached end of selected block
      RETURN .F.
    EndIF
  EndIF

  nRead := LongBufferRead(@cBuffer,@nEol)

  IF nEol != 0
    //Удаляем все CRLF из строки
    cBuffer:= SUBSTR(cBuffer, 1, nEol - 1)+SPACE(MAX_LINE_LEN-nEol)
    //Устанавливаем указатель файла на следующую строку
    nLinePos:=fseek(nHandle, nSaveFPos + nEol + 1, FS_SET)
    nLinePos0:=nSaveFPos
  ENDIF
  IF nEol=0.OR.CHR(0)$cBuffer.OR.cBuffer=CHR(26)
     nRead:=0
     nLinePos:=fseek(nHandle, nSaveFPos, FS_SET)
     nLinePos0:=nSaveFPos
  ENDIF
RETURN nRead != 0

STATIC FUNCTION GetFirst
 fseek(nHandle, nTopPos, FS_SET)
 nLinePos:=FTELL(nHandle)
 lfreadln(nHandle, @cline)
 fseek(nHandle, nTopPos, FS_SET)
RETURN NIL

STATIC FUNCTION GetLast
 fseek(nHandle, 0, FS_END)
 lGoPrevLn()
RETURN FTELL(nHandle)

STATIC FUNCTION skipper(n)
PLOCAL nSkipped := 0
 IF n > 0
   DO WHILE nSkipped != n .AND. lGoNextLn()
     nSkipped++
     nRowAct++
     IF nRowAct>oTbr:nBottom
        nRowAct:=oTbr:nBottom
     ENDIF
   ENDDO
 ELSE
   DO WHILE nSkipped != n .AND. lGoPrevLn()
     nSkipped--
     nRowAct--
     IF nRowAct<oTbr:nTop
        nRowAct:=oTbr:nTop
     ENDIF
   ENDDO
 ENDIF

RETURN nSkipped

STATIC FUNCTION lGoNextLn()
PLOCAL nSavePos := FTELL(nHandle), cBuff := "", lMoved, nNewPos
 nNewPos :=fseek(nHandle, LEN(TRIM(cLine)) + 2, FS_RELATIVE)
 IF lfreadLn(nHandle, @cBuff)
     lMoved := .T.
     cLine := cBuff
     nLinePos:=fseek(nHandle, nNewPos, FS_SET)
 ELSE
     lMoved := .F.
     nLinePos:=fseek(nHandle, nSavePos, FS_SET)
 ENDIF
RETURN lMoved

STATIC FUNCTION lGoPrevLn()
PLOCAL nMaxRead, nNewPos, lMoved, cBuff, nWhereCrLf
 nLinePos:=FTELL(nHandle)
 IF nLinePos == 0.OR.nLinePos<=nTopPos
   lMoved := .F.
 ELSE
   //Найти пpедыдущий CRLF (считать максимально доступный блок слева)
   nMaxRead := MIN(MAX_LINE_LEN, nLinePos)
   nNewPos := fseek(nHandle, -nMaxRead, FS_RELATIVE)
   cBuff := space(nMaxRead)
   fread(nHandle, @cBuff, nMaxRead)
   cBuff:=SUBSTR(cBuff,1,LEN(cBuff)-2)
   WHILE RIGHT(cBuff,1)=CHR(0)
      nNewPos := fseek(nHandle, -1, FS_RELATIVE)
      fread(nHandle, @cBuff, nMaxRead)
      cBuff:=SUBSTR(cBuff,1,LEN(cBuff)-2)
   ENDDO

   nWhereCrLf := rat(CRLF, cBuff)
   IF nWhereCrLf != 0
     cBuff:=SUBSTR(cBuff,nWhereCrLf+2)
   ENDIF
   nLinePos := nLinePos-LEN(cBuff)-2
   lMoved := .T.
   cLine :=cBuff+SPACE(MAX_LINE_LEN-LEN(cBuff))
   fseek(nHandle, nLinePos, FS_SET)
 ENDIF
RETURN lMoved

FUNCTION HelpMess(cMess,nRow,nCol)
PLOCAL cBoth,cBordChar,cAttr               // символ бордера и его атрибут
  nRow:=IF(nRow==NIL, MaxRow()-1, nRow)
  nCol:=IF(nCol==NIL, 2 , nCol)
  cBoth:=ScreenStr(nRow,nCol-1,1)
  cBordChar:=SubStr(cBoth,1,1); cAttr:=SubStr(cBoth,2,1)
  IF cMess == NIL .OR. Empty(cMess)      // погасить
    @ nRow,nCol SAY REPLICATE(cBordChar, 37) COLOR NToColor(ASC(cAttr))
  ELSE
    // выводим цветом w+/на старом фоне
    @ nRow,nCol SAY ' '+cMess+' ' COLOR NToColor(INT(ASC(cAttr)/16)*16+15)
  ENDIF
RETURN .T.

STATIC FUNCTION SetDispArea()
PLOCAL x0,y0,lMore:=.T.
PLOCAL xz0:=xz,yz0:=yz,nOffSet,i
PLOCAL sRest0:=SAVESCREEN(nY1-1,0,nY1-1,MAXCOL())
PLOCAL sRest:=SAVESCREEN(MAXROW(),0,MAXROW(),MAXCOL())
@ nY1-1,nX1 SAY PADC(' Фиксация заголовка ',nX2-nX1+1,'─') COLOR COL_VBORDER
ScrTitul(MaxRow(),'F1:Помощь '+CHR(24)+CHR(25)+CHR(26)+CHR(27)+;
':Установка границ ┘:Фиксация Alt-F5:Отмена фиксации Esc:Выход')
IF xz+yz>0
   IF yz>0
      COLORWIN(1,1,yz,MAXCOL()-1,COL_HEAD)
   ELSEIF xz>0
      COLORWIN(1,1,MAXROW()-2,xz,COL_HEAD)
   ENDIF
ENDIF
WHILE lMore
   INKEY(0)
   x0:=xz;y0:=yz
   DO CASE
      CASE LASTKEY()=K_F1
      DisplayHelp(3)
      LOOP
      CASE LASTKEY()=K_DOWN
      yz++
      CASE LASTKEY()=K_UP
      yz--
      CASE LASTKEY()=K_RIGHT
      xz++
      CASE LASTKEY()=K_LEFT
      xz--
      CASE LASTKEY()=K_ESC.OR.LASTKEY()=K_F5.OR.;
      LASTKEY()=K_ENTER.OR.LASTKEY()=K_ALT_F5
      lMore:=.F.
   ENDCASE
   IF lMore
      xz:=IF(xz<0,0,xz)
      yz:=IF(yz<0,0,yz)
      xz:=IF(xz>MAXCOL()-1,MAXCOL()-1,xz)
      yz:=IF(yz>MAXROW()-3,MAXROW()-3,yz)
      IF xz+yz>0
         IF yz>0.AND.(LASTKEY()=K_UP.OR.LASTKEY()=K_DOWN)
            COLORWIN(1,1,yz,MAXCOL()-1,COL_HEAD)
         ELSEIF xz>0.AND.(LASTKEY()=K_RIGHT.OR.LASTKEY()=K_LEFT)
            COLORWIN(1,1,MAXROW()-2,xz,COL_HEAD)
         ENDIF
      ELSE
         COLORWIN(1,1,1,1,COL_VIEW)
      ENDIF
      IF yz<y0
         COLORWIN(y0,xz+1,y0,MAXCOL()-1,COL_VIEW)
      ELSEIF xz<x0
         COLORWIN(yz+1,x0,MAXROW()-2,x0,COL_VIEW)
      ENDIF
   ENDIF
ENDDO
IF LASTKEY()=K_ESC
   xz:=xz0
   yz:=yz0
ELSEIF LASTKEY()=K_ALT_F5
   xz:=yz:=0
   aFixed:={}
   nTopPos:=0
ENDIF
IF LASTKEY()!=K_ESC
   nTopPos:=0
   nOffSet:=nRowAct-nY1
   FOR i:=1 TO nOffSet
   lGoPrevLn()
   NEXT
   aFixed:={}
   FOR i:=1 TO yz
   AADD(aFixed,cLine)
   lGoNextLn()
   NEXT
   lGoNextLn()
   lGoPrevLn()
   nTopPos:=FTELL(nHandle)
   nLineNum0:=nLineNum-nOffSet+yz
   IF nOffSet>yz
      FOR i:=1 TO yz-nOffSet
      lGoNextLn()
      NEXT
   ELSE
      FOR i:=1 TO nOffSet-yz
      lGoPrevLn()
      NEXT
   ENDIF
   nLinePos:=FTELL(nHandle)
ENDIF
oTbr:nTop+=yz-yz0
nLineNum+=yz-yz0-nRowAct+1
nRowAct+=yz-yz0-oTbr:nTop
SetX()
RESTSCREEN(nY1-1,0,nY1-1,MAXCOL(),sRest0)
RESTSCREEN(MAXROW(),0,MAXROW(),MAXCOL(),sRest)
IF yz>0
   COLORWIN(1,1,yz,MAXCOL()-1,COL_VIEW)
ENDIF
RETURN NIL


STATIC FUNCTION SetX()
PLOCAL oTbc1,oTbc2
IF xz>0
   oTbc1:= tbColumnNew(, {|| ;
   LEFT(cLine,xz)})
   oTbc1:colorblock:=NIL
   oTbc1:width := xz
   oTbc2:= tbColumnNew(, {|| ;
   SUBSTR(cLine, nHorOffSet+xz+1,nX2-nX1+1-xz)})
   oTbc2:colorblock:={|| DispSelected()}
   oTbc2:width :=nX2-nX1-xz
   oTbr:setColumn(1,oTbc1)
   IF oTbr:colCount<2
      oTbr:addColumn(oTbc2)
   ELSE
      oTbr:setColumn(2,oTbc2)
   ENDIF
   oTbr:colPos:=2
ELSE
   oTbc1:= tbColumnNew(, {|| ;
   SUBSTR(cLine, nHorOffSet, nX2-nX1+1)})
   oTbc1:colorblock:={|| DispSelected()}
   oTbc1:width := nX2-nX1+1
   oTbr:setColumn(1,oTbc1)
   IF oTbr:colCount>1
      oTbr:delColumn(2)
   ENDIF
   oTbr:colPos:=1
ENDIF
RETURN(NIL)

STATIC FUNCTION DispFixed()
PLOCAL cLastColor:=SETCOLOR(COL_VIEW)
PLOCAL nRow:=1
IF yz>0
   IF xz>0
      AEVAL(aFixed,{|x|DISPOUTAT(nRow++,nX1,LEFT(x,xz)+' '+SUBSTR(x,nHorOffSet+xz+1,nX2-nX1+1-xz))})
   ELSE
      AEVAL(aFixed,{|x|DISPOUTAT(nRow++,nX1,SUBSTR(x,nHorOffSet,nX2-nX1+1))})
   ENDIF
ENDIF
SETCOLOR(cLastColor)
RETURN(NIL)

STATIC FUNCTION Edit(fname)
PLOCAL nOffSet:=nRowAct-nY1-IF(yz=0,0,yz+1),i
PLOCAL nCol0:=COL(),nRow0:=ROW()
PLOCAL nPos0
PLOCAL cEdit:='',cEdit0
PLOCAL cLastColor:=SETCOLOR(COL_EDIT)
PLOCAL lFull:=(nMaxPos<=MAX_EDIT*1024)
#ifndef __HARBOUR__
PLOCAL sRet:=SETKEY(K_RETURN,{||Keyb(K_CTRL_W)})
#endif
PLOCAL sEsc:=SETKEY(K_ESC,{||Keyb(K_CTRL_W)})
PLOCAL sDel:=SETKEY(K_DEL,IF(lFull,NIL,{||NIL}))
PLOCAL sBS:=SETKEY(K_BS,IF(lFull,NIL,{||NIL}))
PLOCAL sCtrlY:=SETKEY(K_CTRL_Y,IF(lFull,NIL,{||NIL}))
PLOCAL sCtrlT:=SETKEY(K_CTRL_T,IF(lFull,NIL,{||NIL}))
PLOCAL sCtrlB:=SETKEY(K_CTRL_B,IF(lFull,NIL,{||NIL}))
PLOCAL sCtrlV:=SETKEY(K_CTRL_V,IF(lFull,NIL,{||NIL}))
PLOCAL sPgUp:=SETKEY(K_PGUP,IF(lFull,NIL,{||NIL}))
PLOCAL sPgDn:=SETKEY(K_PGDN,IF(lFull,NIL,{||NIL}))
PLOCAL sCtrlPgUp:=SETKEY(K_CTRL_PGUP,IF(lFull,NIL,{||NIL}))
PLOCAL sCtrlPgDn:=SETKEY(K_CTRL_PGDN,IF(lFull,NIL,{||NIL}))
PLOCAL sAltZ:=SETKEY(K_ALT_Z,NIL)
PLOCAL sAltK:=SETKEY(K_ALT_K,NIL)
PLOCAL sAltL:=SETKEY(K_ALT_L,NIL)
PLOCAL sF1:=SETKEY(K_F1,{||DisplayHelp(IF(lFull,4,2))})
PLOCAL sCtrlZ:=SetKey(K_CTRL_Z,{||MAGCALC( ProcName(), ProcLine(), ReadVar() )})
PLOCAL sCtrlIns := SetKey(K_CTRL_INS,{|| __KeyBoard(CHR(251)) })
PLOCAL sRest0:=SAVESCREEN(nY1-1,0,nY1-1,MAXCOL())
PLOCAL sRest:=SAVESCREEN(MaxRow(),0,MaxRow(),MAXCOL())
PLOCAL lCancel:=SETCANCEL(.F.)


@ nY1-1,nX1 SAY PADC(' Редактирование '+IF(lFull,'документа','фрагмента '),;
nX2-nX1+1,'─') COLOR COL_VBORDER
ScrTitul(MaxRow(),'┘:Завершить Alt'+Chr(24)+Chr(25)+Chr(26)+Chr(27)+':Символы рамок F12:Одинарн/Двойные')

IF lFull
   FSEEK(nHandle,0,FS_SET)
   nPos0:=FTELL(nHandle)
   GetFirst()
   cEdit+=TRIM(cLine)+CRLF
   WHILE lGoNextLn()
      cEdit+=TRIM(cLine)+CRLF
   ENDDO
   nOffSet:=0
   nLineNum:= 1
   nRow0:=nRowAct:=nY1
   nCol0:=nX1
   UpdRow(1,1)

ELSE
   FOR i:=1 TO nOffSet
   lGoPrevLn()
   NEXT
   nPos0:=FTELL(nHandle)
   FOR i:=1 TO nY2-nY1+1
   cEdit+=TRIM(cLine)+CRLF
   IF !lGoNextLn()
      EXIT
   ENDIF
   NEXT
ENDIF
ALTD(0)



draw(.T.)

cEdit0:=cEdit
cEdit:=STRTRAN(cEdit,CHR(9),space(4))  //HARBOUR вставляет TAB!!!

SETCURSOR(1)

cEdit:=MEMOEDIT(cEdit,nY1+yz,nX1+xz,nY2,nX2,.T.,'Func1View',nMaxCol+30,;
,nY1+nOffSet,nHorOffSet-1,nY1+nOffSet,0)

draw(.F.)
SETKEY(K_ESC,sEsc)
SETKEY(K_DEL,sDel)
SETKEY(K_BS,sBS)
SETKEY(K_CTRL_Y,sCtrlY)
SETKEY(K_CTRL_Z,sCtrlZ)
SETKEY(K_CTRL_T,sCtrlT)
SETKEY(K_CTRL_B,sCtrlB)
SETKEY(K_CTRL_V,sCtrlV)
SETKEY(K_PGUP,sPgUp)
SETKEY(K_PGDN,sPgDn)
SETKEY(K_CTRL_PGUP,sCtrlPgUp)
SETKEY(K_CTRL_PGDN,sCtrlPgDn)
SetKey(K_CTRL_INS,sCtrlIns)
SETKEY(K_F1,sF1)
SETKEY(K_ALT_Z,sAltZ)
SETKEY(K_ALT_K,sAltK)
SETKEY(K_ALT_L,sAltL)
//TRAPSHIFT()
ALTD(1)
cEdit:=STRTRAN(cEdit,CHR(141)+LF,'  ')
cEdit:=STRTRAN(cEdit,CHR(9),space(4))  //HARBOUR вставляет TAB!!!
IF !(cEdit==cEdit0).AND.YesOrNo('Запомнить изменения для печати ?')
   FSEEK(nHandle, nPos0, FS_SET)
   IF lFull
      cEdit:=TRIM(cEdit)
      IF RIGHT(cEdit,2)!=CRLF
         cEdit+=CRLF
      ENDIF
      // !!!! STRTRAN надо, иначе при редактировании с дополнением
      //              пробелами в конце строки ерунда получается
      FWRITE(nHandle,STRTRAN(cEdit,CHR(32),CHR(255)),LEN(cEdit))
      IF LEN(cEdit)<LEN(cEdit0)
         FWRITE(nHandle,REPLICATE(CHR(0),LEN(cEdit0)-LEN(cEdit)),LEN(cEdit0)-LEN(cEdit))
      ENDIF
      nRow0:=nRowAct:=nY1
   ELSE
      FWRITE(nHandle,cEdit,LEN(cEdit0))
   ENDIF
ENDIF
SETCURSOR(0)
SETRC(nRow0,nCol0)
FSEEK(nHandle, nPos0, FS_SET)
lfreadln(nHandle, @cline)
FSEEK(nHandle, nPos0, FS_SET)
FOR i:=1 TO nOffSet
lGoNextLn()
NEXT
nLinePos:=FTELL(nHandle)
SETCOLOR(cLastColor)
SETCANCEL(lCancel)

RESTSCREEN(nY1-1,0,nY1-1,MAXCOL(),sRest0)
RESTSCREEN(MaxRow(),0,MaxRow(),MAXCOL(),sRest)
UpdRow(nLineNum)
RETURN(NIL)


FUNCTION DisplayHelp(nMode,cVarNAme)
PLOCAL cScreen := SaveScreen(0, 0, MaxRow(), MaxCol()), nCtype
PLOCAL i,n1,n2
PLOCAL helpTXT
PLOCAL nRow0:=ROW(),nCol0:=COL()
DO CASE
   CASE nMode=1
   n1:=4;n2:=6
   HelpTXT:= {;
   "            Функциональные клавиши в режиме просмотра:              ",;
   "",;
   "Вверх      Предыдущая строка │ F1       Вызов экрана помощи         ", ;
   "Вниз       Следующая строка  │ F2       Запись в файл               ", ;
   "PgUp       Предыдущий экран  │ F5       Фиксация заголовков         ", ;
   "PgDn       Следующий экран   │ Alt-F5   Отмена фиксации заголовков  ", ;
   "Ctrl-PgUp  В начало файла    │ F7       Выделение блока для печати  ", ;
   "Ctrl-PgDn  В конец файла     │ Alt-F7   Отмена выделения блока      ", ;
   "┘         Редактирование    │ Alt-F10  Запуск внешнего редактора   ", ;
   "Alt-S      Поиск фрагмента   │ F9       Печать                      ", ;
   "Ctrl-L     Продолжить поиск  │ Ctrl-F9  Печать в файл               ", ;
   'Alt-Z      Калькулятор       │ Shift-F9 Печать через "Сервер печати"', ;
   'Alt-P      Сохранение отчета │ Alt-F9   Настройка принтера          '}


   AADD(HelpTXT,"                             │ Alt-W    Windows-формат              ")
   AADD(HelpTXT,"Esc        Выход             │ Shift-W  Дизайнер Windows-формата    ")


   IF nMaxCol>250
      HelpTxt[10]:=;
      "Alt-S      Поиск фрагмента   │"
   ENDIF

#ifndef __HARBOUR__

   IF !IsWindows()
      HelpTxt[14]:=;
   "                             │                                      "
      HelpTxt[15]:=;
   "Esc        Выход             │                                      "

   ELSEIF cVarName==NIL
      HelpTxt[14]:=;
   "                             │ Alt-W    Excel-формат                "
      HelpTxt[15]:=;
   "Esc        Выход             │                                      "


   ENDIF

#else

   IF cVarName==NIL

      HelpTxt[14]:=;
   "                             │                                      "
      HelpTxt[15]:=;
   "Esc        Выход             │                                      "
   ENDIF



#endif




   CASE nMode=2
   n1:=6;n2:=8
   HelpTXT:= {;
   "* Величина файла не позволяет осуществлять полное редактирование *",;
   "",;
   "   Функциональные клавиши в режиме ограниченного редактирования:  ",;
   "",;
   "Вверх      Предыдущая строка │ Home      В начало строки          ", ;
   "Вниз       Следующая строка  │ End       В конец строки           ", ;
   "Влево      Предыдущий символ │ Ctrl-Home В начало экрана          ", ;
   "Вправо     Следующий символ  │ Ctrl-End  В конец экрана           ", ;
   "Esc        Выход             │ ┘        Закончить редактирование ", ;
   "Alt+символ Рисование рамок   │ Ctrl-Z    Калькулятор              ", ;
   }
   CASE nMode=3
   n1:=4
   HelpTXT:= {;
   "                     Порядок фиксации заголовков                  ",;
   "",;
   "     Клавишами 'Вверх','Вниз','Вправо','Влево' установите границы ", ;
   " фиксирования левого и верхнего полей текста и нажмите ┘ или F5. ", ;
   "                                                                  ", ;
   "     Отмена фиксации производится одновременным нажатием Alt-F5.  ", ;
   }
   CASE nMode>=4
   n1:=4;n2:=6
   HelpTXT:= {;
   "     Функциональные клавиши в режиме редактирования текста:    ",;
   "",;
   "Вверх      Предыдущая строка │ Delete    Удалить символ        ", ;
   "Вниз       Следующая строка  │ Backspace Удалить символ слева  ", ;
   "Влево      Следующий символ  │ Ctrl-Y    Удалить строку        ", ;
   "Вправо     Предыдущий символ │ Ctrl-T    Удалить слово слева   ", ;
   "Home       В начало строки   │ Ctrl-N    Вставить строку       ", ;
   "End        В конец строки    │ Ctrl-Ins  Подвести итог         ", ;
   "Ctrl-Home  В начало экрана   │ Ins       Переключение режима   ", ;
   "Ctrl-End   В конец экрана    │           вставка/замена        ", ;
   "PgUp       Листание назад    │ Ctrl-Z    Калькулятор           ", ;
   "PgDn       Листание вперед   │ Alt-симв  Рисование рамок       ", ;
   "Ctrl-PgUp  В начало текста   │ ┘        Закончить редактиров  ", ;
   "Ctrl-PgDn  В конец текста    │ Esc       Выход                 ", ;
   }

   #ifdef __HARBOUR__
   HelpTxt[13]:=;
      "Ctrl-PgUp  В начало текста   │ Ctrl-W    Закончить редактиров  "
   #endif






   IF nMode=5
   HelpTxt[11]:=;
   "PgUp       Листание назад    │                                 " //Для InitList
   HelpTxt[12]:=;
   "PgDn       Листание вперед   │                                 " //Для InitList
   ENDIF

ENDCASE
nCtype := SetCursor(0)
ShadowBox('',3,5,4+LEN(HelpTxt),8+LEN(HelpTxt[1]),COL_HELP1)
COLORWIN(n1, 7,  5, 5+LEN(HelpTxt[1]),"14/3")
IF nMode!=3
   COLORWIN(n2,  7, 3+LEN(helpTXT), 16, "15/3")
   COLORWIN(n2, 38, 3+LEN(helpTXT), 46, "15/3")
ENDIF
for i = 1 to len(helpTXT)
SAYSCREEN(helpTXT[i], 3+i, 7)
NEXT
INKEY(0)
RESTSCREEN(0,0,MAXROW(),MAXCOL(),cScreen)
SETRC(nRow0,nCol0)
SETCURSOR(nCtype)
RETURN (NIL)


STATIC FUNCTION FirstFind()
PLOCAL x:=4
PLOCAL sWin:=SaveScreen(x, 0, x+3, MAXCOL())
PLOCAL cLastColor:=SETCOLOR(COL_FIND)
ShadowBox(' Искать фрагмент...', x, 10, x+2, 68)
cFindString:=PADR(cFindString,55)
@ x+1,12 GET cFindString PICTURE "@K"
SETCURSOR(1)
READ
SETCURSOR(0)
RESTSCREEN(x, 0, x+3, MAXCOL(),sWin)
IF LASTKEY() != K_ESC
   nLineNum := 1
   GetFirst()
   NextFind()
ENDIF
SETCOLOR(cLastColor)
RETURN NIL

STATIC FUNCTION NextFind()
PLOCAL cStri:=UPPER(TRIM(cFindString))
Busy(.T.,'Поиск...',,,'Не мигая')
WHILE lGoNextLn()
   nLineNum++
   IF cStri$UPPER(cLine)
      EXIT
   ENDIF
ENDDO
Busy(.F.)
oTbr:rowPos:=oTbr:nTop
UpdRow(nLineNum)
RETURN NIL

/**************************************

FUNCTION Load(nHandler,cKey1,cKey2,lString)

* Назначение...Чтение фрагмента из файла без вызова всего файла
* Примечание...Вызов: Load(nHandle,cKey1,cKey2,[lString]) --> aString/cString

 Интерфейс:

 nHandler - хэндлер файла,откуда будем читать (можно открыть только для чтения)
 cKey1 - метка начала фрагента (после нее может идти комментарий до конца строки)
 cKey2 - метка конца фрагмента (метки,комментарий и CRLF в фрагмент не войдут)
 lString - выдать в виде строки (если не указано или .F. - результат выдается
           в виде массива строк)

***/
FUNCTION Load(nHandler,cKey1,cKey2,lString)
PLOCAL n:=1,nPos:=0,a:={}
nHandle:=nHandler
cLine:=SPACE(512)
nLinePos:=0
nTopPos:=0
FSEEK(nHandle,0,FS_SET) //В начало
WHILE n>0
   IF (n:=FREAD(nHandle,@cLine,512))>0
      IF (nPos:=AT(cKey1,cLine))>0
         nTopPos:=nLinePos:=FSEEK(nHandle,nLinePos+nPos-1,FS_SET)
         EXIT
      ENDIF
      IF n<512
         EXIT
      ENDIF
      nLinePos:=FSEEK(nHandle,-LEN(cKey1),FS_RELATIVE)
   ENDIF
ENDDO
IF nPos>0
   GetFirst()
   WHILE lGoNextLn().AND.!cKey2$cLine
      AADD(a,TRIM(cLine))
   ENDDO
ENDIF
IF lString!=NIL.AND.lString
   a:=IF(LEN(a)>0,a[1],'')
ENDIF
nHandle:=NIL
RETURN a

FUNCTION MaxLineLen( nLen )
  PLOCAL nOldLen:= MAX_LINE_LEN
  IF ValType( nLen ) == 'N'
    MAX_LINE_LEN := nLen
  ENDIF
RETURN( nOldLen )

STATIC FUNCTION HISPrint() // V@

#ifndef __HARBOUR__

IF PR_PTYPE = 0
  DO CASE
    CASE PR_DEVICE='LPT1'
    RETURN PRINTREADY(1)
    CASE PR_DEVICE='LPT2'
    RETURN PRINTREADY(2)
    CASE PR_DEVICE='LPT3'
    RETURN PRINTREADY(3)
  ENDCASE
ENDIF

#endif


RETURN .T.

STATIC FUNCTION MyHandler(setPrinter,setConsole,setPrintFile,nWidth,cLine0,aPreCode)
IF !YesOrNo('***    Пpинтеp не готов    ***',,'Пpодолжить','Пpекpатить')
   lOkPrint:=.F.
   set(_SET_PRINTER,.F.)
   set(_SET_CONSOLE,setConsole)
   set(_SET_PRINTFILE,TRIM(setPrintFile))
   set(_SET_PRINTER,setPrinter)
ELSE
   lGoPrevLn()
ENDIF
BREAK
RETURN 0


***********************************************************************
STATIC PROCEDURE NewEdit( fname )
  PLOCAL  cOldPath := DIRNAME(), cOldDisk := DISKNAME(), cI:='',i
  PLOCAL lFullPath:=AT(":\",fname)<>0
  IF !EMPTY(PR_E_FILE)
    IF !EMPTY(PR_E_PATH)
      IF (i := AT( ':', PR_E_PATH ) ) <> 0
        DISKCHANGE( LEFT( PR_E_PATH, i-1 ) )
        IIF(!lFullPath,cI := cOldDisk+':',NIL)
      ENDIF
      DIRCHANGE(PR_E_PATH)
      IIF(!lFullPath,cI += cOldPath+'\',NIL)
    ENDIF
    BS_RUN( PR_E_FILE+' '+cI+fname )
  ENDIF
  DISKCHANGE( cOldDisk )
  DIRCHANGE( cOldPath )
RETURN
// Изменение 3.18
// Изменение 3.60
//--------------------------------------------------------------------------//
FUNCTION SaveParamPrint(_PR_TYPE,_PR_WIDTH,_PR_PAPER,_PR_STR,_PR_PROBROS,;
                        _PR_PAUSE,_PR_DEVICE,_PR_PSEVDO,_PR_E_YES,_PR_E_PATH,;
                        _PR_E_FILE,_PR_WTYPE,_PR_HEAD,_PR_NUMSTR,_PR_BEGSTR,;
                        _PR_LCODE,_PR_BCODE,_PR_ECODE,_PR_LSUM,_PR_TDEVICE,;
                        _PR_TVIEW,_PR_TNAST,_PR_TFILE,_PR_TERROR,_PR_TCOPY,;
                        _PR_PTYPE, _PR_WIN,_PR_TWIN, _PR_ORINT, _PR_OTSTUP)
//--------------------------------------------------------------------------//
// Возвращает (по ссылке, если NIL) и выставляет установки печати

lLoad:=.T.
IF(_PR_TYPE    != NIL, PR_TYPE    := _PR_TYPE   , _PR_TYPE    := IF(PR_TYPE    = NIL,(PR_TYPE   := PRN0_TYPE   ),PR_TYPE   ))
IF(_PR_WIDTH   != NIL, PR_WIDTH   := _PR_WIDTH  , _PR_WIDTH   := IF(PR_WIDTH   = NIL,(PR_WIDTH  := PRN0_WIDTH  ),PR_WIDTH  ))
IF(_PR_PAPER   != NIL, PR_PAPER   := _PR_PAPER  , _PR_PAPER   := IF(PR_PAPER   = NIL,(PR_PAPER  := PRN0_PAPER  ),PR_PAPER  ))
IF(_PR_STR     != NIL, PR_STR     := _PR_STR    , _PR_STR     := IF(PR_STR     = NIL,(PR_STR    := PRN0_STR    ),PR_STR    ))
IF(_PR_PROBROS != NIL, PR_PROBROS := _PR_PROBROS, _PR_PROBROS := IF(PR_PROBROS = NIL,(PR_PROBROS:= PRN0_PROBROS),PR_PROBROS))
IF(_PR_PAUSE   != NIL, PR_PAUSE   := _PR_PAUSE  , _PR_PAUSE   := IF(PR_PAUSE   = NIL,(PR_PAUSE  := PRN0_PAUSE  ),PR_PAUSE  ))
IF(_PR_DEVICE  != NIL, PR_DEVICE  := _PR_DEVICE , _PR_DEVICE  := IF(PR_DEVICE  = NIL,(PR_DEVICE := PRN0_DEVICE ),PR_DEVICE ))
IF(_PR_PSEVDO  != NIL, PR_PSEVDO  := _PR_PSEVDO , _PR_PSEVDO  := IF(PR_PSEVDO  = NIL,(PR_PSEVDO := PRN0_PSEVDO ),PR_PSEVDO ))
IF(_PR_E_YES   != NIL, PR_E_YES   := _PR_E_YES  , _PR_E_YES   := IF(PR_E_YES   = NIL,(PR_E_YES  := PRN0_E_YES  ),PR_E_YES  ))
IF(_PR_E_PATH  != NIL, PR_E_PATH  := _PR_E_PATH , _PR_E_PATH  := IF(PR_E_PATH  = NIL,(PR_E_PATH := PRN0_E_PATH ),PR_E_PATH ))
IF(_PR_E_FILE  != NIL, PR_E_FILE  := _PR_E_FILE , _PR_E_FILE  := IF(PR_E_FILE  = NIL,(PR_E_FILE := PRN0_E_FILE ),PR_E_FILE ))
IF(_PR_WTYPE   != NIL, PR_WTYPE   := _PR_WTYPE  , _PR_WTYPE   := IF(PR_WTYPE   = NIL,(PR_WTYPE  := PRN0_WTYPE  ),PR_WTYPE  ))
IF(_PR_HEAD    != NIL, PR_HEAD    := _PR_HEAD   , _PR_HEAD    := IF(PR_HEAD    = NIL,(PR_HEAD   := PRN0_HEAD   ),PR_HEAD   ))
IF(_PR_NUMSTR  != NIL, PR_NUMSTR  := _PR_NUMSTR , _PR_NUMSTR  := IF(PR_NUMSTR  = NIL,(PR_NUMSTR := PRN0_NUMSTR ),PR_NUMSTR ))
IF(_PR_BEGSTR  != NIL, PR_BEGSTR  := _PR_BEGSTR , _PR_BEGSTR  := IF(PR_BEGSTR  = NIL,(PR_BEGSTR := PRN0_BEGSTR ),PR_BEGSTR ))
IF(_PR_LCODE   != NIL, PR_LCODE   := _PR_LCODE  , _PR_LCODE   := IF(PR_LCODE   = NIL,(PR_LCODE  := PRN0_LCODE  ),PR_LCODE  ))
IF(_PR_BCODE   != NIL, PR_BCODE   := _PR_BCODE  , _PR_BCODE   := IF(PR_BCODE   = NIL,(PR_BCODE  := PRN0_BCODE  ),PR_BCODE  ))
IF(_PR_ECODE   != NIL, PR_ECODE   := _PR_ECODE  , _PR_ECODE   := IF(PR_ECODE   = NIL,(PR_ECODE  := PRN0_ECODE  ),PR_ECODE  ))
IF(_PR_LSUM    != NIL, PR_LSUM    := _PR_LSUM   , _PR_LSUM    := IF(PR_LSUM    = NIL,(PR_LSUM   := PRN0_LSUM   ),PR_LSUM   ))
IF(_PR_TDEVICE != NIL, PR_TDEVICE := _PR_TDEVICE , _PR_TDEVICE:= IF(PR_TDEVICE    = NIL,(PR_TDEVICE   := PRN0_TDEVICE   ),PR_TDEVICE   ))
IF(_PR_TVIEW   != NIL, PR_TVIEW   := _PR_TVIEW   , _PR_TVIEW  := IF(PR_TVIEW    = NIL,(PR_TVIEW   := PRN0_TVIEW   ),PR_TVIEW   ))
IF(_PR_TNAST   != NIL, PR_TNAST   := _PR_TNAST   , _PR_TNAST  := IF(PR_TNAST    = NIL,(PR_TNAST   := PRN0_TNAST   ),PR_TNAST   ))
IF(_PR_TFILE   != NIL, PR_TFILE   := _PR_TFILE   , _PR_TFILE  := IF(PR_TFILE    = NIL,(PR_TFILE   := PRN0_TFILE   ),PR_TFILE   ))
IF(_PR_TERROR  != NIL, PR_TERROR  := _PR_TERROR  , _PR_TERROR := IF(PR_TERROR    = NIL,(PR_TERROR   := PRN0_TERROR   ),PR_TERROR   ))
IF(_PR_TCOPY   != NIL, PR_TCOPY   := _PR_TCOPY   , _PR_TCOPY  := IF(PR_TCOPY    = NIL,(PR_TCOPY   := PRN0_TCOPY   ),PR_TCOPY   ))
IF(_PR_PTYPE   != NIL, PR_PTYPE   := _PR_PTYPE   , _PR_PTYPE  := IF(PR_PTYPE    = NIL,(PR_PTYPE   := PRN0_PTYPE   ),PR_PTYPE   ))
IF(_PR_WIN     != NIL, PR_WIN     := _PR_WIN     , _PR_WIN    := IF(PR_WIN    = NIL,(PR_WIN   := PRN0_WIN   ),PR_WIN   ))
IF(_PR_TWIN    != NIL, PR_TWIN    := _PR_TWIN    , _PR_TWIN   := IF(PR_TWIN    = NIL,(PR_TWIN   := PRN0_TWIN   ),PR_TWIN   ))
IF(_PR_ORINT    != NIL, PR_ORINT    := _PR_ORINT    , _PR_ORINT   := IF(PR_ORINT    = NIL,(PR_ORINT   := PRN0_ORINT   ),PR_ORINT   ))
IF(_PR_OTSTUP    != NIL, PR_OTSTUP    := _PR_OTSTUP    , _PR_OTSTUP   := IF(PR_OTSTUP    = NIL,(PR_OTSTUP   := PRN0_OTSTUP   ),PR_OTSTUP   ))

IF !lSetCode
  PR_TYPE   := '1'
  PR_WIDTH  := 64000
  PR_PAPER  := .F.
  PR_STR    := 1000000000
  PR_PROBROS := .F.
  PR_PAUSE  := .F.
  PR_DEVICE := PR_TDEVICE
  PR_PSEVDO := .T.
  PR_WTYPE  := '1'
  PR_HEAD   := ""
  PR_NUMSTR := .F.
  PR_BEGSTR := 1
  PR_LCODE  := .F.
  PR_BCODE  := ""
  PR_ECODE  := ""
  PR_LSUM   := .F.
    // Изменение 3.60
  PR_PTYPE  := 0
  PR_WIN    := .F.
ENDIF

RETURN NIL
//--------------------------------------------------------------------------//
STATIC FUNCTION Set_Termo(cHead,lNumStr,cId,lSumKol)
//--------------------------------------------------------------------------//
///              PrtSetup(cHead,lNumStr,cId,lSumKol)

  PLOCAL aSet := SaveSet(), aSetKeys := SaveSetKey()
  PLOCAL oGet
  PLOCAL aYes:={{.T.,'Да  '},{.F.,'Нет'}}
  PLOCAL aDevice := {;
                       { 'LPT1', 'Параллельный порт 1' }, ;
                       { 'LPT2', 'Параллельный порт 2' }, ;
                       { 'LPT3', 'Параллельный порт 3' }, ;
                       { 'LPT4', 'Параллельный порт 4' }, ;
                       { 'LPT5', 'Параллельный порт 5' }, ;
                       { 'COM1', 'Послед-ный порт   1' }, ;
                       { 'COM2', 'Послед-ный порт   2' }, ;
                       { 'ФАЙЛ', 'Файл на диске      ' }  ;
                     }
  PRIVATE aIn[5]

  aIn[1]  :=  PR_TDEVICE
  aIn[2]  :=  PR_TFILE
  aIn[3]  :=  PR_TCOPY
  aIn[4]  :=  PR_TWIN
  aIn[5]  :=  .F.

  SETCOLOR(COL_INPUT)
  @ 05,03,12,76 BOX "╔═╗║╝═╚║ "
  @ 05,5 SAY "[ Настройка термопринтера ]"

  @ 07, 09 SAY   "- имя устройства.................... :"
  @ 08, 09 SAY   "- имя файла вывода.................. :"
  @ 09, 09 SAY   "- количество копий.................. :"
  @ 10, 09 SAY   "- вывод в Windows формате .......... :"
  @ 11, 09 SAY   "- настройка параметров печати....... :"


  oGet := GETNEW(07, 48,  { |x| RotateBlock(x,aDevice,'aIn[1]')} )
  oGet:Reader := { |oGet| RotateAndReader( oGet,aDevice, 8, 33 ) }
  AADD( GetList, oGet )

  @ 8, 48 GET aIn[2] PICTURE "@S20"

  @ 9, 48 GET aIn[3] PICTURE "9999"

  oGet := GETNEW(10,48,{|x| BlockCase(GetList[4],.T.,aYes,"aIn[4]","N/BG,N/BG",,,,.T.) },{"aIn[4]",,,,,})
  oGet:reader := {|oGet| ReaderCase(oGet) }
  AADD(GetList, oGet)

  oGet := GETNEW(11,48,{|x| RotateBlock(x,aYes,"aIn[5]") },{"aIn[5]",,,,,})
  oGet:postBlock:= {|| IF(LASTKEY()=K_ENTER.AND.aIn[5],;
                          (PushData({PR_TDEVICE,PR_TWIN}),;
                           PR_TDEVICE:=aIn[1],PR_TWIN:=aIn[4],;
                           PrtSetup(cHead,lNumStr,cId,lSumKol),;
                           PR_TDEVICE:=PopData("V")[1],;
                           PR_TWIN:=PopData()[2]),),.T. }
  oGet:Reader := {|oGet| RotateAndReader(oGet,aYes) }
  AADD(GetList, oGet)

  AEVAL( GetList, {|x| x:Display() } )

  SET CURSOR ON
  READ
  SET CURSOR OFF

  IF LASTKEY() <> K_ESC
    PR_TDEVICE  := aIn[1]
    PR_TFILE    := aIn[2]
    PR_TCOPY    := aIn[3]
    PR_TWIN     := aIn[4]
    PR_TEDIT    := aIn[5]
  ENDIF

  RestSet(aSet)
  RestSetKey(aSetKeys)

RETURN NIL
//--------------------------------------------------------------------------//
    STATIC FUNCTION RetStatus()
//--------------------------------------------------------------------------//
PLOCAL nStatus := PRINTSTAT()
PLOCAL aError := {"  ВНИМАНИЕ: Пpинтеp не готов!  "}
IF nStatus = 1
  AADD(aError,"( тайм-аут истек )")
ELSEIF nStatus = 4
  AADD(aError,"( ошибка передачи )")
ELSEIF nStatus = 6
  AADD(aError,"( конец бумаги )")
ELSEIF nStatus = 8
  AADD(aError,"( принтер недоступен )")
ENDIF
RETURN aError
//--------------------------------------------------------------------------//
                STATIC FUNCTION StrKolLine(nFHandle,nLine)
//--------------------------------------------------------------------------//
// Подсчитывает число строк до прогона листа или число строк на листе
PLOCAL nBakPoz, cPLine := ''

nBakPoz := FTELL(nFHandle)

DO WHILE lFReadLn(nFHandle,@cPLine,MAX_LINE_LEN)
  nLine++
  IF CHR(12) $ cPLine .OR. nLine >= PR_STR/m->nMassh
     EXIT
  ENDIF
ENDDO

FSeek(nFHandle,nBakPoz,FS_SET)

RETURN nLine
//--------------------------------------------------------------------------//
FUNCTION DosToWindows( cText )
//--------------------------------------------------------------------------//
  IF VALTYPE( cText ) == "C"
  #ifdef __HARBOUR__
     cText:=OemToAnsi(cText)
  #else
  CHARREPL( 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя',;
            @cText,;
            '└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■ ',;
            .T. ;
          )
  #endif
        ENDIF
RETURN cText
//--------------------------------------------------------------------------//
FUNCTION WinToDos(cText)
//--------------------------------------------------------------------------//
If VALTYPE(cText) == "C"
  CHARREPL('└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■ ',;
           @cText,;
           'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя',;
           .T.;
          )
EndIf
RETURN cText

//--------------------------------------------------------------------------//
FUNCTION ClearParamPrint()
//--------------------------------------------------------------------------//
        lLoad:=.F.
        PR_TYPE    = NIL ;PR_WIDTH   = NIL ;PR_PAPER   = NIL ;PR_STR     = NIL
        PR_PROBROS = NIL ;PR_PAUSE   = NIL ;PR_DEVICE  = NIL ;PR_PSEVDO  = NIL
        PR_E_YES   = NIL ;PR_E_PATH  = NIL ;PR_E_FILE  = NIL ;PR_WTYPE   = NIL
        PR_HEAD    = NIL ;PR_NUMSTR  = NIL ;PR_BEGSTR  = NIL ;PR_LCODE   = NIL
        PR_BCODE   = NIL ;PR_ECODE   = NIL ;PR_LSUM    = NIL ;PR_TDEVICE = NIL
        PR_TVIEW   = NIL ;PR_TNAST   = NIL ;PR_TFILE   = NIL ;PR_TERROR  = NIL
        PR_TCOPY   = NIL ;PR_PTYPE   = NIL ;PR_WIN     = NIL ;PR_TWIN    = NIL
  PR_ORINT   = NIL ;PR_OTSTUP  = NIL
RETURN NIL
//--------------------------------------------------------------------------//

******************
STATIC FUNCTION GetMassh(lF10,lPrn)
******************
PLOCAL bF10 :=SETKEY(K_F10)
PLOCAL aSetKey:=SaveSetKey()
PLOCAL nMas := m->nMassh*100, nRet:= m->nMassh
PLOCAL cScr:=SAVESCREEN()
PRIVATE GETLIST :={}
lPrn:=!EMPTY(lPrn)
IF !EMPTY(lF10)
   SETKEY(K_F10,bF10)
ENDIF
ShadowBox('', 7, 15, 11+IF(lPrn,2,0), 56, COL_SHEADR)
IF lPrn
   @11,15 SAY '╟────────────────────────────────────────╢' COLOR COL_SHEADR
   @12,17 SAY 'Принтер '+LEFT(m->pPrinter,30) COLOR COL_SHEADR
ENDIF
@9,22 SAY 'Укажите масштаб печати' COLOR COL_SHEADR GET nMas PICTURE '999' COLOR COL_GET VALID nMas>0
@9,48 SAY '%' COLOR COL_SHEADR
IF lPrn
   @13,36 SAY 'F10:Выбор принтера' COLOR COL_SHEADR
ENDIF
SET CURSOR ON
READ
SET CURSOR OFF
IF LASTKEY() # K_ESC
   nRet := nMas/100
ENDIF
RESTSCREEN(,,,,cScr)
RestSetKey(aSetKey)

RETURN nRet

Function IsWindows()
Return (IsMSWIN().or.IsMSNT())
//
STATIC FUNCTION lnfreadln(nHandle, cBuffer) // V@
Local nEol, nRead, nSaveFpos := FTELL(nHandle)
      nRead := LongBufferRead(@cBuffer,@nEol)
  IF nEol != 0
    //Удаляем все CRLF из строки
    cBuffer:= SUBSTR(cBuffer, 1, nEol - 1)+SPACE(MAX_LINE_LEN-nEol)
    //Устанавливаем указатель файла на следующую строку
    nLinePos:=fseek(nHandle, nSaveFPos + nEol + 1, FS_SET)
    nLinePos0:=nSaveFPos
  ENDIF
  IF nEol=0.OR.CHR(0)$cBuffer.OR.cBuffer=CHR(26)
     nRead:=0
     nLinePos:=fseek(nHandle, nSaveFPos, FS_SET)
     nLinePos0:=nSaveFPos
  ENDIF
RETURN nRead != 0

STATIC FUNCTION ToWindows(cFile,cVarName,nVid)
LOCAL cExe:=EXENAME()
LOCAL i:=RAT("\",cExe)
LOCAL cExeP:=LEFT(cExe,i)
LOCAL cDllName:=cExeP+"Report4"
LOCAL cFunction :="ShowReport"
LOCAL cReport




#ifndef __HARBOUR__
IF IsWindows()
   busy(.T.,"Работа Windows-компонент")
   IF cVarName==NIL
      IF FILE(cFile)
//         V32Db2Excel(cFile)
         V32E(cFile)
      ENDIF
   ELSEIF FILE(cVarName)
      cReport:=TRUENAME_(LoadPath()+"Main\Template")+"\"+V32OemToChar(TRIM(Forma->WinShablon))
      V32DllCall(cDllName, cFunction,,,{10,cReport,10,cVarName,3,nVid,3,1})
      While .T.
       Inkey(.1)
       IF !FILE(cVarName)
         Exit
       ENDIF
      EndDo
   ENDIF
   busy(.F.)

ENDIF
#else
IF FILE(cVarName)
   cReport:=TRUENAME_(LoadPath()+"Main\Template")+"\"+OemToAnsi(TRIM(Forma->WinShablon))
   FRCall(cFunction,cReport,cVarName,nVid+2,1)
ENDIF

#endif


RETURN NIL

FUNCTION TrueName_(c)
IF !":\"$c .AND. LEFT(c,2)<>"\\"
   IF c[1]=="\"
      RETURN LEFT(EXENAME(),1)+":"+c
   ELSE
      RETURN LEFT(EXENAME(),1)+":\"+CURDIR()+"\"+c
   ENDIF
ENDIF
RETURN c


#ifndef __HARBOUR__

STATIC FUNCTION V32E(cFile)
local cClassId, a_

cClassId := 'Excel.Application'

a_:={}


aadd( a_, 'v32Ole:WorkBooks():Open("'+cFile+'")' )
aadd( a_, 'v32Ole:visible := .t.' )
V32ActiveX( cClassId, a_ )
RETURN NIL


#endif


STATIC FUNCTION Kolonki(cLine)
LOCAL lRet
IF !("("$cLine.AND.")"$cLine)
   RETURN .F.
ENDIF
lRet:=EMPTY(ALLTRIM(CharRem("()1234567890abаб│"+CHR(255),cLine)))
altd()
RETURN lRet








