2 This file is part of Konsole, an X terminal.
3 Copyright 2000 by Stephan Kulow <coolo@kde.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 #include "BlockArray.h"
27 #include <sys/param.h>
35 using namespace Konsole
;
37 static int blocksize
= 0;
39 BlockArray::BlockArray()
44 lastmap_index(size_t(-1)),
45 lastblock(0), ion(-1),
48 // lastmap_index = index = current = size_t(-1);
50 blocksize
= ((sizeof(Block
) / getpagesize()) + 1) * getpagesize();
54 BlockArray::~BlockArray()
60 size_t BlockArray::append(Block
*block
)
66 if (current
>= size
) current
= 0;
69 rc
= KDE_lseek(ion
, current
* blocksize
, SEEK_SET
); if (rc
< 0) { perror("HistoryBuffer::add.seek"); setHistorySize(0); return size_t(-1); }
70 rc
= write(ion
, block
, blocksize
); if (rc
< 0) { perror("HistoryBuffer::add.write"); setHistorySize(0); return size_t(-1); }
73 if (length
> size
) length
= size
;
81 size_t BlockArray::newBlock()
87 lastblock
= new Block();
91 Block
*BlockArray::lastBlock() const
96 bool BlockArray::has(size_t i
) const
103 if (index
- i
>= length
)
108 const Block
* BlockArray::at(size_t i
)
113 if (i
== lastmap_index
)
117 kDebug(1211) << "BlockArray::at() i > index\n";
121 // if (index - i >= length) {
122 // kDebug(1211) << "BlockArray::at() index - i >= length\n";
126 size_t j
= i
; // (current - (index - i) + (index/size+1)*size) % size ;
131 Block
*block
= (Block
*)mmap(0, blocksize
, PROT_READ
, MAP_PRIVATE
, ion
, j
* blocksize
);
133 if (block
== (Block
*)-1) { perror("mmap"); return 0; }
141 void BlockArray::unmap()
144 int res
= munmap((char*)lastmap
, blocksize
);
145 if (res
< 0) perror("munmap");
148 lastmap_index
= size_t(-1);
151 bool BlockArray::setSize(size_t newsize
)
153 return setHistorySize(newsize
* 1024 / blocksize
);
156 bool BlockArray::setHistorySize(size_t newsize
)
158 // kDebug(1211) << "setHistorySize " << size << " " << newsize;
168 if (ion
>= 0) close(ion
);
170 current
= size_t(-1);
175 FILE* tmp
= tmpfile();
177 perror("konsole: cannot open temp file.\n");
179 ion
= dup(fileno(tmp
));
181 perror("konsole: cannot dup temp file.\n");
190 lastblock
= new Block();
195 if (newsize
> size
) {
200 decreaseBuffer(newsize
);
201 ftruncate(ion
, length
*blocksize
);
208 void moveBlock(FILE *fion
, int cursor
, int newpos
, char *buffer2
)
210 int res
= KDE_fseek(fion
, cursor
* blocksize
, SEEK_SET
);
213 res
= fread(buffer2
, blocksize
, 1, fion
);
217 res
= KDE_fseek(fion
, newpos
* blocksize
, SEEK_SET
);
220 res
= fwrite(buffer2
, blocksize
, 1, fion
);
223 // printf("moving block %d to %d\n", cursor, newpos);
226 void BlockArray::decreaseBuffer(size_t newsize
)
228 if (index
< newsize
) // still fits in whole
231 int offset
= (current
- (newsize
- 1) + size
) % size
;
236 // The Block constructor could do somthing in future...
237 char *buffer1
= new char[blocksize
];
239 FILE *fion
= fdopen(dup(ion
), "w+b");
242 perror("fdopen/dup");
247 if (current
<= newsize
) {
248 firstblock
= current
+ 1;
254 for (size_t i
= 0, cursor
=firstblock
; i
< newsize
; i
++) {
255 oldpos
= (size
+ cursor
+ offset
) % size
;
256 moveBlock(fion
, oldpos
, cursor
, buffer1
);
257 if (oldpos
< newsize
) {
263 current
= newsize
- 1;
272 void BlockArray::increaseBuffer()
274 if (index
< size
) // not even wrapped once
277 int offset
= (current
+ size
+ 1) % size
;
278 if (!offset
) // no moving needed
281 // The Block constructor could do somthing in future...
282 char *buffer1
= new char[blocksize
];
283 char *buffer2
= new char[blocksize
];
286 int bpr
= size
; // blocks per run
288 if (size
% offset
== 0) {
293 FILE *fion
= fdopen(dup(ion
), "w+b");
295 perror("fdopen/dup");
302 for (int i
= 0; i
< runs
; i
++)
304 // free one block in chain
305 int firstblock
= (offset
+ i
) % size
;
306 res
= KDE_fseek(fion
, firstblock
* blocksize
, SEEK_SET
);
309 res
= fread(buffer1
, blocksize
, 1, fion
);
313 for (int j
= 1, cursor
=firstblock
; j
< bpr
; j
++)
315 cursor
= (cursor
+ offset
) % size
;
316 newpos
= (cursor
- offset
+ size
) % size
;
317 moveBlock(fion
, cursor
, newpos
, buffer2
);
319 res
= KDE_fseek(fion
, i
* blocksize
, SEEK_SET
);
322 res
= fwrite(buffer1
, blocksize
, 1, fion
);