⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memo.cpp

📁 一个通讯管理机的源代码。比较好用。推荐
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************                          memo.cpp  -  description                             -------------------    begin                : Thu Jan 17 2002    copyright            : (C) 2002 by     email                :  ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************//*  $Id: memo.cpp,v 1.5 2000/11/07 20:31:20 dbryson Exp $    Xbase project source code    This file contains the basic Xbase routines for handling    dBASE III+ and dBASE IV style memo .dbt files    Copyright (C) 1997  StarTech, Gary A. Kunkel       This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Lesser General Public    License as published by the Free Software Foundation; either    version 2.1 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Lesser General Public License for more details.    You should have received a copy of the GNU Lesser General Public    License along with this library; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    Contact:      Mail:        Technology Associates, Inc.        XBase Project        1455 Deming Way #11        Sparks, NV 89434        USA      Email:        xbase@techass.com      See our website at:        xdb.sourceforge.net    V 1.0   10/10/97   - Initial release of software    V 1.5   1/2/98     - Added memo field support    V 1.6a  4/1/98     - Added expression support    V 1.6b  4/8/98     - Numeric index keys    V 1.7.1 5/25/98    - Added support for dBase III+ type memo files*/#ifdef __WIN32__#include "xbconfigw32.h"#else#include "xbconfig.h"#endif#include "xbase.h"#ifdef XB_MEMO_FIELDS#include <stdio.h>#include "xbexcept.h"/*! \file memo.cpp*//************************************************************************///! Short description/*!*/xbLong xbDbf::CalcLastDataBlock(){  xbShort rc;  if(( rc = fseek( mfp, 0, SEEK_END )) != 0 )    xb_error( XB_SEEK_ERROR );  return ( ftell( mfp ) / MemoHeader.BlockSize );}/************************************************************************///! Short description/*!  \param BlocksNeeded  \param Location  \param PrevNode*/xbShort xbDbf::GetBlockSetFromChain( const xbLong BlocksNeeded,   const xbLong Location, const xbLong PrevNode )/* this routine grabs a set of blocks out of the free block chain  */  {  xbShort rc;  xbLong NextFreeBlock2, NewFreeBlocks, SaveNextFreeBlock;  if(( rc = ReadMemoBlock( Location, 2 )) != XB_NO_ERROR )    xb_error( rc );  if( BlocksNeeded == FreeBlockCnt )  /* grab this whole set of blocks */  {    if( PrevNode == 0 )    /* first in the chain */    {      MemoHeader.NextBlock = NextFreeBlock;      if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR )        xb_error( rc );    }    else  /* remove out of the middle or end */    {      NextFreeBlock2 = NextFreeBlock;      if(( rc = ReadMemoBlock( PrevNode, 2 )) != XB_NO_ERROR )        xb_error( rc );      NextFreeBlock = NextFreeBlock2;      if(( rc = WriteMemoBlock( PrevNode, 2 )) != XB_NO_ERROR )        xb_error( rc );    }  }  else  /* only take a portion of this set */  {    if( PrevNode == 0 )  /* first in the set */    {      MemoHeader.NextBlock = Location + BlocksNeeded;      if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR )        xb_error( rc );      FreeBlockCnt -= BlocksNeeded;      if(( rc = WriteMemoBlock( MemoHeader.NextBlock, 2 )) != XB_NO_ERROR )        xb_error( rc );    }    else  /* remove out of the middle or end */    {      NewFreeBlocks = FreeBlockCnt - BlocksNeeded;      SaveNextFreeBlock = NextFreeBlock;       NextFreeBlock2= Location + BlocksNeeded;      if(( rc = ReadMemoBlock( PrevNode, 2 )) != XB_NO_ERROR )        xb_error( rc );      NextFreeBlock = NextFreeBlock2;      if(( rc = WriteMemoBlock( PrevNode, 2 )) != XB_NO_ERROR )        xb_error( rc );      FreeBlockCnt = NewFreeBlocks;      NextFreeBlock = SaveNextFreeBlock;      if(( rc = WriteMemoBlock( NextFreeBlock2, 2 )) != XB_NO_ERROR )        xb_error( rc );    }  }  return 0;}   /************************************************************************///! Short description/*!  \param BlocksNeeded  \param LastDataBlock  \param Location  \param PreviousNode*/xbShort xbDbf::FindBlockSetInChain( const xbLong BlocksNeeded,   const xbLong LastDataBlock, xbLong &Location, xbLong &PreviousNode )/* this routine searches thru the free node chain in a dbase IV type      memo file searching for a place to grab some free blocks for reuse    LastDataBlock- is the last data block in the file, enter 0                  for the routine to calculate it.   BlocksNeeded - is the size to look in the chain for   Location     - is the location it finds   PreviousNode - is the block number of the node imediately previous                  to this node in the chain - 0 if header node   returns - 0 if no spot in chain found             1 if spot in chain is found*/{  xbShort rc;  xbLong LDB, PrevNode, CurNode;  if( LastDataBlock == 0 )    LDB = CalcLastDataBlock();  else    LDB = LastDataBlock;      if( MemoHeader.NextBlock < LDB ){    PrevNode = 0L;    CurNode = MemoHeader.NextBlock;    if(( rc = ReadMemoBlock( MemoHeader.NextBlock, 2 )) != XB_NO_ERROR )      return rc;    while( BlocksNeeded > FreeBlockCnt && NextFreeBlock < LDB ){      PrevNode = CurNode;      CurNode = NextFreeBlock;      if(( rc = ReadMemoBlock( NextFreeBlock, 2 )) != XB_NO_ERROR )        return rc;    }    if( BlocksNeeded <= FreeBlockCnt ){      Location = CurNode;      PreviousNode = PrevNode;      return 1;    }    else{   /* no data found and at end of chain */      PreviousNode = CurNode;      return 0;    }  }  else{    PreviousNode = 0;    return 0;  }}/************************************************************************///! Short description/*!  \param BlockSize*/xbShort xbDbf::SetMemoBlockSize( const xbShort BlockSize ){   if(IsType3Dbt())     return XB_NO_ERROR;    // not applicable for type 3   if( BlockSize % 512 != 0 )     xb_error(XB_INVALID_BLOCK_SIZE);   MemoHeader.BlockSize = BlockSize;   return XB_NO_ERROR;}/***********************************************************************///! Short description/*!  \param Option*/xbShort xbDbf::GetDbtHeader( const xbShort Option ){   char *p;   xbShort i;   char MemoBlock[24];   /*  Option = 0  -->  read only first four bytes                1  -->  read the entire thing  */   if( !mfp )     xb_error(XB_NOT_OPEN);   if( fseek( mfp, 0, SEEK_SET ))     xb_error(XB_SEEK_ERROR);   if(( fread( MemoBlock, 24, 1, mfp )) != 1 )     xb_error(XB_READ_ERROR);   p = MemoBlock;   MemoHeader.NextBlock = xbase->GetLong( p );    if(IsType3Dbt() || Option == 0)     return XB_NO_ERROR;    /* version IV stuff follows */   p+=8;   for( i = 0; i < 8; i++, p++ )      MemoHeader.FileName[i] = *p;   MemoHeader.Version  = *p;   p+=4;   MemoHeader.BlockSize = xbase->GetShort( p );    return XB_NO_ERROR;}/***********************************************************************///! Short description/*!*/xbShort xbDbf::OpenMemoFile( void ){   xbLong  Size, NewSize, l;   xbShort len, rc;   len = DatabaseName.len() - 1;   char lb = DatabaseName.getCharacter( len );   if( lb == 'F' )     DatabaseName.putAt(len, 'T');   else if( lb == 'f' )     DatabaseName.putAt(len, 't');   else     xb_error(XB_INVALID_NAME);   if(( mfp = fopen( DatabaseName, "r+b" )) == NULL ){     DatabaseName.putAt(len, lb);     xb_open_error(DatabaseName);   }#ifdef XB_LOCKING_ON   setbuf( mfp, NULL );#endif   DatabaseName.putAt(len, lb);   if(( rc = GetDbtHeader(1)) != 0 )   {     fclose( mfp );     return rc;   }   len = GetMemoBlockSize();   if( len == 0 || ((len % 512) != 0 ))   {     fclose( mfp );     xb_error(XB_INVALID_BLOCK_SIZE);   }   /* logic to verify file size is a multiple of block size */   if(( rc = fseek( mfp, 0, SEEK_END )) != 0 )   {     fclose( mfp );     xb_io_error(XB_SEEK_ERROR, DatabaseName);   }   /* if the file is not a multiple of block size, fix it, append nulls */   Size = ftell( mfp );   if(( Size % MemoHeader.BlockSize ) != 0 )   {     NewSize = ( Size / MemoHeader.BlockSize + 1) * MemoHeader.BlockSize;     for( l = Size; l < NewSize; l++ )       fputc( 0x00, mfp );   }   if(( mbb = (void *) malloc(len)) == NULL )   {     fclose( mfp );     xb_memory_error;   }   return XB_NO_ERROR;}/***********************************************************************///! Short description/*!*/xbShort xbDbf::CreateMemoFile( void ){   xbShort len,i;   char  *sp;   char  buf[4];   len = GetMemoBlockSize();   if( len == 0 || len % 512 != 0 )     xb_error(XB_INVALID_BLOCK_SIZE);   if(( sp = (char*)strrchr(DatabaseName, PATH_SEPARATOR)) != NULL )     sp++;   else     sp = MemoHeader.FileName;   memset( MemoHeader.FileName, 0x00, 8 );   for( i = 0; i < 8 && *sp != '.'; i++ )     MemoHeader.FileName[i] = *sp++;   len = DatabaseName.len() - 1;   char lb = DatabaseName.getCharacter( len );   if( lb == 'F' )     DatabaseName.putAt(len, 'T');   else if( lb == 'f' )     DatabaseName.putAt(len, 't');   else     xb_io_error(XB_INVALID_NAME, DatabaseName);   /* Initialize the variables */   MemoHeader.NextBlock = 1L;   if(( mfp = fopen( DatabaseName, "w+b" )) == NULL )   {     DatabaseName.putAt(len, lb);     xb_open_error(DatabaseName);   }#ifdef XB_LOCKING_ON   setbuf( mfp, NULL );#endif   DatabaseName.putAt(len, lb);   if(( fseek( mfp, 0L, SEEK_SET )) != 0 )   {     fclose( mfp );     xb_io_error(XB_SEEK_ERROR, DatabaseName);   }   memset( buf, 0x00, 4 );   xbase->PutLong( buf, MemoHeader.NextBlock );   if(( fwrite( &buf, 4, 1, mfp )) != 1 )    {     fclose( mfp );     xb_io_error(XB_WRITE_ERROR, DatabaseName);   }   if( IsType3Dbt() )   /* dBASE III+ */   {     for( i = 0; i < 12; i++ )  fputc( 0x00, mfp );     fputc( 0x03, mfp );     for( i = 0; i < 495; i++ ) fputc( 0x00, mfp );   }   else   {     for( i = 0; i < 4; i++ )  fputc( 0x00, mfp );     fwrite( &MemoHeader.FileName,  8, 1, mfp );     for( i = 0; i < 4; i++ )  fputc( 0x00, mfp );     memset( buf, 0x00, 2 );     xbase->PutShort( buf, MemoHeader.BlockSize );     if(( fwrite( &buf, 2, 1, mfp )) != 1 )      {       fclose( mfp );       xb_io_error(XB_WRITE_ERROR, DatabaseName);     }     for( i = 22; i <  MemoHeader.BlockSize; i++ ) fputc( 0x00, mfp );   }           if(( mbb = (void *) malloc( MemoHeader.BlockSize )) == NULL )   {     fclose( mfp );     xb_memory_error;   }   return XB_NO_ERROR;}/***********************************************************************///! Short description/*!  \param BlockNo  \param Option*//* Option = 0 - 1st Block of a set of valid data blocks, load buckets  *//* Option = 1 - subsequant block of data in a multi block set or db III*//* Option = 2 - 1st block of a set of free blocks, load buckets        */                     /* Option = 3 - read 8 bytes of a block, don't load any buckets        *//* Option = 4 - read 8 bytes of a block, load data buckets             */xbShort xbDbf::ReadMemoBlock( const xbLong BlockNo, const xbShort Option ){   xbLong ReadSize;   CurMemoBlockNo = -1;   if( BlockNo < 1L )     xb_error(XB_INVALID_BLOCK_NO);   if( fseek( mfp,(xbLong) BlockNo * MemoHeader.BlockSize, SEEK_SET ))     xb_error(XB_SEEK_ERROR);   if( Option ==  0 || Option == 1 )     ReadSize = MemoHeader.BlockSize;   else     ReadSize = 8L;   if(fread( mbb, ReadSize, 1, mfp ) != 1 )     xb_error(XB_READ_ERROR);   if( Option == 0 || Option == 4) // 1st block of a set of valid data blocks   {     mfield1   = xbase->GetShort( (char *) mbb );     MStartPos = xbase->GetShort( (char *) mbb+2 );     MFieldLen = xbase->GetLong ( (char *) mbb+4 );   }   else if( Option == 2 )    // 1st block of a set of free blocks   {     NextFreeBlock = xbase->GetLong( (char *) mbb );     FreeBlockCnt  = xbase->GetLong( (char *) mbb+4 );   }      if( Option ==  0 || Option == 1 )     CurMemoBlockNo = BlockNo;   return XB_NO_ERROR;}/************************************************************************///! Short description/*!  \param BlockNo  \param Option*/xbShort xbDbf::WriteMemoBlock( const xbLong BlockNo, const xbShort Option ){/* Option = 0 - 1st Block of a set of valid data blocks, set buckets    *//* Option = 1 - subsequant block of data in a multi block set or db III *//* Option = 2 - 1st block of a set offree blocks, set buckets           */                        xbLong WriteSize;   if( BlockNo < 1L )     xb_error(XB_INVALID_BLOCK_NO);   CurMemoBlockNo = -1;   if( Option == 0 )   {     xbase->PutShort( (char *) mbb, mfield1 );     xbase->PutShort( (char *) mbb+2, MStartPos );     xbase->PutLong ( (char *) mbb+4, MFieldLen );     WriteSize = MemoHeader.BlockSize;   }   else if( Option == 2 )   {     xbase->PutLong((char *) mbb, NextFreeBlock );     xbase->PutLong((char *) mbb+4, FreeBlockCnt );     WriteSize = 8L;   }   else     WriteSize = MemoHeader.BlockSize;   if( fseek( mfp,(xbLong) BlockNo * MemoHeader.BlockSize, SEEK_SET ))     xb_error(XB_SEEK_ERROR);   if(( fwrite( mbb, WriteSize, 1, mfp )) != 1 )      xb_error(XB_WRITE_ERROR);   if( Option == 0 || Option == 1 )      CurMemoBlockNo = BlockNo;   return XB_NO_ERROR;}/***********************************************************************///! Short description/*!  \param FieldNo  \param len  \param Buf  \param LockOpt*/xbShort xbDbf::GetMemoField( const xbShort FieldNo, const xbLong len,         char * Buf, const xbShort LockOpt ){   xbLong BlockNo, Tcnt, Scnt;   char *tp, *sp;           /* target and source pointers */   xbShort rc;   xbShort Vswitch;   if( FieldNo < 0 || FieldNo > ( NoOfFields - 1 ))     xb_error(XB_INVALID_FIELDNO);   if( GetFieldType( FieldNo ) != 'M' )     xb_error(XB_NOT_MEMO_FIELD);#ifdef XB_LOCKING_ON   if( LockOpt != -1 )      if(( rc = LockMemoFile( LockOpt, F_RDLCK )) != XB_NO_ERROR )         return XB_LOCK_FAILED;#endif   if(( BlockNo = GetLongField( FieldNo )) == 0 )   {#ifdef XB_LOCKING_ON     if( LockOpt != -1 )       LockMemoFile( F_SETLK, F_UNLCK );#endif     xb_error(XB_NO_MEMO_DATA);   }   if( IsType3Dbt() )      Vswitch = 1;   else       Vswitch = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -