~ubuntu-branches/ubuntu/raring/juffed/raring

« back to all changes in this revision

Viewing changes to plugins/terminal/qtermwidget/lib/History.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Maia Kozheva
  • Date: 2011-04-30 13:43:26 UTC
  • mfrom: (2.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20110430134326-0bnvvo5z2medbdxi
Tags: 0.9.1137-1
* New upstream release.
* Remove debian/juffed.1, added upstream (in debian.in).
* Remove debian/patches/static.patch: we can now bundle the .so after
  upstream has resolved soname issues.
* debian/control:
  - Bump Standards-Version to 0.9.2.
  - Update homepage.
  - Do not build-depend on chrpath, not needed anymore.
* debian/rules:
  - Remove chrpath rule, not needed anymore.
* Add juffed-dev and juffed-plugins packages.
* Do not install the libkeybindings.so plugin: causes a segfault on my
  amd64 machine.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file is part of Konsole, an X terminal.
 
3
    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
4
 
 
5
    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
 
6
 
 
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.
 
11
 
 
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.
 
16
 
 
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
 
20
    02110-1301  USA.
 
21
*/
 
22
 
 
23
// Own
 
24
#include "History.h"
 
25
 
 
26
// System
 
27
#include <iostream>
 
28
#include <stdlib.h>
 
29
#include <assert.h>
 
30
#include <stdio.h>
 
31
#include <sys/types.h>
 
32
#include <sys/mman.h>
 
33
#include <unistd.h>
 
34
#include <errno.h>
 
35
 
 
36
 
 
37
// Reasonable line size
 
38
#define LINE_SIZE       1024
 
39
 
 
40
using namespace Konsole;
 
41
 
 
42
/*
 
43
   An arbitrary long scroll.
 
44
 
 
45
   One can modify the scroll only by adding either cells
 
46
   or newlines, but access it randomly.
 
47
 
 
48
   The model is that of an arbitrary wide typewriter scroll
 
49
   in that the scroll is a serie of lines and each line is
 
50
   a serie of cells with no overwriting permitted.
 
51
 
 
52
   The implementation provides arbitrary length and numbers
 
53
   of cells and line/column indexed read access to the scroll
 
54
   at constant costs.
 
55
 
 
56
KDE4: Can we use QTemporaryFile here, instead of KTempFile?
 
57
 
 
58
FIXME: some complain about the history buffer comsuming the
 
59
       memory of their machines. This problem is critical
 
60
       since the history does not behave gracefully in cases
 
61
       where the memory is used up completely.
 
62
 
 
63
       I put in a workaround that should handle it problem
 
64
       now gracefully. I'm not satisfied with the solution.
 
65
 
 
66
FIXME: Terminating the history is not properly indicated
 
67
       in the menu. We should throw a signal.
 
68
 
 
69
FIXME: There is noticeable decrease in speed, also. Perhaps,
 
70
       there whole feature needs to be revisited therefore.
 
71
       Disadvantage of a more elaborated, say block-oriented
 
72
       scheme with wrap around would be it's complexity.
 
73
*/
 
74
 
 
75
//FIXME: tempory replacement for tmpfile
 
76
//       this is here one for debugging purpose.
 
77
 
 
78
//#define tmpfile xTmpFile
 
79
 
 
80
// History File ///////////////////////////////////////////
 
81
 
 
82
/*
 
83
  A Row(X) data type which allows adding elements to the end.
 
84
*/
 
85
 
 
86
HistoryFile::HistoryFile()
 
87
  : ion(-1),
 
88
    length(0),
 
89
        fileMap(0)
 
90
{
 
91
  if (tmpFile.open())
 
92
  { 
 
93
    tmpFile.setAutoRemove(true);
 
94
    ion = tmpFile.handle();
 
95
  }
 
96
}
 
97
 
 
98
HistoryFile::~HistoryFile()
 
99
{
 
100
        if (fileMap)
 
101
                unmap();
 
102
}
 
103
 
 
104
//TODO:  Mapping the entire file in will cause problems if the history file becomes exceedingly large,
 
105
//(ie. larger than available memory).  HistoryFile::map() should only map in sections of the file at a time,
 
106
//to avoid this.
 
107
void HistoryFile::map()
 
108
{
 
109
        assert( fileMap == 0 );
 
110
 
 
111
        fileMap = (char*)mmap( 0 , length , PROT_READ , MAP_PRIVATE , ion , 0 );
 
112
 
 
113
    //if mmap'ing fails, fall back to the read-lseek combination
 
114
    if ( fileMap == MAP_FAILED )
 
115
    {
 
116
            readWriteBalance = 0; 
 
117
            fileMap = 0;
 
118
            qDebug() << ": mmap'ing history failed.  errno = " << errno;
 
119
    }
 
120
}
 
121
 
 
122
void HistoryFile::unmap()
 
123
{
 
124
        int result = munmap( fileMap , length );
 
125
        assert( result == 0 );
 
126
 
 
127
        fileMap = 0;
 
128
}
 
129
 
 
130
bool HistoryFile::isMapped()
 
131
{
 
132
        return (fileMap != 0);
 
133
}
 
134
 
 
135
void HistoryFile::add(const unsigned char* bytes, int len)
 
136
{
 
137
  if ( fileMap )
 
138
                  unmap();
 
139
                
 
140
  readWriteBalance++;
 
141
 
 
142
  int rc = 0;
 
143
 
 
144
  rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryFile::add.seek"); return; }
 
145
  rc = write(ion,bytes,len);       if (rc < 0) { perror("HistoryFile::add.write"); return; }
 
146
  length += rc;
 
147
}
 
148
 
 
149
void HistoryFile::get(unsigned char* bytes, int len, int loc)
 
150
{
 
151
  //count number of get() calls vs. number of add() calls.  
 
152
  //If there are many more get() calls compared with add() 
 
153
  //calls (decided by using MAP_THRESHOLD) then mmap the log
 
154
  //file to improve performance.
 
155
  readWriteBalance--;
 
156
  if ( !fileMap && readWriteBalance < MAP_THRESHOLD )
 
157
                  map();
 
158
 
 
159
  if ( fileMap )
 
160
  {
 
161
        for (int i=0;i<len;i++)
 
162
                        bytes[i]=fileMap[loc+i];
 
163
  }
 
164
  else
 
165
  {     
 
166
        int rc = 0;
 
167
 
 
168
        if (loc < 0 || len < 0 || loc + len > length)
 
169
        fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
 
170
        rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryFile::get.seek"); return; }
 
171
        rc = read(ion,bytes,len);     if (rc < 0) { perror("HistoryFile::get.read"); return; }
 
172
  }
 
173
}
 
174
 
 
175
int HistoryFile::len()
 
176
{
 
177
  return length;
 
178
}
 
179
 
 
180
 
 
181
// History Scroll abstract base class //////////////////////////////////////
 
182
 
 
183
 
 
184
HistoryScroll::HistoryScroll(HistoryType* t)
 
185
  : m_histType(t)
 
186
{
 
187
}
 
188
 
 
189
HistoryScroll::~HistoryScroll()
 
190
{
 
191
  delete m_histType;
 
192
}
 
193
 
 
194
bool HistoryScroll::hasScroll()
 
195
{
 
196
  return true;
 
197
}
 
198
 
 
199
// History Scroll File //////////////////////////////////////
 
200
 
 
201
/* 
 
202
   The history scroll makes a Row(Row(Cell)) from
 
203
   two history buffers. The index buffer contains
 
204
   start of line positions which refere to the cells
 
205
   buffer.
 
206
 
 
207
   Note that index[0] addresses the second line
 
208
   (line #1), while the first line (line #0) starts
 
209
   at 0 in cells.
 
210
*/
 
211
 
 
212
HistoryScrollFile::HistoryScrollFile(const QString &logFileName)
 
213
  : HistoryScroll(new HistoryTypeFile(logFileName)),
 
214
  m_logFileName(logFileName)
 
215
{
 
216
}
 
217
 
 
218
HistoryScrollFile::~HistoryScrollFile()
 
219
{
 
220
}
 
221
 
 
222
int HistoryScrollFile::getLines()
 
223
{
 
224
  return index.len() / sizeof(int);
 
225
}
 
226
 
 
227
int HistoryScrollFile::getLineLen(int lineno)
 
228
{
 
229
  return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character);
 
230
}
 
231
 
 
232
bool HistoryScrollFile::isWrappedLine(int lineno)
 
233
{
 
234
  if (lineno>=0 && lineno <= getLines()) {
 
235
    unsigned char flag;
 
236
    lineflags.get((unsigned char*)&flag,sizeof(unsigned char),(lineno)*sizeof(unsigned char));
 
237
    return flag;
 
238
  }
 
239
  return false;
 
240
}
 
241
 
 
242
int HistoryScrollFile::startOfLine(int lineno)
 
243
{
 
244
  if (lineno <= 0) return 0;
 
245
  if (lineno <= getLines())
 
246
    { 
 
247
        
 
248
        if (!index.isMapped())
 
249
                        index.map();
 
250
        
 
251
        int res;
 
252
    index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
 
253
    return res;
 
254
    }
 
255
  return cells.len();
 
256
}
 
257
 
 
258
void HistoryScrollFile::getCells(int lineno, int colno, int count, Character res[])
 
259
{
 
260
  cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character));
 
261
}
 
262
 
 
263
void HistoryScrollFile::addCells(const Character text[], int count)
 
264
{
 
265
  cells.add((unsigned char*)text,count*sizeof(Character));
 
266
}
 
267
 
 
268
void HistoryScrollFile::addLine(bool previousWrapped)
 
269
{
 
270
  if (index.isMapped())
 
271
                  index.unmap();
 
272
 
 
273
  int locn = cells.len();
 
274
  index.add((unsigned char*)&locn,sizeof(int));
 
275
  unsigned char flags = previousWrapped ? 0x01 : 0x00;
 
276
  lineflags.add((unsigned char*)&flags,sizeof(unsigned char));
 
277
}
 
278
 
 
279
 
 
280
// History Scroll Buffer //////////////////////////////////////
 
281
HistoryScrollBuffer::HistoryScrollBuffer(unsigned int maxLineCount)
 
282
  : HistoryScroll(new HistoryTypeBuffer(maxLineCount))
 
283
   ,_historyBuffer()
 
284
   ,_maxLineCount(0)
 
285
   ,_usedLines(0)
 
286
   ,_head(0)
 
287
{
 
288
  setMaxNbLines(maxLineCount);
 
289
}
 
290
 
 
291
HistoryScrollBuffer::~HistoryScrollBuffer()
 
292
{
 
293
    delete[] _historyBuffer;
 
294
}
 
295
 
 
296
void HistoryScrollBuffer::addCellsVector(const QVector<Character>& cells)
 
297
{
 
298
    _head++;
 
299
    if ( _usedLines < _maxLineCount )
 
300
        _usedLines++;
 
301
 
 
302
    if ( _head >= _maxLineCount )
 
303
    {
 
304
        _head = 0;
 
305
    }
 
306
 
 
307
    _historyBuffer[bufferIndex(_usedLines-1)] = cells;
 
308
    _wrappedLine[bufferIndex(_usedLines-1)] = false;
 
309
}
 
310
void HistoryScrollBuffer::addCells(const Character a[], int count)
 
311
{
 
312
  HistoryLine newLine(count);
 
313
  qCopy(a,a+count,newLine.begin());
 
314
 
 
315
  addCellsVector(newLine);
 
316
}
 
317
 
 
318
void HistoryScrollBuffer::addLine(bool previousWrapped)
 
319
{
 
320
    _wrappedLine[bufferIndex(_usedLines-1)] = previousWrapped;
 
321
}
 
322
 
 
323
int HistoryScrollBuffer::getLines()
 
324
{
 
325
    return _usedLines;
 
326
}
 
327
 
 
328
int HistoryScrollBuffer::getLineLen(int lineNumber)
 
329
{
 
330
  Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount );
 
331
 
 
332
  if ( lineNumber < _usedLines )
 
333
  {
 
334
    return _historyBuffer[bufferIndex(lineNumber)].size();
 
335
  }
 
336
  else
 
337
  {
 
338
    return 0;
 
339
  }
 
340
}
 
341
 
 
342
bool HistoryScrollBuffer::isWrappedLine(int lineNumber)
 
343
{
 
344
  Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount );
 
345
    
 
346
  if (lineNumber < _usedLines)
 
347
  {
 
348
    //kDebug() << "Line" << lineNumber << "wrapped is" << _wrappedLine[bufferIndex(lineNumber)];
 
349
    return _wrappedLine[bufferIndex(lineNumber)];
 
350
  }
 
351
  else
 
352
    return false;
 
353
}
 
354
 
 
355
void HistoryScrollBuffer::getCells(int lineNumber, int startColumn, int count, Character* buffer)
 
356
{
 
357
  if ( count == 0 ) return;
 
358
 
 
359
  Q_ASSERT( lineNumber < _maxLineCount );
 
360
 
 
361
  if (lineNumber >= _usedLines) 
 
362
  {
 
363
    memset(buffer, 0, count * sizeof(Character));
 
364
    return;
 
365
  }
 
366
  
 
367
  const HistoryLine& line = _historyBuffer[bufferIndex(lineNumber)];
 
368
 
 
369
  //kDebug() << "startCol " << startColumn;
 
370
  //kDebug() << "line.size() " << line.size();
 
371
  //kDebug() << "count " << count;
 
372
 
 
373
  Q_ASSERT( startColumn <= line.size() - count );
 
374
    
 
375
  memcpy(buffer, line.constData() + startColumn , count * sizeof(Character));
 
376
}
 
377
 
 
378
void HistoryScrollBuffer::setMaxNbLines(unsigned int lineCount)
 
379
{
 
380
    HistoryLine* oldBuffer = _historyBuffer;
 
381
    HistoryLine* newBuffer = new HistoryLine[lineCount];
 
382
    
 
383
    for ( int i = 0 ; i < qMin(_usedLines,(int)lineCount) ; i++ )
 
384
    {
 
385
        newBuffer[i] = oldBuffer[bufferIndex(i)];
 
386
    }
 
387
    
 
388
    _usedLines = qMin(_usedLines,(int)lineCount);
 
389
    _maxLineCount = lineCount;
 
390
    _head = ( _usedLines == _maxLineCount ) ? 0 : _usedLines-1;
 
391
 
 
392
    _historyBuffer = newBuffer;
 
393
    delete[] oldBuffer;
 
394
 
 
395
    _wrappedLine.resize(lineCount);
 
396
}
 
397
 
 
398
int HistoryScrollBuffer::bufferIndex(int lineNumber)
 
399
{
 
400
    Q_ASSERT( lineNumber >= 0 );
 
401
    Q_ASSERT( lineNumber < _maxLineCount );
 
402
    Q_ASSERT( (_usedLines == _maxLineCount) || lineNumber <= _head );
 
403
 
 
404
    if ( _usedLines == _maxLineCount )
 
405
    {
 
406
        return (_head+lineNumber+1) % _maxLineCount;
 
407
    }
 
408
    else
 
409
    {   
 
410
        return lineNumber;
 
411
    }
 
412
}
 
413
 
 
414
 
 
415
// History Scroll None //////////////////////////////////////
 
416
 
 
417
HistoryScrollNone::HistoryScrollNone()
 
418
  : HistoryScroll(new HistoryTypeNone())
 
419
{
 
420
}
 
421
 
 
422
HistoryScrollNone::~HistoryScrollNone()
 
423
{
 
424
}
 
425
 
 
426
bool HistoryScrollNone::hasScroll()
 
427
{
 
428
  return false;
 
429
}
 
430
 
 
431
int  HistoryScrollNone::getLines()
 
432
{
 
433
  return 0;
 
434
}
 
435
 
 
436
int  HistoryScrollNone::getLineLen(int)
 
437
{
 
438
  return 0;
 
439
}
 
440
 
 
441
bool HistoryScrollNone::isWrappedLine(int /*lineno*/)
 
442
{
 
443
  return false;
 
444
}
 
445
 
 
446
void HistoryScrollNone::getCells(int, int, int, Character [])
 
447
{
 
448
}
 
449
 
 
450
void HistoryScrollNone::addCells(const Character [], int)
 
451
{
 
452
}
 
453
 
 
454
void HistoryScrollNone::addLine(bool)
 
455
{
 
456
}
 
457
 
 
458
// History Scroll BlockArray //////////////////////////////////////
 
459
 
 
460
HistoryScrollBlockArray::HistoryScrollBlockArray(size_t size)
 
461
  : HistoryScroll(new HistoryTypeBlockArray(size))
 
462
{
 
463
  m_blockArray.setHistorySize(size); // nb. of lines.
 
464
}
 
465
 
 
466
HistoryScrollBlockArray::~HistoryScrollBlockArray()
 
467
{
 
468
}
 
469
 
 
470
int  HistoryScrollBlockArray::getLines()
 
471
{
 
472
  return m_lineLengths.count();
 
473
}
 
474
 
 
475
int  HistoryScrollBlockArray::getLineLen(int lineno)
 
476
{
 
477
    if ( m_lineLengths.contains(lineno) )
 
478
        return m_lineLengths[lineno];
 
479
    else
 
480
        return 0;
 
481
}
 
482
 
 
483
bool HistoryScrollBlockArray::isWrappedLine(int /*lineno*/)
 
484
{
 
485
  return false;
 
486
}
 
487
 
 
488
void HistoryScrollBlockArray::getCells(int lineno, int colno,
 
489
                                       int count, Character res[])
 
490
{
 
491
  if (!count) return;
 
492
 
 
493
  const Block *b = m_blockArray.at(lineno);
 
494
 
 
495
  if (!b) {
 
496
    memset(res, 0, count * sizeof(Character)); // still better than random data
 
497
    return;
 
498
  }
 
499
 
 
500
  assert(((colno + count) * sizeof(Character)) < ENTRIES);
 
501
  memcpy(res, b->data + (colno * sizeof(Character)), count * sizeof(Character));
 
502
}
 
503
 
 
504
void HistoryScrollBlockArray::addCells(const Character a[], int count)
 
505
{
 
506
  Block *b = m_blockArray.lastBlock();
 
507
  
 
508
  if (!b) return;
 
509
 
 
510
  // put cells in block's data
 
511
  assert((count * sizeof(Character)) < ENTRIES);
 
512
 
 
513
  memset(b->data, 0, ENTRIES);
 
514
 
 
515
  memcpy(b->data, a, count * sizeof(Character));
 
516
  b->size = count * sizeof(Character);
 
517
 
 
518
  size_t res = m_blockArray.newBlock();
 
519
  assert (res > 0);
 
520
  Q_UNUSED( res );
 
521
 
 
522
  m_lineLengths.insert(m_blockArray.getCurrent(), count);
 
523
}
 
524
 
 
525
void HistoryScrollBlockArray::addLine(bool)
 
526
{
 
527
}
 
528
 
 
529
//////////////////////////////////////////////////////////////////////
 
530
// History Types
 
531
//////////////////////////////////////////////////////////////////////
 
532
 
 
533
HistoryType::HistoryType()
 
534
{
 
535
}
 
536
 
 
537
HistoryType::~HistoryType()
 
538
{
 
539
}
 
540
 
 
541
//////////////////////////////
 
542
 
 
543
HistoryTypeNone::HistoryTypeNone()
 
544
{
 
545
}
 
546
 
 
547
bool HistoryTypeNone::isEnabled() const
 
548
{
 
549
  return false;
 
550
}
 
551
 
 
552
HistoryScroll* HistoryTypeNone::scroll(HistoryScroll *old) const
 
553
{
 
554
  delete old;
 
555
  return new HistoryScrollNone();
 
556
}
 
557
 
 
558
int HistoryTypeNone::maximumLineCount() const
 
559
{
 
560
  return 0;
 
561
}
 
562
 
 
563
//////////////////////////////
 
564
 
 
565
HistoryTypeBlockArray::HistoryTypeBlockArray(size_t size)
 
566
  : m_size(size)
 
567
{
 
568
}
 
569
 
 
570
bool HistoryTypeBlockArray::isEnabled() const
 
571
{
 
572
  return true;
 
573
}
 
574
 
 
575
int HistoryTypeBlockArray::maximumLineCount() const
 
576
{
 
577
  return m_size;
 
578
}
 
579
 
 
580
HistoryScroll* HistoryTypeBlockArray::scroll(HistoryScroll *old) const
 
581
{
 
582
  delete old;
 
583
  return new HistoryScrollBlockArray(m_size);
 
584
}
 
585
 
 
586
 
 
587
//////////////////////////////
 
588
 
 
589
HistoryTypeBuffer::HistoryTypeBuffer(unsigned int nbLines)
 
590
  : m_nbLines(nbLines)
 
591
{
 
592
}
 
593
 
 
594
bool HistoryTypeBuffer::isEnabled() const
 
595
{
 
596
  return true;
 
597
}
 
598
 
 
599
int HistoryTypeBuffer::maximumLineCount() const
 
600
{
 
601
  return m_nbLines;
 
602
}
 
603
 
 
604
HistoryScroll* HistoryTypeBuffer::scroll(HistoryScroll *old) const
 
605
{
 
606
  if (old)
 
607
  {
 
608
    HistoryScrollBuffer *oldBuffer = dynamic_cast<HistoryScrollBuffer*>(old);
 
609
    if (oldBuffer)
 
610
    {
 
611
       oldBuffer->setMaxNbLines(m_nbLines);
 
612
       return oldBuffer;
 
613
    }
 
614
 
 
615
    HistoryScroll *newScroll = new HistoryScrollBuffer(m_nbLines);
 
616
    int lines = old->getLines();
 
617
    int startLine = 0;
 
618
    if (lines > (int) m_nbLines)
 
619
       startLine = lines - m_nbLines;
 
620
 
 
621
    Character line[LINE_SIZE];
 
622
    for(int i = startLine; i < lines; i++)
 
623
    {
 
624
       int size = old->getLineLen(i);
 
625
       if (size > LINE_SIZE)
 
626
       {
 
627
          Character *tmp_line = new Character[size];
 
628
          old->getCells(i, 0, size, tmp_line);
 
629
          newScroll->addCells(tmp_line, size);
 
630
          newScroll->addLine(old->isWrappedLine(i));
 
631
          delete [] tmp_line;
 
632
       }
 
633
       else
 
634
       {
 
635
          old->getCells(i, 0, size, line);
 
636
          newScroll->addCells(line, size);
 
637
          newScroll->addLine(old->isWrappedLine(i));
 
638
       }
 
639
    }
 
640
    delete old;
 
641
    return newScroll;
 
642
  }
 
643
  return new HistoryScrollBuffer(m_nbLines);
 
644
}
 
645
 
 
646
//////////////////////////////
 
647
 
 
648
HistoryTypeFile::HistoryTypeFile(const QString& fileName)
 
649
  : m_fileName(fileName)
 
650
{
 
651
}
 
652
 
 
653
bool HistoryTypeFile::isEnabled() const
 
654
{
 
655
  return true;
 
656
}
 
657
 
 
658
const QString& HistoryTypeFile::getFileName() const
 
659
{
 
660
  return m_fileName;
 
661
}
 
662
 
 
663
HistoryScroll* HistoryTypeFile::scroll(HistoryScroll *old) const
 
664
{
 
665
  if (dynamic_cast<HistoryFile *>(old)) 
 
666
     return old; // Unchanged.
 
667
 
 
668
  HistoryScroll *newScroll = new HistoryScrollFile(m_fileName);
 
669
 
 
670
  Character line[LINE_SIZE];
 
671
  int lines = (old != 0) ? old->getLines() : 0;
 
672
  for(int i = 0; i < lines; i++)
 
673
  {
 
674
     int size = old->getLineLen(i);
 
675
     if (size > LINE_SIZE)
 
676
     {
 
677
        Character *tmp_line = new Character[size];
 
678
        old->getCells(i, 0, size, tmp_line);
 
679
        newScroll->addCells(tmp_line, size);
 
680
        newScroll->addLine(old->isWrappedLine(i));
 
681
        delete [] tmp_line;
 
682
     }
 
683
     else
 
684
     {
 
685
        old->getCells(i, 0, size, line);
 
686
        newScroll->addCells(line, size);
 
687
        newScroll->addLine(old->isWrappedLine(i));
 
688
     }
 
689
  }
 
690
 
 
691
  delete old;
 
692
  return newScroll; 
 
693
}
 
694
 
 
695
int HistoryTypeFile::maximumLineCount() const
 
696
{
 
697
  return 0;
 
698
}