#include best5.h

* NewID

function NewID(cTableName as String) as Integer 

  local nID as Integer 

  if Empty(cTableName)
    cTableName = JustStem(Dbf())
  endif  
  
  if !Used("generator")
    use generator in 0 alias generator shared
  endif
      
  if Seek(cTableName, "generator", "tablename")
    RLock("generator")
    nID = generator.lastid    
    if nID = 2147483647
      p1 = cTableName
      error ERROR_GENERATOR_OVERFLOW 
    else  
      nID = nID + 1
    endif  
    replace lastid with nID in generator
    unlock in generator
  else
    p1 = cTableName
    error ERROR_GENERATOR_TABLE 
  endif
  
  if Type("LastGeneratedIDHolder") == "U"
    public LastGeneratedIDHolder as Integer
  endif  
  LastGeneratedIDHolder = nID
  
  return nID
endfunc

* LastGeneratedID

function LastGeneratedID() as Integer

  if Type("LastGeneratedIDHolder") == "U"
    return .NULL.
  else
    return LastGeneratedIDHolder 
  endif  
endfunc

* NewGuid

function NewGuid() as String @
  
  local cGuid as String 
  declare Integer CoCreateGuid in ole32.dll String @
  
  cGuid = Space(16)
  CoCreateGuid(@cGuid)
  DO WHILE ASC(LEFT(cGuid,1))=0
	  CoCreateGuid(@cGuid)
  ENDDO
  return cGuid
endfunc

* GuidToIdx

function GuidToIdx(cGuid as String) as String

  local cGuidString as String 

  declare Integer StringFromGUID2 in ole32.dll String, String @, Integer    

  cGuidString = Space(38*2)
  StringFromGuid2(cGuid, @cGuidString, Len(cGuidString))
  return StrConv(cGuidString, 6)
endfunc

* События базы данных

* Before DBC is closed. Return .F. to prevent DBC from being closed.
procedure dbc_CloseData(cDatabaseName, lAll)

  DBSetProp(cDatabaseName, "DATABASE", "DBCEvents", .F.)
  return .T.  
endproc

* Just before a table or view is opened. Return .F. to prevent table or view being opened.
procedure dbc_BeforeOpenTable(cTableName)

  cTableName = Lower(cTableName)
  if !(Substr(cTableName, 1, Len(OWNED_AREA_PREFIX)) == OWNED_AREA_PREFIX)
	  CheckSpaceInUsePool(cTableName)
  endif  
  return .T.
endproc 

* After a table or view is opened.
procedure dbc_AfterOpenTable(cTableName)

  cTableName = Lower(cTableName)
  if !(Substr(cTableName, 1, Len(OWNED_AREA_PREFIX)) == OWNED_AREA_PREFIX)
    UpdateUsePool(cTableName)
  endif  
endproc

* Функции использующиеся в индексах

* If

FUNCTION if
LPARAMETERS l1, c1, c2
IF l1
  RETURN c1
ELSE
  RETURN c2
ENDIF
endfunc

* _Descend 

FUNCTION _DESCEND
LPARAMETERS p1
LOCAL i, cTMP
DO CASE
  CASE TYPE("p1")=="C"
    cTMP=""
    FOR i=1 TO LEN(p1)
      cTMP=cTMP+CHR(256-ASC(SUBSTR(p1,i,1)))
    ENDFOR
    RETURN cTMP
  CASE TYPE("p1")=="D"
    RETURN 5231808-VAL(SYS(11,p1))
  CASE TYPE("p1")=="N"
    RETURN -1*p1
  CASE TYPE("p1")=="L"
    RETURN !p1
ENDCASE
RETURN .T.
ENDFUNC

* MemoLine

FUNCTION MemoLine
LPARAMETERS cMemo, nKolSumbols, nLine
IF !EMPTY(nLine)
  RETURN MLINE(cMemo, nLine , nKolSumbols)
ELSE
  RETURN IIF(LEN(SUBSTR(cMemo, 1, nKolSumbols))=0," ",SUBSTR(cMemo, 1, nKolSumbols))
ENDIF
ENDFUNC


* STOD

FUNCTION STOD
&& Преобразует к дате
&& Исправлена 15.11.1999
PARAMETERS cData
PRIVATE cSetCentur, dRet

&& "Старая" версия закоментирована
&& PARAMETERS cData
&& IF !EMPTY(cData)
&&   RETURN CTOD( SUBSTR(cData,7,2)+"/"+SUBSTR(cData,5,2)+"/"+SUBSTR(cData,3,2))
&& ENDIF
&& RETURN CTOD("  /  /  ")

IF EMPTY(cData)
  dRet = CTOD("  /  /  ")
ELSE
  cSetCentur = SET( "CENTURY" )
  SET CENTURY ON
  dRet = CTOD( SUBSTR( cData, 7, 2 ) + "/" +;
  SUBSTR( cData, 5, 2 ) + "/" + SUBSTR( cData, 1, 4 ) )
  SET CENTURY &cSetCentur.
ENDIF
RETURN dRet

* XTOC

FUNCTION XTOC
&& Преобразует к символьной строке
PARAMETERS xVar
PRIVATE cType,cRet
cRet = ''
cType = TYPE('xVar')
DO CASE
 CASE cType = 'L'
   cRet = IIF(xVar,"T","F")
 CASE cType = 'C'
   cRet = xVar
 CASE cType = 'D'
   cRet = DTOS(xVar)
 CASE cType = 'N'
   cRet = FTOC(xVar)
ENDCASE
RETURN cRet

* FTOC

FUNCTION FTOC
PARAMETERS nVar
RETURN ""

* CTOF

FUNCTION CTOF
PARAMETERS cVar
LOCAL nRet
nRet = 0
cVar = PADR( cVar, 8, CHR( 0 ) )
DO CASE
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR( 240 ) + CHR(  63 )
    nRet = 1
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(  64 )
    nRet = 2
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(   8 ) + CHR(  64 )
    nRet = 3
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(  16 ) + CHR(  64 )
    nRet = 4
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(  20 ) + CHR(  64 )
    nRet = 5
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(  24 ) + CHR(  64 )
    nRet = 6
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(  28 ) + CHR(  64 )
    nRet = 7
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(  32 ) + CHR(  64 )
    nRet = 8
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(  34 ) + CHR(  64 )
    nRet = 9
  CASE cVar = CHR(   0 ) + CHR(   0 ) + CHR(   0 ) + CHR(   0 ) +;
              CHR(   0 ) + CHR(   0 ) + CHR(  36 ) + CHR(  64 )
    nRet = 10
ENDCASE
RETURN nRet

&& ФУНКЦИИ РАБОТЫ С ДАТАМИ, ДЛЯ ФОРМАТА ПЕРИОДА ПРИНЯТОГО В BEST 

&& Функция возвращает названия месяца
FUNCTION B_CMonth(cBestPeriod as String) AS String  
 IF EMPTY(cBestPeriod) THEN
    	RETURN SPACE(8)
 ELSE
  LOCAL NumMonth, cNameMonth
  NumMonth=Val(RIGHT(cBestPeriod,2))
  DO CASE
  	CASE NumMonth=1
  		cNameMonth="Январь"
  	CASE NumMonth=2  
  		cNameMonth="Февраль"
  	CASE NumMonth=3
  		cNameMonth="Март"
  	CASE NumMonth=4
  		cNameMonth="Апрель"  		
  	CASE NumMonth=5
  		cNameMonth="Май"
  	CASE NumMonth=6
  		cNameMonth="Июнь"
  	CASE NumMonth=7
  		cNameMonth="Июль"
  	CASE NumMonth=8
  		cNameMonth="Август"
  	CASE NumMonth=9
  		cNameMonth="Сентябрь"
  	CASE NumMonth=10
  		cNameMonth="Октябрь"
  	CASE NumMonth=11
  		cNameMonth="Ноябрь"
  	CASE NumMonth=12  
  		cNameMonth="Декабрь"
  	OTHERWISE
  		cNameMonth=RIGHT(cBestPeriod,2)
  ENDCASE
  RETURN PADR(cNameMonth,8)
 ENDIF
ENDFUNC

FUNCTION B_DayInMonth(cBestPeriod as String) AS Integer
    IF EMPTY(cBestPeriod) THEN
    	RETURN -1
    ELSE
		RETURN DATE(IIF(Val(RIGHT(cBestPeriod,2) )=12,Val(LEFT(cBestPeriod,4))+1,Val(LEFT(cBestPeriod,4))) ,IIF(Val(RIGHT(cBestPeriod,2) )=12,1,Val(RIGHT(cBestPeriod,2) )+1), 1 )-DATE(Val(LEFT(cBestPeriod,4)) ,Val(RIGHT(cBestPeriod,2) ), 1 )
	ENDIF
ENDFUNC

&& Функция возвращает год
FUNCTION B_Year(cBestPeriod as String) AS String  
    IF EMPTY(cBestPeriod) THEN
    	RETURN SPACE(4)
    ELSE
   		RETURN LEFT(cBestPeriod,4)
   	ENDIF
ENDFUNC

&& Функция возвращает месяц
FUNCTION B_Month(cBestPeriod as String) AS String  
    IF EMPTY(cBestPeriod) THEN
    	RETURN SPACE(2)
    ELSE
   		RETURN RIGHT(cBestPeriod,2)
   	ENDIF
ENDFUNC

&& Последний день месяца.
FUNCTION EOM(dDate as Date ) AS Date
    IF EMPTY(dDate) THEN
    	RETURN {..}
    ELSE
    	IF MONTH(dDate)=12
	   		RETURN DATE(YEAR(dDate)+1,1,1)-1
   		ELSE
	   		RETURN DATE(YEAR(dDate),MONTH(dDate)+1,1)-1
   		ENDIF
   	ENDIF
ENDFUNC

&& Первый день месяца (для особо ленивых)
FUNCTION BOM (dDate as Date ) AS Date
	RETURN DATE(YEAR(dDate),MONTH(dDate),1)
ENDFUNC

&& Перекодировка мемо полей из аляски.
FUNCTION ConvertMemo (cMemo as Character, cReplace as Character ) as Character
RETURN STRTRAN(cMemo,CHR(205)+CHR(10),IIF(VARTYPE(cReplace)=="C",cReplace,""))
ENDFUNC

* NewB5Guid_22
function NewB5Guid_22() as String @
  local cGuid as String 
  declare Integer genguid22 in b5common.dll String @
  
  cGuid = Space(22)
  genguid22(@cGuid)
  
  return cGuid
endfunc
