2
This file is part of Konsole, an X terminal.
3
Copyright (C) 2000 by Stephan Kulow <coolo@kde.org>
5
Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
#include "BlockArray.h"
32
#include <sys/param.h>
37
using namespace Konsole;
39
static int blocksize = 0;
41
BlockArray::BlockArray()
43
current( size_t( -1 ) ),
44
index( size_t( -1 ) ),
46
lastmap_index( size_t( -1 ) ),
47
lastblock( 0 ), ion( -1 ),
50
// lastmap_index = index = current = size_t(-1);
52
blocksize = (( sizeof( Block ) / getpagesize() ) + 1 ) * getpagesize();
56
BlockArray::~BlockArray()
62
size_t BlockArray::append( Block *block )
68
if ( current >= size ) current = 0;
71
rc = lseek( ion, current * blocksize, SEEK_SET ); if ( rc < 0 ) { perror( "HistoryBuffer::add.seek" ); setHistorySize( 0 ); return size_t( -1 ); }
72
rc = write( ion, block, blocksize ); if ( rc < 0 ) { perror( "HistoryBuffer::add.write" ); setHistorySize( 0 ); return size_t( -1 ); }
75
if ( length > size ) length = size;
83
size_t BlockArray::newBlock()
89
lastblock = new Block();
93
Block *BlockArray::lastBlock() const
98
bool BlockArray::has( size_t i ) const
100
if ( i == index + 1 )
105
if ( index - i >= length )
110
const Block* BlockArray::at( size_t i )
112
if ( i == index + 1 )
115
if ( i == lastmap_index )
120
qDebug() << "BlockArray::at() i > index\n";
124
// if (index - i >= length) {
125
// kDebug(1211) << "BlockArray::at() index - i >= length\n";
129
size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
134
Block *block = ( Block* )mmap( 0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize );
136
if ( block == ( Block* ) - 1 ) { perror( "mmap" ); return 0; }
144
void BlockArray::unmap()
148
int res = munmap(( char* )lastmap, blocksize );
149
if ( res < 0 ) perror( "munmap" );
152
lastmap_index = size_t( -1 );
155
bool BlockArray::setSize( size_t newsize )
157
return setHistorySize( newsize * 1024 / blocksize );
160
bool BlockArray::setHistorySize( size_t newsize )
162
// kDebug(1211) << "setHistorySize " << size << " " << newsize;
164
if ( size == newsize )
173
if ( ion >= 0 ) close( ion );
175
current = size_t( -1 );
181
FILE* tmp = tmpfile();
184
perror( "konsole: cannot open temp file.\n" );
188
ion = dup( fileno( tmp ) );
191
perror( "konsole: cannot dup temp file.\n" );
198
assert( !lastblock );
200
lastblock = new Block();
205
if ( newsize > size )
213
decreaseBuffer( newsize );
214
ftruncate( ion, length*blocksize );
221
void moveBlock( FILE *fion, int cursor, int newpos, char *buffer2 )
223
int res = fseek( fion, cursor * blocksize, SEEK_SET );
226
res = fread( buffer2, blocksize, 1, fion );
230
res = fseek( fion, newpos * blocksize, SEEK_SET );
233
res = fwrite( buffer2, blocksize, 1, fion );
236
// printf("moving block %d to %d\n", cursor, newpos);
239
void BlockArray::decreaseBuffer( size_t newsize )
241
if ( index < newsize ) // still fits in whole
244
int offset = ( current - ( newsize - 1 ) + size ) % size;
249
// The Block constructor could do somthing in future...
250
char *buffer1 = new char[blocksize];
252
FILE *fion = fdopen( dup( ion ), "w+b" );
256
perror( "fdopen/dup" );
261
if ( current <= newsize )
263
firstblock = current + 1;
271
for ( size_t i = 0, cursor = firstblock; i < newsize; i++ )
273
oldpos = ( size + cursor + offset ) % size;
274
moveBlock( fion, oldpos, cursor, buffer1 );
275
if ( oldpos < newsize )
283
current = newsize - 1;
292
void BlockArray::increaseBuffer()
294
if ( index < size ) // not even wrapped once
297
int offset = ( current + size + 1 ) % size;
298
if ( !offset ) // no moving needed
301
// The Block constructor could do somthing in future...
302
char *buffer1 = new char[blocksize];
303
char *buffer2 = new char[blocksize];
306
int bpr = size; // blocks per run
308
if ( size % offset == 0 )
314
FILE *fion = fdopen( dup( ion ), "w+b" );
317
perror( "fdopen/dup" );
324
for ( int i = 0; i < runs; i++ )
326
// free one block in chain
327
int firstblock = ( offset + i ) % size;
328
res = fseek( fion, firstblock * blocksize, SEEK_SET );
331
res = fread( buffer1, blocksize, 1, fion );
335
for ( int j = 1, cursor = firstblock; j < bpr; j++ )
337
cursor = ( cursor + offset ) % size;
338
newpos = ( cursor - offset + size ) % size;
339
moveBlock( fion, cursor, newpos, buffer2 );
341
res = fseek( fion, i * blocksize, SEEK_SET );
344
res = fwrite( buffer1, blocksize, 1, fion );