summaryrefslogtreecommitdiff
Side-by-side diff
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
@@ -1,662 +1,685 @@
/************************************************************************************
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
************************************************************************************/
// copyright 2002 Jeremy Cowgar <jc@cowgar.com>
// copyright 2002 and 2003 L.J.Potter <ljp@llornkcor.com>
/* OPIE */
#include <opie2/odebug.h>
using namespace Opie::Core;
extern "C" {
#include "adpcm.h"
}
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
#include <errno.h>
typedef struct _waveheader {
u_long main_chunk; /* 'RIFF' */
u_long length; /* filelen */
u_long chunk_type; /* 'WAVE' */
u_long sub_chunk; /* 'fmt ' */
u_long sc_len; /* length of sub_chunk, =16
(chunckSize) format len */
u_short format; /* should be 1 for PCM-code (formatTag) */
u_short modus; /* 1 Mono, 2 Stereo (channels) */
u_long sample_fq; /* samples per second (samplesPerSecond) */
u_long byte_p_sec; /* avg bytes per second (avgBytePerSecond) */
u_short byte_p_spl; /* samplesize; 1 or 2 bytes (blockAlign) */
u_short bit_p_spl; /* 8, 12 or 16 bit (bitsPerSample) */
u_long data_chunk; /* 'data' */
u_long data_length;/* samplecount */
} WaveHeader;
#define RIFF 0x46464952
#define WAVE 0x45564157
#define FMT 0x20746D66
#define DATA 0x61746164
#define PCM_CODE 1
#define WAVE_MONO 1
#define WAVE_STEREO 2
struct adpcm_state encoder_state;
//struct adpcm_state decoder_state;
#define WAVE_FORMAT_DVI_ADPCM (0x0011)
#define WAVE_FORMAT_PCM (0x0001)
#include "vmemo.h"
#include <opie2/otaskbarapplet.h>
#include <qpe/qpeapplication.h>
#include <qpe/config.h>
#include <qpainter.h>
#include <qmessagebox.h>
int seq = 0;
/* XPM */
static char * vmemo_xpm[] = {
"16 16 102 2",
" c None",
". c #60636A",
"+ c #6E6E72",
"@ c #68696E",
"# c #4D525C",
"$ c #6B6C70",
"% c #E3E3E8",
"& c #EEEEF2",
"* c #EAEAEF",
"= c #CACAD0",
"- c #474A51",
"; c #171819",
"> c #9B9B9F",
", c #EBEBF0",
"' c #F4F4F7",
") c #F1F1F5",
"! c #DEDEE4",
"~ c #57575C",
"{ c #010101",
"] c #A2A2A6",
"^ c #747477",
"/ c #B5B5B8",
"( c #AEAEB2",
"_ c #69696D",
": c #525256",
"< c #181C24",
"[ c #97979B",
"} c #A7A7AC",
"| c #B0B0B4",
"1 c #C8C8D1",
"2 c #75757B",
"3 c #46464A",
"4 c #494A4F",
"5 c #323234",
"6 c #909095",
"7 c #39393B",
"8 c #757578",
"9 c #87878E",
"0 c #222224",
"a c #414144",
"b c #6A6A6E",
"c c #020C16",
"d c #6B6B6F",
"e c #68686D",
"f c #5B5B60",
"g c #8A8A8F",
"h c #6B6B6E",
"i c #ADADB2",
"j c #828289",
"k c #3E3E41",
"l c #CFCFD7",
"m c #4C4C50",
"n c #000000",
"o c #66666A",
"p c #505054",
"q c #838388",
"r c #A1A1A7",
"s c #A9A9AE",
"t c #A8A8B0",
"u c #5E5E63",
"v c #3A3A3E",
"w c #BDBDC6",
"x c #59595E",
"y c #76767C",
"z c #373738",
"A c #717174",
"B c #727278",
"C c #1C1C1E",
"D c #3C3C3F",
"E c #ADADB6",
"F c #54555A",
"G c #8B8C94",
"H c #5A5A5F",
"I c #BBBBC3",
"J c #C4C4CB",
"K c #909098",
"L c #737379",
"M c #343437",
"N c #8F8F98",
"O c #000407",
"P c #2D3137",
"Q c #B0B1BC",
"R c #3B3C40",
"S c #6E6E74",
"T c #95959C",
"U c #74747A",
"V c #1D1D1E",
"W c #91929A",
"X c #42444A",
"Y c #22282E",
"Z c #B0B2BC",
"` c #898A90",
" . c #65656A",
".. c #999AA2",
"+. c #52535A",
"@. c #151B21",
"#. c #515257",
"$. c #B5B5BE",
"%. c #616167",
"&. c #1A1D22",
"*. c #000713",
"=. c #1F1F21",
" ",
" . + @ # ",
" $ % & * = - ",
" ; > , ' ) ! ~ ",
" { ] ^ / ( _ : ",
" < [ } | 1 2 3 ",
" 4 5 6 7 8 9 0 a b c ",
" d e f g h i j 3 k l m n ",
" o p q r s t u v w n ",
" o x y z A B C D E n ",
" F G H I J K L M N O ",
" P Q R S T U V W X ",
" Y Z ` b ...+. ",
" @.#.$.%.&. ",
" *.B =. ",
" n n n n n n n n n "};
using namespace Opie::Ui;
VMemo::VMemo( QWidget *parent, const char *_name )
: QWidget( parent, _name ) {
setFixedHeight( 18 );
setFixedWidth( 14 );
t_timer = new QTimer( this );
connect( t_timer, SIGNAL( timeout() ), SLOT( timerBreak() ) );
Config vmCfg("Vmemo");
vmCfg.setGroup("Defaults");
int toggleKey = setToggleButton(vmCfg.readNumEntry("toggleKey", -1));
useADPCM = vmCfg.readBoolEntry("use_ADPCM", 0);
owarn <<"VMemo toggleKey" << toggleKey << oendl;
systemZaurus = false;
myChannel = new QCopChannel( "QPE/VMemo", this );
connect( myChannel, SIGNAL(received(const QCString&,const QByteArray&)),
this, SLOT(receive(const QCString&,const QByteArray&)) );
if( toggleKey != -1 ) {
owarn << "Register key " << toggleKey << "" << oendl;
QCopEnvelope e("QPE/Launcher", "keyRegister(int,QCString,QCString)");
// e << 4096; // Key_Escape
// e << Key_F5; //4148
e << toggleKey;
e << QCString("QPE/VMemo");
e << QCString("toggleRecord()");
}
if(toggleKey == 0)
usingIcon = true;
else
usingIcon = false;
if (!usingIcon)
hide();
recording = false;
}
VMemo::~VMemo() {
}
int VMemo::position()
{
return 1;
}
void VMemo::receive( const QCString &msg, const QByteArray &data ) {
QDataStream stream( data, IO_ReadOnly );
if (msg == "toggleRecord()") {
if (recording) {
fromToggle = true;
stopRecording();
} else {
fromToggle = true;
startRecording();
}
}
}
void VMemo::paintEvent( QPaintEvent* ) {
QPainter p(this);
p.drawPixmap( 0, 1,( const char** ) vmemo_xpm );
}
void VMemo::mousePressEvent( QMouseEvent * /*me*/) {
if(!recording) {
if(!startRecording() ){
QMessageBox::critical(0, "vmemo", "Abort Recording", "Abort Recording");
}
} else {
stopRecording();
}
}
void VMemo::mouseReleaseEvent( QMouseEvent * ) {
}
bool VMemo::startRecording() {
Config config( "Vmemo" );
config.setGroup( "System" );
odebug << "Start recording engines" << oendl;
recording = true;
if (openDSP() == -1) {
recording = false;
return false;
}
config.setGroup("Defaults");
date = TimeString::dateString( QDateTime::currentDateTime(),false,true);
date.replace(QRegExp("'"),"");
date.replace(QRegExp(" "),"_");
date.replace(QRegExp(":"),"-");
date.replace(QRegExp(","),"");
QString fName;
config.setGroup( "System" );
fName = QPEApplication::documentDir() ;
fileName = config.readEntry("RecLocation", fName);
int s;
s=fileName.find(':');
if(s)
fileName=fileName.right(fileName.length()-s-2);
odebug << "pathname will be "+fileName << oendl;
if( fileName.left(1).find('/') == -1)
fileName="/"+fileName;
if( fileName.right(1).find('/') == -1)
fileName+="/";
fName = "vm_"+ date + ".wav";
fileName += fName;
odebug << "filename is " + fileName << oendl;
useAlerts = config.readBoolEntry("Alert",1);
if(useAlerts) {
msgLabel = new QLabel( 0, "alertLabel" );
msgLabel->setText( tr("<B><P><font size=+2>VMemo-Recording</font></B><p>%1</p>").arg("vm_"+ date));
msgLabel->show();
}
-// open tmp file here
- char *pointer;
- pointer=tmpnam(NULL);
- odebug << "Opening tmp file " << pointer << "" << oendl;
+ // open tmp file here
+ char *tmpFilePath = 0;
+ char *tmpDir = getenv("TMPDIR");
+ if (tmpDir && *tmpDir != '\0') {
+ tmpFilePath = new char[strlen(tmpDir) + strlen("/vmemo-wav-XXXXXX") + 1];
+ strcpy(tmpFilePath, tmpDir);
+ free(tmpDir);
+ } else {
+ tmpFilePath = new char[strlen("/tmp/vmemo-wav-XXXXXX") + 1];
+ strcpy(tmpFilePath, "/tmp");
+ }
+ strcat(tmpFilePath, "/vmemo-wav-XXXXXX");
+ mode_t currUmask = umask(S_IRWXO | S_IRWXG);
+ int tmpFd = mkstemp(tmpFilePath);
+ umask(currUmask);
+ if (tmpFd == -1) {
+ owarn << "Could not open temp file with template " << tmpFilePath
+ << oendl;
+ delete [] tmpFilePath;
+ return false;
+ } else
+ odebug << "Opened temp file " << tmpFilePath << "" << oendl;
+
+ close(tmpFd);
- if(openWAV(pointer ) == -1) {
+ if(openWAV(tmpFilePath ) == -1) {
QString err("Could not open the temp file\n");
err += fileName;
QMessageBox::critical(0, "vmemo", err, "Abort");
::close(dsp);
return false;
}
if( record() ) {
- QString cmd;
- if( fileName.find(".wav",0,true) == -1)
- fileName += ".wav";
+ if( fileName.find(".wav",0,true) == -1)
+ fileName += ".wav";
- cmd.sprintf("mv %s "+fileName, pointer);
-// move tmp file to regular file here
-
- system(cmd.latin1());
-
- QArray<int> cats(1);
- cats[0] = config.readNumEntry("Category", 0);
-
- QString dlName("vm_");
- dlName += date;
- DocLnk l;
- l.setFile(fileName);
- l.setName(dlName);
- l.setType("audio/x-wav");
- l.setCategories(cats);
- l.writeLink();
- return true;
+ int retVal = rename(tmpFilePath, fileName.local8Bit());
+ if (retVal == -1) {
+ owarn << "Could not move " << tmpFilePath << " to " << fileName
+ << oendl;
+ delete [] tmpFilePath;
+ return false;
+ }
+ delete [] tmpFilePath;
+
+ QArray<int> cats(1);
+ cats[0] = config.readNumEntry("Category", 0);
+
+ QString dlName("vm_");
+ dlName += date;
+ DocLnk l;
+ l.setFile(fileName);
+ l.setName(dlName);
+ l.setType("audio/x-wav");
+ l.setCategories(cats);
+ l.writeLink();
+ return true;
} else
return false;
}
void VMemo::stopRecording() {
// show();
odebug << "Stopped recording" << oendl;
recording = false;
if(useAlerts) {
msgLabel->close();
msgLabel=0;
delete msgLabel;
}
t_timer->stop();
Config cfg("Vmemo");
cfg.setGroup("Defaults");
// if( cfg.readNumEntry("hideIcon",0) == 1 )
// hide();
}
int VMemo::openDSP() {
Config cfg("Vmemo");
cfg.setGroup("Record");
speed = cfg.readNumEntry("SampleRate", 22050);
channels = cfg.readNumEntry("Stereo", 1) ? 2 : 1; // 1 = stereo(2), 0 = mono(1)
if (cfg.readNumEntry("SixteenBit", 1)==1) {
format = AFMT_S16_LE;
resolution = 16;
} else {
format = AFMT_U8;
resolution = 8;
}
odebug << "samplerate: " << speed << ", channels " << channels << ", resolution " << resolution << "" << oendl;
if(systemZaurus) {
dsp = open("/dev/dsp1", O_RDONLY); //Zaurus needs /dev/dsp1
channels=1; //zaurus has one input channel
} else {
#ifdef QT_QWS_DEVFS
dsp = open("/dev/sound/dsp", O_RDONLY);
#else
dsp = open("/dev/dsp", O_RDONLY);
#endif
}
if (dsp == -1) {
msgLabel->close();
msgLabel=0;
delete msgLabel;
perror("open(\"/dev/dsp\")");
errorMsg="open(\"/dev/dsp\")\n "+(QString)strerror(errno);
QMessageBox::critical(0, "vmemo", errorMsg, "Abort");
return -1;
}
if(ioctl(dsp, SNDCTL_DSP_SETFMT , &format)==-1) {
perror("ioctl(\"SNDCTL_DSP_SETFMT\")");
// return -1;
}
if(ioctl(dsp, SNDCTL_DSP_CHANNELS , &channels)==-1) {
perror("ioctl(\"SNDCTL_DSP_CHANNELS\")");
// return -1;
}
if(ioctl(dsp, SNDCTL_DSP_SPEED , &speed)==-1) {
perror("ioctl(\"SNDCTL_DSP_SPEED\")");
// return -1;
}
if(ioctl(dsp, SOUND_PCM_READ_RATE , &rate)==-1) {
perror("ioctl(\"SOUND_PCM_READ_RATE\")");
// return -1;
}
QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << false; //mute
return 1;
}
int VMemo::openWAV(const char *filename) {
track.setName(filename);
if(!track.open(IO_WriteOnly|IO_Truncate|IO_Raw)) {
errorMsg=filename;
return -1;
}
wav=track.handle();
Config vmCfg("Vmemo");
vmCfg.setGroup("Defaults");
useADPCM = vmCfg.readBoolEntry("use_ADPCM", 0);
WaveHeader wh;
wh.main_chunk = RIFF;
wh.length=0;
wh.chunk_type = WAVE;
wh.sub_chunk = FMT;
wh.sc_len = 16;
if(useADPCM)
wh.format = WAVE_FORMAT_DVI_ADPCM;//PCM_CODE;
else
wh.format = PCM_CODE;
wh.modus = channels;
wh.sample_fq = speed;
wh.byte_p_sec = speed * channels * resolution/8;
wh.byte_p_spl = channels * (resolution / 8);
wh.bit_p_spl = resolution;
wh.data_chunk = DATA;
wh.data_length= 0;
// odebug << "Write header channels " << wh.modus << ", speed " << wh.sample_fq << ", b/s "
// << wh.byte_p_sec << ", blockalign " << wh.byte_p_spl << ", bitrate " << wh.bit_p_spl << oendl;
write (wav, &wh, sizeof(WaveHeader));
return 1;
}
bool VMemo::record() {
length = 0;
int bytesWritten = 0;
int result = 0;
int value = 0;
QString msg;
msg.sprintf("Recording format %d", format);
odebug << msg << oendl;
Config config("Vmemo");
config.setGroup("Record");
int sRate = config.readNumEntry("SizeLimit", 30);
odebug << "VMEMO rate" << sRate << oendl;
if(sRate > 0) {
t_timer->start( sRate * 1000+1000, true);
}
msg.sprintf("Recording format other");
odebug << msg << oendl;
config.setGroup("Defaults");
useADPCM = config.readBoolEntry("use_ADPCM", 0);
int bufsize = config.readNumEntry("BufferSize",1024);
unsigned short sound[bufsize]; //, monoBuffer[bufsize];
char abuf[bufsize / 2];
short sbuf[bufsize];
odebug << "ready to record"<< oendl;
if(useADPCM) {
odebug << "usr ADPCM" << oendl;
while(recording) {
result = ::read(dsp, sbuf, bufsize); // adpcm read
if( result <= 0) {
perror("recording error ");
QMessageBox::message(tr("Note"),tr("error recording"));
recording = false;
break;
return false;
}
adpcm_coder( sbuf, abuf, result/2, &encoder_state);
bytesWritten = ::write(wav, abuf, result/4); // adpcm write
length += bytesWritten;
if(length < 0) {
recording = false;
perror("dev/dsp's is a lookin' messy");
QMessageBox::message("Vmemo","Error writing to file\n"+ fileName);
break;
return false;
}
printf("%d\r", length);
fflush(stdout);
qApp->processEvents();
}
} else {
odebug << "use regular wav" << oendl;
while(recording) {
result = ::read(dsp, sound, bufsize); // read
if( result <= 0) {
perror("recording error ");
QMessageBox::message(tr("Note"),tr("error recording"));
recording = false;
break;
return false;
}
bytesWritten = ::write(wav, sound, result); // write
length += bytesWritten;
if(length < 0) {
recording = false;
perror("dev/dsp's is a lookin' messy");
QMessageBox::message("Vmemo","Error writing to file\n"+ fileName);
break;
return false;
}
// printf("%d\r", length);
// fflush(stdout);
qApp->processEvents();
}
}
owarn << "file has length of " << length << " lasting " << (( length / speed) / channels) / 2 << " seconds" << oendl;
value = length + 36;
lseek(wav, 4, SEEK_SET);
write(wav, &value, 4);
lseek(wav, 40, SEEK_SET);
write(wav, &length, 4);
track.close();
if( ioctl( dsp, SNDCTL_DSP_RESET,0) == -1)
perror("ioctl(\"SNDCTL_DSP_RESET\")");
::close(dsp);
Config cfgO("OpieRec");
cfgO.setGroup("Sounds");
int nFiles = cfgO.readNumEntry( "NumberofFiles",0);
QString currentFileName = fileName;
QString currentFile = "vm_"+ date;
float numberOfRecordedSeconds = (float) length / (float)speed * (float)2;
cfgO.writeEntry( "NumberofFiles", nFiles + 1);
cfgO.writeEntry( QString::number( nFiles + 1), currentFile);
cfgO.writeEntry( currentFile, currentFileName);
QString time;
time.sprintf("%.2f", numberOfRecordedSeconds);
cfgO.writeEntry( currentFileName, time );
// odebug << "writing config numberOfRecordedSeconds "+time << oendl;
cfgO.write();
odebug << "done recording "+fileName << oendl;
Config cfg("qpe");
cfg.setGroup("Volume");
QString foo = cfg.readEntry("Mute","true");
if(foo.find("true",0,true) != -1)
QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << true; //mute
return true;
}
int VMemo::setToggleButton(int tog) {
for( int i=0; i < 10;i++) {
switch (tog) {
case 0:
return -1;
break;
case 1:
return 0;
break;
case 2:
return Key_F24; //was Escape
break;
case 3:
return Key_Space;
break;
case 4:
return Key_F12;
break;
case 5:
return Key_F9;
break;
case 6:
return Key_F10;
break;
case 7:
return Key_F11;
break;
case 8:
return Key_F13;
break;
};
}
return -1;
}
void VMemo::timerBreak() {
//stop
stopRecording();
QMessageBox::message("Vmemo","Vmemo recording has ended");
}
EXPORT_OPIE_APPLET_v1( VMemo )
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,212 +1,233 @@
/* -------------------------------------------------------------------------- */
/* */
/* [TEHistory.C] History Buffer */
/* */
/* -------------------------------------------------------------------------- */
/* */
/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
/* */
/* This file is part of Konsole - an X terminal for KDE */
/* */
/* -------------------------------------------------------------------------- */
/* */
/* Ported Konsole to Qt/Embedded */
/* */
/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
/* */
/* -------------------------------------------------------------------------- */
#include "TEHistory.h"
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
/*
An arbitrary long scroll.
One can modify the scroll only by adding either cells
or newlines, but access it randomly.
The model is that of an arbitrary wide typewriter scroll
in that the scroll is a serie of lines and each line is
a serie of cells with no overwriting permitted.
The implementation provides arbitrary length and numbers
of cells and line/column indexed read access to the scroll
at constant costs.
FIXME: some complain about the history buffer comsuming the
memory of their machines. This problem is critical
since the history does not behave gracefully in cases
where the memory is used up completely.
I put in a workaround that should handle it problem
now gracefully. I'm not satisfied with the solution.
FIXME: Terminating the history is not properly indicated
in the menu. We should throw a signal.
FIXME: There is noticable decrease in speed, also. Perhaps,
there whole feature needs to be revisited therefore.
Disadvantage of a more elaborated, say block-oriented
scheme with wrap around would be it's complexity.
*/
//FIXME: tempory replacement for tmpfile
// this is here one for debugging purpose.
//#define tmpfile xTmpFile
FILE* xTmpFile()
{
static int fid = 0;
char fname[80];
sprintf(fname,"TmpFile.%d",fid++);
return fopen(fname,"w");
}
// History Buffer ///////////////////////////////////////////
/*
A Row(X) data type which allows adding elements to the end.
*/
HistoryBuffer::HistoryBuffer()
{
ion = -1;
length = 0;
}
HistoryBuffer::~HistoryBuffer()
{
setScroll(FALSE);
}
void HistoryBuffer::setScroll(bool on)
{
if (on == hasScroll()) return;
if (on)
{
assert( ion < 0 );
assert( length == 0);
- FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; }
- ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n");
- fclose(tmp);
+ char* tmpDir = getenv("TMPDIR");
+ char* tmpFilePath = 0;
+ if (tmpDir && *tmpDir != '\0') {
+ tmpFilePath = new char[strlen(tmpDir) + strlen("/opie-console-HistoryBuffer-XXXXXX") + 1];
+ strcpy(tmpFilePath, tmpDir);
+ free(tmpDir);
+ } else {
+ tmpFilePath = new char[strlen("/tmp/opie-console-HistoryBuffer-XXXXXX") + 1];
+ strcpy(tmpFilePath, "/tmp");
+ }
+ strcat(tmpFilePath, "/opie-console-HistoryBuffer-XXXXXX");
+ mode_t currUmask = umask(S_IRWXO | S_IRWXG);
+ int tmpfd = mkstemp(tmpFilePath);
+ delete [] tmpFilePath;
+ umask(currUmask);
+ if (tmpfd == -1) {
+ perror("konsole: cannot open temp file.\n");
+ return;
+ }
+ ion = dup(tmpfd);
+ if (ion<0)
+ perror("konsole: cannot dup temp file.\n");
+ close(tmpfd);
}
else
{
assert( ion >= 0 );
close(ion);
ion = -1;
length = 0;
}
}
bool HistoryBuffer::hasScroll()
{
return ion >= 0;
}
void HistoryBuffer::add(const unsigned char* bytes, int len)
{ int rc;
assert(hasScroll());
rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; }
rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; }
length += rc;
}
void HistoryBuffer::get(unsigned char* bytes, int len, int loc)
{ int rc;
assert(hasScroll());
if (loc < 0 || len < 0 || loc + len > length)
fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; }
rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; }
}
int HistoryBuffer::len()
{
return length;
}
// History Scroll //////////////////////////////////////
/*
The history scroll makes a Row(Row(Cell)) from
two history buffers. The index buffer contains
start of line positions which refere to the cells
buffer.
Note that index[0] addresses the second line
(line #1), while the first line (line #0) starts
at 0 in cells.
*/
HistoryScroll::HistoryScroll()
{
}
HistoryScroll::~HistoryScroll()
{
}
void HistoryScroll::setScroll(bool on)
{
index.setScroll(on);
cells.setScroll(on);
}
bool HistoryScroll::hasScroll()
{
return index.hasScroll() && cells.hasScroll();
}
int HistoryScroll::getLines()
{
if (!hasScroll()) return 0;
return index.len() / sizeof(int);
}
int HistoryScroll::getLineLen(int lineno)
{
if (!hasScroll()) return 0;
return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca);
}
int HistoryScroll::startOfLine(int lineno)
{
if (lineno <= 0) return 0;
if (!hasScroll()) return 0;
if (lineno <= getLines())
{ int res;
index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
return res;
}
return cells.len();
}
void HistoryScroll::getCells(int lineno, int colno, int count, ca res[])
{
assert(hasScroll());
cells.get((unsigned char*)res,count*sizeof(ca),startOfLine(lineno)+colno*sizeof(ca));
}
void HistoryScroll::addCells(ca text[], int count)
{
if (!hasScroll()) return;
cells.add((unsigned char*)text,count*sizeof(ca));
}
void HistoryScroll::addLine()
{
if (!hasScroll()) return;
int locn = cells.len();
index.add((unsigned char*)&locn,sizeof(int));
}