/*!!!!!!!!!!!!!!!!    Изменения   !!!!!!!!!!!!!!!!!!!1
 - в БД "BLOKNOT.DBF" вместо поля TEXT поле NOTE
 - другой ключ индексного файла "BLOKNOT.NTX"  (Index: TASK+DATA)
 - БД "PRAZDNIK.DBF" не нужна    ***
*/

/***
* Файл.........BLKN.PRG
* Автор........Ю.Голубчиков
* Дата.........12.01.94 16,51
* Язык.........CLIPPER 5.01
* Назначение...Календарь-блокнот
* Примечание...Вызов по "Hot-Key" - SetKey(K_ALT_K, {||BlokNot(3)})
// Copyright (c) 1993-2005 "Компания БЭСТ". Все права сохраняются.

 Используемые функции:
          Bloknot()
 (static) WTitle()
 (static) IsLeap()
 (static) DateString()
          MemoFunk()
 (static) StrToArray()
 (static) aComp()
 (static) BlkHlp()

 Используемые процедуры:
   (static) BlokEdit

  Функции из BEST.PLL :
        - SaveSet(), RestSet(), SaveSetKey(), RestSetKey()
        - NetUse(), AddRec(), RecLock(), Error_Use(), Error_Lock()
        - NewWindow(), YesOrNo(), ShadowBox()
  Внешние переменные :
        - Help_code, GlobalTask, INST_COLOR
  Базы данных :
        - "BLOKNOT.DBF" ("BLOKNOT.DBT"), "BLOKNOT.NTX"  (Index: TASK+DATA)
             Fields: TASK(C2), DATA (C8), NOTE(M10)

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

#include "inkey.ch"
#include "s_public.ch"

#define  COL_BLOKNOT "N/W,R+/W,GR+/W,W+/N,W+/R+,R/G"


*
/***
* Function: Календарь/блокнот
*/
FUNCTION Bloknot(nTop)
LOCAL nLeft:=3, nHotKey:=LASTKEY()
LOCAL aDays[31], sysdate, first, today, nKey, aClr, x,i,j,l,n,cEl
LOCAL bHol, bPlace, aDayOff, aDaySave, oGet:=GetActive(), bAction
LOCAL aVarSave:=SaveSet(), bHelp, bEsc, bTab, bBlkn, aKeySave
LOCAL xDateFormat, xDeleted, lGetDate:=oGet<>Nil.AND.oGet:type=="D", nWiSave

aKeySave:=SaveSetKey()          /* F2-F10,K_ENTER,K_LEFT,K_RIGHT */

nTop:=If(nTop==Nil,3,If(nTop>12,12,nTop))
nTop:=If(lGetDate.AND.oGet:row<13,oGet:row+1,nTop)

aClr:=LineToArray( COL_BLOKNOT, ',' )
//{"N/W","R+/W","GR+/W","W+/N","W+/R+"}, R/G
/* ========== альтернативный вариант ===========
   aClr:={'W/B','R+/B','GR+/B','B/W,'R+/W'}
   aClr[1] - осн.фон
   aClr[2] - для выходных дней
   aClr[3] - для сообщений
   aClr[4] - для текущего дня
   aClr[5] - для текущего выходного/празднич. дня
*/

If !NetUse("Bloknot","Bloknot","Bloknot")
  Error_Use()
  RETURN (Nil)
EndIf
If ((nWiSave:=NewWindow(nTop,3,12,74,"",2,.F.,.T.,aClr[1])) < 0)
  RETURN (Nil)
EndIF
 nTop:=0; nLeft:=0
 SetKey(K_F1, {|| BlkHlp("#1")})
xDateFormat:=SET(_SET_DATEFORMAT,"mm/dd/yy")
xDeleted:=SET(_SET_DELETED,"on")
/*
//SetColor(),SaveScreen(),SetCursor(),Select(),Row(),Col(),Save_Help()
aVarSave:=SaveSet()
*/
aDayOff:=If(DBSeek("#####0"),;
   StrToArray(FIELD->NOTE),;
   {"01/01","01/07","03/08","05/01","05/02","05/09","11/07","11/08"})
aDaySave:=ARRAY(LEN(aDayOff))
ACOPY(aDayOff,aDaySave)  /* Сохраняем вых.дни на предмет внесений изменений */
///SysDate:=If(lGetDate.AND.!EMPTY(oGet:VarGet()), oGet:VarGet(), DATE())
SysDate:=If(lGetDate,IF(VALTYPE(oGet:Name)=="A".AND.LEN(oGet:Name)>3,aIn[oGet:Name[3]],oGet:VarGet()),DATE())
PRIVATE cTask:= UPPER(GlobalTask)
bPlace:={|day| nLeft-2+(If(DOW(day)==1,7,DOW(day)-1)*4)}
bHol:={|day| If(ASCAN(aDayOff,LEFT(DTOC(day),5))!=0,.F.,.T.)}

SETCURSOR(0)
/*
 ╔════════════════════════════════════════════════════════════════════════╗
 ║        Январь 1994         │  Запись в блокноте на XX xxxxxxxx 19XX г. ║
 ╟────────────────────────────│───────────────────────────────────────────╢
 ║ Пн  Вт  Ср  Чт  Пт  Сб  Вс │                                           ║
 ║                            │                                           ║
 ║                            │                                           ║
 ║                            │                                           ║
 ║                            │                                           ║
 ║                            │                                           ║
 ║                            │                                           ║
 ║                            │                                           ║
 ╚════════════════════════════════════════════════════════════════════════╝
*/
SETCOLOR(aClr[1])
*@ nTop,nLeft CLEAR TO nTop+11,nLeft+73
*@ nTop,nLeft,nTop+11,nLeft+73 BOX '╔═╗║╝═╚║'
@ nTop+2, nLeft SAY "╟"+REPLICATE("─",72)+"╢"
@ nTop+1, nLeft+29 To nTop+10,nLeft+29
@ nTop+1, nLeft+32 SAY "Запись в блокноте на "
@ nTop+3, nLeft+2  SAY 'Пн  Вт  Ср  Чт  Пт' COLOR aClr[3]
@ nTop+3, nLeft+22 SAY 'Сб  Вс'             COLOR aClr[2]
BEGIN SEQUENCE
While (.T.) //NEXTKEY() <> K_ESC
  first:=BOM(sysdate)  /* первый день месяца */
  x:=If(DOW(first)==1,7,DOW(first)-1)  // день недели для него
  today:=first         /* счетчик дней */
  SETCOLOR(aClr[1])
  @ nTop+5,nLeft+2 CLEAR TO nTop+10,nLeft+27
  SETCOLOR(aClr[1])
  WTitle(UPPER(CMONTH(sysdate))+' '+STR(YEAR(sysdate),4),nTop+1,nLeft+1,nLeft+29)
  SETCOLOR(aClr[1])
  For i:=nTop+5 To nTop+10
    For j:=x To 7           /* отображаем каждый день */
      @ i,Eval(bPlace,today) SAY DAY(today) PICTURE "99";
          COLOR If(j<6.AND.EVAL(bHol,today),aClr[1],aClr[2])
      aDays[DAY(today)] := i
      ++today
      If MONTH(today) # MONTH(first)
        Exit
      EndIF
    Next
    x:=1  /* сбросили счетчик недели */
    If MONTH(today) # MONTH(first)
      Exit
    EndIF
  Next
  nKey:=0
  While !STR(nKey,2) $ ' 3,18,45,43,13,27'
    l:=If(DOW(sysdate)==1,7,DOW(sysdate)-1)
    SETCOLOR( If(l<6.AND.EVAL(bHol,sysdate),aClr[4],aClr[5]) )
    @ aDays[DAY(sysdate)],Eval(bPlace,sysdate) SAY DAY(sysdate) PICTURE '99'
    SetColor(aClr[1])
    @ nTop+1, nLeft+53 CLEAR TO nTop+1, nLeft+72
    @ nTop+1, nLeft+53 SAY DateString(sysdate) COLOR aClr[4]
    __KeyBoard(CHR(K_ESC)) /* отобразить MEMO-поле и выйти */
    MemoEdit( If(DbSeek(cTask+DTOS(SysDate)), FIELD->NOTE, ""),;
                 nTop+3, nLeft+31, nTop+10, nLeft+72, .F.)
    @ MAXROW(),MAXCOL() SAY ""
    nKey:=INKEY(0)
    If ( (bAction := SetKey(nKey)) != Nil )
      Eval(bAction)
    EndIf
    If STR(nKey,2) $ ' 3, 4, 5,18,19,24,45,43'
      SETCOLOR(If(l<6.AND.EVAL(bHol,sysdate),aClr[1],aClr[2]))
      @ aDays[DAY(sysdate)],Eval(bPlace,sysdate) SAY DAY(sysdate) PICTURE '99'
      DO Case
        CASE nKey==K_PGDN
          sysdate:=BOM(BOM(sysdate)+31)+DAY(sysdate)-1
        CASE nKey==K_PGUP
          sysdate:=BOM(BOM(sysdate)-1)+DAY(sysdate)-1
        CASE nKey==K_UP .OR. nKey==K_DOWN
          sysdate:=sysdate+if(nKey=24,7,-7)
          If MONTH(sysdate) # MONTH(first)
            Exit
          EndIF
        CASE nKey==K_LEFT .OR. nKey==K_RIGHT
          sysdate:=sysdate+if(nKey=19,-1,1)
          If MONTH(sysdate) # MONTH(first)
            Exit
          EndIF
        CASE nKey==ASC("-")
          sysdate-=365+If(IsLeap(sysdate),1,0)
        CASE nKey==ASC("+")
          sysdate+=365+If(IsLeap(sysdate),1,0)
      EndCASE
    ElseIf nKey==K_TAB .OR. IsAlpha(CHR(nKey))
      If IsAlpha(CHR(nKey))
        KeyBoard(CHR(nKey))
      EndIf
      BlokEdit(DTOS(SysDate),nTop,nLeft,aClr[1])
    ElseIf nKey==K_DEL  /* удаление записи из блокнота  */
      If Bloknot->(!EOF()) .AND. YesOrNo('Удалить запись?')
        If !RecLock()
          Error_Lock()
        Else
          DBDelete();  DBUnLock()
        EndIf
      EndIf
    ElseIf nKey==K_INS  /* отметка праздничных дней */
      cEl:=LEFT(DTOC(SysDate),5)
      If( (n:=ASCAN(aDayOff,cEl))<>0, ADEL(aDayOff,n), AADD(aDayOff,cEl) )
    ElseIf nKey == K_ENTER// .OR. nKey==K_ESC
           Break
    ElseIf nKey == K_ESC
           Break
    EndIF
  End
ENDDO
ENDSEQUENCE
If !aComp(aDayOff,aDaySave)
  /* Запись измененного массива прадничных дней в базу */
  cEl:=""
  AEval(aDayOff, {|i,j| cEl+=If(aDayOff[j]<>Nil,aDayOff[j]+";","")})
  If (DBSeek("#####0") .AND. RecLock()) .OR. AddRec()
    FIELD->TASK:="#####0";  FIELD->NOTE:=cEl
  Else
    Error_Lock()
  EndIf
EndIf
SET(_SET_DATEFORMAT,xDateFormat)
SET(_SET_DELETED,xDeleted)
BLOKNOT->(DBCloseArea())
RestSetKey(aKeySave)
If (WCLOSE() != nWiSave)
  WSELECT(nWiSave)
EndIF
RestSet(aVarSave)
If LASTKEY()==K_ENTER .AND. lGetDate
  oGet:home(); KeyBoard(DTOC(sysdate))
EndIf
RETURN (Nil)

*
STATIC FUNCTION WTitle(cName,nRow,nCol,nRight)
@ nRow,nCol SAY SPACE(nRight-nCol)
@ nRow,nCol+((nRight-nCol)-LEN(cName))/2 SAY cName
RETURN (Nil)

*
STATIC FUNCTION IsLeap(dDate)
LOCAL nYear:=VAL(SUBSTR(DTOC(dDate),-2))/4
RETURN (nYear-INT(nYear)=0)

*
STATIC FUNCTION DateString(dDate)
LOCAL nMon:=MONTH(dDate), cMon:=CMONTH(dDate)
cMon:=If( STR(nMon,1) $ "38",cMon+"а",SUBSTR(cMon,1,LEN(cMon)-1)+"я")
RETURN (STR(DAY(dDate),2)+" "+cMon+" "+STR(YEAR(dDate),4)+" г.")

*
STATIC PROCEDURE BlokEdit(dDate,nTop,nLeft,cColor)
LOCAL cEdit:=If(DbSeek(m->cTask+dDate),Bloknot->NOTE,""), cStr
LOCAL cClrSave:=SetColor(cColor), bHelp:=SetKey(K_F1, {||BlkHlp("#2")}),;
      lInsMode:=READINSERT(.T.)
*CLEAREOL(24,0,'N/W'); ScrTitul(24,'F10:Выход')
SetCursor(1)
cStr:=MemoEdit(cEdit,nTop+3,nLeft+31,nTop+10,nLeft+72,.T.,"MemoFunk")
SetCursor(0)
READINSERT(lInsMode)
If cEdit<>cStr .AND. LastKey()<>K_ESC
  If (DbSeek(m->cTask+dDate).AND.RecLock()) .OR. AddRec()
    FIELD->TASK := m->cTask
    FIELD->DATA := dDate
    FIELD->NOTE := cStr
    DBUnLock()
  Else
    Error_Lock()
  EndIf
EndIf
SetColor(cClrSave); SetKey(K_F1, bHelp)
RETURN

*
FUNCTION MemoFunk(nMode, nLine, nCol)
LOCAL nKey:=LastKey()
If nKey==K_F10 .OR. nKey==K_ESC
  RETURN (K_CTRL_W) /* выход из MemoEdit() */
EndIf
RETURN (0)

*
STATIC FUNCTION StrToArray(cString,cDelim)
LOCAL aArray:={}, i
cDelim:=If(cDelim==Nil,";",cDelim)
While ( (i:=AT(cDelim,cString)) > 0 )
  AADD(aArray, LEFT(cString, i-1))
  cString:=LTRIM(SUBSTR(cString,i+1))
End
If !EMPTY(cString)
  AADD(aArray,cString)
EndIf
RETURN (aArray)

*
STATIC FUNCTION aComp(array1,array2)  /* сравнение 2-х одномерных массивов */
LOCAL i
If LEN(array1) <> LEN(array2)
  RETURN (.F.)
EndIF
For i:=1 To LEN(array1)
  If !(array1[i]==array2[i])
    RETURN (.F.)
  EndIF
Next
RETURN (.T.)

*
STATIC FUNCTION BlkHlp(n)
LOCAL bF1, aVarSave:=SaveSet(), nRecSave:=RecNo()
LOCAL nWiSave,aColHelp := LineToArray( COL_HELP_BLK, ',' )
LOCAL cMemo:=;
"           Клавиши управления календарем          "+CHR(13)+CHR(10)+; 
"PgUp...........................на один месяц назад"+CHR(13)+CHR(10)+; 
"PgDn..........................на один месяц вперед"+CHR(13)+CHR(10)+; 
"Клавиша "-"......................на один год назад"+CHR(13)+CHR(10)+; 
"Клавиша "+".....................на один год вперед"+CHR(13)+CHR(10)+; 
"Ins.......................отметка праздничных дней"+CHR(13)+CHR(10)+; 
"Del......................удалить запись в блокноте"+CHR(13)+CHR(10)+; 
"Tab...............редактирование записи в блокноте"+CHR(13)+CHR(10)+; 
"Enter.............ввести текущую дату в поле ввода"+CHR(13)+CHR(10)+; 
"Esc.............................выход из календаря"+CHR(13)+CHR(10)+; 
"                                                  "+CHR(13)+CHR(10)+; 
"           Клавиши управления блокнотом           "+CHR(13)+CHR(10)+; 
"Ins...............переключить режим Вставка/Замена"+CHR(13)+CHR(10)+; 
"Ctrl-N.............................вставить строку"+CHR(13)+CHR(10)+; 
"Ctrl-B....................реформатировать параграф"+CHR(13)+CHR(10)+; 
"Del....................удалить символ над курсором"+CHR(13)+CHR(10)+; 
"Backspace..........удалить символ слева от курсора"+CHR(13)+CHR(10)+; 
"Ctrl-T........................удалить слово справа"+CHR(13)+CHR(10)+; 
"Ctrl-Y......................удалить текущую строку"+CHR(13)+CHR(10)+; 
"Ctrl-W /F10/...завершить с сохранением результатов"+CHR(13)+CHR(10)+; 
"Esc.......................завершить без сохранения"
If ((nWiSave:=;
  NewWindow(9,13,12,55,"[ Помощь ]",2,.F.,.T.,aColHelp[2])) < 0)
  RETURN (Nil)
EndIF
bF1:=SetKey(K_F1,Nil)
SetCursor(0)
SetColor(aColHelp[1])
//MemoEdit(If(DbSeek(n),FIELD->NOTE,""),1,2,10,53,.F.)
MemoEdit(cMemo,1,2,10,53,.F.)
SetKey(K_F1,bF1) //; DBGoTo(nRecSave)
If (WCLOSE() != nWiSave)
  WSELECT(nWiSave)
EndIF
RestSet(aVarSave)
RETURN (Nil)

*

FUNCTION MessBloknot(cTask, dData)
LOCAL aSet:=SaveSet(), aF:=SaveSetKey(), cString:='', nC:=SetCursor()
LOCAL nTop:=04, nLeft:=15, nBottom:=20, nRight:=61
LOCAL cData:=If(dData==NIL, DTOS(Date()), DTOS(dData))
BEGIN SEQUENCE
If !NetUse("Bloknot","Bloknot","Bloknot")
  Error_Use()
  Break
EndIF
Select("Bloknot")
If DbSeek( cTask+cData )
  cString := FIELD->NOTE
  If YesOrNo("Найдено сообщение в записной книжке. Показать ?")
    ShadowBox('', nTop, nLeft, nBottom, nRight, COL_BROWSE, , .T.)
    Title( nTop, '[ Страничка записной книжки ]', nLeft+1, nRight-1, "═", COL_BROWSE)
    SetCursor(0)
    SetColor(COL_BROWSE)
    MemoEdit(cString, nTop+2, nLeft+2, nBottom-2, nRight-2, .F.)
    SetCursor(nC)
  EndIF
EndIf
BLOKNOT->(DBCloseArea())
END SEQUENCE
RestSet(aSet); RestSetKey(aF)
RETURN NIL

*
