summaryrefslogtreecommitdiff
authorerik <erik>2007-01-26 21:43:58 (UTC)
committer erik <erik>2007-01-26 21:43:58 (UTC)
commit3cd37427b5c5f26f62cff583fbde914467ddafe3 (patch) (unidiff)
tree664a2c1cf2198b69f94e9aa683133a3d92c98511
parentf77da1ae08512b02a3c50a124f823ed77e53dd64 (diff)
downloadopie-3cd37427b5c5f26f62cff583fbde914467ddafe3.zip
opie-3cd37427b5c5f26f62cff583fbde914467ddafe3.tar.gz
opie-3cd37427b5c5f26f62cff583fbde914467ddafe3.tar.bz2
Both files in this commit exhibit the wrong way to use temporary files.
For TEHistory.cpp, it uses tmpfile() which produces a file which has a name that can be guessed. For vmemo.cpp, it uses tmpname() which only creates a predictable string. Both uses have been switched to using mkstemp() wrapped around umask(). This produces a much less predictable file that also has guaranteed restrictive permissions. I went a little farther in vmemo because it calls out to the shell using system to 'mv' the new file. That is kinda wasteful so I switched it to use rename instead.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/applets/vmemo/vmemo.cpp73
-rw-r--r--noncore/apps/opie-console/TEHistory.cpp27
2 files changed, 72 insertions, 28 deletions
diff --git a/core/applets/vmemo/vmemo.cpp b/core/applets/vmemo/vmemo.cpp
index 8ba1eb7..1a8f154 100644
--- a/core/applets/vmemo/vmemo.cpp
+++ b/core/applets/vmemo/vmemo.cpp
@@ -236,228 +236,251 @@ VMemo::VMemo( QWidget *parent, const char *_name )
236 else 236 else
237 usingIcon = false; 237 usingIcon = false;
238 if (!usingIcon) 238 if (!usingIcon)
239 hide(); 239 hide();
240 recording = false; 240 recording = false;
241} 241}
242 242
243VMemo::~VMemo() { 243VMemo::~VMemo() {
244} 244}
245 245
246int VMemo::position() 246int VMemo::position()
247{ 247{
248 return 1; 248 return 1;
249} 249}
250 250
251void VMemo::receive( const QCString &msg, const QByteArray &data ) { 251void VMemo::receive( const QCString &msg, const QByteArray &data ) {
252 QDataStream stream( data, IO_ReadOnly ); 252 QDataStream stream( data, IO_ReadOnly );
253 253
254 if (msg == "toggleRecord()") { 254 if (msg == "toggleRecord()") {
255 if (recording) { 255 if (recording) {
256 fromToggle = true; 256 fromToggle = true;
257 stopRecording(); 257 stopRecording();
258 } else { 258 } else {
259 fromToggle = true; 259 fromToggle = true;
260 startRecording(); 260 startRecording();
261 } 261 }
262 } 262 }
263} 263}
264 264
265void VMemo::paintEvent( QPaintEvent* ) { 265void VMemo::paintEvent( QPaintEvent* ) {
266 QPainter p(this); 266 QPainter p(this);
267 p.drawPixmap( 0, 1,( const char** ) vmemo_xpm ); 267 p.drawPixmap( 0, 1,( const char** ) vmemo_xpm );
268} 268}
269 269
270void VMemo::mousePressEvent( QMouseEvent * /*me*/) { 270void VMemo::mousePressEvent( QMouseEvent * /*me*/) {
271 271
272 if(!recording) { 272 if(!recording) {
273 if(!startRecording() ){ 273 if(!startRecording() ){
274 QMessageBox::critical(0, "vmemo", "Abort Recording", "Abort Recording"); 274 QMessageBox::critical(0, "vmemo", "Abort Recording", "Abort Recording");
275 } 275 }
276 } else { 276 } else {
277 stopRecording(); 277 stopRecording();
278 } 278 }
279} 279}
280 280
281void VMemo::mouseReleaseEvent( QMouseEvent * ) { 281void VMemo::mouseReleaseEvent( QMouseEvent * ) {
282} 282}
283 283
284bool VMemo::startRecording() { 284bool VMemo::startRecording() {
285 Config config( "Vmemo" ); 285 Config config( "Vmemo" );
286 config.setGroup( "System" ); 286 config.setGroup( "System" );
287 287
288 288
289 odebug << "Start recording engines" << oendl; 289 odebug << "Start recording engines" << oendl;
290 recording = true; 290 recording = true;
291 291
292 if (openDSP() == -1) { 292 if (openDSP() == -1) {
293 recording = false; 293 recording = false;
294 return false; 294 return false;
295 } 295 }
296 296
297 config.setGroup("Defaults"); 297 config.setGroup("Defaults");
298 298
299 date = TimeString::dateString( QDateTime::currentDateTime(),false,true); 299 date = TimeString::dateString( QDateTime::currentDateTime(),false,true);
300 date.replace(QRegExp("'"),""); 300 date.replace(QRegExp("'"),"");
301 date.replace(QRegExp(" "),"_"); 301 date.replace(QRegExp(" "),"_");
302 date.replace(QRegExp(":"),"-"); 302 date.replace(QRegExp(":"),"-");
303 date.replace(QRegExp(","),""); 303 date.replace(QRegExp(","),"");
304 304
305 QString fName; 305 QString fName;
306 config.setGroup( "System" ); 306 config.setGroup( "System" );
307 fName = QPEApplication::documentDir() ; 307 fName = QPEApplication::documentDir() ;
308 fileName = config.readEntry("RecLocation", fName); 308 fileName = config.readEntry("RecLocation", fName);
309 309
310 int s; 310 int s;
311 s=fileName.find(':'); 311 s=fileName.find(':');
312 if(s) 312 if(s)
313 fileName=fileName.right(fileName.length()-s-2); 313 fileName=fileName.right(fileName.length()-s-2);
314 odebug << "pathname will be "+fileName << oendl; 314 odebug << "pathname will be "+fileName << oendl;
315 315
316 if( fileName.left(1).find('/') == -1) 316 if( fileName.left(1).find('/') == -1)
317 fileName="/"+fileName; 317 fileName="/"+fileName;
318 if( fileName.right(1).find('/') == -1) 318 if( fileName.right(1).find('/') == -1)
319 fileName+="/"; 319 fileName+="/";
320 fName = "vm_"+ date + ".wav"; 320 fName = "vm_"+ date + ".wav";
321 321
322 fileName += fName; 322 fileName += fName;
323 odebug << "filename is " + fileName << oendl; 323 odebug << "filename is " + fileName << oendl;
324 324
325 useAlerts = config.readBoolEntry("Alert",1); 325 useAlerts = config.readBoolEntry("Alert",1);
326 if(useAlerts) { 326 if(useAlerts) {
327 msgLabel = new QLabel( 0, "alertLabel" ); 327 msgLabel = new QLabel( 0, "alertLabel" );
328 msgLabel->setText( tr("<B><P><font size=+2>VMemo-Recording</font></B><p>%1</p>").arg("vm_"+ date)); 328 msgLabel->setText( tr("<B><P><font size=+2>VMemo-Recording</font></B><p>%1</p>").arg("vm_"+ date));
329 msgLabel->show(); 329 msgLabel->show();
330 } 330 }
331 331
332// open tmp file here 332 // open tmp file here
333 char *pointer; 333 char *tmpFilePath = 0;
334 pointer=tmpnam(NULL); 334 char *tmpDir = getenv("TMPDIR");
335 odebug << "Opening tmp file " << pointer << "" << oendl; 335 if (tmpDir && *tmpDir != '\0') {
336 tmpFilePath = new char[strlen(tmpDir) + strlen("/vmemo-wav-XXXXXX") + 1];
337 strcpy(tmpFilePath, tmpDir);
338 free(tmpDir);
339 } else {
340 tmpFilePath = new char[strlen("/tmp/vmemo-wav-XXXXXX") + 1];
341 strcpy(tmpFilePath, "/tmp");
342 }
343 strcat(tmpFilePath, "/vmemo-wav-XXXXXX");
344 mode_t currUmask = umask(S_IRWXO | S_IRWXG);
345 int tmpFd = mkstemp(tmpFilePath);
346 umask(currUmask);
347 if (tmpFd == -1) {
348 owarn << "Could not open temp file with template " << tmpFilePath
349 << oendl;
350 delete [] tmpFilePath;
351 return false;
352 } else
353 odebug << "Opened temp file " << tmpFilePath << "" << oendl;
354
355 close(tmpFd);
336 356
337 if(openWAV(pointer ) == -1) { 357 if(openWAV(tmpFilePath ) == -1) {
338 358
339 QString err("Could not open the temp file\n"); 359 QString err("Could not open the temp file\n");
340 err += fileName; 360 err += fileName;
341 QMessageBox::critical(0, "vmemo", err, "Abort"); 361 QMessageBox::critical(0, "vmemo", err, "Abort");
342 ::close(dsp); 362 ::close(dsp);
343 return false; 363 return false;
344 } 364 }
345 if( record() ) { 365 if( record() ) {
346 366
347 QString cmd; 367 if( fileName.find(".wav",0,true) == -1)
348 if( fileName.find(".wav",0,true) == -1) 368 fileName += ".wav";
349 fileName += ".wav";
350 369
351 cmd.sprintf("mv %s "+fileName, pointer); 370 int retVal = rename(tmpFilePath, fileName.local8Bit());
352// move tmp file to regular file here 371 if (retVal == -1) {
353 372 owarn << "Could not move " << tmpFilePath << " to " << fileName
354 system(cmd.latin1()); 373 << oendl;
355 374 delete [] tmpFilePath;
356 QArray<int> cats(1); 375 return false;
357 cats[0] = config.readNumEntry("Category", 0); 376 }
358 377 delete [] tmpFilePath;
359 QString dlName("vm_"); 378
360 dlName += date; 379 QArray<int> cats(1);
361 DocLnk l; 380 cats[0] = config.readNumEntry("Category", 0);
362 l.setFile(fileName); 381
363 l.setName(dlName); 382 QString dlName("vm_");
364 l.setType("audio/x-wav"); 383 dlName += date;
365 l.setCategories(cats); 384 DocLnk l;
366 l.writeLink(); 385 l.setFile(fileName);
367 return true; 386 l.setName(dlName);
387 l.setType("audio/x-wav");
388 l.setCategories(cats);
389 l.writeLink();
390 return true;
368 } else 391 } else
369 return false; 392 return false;
370 393
371} 394}
372 395
373void VMemo::stopRecording() { 396void VMemo::stopRecording() {
374// show(); 397// show();
375 odebug << "Stopped recording" << oendl; 398 odebug << "Stopped recording" << oendl;
376 recording = false; 399 recording = false;
377 if(useAlerts) { 400 if(useAlerts) {
378 msgLabel->close(); 401 msgLabel->close();
379 msgLabel=0; 402 msgLabel=0;
380 delete msgLabel; 403 delete msgLabel;
381 } 404 }
382 t_timer->stop(); 405 t_timer->stop();
383 Config cfg("Vmemo"); 406 Config cfg("Vmemo");
384 cfg.setGroup("Defaults"); 407 cfg.setGroup("Defaults");
385// if( cfg.readNumEntry("hideIcon",0) == 1 ) 408// if( cfg.readNumEntry("hideIcon",0) == 1 )
386// hide(); 409// hide();
387} 410}
388 411
389int VMemo::openDSP() { 412int VMemo::openDSP() {
390 Config cfg("Vmemo"); 413 Config cfg("Vmemo");
391 cfg.setGroup("Record"); 414 cfg.setGroup("Record");
392 415
393 speed = cfg.readNumEntry("SampleRate", 22050); 416 speed = cfg.readNumEntry("SampleRate", 22050);
394 channels = cfg.readNumEntry("Stereo", 1) ? 2 : 1; // 1 = stereo(2), 0 = mono(1) 417 channels = cfg.readNumEntry("Stereo", 1) ? 2 : 1; // 1 = stereo(2), 0 = mono(1)
395 if (cfg.readNumEntry("SixteenBit", 1)==1) { 418 if (cfg.readNumEntry("SixteenBit", 1)==1) {
396 format = AFMT_S16_LE; 419 format = AFMT_S16_LE;
397 resolution = 16; 420 resolution = 16;
398 } else { 421 } else {
399 format = AFMT_U8; 422 format = AFMT_U8;
400 resolution = 8; 423 resolution = 8;
401 } 424 }
402 425
403 odebug << "samplerate: " << speed << ", channels " << channels << ", resolution " << resolution << "" << oendl; 426 odebug << "samplerate: " << speed << ", channels " << channels << ", resolution " << resolution << "" << oendl;
404 427
405 if(systemZaurus) { 428 if(systemZaurus) {
406 dsp = open("/dev/dsp1", O_RDONLY); //Zaurus needs /dev/dsp1 429 dsp = open("/dev/dsp1", O_RDONLY); //Zaurus needs /dev/dsp1
407 channels=1; //zaurus has one input channel 430 channels=1; //zaurus has one input channel
408 } else { 431 } else {
409#ifdef QT_QWS_DEVFS 432#ifdef QT_QWS_DEVFS
410 dsp = open("/dev/sound/dsp", O_RDONLY); 433 dsp = open("/dev/sound/dsp", O_RDONLY);
411#else 434#else
412 dsp = open("/dev/dsp", O_RDONLY); 435 dsp = open("/dev/dsp", O_RDONLY);
413#endif 436#endif
414 } 437 }
415 438
416 if (dsp == -1) { 439 if (dsp == -1) {
417 msgLabel->close(); 440 msgLabel->close();
418 msgLabel=0; 441 msgLabel=0;
419 delete msgLabel; 442 delete msgLabel;
420 443
421 perror("open(\"/dev/dsp\")"); 444 perror("open(\"/dev/dsp\")");
422 errorMsg="open(\"/dev/dsp\")\n "+(QString)strerror(errno); 445 errorMsg="open(\"/dev/dsp\")\n "+(QString)strerror(errno);
423 QMessageBox::critical(0, "vmemo", errorMsg, "Abort"); 446 QMessageBox::critical(0, "vmemo", errorMsg, "Abort");
424 return -1; 447 return -1;
425 } 448 }
426 449
427 if(ioctl(dsp, SNDCTL_DSP_SETFMT , &format)==-1) { 450 if(ioctl(dsp, SNDCTL_DSP_SETFMT , &format)==-1) {
428 perror("ioctl(\"SNDCTL_DSP_SETFMT\")"); 451 perror("ioctl(\"SNDCTL_DSP_SETFMT\")");
429// return -1; 452// return -1;
430 } 453 }
431 if(ioctl(dsp, SNDCTL_DSP_CHANNELS , &channels)==-1) { 454 if(ioctl(dsp, SNDCTL_DSP_CHANNELS , &channels)==-1) {
432 perror("ioctl(\"SNDCTL_DSP_CHANNELS\")"); 455 perror("ioctl(\"SNDCTL_DSP_CHANNELS\")");
433// return -1; 456// return -1;
434 } 457 }
435 if(ioctl(dsp, SNDCTL_DSP_SPEED , &speed)==-1) { 458 if(ioctl(dsp, SNDCTL_DSP_SPEED , &speed)==-1) {
436 perror("ioctl(\"SNDCTL_DSP_SPEED\")"); 459 perror("ioctl(\"SNDCTL_DSP_SPEED\")");
437// return -1; 460// return -1;
438 } 461 }
439 if(ioctl(dsp, SOUND_PCM_READ_RATE , &rate)==-1) { 462 if(ioctl(dsp, SOUND_PCM_READ_RATE , &rate)==-1) {
440 perror("ioctl(\"SOUND_PCM_READ_RATE\")"); 463 perror("ioctl(\"SOUND_PCM_READ_RATE\")");
441// return -1; 464// return -1;
442 } 465 }
443 466
444 QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << false; //mute 467 QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << false; //mute
445 468
446 return 1; 469 return 1;
447} 470}
448 471
449int VMemo::openWAV(const char *filename) { 472int VMemo::openWAV(const char *filename) {
450 track.setName(filename); 473 track.setName(filename);
451 if(!track.open(IO_WriteOnly|IO_Truncate|IO_Raw)) { 474 if(!track.open(IO_WriteOnly|IO_Truncate|IO_Raw)) {
452 errorMsg=filename; 475 errorMsg=filename;
453 return -1; 476 return -1;
454 } 477 }
455 478
456 wav=track.handle(); 479 wav=track.handle();
457 Config vmCfg("Vmemo"); 480 Config vmCfg("Vmemo");
458 vmCfg.setGroup("Defaults"); 481 vmCfg.setGroup("Defaults");
459 useADPCM = vmCfg.readBoolEntry("use_ADPCM", 0); 482 useADPCM = vmCfg.readBoolEntry("use_ADPCM", 0);
460 483
461 WaveHeader wh; 484 WaveHeader wh;
462 485
463 wh.main_chunk = RIFF; 486 wh.main_chunk = RIFF;
diff --git a/noncore/apps/opie-console/TEHistory.cpp b/noncore/apps/opie-console/TEHistory.cpp
index 317ce57..e2be42a 100644
--- a/noncore/apps/opie-console/TEHistory.cpp
+++ b/noncore/apps/opie-console/TEHistory.cpp
@@ -1,197 +1,218 @@
1/* -------------------------------------------------------------------------- */ 1/* -------------------------------------------------------------------------- */
2/* */ 2/* */
3/* [TEHistory.C] History Buffer */ 3/* [TEHistory.C] History Buffer */
4/* */ 4/* */
5/* -------------------------------------------------------------------------- */ 5/* -------------------------------------------------------------------------- */
6/* */ 6/* */
7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ 7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
8/* */ 8/* */
9/* This file is part of Konsole - an X terminal for KDE */ 9/* This file is part of Konsole - an X terminal for KDE */
10/* */ 10/* */
11/* -------------------------------------------------------------------------- */ 11/* -------------------------------------------------------------------------- */
12 /* */ 12 /* */
13/* Ported Konsole to Qt/Embedded */ 13/* Ported Konsole to Qt/Embedded */
14 /* */ 14 /* */
15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ 15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
16 /* */ 16 /* */
17/* -------------------------------------------------------------------------- */ 17/* -------------------------------------------------------------------------- */
18 18
19#include "TEHistory.h" 19#include "TEHistory.h"
20#include <stdlib.h> 20#include <stdlib.h>
21#include <assert.h> 21#include <assert.h>
22#include <stdio.h> 22#include <stdio.h>
23#include <sys/types.h> 23#include <sys/types.h>
24#include <sys/stat.h>
24#include <unistd.h> 25#include <unistd.h>
25#include <errno.h> 26#include <errno.h>
26 27
27#define HERE printf("%s(%d): here\n",__FILE__,__LINE__) 28#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
28 29
29/* 30/*
30 An arbitrary long scroll. 31 An arbitrary long scroll.
31 32
32 One can modify the scroll only by adding either cells 33 One can modify the scroll only by adding either cells
33 or newlines, but access it randomly. 34 or newlines, but access it randomly.
34 35
35 The model is that of an arbitrary wide typewriter scroll 36 The model is that of an arbitrary wide typewriter scroll
36 in that the scroll is a serie of lines and each line is 37 in that the scroll is a serie of lines and each line is
37 a serie of cells with no overwriting permitted. 38 a serie of cells with no overwriting permitted.
38 39
39 The implementation provides arbitrary length and numbers 40 The implementation provides arbitrary length and numbers
40 of cells and line/column indexed read access to the scroll 41 of cells and line/column indexed read access to the scroll
41 at constant costs. 42 at constant costs.
42 43
43FIXME: some complain about the history buffer comsuming the 44FIXME: some complain about the history buffer comsuming the
44 memory of their machines. This problem is critical 45 memory of their machines. This problem is critical
45 since the history does not behave gracefully in cases 46 since the history does not behave gracefully in cases
46 where the memory is used up completely. 47 where the memory is used up completely.
47 48
48 I put in a workaround that should handle it problem 49 I put in a workaround that should handle it problem
49 now gracefully. I'm not satisfied with the solution. 50 now gracefully. I'm not satisfied with the solution.
50 51
51FIXME: Terminating the history is not properly indicated 52FIXME: Terminating the history is not properly indicated
52 in the menu. We should throw a signal. 53 in the menu. We should throw a signal.
53 54
54FIXME: There is noticable decrease in speed, also. Perhaps, 55FIXME: There is noticable decrease in speed, also. Perhaps,
55 there whole feature needs to be revisited therefore. 56 there whole feature needs to be revisited therefore.
56 Disadvantage of a more elaborated, say block-oriented 57 Disadvantage of a more elaborated, say block-oriented
57 scheme with wrap around would be it's complexity. 58 scheme with wrap around would be it's complexity.
58*/ 59*/
59 60
60//FIXME: tempory replacement for tmpfile 61//FIXME: tempory replacement for tmpfile
61// this is here one for debugging purpose. 62// this is here one for debugging purpose.
62 63
63//#define tmpfile xTmpFile 64//#define tmpfile xTmpFile
64 65
65FILE* xTmpFile() 66FILE* xTmpFile()
66{ 67{
67 static int fid = 0; 68 static int fid = 0;
68 char fname[80]; 69 char fname[80];
69 sprintf(fname,"TmpFile.%d",fid++); 70 sprintf(fname,"TmpFile.%d",fid++);
70 return fopen(fname,"w"); 71 return fopen(fname,"w");
71} 72}
72 73
73 74
74// History Buffer /////////////////////////////////////////// 75// History Buffer ///////////////////////////////////////////
75 76
76/* 77/*
77 A Row(X) data type which allows adding elements to the end. 78 A Row(X) data type which allows adding elements to the end.
78*/ 79*/
79 80
80HistoryBuffer::HistoryBuffer() 81HistoryBuffer::HistoryBuffer()
81{ 82{
82 ion = -1; 83 ion = -1;
83 length = 0; 84 length = 0;
84} 85}
85 86
86HistoryBuffer::~HistoryBuffer() 87HistoryBuffer::~HistoryBuffer()
87{ 88{
88 setScroll(FALSE); 89 setScroll(FALSE);
89} 90}
90 91
91void HistoryBuffer::setScroll(bool on) 92void HistoryBuffer::setScroll(bool on)
92{ 93{
93 if (on == hasScroll()) return; 94 if (on == hasScroll()) return;
94 95
95 if (on) 96 if (on)
96 { 97 {
97 assert( ion < 0 ); 98 assert( ion < 0 );
98 assert( length == 0); 99 assert( length == 0);
99 FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; } 100 char* tmpDir = getenv("TMPDIR");
100 ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n"); 101 char* tmpFilePath = 0;
101 fclose(tmp); 102 if (tmpDir && *tmpDir != '\0') {
103 tmpFilePath = new char[strlen(tmpDir) + strlen("/opie-console-HistoryBuffer-XXXXXX") + 1];
104 strcpy(tmpFilePath, tmpDir);
105 free(tmpDir);
106 } else {
107 tmpFilePath = new char[strlen("/tmp/opie-console-HistoryBuffer-XXXXXX") + 1];
108 strcpy(tmpFilePath, "/tmp");
109 }
110 strcat(tmpFilePath, "/opie-console-HistoryBuffer-XXXXXX");
111 mode_t currUmask = umask(S_IRWXO | S_IRWXG);
112 int tmpfd = mkstemp(tmpFilePath);
113 delete [] tmpFilePath;
114 umask(currUmask);
115 if (tmpfd == -1) {
116 perror("konsole: cannot open temp file.\n");
117 return;
118 }
119 ion = dup(tmpfd);
120 if (ion<0)
121 perror("konsole: cannot dup temp file.\n");
122 close(tmpfd);
102 } 123 }
103 else 124 else
104 { 125 {
105 assert( ion >= 0 ); 126 assert( ion >= 0 );
106 close(ion); 127 close(ion);
107 ion = -1; 128 ion = -1;
108 length = 0; 129 length = 0;
109 } 130 }
110} 131}
111 132
112bool HistoryBuffer::hasScroll() 133bool HistoryBuffer::hasScroll()
113{ 134{
114 return ion >= 0; 135 return ion >= 0;
115} 136}
116 137
117void HistoryBuffer::add(const unsigned char* bytes, int len) 138void HistoryBuffer::add(const unsigned char* bytes, int len)
118{ int rc; 139{ int rc;
119 assert(hasScroll()); 140 assert(hasScroll());
120 rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; } 141 rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; }
121 rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; } 142 rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; }
122 length += rc; 143 length += rc;
123} 144}
124 145
125void HistoryBuffer::get(unsigned char* bytes, int len, int loc) 146void HistoryBuffer::get(unsigned char* bytes, int len, int loc)
126{ int rc; 147{ int rc;
127 assert(hasScroll()); 148 assert(hasScroll());
128 if (loc < 0 || len < 0 || loc + len > length) 149 if (loc < 0 || len < 0 || loc + len > length)
129 fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc); 150 fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
130 rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; } 151 rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; }
131 rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; } 152 rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; }
132} 153}
133 154
134int HistoryBuffer::len() 155int HistoryBuffer::len()
135{ 156{
136 return length; 157 return length;
137} 158}
138 159
139// History Scroll ////////////////////////////////////// 160// History Scroll //////////////////////////////////////
140 161
141/* 162/*
142 The history scroll makes a Row(Row(Cell)) from 163 The history scroll makes a Row(Row(Cell)) from
143 two history buffers. The index buffer contains 164 two history buffers. The index buffer contains
144 start of line positions which refere to the cells 165 start of line positions which refere to the cells
145 buffer. 166 buffer.
146 167
147 Note that index[0] addresses the second line 168 Note that index[0] addresses the second line
148 (line #1), while the first line (line #0) starts 169 (line #1), while the first line (line #0) starts
149 at 0 in cells. 170 at 0 in cells.
150*/ 171*/
151 172
152HistoryScroll::HistoryScroll() 173HistoryScroll::HistoryScroll()
153{ 174{
154} 175}
155 176
156HistoryScroll::~HistoryScroll() 177HistoryScroll::~HistoryScroll()
157{ 178{
158} 179}
159 180
160void HistoryScroll::setScroll(bool on) 181void HistoryScroll::setScroll(bool on)
161{ 182{
162 index.setScroll(on); 183 index.setScroll(on);
163 cells.setScroll(on); 184 cells.setScroll(on);
164} 185}
165 186
166bool HistoryScroll::hasScroll() 187bool HistoryScroll::hasScroll()
167{ 188{
168 return index.hasScroll() && cells.hasScroll(); 189 return index.hasScroll() && cells.hasScroll();
169} 190}
170 191
171int HistoryScroll::getLines() 192int HistoryScroll::getLines()
172{ 193{
173 if (!hasScroll()) return 0; 194 if (!hasScroll()) return 0;
174 return index.len() / sizeof(int); 195 return index.len() / sizeof(int);
175} 196}
176 197
177int HistoryScroll::getLineLen(int lineno) 198int HistoryScroll::getLineLen(int lineno)
178{ 199{
179 if (!hasScroll()) return 0; 200 if (!hasScroll()) return 0;
180 return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca); 201 return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca);
181} 202}
182 203
183int HistoryScroll::startOfLine(int lineno) 204int HistoryScroll::startOfLine(int lineno)
184{ 205{
185 if (lineno <= 0) return 0; 206 if (lineno <= 0) return 0;
186 if (!hasScroll()) return 0; 207 if (!hasScroll()) return 0;
187 if (lineno <= getLines()) 208 if (lineno <= getLines())
188 { int res; 209 { int res;
189 index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int)); 210 index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
190 return res; 211 return res;
191 } 212 }
192 return cells.len(); 213 return cells.len();
193} 214}
194 215
195void HistoryScroll::getCells(int lineno, int colno, int count, ca res[]) 216void HistoryScroll::getCells(int lineno, int colno, int count, ca res[])
196{ 217{
197 assert(hasScroll()); 218 assert(hasScroll());