summaryrefslogtreecommitdiff
authorerik <erik>2007-01-10 17:31:08 (UTC)
committer erik <erik>2007-01-10 17:31:08 (UTC)
commit6825f30b665952864dbe35fe8329a0e4c264d4b8 (patch) (side-by-side diff)
tree7c8d178f835d4a7d294b6ef65e0040c40579e84e
parentd8e580a239ab84fbe063b2f3779d417598d5ca0a (diff)
downloadopie-6825f30b665952864dbe35fe8329a0e4c264d4b8.zip
opie-6825f30b665952864dbe35fe8329a0e4c264d4b8.tar.gz
opie-6825f30b665952864dbe35fe8329a0e4c264d4b8.tar.bz2
All of the files included have instances where an array is new'ed but
the corresponding delete does not have the corresponding [] argument.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/apps/embeddedkonsole/TEScreen.cpp4
-rw-r--r--noncore/apps/checkbook/listedit.cpp2
-rw-r--r--noncore/apps/opie-console/TEScreen.cpp4
-rw-r--r--noncore/apps/opie-sheet/Excel.cpp2
-rw-r--r--noncore/apps/tinykate/libkate/document/katedocument.cpp4
-rw-r--r--noncore/comm/keypebble/krfbdecoder.cpp6
-rw-r--r--noncore/games/sfcave/sfcave.cpp2
-rw-r--r--noncore/settings/aqpkg/settingsimpl.cpp2
-rw-r--r--noncore/settings/aqpkg/version.cpp2
9 files changed, 14 insertions, 14 deletions
diff --git a/core/apps/embeddedkonsole/TEScreen.cpp b/core/apps/embeddedkonsole/TEScreen.cpp
index 8e69a88..1db34d2 100644
--- a/core/apps/embeddedkonsole/TEScreen.cpp
+++ b/core/apps/embeddedkonsole/TEScreen.cpp
@@ -1,1236 +1,1236 @@
/* -------------------------------------------------------------------------- */
/* */
/* [TEScreen.C] Screen Data Type */
/* */
/* -------------------------------------------------------------------------- */
/* */
/* 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> */
/* */
/* -------------------------------------------------------------------------- */
// enhancements added by L.J. Potter <ljp@llornkcor.com>
/*! \file
*/
/*! \class TEScreen
\brief The image manipulated by the emulation.
This class implements the operations of the terminal emulation framework.
It is a complete passive device, driven by the emulation decoder
(TEmuVT102). By this it forms in fact an ADT, that defines operations
on a rectangular image.
It does neither know how to display its image nor about escape sequences.
It is further independent of the underlying toolkit. By this, one can even
use this module for an ordinary text surface.
Since the operations are called by a specific emulation decoder, one may
collect their different operations here.
The state manipulated by the operations is mainly kept in `image', though
it is a little more complex bejond this. See the header file of the class.
\sa TEWidget \sa VT102Emulation
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// #include <kdebug.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <qpe/config.h>
#include "TEScreen.h"
#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
//FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
//FIXME: see if we can get this from terminfo.
#define BS_CLEARS FALSE
#define loc(X,Y) ((Y) * columns + (X))
/*! creates a `TEScreen' of `lines' lines and `columns' columns.
*/
TEScreen::TEScreen(int lines, int columns)
{
this->lines = lines;
this->columns = columns;
// odebug << "Columns " << columns << "" << oendl;
image = (ca*) malloc(lines*columns*sizeof(ca));
tabstops = NULL; initTabStops();
histCursor = 0;
horzCursor = 0;
clearSelection();
reset();
}
/*! Destructor
*/
TEScreen::~TEScreen()
{
free(image);
if (tabstops) free(tabstops);
}
/* ------------------------------------------------------------------------- */
/* */
/* Normalized Screen Operations */
/* */
/* ------------------------------------------------------------------------- */
// Cursor Setting --------------------------------------------------------------
/*! \section Cursor
The `cursor' is a location within the screen that is implicitely used in
many operations. The operations within this section allow to manipulate
the cursor explicitly and to obtain it's value.
The position of the cursor is guarantied to be between (including) 0 and
`columns-1' and `lines-1'.
*/
/*!
Move the cursor up.
The cursor will not be moved beyond the top margin.
*/
void TEScreen::cursorUp(int n)
//=CUU
{
if (n == 0) n = 1; // Default
int stop = cuY < tmargin ? 0 : tmargin;
cuX = QMIN(columns-1,cuX); // nowrap!
cuY = QMAX(stop,cuY-n);
}
/*!
Move the cursor down.
The cursor will not be moved beyond the bottom margin.
*/
void TEScreen::cursorDown(int n)
//=CUD
{
if (n == 0) n = 1; // Default
int stop = cuY > bmargin ? lines-1 : bmargin;
cuX = QMIN(columns-1,cuX); // nowrap!
cuY = QMIN(stop,cuY+n);
}
/*!
Move the cursor left.
The cursor will not move beyond the first column.
*/
void TEScreen::cursorLeft(int n)
//=CUB
{
if (n == 0) n = 1; // Default
cuX = QMIN(columns-1,cuX); // nowrap!
cuX = QMAX(0,cuX-n);
}
/*!
Move the cursor left.
The cursor will not move beyond the rightmost column.
*/
void TEScreen::cursorRight(int n)
//=CUF
{
if (n == 0) n = 1; // Default
cuX = QMIN(columns-1,cuX+n);
}
/*!
Set top and bottom margin.
*/
void TEScreen::setMargins(int top, int bot)
//=STBM
{
if (top == 0) top = 1; // Default
if (bot == 0) bot = lines; // Default
top = top - 1; // Adjust to internal lineno
bot = bot - 1; // Adjust to internal lineno
if ( !( 0 <= top && top < bot && bot < lines ) )
{ fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
__FILE__,__LINE__,top,bot);
return; // Default error action: ignore
}
tmargin = top;
bmargin = bot;
cuX = 0;
cuY = getMode(MODE_Origin) ? top : 0;
}
/*!
Move the cursor down one line.
If cursor is on bottom margin, the region between the
actual top and bottom margin is scrolled up instead.
*/
void TEScreen::index()
//=IND
{
if (cuY == bmargin)
{
if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
scrollUp(tmargin,1);
}
else if (cuY < lines-1)
cuY += 1;
}
/*!
Move the cursor up one line.
If cursor is on the top margin, the region between the
actual top and bottom margin is scrolled down instead.
*/
void TEScreen::reverseIndex()
//=RI
{
if (cuY == tmargin)
scrollDown(tmargin,1);
else if (cuY > 0)
cuY -= 1;
}
/*!
Move the cursor to the begin of the next line.
If cursor is on bottom margin, the region between the
actual top and bottom margin is scrolled up.
*/
void TEScreen::NextLine()
//=NEL
{
Return(); index();
}
// Line Editing ----------------------------------------------------------------
/*! \section inserting / deleting characters
*/
/*! erase `n' characters starting from (including) the cursor position.
The line is filled in from the right with spaces.
*/
void TEScreen::eraseChars(int n)
{
if (n == 0) n = 1; // Default
int p = QMAX(0,QMIN(cuX+n-1,columns-1));
clearImage(loc(cuX,cuY),loc(p,cuY),' ');
}
/*! delete `n' characters starting from (including) the cursor position.
The line is filled in from the right with spaces.
*/
void TEScreen::deleteChars(int n)
{
if (n == 0) n = 1; // Default
int p = QMAX(0,QMIN(cuX+n,columns-1));
moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
}
/*! insert `n' spaces at the cursor position.
The cursor is not moved by the operation.
*/
void TEScreen::insertChars(int n)
{
if (n == 0) n = 1; // Default
int p = QMAX(0,QMIN(columns-1-n,columns-1));
int q = QMAX(0,QMIN(cuX+n,columns-1));
moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
}
/*! delete `n' lines starting from (including) the cursor position.
The cursor is not moved by the operation.
*/
void TEScreen::deleteLines(int n)
{
if (n == 0) n = 1; // Default
scrollUp(cuY,n);
}
/*! insert `n' lines at the cursor position.
The cursor is not moved by the operation.
*/
void TEScreen::insertLines(int n)
{
if (n == 0) n = 1; // Default
scrollDown(cuY,n);
}
// Mode Operations -----------------------------------------------------------
/*! Set a specific mode. */
void TEScreen::setMode(int m)
{
currParm.mode[m] = TRUE;
switch(m)
{
case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
}
}
/*! Reset a specific mode. */
void TEScreen::resetMode(int m)
{
currParm.mode[m] = FALSE;
switch(m)
{
case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
}
}
/*! Save a specific mode. */
void TEScreen::saveMode(int m)
{
saveParm.mode[m] = currParm.mode[m];
}
/*! Restore a specific mode. */
void TEScreen::restoreMode(int m)
{
currParm.mode[m] = saveParm.mode[m];
}
//NOTE: this is a helper function
/*! Return the setting a specific mode. */
BOOL TEScreen::getMode(int m)
{
return currParm.mode[m];
}
/*! Save the cursor position and the rendition attribute settings. */
void TEScreen::saveCursor()
{
sa_cuX = cuX;
sa_cuY = cuY;
sa_cu_re = cu_re;
sa_cu_fg = cu_fg;
sa_cu_bg = cu_bg;
}
/*! Restore the cursor position and the rendition attribute settings. */
void TEScreen::restoreCursor()
{
cuX = QMIN(sa_cuX,columns-1);
cuY = QMIN(sa_cuY,lines-1);
cu_re = sa_cu_re;
cu_fg = sa_cu_fg;
cu_bg = sa_cu_bg;
effectiveRendition();
}
/* ------------------------------------------------------------------------- */
/* */
/* Screen Operations */
/* */
/* ------------------------------------------------------------------------- */
/*! Assing a new size to the screen.
The topmost left position is maintained, while lower lines
or right hand side columns might be removed or filled with
spaces to fit the new size.
The region setting is reset to the whole screen and the
tab positions reinitialized.
*/
void TEScreen::resizeImage(int new_lines, int new_columns)
{
if (cuY > new_lines-1) {
// attempt to preserve focus and lines
bmargin = lines-1; //FIXME: margin lost
for (int i = 0; i < cuY-(new_lines-1); i++) {
addHistLine(); scrollUp(horzCursor,1);
}
}
// make new image
ca* newimg = (ca*)malloc( new_lines * new_columns * sizeof( ca));
clearSelection();
// clear new image
for (int y = 0; y < new_lines; y++)
for (int x = 0; x < new_columns; x++) {
newimg[y*new_columns+x].c = ' ';
newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
newimg[y*new_columns+x].r = DEFAULT_RENDITION;
}
int cpy_lines = QMIN(new_lines, lines);
int cpy_columns = QMIN(new_columns,columns);
// copy to new image
for (int y = 0; y < cpy_lines; y++)
for (int x = 0; x < cpy_columns; x++) {
newimg[y*new_columns+x].c = image[loc(x,y)].c;
newimg[y*new_columns+x].f = image[loc(x,y)].f;
newimg[y*new_columns+x].b = image[loc(x,y)].b;
newimg[y*new_columns+x].r = image[loc(x,y)].r;
}
free(image);
image = newimg;
lines = new_lines;
columns = new_columns;
cuX = QMIN(cuX,columns-1);
cuY = QMIN(cuY,lines-1);
// FIXME: try to keep values, evtl.
tmargin=0;
bmargin=lines-1;
initTabStops();
clearSelection();
}
/*
Clarifying rendition here and in TEWidget.
currently, TEWidget's color table is
0 1 2 .. 9 10 .. 17
dft_fg, dft_bg, dim 0..7, intensive 0..7
cu_fg, cu_bg contain values 0..8;
- 0 = default color
- 1..8 = ansi specified color
re_fg, re_bg contain values 0..17
due to the TEWidget's color table
rendition attributes are
attr widget screen
-------------- ------ ------
RE_UNDERLINE XX XX affects foreground only
RE_BLINK XX XX affects foreground only
RE_BOLD XX XX affects foreground only
RE_REVERSE -- XX
RE_TRANSPARENT XX -- affects background only
RE_INTENSIVE XX -- affects foreground only
Note that RE_BOLD is used in both widget
and screen rendition. Since xterm/vt102
is to poor to distinguish between bold
(which is a font attribute) and intensive
(which is a color attribute), we translate
this and RE_BOLD in falls eventually appart
into RE_BOLD and RE_INTENSIVE.
*/
void TEScreen::reverseRendition(ca* p)
{ UINT8 f = p->f; UINT8 b = p->b;
p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
}
void TEScreen::effectiveRendition()
// calculate rendition
{
ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
if (cu_re & RE_REVERSE)
{
ef_fg = cu_bg;
ef_bg = cu_fg;
}
else
{
ef_fg = cu_fg;
ef_bg = cu_bg;
}
if (cu_re & RE_BOLD)
{
if (ef_fg < BASE_COLORS)
ef_fg += BASE_COLORS;
else
ef_fg -= BASE_COLORS;
}
}
/*!
returns the image.
Get the size of the image by \sa getLines and \sa getColumns.
NOTE that the image returned by this function must later be
freed.
*/
ca* TEScreen::getCookedImage()
{
int x,y;
ca* merged = (ca*)malloc(lines*columns*sizeof(ca));
ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
if (histCursor > hist.getLines()) {
histCursor = hist.getLines();
}
for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
{
int len = QMIN(columns,hist.getLineLen(y+histCursor));
int yp = y*columns;
int yq = (y+histCursor)*columns;
hist.getCells(y+histCursor,0,len,merged+yp);
for (x = len; x < columns; x++) merged[yp+x] = dft;
for (x = 0; x < columns; x++)
{ int p=x + yp; int q=x + yq;
if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
reverseRendition(&merged[p]); // for selection
}
}
if (lines >= hist.getLines()-histCursor)
{
for (y = (hist.getLines()-histCursor); y < lines ; y++)
{
int yp = y*columns;
int yq = (y+histCursor)*columns;
int yr = (y-hist.getLines()+histCursor)*columns;
for (x = 0; x < columns; x++)
{ int p = x + yp; int q = x + yq; int r = x + yr;
merged[p] = image[r];
if ( q >= sel_TL && q <= sel_BR )
reverseRendition(&merged[p]); // for selection
}
}
}
// evtl. inverse display
if (getMode(MODE_Screen))
{ int i,n = lines*columns;
for (i = 0; i < n; i++)
reverseRendition(&merged[i]); // for reverse display
}
if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
return merged;
}
/*!
*/
void TEScreen::reset()
{
Config cfg( "Konsole" );
cfg.setGroup("ScrollBar");
if( !cfg.readBoolEntry("HorzScroll",0) )
setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin
resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1]
resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke
setMode(MODE_Cursor); // cursor visible
resetMode(MODE_Screen); // screen not inverse
resetMode(MODE_NewLine);
tmargin=0;
bmargin=lines-1;
setDefaultRendition();
saveCursor();
clear();
}
/*! Clear the entire screen and home the cursor.
*/
void TEScreen::clear()
{
clearEntireScreen();
home();
}
/*! Moves the cursor left one column.
*/
void TEScreen::BackSpace()
{
cuX = QMAX(0,cuX-1);
if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
}
/*!
*/
void TEScreen::Tabulate()
{
// note that TAB is a format effector (does not write ' ');
cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
}
void TEScreen::clearTabStops()
{
for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
}
void TEScreen::changeTabStop(bool set)
{
if (cuX >= columns) return;
tabstops[cuX] = set;
}
void TEScreen::initTabStops()
{
if (tabstops) free(tabstops);
tabstops = (bool*)malloc(columns*sizeof(bool));
// Arrg! The 1st tabstop has to be one longer than the other.
// i.e. the kids start counting from 0 instead of 1.
// Other programs might behave correctly. Be aware.
for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
}
/*!
This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)
depending on the NewLine Mode (LNM). This mode also
affects the key sequence returned for newline ([CR]LF).
*/
void TEScreen::NewLine()
{
if (getMode(MODE_NewLine)) Return();
index();
}
/*! put `c' literally onto the screen at the current cursor position.
VT100 uses the convention to produce an automatic newline (am)
with the *first* character that would fall onto the next line (xenl).
*/
void TEScreen::checkSelection(int from, int to)
{
if (sel_begin == -1) return;
int scr_TL = loc(0, hist.getLines());
//Clear entire selection if it overlaps region [from, to]
if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
{
clearSelection();
}
}
void TEScreen::ShowCharacter(unsigned short c)
{
// Note that VT100 does wrapping BEFORE putting the character.
// This has impact on the assumption of valid cursor positions.
// We indicate the fact that a newline has to be triggered by
// putting the cursor one right to the last column of the screen.
if (cuX >= columns)
{
if (getMode(MODE_Wrap)) NextLine(); else cuX = columns - 1;
// comment out for no wrap
}
if (getMode(MODE_Insert)) insertChars(1);
int i = loc( cuX, cuY);
checkSelection(i, i); // check if selection is still valid.
image[i].c = c;
image[i].f = ef_fg;
image[i].b = ef_bg;
image[i].r = ef_re;
cuX += 1;
}
// Region commands -------------------------------------------------------------
/*! scroll up `n' lines within current region.
The `n' new lines are cleared.
\sa setRegion \sa scrollDown
*/
void TEScreen::scrollUp(int from, int n)
{
if (n <= 0 || from + n > bmargin) return;
//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
moveImage( loc( 0, from), loc( 0, from + n), loc( columns - 1, bmargin));
clearImage( loc( 0, bmargin - n + 1), loc( columns - 1, bmargin), ' ');
}
/*! scroll down `n' lines within current region.
The `n' new lines are cleared.
\sa setRegion \sa scrollUp
*/
void TEScreen::scrollDown(int from, int n)
{
//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
if (n <= 0) return;
if (from > bmargin) return;
if (from + n > bmargin) n = bmargin - from;
moveImage( loc(0,from+n), loc(0,from), loc(columns-1,bmargin-n));
clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
}
/*! position the cursor to a specific line and column. */
void TEScreen::setCursorYX(int y, int x)
{
setCursorY(y); setCursorX(x);
}
/*! Set the cursor to x-th line. */
void TEScreen::setCursorX(int x)
{
if (x == 0) x = 1; // Default
x -= 1; // Adjust
cuX = QMAX(0,QMIN(columns-1, x));
}
/*! Set the cursor to y-th line. */
void TEScreen::setCursorY(int y)
{
if (y == 0) y = 1; // Default
y -= 1; // Adjust
cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
}
/*! set cursor to the `left upper' corner of the screen (1,1).
*/
void TEScreen::home()
{
cuX = 0;
cuY = 0;
}
/*! set cursor to the begin of the current line.
*/
void TEScreen::Return()
{
cuX = 0;
}
/*! returns the current cursor columns.
*/
int TEScreen::getCursorX()
{
return cuX;
}
/*! returns the current cursor line.
*/
int TEScreen::getCursorY()
{
return cuY;
}
// Erasing ---------------------------------------------------------------------
/*! \section Erasing
This group of operations erase parts of the screen contents by filling
it with spaces colored due to the current rendition settings.
Althought the cursor position is involved in most of these operations,
it is never modified by them.
*/
/*! fill screen between (including) `loca' and `loce' with spaces.
This is an internal helper functions. The parameter types are internal
addresses of within the screen image and make use of the way how the
screen matrix is mapped to the image vector.
*/
void TEScreen::clearImage(int loca, int loce, char c)
{ int i;
int scr_TL=loc(0,hist.getLines());
//FIXME: check positions
//Clear entire selection if it overlaps region to be moved...
if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
{
clearSelection();
}
for (i = loca; i <= loce; i++)
{
image[i].c = c;
image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different
image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here.
}
}
/*! move image between (including) `loca' and `loce' to 'dst'.
This is an internal helper functions. The parameter types are internal
addresses of within the screen image and make use of the way how the
screen matrix is mapped to the image vector.
*/
void TEScreen::moveImage(int dst, int loca, int loce)
{
//FIXME: check positions
if (loce < loca) {
// kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
return;
}
memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
}
/*! clear from (including) current cursor position to end of screen.
*/
void TEScreen::clearToEndOfScreen()
{
clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
}
/*! clear from begin of screen to (including) current cursor position.
*/
void TEScreen::clearToBeginOfScreen()
{
clearImage(loc(0,0),loc(cuX,cuY),' ');
}
/*! clear the entire screen.
*/
void TEScreen::clearEntireScreen()
{
clearImage(loc(0,0),loc(columns-1,lines-1),' ');
}
/*! fill screen with 'E'
This is to aid screen alignment
*/
void TEScreen::helpAlign()
{
clearImage(loc(0,0),loc(columns-1,lines-1),'E');
}
/*! clear from (including) current cursor position to end of current cursor line.
*/
void TEScreen::clearToEndOfLine()
{
clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
}
/*! clear from begin of current cursor line to (including) current cursor position.
*/
void TEScreen::clearToBeginOfLine()
{
clearImage(loc(0,cuY),loc(cuX,cuY),' ');
}
/*! clears entire current cursor line
*/
void TEScreen::clearEntireLine()
{
clearImage( loc( 0, cuY),loc( columns - 1, cuY),' ');
}
// Rendition ------------------------------------------------------------------
/*!
set rendition mode
*/
void TEScreen::setRendition(int re)
{
cu_re |= re;
effectiveRendition();
}
/*!
reset rendition mode
*/
void TEScreen::resetRendition(int re)
{
cu_re &= ~re;
effectiveRendition();
}
/*!
*/
void TEScreen::setDefaultRendition()
{
setForeColorToDefault();
setBackColorToDefault();
cu_re = DEFAULT_RENDITION;
effectiveRendition();
}
/*!
*/
void TEScreen::setForeColor(int fgcolor)
{
cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
effectiveRendition();
}
/*!
*/
void TEScreen::setBackColor(int bgcolor)
{
cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
effectiveRendition();
}
/*!
*/
void TEScreen::setBackColorToDefault()
{
cu_bg = DEFAULT_BACK_COLOR;
effectiveRendition();
}
/*!
*/
void TEScreen::setForeColorToDefault()
{
cu_fg = DEFAULT_FORE_COLOR;
effectiveRendition();
}
/* ------------------------------------------------------------------------- */
/* */
/* Marking & Selection */
/* */
/* ------------------------------------------------------------------------- */
void TEScreen::clearSelection()
{
sel_BR = -1;
sel_TL = -1;
sel_begin = -1;
}
void TEScreen::setSelBeginXY(const int x, const int y)
{
if (histCursor > hist.getLines()) {
histCursor = hist.getLines();
}
sel_begin = loc(x,y+histCursor) ;
sel_BR = sel_begin;
sel_TL = sel_begin;
}
void TEScreen::setSelExtentXY(const int x, const int y)
{
if (sel_begin == -1) return;
if (histCursor > hist.getLines()) {
histCursor = hist.getLines();
}
int l = loc(x,y + histCursor);
if (l < sel_begin)
{
sel_TL = l;
sel_BR = sel_begin;
}
else
{
/* FIXME, HACK to correct for x too far to the right... */
if (( x == columns )|| (x == 0)) l--;
sel_TL = sel_begin;
sel_BR = l;
}
}
QString TEScreen::getSelText(const BOOL preserve_line_breaks)
{
if (sel_begin == -1)
return QString::null; // Selection got clear while selecting.
int *m; // buffer to fill.
int s, d; // source index, dest. index.
int hist_BR = loc(0, hist.getLines());
int hY = sel_TL / columns;
int hX = sel_TL % columns;
int eol; // end of line
s = sel_TL; // tracks copy in source.
// allocate buffer for maximum
// possible size...
d = (sel_BR - sel_TL) / columns + 1;
m = new int[d * (columns + 1) + 2];
d = 0;
while (s <= sel_BR)
{
if (s < hist_BR)
{ // get lines from hist.history
// buffer.
eol = hist.getLineLen(hY);
if ((hY == (sel_BR / columns)) &&
(eol >= (sel_BR % columns)))
{
eol = sel_BR % columns + 1;
}
while (hX < eol)
{
m[d++] = hist.getCell(hY, hX++).c;
s++;
}
if (s <= sel_BR)
{
// The line break handling
// It's different from the screen
// image case!
if (eol % columns == 0)
{
// That's either a completely filled
// line or an empty line
if (eol == 0)
{
m[d++] = '\n';
}
else
{
// We have a full line.
// FIXME: How can we handle newlines
// at this position?!
}
}
else if ((eol + 1) % columns == 0)
{
// FIXME: We don't know if this was a
// space at the last position or a
// short line!!
m[d++] = ' ';
}
else
{
// We have a short line here. Put a
// newline or a space into the
// buffer.
m[d++] = preserve_line_breaks ? '\n' : ' ';
}
}
hY++;
hX = 0;
s = hY * columns;
}
else
{ // or from screen image.
eol = (s / columns + 1) * columns - 1;
if (eol < sel_BR)
{
while ((eol > s) &&
isspace(image[eol - hist_BR].c))
{
eol--;
}
}
else
{
eol = sel_BR;
}
while (s <= eol)
{
m[d++] = image[s++ - hist_BR].c;
}
if (eol < sel_BR)
{
// eol processing see below ...
if ((eol + 1) % columns == 0)
{
if (image[eol - hist_BR].c == ' ')
{
m[d++] = ' ';
}
}
else
{
m[d++] = ((preserve_line_breaks ||
((eol % columns) == 0)) ?
'\n' : ' ');
}
}
s = (eol / columns + 1) * columns;
}
}
QChar* qc = new QChar[d];
for (int i = 0; i < d; i++)
{
qc[i] = m[i];
}
QString res(qc, d);
- delete m;
- delete qc;
+ delete [] m;
+ delete [] qc;
return res;
}
/* above ... end of line processing for selection -- psilva
cases:
1) (eol+1)%columns == 0 --> the whole line is filled.
If the last char is a space, insert (preserve) space. otherwise
leave the text alone, so that words that are broken by linewrap
are preserved.
FIXME:
* this suppresses \n for command output that is
sized to the exact column width of the screen.
2) eol%columns == 0 --> blank line.
insert a \n unconditionally.
Do it either you would because you are in preserve_line_break mode,
or because it's an ASCII paragraph delimiter, so even when
not preserving line_breaks, you want to preserve paragraph breaks.
3) else --> partially filled line
insert a \n in preserve line break mode, else a space
The space prevents concatenation of the last word of one
line with the first of the next.
*/
void TEScreen::addHistLine()
{
assert(hasScroll() || histCursor == 0);
// add to hist buffer
// we have to take care about scrolling, too...
if (hasScroll()){
ca dft;
int end = columns - 1;
while (end >= 0 && image[end] == dft)
end -= 1;
hist.addCells( image, end + 1);
hist.addLine();
// adjust history cursor
histCursor += ( hist.getLines() - 1 == histCursor);
}
if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
}
void TEScreen::setHistCursor(int cursor)
{
histCursor = cursor; //FIXME:rangecheck
if (histCursor > hist.getLines()) {
histCursor = hist.getLines();
}
if (histCursor < 0) {
histCursor = 0;
}
}
void TEScreen::setHorzCursor(int cursor)
{
horzCursor = cursor;
}
int TEScreen::getHistCursor()
{
return histCursor;
}
int TEScreen::getHorzCursor()
{
return horzCursor;
}
int TEScreen::getHistLines()
{
return hist.getLines();
}
void TEScreen::setScroll(bool on)
{
histCursor = 0;
clearSelection();
hist.setScroll(on);
}
bool TEScreen::hasScroll()
{
return hist.hasScroll();
}
diff --git a/noncore/apps/checkbook/listedit.cpp b/noncore/apps/checkbook/listedit.cpp
index e40377b..b297d69 100644
--- a/noncore/apps/checkbook/listedit.cpp
+++ b/noncore/apps/checkbook/listedit.cpp
@@ -1,355 +1,355 @@
/*
This file is part of the OPIE Project
=.
.=l. Copyright (c) 2002 Dan Williams <drw@handhelds.org>
.>+-=
_;:, .> :=|. This file is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This file is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU General
..}^=.= = ; Public License for more details.
++= -. .` .:
: = ...= . :.=- You should have received a copy of the GNU
-. .:....=;==+<; General Public License along with this file;
-_. . . )=. = see the file COPYING. If not, write to the
-- :-=` Free Software Foundation, Inc.,
59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "listedit.h"
/* OPIE */
#include <opie2/odebug.h>
#include <opie2/oresource.h>
#include <qpe/applnk.h>
using namespace Opie::Core;
/* QT */
#include <qlayout.h>
#include <qlineedit.h>
#include <qlistview.h>
#include <qwidgetstack.h>
#include <qcombobox.h>
#include <qpushbutton.h>
// --- ListEdit ---------------------------------------------------------------
ListEdit::ListEdit( QWidget *parent, const char *sName )
: QWidget(parent, sName), TableDef(sName)
{
// get font height
int fh = fontMetrics().height();
// create layout
QGridLayout *layout=new QGridLayout(this);
layout->setSpacing( 2 );
layout->setMargin( 4 );
// type table
_typeTable = new QListView( this );
ColumnDef *def=first();
while( def ) {
_typeTable->addColumn( def->getName() );
def=next();
}
connect( _typeTable, SIGNAL( clicked(QListViewItem*,const QPoint&,int) ), this, SLOT( slotClick(QListViewItem*,const QPoint&,int) ) );
layout->addMultiCellWidget(_typeTable, 0,4,0,4);
_currentItem=NULL;
// edit field
_stack=new QWidgetStack( this );
_stack->setMaximumHeight(fh+5);
layout->addMultiCellWidget(_stack, 5,5,0,2);
_typeEdit = new QLineEdit( _stack );
_stack->raiseWidget(_typeEdit );
connect( _typeEdit, SIGNAL( textChanged(const QString&) ), this, SLOT( slotEditChanged(const QString&) ) );
// combo box
_box=new QComboBox( _stack );
connect( _box, SIGNAL( activated(const QString&) ), this, SLOT( slotActivated(const QString&) ) );
// add button
QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ),
tr( "Add" ), this );
btn->setFixedHeight( AppLnk::smallIconSize()+4 );
connect( btn, SIGNAL( clicked() ), this, SLOT( slotAdd() ) );
layout->addWidget( btn, 5, 3 );
// delete button
btn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), tr( "Delete" ), this );
btn->setFixedHeight( AppLnk::smallIconSize()+4 );
connect( btn, SIGNAL( clicked() ), this, SLOT( slotDel() ) );
layout->addWidget( btn, 5, 4 );
}
// --- ~ListEdit --------------------------------------------------------------
ListEdit::~ListEdit()
{
}
// --- slotEditTypeChanged ----------------------------------------------------
void ListEdit::slotEditChanged(const QString &str)
{
if( !_currentItem || _currentColumn<0 ) return;
_currentItem->setText(_currentColumn, str);
}
// --- slotAddType ------------------------------------------------------------
void ListEdit::slotAdd()
{
// construct new row
QString args[8];
ColumnDef *pCol=this->first();
int i=0;
while( pCol && i<8 ) {
args[i++]=pCol->getNewValue();
pCol=this->next();
}
_currentItem=new QListViewItem(_typeTable, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7] );
// fix uniques
fixTypes();
// display col 0 of new value
QPoint pnt;
slotClick(_currentItem, pnt, 0);
_typeTable->setSelected( _currentItem, true );
// make it selected
_typeEdit->setCursorPosition(0);
_typeEdit->setSelection(0, _typeEdit->text().length() );
}
// --- slotDel -------------------------------------------------------------
void ListEdit::slotDel()
{
if( !_currentItem ) return;
delete _currentItem;
_currentItem=NULL;
_typeEdit->setText("");
_stack->raiseWidget(_typeEdit);
}
// --- fixTypes ----------------------------------------------------------------
// Makes sure all entries have a unique name and empty entries are replaced
// by a generic string. The first version performs the operation on a particular
// column, whereas the 2nd does it for all unique columns.
class ColMap {
public:
ColMap(QString sValue, QListViewItem *pEntry) {
_sValue=sValue;
_pEntry=pEntry;
}
QString &getValue() { return(_sValue); }
QListViewItem *getItem() { return(_pEntry); }
protected:
QString _sValue;
QListViewItem *_pEntry;
};
class ColList : public QList<QString>
{
public:
ColList() : QList<QString>() { }
protected:
int compareItems(QCollection::Item, QCollection::Item);
};
int ColList::compareItems(QCollection::Item i1, QCollection::Item i2) {
return( ((QString *)i1)->compare(*(QString *)i2) );
}
void ListEdit::fixTypes(int iColumn)
{
// get column def
ColumnDef *pDef=this->at(iColumn);
// create map of entries
if( !_typeTable->childCount() ) return;
ColMap **colMap=new ColMap *[_typeTable->childCount()];
QListViewItem *cur=_typeTable->firstChild();
ColList lst;
for(int i=0; i<_typeTable->childCount(); i++) {
colMap[i]=new ColMap(cur->text(iColumn), cur);
lst.append( &(colMap[i]->getValue()) );
cur=cur->nextSibling();
}
// fix empty entries
int i=0;
for(QString *ptr=lst.first(); ptr; ptr=lst.next()) {
*ptr=ptr->stripWhiteSpace();
if( ptr->isEmpty() ) {
i++;
if( i==1 ) *ptr=pDef->getNewValue();
else ptr->sprintf("%s %d", (const char *)pDef->getNewValue(), i);
}
}
// fix dups
lst.sort();
QString repl;
for(uint iCur=0; iCur<lst.count()-1; iCur++) {
QString *current=lst.at(iCur);
for(uint iNext=iCur+1; iNext<lst.count(); iNext++ ) {
if( *current!=*lst.at(iNext) ) continue;
for(int i=2; ; i++) {
repl.sprintf("%s %d", (const char *)*current, i);
bool bDup=false;
uint iChk=iNext+1;
while( iChk<lst.count() ) {
QString *chk=lst.at(iChk);
if( !chk->startsWith(*current) ) break;
if( *chk==repl ) {
bDup=true;
break;
}
iChk++;
}
if( !bDup ) {
*lst.at(iNext)=repl;
break;
}
}
}
}
lst.sort();
// copy back clean up col map
for(int i=0; i<_typeTable->childCount(); i++) {
colMap[i]->getItem()->setText(iColumn, colMap[i]->getValue());
delete colMap[i];
}
- delete colMap;
+ delete [] colMap;
}
void ListEdit::fixTypes()
{
int i;
ColumnDef *pDef;
for(pDef=this->first(), i=0; pDef; pDef=this->next(), i++) {
if( pDef->hasFlag(ColumnDef::typeUnique) )
fixTypes(i);
}
_typeTable->sort();
}
// --- storeInList ------------------------------------------------------------
void ListEdit::storeInList(QStringList &lst)
{
// delete old content
lst.clear();
// add new one
fixTypes();
QListViewItem *itm=_typeTable->firstChild();
while( itm ) {
int i=0;
QString sAdd;
ColumnDef *pDef;
for(pDef=this->first(), i=0; pDef; pDef=this->next(), i++) {
if( i>=1 ) sAdd+=";";
sAdd += itm->text(i);
}
lst.append( sAdd );
itm=itm->nextSibling();
}
}
// --- slotClicked ------------------------------------------------------------
void ListEdit::slotClick(QListViewItem *itm, const QPoint &pnt, int col)
{
(void)pnt; // get rid of unused warning;
// save values
_currentItem=itm;
_currentColumn=col;
if( itm==NULL ) {
_typeEdit->setText("");
_stack->raiseWidget(_typeEdit);
return;
}
// display value
if( _currentColumn<0 ) _currentColumn=0;
ColumnDef *pDef=this->at(_currentColumn);
if( pDef->isType(ColumnDef::typeString) ) {
_typeEdit->setText( _currentItem->text(_currentColumn) );
_stack->raiseWidget(_typeEdit);
} else if( pDef->isType(ColumnDef::typeList) ){
_box->clear();
_box->insertStringList( pDef->getValueList() );
QStringList::Iterator itr;
int i=0;
for(itr=pDef->getValueList().begin(); itr!=pDef->getValueList().end(); itr++) {
if( (*itr)==_currentItem->text(_currentColumn) ) {
_box->setCurrentItem(i);
i=-1;
break;
}
i++;
}
if( i>=0 ) {
_box->insertItem( _currentItem->text(_currentColumn) );
_box->setCurrentItem(i);
}
_stack->raiseWidget(_box);
} else {
odebug << "Unsupported column type for column " << (const char *)pDef->getName() << "" << oendl;
_typeEdit->setText("");
_stack->raiseWidget(_typeEdit);
}
}
// --- addColumnDef -----------------------------------------------------------
void ListEdit::addColumnDef(ColumnDef *pDef)
{
_typeTable->addColumn( pDef->getName() );
_vColumns.append(pDef);
}
// --- addData ----------------------------------------------------------------
void ListEdit::addData(QStringList &lst)
{
// run through list
QStringList::Iterator itr;
for(itr=lst.begin(); itr!=lst.end(); itr++) {
QStringList split=QStringList::split(";", *itr, true);
QStringList::Iterator entry;
QString args[8];
int i=0;
for(entry=split.begin(); entry!=split.end() && i<8; entry++, i++) {
args[i]= (*entry);
}
while(i<8) {
args[i++]="";
}
new QListViewItem(_typeTable, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
}
}
// --- slotActivated ----------------------------------------------------------
void ListEdit::slotActivated(const QString &str)
{
if( _currentItem==NULL || _currentColumn<0 ) return;
_currentItem->setText(_currentColumn, str);
}
diff --git a/noncore/apps/opie-console/TEScreen.cpp b/noncore/apps/opie-console/TEScreen.cpp
index 2675d31..8e91532 100644
--- a/noncore/apps/opie-console/TEScreen.cpp
+++ b/noncore/apps/opie-console/TEScreen.cpp
@@ -1,1208 +1,1208 @@
/* -------------------------------------------------------------------------- */
/* */
/* [TEScreen.C] Screen Data Type */
/* */
/* -------------------------------------------------------------------------- */
/* */
/* 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> */
/* */
/* -------------------------------------------------------------------------- */
/*! \file
*/
/*! \class TEScreen
\brief The image manipulated by the emulation.
This class implements the operations of the terminal emulation framework.
It is a complete passive device, driven by the emulation decoder
(TEmuVT102). By this it forms in fact an ADT, that defines operations
on a rectangular image.
It does neither know how to display its image nor about escape sequences.
It is further independent of the underlying toolkit. By this, one can even
use this module for an ordinary text surface.
Since the operations are called by a specific emulation decoder, one may
collect their different operations here.
The state manipulated by the operations is mainly kept in `image', though
it is a little more complex bejond this. See the header file of the class.
\sa TEWidget \sa VT102Emulation
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// #include <kdebug.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include "TEScreen.h"
#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
//FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
//FIXME: see if we can get this from terminfo.
#define BS_CLEARS FALSE
#define loc(X,Y) ((Y)*columns+(X))
/*! creates a `TEScreen' of `lines' lines and `columns' columns.
*/
TEScreen::TEScreen(int lines, int columns)
{
this->lines = lines;
this->columns = columns;
image = (ca*) malloc(lines*columns*sizeof(ca));
tabstops = NULL; initTabStops();
histCursor = 0;
clearSelection();
reset();
}
/*! Destructor
*/
TEScreen::~TEScreen()
{
free(image);
if (tabstops) free(tabstops);
}
/* ------------------------------------------------------------------------- */
/* */
/* Normalized Screen Operations */
/* */
/* ------------------------------------------------------------------------- */
// Cursor Setting --------------------------------------------------------------
/*! \section Cursor
The `cursor' is a location within the screen that is implicitely used in
many operations. The operations within this section allow to manipulate
the cursor explicitly and to obtain it's value.
The position of the cursor is guarantied to be between (including) 0 and
`columns-1' and `lines-1'.
*/
/*!
Move the cursor up.
The cursor will not be moved beyond the top margin.
*/
void TEScreen::cursorUp(int n)
//=CUU
{
if (n == 0) n = 1; // Default
int stop = cuY < tmargin ? 0 : tmargin;
cuX = QMIN(columns-1,cuX); // nowrap!
cuY = QMAX(stop,cuY-n);
}
/*!
Move the cursor down.
The cursor will not be moved beyond the bottom margin.
*/
void TEScreen::cursorDown(int n)
//=CUD
{
if (n == 0) n = 1; // Default
int stop = cuY > bmargin ? lines-1 : bmargin;
cuX = QMIN(columns-1,cuX); // nowrap!
cuY = QMIN(stop,cuY+n);
}
/*!
Move the cursor left.
The cursor will not move beyond the first column.
*/
void TEScreen::cursorLeft(int n)
//=CUB
{
if (n == 0) n = 1; // Default
cuX = QMIN(columns-1,cuX); // nowrap!
cuX = QMAX(0,cuX-n);
}
/*!
Move the cursor left.
The cursor will not move beyond the rightmost column.
*/
void TEScreen::cursorRight(int n)
//=CUF
{
if (n == 0) n = 1; // Default
cuX = QMIN(columns-1,cuX+n);
}
/*!
Set top and bottom margin.
*/
void TEScreen::setMargins(int top, int bot)
//=STBM
{
if (top == 0) top = 1; // Default
if (bot == 0) bot = lines; // Default
top = top - 1; // Adjust to internal lineno
bot = bot - 1; // Adjust to internal lineno
if ( !( 0 <= top && top < bot && bot < lines ) )
{ fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
__FILE__,__LINE__,top,bot);
return; // Default error action: ignore
}
tmargin = top;
bmargin = bot;
cuX = 0;
cuY = getMode(MODE_Origin) ? top : 0;
}
/*!
Move the cursor down one line.
If cursor is on bottom margin, the region between the
actual top and bottom margin is scrolled up instead.
*/
void TEScreen::index()
//=IND
{
if (cuY == bmargin)
{
if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
scrollUp(tmargin,1);
}
else if (cuY < lines-1)
cuY += 1;
}
/*!
Move the cursor up one line.
If cursor is on the top margin, the region between the
actual top and bottom margin is scrolled down instead.
*/
void TEScreen::reverseIndex()
//=RI
{
if (cuY == tmargin)
scrollDown(tmargin,1);
else if (cuY > 0)
cuY -= 1;
}
/*!
Move the cursor to the begin of the next line.
If cursor is on bottom margin, the region between the
actual top and bottom margin is scrolled up.
*/
void TEScreen::NextLine()
//=NEL
{
Return(); index();
}
// Line Editing ----------------------------------------------------------------
/*! \section inserting / deleting characters
*/
/*! erase `n' characters starting from (including) the cursor position.
The line is filled in from the right with spaces.
*/
void TEScreen::eraseChars(int n)
{
if (n == 0) n = 1; // Default
int p = QMAX(0,QMIN(cuX+n-1,columns-1));
clearImage(loc(cuX,cuY),loc(p,cuY),' ');
}
/*! delete `n' characters starting from (including) the cursor position.
The line is filled in from the right with spaces.
*/
void TEScreen::deleteChars(int n)
{
if (n == 0) n = 1; // Default
int p = QMAX(0,QMIN(cuX+n,columns-1));
moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
}
/*! insert `n' spaces at the cursor position.
The cursor is not moved by the operation.
*/
void TEScreen::insertChars(int n)
{
if (n == 0) n = 1; // Default
int p = QMAX(0,QMIN(columns-1-n,columns-1));
int q = QMAX(0,QMIN(cuX+n,columns-1));
moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
}
/*! delete `n' lines starting from (including) the cursor position.
The cursor is not moved by the operation.
*/
void TEScreen::deleteLines(int n)
{
if (n == 0) n = 1; // Default
scrollUp(cuY,n);
}
/*! insert `n' lines at the cursor position.
The cursor is not moved by the operation.
*/
void TEScreen::insertLines(int n)
{
if (n == 0) n = 1; // Default
scrollDown(cuY,n);
}
// Mode Operations -----------------------------------------------------------
/*! Set a specific mode. */
void TEScreen::setMode(int m)
{
currParm.mode[m] = TRUE;
switch(m)
{
case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
}
}
/*! Reset a specific mode. */
void TEScreen::resetMode(int m)
{
currParm.mode[m] = FALSE;
switch(m)
{
case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
}
}
/*! Save a specific mode. */
void TEScreen::saveMode(int m)
{
saveParm.mode[m] = currParm.mode[m];
}
/*! Restore a specific mode. */
void TEScreen::restoreMode(int m)
{
currParm.mode[m] = saveParm.mode[m];
}
//NOTE: this is a helper function
/*! Return the setting a specific mode. */
BOOL TEScreen::getMode(int m)
{
return currParm.mode[m];
}
/*! Save the cursor position and the rendition attribute settings. */
void TEScreen::saveCursor()
{
sa_cuX = cuX;
sa_cuY = cuY;
sa_cu_re = cu_re;
sa_cu_fg = cu_fg;
sa_cu_bg = cu_bg;
}
/*! Restore the cursor position and the rendition attribute settings. */
void TEScreen::restoreCursor()
{
cuX = QMIN(sa_cuX,columns-1);
cuY = QMIN(sa_cuY,lines-1);
cu_re = sa_cu_re;
cu_fg = sa_cu_fg;
cu_bg = sa_cu_bg;
effectiveRendition();
}
/* ------------------------------------------------------------------------- */
/* */
/* Screen Operations */
/* */
/* ------------------------------------------------------------------------- */
/*! Assing a new size to the screen.
The topmost left position is maintained, while lower lines
or right hand side columns might be removed or filled with
spaces to fit the new size.
The region setting is reset to the whole screen and the
tab positions reinitialized.
*/
void TEScreen::resizeImage(int new_lines, int new_columns)
{
if (cuY > new_lines-1)
{ // attempt to preserve focus and lines
bmargin = lines-1; //FIXME: margin lost
for (int i = 0; i < cuY-(new_lines-1); i++)
{
addHistLine(); scrollUp(0,1);
}
}
// make new image
ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca));
clearSelection();
// clear new image
for (int y = 0; y < new_lines; y++)
for (int x = 0; x < new_columns; x++)
{
newimg[y*new_columns+x].c = ' ';
newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
newimg[y*new_columns+x].r = DEFAULT_RENDITION;
}
int cpy_lines = QMIN(new_lines, lines);
int cpy_columns = QMIN(new_columns,columns);
// copy to new image
for (int y = 0; y < cpy_lines; y++)
for (int x = 0; x < cpy_columns; x++)
{
newimg[y*new_columns+x].c = image[loc(x,y)].c;
newimg[y*new_columns+x].f = image[loc(x,y)].f;
newimg[y*new_columns+x].b = image[loc(x,y)].b;
newimg[y*new_columns+x].r = image[loc(x,y)].r;
}
free(image);
image = newimg;
lines = new_lines;
columns = new_columns;
cuX = QMIN(cuX,columns-1);
cuY = QMIN(cuY,lines-1);
// FIXME: try to keep values, evtl.
tmargin=0;
bmargin=lines-1;
initTabStops();
clearSelection();
}
/*
Clarifying rendition here and in TEWidget.
currently, TEWidget's color table is
0 1 2 .. 9 10 .. 17
dft_fg, dft_bg, dim 0..7, intensive 0..7
cu_fg, cu_bg contain values 0..8;
- 0 = default color
- 1..8 = ansi specified color
re_fg, re_bg contain values 0..17
due to the TEWidget's color table
rendition attributes are
attr widget screen
-------------- ------ ------
RE_UNDERLINE XX XX affects foreground only
RE_BLINK XX XX affects foreground only
RE_BOLD XX XX affects foreground only
RE_REVERSE -- XX
RE_TRANSPARENT XX -- affects background only
RE_INTENSIVE XX -- affects foreground only
Note that RE_BOLD is used in both widget
and screen rendition. Since xterm/vt102
is to poor to distinguish between bold
(which is a font attribute) and intensive
(which is a color attribute), we translate
this and RE_BOLD in falls eventually appart
into RE_BOLD and RE_INTENSIVE.
*/
void TEScreen::reverseRendition(ca* p)
{ UINT8 f = p->f; UINT8 b = p->b;
p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
}
void TEScreen::effectiveRendition()
// calculate rendition
{
ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
if (cu_re & RE_REVERSE)
{
ef_fg = cu_bg;
ef_bg = cu_fg;
}
else
{
ef_fg = cu_fg;
ef_bg = cu_bg;
}
if (cu_re & RE_BOLD)
{
if (ef_fg < BASE_COLORS)
ef_fg += BASE_COLORS;
else
ef_fg -= BASE_COLORS;
}
}
/*!
returns the image.
Get the size of the image by \sa getLines and \sa getColumns.
NOTE that the image returned by this function must later be
freed.
*/
ca* TEScreen::getCookedImage()
{ int x,y;
ca* merged = (ca*)malloc(lines*columns*sizeof(ca));
ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
{
int len = QMIN(columns,hist.getLineLen(y+histCursor));
int yp = y*columns;
int yq = (y+histCursor)*columns;
hist.getCells(y+histCursor,0,len,merged+yp);
for (x = len; x < columns; x++) merged[yp+x] = dft;
for (x = 0; x < columns; x++)
{ int p=x + yp; int q=x + yq;
if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
reverseRendition(&merged[p]); // for selection
}
}
if (lines >= hist.getLines()-histCursor)
{
for (y = (hist.getLines()-histCursor); y < lines ; y++)
{
int yp = y*columns;
int yq = (y+histCursor)*columns;
int yr = (y-hist.getLines()+histCursor)*columns;
for (x = 0; x < columns; x++)
{ int p = x + yp; int q = x + yq; int r = x + yr;
merged[p] = image[r];
if ( q >= sel_TL && q <= sel_BR )
reverseRendition(&merged[p]); // for selection
}
}
}
// evtl. inverse display
if (getMode(MODE_Screen))
{ int i,n = lines*columns;
for (i = 0; i < n; i++)
reverseRendition(&merged[i]); // for reverse display
}
if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
return merged;
}
/*!
*/
void TEScreen::reset()
{
setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin
resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1]
resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke
setMode(MODE_Cursor); // cursor visible
resetMode(MODE_Screen); // screen not inverse
resetMode(MODE_NewLine);
tmargin=0;
bmargin=lines-1;
setDefaultRendition();
saveCursor();
clear();
}
/*! Clear the entire screen and home the cursor.
*/
void TEScreen::clear()
{
clearEntireScreen();
home();
}
/*! Moves the cursor left one column.
*/
void TEScreen::BackSpace()
{
cuX = QMAX(0,cuX-1);
if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
}
/*!
*/
void TEScreen::Tabulate()
{
// note that TAB is a format effector (does not write ' ');
cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
}
void TEScreen::clearTabStops()
{
for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
}
void TEScreen::changeTabStop(bool set)
{
if (cuX >= columns) return;
tabstops[cuX] = set;
}
void TEScreen::initTabStops()
{
if (tabstops) free(tabstops);
tabstops = (bool*)malloc(columns*sizeof(bool));
// Arrg! The 1st tabstop has to be one longer than the other.
// i.e. the kids start counting from 0 instead of 1.
// Other programs might behave correctly. Be aware.
for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
}
/*!
This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)
depending on the NewLine Mode (LNM). This mode also
affects the key sequence returned for newline ([CR]LF).
*/
void TEScreen::NewLine()
{
if (getMode(MODE_NewLine)) Return();
index();
}
/*! put `c' literally onto the screen at the current cursor position.
VT100 uses the convention to produce an automatic newline (am)
with the *first* character that would fall onto the next line (xenl).
*/
void TEScreen::checkSelection(int from, int to)
{
if (sel_begin == -1) return;
int scr_TL = loc(0, hist.getLines());
//Clear entire selection if it overlaps region [from, to]
if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
{
clearSelection();
}
}
void TEScreen::ShowCharacter(unsigned short c)
{
// Note that VT100 does wrapping BEFORE putting the character.
// This has impact on the assumption of valid cursor positions.
// We indicate the fact that a newline has to be triggered by
// putting the cursor one right to the last column of the screen.
if (cuX >= columns)
{
if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1;
}
if (getMode(MODE_Insert)) insertChars(1);
int i = loc(cuX,cuY);
checkSelection(i, i); // check if selection is still valid.
image[i].c = c;
image[i].f = ef_fg;
image[i].b = ef_bg;
image[i].r = ef_re;
cuX += 1;
}
// Region commands -------------------------------------------------------------
/*! scroll up `n' lines within current region.
The `n' new lines are cleared.
\sa setRegion \sa scrollDown
*/
void TEScreen::scrollUp(int from, int n)
{
if (n <= 0 || from + n > bmargin) return;
//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
}
/*! scroll down `n' lines within current region.
The `n' new lines are cleared.
\sa setRegion \sa scrollUp
*/
void TEScreen::scrollDown(int from, int n)
{
//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
if (n <= 0) return;
if (from > bmargin) return;
if (from + n > bmargin) n = bmargin - from;
moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
}
/*! position the cursor to a specific line and column. */
void TEScreen::setCursorYX(int y, int x)
{
setCursorY(y); setCursorX(x);
}
/*! Set the cursor to x-th line. */
void TEScreen::setCursorX(int x)
{
if (x == 0) x = 1; // Default
x -= 1; // Adjust
cuX = QMAX(0,QMIN(columns-1, x));
}
/*! Set the cursor to y-th line. */
void TEScreen::setCursorY(int y)
{
if (y == 0) y = 1; // Default
y -= 1; // Adjust
cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
}
/*! set cursor to the `left upper' corner of the screen (1,1).
*/
void TEScreen::home()
{
cuX = 0;
cuY = 0;
}
/*! set cursor to the begin of the current line.
*/
void TEScreen::Return()
{
cuX = 0;
}
/*! returns the current cursor columns.
*/
int TEScreen::getCursorX()
{
return cuX;
}
/*! returns the current cursor line.
*/
int TEScreen::getCursorY()
{
return cuY;
}
// Erasing ---------------------------------------------------------------------
/*! \section Erasing
This group of operations erase parts of the screen contents by filling
it with spaces colored due to the current rendition settings.
Althought the cursor position is involved in most of these operations,
it is never modified by them.
*/
/*! fill screen between (including) `loca' and `loce' with spaces.
This is an internal helper functions. The parameter types are internal
addresses of within the screen image and make use of the way how the
screen matrix is mapped to the image vector.
*/
void TEScreen::clearImage(int loca, int loce, char c)
{ int i;
int scr_TL=loc(0,hist.getLines());
//FIXME: check positions
//Clear entire selection if it overlaps region to be moved...
if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
{
clearSelection();
}
for (i = loca; i <= loce; i++)
{
image[i].c = c;
image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different
image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here.
}
}
/*! move image between (including) `loca' and `loce' to 'dst'.
This is an internal helper functions. The parameter types are internal
addresses of within the screen image and make use of the way how the
screen matrix is mapped to the image vector.
*/
void TEScreen::moveImage(int dst, int loca, int loce)
{
//FIXME: check positions
if (loce < loca) {
// kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
return;
}
memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
}
/*! clear from (including) current cursor position to end of screen.
*/
void TEScreen::clearToEndOfScreen()
{
clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
}
/*! clear from begin of screen to (including) current cursor position.
*/
void TEScreen::clearToBeginOfScreen()
{
clearImage(loc(0,0),loc(cuX,cuY),' ');
}
/*! clear the entire screen.
*/
void TEScreen::clearEntireScreen()
{
clearImage(loc(0,0),loc(columns-1,lines-1),' ');
}
/*! fill screen with 'E'
This is to aid screen alignment
*/
void TEScreen::helpAlign()
{
clearImage(loc(0,0),loc(columns-1,lines-1),'E');
}
/*! clear from (including) current cursor position to end of current cursor line.
*/
void TEScreen::clearToEndOfLine()
{
clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
}
/*! clear from begin of current cursor line to (including) current cursor position.
*/
void TEScreen::clearToBeginOfLine()
{
clearImage(loc(0,cuY),loc(cuX,cuY),' ');
}
/*! clears entire current cursor line
*/
void TEScreen::clearEntireLine()
{
clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
}
// Rendition ------------------------------------------------------------------
/*!
set rendition mode
*/
void TEScreen::setRendition(int re)
{
cu_re |= re;
effectiveRendition();
}
/*!
reset rendition mode
*/
void TEScreen::resetRendition(int re)
{
cu_re &= ~re;
effectiveRendition();
}
/*!
*/
void TEScreen::setDefaultRendition()
{
setForeColorToDefault();
setBackColorToDefault();
cu_re = DEFAULT_RENDITION;
effectiveRendition();
}
/*!
*/
void TEScreen::setForeColor(int fgcolor)
{
cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
effectiveRendition();
}
/*!
*/
void TEScreen::setBackColor(int bgcolor)
{
cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
effectiveRendition();
}
/*!
*/
void TEScreen::setBackColorToDefault()
{
cu_bg = DEFAULT_BACK_COLOR;
effectiveRendition();
}
/*!
*/
void TEScreen::setForeColorToDefault()
{
cu_fg = DEFAULT_FORE_COLOR;
effectiveRendition();
}
/* ------------------------------------------------------------------------- */
/* */
/* Marking & Selection */
/* */
/* ------------------------------------------------------------------------- */
void TEScreen::clearSelection()
{
sel_BR = -1;
sel_TL = -1;
sel_begin = -1;
}
void TEScreen::setSelBeginXY(const int x, const int y)
{
sel_begin = loc(x,y+histCursor) ;
sel_BR = sel_begin;
sel_TL = sel_begin;
}
void TEScreen::setSelExtentXY(const int x, const int y)
{
if (sel_begin == -1) return;
int l = loc(x,y + histCursor);
if (l < sel_begin)
{
sel_TL = l;
sel_BR = sel_begin;
}
else
{
/* FIXME, HACK to correct for x too far to the right... */
if (( x == columns )|| (x == 0)) l--;
sel_TL = sel_begin;
sel_BR = l;
}
}
QString TEScreen::getSelText(const BOOL preserve_line_breaks)
{
if (sel_begin == -1)
return QString::null; // Selection got clear while selecting.
int *m; // buffer to fill.
int s, d; // source index, dest. index.
int hist_BR = loc(0, hist.getLines());
int hY = sel_TL / columns;
int hX = sel_TL % columns;
int eol; // end of line
s = sel_TL; // tracks copy in source.
// allocate buffer for maximum
// possible size...
d = (sel_BR - sel_TL) / columns + 1;
m = new int[d * (columns + 1) + 2];
d = 0;
while (s <= sel_BR)
{
if (s < hist_BR)
{ // get lines from hist.history
// buffer.
eol = hist.getLineLen(hY);
if ((hY == (sel_BR / columns)) &&
(eol >= (sel_BR % columns)))
{
eol = sel_BR % columns + 1;
}
while (hX < eol)
{
m[d++] = hist.getCell(hY, hX++).c;
s++;
}
if (s <= sel_BR)
{
// The line break handling
// It's different from the screen
// image case!
if (eol % columns == 0)
{
// That's either a completely filled
// line or an empty line
if (eol == 0)
{
m[d++] = '\n';
}
else
{
// We have a full line.
// FIXME: How can we handle newlines
// at this position?!
}
}
else if ((eol + 1) % columns == 0)
{
// FIXME: We don't know if this was a
// space at the last position or a
// short line!!
m[d++] = ' ';
}
else
{
// We have a short line here. Put a
// newline or a space into the
// buffer.
m[d++] = preserve_line_breaks ? '\n' : ' ';
}
}
hY++;
hX = 0;
s = hY * columns;
}
else
{ // or from screen image.
eol = (s / columns + 1) * columns - 1;
if (eol < sel_BR)
{
while ((eol > s) &&
isspace(image[eol - hist_BR].c))
{
eol--;
}
}
else
{
eol = sel_BR;
}
while (s <= eol)
{
m[d++] = image[s++ - hist_BR].c;
}
if (eol < sel_BR)
{
// eol processing see below ...
if ((eol + 1) % columns == 0)
{
if (image[eol - hist_BR].c == ' ')
{
m[d++] = ' ';
}
}
else
{
m[d++] = ((preserve_line_breaks ||
((eol % columns) == 0)) ?
'\n' : ' ');
}
}
s = (eol / columns + 1) * columns;
}
}
QChar* qc = new QChar[d];
for (int i = 0; i < d; i++)
{
qc[i] = m[i];
}
QString res(qc, d);
- delete m;
- delete qc;
+ delete [] m;
+ delete [] qc;
return res;
}
QString TEScreen::getHistory() {
sel_begin = 0;
sel_BR = sel_begin;
sel_TL = sel_begin;
setSelExtentXY(columns-1,lines-1);
QString tmp=getSelText(true);
while (tmp.at(tmp.length()-2).unicode()==10 && tmp.at(tmp.length()-1).unicode()==10)
tmp.truncate(tmp.length()-1);
return tmp;
}
/* above ... end of line processing for selection -- psilva
cases:
1) (eol+1)%columns == 0 --> the whole line is filled.
If the last char is a space, insert (preserve) space. otherwise
leave the text alone, so that words that are broken by linewrap
are preserved.
FIXME:
* this suppresses \n for command output that is
sized to the exact column width of the screen.
2) eol%columns == 0 --> blank line.
insert a \n unconditionally.
Do it either you would because you are in preserve_line_break mode,
or because it's an ASCII paragraph delimiter, so even when
not preserving line_breaks, you want to preserve paragraph breaks.
3) else --> partially filled line
insert a \n in preserve line break mode, else a space
The space prevents concatenation of the last word of one
line with the first of the next.
*/
void TEScreen::addHistLine()
{
assert(hasScroll() || histCursor == 0);
// add to hist buffer
// we have to take care about scrolling, too...
if (hasScroll())
{ ca dft;
int end = columns-1;
while (end >= 0 && image[end] == dft)
end -= 1;
hist.addCells(image,end+1);
hist.addLine();
// adjust history cursor
histCursor += (hist.getLines()-1 == histCursor);
}
if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
}
void TEScreen::setHistCursor(int cursor)
{
histCursor = cursor; //FIXME:rangecheck
}
int TEScreen::getHistCursor()
{
return histCursor;
}
int TEScreen::getHistLines()
{
return hist.getLines();
}
void TEScreen::setScroll(bool on)
{
histCursor = 0;
clearSelection();
hist.setScroll(on);
}
bool TEScreen::hasScroll()
{
return hist.hasScroll();
}
diff --git a/noncore/apps/opie-sheet/Excel.cpp b/noncore/apps/opie-sheet/Excel.cpp
index 338bc30..51fe707 100644
--- a/noncore/apps/opie-sheet/Excel.cpp
+++ b/noncore/apps/opie-sheet/Excel.cpp
@@ -1,1709 +1,1709 @@
/*
=. This file is part of the Opie Project
.=l. Copyright (C) 2004 Opie Developer Team <opie-devel@handhelds.org>
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "Excel.h"
/* STD */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/types.h>
#include <strings.h>
static xfrecord formatter[] = {
{ 0xe , DATEFORMAT, "%m/%d/%y"},
{ 0xf , DATEFORMAT, "%d-%b-%y"},
{ 0x10, DATEFORMAT, "%d-%b"},
{ 0x11, DATEFORMAT, "%b-%y"},
{ 0x12, DATEFORMAT, "%I:%M %p"},
{ 0x13, DATEFORMAT, "%I:%M:%S %p"},
{ 0x14, DATEFORMAT, "%H:%M"},
{ 0x15, DATEFORMAT, "%H:%M:%S"},
{ 0x16, DATEFORMAT, "%m/%d/%y %H:%M"},
{ 0x2d, DATEFORMAT, "%M:%S"},
{ 0x2e, DATEFORMAT, "%H:%M:%S"},
{ 0x2f, DATEFORMAT, "%M:%S"},
{ 0xa5, DATEFORMAT, "%m/%d/%y %I:%M %p"},
{ 0x1 , NUMBERFORMAT, "%.0f"},
{ 0x2 , NUMBERFORMAT, "%.2f"},
{ 0x3 , NUMBERFORMAT, "#,##%.0f"},
{ 0x4 , NUMBERFORMAT, "#,##%.2f"},
{ 0x5 , NUMBERFORMAT, "$#,##%.0f"},
{ 0x6 , NUMBERFORMAT, "$#,##%.0f"},
{ 0x7 , NUMBERFORMAT, "$#,##%.2f"},
{ 0x8 , NUMBERFORMAT, "$#,##%.2f"},
{ 0x9 , NUMBERFORMAT, "%.0f%%"},
{ 0xa , NUMBERFORMAT, "%.2f%%"},
{ 0xb , NUMBERFORMAT, "%e"},
{ 0x25, NUMBERFORMAT, "#,##%.0f;(#,##0)"},
{ 0x26, NUMBERFORMAT, "#,##%.0f;(#,##0)"},
{ 0x27, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"},
{ 0x28, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"},
{ 0x29, NUMBERFORMAT, "#,##%.0f;(#,##0)"},
{ 0x2a, NUMBERFORMAT, "$#,##%.0f;($#,##0)"},
{ 0x2b, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"},
{ 0x2c, NUMBERFORMAT, "$#,##%.2f;($#,##0.00)"},
{ 0x30, NUMBERFORMAT, "##0.0E0"},
{ 0, 0, ""}
};
int ExcelBook::Integer2Byte(int b1, int b2)
{
int i1 = b1 & 0xff;
int i2 = b2 & 0xff;
int val = i2 << 8 | i1;
return val;
};
int ExcelBook::Integer4Byte(int b1,int b2,int b3,int b4)
{
int i1 = Integer2Byte(b1, b2);
int i2 = Integer2Byte(b3, b4);
int val = i2 << 16 | i1;
return val;
};
int ExcelBook::Integer2ByteFile(FILE *f)
{
int i1, i2;
i1 = fgetc(f);
i2 = fgetc(f);
return Integer2Byte(i1,i2);
};
float ExcelBook::Float4Byte(int b1, int b2, int b3, int b4)
{
int i;
float f;
unsigned char *ieee;
ieee = (unsigned char *) &f;
for (i = 0; i < 4; i++) ieee[i] = 0;
ieee[0] = ((int)b4) & 0xff;
ieee[1] = ((int)b3) & 0xff;
ieee[2] = ((int)b2) & 0xff;
ieee[3] = ((int)b1) & 0xff;
return f;
};
double ExcelBook::Double4Byte(int b1, int b2, int b3, int b4)
{
long int rk;
double value;
rk=Integer4Byte(b1,b2,b3,b4);
//printf("Double4Bytes:%d,%d,%d,%d\r\n",b1,b2,b3,b4);
if ( (rk & 0x02) != 0)
{
long int intval = rk >> 2; //drops the 2 bits
printf("Double4Byte:intval=%d, rk=%d, rk>>2=%d\r\n",intval,rk,rk>>2);
value = (double) intval;
printf("Double4Byte: VALUEINT=%f\r\n",value);
if ( (rk & 0x01) != 0)
{
value /= 100.0;
};
return value;
}
else
{
union { double d; unsigned long int b[2]; } dbl_byte;
unsigned long int valbits = (rk & 0xfffffffc);
#if defined(__arm__) && !defined(__vfp__)
dbl_byte.b[0]=valbits;
dbl_byte.b[1]=0;
#else
dbl_byte.b[0]=0;
dbl_byte.b[1]=valbits;
#endif
printf("dbl_byte.b[0]=%d,dbl_byte.b[1]=%d\r\n",dbl_byte.b[0],dbl_byte.b[1]);
value=dbl_byte.d;
printf("Double4Byte: VALUE=%f\r\n",value);
if ( (rk & 0x01) != 0)
{
value /= 100.0;
};
return value;
};
};
void ExcelBook::DetectEndian(void)
{
int end;
long i = 0x44332211;
unsigned char* a = (unsigned char*) &i;
end = (*a != 0x11);
if (end == 1)
{
endian = BIG_ENDIAN;
printf("BIGENDIAN!\r\n");
}
else
{
endian = LITTLE_ENDIAN;
printf("LITTLEENDIAN!\r\n");
}
};
double ExcelBook::Double8Byte(int b1, int b2, int b3, int b4, int b5, int b6, int b7, int b8)
{
int i;
double d;
unsigned char *ieee;
ieee = (unsigned char *)&d;
for (i = 0; i < 8; i++) ieee[i] = 0;
if (endian == BIG_ENDIAN)
{
ieee[0] = ((int)b8) & 0xff;ieee[1] = ((int)b7) & 0xff;
ieee[2] = ((int)b6) & 0xff;ieee[3] = ((int)b5) & 0xff;
ieee[4] = ((int)b4) & 0xff;ieee[5] = ((int)b3) & 0xff;
ieee[6] = ((int)b2) & 0xff;ieee[7] = ((int)b1) & 0xff;
}
else
{
ieee[0] = ((int)b1) & 0xff;ieee[1] = ((int)b2) & 0xff;
ieee[2] = ((int)b3) & 0xff;ieee[3] = ((int)b4) & 0xff;
ieee[4] = ((int)b5) & 0xff;ieee[5] = ((int)b6) & 0xff;
ieee[6] = ((int)b7) & 0xff;ieee[7] = ((int)b8) & 0xff;
}
return d;
};
bool ExcelBook::OpenFile(char *Filename)
{
printf("Opening excel file!\r\n");
File= fopen(Filename, "r");
Position=0; // first byte index in file
XFRecords.resize(0);
SharedStrings.resize(0);
Names.resize(0);
Sheets.resize(0);
if(File==NULL) return false;
printf("Opened excel file!\r\n");
return true;
};
bool ExcelBook::CloseFile(void)
{
int w1;
for(w1=0;w1<(int)XFRecords.count();w1++)
{
if(XFRecords[w1]!=NULL) {delete XFRecords[w1];XFRecords[w1]=NULL;};
};
for(w1=0;w1<(int)SharedStrings.count();w1++)
{
if(SharedStrings[w1]!=NULL) {delete SharedStrings[w1];SharedStrings[w1]=NULL;};
};
for(w1=0;w1<(int)Names.count();w1++)
{
if(Names[w1]!=NULL) {delete Names[w1];Names[w1]=NULL;};
};
for(w1=0;w1<(int)Sheets.count();w1++)
{
if(Sheets[w1]!=NULL) {delete Sheets[w1];Sheets[w1]=NULL;};
};
XFRecords.resize(0);
SharedStrings.resize(0);
Names.resize(0);
Sheets.resize(0);
fclose(File);
printf("closed excel file!\r\n");
if(File==NULL) return true;
return false;
};
void ExcelBook::SeekPosition(int pos)
{
if(!feof(File))
{
Position=pos;
//printf("SeekPosition:Pos:%d\r\n",Position);
fseek(File,pos,SEEK_SET);
};
};
void ExcelBook::SeekSkip(int pos)
{
if(!feof(File))
{
Position=Position+pos;
//printf("SeekSkip:Pos:%d\r\n",Position);
fseek(File, Position, SEEK_SET);
};
};
int ExcelBook::FileEOF(void)
{
if(File!=NULL) return(feof(File)); else return 0;
//EOF is defined in stdlib as -1
};
int ExcelBook::Get2Bytes(void)
{
int i1,i2;
i1=0; i2=0;
if (!feof(File))
{
i1=fgetc(File);
Position++;
};
if (!feof(File))
{
i2=fgetc(File);
Position++;
};
return Integer2Byte(i1,i2);
};
char* ExcelBook::Read(int pos, int length)
{
int i;
char *data;
data= new char[length];
SeekPosition(pos);
for(i=0; i<length; i++)
{
if(!feof(File)) data[i]=fgetc(File);
};
Position= Position+length;
return data;
};
QString ExcelBook::ReadUnicodeChar(int pos, int length)
{
int i;
QString data;
int i1=' ',i2=' ',ii;
SeekPosition(pos);
for(i=0; i<length; i++)
{
if(!feof(File)) i1=fgetc(File);
if(!feof(File)) i2=fgetc(File);
ii=Integer2Byte(i1,i2);
data.append(ii);
Position+=2;
};
return data;
};
QString* ExcelBook::GetString(int num)
{
if(num>=0 && num<(int)SharedStrings.count())
{
return SharedStrings[num];
};
return new QString("");
};
int ExcelBook::SeekBOF(void)
{
int opcode,version,streamtype,length,ret=0;
char *data;
while(!feof(File))
{
opcode=Get2Bytes();
if(opcode==XL_BOF)
{
length=Get2Bytes();
data=Read(Position,length);
version=Integer2Byte(data[0], data[1]);
streamtype=Integer2Byte(data[2], data[3]);
printf("SEEKBOF:opcode=XLBOF, %d ,version %d\r\n",Position,version);
- delete data; data=NULL;
+ delete [] data; data=NULL;
if (version==BIFF8) ret=8;
else if(version==BIFF7) ret=7;
printf("SEEKBOF:versionBIFF%d\r\n",ret);
if(streamtype==WBKGLOBAL) return ret *2;
else if(streamtype==WRKSHEET) return ret *1;
return 1;
};
};
return 0;
};
ExcelBREC* ExcelBook::GetBREC(void)
{
ExcelBREC* rec;
rec= new ExcelBREC;
if(FileEOF()) return NULL;
rec->data=NULL;
rec->code=Get2Bytes();
rec->length=Get2Bytes();
rec->position=Position;
SeekSkip(rec->length);
return rec;
};
ExcelBREC* ExcelBook::PeekBREC(void)
{
int oldpos;
ExcelBREC* NextRec;
oldpos=Position;
NextRec=GetBREC();
SeekPosition(oldpos);
return NextRec;
};
char* ExcelBook::GetDataOfBREC(ExcelBREC* record)
{
if(record->data==NULL)
{
ConvertCharToArray(record,Read(record->position,record->length),record->length);
};
return record->data;//new?
};
void ExcelBook::ConvertCharToArray(ExcelBREC* record, char* chars, int length)
{
record->data=new char[length];
for(int w1=0;w1<=length-1;w1++)
record->data[w1]=chars[w1];
};
bool ExcelSheet::InitCells()
{
int r;
Cells.resize(rows * cols + cols+1);
if(Cells.count()==0) return false;
for(r=0;r < Cells.count();r++)
{
Cells[r]=NULL;
};
return true;
};
void ExcelSheet::Set(int row, int col, ExcelCell* cell)
{
if(cell!=NULL&&(row*cols+col)<Cells.count())
{
Cells[row*cols+col]=cell;
};
};
ExcelCell* ExcelSheet::Get(int row, int col)
{
ExcelCell* cell;
cell=Cells[row*cols+col];
if(cell==NULL) return NULL;
return cell;
};
int ExcelBook::SheetHandleRecord(ExcelSheet* sheet, ExcelBREC* record)
{
char* data=NULL;
switch (record->code)
{
case XL_DIMENSION:
data = GetDataOfBREC(record);
if (record->length == 10)
{
sheet->rows = Integer2Byte(data[2], data[3]);
sheet->cols = Integer2Byte(data[6], data[7]);
}
else
{
sheet->rows = Integer4Byte(data[4], data[5], data[6], data[7]);
sheet->cols = Integer2Byte(data[10], data[11]);
}
sheet->InitCells();
break;
case XL_LABELSST:
HandleLabelSST(sheet, record);
break;
case XL_RK:
case XL_RK2:
HandleRK(sheet, record);
break;
case XL_MULRK:
HandleMulrk(sheet, record);
break;
case XL_ROW:
break;
case XL_NUMBER:
HandleNumber(sheet, record);
break;
case XL_BOOLERR:
break;
case XL_CONTINUE:
break;
case XL_FORMULA:
case XL_FORMULA2:
HandleFormula(sheet, record);
break;
case XL_LABEL:
break;
case XL_NAME:
HandleName(sheet, record);
break;
case XL_BOF:
break;
case XL_EOF:
return 0;
default:
break;
};
return 1;
};
int ExcelBook::ReadSheet(ExcelSheet* sheet)
{
ExcelBREC* record;
int oldpos;
oldpos = Position;
SeekPosition(sheet->position);
record = GetBREC();
while (record!=NULL)
{
if (!SheetHandleRecord(sheet, record)) break;
record=GetBREC();
};
SeekPosition(oldpos);
return 1;
};
ExcelSheet* ExcelBook::GetSheet(void)
{
ExcelSheet* sh=NULL;
int type;
type=SeekBOF();
Version=type;
sh=new ExcelSheet;
if(type)
{
sh->type=type;
sh->position=Position;
sh->name=QString("");
};
if(type==8||type==7)
{
ReadSheet(sh);
};
return sh;
};
void ExcelBook::ParseSheets(void)
{
int BOFs;
ExcelBREC* r;
BOFs=1;
r=GetBREC();
while(BOFs)
{
r=GetBREC();
switch(r->code)
{
case XL_SST:
HandleSST(r);
break;
case XL_TXO:
break;
case XL_NAME:
break;
case XL_ROW:
break;
case XL_FORMAT:
HandleFormat(r);
break;
case XL_XF:
HandleXF(r);
break;
case XL_BOUNDSHEET:
HandleBoundSheet(r);
break;
case XL_EXTSST:
break;
case XL_CONTINUE:
break;
case XL_EOF:
BOFs--;
break;
default:
break;
};
};
};
void ExcelBook::GetSheets(void)
{
ExcelSheet* sheet;
Sheets.resize(0);
sheet=GetSheet();
while (sheet->Cells.count()!= 0 )
{
Sheets.resize(Sheets.count()+1);
Sheets[Sheets.count()-1]=sheet;
sheet->name=*Names[Sheets.count()-1];
sheet=GetSheet();
};
};
bool ExcelBook::ParseBook(char *file)
{
dateformat=QString("");
DetectEndian();
if ( !OpenFile( file ) )
return false;
SeekBOF();
ParseSheets();
GetSheets();
return true;
};
QString ExcelBook::GetASCII(char* inbytes, int pos, int chars)
{
int i;
QString outstr="";
for (i = 0; i < chars; i++)
{
outstr.append(inbytes[i+pos]);
};
return outstr;
};
QString ExcelBook::GetUnicode(char * inbytes, int pos, int chars)
{
QString outstr="";
int i;
int rc;
for (i=0; i<chars*2; i++)
{
rc=Integer2Byte(inbytes[i+pos],inbytes[i+pos+1]);
outstr.append(QChar(rc));
i++;
};
return outstr;
};
void ExcelBook::HandleBoundSheet(ExcelBREC* rec)
{
char* data;
int type;
int visibility;
int length;
int pos;
QString name;
pos = 8;
data = GetDataOfBREC(rec);
type = data[4];
visibility = data[5];
length = data[6];
if(data[7]==0)
{
//ascii
name=GetASCII(data,pos,length);
}
else
{
name=GetUnicode(data,pos,length);
};
Names.resize(Names.count()+1);
Names[Names.count()-1]=new QString(name);
};
void ExcelBook::HandleName(ExcelSheet* sheet, ExcelBREC* rec)
{
char* data;
QString name;
int length;
int pos;
pos = 15;
data = GetDataOfBREC(rec);
length = data[3];
name = GetASCII(data,pos,length);
};
ExcelFormat* ExcelBook::GetFormatting(int xf)
{
int i;
ExcelFormat* rec;
rec=new ExcelFormat();
for (i = 0; formatter[i].code != 0; i++)
{
if (xf == formatter[i].code) break;
};
if (formatter[i].format ==NULL) return NULL;
rec->code = xf;
rec->type = formatter[i].type;
rec->format = formatter[i].format;
return rec;
};
void ExcelBook::HandleSetOfSST(ExcelBREC* rec/*, SSTList* cont*/, char* bytes)
{
QString str=QString("");
char* data;
int chars, pos, options, i;
int richstring, fareaststring, runlength=0;
int richruns=0,fareastsize=0;
int totalstrings;
int uniquestrings;
data = GetDataOfBREC(rec);
totalstrings = Integer4Byte(data[0], data[1], data[2], data[3]);
uniquestrings = Integer4Byte(data[4], data[5], data[6], data[7]);
pos = 8;
for (i = 0; i < uniquestrings; i++)
{
richruns=0; fareastsize=0;
chars = Integer2Byte(data[pos], data[pos+1]);
pos += 2;
options = data[pos];
pos++;
fareaststring = ((options & 0x04) != 0);
richstring = ((options & 0x08) != 0);
if(richstring)
{
richruns= Integer2Byte(data[pos],data[pos+1]);
pos+=2;
};
if(fareaststring)
{
fareastsize=Integer4Byte(data[pos], data[pos+1], data[pos+2], data[pos+3]);
pos+=4;
};
if ((options & 0x01) == 0) //8 bit chars
{
/* ascii */
str = GetASCII(bytes,pos,chars);
pos=pos+chars;
if(str[0]=='=') str[0]=' ';
}else //16 bit chars
{
/* unicode */
str = GetUnicode(bytes,pos,chars);
pos=pos+chars*2;
};
// HERE TO PUT richformat handling
if (richstring)
{
pos += 4 * richruns;
};
if (fareaststring)
{
pos += fareastsize;
};
//printf("String=%s, length=%d first=0x%x\r\n",str.ascii(),str.length(),str[0].unicode());
SharedStrings.resize(SharedStrings.count()+1);
SharedStrings[SharedStrings.count()-1]=new QString(str);
}
};
char* ExcelBook::MergeBytesFromSSTs(ExcelBREC* rec,SSTList* cont)
{
int i, pos;
int length;
char* data;
char* bytes;
length = rec->length;
for (i = 0; i < (int) cont->rec.count(); i++)
{
length += cont->rec[i]->length;
}
bytes = GetDataOfBREC(rec);
pos = rec->length;
for (i = 0; i < (int) cont->rec.count(); i++)
{
data = GetDataOfBREC(cont->rec[i]);
*bytes += pos;
bytes = data;
pos += cont->rec[i]->length;
}
return bytes;
};
void ExcelBook::HandleSST(ExcelBREC* rec)
{
char* bytes;
SSTList* cont;
cont= new SSTList;
ExcelBREC* nr;
nr = PeekBREC();
while (nr->code == XL_CONTINUE)
{
cont->rec.resize(cont->rec.count()+1);
cont->rec[cont->rec.count()-1]=GetBREC();
nr = PeekBREC();
}
bytes = MergeBytesFromSSTs(rec,cont);
HandleSetOfSST(rec, bytes);
for(int w1=0;w1<(int)cont->rec.count();w1++)
{
if(cont->rec[w1]!=NULL) {delete cont->rec[w1];cont->rec[w1]=NULL;};
};
cont->rec.resize(0);
};
void ExcelBook::HandleLabelSST(ExcelSheet* sheet, ExcelBREC* rec)
{
int index, row, col;
char* data;
data = GetDataOfBREC(rec);
index = Integer4Byte(data[6], data[7], data[8], data[9]);
row = Integer2Byte(data[0], data[1]);
col = Integer2Byte(data[2], data[3]);
sheet->Set(row,col, CellLabel(row, col, *GetString(index)));
};
ExcelCell* ExcelBook::CellLabel(int row, int col, QString str)
{
ExcelCell* c;
c= new ExcelCell;
c->row = row;
c->col = col;
c->type = CELL_LABEL;
c->valuec = str;
return c;
};
ExcelCell* ExcelBook::CellNumber(int row, int col, int index, double d)
{
ExcelCell* c;
c=new ExcelCell;
c->row = row;
c->col = col;
c->xfindex = index;
c->type = CELL_NUMBER;
c->valued = d;
return c;
};
QString* ExcelBook::CellDataString(ExcelSheet* sh, int row, int col)
{
time_t date;
struct tm *tmptr;
ExcelCell* c;
char str[128];
QString format;
int precision;
int utcOffsetDays = 25569;
int sInADay = 24 * 60 * 60;
c = sh->Get(row,col);
if (c == NULL) return new QString("");
switch (c->type)
{
case CELL_LABEL:
return new QString(c->valuec);
case CELL_NUMBER:
if (XFRecords[c->xfindex]->type == DATEFORMAT)
{
format = XFRecords[c->xfindex]->format;
date = (time_t) ((c->valued - utcOffsetDays) * sInADay);
tmptr = gmtime(&date);
if (dateformat)
{
strftime(str,1024,dateformat.ascii(),tmptr);
}
else
{
strftime(str,1024,format.ascii(),tmptr);
};
}
else
if (XFRecords[c->xfindex]->type == NUMBERFORMAT)
{
format = XFRecords[c->xfindex]->format;
//sprintf(str,format.ascii(),c->valued);
// the real format is ignored...
// because there is more work to be done in the field
precision = CellGetPrecision(c->valued);
sprintf(str,"%.*f",precision,c->valued);
}
else
{
precision = CellGetPrecision(c->valued);
sprintf(str,"%.*f",precision,c->valued);
};
break;
case CELL_DATE:
break;
case CELL_BOOLEAN:
break;
case CELL_ERROR:
break;
}
return new QString(str);
};
int ExcelBook::CellGetPrecision(double d)
{
double t;
int i,x;
int count;
if (d < 0) d *= -1;
i = (int)d;
t = d - (double)i;
if (t <= 0)
{
return 0;
};
count = 0;
for (x = 6; x > 1; x--)
{
i = (int)d;
t = d - (double)i;
t *= pow(10,x - 2);
i = (int)t;
t = t - (double)i;
t *= 10;
i = (int)t;
if (i > 0) break;
count++;
};
return (5 - count);
};
void ExcelBook::CellSetDateFormat(char *d)
{
dateformat = QString(d);
};
void ExcelBook::HandleMulrk(ExcelSheet* sheet, ExcelBREC* record)
{
struct mulrk mulrk;
char* data;
ExcelCell* cell;
int len;
int i;
len = record->length;
data = GetDataOfBREC(record);
mulrk.row = Integer2Byte(data[0],data[1]);
mulrk.first = Integer2Byte(data[2],data[3]);
mulrk.last = Integer2Byte(data[len - 2],data[len - 1]);
mulrk.numrks = mulrk.last - mulrk.first + 1;
MulrkRead(&mulrk, data);
for (i = 0; i < mulrk.numrks; i++)
{
cell = CellNumber(mulrk.row, mulrk.first + i, mulrk.xfindices[i], mulrk.rkdbls[i]);
sheet->Set(mulrk.row,mulrk.first+ i, cell);
//printf("handleMULRK:row=%d,col=%d,val=%f\r\n",mulrk.row,mulrk.first+i,mulrk.rkdbls[i]);
}
//delete(mulrk.xfindices);
//delete(mulrk.rkdbls);
};
void ExcelBook::MulrkRead(struct mulrk *mulrk, char* data)
{
double d;
int i;
int pos;
pos = 4;
mulrk->xfindices.resize(mulrk->numrks);
mulrk->rkdbls.resize(mulrk->numrks);
for (i = 0; i < mulrk->numrks; i++)
{
mulrk->xfindices[i] = Integer2Byte(data[pos], data[pos+1]);
d=Double4Byte(data[pos+2], data[pos+3], data[pos+4], data[pos+5]);
//printf("double:%f\r\n",d);
mulrk->rkdbls[i] = d;
pos += 6;
}
};
void ExcelBook::HandleNumber(ExcelSheet* sheet, ExcelBREC* record)
{
int xfindex, row, col;
char* data;
double d;
data = GetDataOfBREC(record);
row = Integer2Byte(data[0], data[1]);
col = Integer2Byte(data[2], data[3]);
xfindex = Integer2Byte(data[4], data[5]);
#if defined(__arm__) && !defined(__vfp__)
d=Double8Byte(data[10], data[11], data[12], data[13],data[6], data[7], data[8], data[9]);
#else
d=Double8Byte(data[6], data[7], data[8], data[9],data[10], data[11], data[12], data[13]);
#endif
//even if ARM is little endian... doubles are been placed as bigendian words.
//thanks pb_ for that. :)
sheet->Set(row,col, CellNumber(row,col,xfindex,d));
//printf("handleNumber:row=%d,col=%d,val=%f\r\n",row,col,d);
};
ExcelFormat::ExcelFormat()
{
code=0;type=0;format="";
};
ExcelFormat::ExcelFormat(int c,int t, QString s)
{
code=c;type=t;format=s;
};
void ExcelBook::HandleFormat(ExcelBREC* rec)
{
ExcelFormat* xfrec;
char* data;
int format;
data = GetDataOfBREC(rec);
format = Integer2Byte(data[2],data[3]);
xfrec = GetFormatting(format);
/*int idx;
idx=XFRecords.count()-1;
XFRecords[idx]->code=xfrec->code;
XFRecords[idx]->type=xfrec->type;
XFRecords[idx]->format="manos";
//XFRecords[XFRecords.count()-1]=xfrec;
printf("6\r\n");*/
};
void ExcelBook::HandleXF(ExcelBREC* rec)
{
ExcelFormat* xfrec;
char* data;
int format;
data = GetDataOfBREC(rec);
format = Integer2Byte(data[2],data[3]);
xfrec = GetFormatting(format);
XFRecords.resize(XFRecords.count()+1);
XFRecords[XFRecords.count()-1]=xfrec;
};
void ExcelBook::HandleRK(ExcelSheet* sheet, ExcelBREC* record)
{
int xfindex, row, col;
char* data;
double d;
data = GetDataOfBREC(record);
row = Integer2Byte(data[0], data[1]);
col = Integer2Byte(data[2], data[3]);
xfindex = Integer2Byte(data[4], data[5]);
d=Double4Byte(data[6], data[7], data[8], data[9]);
sheet->Set(row,col,CellNumber(row,col,xfindex,d));
//printf("handleRK:row=%d,col=%d,val=%f\r\n",row,col,d);
};
void ExcelBook::HandleFormula(ExcelSheet* sheet, ExcelBREC* record)
{
int xfindex, row, col;
char* data;
double d;
data = GetDataOfBREC(record);
row = Integer2Byte(data[0], data[1]);
col = Integer2Byte(data[2], data[3]);
if (data[6] == 0 && data[12] == -1 && data[13] == -1)
{
// string
}
else
if (data[6] == 1 && data[12] == -1 && data[13] == -1)
{
// boolean
}
else
if ( data[6] == 2 && data[12] == -1 && data[13] == -1)
{
// error
}
else
{
// number
xfindex = Integer2Byte(data[4], data[5]);
d=Double8Byte(data[6], data[7], data[8], data[9],data[10], data[11], data[12], data[13]);
QString s1;
int sz;
sz=Integer2Byte(data[20],data[21]);// size of the formula
char* formuladata;
formuladata=new char[sz];
for(int w1=0;w1<sz;w1++)
{
formuladata[w1]=data[22+w1];
};
//22 is the first 0 idx of formula data
s1="="+GetFormula(row,col,sheet,formuladata,sz);
//printf("GetFormula:Formula=%s\r\n",s1.ascii());
sheet->Set(row,col,CellLabel(row,col,s1));
}
};
QString ExcelBook::GetFormula(int row, int col, ExcelSheet* sheet, char* data, int sz)
{
int length=sz;
printf("{FormulaParser}\r\n");
printf("row=%d, col=%d, length=%d\r\n",row,col,length);
int idx=0;
int w1,w2,w3,w4;
double d1;
int token;
QString s1;
QList <QString> operands;
operands.setAutoDelete(TRUE);
QString formula;
operands.clear();
while( idx<length )
{
token= data[idx]; idx++;
switch(token)
{
case 0x1E: //prtInt
w1=Integer2Byte(data[idx],data[idx+1]);
idx=idx+2;
operands.prepend(new QString(QString::number(w1)));
printf(" token:ptgInt,num=%d\r\n",w1);
break;
case 0x1F: //ptgNumber
#if defined(__arm__) && !defined(__vfp__)
d1=Double8Byte(data[idx+4],data[idx+5],data[idx+6],data[idx+7]
,data[idx],data[idx+1],data[idx+2],data[idx+3]);
#else
d1=Double8Byte(data[idx],data[idx+1],data[idx+2],data[idx+3]
,data[idx+4],data[idx+5],data[idx+6],data[idx+7]);
#endif
idx=idx+8;
operands.prepend(new QString(QString::number(d1)));
printf(" token:ptgNumber,num=%f\r\n",d1);
break;
case 0x17: //ptgStr
if(Version==8)
{
//unicode string
//w1=Integer2Byte(data[idx],data[idx+1]);idx+=2;
w1=data[idx];idx++;
printf("len=%d\r\n",w1);
int richruns=0; int fareastsize=0;
int richstring,fareaststring;
int options = data[idx];idx++;
fareaststring = ((options & 0x04) != 0);
richstring = ((options & 0x08) != 0);
if(richstring)
{
//containts rich string formatting.
printf("STRING:richstring\r\n");
richruns= Integer2Byte(data[idx],data[idx+1]);
printf("richruns:%d\r\n",richruns);
idx+=2;
};
if(fareaststring)
{
//contains far east formatting
printf("STRING:fareast!\r\n");
fareastsize=Integer4Byte(data[idx], data[idx+1],
data[idx+2], data[idx+3]);
printf("fareastsize=%d",fareastsize);
idx+=4;
};
if ((options & 0x01) == 0) //8 bit chars
{
/* ascii */
s1 = GetASCII(data,idx,w1);
idx=idx+w1;
printf("STRING:ASCII=%s\r\n",s1.ascii());
}else //16 bit chars
{
/* unicode */
s1 = GetUnicode(data,idx,w1);
idx=idx+w1*2;
printf("STRING:unicode=%s\r\n",s1.ascii());
};
// HERE TO PUT richformat handling
if (richstring)
{
idx += 4 * richruns;
};
if (fareaststring)
{
idx += fareastsize;
};
s1=QString("""")+s1+QString("""");
operands.prepend(new QString(s1));
}
else
{
w1=data[idx];idx++;
s1=GetASCII(data,idx,w1);
s1=QString("""")+s1+QString("""");
idx=idx+w1;
operands.prepend(new QString(s1));
};
printf(" token:ptgStr,num=%d\r\n",w1);
break;
case 0x25:
case 0x45:
case 0x65: // ptgArea
if(Version==8)
{
w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row1
w2=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row2
w3=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col1
w4=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col2
}
else
{
w1=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row1
w2=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row2
w3=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col1
w4=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col2
};
//ignores relative or absolute refs
s1=FindCellName(w1,w3)+":"+FindCellName(w2,w4);
printf(" token:ptgArea,ref=%s\r\n",s1.ascii());
operands.prepend(new QString(s1));
break;
case 0x24:
case 0x44:
case 0x64://ptgRef
if(Version==8)
{
w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row
w2=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col
}
else
{
w1=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row
w2=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col
};
s1=FindCellName(w1,w2);
printf("token:ptgRef,ref=%s\r\n",s1.ascii());
operands.prepend(new QString(s1));
break;
case 0x1D: // ptgBool
w1=data[idx];idx++;
printf("token:ptgBool,val=%d\r\n",w1);
operands.prepend(new QString(QString::number(w1)));
break;
case 0x16://ptg MissArg
printf("token:ptgMissArg, val=' '\r\n");
operands.prepend(new QString("0"));
break;
case 0x12://ptgUplus==
printf("token:ptgUplus\r\n");
s1=QString("+")+operands.first()->ascii();
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x13://ptgUminus
printf("token:ptgUminus\r\n");
s1=QString("-")+operands.first()->ascii();
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x03://ptgAdd
printf("token:ptgAdd\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("+")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x04://ptgSub
printf("token:ptgSub\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("-")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x05://ptgMul
printf("token:ptgMul\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("*")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x06://ptgDiv
printf("token:ptgDiv\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("/")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x07://ptgPOWER
printf("token:ptgPow\r\n");
operands.first();
s1=QString("POWER(")+operands.next()->ascii()
+QString(",")+operands.first()->ascii()+QString(")");
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x08://ptgConcat
printf("token:ptgConcat\r\n");
operands.first();
s1=QString("CONCATENATE(")+operands.next()->ascii()
+QString(",")+operands.first()->ascii()+QString(")");
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x15://ptgParenthesis
printf("token:ptgParenthesis\r\n");
s1=QString("(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x14://ptgPercent
printf("token:ptgPercent\r\n");
s1=operands.first()->ascii()+QString("*0.01");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x9://ptgLessThan
printf("token:ptgLESS\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("<")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xa://ptgLessEqual
printf("token:ptgLESS_EQUAL\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("<=")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xb://ptgEQUAL
printf("token:ptgEQUAL\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("==")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xc://ptgGREATER_EQUAL
printf("token:ptgGREAT_EQUAL\r\n");
operands.first();
s1=operands.next()->ascii()
+QString(">=")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xd://ptgGREAT_THAN
printf("token:ptgGREAT_THAN\r\n");
operands.first();
s1=operands.next()->ascii()
+QString(">")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xe://ptgNOT_EQUAL
printf("token:ptgNOTequal\r\n");
operands.first();
s1=operands.next()->ascii()
+QString("!=")+operands.first()->ascii();
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x19://attribute can be Sum,If,Choose
w3=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;
idx++;
printf("token:ATTRIBUTE:0x%x\r\n",w3);
for(w4=idx;w4<length;w4++)
printf("0x%x, ",data[w4]);
if(w3&0x01)//choose
{
printf("token:CHOOSE\r\n");
}
else if(w3&0x02)//if
{
printf("token:IF\r\n");
}
else if(w3&0x10)//sum
{
printf("token:SUM\r\n");
};
break;
case 0x21:
case 0x22:
case 0x42:
case 0x62:
case 0x41:
case 0x61://ptgFunction
printf("token:ptgFunction\r\n");
if(token==0x22||token==0x42||token==0x62)
{
w2=(int)data[idx];idx++;
w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;
}
else
{
w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;
};
switch(w1)
{
case 0xf://SIN
s1=QString("SIN(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x10://COS
s1=QString("COS(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x11://tan
s1=QString("TAN(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x62://asin
s1=QString("ASIN(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x63://ACOS
s1=QString("ACOS(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x12://ATAN
s1=QString("ATAN(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xe5://SINH
s1=QString("SINH(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xe6://COSH
s1=QString("COSH(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xe7://TANH
s1=QString("TANH(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xe8://ASINH
s1=QString("ASINH(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xe9://ACOSH
s1=QString("ACOSH(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xea://ATANH
s1=QString("ATANH(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x13://pi
s1="PI()";
operands.prepend(new QString(s1));
break;
case 0x14://sqrt
s1=QString("SQRT(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x15://exp
s1=QString("EXP(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x16://LN
s1=QString("LN(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x17://LOG10
s1=QString("LOG10(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x18://ABS
s1=QString("ABS(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x19://int
s1=QString("INT(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x1a://sign
s1=QString("SIGN(")+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x1b://round
operands.first();
s1=QString("ROUND(")+operands.next()->ascii()
+QString(",")+operands.first()->ascii()
+QString(")");
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x1d://index
operands.first();
s1=QString("INDEX(")+operands.next()->ascii()
+QString(",")
+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x1: // if ATTRIBUTE
operands.first();operands.next();
s1=QString("IF(")+operands.next()->ascii()+QString(",");
operands.first();
s1=s1+operands.next()->ascii()+QString(",");
s1=s1+operands.first()->ascii()+QString(")");
operands.removeFirst();
operands.removeFirst();
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x81://isblank
s1=QString("ISBLANK(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x80://isnumber
s1=QString("ISNUMBER(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x120://ceiling
operands.first();
s1=QString("CEILING(")+operands.next()->ascii()
+QString(",")+operands.first()->ascii()
+QString(")");
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x11d://floor
operands.first();
s1=QString("FLOOR(")+operands.next()->ascii()
+QString(",")+operands.first()->ascii()
+QString(")");
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x157://degrees
s1=QString("DEGREES(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x156://radians
s1=QString("RADIANS(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xb8://fact
s1=QString("FACT(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x27://MOD
operands.first();
s1=QString("MOD(")+operands.next()->ascii()
+QString(",")+operands.first()->ascii()
+QString(")");
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x151://power
operands.first();
s1=QString("POWER(")+operands.next()->ascii()
+QString(",")+operands.first()->ascii()
+QString(")");
operands.removeFirst();operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x3f://rand()
s1="RAND()";
operands.prepend(new QString(s1));
break;
case 0x4://sum
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("SUM(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x6://min
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("MIN(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x7://max
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("MAX(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x5://average
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("AVERAGE(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x2e://var
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("VAR(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xc2://varp
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("VARP(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xc://stdev
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("STDEV(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0xc1://stdevp
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("STDEVP(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x143://skew
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("SKEW(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x142://kurt
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("KURT(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
case 0x0://count
for(w4=1;w4<w2;w4++) operands.removeFirst();
s1=QString("COUNT(")+operands.first()->ascii()
+QString(")");
operands.removeFirst();
operands.prepend(new QString(s1));
break;
default:
printf("token:FUNCTION_UNKNOWN=0x%x\r\n",w1);
return QString("FUNC_UNKNOWN");
break;
};
break;
default:
printf("tokenUNKNOWN=0x%x\r\n",token);
return QString("TOKEN_UKNOWN");
//it is dangerous to go to idx++ and not return
// because the result is unexpected.
// but there is a possibility the the parser will give the correct
// answer, because there are some tokens in excel formulas that can be //ignored.
idx++;
break;
};
};
printf("{////FormulaParser}\r\n");
printf("GetFormula:::::::r=%d,c=%d,,,%s\r\n",row,col,s1.ascii());
printf("\r\n");
s1=operands.first()->ascii();
operands.clear();
return QString(s1);
};
QString ExcelBook::FindCellName(int row, int col)
{
row++;col++;
QString s1="";
int i1=col % 26;
int i2=col / 26;
if (i2!=0) s1=(char)(i2+65); //65 =A
s1=s1+(char)(i1+65-1);
return (s1+QString::number(row));
};
diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp
index 6dc4fd2..a70f3aa 100644
--- a/noncore/apps/tinykate/libkate/document/katedocument.cpp
+++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp
@@ -1,3175 +1,3175 @@
/***************************************************************************
katedocument.cpp - description
-------------------
begin : Mon Jan 15 2001
copyright : (C) 2001 by Christoph "Crossfire" Cullmann
(C) 2002 by Joseph Wenninger
email : crossfire@babylon2k.de
jowenn@kde.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/*
Copyright (C) 1998, 1999 Jochen Wilhelmy
digisnap@cs.tu-berlin.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "katedocument.h"
#include "kmessagebox.h"
#include "kglobal.h"
//#include "kcharsets.h"
#include "kdebug.h"
//#include "kinstance.h"
#include "kglobalsettings.h"
//#include "kaction.h"
//#include "kstdaction.h"
#include "../view/kateview.h"
#include "katebuffer.h"
#include "katetextline.h"
#include "katecmd.h"
/* OPIE */
#include <opie2/odebug.h>
#include <qpe/config.h>
/* QT */
#include <qfileinfo.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qtimer.h>
#include <qobject.h>
#include <qapplication.h>
#include <qclipboard.h>
#include <qfont.h>
#include <qpainter.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qtextcodec.h>
/* STD */
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
KateAction::KateAction(Action a, PointStruc &cursor, int len, const QString &text)
: action(a), cursor(cursor), len(len), text(text) {
}
KateActionGroup::KateActionGroup(PointStruc &aStart, int type)
: start(aStart), action(0L), undoType(type) {
}
KateActionGroup::~KateActionGroup() {
KateAction *current, *next;
current = action;
while (current) {
next = current->next;
delete current;
current = next;
}
}
void KateActionGroup::insertAction(KateAction *a) {
a->next = action;
action = a;
}
const char * KateActionGroup::typeName(int type)
{
// return a short text description of the given undo group type suitable for a menu
// not the lack of i18n's, the caller is expected to handle translation
switch (type) {
case ugPaste : return "Paste Text";
case ugDelBlock : return "Selection Overwrite";
case ugIndent : return "Indent";
case ugUnindent : return "Unindent";
case ugComment : return "Comment";
case ugUncomment : return "Uncomment";
case ugReplace : return "Text Replace";
case ugSpell : return "Spell Check";
case ugInsChar : return "Typing";
case ugDelChar : return "Delete Text";
case ugInsLine : return "New Line";
case ugDelLine : return "Delete Line";
}
return "";
}
const int KateDocument::maxAttribs = 32;
QStringList KateDocument::searchForList = QStringList();
QStringList KateDocument::replaceWithList = QStringList();
uint KateDocument::uniqueID = 0;
QPtrDict<KateDocument::KateDocPrivate>* KateDocument::d_ptr = 0;
KateDocument::KateDocument(bool bSingleViewMode, bool bBrowserView,
QWidget *parentWidget, const char *widgetName,
QObject *, const char *)
: Kate::Document (),
myFont(KGlobalSettings::generalFont()), myFontBold(KGlobalSettings::generalFont()), myFontItalic(KGlobalSettings::generalFont()), myFontBI(KGlobalSettings::generalFont()),
myFontMetrics (myFont), myFontMetricsBold (myFontBold), myFontMetricsItalic (myFontItalic), myFontMetricsBI (myFontBI),
hlManager(HlManager::self ())
{
d(this)->hlSetByUser = false;
PreHighlightedTill=0;
RequestPreHighlightTill=0;
m_bSingleViewMode=bSingleViewMode;
m_bBrowserView = bBrowserView;
m_url = QString::null;
// NOTE: QFont::CharSet doesn't provide all the charsets KDE supports
// (esp. it doesn't distinguish between UTF-8 and iso10646-1)
myEncoding = QString::fromLatin1(QTextCodec::codecForLocale()->name());
maxLength = -1;
setFont (KGlobalSettings::generalFont());
myDocID = uniqueID;
uniqueID++;
myDocName = QString ("");
fileInfo = new QFileInfo ();
myCmd = new KateCmd (this);
connect(this,SIGNAL(modifiedChanged()),this,SLOT(slotModChanged()));
buffer = new KWBuffer;
connect(buffer, SIGNAL(linesChanged(int)), this, SLOT(slotBufferChanged()));
// connect(buffer, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
connect(buffer, SIGNAL(needHighlight(long,long)),this,SLOT(slotBufferHighlight(long,long)));
colors[0] = KGlobalSettings::baseColor();
colors[1] = KGlobalSettings::highlightColor();
m_attribs = new Attribute[maxAttribs];
m_highlight = 0L;
tabChars = 8;
m_singleSelection = false;
newDocGeometry = false;
readOnly = false;
newDoc = false;
modified = false;
undoList.setAutoDelete(true);
undoState = 0;
undoSteps = 50;
pseudoModal = 0L;
clear();
setHighlight(0); //calls updateFontData()
// if the user changes the highlight with the dialog, notify the doc
connect(hlManager,SIGNAL(changed()),SLOT(hlChanged()));
newDocGeometry = false;
readConfig();
setReadOnly(false);
}
void KateDocument::setDontChangeHlOnSave()
{
d(this)->hlSetByUser = true;
}
void KateDocument::setFont (QFont font)
{
kdDebug()<<"Kate:: setFont"<<endl;
int oldwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
myFont = font;
myFontBold = QFont (font);
myFontBold.setBold (true);
myFontItalic = QFont (font);
myFontItalic.setItalic (true);
myFontBI = QFont (font);
myFontBI.setBold (true);
myFontBI.setItalic (true);
myFontMetrics = CachedFontMetrics (myFont);
myFontMetricsBold = CachedFontMetrics (myFontBold);
myFontMetricsItalic = CachedFontMetrics (myFontItalic);
myFontMetricsBI = CachedFontMetrics (myFontBI);
int newwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
maxLength=maxLength*(float)newwidth/(float)oldwidth; //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
updateFontData();
updateViews(); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
}
long KateDocument::needPreHighlight(long till)
{
int max=numLines()-1;
if (till>max)
{
till=max;
}
if (PreHighlightedTill>=till) return -1;
long tmp=RequestPreHighlightTill;
if (RequestPreHighlightTill<till)
{
RequestPreHighlightTill=till;
if (tmp<=PreHighlightedTill) QTimer::singleShot(10,this,SLOT(doPreHighlight()));
}
return RequestPreHighlightTill;
}
void KateDocument::doPreHighlight()
{
int from = PreHighlightedTill;
int till = PreHighlightedTill+200;
int max = numLines()-1;
if (till > max)
{
till = max;
}
PreHighlightedTill = till;
updateLines(from,till);
emit preHighlightChanged(PreHighlightedTill);
if (PreHighlightedTill<RequestPreHighlightTill)
QTimer::singleShot(10,this,SLOT(doPreHighlight()));
}
KateDocument::~KateDocument()
{
m_highlight->release();
writeConfig();
if ( !m_bSingleViewMode )
{
m_views.setAutoDelete( true );
m_views.clear();
m_views.setAutoDelete( false );
}
delete_d(this);
}
void KateDocument::openURL(const QString &filename)
{
m_file=filename;
fileInfo->setFile (m_file);
setMTime();
if (!fileInfo->exists() || !fileInfo->isReadable())
{
odebug << "File doesn't exit or couldn't be read" << oendl;
return ;
}
buffer->clear();
#warning fixme
// buffer->insertFile(0, m_file, KGlobal::charsets()->codecForName(myEncoding));
odebug << "Telling buffer to open file" << oendl;
buffer->insertFile(0, m_file, QTextCodec::codecForLocale());
setMTime();
if (myWordWrap)
wrapText (myWordWrapAt);
int hl = hlManager->wildcardFind( m_file );
setHighlight(hl);
updateLines();
updateViews();
emit fileNameChanged();
return ;
}
bool KateDocument::saveFile()
{
QFile f( m_file );
if ( !f.open( IO_WriteOnly ) )
return false; // Error
QTextStream stream(&f);
stream.setEncoding(QTextStream::RawUnicode); // disable Unicode headers
#warning fixme
// stream.setCodec(KGlobal::charsets()->codecForName(myEncoding));
stream.setCodec(QTextCodec::codecForLocale()); // this line sets the mapper to the correct codec
int maxLine = numLines();
int line = 0;
while(true)
{
stream << getTextLine(line)->getString();
line++;
if (line >= maxLine) break;
if (eolMode == KateDocument::eolUnix) stream << "\n";
else if (eolMode == KateDocument::eolDos) stream << "\r\n";
else if (eolMode == KateDocument::eolMacintosh) stream << '\r';
};
f.close();
fileInfo->setFile (m_file);
setMTime();
if (!(d(this)->hlSetByUser))
{
int hl = hlManager->wildcardFind( m_file );
setHighlight(hl);
}
emit fileNameChanged ();
return (f.status() == IO_Ok);
}
KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name )
{
return new KateView( this, parent, name);
}
QString KateDocument::textLine( int line ) const
{
TextLine::Ptr l = getTextLine( line );
if ( !l )
return QString();
return l->getString();
}
void KateDocument::replaceLine(const QString& s,int line)
{
remove_Line(line,false);
insert_Line(s,line,true);
}
void KateDocument::insertLine( const QString &str, int l ) {
insert_Line(str,l,true);
}
void KateDocument::insert_Line(const QString& s,int line, bool update)
{
kdDebug(13020)<<"KateDocument::insertLine "<<s<<QString(" %1").arg(line)<<endl;
TextLine::Ptr TL=new TextLine();
TL->append(s.unicode(),s.length());
buffer->insertLine(line,TL);
if (update)
{
newDocGeometry=true;
updateLines(line);
updateViews();
}
}
void KateDocument::insertAt( const QString &s, int line, int col, bool )
{
VConfig c;
c.view = 0; // ### FIXME
c.cursor.x = col;
c.cursor.y = line;
c.cXPos = 0; // ### FIXME
c.flags = 0; // ### FIXME
insert( c, s );
}
void KateDocument::removeLine( int line ) {
remove_Line(line,true);
}
void KateDocument::remove_Line(int line,bool update)
{
kdDebug(13020)<<"KateDocument::removeLine "<<QString("%1").arg(line)<<endl;
buffer->removeLine(line);
// newDocGeometry=true;
// if line==0)
if (update)
{
updateLines(line);
updateViews();
}
}
int KateDocument::length() const
{
return text().length();
}
void KateDocument::setSelection( int , int , int , int )
{
}
bool KateDocument::hasSelection() const
{
return (selectEnd >= selectStart);
}
QString KateDocument::selection() const
{
uint flags = 0;
TextLine::Ptr textLine;
int len, z, start, end, i;
len = 1;
if (!(flags & KateView::cfVerticalSelect)) {
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
len += textLine->numSelected();
if (textLine->isSelected()) len++;
}
QString s;
len = 0;
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
end = 0;
do {
start = textLine->findUnselected(end);
end = textLine->findSelected(start);
for (i = start; i < end; i++) {
s[len] = textLine->getChar(i);
len++;
}
} while (start < end);
if (textLine->isSelected()) {
s[len] = '\n';
len++;
}
}
// s[len] = '\0';
return s;
} else {
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
len += textLine->numSelected() + 1;
}
QString s;
len = 0;
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
end = 0;
do {
start = textLine->findUnselected(end);
end = textLine->findSelected(start);
for (i = start; i < end; i++) {
s[len] = textLine->getChar(i);
len++;
}
} while (start < end);
s[len] = '\n';
len++;
}
// s[len] = '\0'; // the final \0 is not counted in length()
return s;
}
}
int KateDocument::numLines() const
{
return buffer->count();
}
TextLine::Ptr KateDocument::getTextLine(int line) const
{
// This is a hack to get this stuff working.
return buffer->line(line);
}
int KateDocument::textLength(int line) {
TextLine::Ptr textLine = getTextLine(line);
if (!textLine) return 0;
return textLine->length();
}
void KateDocument::setTabWidth(int chars) {
if (tabChars == chars) return;
if (chars < 1) chars = 1;
if (chars > 16) chars = 16;
tabChars = chars;
updateFontData();
maxLength = -1;
for (int i=0; i < buffer->count(); i++)
{
TextLine::Ptr textLine = buffer->line(i);
int len = textWidth(textLine,textLine->length());
if (len > maxLength) {
maxLength = len;
longestLine = textLine;
}
}
}
void KateDocument::setReadOnly(bool m) {
KTextEditor::View *view;
if (m != readOnly) {
readOnly = m;
// if (readOnly) recordReset();
for (view = m_views.first(); view != 0L; view = m_views.next() ) {
emit static_cast<KateView *>( view )->newStatus();
}
}
}
bool KateDocument::isReadOnly() const {
return readOnly;
}
void KateDocument::setNewDoc( bool m )
{
// KTextEditor::View *view;
if ( m != newDoc )
{
newDoc = m;
//// if (readOnly) recordReset();
// for (view = m_views.first(); view != 0L; view = m_views.next() ) {
// emit static_cast<KateView *>( view )->newStatus();
// }
}
}
bool KateDocument::isNewDoc() const {
return newDoc;
}
void KateDocument::setModified(bool m) {
KTextEditor::View *view;
if (m != modified) {
modified = m;
for (view = m_views.first(); view != 0L; view = m_views.next() ) {
emit static_cast<KateView *>( view )->newStatus();
}
emit modifiedChanged ();
}
}
bool KateDocument::isModified() const {
return modified;
}
void KateDocument::readConfig()
{
KateConfig *config = KGlobal::config();
config->setGroup("Kate Document");
myWordWrap = config->readBoolEntry("Word Wrap On", false);
myWordWrapAt = config->readNumEntry("Word Wrap At", 80);
if (myWordWrap)
wrapText (myWordWrapAt);
setTabWidth(config->readNumEntry("TabWidth", 8));
setUndoSteps(config->readNumEntry("UndoSteps", 50));
m_singleSelection = config->readBoolEntry("SingleSelection", false);
myEncoding = config->readEntry("Encoding", QString::fromLatin1(QTextCodec::codecForLocale()->name()));
setFont (config->readFontEntry("Font", myFont));
colors[0] = config->readColorEntry("Color Background", colors[0]);
colors[1] = config->readColorEntry("Color Selected", colors[1]);
// config->sync();
}
void KateDocument::writeConfig()
{
KateConfig *config = KGlobal::config();
config->setGroup("Kate Document");
config->writeEntry("Word Wrap On", myWordWrap);
config->writeEntry("Word Wrap At", myWordWrapAt);
config->writeEntry("TabWidth", tabChars);
config->writeEntry("UndoSteps", undoSteps);
config->writeEntry("SingleSelection", m_singleSelection);
config->writeEntry("Encoding", myEncoding);
config->writeEntry("Font", myFont);
config->writeEntry("Color Background", colors[0]);
config->writeEntry("Color Selected", colors[1]);
// config->sync();
}
void KateDocument::readSessionConfig(KateConfig *config)
{
m_url = config->readEntry("URL"); // ### doesn't this break the encoding? (Simon)
setHighlight(hlManager->nameFind(config->readEntry("Highlight")));
// anders: restore bookmarks if possible
QValueList<int> l = config->readIntListEntry("Bookmarks");
if ( l.count() ) {
for (uint i=0; i < l.count(); i++) {
if ( numLines() < l[i] ) break;
getTextLine( l[i] )->addMark( Bookmark );
}
}
}
void KateDocument::writeSessionConfig(KateConfig *config)
{
#if 0
config->writeEntry("URL", m_url); // ### encoding?? (Simon)
config->writeEntry("Highlight", m_highlight->name());
// anders: save bookmarks
QList<Kate::Mark> l = marks();
QValueList<int> ml;
for (uint i=0; i < l.count(); i++) {
if ( l.at(i)->type == 1) // only save bookmarks
ml << l.at(i)->line;
}
if ( ml.count() )
config->writeEntry("Bookmarks", ml);
#endif
}
void KateDocument::setHighlight(int n) {
Highlight *h;
// hlNumber = n;
h = hlManager->getHl(n);
if (h == m_highlight) {
updateLines();
} else {
if (m_highlight != 0L) m_highlight->release();
h->use();
m_highlight = h;
makeAttribs();
}
PreHighlightedTill=0;
RequestPreHighlightTill=0;
emit(highlightChanged());
}
void KateDocument::makeAttribs() {
odebug << "KateDocument::makeAttribs()" << oendl;
m_numAttribs = hlManager->makeAttribs(m_highlight, m_attribs, maxAttribs);
updateFontData();
updateLines();
}
void KateDocument::updateFontData() {
int maxAscent, maxDescent;
int tabWidth;
KateView *view;
maxAscent = myFontMetrics.ascent();
maxDescent = myFontMetrics.descent();
tabWidth = myFontMetrics.width(' ');
fontHeight = maxAscent + maxDescent + 1;
fontAscent = maxAscent;
m_tabWidth = tabChars*tabWidth;
for (view = views.first(); view != 0L; view = views.next() ) {
view->myViewInternal->drawBuffer->resize(view->width(),fontHeight);
view->tagAll();
view->updateCursor();
}
}
void KateDocument::hlChanged() { //slot
makeAttribs();
updateViews();
}
void KateDocument::addView(KTextEditor::View *view) {
views.append( static_cast<KateView *>( view ) );
KTextEditor::Document::addView( view );
connect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
}
void KateDocument::removeView(KTextEditor::View *view) {
// if (undoView == view) recordReset();
disconnect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
views.removeRef( static_cast<KateView *>( view ) );
KTextEditor::Document::removeView( view );
}
void KateDocument::slotViewDestroyed()
{
views.removeRef( static_cast<const KateView *>( sender() ) );
}
bool KateDocument::ownedView(KateView *view) {
// do we own the given view?
return (views.containsRef(view) > 0);
}
bool KateDocument::isLastView(int numViews) {
return ((int) views.count() == numViews);
}
int KateDocument::textWidth(const TextLine::Ptr &textLine, int cursorX) {
int x;
int z;
QChar ch;
Attribute *a;
x = 0;
for (z = 0; z < cursorX; z++) {
ch = textLine->getChar(z);
a = &m_attribs[textLine->getAttr(z)];
if (ch == '\t')
x += m_tabWidth - (x % m_tabWidth);
else if (a->bold && a->italic)
x += myFontMetricsBI.width(ch);
else if (a->bold)
x += myFontMetricsBold.width(ch);
else if (a->italic)
x += myFontMetricsItalic.width(ch);
else
x += myFontMetrics.width(ch);
}
return x;
}
int KateDocument::textWidth(PointStruc &cursor) {
if (cursor.x < 0)
cursor.x = 0;
if (cursor.y < 0)
cursor.y = 0;
if (cursor.y >= numLines())
cursor.y = lastLine();
return textWidth(getTextLine(cursor.y),cursor.x);
}
int KateDocument::textWidth(bool wrapCursor, PointStruc &cursor, int xPos) {
int len;
int x, oldX;
int z;
QChar ch;
Attribute *a;
if (cursor.y < 0) cursor.y = 0;
if (cursor.y > lastLine()) cursor.y = lastLine();
TextLine::Ptr textLine = getTextLine(cursor.y);
len = textLine->length();
x = oldX = z = 0;
while (x < xPos && (!wrapCursor || z < len)) {
oldX = x;
ch = textLine->getChar(z);
a = &m_attribs[textLine->getAttr(z)];
if (ch == '\t')
x += m_tabWidth - (x % m_tabWidth);
else if (a->bold && a->italic)
x += myFontMetricsBI.width(ch);
else if (a->bold)
x += myFontMetricsBold.width(ch);
else if (a->italic)
x += myFontMetricsItalic.width(ch);
else
x += myFontMetrics.width(ch);
z++;
}
if (xPos - oldX < x - xPos && z > 0) {
z--;
x = oldX;
}
cursor.x = z;
return x;
}
int KateDocument::textPos(const TextLine::Ptr &textLine, int xPos) {
int x, oldX;
int z;
QChar ch;
Attribute *a;
x = oldX = z = 0;
while (x < xPos) { // && z < len) {
oldX = x;
ch = textLine->getChar(z);
a = &m_attribs[textLine->getAttr(z)];
if (ch == '\t')
x += m_tabWidth - (x % m_tabWidth);
else if (a->bold && a->italic)
x += myFontMetricsBI.width(ch);
else if (a->bold)
x += myFontMetricsBold.width(ch);
else if (a->italic)
x += myFontMetricsItalic.width(ch);
else
x += myFontMetrics.width(ch);
z++;
}
if (xPos - oldX < x - xPos && z > 0) {
z--;
// newXPos = oldX;
}// else newXPos = x;
return z;
}
int KateDocument::textWidth() {
return int(maxLength + 8);
}
int KateDocument::textHeight() {
return numLines()*fontHeight;
}
void KateDocument::insert(VConfig &c, const QString &s) {
int pos;
QChar ch;
QString buf;
if (s.isEmpty()) return;
recordStart(c, KateActionGroup::ugPaste);
pos = 0;
if (!(c.flags & KateView::cfVerticalSelect)) {
do {
ch = s[pos];
if (ch.isPrint() || ch == '\t') {
buf += ch; // append char to buffer
} else if (ch == '\n') {
recordAction(KateAction::newLine, c.cursor); // wrap contents behind cursor to new line
recordInsert(c, buf); // append to old line
// c.cursor.x += buf.length();
buf.truncate(0); // clear buffer
c.cursor.y++;
c.cursor.x = 0;
}
pos++;
} while (pos < (int) s.length());
} else {
int xPos;
xPos = textWidth(c.cursor);
do {
ch = s[pos];
if (ch.isPrint() || ch == '\t') {
buf += ch;
} else if (ch == '\n') {
recordInsert(c, buf);
c.cursor.x += buf.length();
buf.truncate(0);
c.cursor.y++;
if (c.cursor.y >= numLines())
recordAction(KateAction::insLine, c.cursor);
c.cursor.x = textPos(getTextLine(c.cursor.y), xPos);
}
pos++;
} while (pos < (int) s.length());
}
recordInsert(c, buf);
c.cursor.x += buf.length();
recordEnd(c);
}
void KateDocument::insertFile(VConfig &c, QIODevice &dev)
{
recordStart(c, KateActionGroup::ugPaste);
QString buf;
QChar ch, last;
QTextStream stream( &dev );
while ( !stream.atEnd() ) {
stream >> ch;
if (ch.isPrint() || ch == '\t') {
buf += ch;
} else if (ch == '\n' || ch == '\r') {
if (last != '\r' || ch != '\n') {
recordAction(KateAction::newLine, c.cursor);
recordInsert(c, buf);
buf.truncate(0);
c.cursor.y++;
c.cursor.x = 0;
}
last = ch;
}
}
recordInsert(c, buf);
recordEnd(c);
}
int KateDocument::currentColumn(PointStruc &cursor) {
return getTextLine(cursor.y)->cursorX(cursor.x,tabChars);
}
bool KateDocument::insertChars(VConfig &c, const QString &chars) {
int z, pos, l;
bool onlySpaces;
QChar ch;
QString buf;
TextLine::Ptr textLine = getTextLine(c.cursor.y);
pos = 0;
onlySpaces = true;
for (z = 0; z < (int) chars.length(); z++) {
ch = chars[z];
if (ch == '\t' && c.flags & KateView::cfReplaceTabs) {
l = tabChars - (textLine->cursorX(c.cursor.x, tabChars) % tabChars);
while (l > 0) {
buf.insert(pos, ' ');
pos++;
l--;
}
} else if (ch.isPrint() || ch == '\t') {
buf.insert(pos, ch);
pos++;
if (ch != ' ') onlySpaces = false;
if (c.flags & KateView::cfAutoBrackets) {
if (ch == '(') buf.insert(pos, ')');
if (ch == '[') buf.insert(pos, ']');
if (ch == '{') buf.insert(pos, '}');
}
}
}
//pos = cursor increment
//return false if nothing has to be inserted
if (buf.isEmpty()) return false;
//auto deletion of the marked text occurs not very often and can therefore
// be recorded separately
if (c.flags &KateView:: cfDelOnInput) delMarkedText(c);
recordStart(c, KateActionGroup::ugInsChar);
recordReplace(c/*.cursor*/, (c.flags & KateView::cfOvr) ? buf.length() : 0, buf);
c.cursor.x += pos;
if (myWordWrap && myWordWrapAt > 0) {
int line;
const QChar *s;
// int pos;
PointStruc actionCursor;
line = c.cursor.y;
do {
textLine = getTextLine(line);
s = textLine->getText();
l = textLine->length();
for (z = myWordWrapAt; z < l; z++) if (!s[z].isSpace()) break; //search for text to wrap
if (z >= l) break; // nothing more to wrap
pos = myWordWrapAt;
for (; z >= 0; z--) { //find wrap position
if (s[z].isSpace()) {
pos = z + 1;
break;
}
}
//pos = wrap position
if (line == c.cursor.y && pos <= c.cursor.x) {
//wrap cursor
c.cursor.y++;
c.cursor.x -= pos;
}
if (line == lastLine() || (getTextLine(line+1)->length() == 0) ) {
//at end of doc: create new line
actionCursor.x = pos;
actionCursor.y = line;
recordAction(KateAction::newLine,actionCursor);
} else {
//wrap
actionCursor.y = line + 1;
if (!s[l - 1].isSpace()) { //add space in next line if necessary
actionCursor.x = 0;
recordInsert(actionCursor, " ");
}
actionCursor.x = textLine->length() - pos;
recordAction(KateAction::wordWrap, actionCursor);
}
line++;
} while (true);
}
recordEnd(c);
return true;
}
QString tabString(int pos, int tabChars) {
QString s;
while (pos >= tabChars) {
s += '\t';
pos -= tabChars;
}
while (pos > 0) {
s += ' ';
pos--;
}
return s;
}
void KateDocument::newLine(VConfig &c) {
//auto deletion of marked text is done by the view to have a more
// "low level" KateDocument::newLine method
recordStart(c, KateActionGroup::ugInsLine);
if (!(c.flags & KateView::cfAutoIndent)) {
recordAction(KateAction::newLine,c.cursor);
c.cursor.y++;
c.cursor.x = 0;
} else {
TextLine::Ptr textLine = getTextLine(c.cursor.y);
int pos = textLine->firstChar();
if (c.cursor.x < pos) c.cursor.x = pos; // place cursor on first char if before
int y = c.cursor.y;
while ((y > 0) && (pos < 0)) { // search a not empty text line
textLine = getTextLine(--y);
pos = textLine->firstChar();
}
recordAction(KateAction::newLine, c.cursor);
c.cursor.y++;
c.cursor.x = 0;
if (pos > 0) {
pos = textLine->cursorX(pos, tabChars);
// if (getTextLine(c.cursor.y)->length() > 0) {
QString s = tabString(pos, (c.flags & KateView::cfSpaceIndent) ? 0xffffff : tabChars);
recordInsert(c.cursor, s);
pos = s.length();
// }
// recordInsert(c.cursor, QString(textLine->getText(), pos));
c.cursor.x = pos;
}
}
recordEnd(c);
}
void KateDocument::killLine(VConfig &c) {
recordStart(c, KateActionGroup::ugDelLine);
c.cursor.x = 0;
recordDelete(c.cursor, 0xffffff);
if (c.cursor.y < lastLine()) {
recordAction(KateAction::killLine, c.cursor);
}
recordEnd(c);
}
void KateDocument::backspace(VConfig &c) {
if (c.cursor.x <= 0 && c.cursor.y <= 0) return;
if (c.cursor.x > 0) {
recordStart(c, KateActionGroup::ugDelChar);
if (!(c.flags & KateView::cfBackspaceIndents)) {
// ordinary backspace
c.cursor.x--;
recordDelete(c.cursor, 1);
} else {
// backspace indents: erase to next indent position
int l = 1; // del one char
TextLine::Ptr textLine = getTextLine(c.cursor.y);
int pos = textLine->firstChar();
if (pos < 0 || pos >= c.cursor.x) {
// only spaces on left side of cursor
// search a line with less spaces
int y = c.cursor.y;
while (y > 0) {
textLine = getTextLine(--y);
pos = textLine->firstChar();
if (pos >= 0 && pos < c.cursor.x) {
l = c.cursor.x - pos; // del more chars
break;
}
}
}
// break effectively jumps here
c.cursor.x -= l;
recordDelete(c.cursor, l);
}
} else {
// c.cursor.x == 0: wrap to previous line
recordStart(c, KateActionGroup::ugDelLine);
c.cursor.y--;
c.cursor.x = getTextLine(c.cursor.y)->length();
recordAction(KateAction::delLine,c.cursor);
}
recordEnd(c);
}
void KateDocument::del(VConfig &c) {
TextLine::Ptr textLine = getTextLine(c.cursor.y);
int len = (c.flags & KateView::cfRemoveSpaces) ? textLine->lastChar() : textLine->length();
if (c.cursor.x < len/*getTextLine(c.cursor.y)->length()*/) {
// delete one character
recordStart(c, KateActionGroup::ugDelChar);
recordDelete(c.cursor, 1);
recordEnd(c);
} else {
if (c.cursor.y < lastLine()) {
// wrap next line to this line
textLine->truncate(c.cursor.x); // truncate spaces
recordStart(c, KateActionGroup::ugDelLine);
recordAction(KateAction::delLine,c.cursor);
recordEnd(c);
}
}
}
void KateDocument::clear() {
PointStruc cursor;
KateView *view;
setPseudoModal(0L);
cursor.x = cursor.y = 0;
for (view = views.first(); view != 0L; view = views.next() ) {
view->updateCursor(cursor);
view->tagAll();
}
eolMode = KateDocument::eolUnix;
buffer->clear();
longestLine = buffer->line(0);
maxLength = 0;
select.x = -1;
selectStart = 0xffffff;
selectEnd = 0;
oldMarkState = false;
setModified(false);
undoList.clear();
currentUndo = 0;
newUndo();
}
void KateDocument::cut(VConfig &c) {
if (selectEnd < selectStart) return;
copy(c.flags);
delMarkedText(c);
}
void KateDocument::copy(int flags) {
if (selectEnd < selectStart) return;
QString s = markedText(flags);
if (!s.isEmpty()) {
//#if defined(_WS_X11_)
if (m_singleSelection)
disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, 0);
//#endif
QApplication::clipboard()->setText(s);
//#if defined(_WS_X11_)
if (m_singleSelection) {
connect(QApplication::clipboard(), SIGNAL(dataChanged()),
this, SLOT(clipboardChanged()));
}
//#endif
}
}
void KateDocument::paste(VConfig &c) {
QString s = QApplication::clipboard()->text();
if (!s.isEmpty()) {
insert(c, s);
}
}
void KateDocument::toggleRect(int start, int end, int x1, int x2) {
int z, line;
bool t;
if (x1 > x2) {
z = x1;
x1 = x2;
x2 = z;
}
if (start > end) {
z = start;
start = end;
end = z;
}
t = false;
for (line = start; line < end; line++) {
int x, oldX, s, e, newX1, newX2;
QChar ch;
Attribute *a;
TextLine::Ptr textLine = getTextLine(line);
//--- speed optimization
//s = textPos(textLine, x1, newX1);
x = oldX = z = 0;
while (x < x1) { // && z < len) {
oldX = x;
ch = textLine->getChar(z);
a = &m_attribs[textLine->getAttr(z)];
if (ch == '\t')
x += m_tabWidth - (x % m_tabWidth);
else if (a->bold && a->italic)
x += myFontMetricsBI.width(ch);
else if (a->bold)
x += myFontMetricsBold.width(ch);
else if (a->italic)
x += myFontMetricsItalic.width(ch);
else
x += myFontMetrics.width(ch);
z++;
}
s = z;
if (x1 - oldX < x - x1 && z > 0) {
s--;
newX1 = oldX;
} else newX1 = x;
//e = textPos(textLine, x2, newX2);
while (x < x2) { // && z < len) {
oldX = x;
ch = textLine->getChar(z);
a = &m_attribs[textLine->getAttr(z)];
if (ch == '\t')
x += m_tabWidth - (x % m_tabWidth);
else if (a->bold && a->italic)
x += myFontMetricsBI.width(ch);
else if (a->bold)
x += myFontMetricsBold.width(ch);
else if (a->italic)
x += myFontMetricsItalic.width(ch);
else
x += myFontMetrics.width(ch);
z++;
}
e = z;
if (x2 - oldX < x - x2 && z > 0) {
e--;
newX2 = oldX;
} else newX2 = x;
//---
if (e > s) {
textLine->toggleSelect(s, e);
tagLineRange(line, newX1, newX2);
t = true;
}
}
if (t) {
end--;
// tagLines(start, end);
if (start < selectStart) selectStart = start;
if (end > selectEnd) selectEnd = end;
emit selectionChanged();
}
}
void KateDocument::selectTo(VConfig &c, PointStruc &cursor, int cXPos) {
//c.cursor = old cursor position
//cursor = new cursor position
if (c.cursor.x != select.x || c.cursor.y != select.y) {
//new selection
if (!(c.flags & KateView::cfKeepSelection)) deselectAll();
// else recordReset();
anchor = c.cursor;
aXPos = c.cXPos;
}
if (!(c.flags & KateView::cfVerticalSelect)) {
//horizontal selections
int x, y, sXPos;
int ex, ey, eXPos;
bool sel;
if (cursor.y > c.cursor.y || (cursor.y == c.cursor.y && cursor.x > c.cursor.x)) {
x = c.cursor.x;
y = c.cursor.y;
sXPos = c.cXPos;
ex = cursor.x;
ey = cursor.y;
eXPos = cXPos;
sel = true;
} else {
x = cursor.x;
y = cursor.y;
sXPos = cXPos;
ex = c.cursor.x;
ey = c.cursor.y;
eXPos = c.cXPos;
sel = false;
}
// tagLines(y, ye);
if (y < ey) {
//tagLineRange(y, sXPos, 0xffffff);
tagLines(y, ey -1);
tagLineRange(ey, 0, eXPos);
} else tagLineRange(y, sXPos, eXPos);
if (y < selectStart) selectStart = y;
if (ey > selectEnd) selectEnd = ey;
TextLine::Ptr textLine = getTextLine(y);
if (c.flags & KateView::cfXorSelect) {
//xor selection with old selection
while (y < ey) {
textLine->toggleSelectEol(x);
x = 0;
y++;
textLine = getTextLine(y);
}
textLine->toggleSelect(x, ex);
} else {
//set selection over old selection
if (anchor.y > y || (anchor.y == y && anchor.x > x)) {
if (anchor.y < ey || (anchor.y == ey && anchor.x < ex)) {
sel = !sel;
while (y < anchor.y) {
textLine->selectEol(sel, x);
x = 0;
y++;
textLine = getTextLine(y);
}
textLine->select(sel, x, anchor.x);
x = anchor.x;
}
sel = !sel;
}
while (y < ey) {
textLine->selectEol(sel, x);
x = 0;
y++;
textLine = getTextLine(y);
}
textLine->select(sel, x, ex);
}
} else {
//vertical (block) selections
// int ax, sx, ex;
// ax = textWidth(anchor);
// sx = textWidth(start);
// ex = textWidth(end);
toggleRect(c.cursor.y + 1, cursor.y + 1, aXPos, c.cXPos);
toggleRect(anchor.y, cursor.y + 1, c.cXPos, cXPos);
}
select = cursor;
optimizeSelection();
emit selectionChanged();
}
void KateDocument::selectAll() {
int z;
TextLine::Ptr textLine;
select.x = -1;
// if (selectStart != 0 || selectEnd != lastLine()) recordReset();
selectStart = 0;
selectEnd = lastLine();
tagLines(selectStart,selectEnd);
for (z = selectStart; z < selectEnd; z++) {
textLine = getTextLine(z);
textLine->selectEol(true,0);
}
textLine = getTextLine(z);
textLine->select(true,0,textLine->length());
emit selectionChanged();
}
void KateDocument::deselectAll() {
select.x = -1;
if (selectEnd < selectStart) return;
// recordReset();
tagLines(selectStart,selectEnd);
for (int z = selectStart; z <= selectEnd; z++) {
TextLine::Ptr textLine = getTextLine(z);
textLine->selectEol(false,0);
}
selectStart = 0xffffff;
selectEnd = 0;
emit selectionChanged();
}
void KateDocument::invertSelection() {
TextLine::Ptr textLine;
select.x = -1;
// if (selectStart != 0 || selectEnd != lastLine()) recordReset();
selectStart = 0;
selectEnd = lastLine();
tagLines(selectStart,selectEnd);
for (int z = selectStart; z < selectEnd; z++) {
textLine = getTextLine(z);
textLine->toggleSelectEol(0);
}
textLine = getTextLine(selectEnd);
textLine->toggleSelect(0,textLine->length());
optimizeSelection();
emit selectionChanged();
}
void KateDocument::selectWord(PointStruc &cursor, int flags) {
int start, end, len;
TextLine::Ptr textLine = getTextLine(cursor.y);
len = textLine->length();
start = end = cursor.x;
while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--;
while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++;
if (end <= start) return;
if (!(flags & KateView::cfKeepSelection)) deselectAll();
// else recordReset();
textLine->select(true, start, end);
anchor.x = start;
select.x = end;
anchor.y = select.y = cursor.y;
tagLines(cursor.y, cursor.y);
if (cursor.y < selectStart) selectStart = cursor.y;
if (cursor.y > selectEnd) selectEnd = cursor.y;
emit selectionChanged();
}
void KateDocument::selectLength(PointStruc &cursor, int length, int flags) {
int start, end;
TextLine::Ptr textLine = getTextLine(cursor.y);
start = cursor.x;
end = start + length;
if (end <= start) return;
if (!(flags & KateView::cfKeepSelection)) deselectAll();
textLine->select(true, start, end);
anchor.x = start;
select.x = end;
anchor.y = select.y = cursor.y;
tagLines(cursor.y, cursor.y);
if (cursor.y < selectStart) selectStart = cursor.y;
if (cursor.y > selectEnd) selectEnd = cursor.y;
emit selectionChanged();
}
void KateDocument::doIndent(VConfig &c, int change) {
c.cursor.x = 0;
recordStart(c, (change < 0) ? KateActionGroup::ugUnindent
: KateActionGroup::ugIndent);
if (selectEnd < selectStart) {
// single line
optimizeLeadingSpace(c.cursor.y, c.flags, change);
} else {
// entire selection
TextLine::Ptr textLine;
int line, z;
QChar ch;
if (c.flags & KateView::cfKeepIndentProfile && change < 0) {
// unindent so that the existing indent profile doesn´t get screwed
// if any line we may unindent is already full left, don't do anything
for (line = selectStart; line <= selectEnd; line++) {
textLine = getTextLine(line);
if (textLine->isSelected() || textLine->numSelected()) {
for (z = 0; z < tabChars; z++) {
ch = textLine->getChar(z);
if (ch == '\t') break;
if (ch != ' ') {
change = 0;
goto jumpOut;
}
}
}
}
jumpOut:;
}
for (line = selectStart; line <= selectEnd; line++) {
textLine = getTextLine(line);
if (textLine->isSelected() || textLine->numSelected()) {
optimizeLeadingSpace(line, c.flags, change);
}
}
}
// recordEnd now removes empty undo records
recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent);
}
/*
Optimize the leading whitespace for a single line.
If change is > 0, it adds indentation units (tabChars)
if change is == 0, it only optimizes
If change is < 0, it removes indentation units
This will be used to indent, unindent, and optimal-fill a line.
If excess space is removed depends on the flag cfKeepExtraSpaces
which has to be set by the user
*/
void KateDocument::optimizeLeadingSpace(int line, int flags, int change) {
int len;
int chars, space, okLen;
QChar ch;
int extra;
QString s;
PointStruc cursor;
TextLine::Ptr textLine = getTextLine(line);
len = textLine->length();
space = 0; // length of space at the beginning of the textline
okLen = 0; // length of space which does not have to be replaced
for (chars = 0; chars < len; chars++) {
ch = textLine->getChar(chars);
if (ch == ' ') {
space++;
if (flags & KateView::cfSpaceIndent && okLen == chars) okLen++;
} else if (ch == '\t') {
space += tabChars - space % tabChars;
if (!(flags & KateView::cfSpaceIndent) && okLen == chars) okLen++;
} else break;
}
space += change*tabChars; // modify space width
// if line contains only spaces it will be cleared
if (space < 0 || chars == len) space = 0;
extra = space % tabChars; // extra spaces which don´t fit the indentation pattern
if (flags & KateView::cfKeepExtraSpaces) chars -= extra;
if (flags & KateView::cfSpaceIndent) {
space -= extra;
ch = ' ';
} else {
space /= tabChars;
ch = '\t';
}
// don´t replace chars which are already ok
cursor.x = QMIN(okLen, QMIN(chars, space));
chars -= cursor.x;
space -= cursor.x;
if (chars == 0 && space == 0) return; //nothing to do
s.fill(ch, space);
//printf("chars %d insert %d cursor.x %d\n", chars, insert, cursor.x);
cursor.y = line;
recordReplace(cursor, chars, s);
}
void KateDocument::doComment(VConfig &c, int change)
{
c.flags |=KateView:: cfPersistent;
recordStart(c, (change < 0) ? KateActionGroup::ugUncomment
: KateActionGroup::ugComment);
QString startComment = m_highlight->getCommentStart();
QString startLineComment = m_highlight->getCommentSingleLineStart();
QString endComment = m_highlight->getCommentEnd();
int startCommentLen = startComment.length();
int startLineCommentLen = startLineComment.length();
int endCommentLen = endComment.length();
if (change > 0)
{
if ( !hasMarkedText() )
{
if (startLineComment != "")
{
// Add a start comment mark
c.cursor.x = 0;
recordReplace(c.cursor, 0, startLineComment);
}
else if ((startComment != "") && (endComment != ""))
{
// Add a start comment mark
c.cursor.x = 0;
recordReplace(c.cursor, 0, startComment);
// Add an end comment mark
TextLine* textline = getTextLine(c.cursor.y);
c.cursor.x = textline->length();
recordReplace(c.cursor, 0, endComment);
c.cursor.x = 0;
}
}
else if ((startComment != "") && (endComment != ""))
{
QString marked (c.view->markedText ());
int preDeleteLine = -1, preDeleteCol = -1;
c.view->getCursorPosition (&preDeleteLine, &preDeleteCol);
if (marked.length() > 0)
c.view->keyDelete ();
int line = -1, col = -1;
c.view->getCursorPosition (&line, &col);
c.view->insertText (startComment + marked + endComment);
}
}
else
{
if ( !hasMarkedText() )
{
TextLine* textline = getTextLine(c.cursor.y);
if(textline->startingWith(startLineComment))
{
// Remove start comment mark
c.cursor.x = 0;
recordReplace(c.cursor, startLineCommentLen, "");
}
else if (textline->startingWith(startComment) && textline->endingWith(endComment))
{
// Remove start comment mark
c.cursor.x = 0;
recordReplace(c.cursor, startCommentLen, "");
// Remove end comment mark
if(endComment != "")
{
c.cursor.x = textline->length() - endCommentLen;
recordReplace(c.cursor, endCommentLen, "");
c.cursor.x = 0;
}
}
}
else
{
QString marked (c.view->markedText ());
int preDeleteLine = -1, preDeleteCol = -1;
c.view->getCursorPosition (&preDeleteLine, &preDeleteCol);
int start = marked.find (startComment);
int end = marked.findRev (endComment);
if ((start > -1) && (end > -1))
{
marked.remove (start, startCommentLen);
marked.remove (end-startCommentLen, endCommentLen);
c.view->keyDelete ();
int line = -1, col = -1;
c.view->getCursorPosition (&line, &col);
c.view->insertText (marked);
}
}
}
recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent);
}
QString KateDocument::text() const
{
QString s;
for (int i=0; i < buffer->count(); i++)
{
TextLine::Ptr textLine = buffer->line(i);
s.insert(s.length(), textLine->getText(), textLine->length());
if ( (i < (buffer->count()-1)) )
s.append('\n');
}
return s;
}
QString KateDocument::getWord(PointStruc &cursor) {
int start, end, len;
TextLine::Ptr textLine = getTextLine(cursor.y);
len = textLine->length();
start = end = cursor.x;
while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--;
while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++;
len = end - start;
return QString(&textLine->getText()[start], len);
}
void KateDocument::setText(const QString &s) {
int pos;
QChar ch;
clear();
int line=1;
TextLine::Ptr textLine = buffer->line(0);
for (pos = 0; pos <= (int) s.length(); pos++) {
ch = s[pos];
if (ch.isPrint() || ch == '\t') {
textLine->append(&ch, 1);
} else if (ch == '\n')
{
textLine = new TextLine();
buffer->insertLine (line, textLine);
line++;
}
}
updateLines();
}
QString KateDocument::markedText(int flags) {
TextLine::Ptr textLine;
int len, z, start, end, i;
len = 1;
if (!(flags & KateView::cfVerticalSelect)) {
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
len += textLine->numSelected();
if (textLine->isSelected()) len++;
}
QString s;
len = 0;
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
end = 0;
do {
start = textLine->findUnselected(end);
end = textLine->findSelected(start);
for (i = start; i < end; i++) {
s[len] = textLine->getChar(i);
len++;
}
} while (start < end);
if (textLine->isSelected()) {
s[len] = '\n';
len++;
}
}
// s[len] = '\0';
return s;
} else {
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
len += textLine->numSelected() + 1;
}
QString s;
len = 0;
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
end = 0;
do {
start = textLine->findUnselected(end);
end = textLine->findSelected(start);
for (i = start; i < end; i++) {
s[len] = textLine->getChar(i);
len++;
}
} while (start < end);
s[len] = '\n';
len++;
}
// s[len] = '\0'; // the final \0 is not counted in length()
return s;
}
}
void KateDocument::delMarkedText(VConfig &c/*, bool undo*/) {
int end = 0;
if (selectEnd < selectStart) return;
// the caller may have already started an undo record for the current action
// if (undo)
//auto deletion of the marked text occurs not very often and can therefore
// be recorded separately
recordStart(c, KateActionGroup::ugDelBlock);
for (c.cursor.y = selectEnd; c.cursor.y >= selectStart; c.cursor.y--) {
TextLine::Ptr textLine = getTextLine(c.cursor.y);
c.cursor.x = textLine->length();
do {
end = textLine->findRevUnselected(c.cursor.x);
if (end == 0) break;
c.cursor.x = textLine->findRevSelected(end);
recordDelete(c.cursor, end - c.cursor.x);
} while (true);
end = c.cursor.x;
c.cursor.x = textLine->length();
if (textLine->isSelected()) recordAction(KateAction::delLine,c.cursor);
}
c.cursor.y++;
/*if (end < c.cursor.x)*/ c.cursor.x = end;
selectEnd = -1;
select.x = -1;
/*if (undo)*/ recordEnd(c);
}
void KateDocument::tagLineRange(int line, int x1, int x2) {
int z;
for (z = 0; z < (int) views.count(); z++) {
views.at(z)->tagLines(line, line, x1, x2);
}
}
void KateDocument::tagLines(int start, int end) {
int z;
for (z = 0; z < (int) views.count(); z++) {
views.at(z)->tagLines(start, end, 0, 0xffffff);
}
}
void KateDocument::tagAll() {
int z;
for (z = 0; z < (int) views.count(); z++) {
views.at(z)->tagAll();
}
}
void KateDocument::updateLines(int startLine, int endLine, int flags, int cursorY) {
TextLine::Ptr textLine;
int line, last_line;
int ctxNum, endCtx;
// kdDebug(13020)<<"******************KateDocument::updateLines Checkpoint 1"<<endl;
if (buffer->line(startLine)==0) {kdDebug(13020)<<"********************No buffer for line " << startLine << " found**************"<<endl; return;};
// kdDebug(13020)<<"KateDocument::updateLines Checkpoint 2"<<endl;
last_line = lastLine();
// if (endLine >= last_line) endLine = last_line;
line = startLine;
ctxNum = 0;
if (line > 0) ctxNum = getTextLine(line - 1)->getContext();
do {
// kdDebug(13020)<<QString("**************Working on line: %1").arg(line)<<endl;
textLine = getTextLine(line);
if (textLine==0) kdDebug(13020)<<"****updateLines()>> error textLine==0"<<endl;
if (line <= endLine && line != cursorY) {
if (flags & KateView::cfRemoveSpaces) textLine->removeSpaces();
updateMaxLength(textLine);
}
endCtx = textLine->getContext();
// odebug << "DOHIGHLIGHT" << oendl;
ctxNum = m_highlight->doHighlight(ctxNum,textLine);
textLine->setContext(ctxNum);
line++;
} while ((buffer->line(line)!=0) && (line <= endLine || endCtx != ctxNum));
// kdDebug(13020)<<"updateLines :: while loop left"<<endl;
tagLines(startLine, line - 1);
}
void KateDocument::updateMaxLength(TextLine::Ptr &textLine) {
int len;
len = textWidth(textLine,textLine->length());
if (len > maxLength) {
longestLine = textLine;
maxLength = len;
newDocGeometry = true;
} else {
if (!longestLine || (textLine == longestLine && len <= maxLength*3/4)) {
maxLength = -1;
for (int i = 0; i < numLines();i++) {
textLine = getTextLine(i);
len = textWidth(textLine,textLine->length());
if (len > maxLength) {
maxLength = len;
longestLine = textLine;
}
}
newDocGeometry = true;
}
}
}
void KateDocument::slotBufferChanged() {
newDocGeometry = true;
//updateLines();//JW
updateViews();
}
void KateDocument::slotBufferHighlight(long start,long stop) {
kdDebug(13020)<<"KateDocument::slotBufferHighlight"<<QString("%1-%2").arg(start).arg(stop)<<endl;
updateLines(start,stop);
// buffer->startLoadTimer();
}
void KateDocument::updateViews(KateView *exclude) {
KateView *view;
int flags;
bool markState = hasMarkedText();
flags = (newDocGeometry) ? KateView::ufDocGeometry : 0;
for (view = views.first(); view != 0L; view = views.next() ) {
if (view != exclude) view->updateView(flags);
// notify every view about the changed mark state....
if (oldMarkState != markState) emit view->newMarkStatus();
}
oldMarkState = markState;
newDocGeometry = false;
}
QColor &KateDocument::cursorCol(int x, int y) {
int attr;
Attribute *a;
TextLine::Ptr textLine = getTextLine(y);
attr = textLine->getRawAttr(x);
a = &m_attribs[attr & taAttrMask];
if (attr & taSelected) return a->selCol; else return a->col;
}
void KateDocument::paintTextLine(QPainter &paint, int line, int xStart, int xEnd, bool showTabs)
{
paintTextLine (paint, line, 0, xStart, xEnd, showTabs);
}
void KateDocument::paintTextLine(QPainter &paint, int line, int y, int xStart, int xEnd, bool showTabs)
{
TextLine::Ptr textLine;
int len;
const QChar *s;
int z, x;
QChar ch;
Attribute *a = 0L;
int attr, nextAttr;
int xs;
int xc, zc;
if (line > lastLine()) {
paint.fillRect(0, y, xEnd - xStart,fontHeight, colors[0]);
return;
}
textLine = getTextLine(line);
len = textLine->length();
s = textLine->getText();
// skip to first visible character
x = 0;
z = 0;
do {
xc = x;
zc = z;
if (z == len) break;
ch = s[z];//textLine->getChar(z);
if (ch == '\t') {
x += m_tabWidth - (x % m_tabWidth);
} else {
a = &m_attribs[textLine->getAttr(z)];
if (a->bold && a->italic)
x += myFontMetricsBI.width(ch);
else if (a->bold)
x += myFontMetricsBold.width(ch);
else if (a->italic)
x += myFontMetricsItalic.width(ch);
else
x += myFontMetrics.width(ch);
}
z++;
} while (x <= xStart);
// draw background
xs = xStart;
attr = textLine->getRawAttr(zc);
while (x < xEnd)
{
nextAttr = textLine->getRawAttr(z);
if ((nextAttr ^ attr) & taSelected)
{
if (attr & taSelected)
paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[1]);
else
paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[0]);
xs = x;
attr = nextAttr;
}
if (z == len) break;
ch = s[z];//textLine->getChar(z);
if (ch == '\t')
x += m_tabWidth - (x % m_tabWidth);
else
{
a = &m_attribs[textLine->getAttr(z)];
if (a->bold && a->italic)
x += myFontMetricsBI.width(ch);
else if (a->bold)
x += myFontMetricsBold.width(ch);
else if (a->italic)
x += myFontMetricsItalic.width(ch);
else
x += myFontMetrics.width(ch);
}
z++;
}
if (attr & taSelected)
paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[1]);
else
paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[0]);
len = z; //reduce length to visible length
// draw text
x = xc;
z = zc;
y += fontAscent;// -1;
attr = -1;
while (z < len) {
ch = s[z];//textLine->getChar(z);
if (ch == '\t') {
if (z > zc) {
//this should cause no copy at all
QConstString str((QChar *) &s[zc], z - zc /*+1*/);
QString s = str.string();
paint.drawText(x - xStart, y, s);
if (a->bold && a->italic)
x += myFontMetricsBI.width(s);
else if (a->bold)
x += myFontMetricsBold.width(s);
else if (a->italic)
x += myFontMetricsItalic.width(s);
else
x += myFontMetrics.width(s);
}
zc = z +1;
if (showTabs) {
nextAttr = textLine->getRawAttr(z);
if (nextAttr != attr) {
attr = nextAttr;
a = &m_attribs[attr & taAttrMask];
if (attr & taSelected) paint.setPen(a->selCol);
else paint.setPen(a->col);
if (a->bold && a->italic)
paint.setFont(myFontBI);
else if (a->bold)
paint.setFont(myFontBold);
else if (a->italic)
paint.setFont(myFontItalic);
else
paint.setFont(myFont);
}
// paint.drawLine(x - xStart, y -2, x - xStart, y);
// paint.drawLine(x - xStart, y, x - xStart + 2, y);
paint.drawPoint(x - xStart, y);
paint.drawPoint(x - xStart +1, y);
paint.drawPoint(x - xStart, y -1);
}
x += m_tabWidth - (x % m_tabWidth);
} else {
nextAttr = textLine->getRawAttr(z);
if (nextAttr != attr) {
if (z > zc) {
QConstString str((QChar *) &s[zc], z - zc /*+1*/);
QString s = str.string();
paint.drawText(x - xStart, y, s);
if (a->bold && a->italic)
x += myFontMetricsBI.width(s);
else if (a->bold)
x += myFontMetricsBold.width(s);
else if (a->italic)
x += myFontMetricsItalic.width(s);
else
x += myFontMetrics.width(s);
zc = z;
}
attr = nextAttr;
a = &m_attribs[attr & taAttrMask];
if (attr & taSelected) paint.setPen(a->selCol);
else paint.setPen(a->col);
if (a->bold && a->italic)
paint.setFont(myFontBI);
else if (a->bold)
paint.setFont(myFontBold);
else if (a->italic)
paint.setFont(myFontItalic);
else
paint.setFont(myFont);
}
}
z++;
}
if (z > zc) {
QConstString str((QChar *) &s[zc], z - zc /*+1*/);
paint.drawText(x - xStart, y, str.string());
}
}
// Applies the search context, and returns whether a match was found. If one is,
// the length of the string matched is also returned.
bool KateDocument::doSearch(SConfig &sc, const QString &searchFor) {
int line, col;
int searchEnd;
int bufLen, tlen;
QChar *t;
TextLine::Ptr textLine;
int pos, newPos;
if (searchFor.isEmpty()) return false;
bufLen = 0;
t = 0L;
line = sc.cursor.y;
col = sc.cursor.x;
if (!(sc.flags & KateView::sfBackward)) {
//forward search
if (sc.flags & KateView::sfSelected) {
if (line < selectStart) {
line = selectStart;
col = 0;
}
searchEnd = selectEnd;
} else searchEnd = lastLine();
while (line <= searchEnd) {
textLine = getTextLine(line);
tlen = textLine->length();
if (tlen > bufLen) {
- delete t;
+ delete [] t;
bufLen = (tlen + 255) & (~255);
t = new QChar[bufLen];
}
memcpy(t, textLine->getText(), tlen*sizeof(QChar));
if (sc.flags & KateView::sfSelected) {
pos = 0;
do {
pos = textLine->findSelected(pos);
newPos = textLine->findUnselected(pos);
memset(&t[pos], 0, (newPos - pos)*sizeof(QChar));
pos = newPos;
} while (pos < tlen);
}
QString text(t, tlen);
if (sc.flags & KateView::sfWholeWords) {
// Until the end of the line...
while (col < tlen) {
// ...find the next match.
col = sc.search(text, col);
if (col != -1) {
// Is the match delimited correctly?
if (((col == 0) || (!m_highlight->isInWord(t[col]))) &&
((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) {
goto found;
}
else {
// Start again from the next character.
col++;
}
}
else {
// No match.
break;
}
}
}
else {
// Non-whole-word search.
col = sc.search(text, col);
if (col != -1)
goto found;
}
col = 0;
line++;
}
} else {
// backward search
if (sc.flags & KateView::sfSelected) {
if (line > selectEnd) {
line = selectEnd;
col = -1;
}
searchEnd = selectStart;
} else searchEnd = 0;
while (line >= searchEnd) {
textLine = getTextLine(line);
tlen = textLine->length();
if (tlen > bufLen) {
- delete t;
+ delete [] t;
bufLen = (tlen + 255) & (~255);
t = new QChar[bufLen];
}
memcpy(t, textLine->getText(), tlen*sizeof(QChar));
if (sc.flags & KateView::sfSelected) {
pos = 0;
do {
pos = textLine->findSelected(pos);
newPos = textLine->findUnselected(pos);
memset(&t[pos], 0, (newPos - pos)*sizeof(QChar));
pos = newPos;
} while (pos < tlen);
}
if (col < 0 || col > tlen) col = tlen;
QString text(t, tlen);
if (sc.flags & KateView::sfWholeWords) {
// Until the beginning of the line...
while (col >= 0) {
// ...find the next match.
col = sc.search(text, col);
if (col != -1) {
// Is the match delimited correctly?
if (((col == 0) || (!m_highlight->isInWord(t[col]))) &&
((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) {
goto found;
}
else {
// Start again from the previous character.
col--;
}
}
else {
// No match.
break;
}
}
}
else {
// Non-whole-word search.
col = sc.search(text, col);
if (col != -1)
goto found;
}
col = -1;
line--;
}
}
sc.flags |= KateView::sfWrapped;
return false;
found:
if (sc.flags & KateView::sfWrapped) {
if ((line > sc.startCursor.y || (line == sc.startCursor.y && col >= sc.startCursor.x))
^ ((sc.flags & KateView::sfBackward) != 0)) return false;
}
sc.cursor.x = col;
sc.cursor.y = line;
return true;
}
void KateDocument::tagLine(int line) {
if (tagStart > line) tagStart = line;
if (tagEnd < line) tagEnd = line;
}
void KateDocument::insLine(int line) {
KateView *view;
if (selectStart >= line) selectStart++;
if (selectEnd >= line) selectEnd++;
if (tagStart >= line) tagStart++;
if (tagEnd >= line) tagEnd++;
newDocGeometry = true;
for (view = views.first(); view != 0L; view = views.next() ) {
view->insLine(line);
}
}
void KateDocument::delLine(int line) {
KateView *view;
if (selectStart >= line && selectStart > 0) selectStart--;
if (selectEnd >= line) selectEnd--;
if (tagStart >= line && tagStart > 0) tagStart--;
if (tagEnd >= line) tagEnd--;
newDocGeometry = true;
for (view = views.first(); view != 0L; view = views.next() ) {
view->delLine(line);
}
}
void KateDocument::optimizeSelection() {
TextLine::Ptr textLine;
while (selectStart <= selectEnd) {
textLine = getTextLine(selectStart);
if (textLine->isSelected() || textLine->numSelected() > 0) break;
selectStart++;
}
while (selectEnd >= selectStart) {
textLine = getTextLine(selectEnd);
if (textLine->isSelected() || textLine->numSelected() > 0) break;
selectEnd--;
}
if (selectStart > selectEnd) {
selectStart = 0xffffff;
selectEnd = 0;
}
}
void KateDocument::doAction(KateAction *a) {
switch (a->action) {
case KateAction::replace:
doReplace(a);
break;
case KateAction::wordWrap:
doWordWrap(a);
break;
case KateAction::wordUnWrap:
doWordUnWrap(a);
break;
case KateAction::newLine:
doNewLine(a);
break;
case KateAction::delLine:
doDelLine(a);
break;
case KateAction::insLine:
doInsLine(a);
break;
case KateAction::killLine:
doKillLine(a);
break;
/* case KateAction::doubleLine:
break;
case KateAction::removeLine:
break;*/
}
}
void KateDocument::doReplace(KateAction *a) {
TextLine::Ptr textLine;
int l;
//exchange current text with stored text in KateAction *a
textLine = getTextLine(a->cursor.y);
l = textLine->length() - a->cursor.x;
if (l > a->len) l = a->len;
QString oldText(&textLine->getText()[a->cursor.x], (l < 0) ? 0 : l);
textLine->replace(a->cursor.x, a->len, a->text.unicode(), a->text.length());
a->len = a->text.length();
a->text = oldText;
buffer->changeLine(a->cursor.y);
tagLine(a->cursor.y);
}
void KateDocument::doWordWrap(KateAction *a) {
TextLine::Ptr textLine;
textLine = getTextLine(a->cursor.y - 1);
a->len = textLine->length() - a->cursor.x;
textLine->wrap(getTextLine(a->cursor.y),a->len);
buffer->changeLine(a->cursor.y - 1);
buffer->changeLine(a->cursor.y);
tagLine(a->cursor.y - 1);
tagLine(a->cursor.y);
if (selectEnd == a->cursor.y - 1) selectEnd++;
a->action = KateAction::wordUnWrap;
}
void KateDocument::doWordUnWrap(KateAction *a) {
TextLine::Ptr textLine;
textLine = getTextLine(a->cursor.y - 1);
// textLine->setLength(a->len);
textLine->unWrap(a->len, getTextLine(a->cursor.y),a->cursor.x);
buffer->changeLine(a->cursor.y - 1);
buffer->changeLine(a->cursor.y);
tagLine(a->cursor.y - 1);
tagLine(a->cursor.y);
a->action = KateAction::wordWrap;
}
void KateDocument::doNewLine(KateAction *a) {
TextLine::Ptr textLine, newLine;
textLine = getTextLine(a->cursor.y);
newLine = new TextLine(textLine->getRawAttr(), textLine->getContext());
textLine->wrap(newLine,a->cursor.x);
buffer->insertLine(a->cursor.y + 1, newLine);
buffer->changeLine(a->cursor.y);
insLine(a->cursor.y + 1);
tagLine(a->cursor.y);
tagLine(a->cursor.y + 1);
if (selectEnd == a->cursor.y) selectEnd++;//addSelection(a->cursor.y + 1);
a->action = KateAction::delLine;
}
void KateDocument::doDelLine(KateAction *a) {
TextLine::Ptr textLine, nextLine;
textLine = getTextLine(a->cursor.y);
nextLine = getTextLine(a->cursor.y+1);
// textLine->setLength(a->cursor.x);
textLine->unWrap(a->cursor.x, nextLine,nextLine->length());
textLine->setContext(nextLine->getContext());
if (longestLine == nextLine) longestLine = 0L;
buffer->changeLine(a->cursor.y);
buffer->removeLine(a->cursor.y+1);
tagLine(a->cursor.y);
delLine(a->cursor.y + 1);
a->action = KateAction::newLine;
}
void KateDocument::doInsLine(KateAction *a) {
buffer->insertLine(a->cursor.y, new TextLine());
insLine(a->cursor.y);
a->action = KateAction::killLine;
}
void KateDocument::doKillLine(KateAction *a) {
TextLine::Ptr textLine = getTextLine(a->cursor.y);
if (longestLine == textLine) longestLine = 0L;
buffer->removeLine(a->cursor.y);
delLine(a->cursor.y);
tagLine(a->cursor.y);
a->action = KateAction::insLine;
}
void KateDocument::newUndo() {
KTextEditor::View *view;
int state;
state = 0;
if (currentUndo > 0) state |= 1;
if (currentUndo < (int) undoList.count()) state |= 2;
undoState = state;
for (view = m_views.first(); view != 0L; view = m_views.next() ) {
emit static_cast<KateView *>( view )->newUndo();
}
}
void KateDocument::recordStart(VConfig &c, int newUndoType) {
recordStart(c.view, c.cursor, c.flags, newUndoType);
}
void KateDocument::recordStart(KateView *, PointStruc &cursor, int flags,
int newUndoType, bool keepModal, bool mergeUndo) {
KateActionGroup *g;
// if (newUndoType == KateActionGroup::ugNone) {
// only a bug would cause this
//why should someone do this? we can't prevent all programming errors :) (jochen whilhelmy)
// debug("KateDocument::recordStart() called with no undo group type!");
// return;
// }
if (!keepModal) setPseudoModal(0L);
//i optimized the group undo stuff a bit (jochen wilhelmy)
// recordReset() is not needed any more
g = undoList.getLast();
if (g != 0L && ((undoCount < 1024 && flags & KateView::cfGroupUndo
&& g->end.x == cursor.x && g->end.y == cursor.y) || mergeUndo)) {
//undo grouping : same actions are put into one undo step
//precondition : new action starts where old stops or mergeUndo flag
if (g->undoType == newUndoType
|| (g->undoType == KateActionGroup::ugInsChar
&& newUndoType == KateActionGroup::ugInsLine)
|| (g->undoType == KateActionGroup::ugDelChar
&& newUndoType == KateActionGroup::ugDelLine)) {
undoCount++;
if (g->undoType != newUndoType) undoCount = 0xffffff;
return;
}
}
undoCount = 0;
/*
if (undoView != view) {
// always kill the current undo group if the editing view changes
recordReset();
undoType = newUndoType;
} else if (newUndoType == undoType) {
printf("bla!!!\n");
// same as current type, keep using it
return;
} else if ( (undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) ||
(undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine) ) {
// some type combinations can run together...
undoType += 1000;
return;
} else {
recordReset();
undoType = newUndoType;
}
undoView = view;
*/
while ((int) undoList.count() > currentUndo) undoList.removeLast();
while ((int) undoList.count() > undoSteps) {
undoList.removeFirst();
currentUndo--;
}
g = new KateActionGroup(cursor, newUndoType);
undoList.append(g);
// currentUndo++;
tagEnd = 0;
tagStart = 0xffffff;
}
void KateDocument::recordAction(KateAction::Action action, PointStruc &cursor) {
KateAction *a;
a = new KateAction(action, cursor);
doAction(a);
undoList.getLast()->insertAction(a);
}
void KateDocument::recordInsert(VConfig &c, const QString &text) {
recordReplace(c, 0, text);
}
void KateDocument::recordReplace(VConfig &c, int len, const QString &text) {
if (c.cursor.x > 0 && !(c.flags & KateView::cfSpaceIndent)) {
TextLine::Ptr textLine = getTextLine(c.cursor.y);
if (textLine->length() == 0) {
QString s = tabString(c.cursor.x, tabChars);
int len = s.length();
s += text;
c.cursor.x = 0;
recordReplace(c.cursor, len, s);
c.cursor.x = len;
return;
}
}
recordReplace(c.cursor, len, text);
}
void KateDocument::recordInsert(PointStruc &cursor, const QString &text) {
recordReplace(cursor, 0, text);
}
void KateDocument::recordDelete(PointStruc &cursor, int len) {
recordReplace(cursor, len, QString::null);
}
void KateDocument::recordReplace(PointStruc &cursor, int len, const QString &text) {
KateAction *a;
TextLine::Ptr textLine;
int l;
if (len == 0 && text.isEmpty()) return;
//try to append to last replace action
a = undoList.getLast()->action;
if (a == 0L || a->action != KateAction::replace
|| a->cursor.x + a->len != cursor.x || a->cursor.y != cursor.y) {
//if (a != 0L) printf("new %d %d\n", a->cursor.x + a->len, cursor.x);
a = new KateAction(KateAction::replace, cursor);
undoList.getLast()->insertAction(a);
}
//replace
textLine = getTextLine(cursor.y);
l = textLine->length() - cursor.x;
if (l > len) l = len;
a->text.insert(a->text.length(), &textLine->getText()[cursor.x], (l < 0) ? 0 : l);
textLine->replace(cursor.x, len, text.unicode(), text.length());
a->len += text.length();
buffer->changeLine(a->cursor.y);
updateMaxLength(textLine);
tagLine(a->cursor.y);
}
void KateDocument::recordEnd(VConfig &c) {
recordEnd(c.view, c.cursor, c.flags);
}
void KateDocument::recordEnd(KateView *view, PointStruc &cursor, int flags) {
KateActionGroup *g;
// clear selection if option "persistent selections" is off
// if (!(flags & cfPersistent)) deselectAll();
g = undoList.getLast();
if (g->action == 0L) {
// no action has been done: remove empty undo record
undoList.removeLast();
return;
}
// store end cursor position for redo
g->end = cursor;
currentUndo = undoList.count();
if (tagStart <= tagEnd) {
optimizeSelection();
updateLines(tagStart, tagEnd, flags, cursor.y);
setModified(true);
}
view->updateCursor(cursor, flags);
// newUndo();
/*
undoCount++;
// we limit the number of individual undo operations for sanity - is 1K reasonable?
// this is also where we handle non-group undo preference
// if the undo type is singlular, we always finish it now
if ( undoType == KateActionGroup::ugPaste ||
undoType == KateActionGroup::ugDelBlock ||
undoType > 1000 ||
undoCount > 1024 || !(flags & cfGroupUndo) ) {
printf("recordend %d %d\n", undoType, undoCount);
recordReset();
}
*/
// this should keep the flood of signals down a little...
if (undoCount == 0) newUndo();
emit textChanged();
}
/*
void KateDocument::recordReset()
{
if (pseudoModal)
return;
// forces the next call of recordStart() to begin a new undo group
// not used in normal editing, but used by markFound(), etc.
undoType = KateActionGroup::ugNone;
undoCount = 0;
undoView = NULL;
undoReported = false;
printf("recordreset\n");
}
*/
/*
void KateDocument::recordDel(PointStruc &cursor, TextLine::Ptr &textLine, int l) {
int len;
len = textLine->length() - cursor.x;
if (len > l) len = l;
if (len > 0) {
insertUndo(new KateAction(KateAction::replace,cursor,&textLine->getText()[cursor.x],len));
}
}
*/
void KateDocument::doActionGroup(KateActionGroup *g, int flags, bool undo) {
KateAction *a, *next;
setPseudoModal(0L);
if (!(flags & KateView::cfPersistent)) deselectAll();
tagEnd = 0;
tagStart = 0xffffff;
a = g->action;
g->action = 0L;
while (a) {
doAction(a);
next = a->next;
g->insertAction(a);
a = next;
}
optimizeSelection();
if (tagStart <= tagEnd) updateLines(tagStart, tagEnd, flags);
// the undo/redo functions set undo to true, all others should leave it
// alone (default)
if (!undo) {
setModified(true);
newUndo();
}
}
int KateDocument::nextUndoType()
{
KateActionGroup *g;
if (currentUndo <= 0) return KateActionGroup::ugNone;
g = undoList.at(currentUndo - 1);
return g->undoType;
}
int KateDocument::nextRedoType()
{
KateActionGroup *g;
if (currentUndo >= (int) undoList.count()) return KateActionGroup::ugNone;
g = undoList.at(currentUndo);
// if (!g) return KateActionGroup::ugNone;
return g->undoType;
}
void KateDocument::undoTypeList(QValueList<int> &lst)
{
lst.clear();
for (int i = currentUndo-1; i>=0 ;i--)
lst.append(undoList.at(i)->undoType);
}
void KateDocument::redoTypeList(QValueList<int> &lst)
{
lst.clear();
for (int i = currentUndo+1; i<(int)undoList.count(); i++)
lst.append(undoList.at(i)->undoType);
}
void KateDocument::undo(VConfig &c, int count) {
KateActionGroup *g = 0L;
int num;
bool needUpdate = false; // don't update the cursor until completely done
if (count <= 0) return;
for (num = 0 ; num < count ; num++) {
if (currentUndo <= 0) break;
currentUndo--;
g = undoList.at(currentUndo);
doActionGroup(g, c.flags, true); // do not setModified() or newUndo()
needUpdate = true;
// if (num == 0) recordReset();
}
if (needUpdate) {
// since we told doActionGroup() not to do this stuff, we need to do it now
c.view->updateCursor(g->start);
setModified(true);
newUndo();
}
}
void KateDocument::redo(VConfig &c, int count) {
KateActionGroup *g = 0L;
int num;
bool needUpdate = false; // don't update the cursor until completely done
if (count <= 0) return;
for (num = 0 ; num < count ; num++) {
if (currentUndo+1 > (int)undoList.count()) break;
g = undoList.at(currentUndo);
currentUndo++;
doActionGroup(g, c.flags, true); // do not setModified() or newUndo()
needUpdate = true;
// if (num == 0) recordReset();
}
if (needUpdate) {
// since we told doActionGroup() not to do this stuff, we need to do it now
c.view->updateCursor(g->end);
setModified(true);
newUndo();
}
}
void KateDocument::clearRedo() {
// disable redos
// this was added as an assist to the spell checker
bool deleted = false;
while ((int) undoList.count() > currentUndo) {
deleted = true;
undoList.removeLast();
}
if (deleted) newUndo();
}
void KateDocument::setUndoSteps(int steps) {
if (steps < 5) steps = 5;
undoSteps = steps;
}
void KateDocument::setPseudoModal(QWidget *w) {
// QWidget *old = pseudoModal;
// (glenebob)
// this is a temporary hack to make the spell checker work a little
// better - as kspell progresses, this sort of thing should become
// obsolete or worked around more cleanly
// this is relied upon *only* by the spell-check code
if (pseudoModal && pseudoModal != (QWidget*)1L)
delete pseudoModal;
// pseudoModal = 0L;
// if (old || w) recordReset();
pseudoModal = w;
}
void KateDocument::newBracketMark(PointStruc &cursor, BracketMark &bm)
{
TextLine::Ptr textLine;
int x, line, count, attr;
QChar bracket, opposite, ch;
Attribute *a;
bm.eXPos = -1; //mark bracked mark as invalid
x = cursor.x -1; // -1 to look at left side of cursor
if (x < 0) return;
line = cursor.y; //current line
count = 0; //bracket counter for nested brackets
textLine = getTextLine(line);
if (!textLine) return;
bracket = textLine->getChar(x);
attr = textLine->getAttr(x);
if (bracket == '(' || bracket == '[' || bracket == '{')
{
//get opposite bracket
opposite = ')';
if (bracket == '[') opposite = ']';
if (bracket == '{') opposite = '}';
//get attribute of bracket (opposite bracket must have the same attribute)
x++;
while (line - cursor.y < 40) {
//go to next line on end of line
while (x >= (int) textLine->length()) {
line++;
if (line > lastLine()) return;
textLine = getTextLine(line);
x = 0;
}
if (textLine->getAttr(x) == attr) {
//try to find opposite bracked
ch = textLine->getChar(x);
if (ch == bracket) count++; //same bracket : increase counter
if (ch == opposite) {
count--;
if (count < 0) goto found;
}
}
x++;
}
}
else if (bracket == ')' || bracket == ']' || bracket == '}')
{
opposite = '(';
if (bracket == ']') opposite = '[';
if (bracket == '}') opposite = '{';
x--;
while (cursor.y - line < 20) {
while (x < 0) {
line--;
if (line < 0) return;
textLine = getTextLine(line);
x = textLine->length() -1;
}
if (textLine->getAttr(x) == attr) {
ch = textLine->getChar(x);
if (ch == bracket) count++;
if (ch == opposite) {
count--;
if (count < 0) goto found;
}
}
x--;
}
}
return;
found:
//cursor position of opposite bracket
bm.cursor.x = x;
bm.cursor.y = line;
//x position (start and end) of related bracket
bm.sXPos = textWidth(textLine, x);
a = &m_attribs[attr];
if (a->bold && a->italic)
bm.eXPos = bm.sXPos + myFontMetricsBI.width(bracket);
else if (a->bold)
bm.eXPos = bm.sXPos + myFontMetricsBold.width(bracket);
else if (a->italic)
bm.eXPos = bm.sXPos + myFontMetricsItalic.width(bracket);
else
bm.eXPos = bm.sXPos + myFontMetrics.width(bracket);
}
void KateDocument::clipboardChanged() { //slot
//#if defined(_WS_X11_)
if (m_singleSelection) {
disconnect(QApplication::clipboard(), SIGNAL(dataChanged()),
this, SLOT(clipboardChanged()));
deselectAll();
updateViews();
}
//#endif
}
#if 0
void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev )
{
KParts::ReadWritePart::guiActivateEvent( ev );
if ( ev->activated() )
emit selectionChanged();
}
#endif
void KateDocument::setDocName (QString docName)
{
myDocName = docName;
emit nameChanged (this);
}
void KateDocument::setDocFile (QString docFile)
{
m_file = docFile;
emit fileNameChanged ();
}
void KateDocument::setMTime()
{
if (fileInfo && !fileInfo->fileName().isEmpty()) {
fileInfo->refresh();
mTime = fileInfo->lastModified();
}
}
void KateDocument::isModOnHD(bool forceReload)
{
if (fileInfo && !fileInfo->fileName().isEmpty()) {
fileInfo->refresh();
if (fileInfo->lastModified() > mTime) {
if ( forceReload ||
(KMessageBox::warningContinueCancel(0,
(i18n("The file %1 has changed on disk.\nDo you want to reload it?\n\nIf you cancel you will lose these changes next time you save this file")).arg(m_url),
i18n("File has changed on Disk"),
i18n("Yes") ) == KMessageBox::Continue)
)
reloadFile();
else
setMTime();
}
}
}
void KateDocument::reloadFile()
{
#warning fixme
#if 0
if (fileInfo && !fileInfo->fileName().isEmpty()) {
KateDocument::openFile();
setMTime();
}
#endif
}
void KateDocument::slotModChanged()
{
emit modStateChanged (this);
}
QList<Kate::Mark> KateDocument::marks ()
{
QList<Kate::Mark> list;
TextLine::Ptr line;
for (int i=0; i < numLines(); i++)
{
line = getTextLine(i);
if (line->mark() != 0)
{
Kate::Mark *mark=new Kate::Mark;
mark->line = i;
mark->type = line->mark();
list.append (mark);
}
}
return list;
}
void KateDocument::flush ()
{
if (isReadOnly())
return;
m_url = QString::null;
fileInfo->setFile (QString());
setMTime();
clear();
updateViews();
emit fileNameChanged ();
}
void KateDocument::open (const QString &name)
{
openURL (name);
}
void KateDocument::wrapText (uint col)
{
int line = 0;
int z = 0;
while(true)
{
TextLine::Ptr l = getTextLine(line);
if (l->length() > col)
{
TextLine::Ptr tl = new TextLine();
buffer->insertLine(line+1,tl);
const QChar *text = l->getText();
for (z=col; z>0; z--)
{
if (z < 1) break;
if (text[z].isSpace()) break;
}
if (z < 1) z=col;
l->wrap (tl, z);
}
line++;
if (line >= numLines()) break;
};
newDocGeometry=true;
updateLines();
updateViews();
}
void KateDocument::setWordWrap (bool on)
{
if (on != myWordWrap && on)
wrapText (myWordWrapAt);
myWordWrap = on;
}
void KateDocument::setWordWrapAt (uint col)
{
if (myWordWrapAt != col && myWordWrap)
wrapText (myWordWrapAt);
myWordWrapAt = col;
}
void KateDocument::applyWordWrap ()
{
wrapText (myWordWrapAt);
}
diff --git a/noncore/comm/keypebble/krfbdecoder.cpp b/noncore/comm/keypebble/krfbdecoder.cpp
index 837fcc5..27ae101 100644
--- a/noncore/comm/keypebble/krfbdecoder.cpp
+++ b/noncore/comm/keypebble/krfbdecoder.cpp
@@ -1,831 +1,831 @@
#include "krfbconnection.h"
#include "krfbserverinfo.h"
#include "krfbdecoder.h"
#include "krfbbuffer.h"
/* OPIE */
#include <opie2/odebug.h>
using namespace Opie::Core;
/* QT */
#include <qpixmap.h>
/* STD */
#include <assert.h>
//
// Endian stuff
//
//#ifndef OPIE_NO_DEBUG
const int endianTest = 1;
//#endif
#define Swap16IfLE(s) \
(*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
#define Swap32IfLE(l) \
(*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \
(((l) & 0x00ff0000) >> 8) | \
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x000000ff) << 24)) : (l))
//
// The lengths of the messages we need to wait for
//
const int ServerInitLength = 24;
const int UpdateHeaderLength = 4;
const int RectHeaderLength = 12;
const int RectChunkSize = 4;
const int CopyRectPosLength = 4;
const int ServerCutLenLength = 7;
//
// Client -> Server Message Identifiers
//
static CARD8 SetPixelFormatId = 0;
//static CARD8 FixColourMapEntriesId = 1; // Not used
static CARD8 SetEncodingsId = 2;
static CARD8 UpdateRequestId = 3;
static CARD8 KeyEventId = 4;
static CARD8 PointerEventId = 5;
static CARD8 ClientCutTextId = 6;
//
// Server -> Client Message Identifiers
//
static CARD8 UpdateId = 0;
static CARD8 BellId = 2;
static CARD8 ServerCutId = 3;
//
// Encoding identifiers
//
static CARD32 RawEncoding = Swap32IfLE( 0 );
static CARD32 CopyRectEncoding = Swap32IfLE(1 );
static CARD32 RreEncoding = Swap32IfLE( 2 );
static CARD32 CorreEncoding = Swap32IfLE( 4 );
static CARD32 HexTileEncoding = Swap32IfLE( 5 );
static struct {
int keysym;
int keycode;
} keyMap[] = {
{ 0xff08, Qt::Key_Backspace },
{ 0xff09, Qt::Key_Tab },
{ 0xff0d, Qt::Key_Return },
{ 0xff1b, Qt::Key_Escape },
{ 0xff63, Qt::Key_Insert },
{ 0xffff, Qt::Key_Delete },
{ 0xff50, Qt::Key_Home },
{ 0xff57, Qt::Key_End },
{ 0xff55, Qt::Key_Prior },
{ 0xff56, Qt::Key_Next },
{ 0xff51, Qt::Key_Left },
{ 0xff52, Qt::Key_Up },
{ 0xff53, Qt::Key_Right },
{ 0xff54, Qt::Key_Down },
{ 0xffbe, Qt::Key_F1 },
{ 0xffbf, Qt::Key_F2 },
{ 0xffc0, Qt::Key_F3 },
{ 0xffc1, Qt::Key_F4 },
{ 0xffc2, Qt::Key_F5 },
{ 0xffc3, Qt::Key_F6 },
{ 0xffc4, Qt::Key_F7 },
{ 0xffc5, Qt::Key_F8 },
{ 0xffc6, Qt::Key_F9 },
{ 0xffc7, Qt::Key_F10 },
{ 0xffc8, Qt::Key_F11 },
{ 0xffc9, Qt::Key_F12 },
{ 0xffe1, Qt::Key_Shift },
{ 0xffe2, Qt::Key_Shift },
{ 0xffe3, Qt::Key_Control },
{ 0xffe4, Qt::Key_Control },
{ 0xffe7, Qt::Key_Meta },
{ 0xffe8, Qt::Key_Meta },
{ 0xffe9, Qt::Key_Alt },
{ 0xffea, Qt::Key_Alt },
{ 0, 0 }
};
KRFBDecoder::KRFBDecoder( KRFBConnection *con )
: QObject( con, "RFB Decoder" )
{
assert( con );
assert( con->state() == KRFBConnection::Connected );
this->con = con;
this->buf = 0;
this->info = 0;
this->format = 0;
this->buttonMask = 0;
currentState = Idle;
}
KRFBDecoder::~KRFBDecoder()
{
if ( info )
delete info;
if ( format )
delete format;
}
void KRFBDecoder::start()
{
sendClientInit();
}
void KRFBDecoder::sendClientInit()
{
con->write( &( con->options()->shared ), 1 );
// Wait for server init
owarn << "Waiting for server init" << oendl;
static QString statusMsg = tr( "Waiting for server initialization..." );
emit status( statusMsg );
currentState = AwaitingServerInit;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerInit() ) );
con->waitForData( ServerInitLength );
}
void KRFBDecoder::gotServerInit()
{
owarn << "Got server init" << oendl;
disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerInit() ) );
if ( info )
delete info;
info = new KRFBServerInfo;
CHECK_PTR( info );
con->read( &(info->width), 2 );
info->width = Swap16IfLE( info->width );
con->read( &info->height, 2 );
info->height = Swap16IfLE( info->height );
con->read( &(info->bpp), 1 );
con->read( &(info->depth), 1 );
con->read( &(info->bigEndian), 1 );
con->read( &(info->trueColor), 1 );
con->read( &(info->redMax), 2 );
info->redMax = Swap16IfLE( info->redMax );
con->read( &(info->greenMax), 2 );
info->greenMax = Swap16IfLE( info->greenMax );
con->read( &(info->blueMax), 2 );
info->blueMax = Swap16IfLE( info->blueMax );
con->read( &(info->redShift), 1 );
con->read( &(info->greenShift), 1 );
con->read( &(info->blueShift), 1 );
con->read( info->padding, 3 );
con->read( &(info->nameLength), 4 );
info->nameLength = Swap32IfLE( info->nameLength );
owarn << "Width = " << info->width << ", Height = " << info->height << "" << oendl;
owarn << "Bpp = " << info->bpp << ", Depth = " << info->depth << ", Big = " << info->bigEndian
<< ", True = " << info->trueColor << oendl;
owarn << "RedMax = " << info->redMax << ", GreenMax = " << info->greenMax << ", BlueMax = " << info->blueMax << oendl;
owarn << "RedShift = " << info->redShift << ", GreenShift = " << info->greenShift
<< ", BlueShift = " << info-> blueShift << oendl;
buf->resize( info->width/con->options()->scaleFactor, info->height /con->options()->scaleFactor);
// Wait for desktop name
owarn << "Waiting for desktop name" << oendl;
static QString statusMsg = tr( "Waiting for desktop name..." );
emit status( statusMsg );
currentState = AwaitingDesktopName;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotDesktopName() ) );
con->waitForData( info->nameLength );
}
void KRFBDecoder::gotDesktopName()
{
assert( info );
assert( currentState == AwaitingDesktopName );
owarn << "Got desktop name" << oendl;
disconnect( con, SIGNAL( gotEnoughData() ),
this, SLOT( gotDesktopName() ) );
char *buf = new char[ info->nameLength + 1 ];
CHECK_PTR( buf );
con->read( buf, info->nameLength );
buf[ info->nameLength ] = '\0';
info->name = buf;
owarn << "Desktop: " << info->name.latin1() << "" << oendl;
- delete buf;
+ delete [] buf;
// Get the format we'll really use and tell the server
decidePixelFormat();
sendPixelFormat();
sendAllowedEncodings();
currentState = Idle;
QString msg;
msg = tr( "Connected to %1" );
msg = msg.arg( info->name );
emit status( msg );
sendUpdateRequest( false );
}
void KRFBDecoder::decidePixelFormat()
{
assert( info );
if ( format )
delete format;
format = new KRFBPixelFormat;
CHECK_PTR( format );
// What depth do we want?
//
// We'll use the minimum of the remote and local depths, UNLESS an
// eight bit session has been specifically requested by the user.
int screenDepth = QPixmap::defaultDepth();
int bestDepth = ( screenDepth > info->depth ) ? info->depth : screenDepth;
int chosenDepth;
if ( con->options()->colors256 )
chosenDepth = 8;
else
chosenDepth = bestDepth;
owarn << "Screen depth=" << screenDepth << ", server depth=" << info->depth
<< ", best depth=" << bestDepth << "eight bit " << con->options()->colors256
<< ", chosenDepth=" << chosenDepth << oendl;
format->depth = chosenDepth;
// If we're using the servers native depth
if ( chosenDepth == info->depth ) {
// Use the servers native format
format->bpp = info->bpp;
// format->bigEndian = info->bigEndian;
format->bigEndian = true;
format->trueColor = info->trueColor;
format->redMax = info->redMax;
format->greenMax = info->greenMax;
format->blueMax = info->blueMax;
format->redShift = info->redShift;
format->greenShift = info->greenShift;
format->blueShift = info->blueShift;
}
else {
if ( chosenDepth == 8 ) {
format->bpp = 8;
format->bigEndian = true;
format->trueColor = true;
format->redMax = 7;
format->greenMax = 7;
format->blueMax = 3;
format->redShift = 0;
format->greenShift = 3;
format->blueShift = 6;
}
}
format->redMax = Swap16IfLE( format->redMax );
format->greenMax = Swap16IfLE( format->greenMax );
format->blueMax = Swap16IfLE( format->blueMax );
}
void KRFBDecoder::sendPixelFormat()
{
static char padding[3];
con->write( &SetPixelFormatId, 1 );
con->write( padding, 3 );
con->write( &(format->bpp), 1 );
con->write( &(format->depth), 1 );
con->write( &(format->bigEndian), 1 );
con->write( &(format->trueColor), 1 );
con->write( &(format->redMax), 2 );
con->write( &(format->greenMax), 2 );
con->write( &(format->blueMax), 2 );
con->write( &(format->redShift), 1 );
con->write( &(format->greenShift), 1 );
con->write( &(format->blueShift), 1 );
con->write( format->padding, 3 ); // Padding
}
void KRFBDecoder::sendAllowedEncodings()
{
static CARD8 padding[1];
con->write( &SetEncodingsId, 1 );
con->write( padding, 1 );
CARD16 noEncodings = con->options()->encodings();
noEncodings = Swap16IfLE( noEncodings );
con->write( &noEncodings, 2 );
if ( con->options()->corre )
con->write( &CorreEncoding, 4 );
if ( con->options()->hexTile )
con->write( &HexTileEncoding, 4 );
if ( con->options()->rre )
con->write( &RreEncoding, 4 );
if ( con->options()->copyrect )
con->write( &CopyRectEncoding, 4 );
// We always support this
con->write( &RawEncoding, 4 );
}
void KRFBDecoder::sendUpdateRequest( bool incremental )
{
if ( currentState != Idle )
return;
con->write( &UpdateRequestId, 1 );
con->write( &incremental, 1 );
static CARD16 x = 0, y = 0;
static CARD16 w = Swap16IfLE( info->width );
static CARD16 h = Swap16IfLE( info->height );
con->write( &x, 2 );
con->write( &y, 2 );
con->write( &w, 2 );
con->write( &h, 2 );
// Now wait for the update
currentState = AwaitingUpdate;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) );
con->waitForData( UpdateHeaderLength );
}
void KRFBDecoder::gotUpdateHeader()
{
assert( currentState == AwaitingUpdate );
// owarn << "Got update header" << oendl;
disconnect( con, SIGNAL( gotEnoughData() ),
this, SLOT( gotUpdateHeader() ) );
CARD8 msgType;
con->read( &msgType, 1 );
if ( msgType != UpdateId ) {
// We might have a bell or server cut
if ( msgType == ServerCutId ) {
oldState = currentState;
gotServerCut();
}
else if ( msgType == BellId ) {
oldState = currentState;
gotBell();
}
else {
int msg = msgType;
QString protocolError = tr( "Protocol Error: Message Id %1 was "
"found when expecting an update "
"message." ).arg( msg );
currentState = Error;
emit error( protocolError );
}
return;
}
CARD8 padding;
con->read( &padding, 1 );
con->read( &noRects, 2 );
noRects = Swap16IfLE( noRects );
// owarn << "Expecting " << noRects << " rects" << oendl;
// Now wait for the data
currentState = AwaitingRectHeader;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) );
con->waitForData( RectHeaderLength );
}
void KRFBDecoder::gotRectHeader()
{
assert( currentState == AwaitingRectHeader );
// owarn << "Got rect header" << oendl;
disconnect( con, SIGNAL( gotEnoughData() ),
this, SLOT( gotRectHeader() ) );
con->read( &x, 2 );
x = Swap16IfLE( x );
con->read( &y, 2 );
y = Swap16IfLE( y );
con->read( &w, 2 );
w = Swap16IfLE( w );
con->read( &h, 2 );
h = Swap16IfLE( h );
con->read( &encoding, 4 );
// CARD32 encodingLocal = Swap32IfLE( encoding );
// owarn << "Rect: x=" << x << ", y= " << y << ", w=" << w << ", h=" << h
// << ", encoding= " << encodingLocal << oendl;
//
// Each encoding needs to be handled differently. Some require
// waiting for more data, but others like a copyrect do not.
// Our constants have already been byte swapped, so we use
// the remote value as is.
//
if ( encoding == RawEncoding ) {
// owarn << "Raw encoding" << oendl;
handleRawRect();
}
else if ( encoding == CopyRectEncoding ) {
// owarn << "CopyRect encoding" << oendl;
handleCopyRect();
}
else if ( encoding == RreEncoding ) {
owarn << "RRE encoding" << oendl;
handleRRERect();
}
else if ( encoding == CorreEncoding ) {
owarn << "CoRRE encoding" << oendl;
handleCoRRERect();
}
else if ( encoding == HexTileEncoding ) {
owarn << "HexTile encoding" << oendl;
handleHexTileRect();
}
else {
int msg = Swap32IfLE( encoding );
QString protocolError = tr( "Protocol Error: An unknown encoding was "
"used by the server %1" ).arg( msg );
currentState = Error;
owarn << "Unknown encoding, " << msg << "" << oendl;
emit error( protocolError );
return;
}
}
//
// Raw Encoding
//
void KRFBDecoder::handleRawRect()
{
// We need something a bit cleverer here to handle large
// rectanges nicely. The chunking should be based on the
// overall size (but has to be in complete lines).
// owarn << "Handling a raw rect chunk" << oendl;
// CARD32 lineCount = w * format->bpp / 8;
if ( h > RectChunkSize ) {
// if ( con->sock->size() / lineCount ) {
// getRawRectChunk( con->sock->size() / lineCount );
// }
// else {
getRawRectChunk( RectChunkSize );
// }
}
else {
getRawRectChunk( h );
}
}
void KRFBDecoder::getRawRectChunk( int lines )
{
this->lines = lines;
CARD32 count = lines * w * format->bpp / 8;
// Wait for server init
// owarn << "Waiting for raw rect chunk, " << count << "" << oendl;
currentState = AwaitingRawRectChunk;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRawRectChunk() ) );
con->waitForData( count );
}
void KRFBDecoder::gotRawRectChunk()
{
assert( currentState == AwaitingRawRectChunk );
disconnect( con, SIGNAL( gotEnoughData() ),
this, SLOT( gotRawRectChunk() ) );
// owarn << "Got raw rect chunk" << oendl;
//
// Read the rect data and copy it to the buffer.
//
// TODO: Replace this!
int count = lines * w * format->bpp / 8;
char *hack = new char[ count ];
con->read( hack, count );
buf->drawRawRectChunk( hack, x, y, w, lines );
- delete hack;
+ delete [] hack;
// /TODO:
h = h - lines;
y = y + lines;
if ( h > 0 ) {
handleRawRect();
}
else {
noRects--;
// owarn << "There are " << noRects << " rects left" << oendl;
if ( noRects ) {
currentState = AwaitingRectHeader;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) );
con->waitForData( RectHeaderLength );
}
else {
// we are now ready for the next update - no need to wait for the timer
currentState = Idle;
sendUpdateRequest (1);
}
}
}
//
// Copy Rectangle Encoding
//
void KRFBDecoder::handleCopyRect()
{
currentState = AwaitingCopyRectPos;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotCopyRectPos() ) );
con->waitForData( CopyRectPosLength );
}
void KRFBDecoder::gotCopyRectPos()
{
disconnect( con, SIGNAL( gotEnoughData() ),
this, SLOT( gotCopyRectPos() ) );
CARD16 srcX;
CARD16 srcY;
con->read( &srcX, 2 );
con->read( &srcY, 2 );
srcX = Swap16IfLE( srcX );
srcY = Swap16IfLE( srcY );
buf->copyRect( srcX, srcY, x, y, w, h );
noRects--;
// owarn << "There are " << noRects << " rects left" << oendl;
if ( noRects ) {
currentState = AwaitingRectHeader;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) );
con->waitForData( RectHeaderLength );
}
else
currentState = Idle;
}
void KRFBDecoder::handleRRERect()
{
owarn << "RRE not implemented" << oendl;
}
void KRFBDecoder::handleCoRRERect()
{
owarn << "CoRRE not implemented" << oendl;
}
void KRFBDecoder::handleHexTileRect()
{
owarn << "HexTile not implemented" << oendl;
}
void KRFBDecoder::sendMouseEvent( QMouseEvent *e )
{
// Deal with the buttons
if ( e->type() != QEvent::MouseMove ) {
buttonMask = 0;
if ( e->type() == QEvent::MouseButtonPress ) {
if ( e->button() & LeftButton )
buttonMask |= 0x01;
if ( e->button() & MidButton )
buttonMask |= 0x04;
if ( e->button() & RightButton )
buttonMask |= 0x02;
}
else if ( e->type() == QEvent::MouseButtonRelease ) {
if ( e->button() & LeftButton )
buttonMask &= 0x06;
if ( e->button() & MidButton )
buttonMask |= 0x03;
if ( e->button() & RightButton )
buttonMask |= 0x05;
}
}
// HACK: Scaling
CARD16 x = Swap16IfLE( e->x() * con->options()->scaleFactor );
CARD16 y = Swap16IfLE( e->y() * con->options()->scaleFactor );
con->write( &PointerEventId, 1 );
con->write( &buttonMask, 1 );
con->write( &x, 2 );
con->write( &y, 2 );
}
void KRFBDecoder::sendCutEvent( const QString &unicode )
{
//
// Warning: There is a bug in the RFB protocol because there is no way to find
// out the codepage in use on the remote machine. This could be fixed by requiring
// the remote server to use utf8 etc. but for now we have to assume they're the
// same. I've reported this problem to the ORL guys, but they apparantly have no
// immediate plans to fix the issue. :-( (rich)
//
CARD8 padding[3];
QCString text = unicode.local8Bit();
CARD32 length = text.length();
length = Swap32IfLE( length );
con->write( &ClientCutTextId, 1 );
con->write( &padding, 3 );
con->write( &length, 4 );
con->write( text.data(), length );
}
void KRFBDecoder::gotServerCut()
{
owarn << "Got server cut" << oendl;
currentState = AwaitingServerCutLength;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutLength() ) );
con->waitForData( ServerCutLenLength );
}
void KRFBDecoder::gotServerCutLength()
{
assert( currentState = AwaitingServerCutLength );
disconnect( con, SIGNAL( gotEnoughData() ),
this, SLOT( gotServerCutLength() ) );
CARD8 padding[3];
con->read( padding, 3 );
con->read( &serverCutTextLen, 4 );
serverCutTextLen = Swap32IfLE( serverCutTextLen );
currentState = AwaitingServerCutText;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutText() ) );
con->waitForData( serverCutTextLen );
}
void KRFBDecoder::gotServerCutText()
{
assert( currentState = AwaitingServerCutText );
disconnect( con, SIGNAL( gotEnoughData() ),
this, SLOT( gotServerCutText() ) );
//
// Warning: There is a bug in the RFB protocol because there is no way to find
// out the codepage in use on the remote machine. This could be fixed by requiring
// the remote server to use utf8 etc. but for now we have to assume they're the
// same. I've reported this problem to the ORL guys, but they apparantly have no
// immediate plans to fix the issue. :-( (rich)
//
char *cutbuf = new char[ serverCutTextLen + 1 ];
CHECK_PTR( cutbuf );
con->read( cutbuf, serverCutTextLen );
cutbuf[ serverCutTextLen ] = '\0';
/* For some reason QApplication::clipboard()->setText() segfaults when called
* from within keypebble's mass of signals and slots
owarn << "Server cut: " << cutbuf << "" << oendl;
QString cutText( cutbuf ); // DANGER!!
qApp->clipboard()->setText( cutText );
*/
- delete cutbuf;
+ delete [] cutbuf;
// Now wait for the update (again)
if ( oldState == AwaitingUpdate ) {
currentState = AwaitingUpdate;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) );
con->waitForData( UpdateHeaderLength );
}
else if ( oldState == Idle ) {
currentState = Idle;
}
else {
owarn << "Async handled in weird state" << oendl;
currentState = oldState;
};
}
void KRFBDecoder::gotBell()
{
owarn << "Got server bell" << oendl;
buf->soundBell();
// Now wait for the update (again)
if ( oldState == AwaitingUpdate ) {
currentState = AwaitingUpdate;
connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) );
con->waitForData( UpdateHeaderLength );
}
else if ( oldState == Idle ) {
currentState = Idle;
}
else {
owarn << "Async handled in weird state" << oendl;
currentState = oldState;
};
}
void KRFBDecoder::sendKeyPressEvent( QKeyEvent *event )
{
int key;
key = toKeySym( event );
if ( key ) {
key = Swap32IfLE( key );
CARD8 mask = true;
CARD16 padding = 0;
con->write( &KeyEventId, 1 );
con->write( &mask, 1 );
con->write( &padding, 2 );
con->write( &key, 4 );
}
}
void KRFBDecoder::sendKeyReleaseEvent( QKeyEvent *event )
{
int key;
key = toKeySym( event );
if ( key ) {
key = Swap32IfLE( key );
CARD8 mask = false;
CARD16 padding = 0;
con->write( &KeyEventId, 1 );
con->write( &mask, 1 );
con->write( &padding, 2 );
con->write( &key, 4 );
}
}
//
// The RFB protocol spec says 'For most ordinary keys, the 'keysym'
// is the same as the corresponding ASCII value.', but doesn't
// elaborate what the most ordinary keys are. The spec also lists
// a set (possibly subset, it's unspecified) of mappings for
// "other common keys" (backspace, tab, return, escape, etc).
//
int KRFBDecoder::toKeySym( QKeyEvent *k )
{
//
// Try and map these "other common keys" first.
//
if ((k->key() >= Qt::Key_Escape) && (k->key() <= Qt::Key_F12)) {
for(int i = 0; keyMap[i].keycode != 0; i++) {
if (k->key() == keyMap[i].keycode) {
return keyMap[i].keysym;
}
}
}
//
// If these keys aren't matched, return the ascii code and let the
// server figure it out. We don't return k->key(), as the data in
// key differs between input methods, and we don't want special cases.
//
return k->ascii();
}
diff --git a/noncore/games/sfcave/sfcave.cpp b/noncore/games/sfcave/sfcave.cpp
index a6c92a0..516dc93 100644
--- a/noncore/games/sfcave/sfcave.cpp
+++ b/noncore/games/sfcave/sfcave.cpp
@@ -1,1211 +1,1211 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <opie2/oapplicationfactory.h>
#include <qpe/qpeapplication.h>
#include <qpe/config.h>
#include <qpe/global.h>
#include <qdir.h>
#include "helpwindow.h"
#include "sfcave.h"
#define CAPTION "SFCave 1.13 by AndyQ"
#define UP_THRUST 0.6
#define NO_THRUST 0.8
#define MAX_DOWN_THRUST 4.0
#define MAX_UP_THRUST -3.5
// States
#define STATE_BOSS 0
#define STATE_RUNNING 1
#define STATE_CRASHING 2
#define STATE_CRASHED 3
#define STATE_NEWGAME 4
#define STATE_MENU 5
#define STATE_REPLAY 6
// Menus
#define MENU_MAIN_MENU 0
#define MENU_OPTIONS_MENU 1
#define MENU_REPLAY_MENU 2
// Main Menu Options
#define MENU_START_GAME 0
#define MENU_REPLAY 1
#define MENU_OPTIONS 2
#define MENU_HELP 3
#define MENU_QUIT 4
// Option Menu Options
#define MENU_GAME_TYPE 0
#define MENU_GAME_DIFFICULTY 1
#define MENU_CLEAR_HIGHSCORES 2
#define MENU_BACK 3
// Replay Menu Options
#define MENU_REPLAY_START 0
#define MENU_REPLAY_LOAD 1
#define MENU_REPLAY_SAVE 2
#define MENU_REPLAY_BACK 3
#define NR_GAME_DIFFICULTIES 3
#define NR_GAME_TYPES 3
#define DIFICULTY_EASY 0
#define DIFICULTY_NORMAL 1
#define DIFICULTY_HARD 2
#define EASY "Easy"
#define NORMAL "Normal"
#define HARD "Hard"
#define SFCAVE_GAME_TYPE 0
#define GATES_GAME_TYPE 1
#define FLY_GAME_TYPE 2
#define SFCAVE_GAME "SFCave"
#define GATES_GAME "Gates"
#define FLY_GAME "Fly"
#define CURRENT_GAME_TYPE gameTypes[currentGameType]
#define CURRENT_GAME_DIFFICULTY difficultyOption[currentGameDifficulty];
QString SFCave::dificultyOption[] = { EASY, NORMAL, HARD };
QString SFCave::gameTypes[] = { SFCAVE_GAME, GATES_GAME, FLY_GAME };
QString SFCave::menuOptions[NR_MENUS][MAX_MENU_OPTIONS] = { { "Start Game", "Replays", "Options", "Help", "Quit", "", "", "" },
{ "Game Type - %s", "Game Difficulty - %s", "Clear High Scores for this game", "Back", "", "", "", "" },
{ "Play Reply", "Load Replay", "Save Replay", "Back", "", "", "", "" } };
int SFCave::nrMenuOptions[NR_MENUS] = { 5, 4, 4 };
int SFCave ::currentMenuOption[NR_MENUS] = { 0, 0, 0 };
#define UP_THRUST 0.6
#define NO_THRUST 0.8
#define MAX_DOWN_THRUST 4.0
#define MAX_UP_THRUST -3.5
double SFCave::UpThrustVals[3][3] = {{ 0.6, 0.6, 0.6 }, // SFCave
{ 0.6, 0.6, 0.8 }, // Gates
{ 0.4, 0.7, 1.0 } }; // Fly
double SFCave::DownThrustVals[3][3] = {{ 0.8, 0.8, 0.8 }, // SFCave
{ 0.8, 0.8, 1.0 }, // Gates
{ 0.4, 0.7, 1.0 } }; // Fly
double SFCave::MaxUpThrustVals[3][3] = {{ -3.5, -3.5, -3.5 }, // SFCave
{ -3.5, -4.0, -5.0 }, // Gates
{ -3.5, -4.0, -5.0 } }; // Fly
double SFCave::MaxDownThrustVals[3][3] = {{ 4.0, 4.0, 4.0 }, // SFCave
{ 4.0, 5.0, 5.5 }, // Gates
{ 3.5, 4.0, 5.0 } }; // Fly
int SFCave::flyEasyScores[7][3] = { { 0, 10, 5 },
{ 10, 20, 3 },
{ 20, 30, 2 },
{ 30, 40, 1 },
{ 50, 70, -2 },
{ 70, 300, -5 },
{ -1, -1, -1 } };
int SFCave::flyNormalScores[7][3] = { { 0, 10, 5 },
{ 10, 20, 3 },
{ 20, 30, 2 },
{ 30, 40, 1 },
{ 50, 70, -2 },
{ 70, 300, -5 },
{ -1, -1, -1 } };
int SFCave::flyHardScores[7][3] = { { 0, 20, 5 },
{ 20, 40, 3 },
{ 40, 100, 1 },
{ 100, 150, -2 },
{ 150, 300, -5 },
{ -1, -1, -1 } };
int SFCave::initialGateGaps[] = { 75, 50, 25 };
#define FLYSCORES( x, y ) (*(flyScores + ((x)*3) + y))
bool movel;
OPIE_EXPORT_APP( Opie::Core::OApplicationFactory<SFCave> )
SFCave :: SFCave( QWidget *w, const char *name, WFlags fl )
: QMainWindow( w, name, fl )
{
showMaximized();
movel = true;
int spd = 3;
replayIt = 0;
replayFile = Global::applicationFileName("sfcave", "replay");
sWidth = width();
sHeight = height();
segSize = sWidth/(MAPSIZE-1)+1;
currentMenuNr = 0;
currentGameType = 0;
currentGameDifficulty = 0;
setCaption( CAPTION );
showScoreZones = false;
#ifdef QWS
Config cfg( "sfcave" );
cfg.setGroup( "settings" );
QString key = "highScore_";
for ( int i = 0 ; i < 3 ; ++i )
{
for ( int j = 0 ; j < 3 ; ++j )
highestScore[i][j] = cfg.readNumEntry( key + gameTypes[i] + "_" + dificultyOption[j], 0 );
}
currentGameType = cfg.readNumEntry( "gameType", 0 );
currentGameDifficulty = cfg.readNumEntry( "difficulty", 0 );
#endif
speed = spd; // Change to 2 for PC
press = false;
showEyeCandy = false;
offscreen = new QPixmap( sWidth, sHeight );
offscreen->fill( Qt::black );
// setUp();
crashLineLength = -1;
state = STATE_MENU;
prevState = STATE_MENU;
gameTimer = new QTimer( this, "game timer" );
connect( gameTimer, SIGNAL( timeout() ),
this, SLOT( run() ) );
QTimer::singleShot(0, this, SLOT(start()));
}
SFCave :: ~SFCave()
{
}
void SFCave :: start()
{
gameTimer->start( 10 );
}
void SFCave :: setSeed( int seed )
{
if ( seed == -1 )
currentSeed = ((unsigned long) time((time_t *) NULL));
else
currentSeed = seed;
PutSeed( currentSeed );
}
int SFCave :: nextInt( int range )
{
int val = (int)(Random( ) * range);
return val;
}
void SFCave :: setUp()
{
score = 0;
offset = 0;
nrFrames = 0;
dir = 1;
thrust = 0;
startScoring = false;
press = false;
if ( CURRENT_GAME_TYPE == SFCAVE_GAME )
{
thrustUp = UpThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
noThrust = DownThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
maxUpThrust = MaxUpThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
maxDownThrust = MaxDownThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
if ( currentGameDifficulty == DIFICULTY_EASY )
gateDistance = 100;
else if ( currentGameDifficulty == DIFICULTY_NORMAL )
gateDistance = 60;
else
gateDistance = 40;
}
else if ( CURRENT_GAME_TYPE == GATES_GAME )
{
thrustUp = UpThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
noThrust = DownThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
maxUpThrust = MaxUpThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
maxDownThrust = MaxDownThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
gateDistance = 75;
nextGate = nextInt( 50 ) + gateDistance;
}
else
{
thrustUp = UpThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
noThrust = DownThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
maxUpThrust = MaxUpThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
maxDownThrust = MaxDownThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
if ( currentGameDifficulty == DIFICULTY_EASY )
flyScores = (int*)flyEasyScores;
else if ( currentGameDifficulty == DIFICULTY_NORMAL )
flyScores = (int*)flyNormalScores;
else
flyScores = (int*)flyHardScores;
}
crashLineLength = 0;
lastGateBottomY = 0;
user.setRect( 50, sWidth/2, 4, 4 );
blockWidth = 20;
blockHeight = 70;
gapHeight = initialGateGaps[currentGameDifficulty];
for ( int i = 0 ; i < TRAILSIZE ; ++i )
{
trail[i].setX( -1 );
trail[i].setY( 0 );
}
if ( CURRENT_GAME_TYPE != FLY_GAME )
{
maxHeight = 50;
mapTop[0] = (int)(nextInt(50)) + 5;
mapBottom[0] = (int)(nextInt(50)) + 5;
for ( int i = 1 ; i < MAPSIZE ; ++i )
setPoint( i );
}
else
{
maxHeight = 100;
for ( int i = 0 ; i < MAPSIZE ; ++i )
mapBottom[i] = sHeight - 10;
}
for ( int i = 0 ; i < BLOCKSIZE ; ++i )
blocks[i].setY( -1 );
}
void SFCave :: run()
{
switch ( state )
{
case STATE_MENU:
displayMenu();
break;
case STATE_NEWGAME:
setSeed( -1 );
setUp();
draw();
state = STATE_RUNNING;
replay = false;
replayList.clear();
break;
case STATE_REPLAY:
setSeed( currentSeed );
setUp();
draw();
state = STATE_RUNNING;
replay = true;
if ( replayIt )
delete replayIt;
replayIt = new QListIterator<int>( replayList );
break;
case STATE_BOSS:
drawBoss();
break;
case STATE_CRASHING:
case STATE_CRASHED:
press = false;
draw();
break;
case STATE_RUNNING:
{
if ( nrFrames % 2 == 0 )
handleKeys();
// Apply Game rules
nrFrames ++;
if ( replay )
{
while( replayIt->current() && *(replayIt->current()) == nrFrames )
{
press = !press;
++(*replayIt);
}
}
if ( CURRENT_GAME_TYPE == SFCAVE_GAME )
handleGameSFCave();
else if ( CURRENT_GAME_TYPE == GATES_GAME )
handleGameGates();
else if ( CURRENT_GAME_TYPE == FLY_GAME )
handleGameFly();
draw();
break;
}
}
}
void SFCave :: handleGameSFCave()
{
// Update score
if ( nrFrames % 5 == 0 )
score ++;
if ( nrFrames % 500 == 0 )
{
if ( maxHeight < sHeight - 100 )
{
maxHeight += 10;
// Reduce block height
if ( maxHeight > sHeight - 150 )
blockHeight -= 5;
}
}
if ( nrFrames % gateDistance == 0 )
addBlock();
if ( checkCollision() )
{
if ( score > highestScore[currentGameType][currentGameDifficulty] )
{
highestScore[currentGameType][currentGameDifficulty] = score;
saveScore();
}
state = STATE_CRASHING;
}
else
{
moveLandscape();
}
}
void SFCave :: handleGameGates()
{
// Update score
if ( nrFrames % 5 == 0 )
score ++;
// Slightly random gap distance
if ( nrFrames >= nextGate )
{
nextGate = nrFrames + nextInt( 50 ) + gateDistance;
addGate();
}
if ( nrFrames % 500 == 0 )
{
if ( gapHeight > 75 )
gapHeight -= 5;
}
if ( checkCollision() )
{
if ( score > highestScore[currentGameType][currentGameDifficulty] )
{
highestScore[currentGameType][currentGameDifficulty] = score;
saveScore();
}
state = STATE_CRASHING;
}
else
{
moveLandscape();
}
}
void SFCave :: handleGameFly()
{
int diff = mapBottom[10] - user.y();
if ( nrFrames % 4 == 0 )
{
if ( !startScoring )
{
if ( diff < 40 )
startScoring = true;
}
if ( startScoring )
{
// Update score
// get distance between landscape and ship
// the closer the difference is to 0 means more points
for ( int i = 0 ; i < 10 && FLYSCORES( i, 0 ) != -1 ; ++i )
{
if ( FLYSCORES( i, 0 ) <= diff && FLYSCORES(i, 1 ) > diff )
{
score += FLYSCORES( i, 2 );
break;
}
}
}
}
if ( checkFlyGameCollision() )
{
if ( score > highestScore[currentGameType][currentGameDifficulty] )
{
highestScore[currentGameType][currentGameDifficulty] = score;
saveScore();
}
state = STATE_CRASHING;
}
else
{
moveFlyGameLandscape();
}
}
bool SFCave :: checkFlyGameCollision()
{
if ( (user.y() + user.width()) >= mapBottom[11] )
return true;
return false;
}
void SFCave :: moveFlyGameLandscape()
{
offset++;
if ( offset >= segSize )
{
offset = 0;
for ( int i = 0 ; i < MAPSIZE-speed ; ++i )
mapBottom[i] = mapBottom[i+speed];
for ( int i = speed ; i > 0 ; --i )
setFlyPoint( MAPSIZE-i );
}
}
void SFCave :: setFlyPoint( int point )
{
static int fly_difficulty_levels[] = { 5, 10, 15 };
if ( nextInt(100) >= 75 )
dir *= -1;
int prevPoint = mapBottom[point-1];
int nextPoint = prevPoint + (dir * nextInt( fly_difficulty_levels[currentGameDifficulty] ) );
if ( nextPoint > sHeight )
{
nextPoint = sHeight;
dir *= -1;
}
else if ( nextPoint < maxHeight )
{
nextPoint = maxHeight;
dir *= 1;
}
mapBottom[point] = nextPoint;
}
bool SFCave :: checkCollision()
{
if ( (user.y() + user.width()) >= mapBottom[11] || user.y() <= mapTop[11] )
return true;
for ( int i = 0 ; i < BLOCKSIZE ; ++i )
{
if ( blocks[i].y() != -1 )
{
if ( blocks[i].intersects( user ) )
return true;
}
}
return false;
}
void SFCave :: moveLandscape()
{
offset++;
if ( offset >= segSize )
{
offset = 0;
for ( int i = 0 ; i < MAPSIZE-speed ; ++i )
{
mapTop[i] = mapTop[i+speed];
mapBottom[i] = mapBottom[i+speed];
}
for ( int i = speed ; i > 0 ; --i )
setPoint( MAPSIZE-i );
}
for ( int i = 0 ; i < BLOCKSIZE ; ++i )
{
if ( blocks[i].y() != -1 )
{
blocks[i].moveBy( -speed, 0 );
if ( blocks[i].x() + blocks[i].width() < 0 )
blocks[i].setY( -1 );
}
}
}
void SFCave :: addBlock()
{
for ( int i = 0 ; i < BLOCKSIZE ; ++i )
{
if ( blocks[i].y() == -1 )
{
int x = sWidth;
int y = mapTop[50] + (int)(nextInt(mapBottom[50] - mapTop[50] - blockHeight));
blocks[i].setRect( x, y, blockWidth, blockHeight );
break;
}
}
}
void SFCave :: addGate()
{
for ( int i = 0 ; i < BLOCKSIZE ; ++i )
{
if ( blocks[i].y() == -1 )
{
int x1 = sWidth;
int y1 = mapTop[50];
int b1Height = nextInt(mapBottom[50] - mapTop[50] - gapHeight);
// See if height between last gate and this one is too big
if ( b1Height - 100 > lastGateBottomY )
b1Height -= 25;
else if ( b1Height + 100 < lastGateBottomY )
b1Height += 25;
lastGateBottomY = b1Height;
int x2 = sWidth;
int y2 = y1 + b1Height + gapHeight;
int b2Height = mapBottom[50] - y2;
blocks[i].setRect( x1, y1, blockWidth, b1Height );
blocks[i+1].setRect( x2, y2, blockWidth, b2Height );
break;
}
}
}
void SFCave :: setPoint( int point )
{
if ( nextInt(100) >= 80 )
dir *= -1;
mapTop[point] = mapTop[point-1] + (dir * nextInt( 5 ) );
if ( mapTop[point] < 0 )
{
mapTop[point] = 0;
dir *= -1;
}
else if ( mapTop[point] >= maxHeight )
{
mapTop[point] = maxHeight;
dir *= -1;
}
// mapBottom[point] = sHeight - (maxHeight - mapBottom[point]);
mapBottom[point] = sHeight - (maxHeight - mapTop[point]);
}
void SFCave :: drawBoss()
{
offscreen->fill( Qt::black );
bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true );
}
void SFCave :: draw()
{
//printf( "Paint\n" );
offscreen->fill( Qt::black );
QPainter p( offscreen );
QFontMetrics fm = p.fontMetrics();
p.setPen( Qt::white );
for ( int i = 0 ; i < MAPSIZE -3; ++i )
{
// Only display top landscape if not running FLY_GAME
if ( CURRENT_GAME_TYPE != FLY_GAME )
p.drawLine( (i*segSize) - (offset*speed), mapTop[i], ((i+1)*segSize)-(offset*speed), mapTop[i+1] );
p.drawLine( (i*segSize) - (offset*speed), mapBottom[i], ((i+1)*segSize)-(offset*speed), mapBottom[i+1] );
if ( CURRENT_GAME_TYPE == FLY_GAME && showScoreZones )
{
p.setPen( Qt::blue );
for ( int j = 1 ; j < 10 && FLYSCORES( j, 0 ) != -1 ; ++j )
{
if ( FLYSCORES( j, 2 ) < 0 )
p.setPen( Qt::red );
p.drawLine( (i*segSize) - (offset*speed), mapBottom[i]-FLYSCORES( j, 0 ), ((i+1)*segSize)-(offset*speed), mapBottom[i+1]-FLYSCORES( j, 0 ) );
}
p.setPen( Qt::white );
}
}
// Uncomment this to show user segment (usful for checking collision boundary with landscape
// p.setPen( Qt::red );
// p.drawLine( (11*segSize) - (offset*speed), 0, ((11)*segSize)-(offset*speed), sHeight );
// p.setPen( Qt::white );
// Draw user
p.drawRect( user );
// Draw trails
for ( int i = 0 ; i < TRAILSIZE ; ++i )
if ( trail[i].x() >= 0 )
{
if ( showEyeCandy )
p.setPen( Qt::white.light((int)(100.0-3*(user.x()/100.0)* (user.x()-trail[i].x())) ) );
p.drawRect( trail[i].x(), trail[i].y(), 2, 2 );
}
p.setPen( Qt::white );
// Draw blocks
for ( int i = 0 ; i < BLOCKSIZE ; ++i )
if ( blocks[i].y() != -1 )
{
p.fillRect( blocks[i], Qt::black );
p.drawRect( blocks[i] );
}
// draw score
QString s;
s.sprintf( "score %06d high score %06d", score, highestScore[currentGameType][currentGameDifficulty] );
p.drawText( 5, 10, s );
if ( state == STATE_CRASHING || state == STATE_CRASHED )
{
// add next crash line
if ( crashLineLength != -1 )
{
for ( int i = 0 ; i < 36 ; ++i )
{
int x = (int)(user.x() + (crashLineLength+nextInt(10)) * cos( (M_PI/180) * (10.0 * i) ) );
int y = (int)(user.y() + (crashLineLength+nextInt(10)) * sin( (M_PI/180) * (10.0 * i) ) ); p.drawLine( user.x(), user.y(), x, y );
}
}
if ( state == STATE_CRASHING && crashLineLength >= 15 ) //|| crashLineLength == -1) )
state = STATE_CRASHED;
if ( state == STATE_CRASHED )
{
QString text = "Press up or down to start";
p.drawText( (sWidth/2) - (fm.width( text )/2), 120, text );
text = "Press OK for menu";
p.drawText( (sWidth/2) - (fm.width( text )/2), 135, text );
/*
text = "Press r to replay";
p.drawText( (sWidth/2) - (fm.width( text )/2), 150, text );
text = "Press s to save the replay";
p.drawText( (sWidth/2) - (fm.width( text )/2), 165, text );
text = "Press r to load a saved replay";
p.drawText( (sWidth/2) - (fm.width( text )/2), 180, text );
*/
}
else
crashLineLength ++;
}
p.end();
bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true );
//printf( "endpaint\n" );
}
void SFCave :: handleKeys()
{
// Find enpty trail and move others
bool done = false;
for ( int i = 0 ; i < TRAILSIZE ; ++i )
{
if ( trail[i].x() < 0 )
{
if ( !done )
{
trail[i].setX( user.x() - 5 );
trail[i].setY( user.y() );
done = true;
}
}
else
{
trail[i].setX( trail[i].x() - (2) );
}
}
if ( speed <= 3 )
{
if ( press )
thrust -= thrustUp;
else
thrust += noThrust;
if ( thrust > maxDownThrust )
thrust = maxDownThrust;
else if ( thrust < maxUpThrust )
thrust = maxUpThrust;
}
else
{
if ( press )
thrust -= 0.5;
else
thrust += 0.8;
if ( thrust > 5.0 )
thrust = 5.0;
else if ( thrust < -3.5 )
thrust = -3.5;
}
user.moveBy( 0, (int)thrust );
}
void SFCave :: keyPressEvent( QKeyEvent *e )
{
if ( state == STATE_MENU )
handleMenuKeys( e );
else
{
switch( e->key() )
{
case Qt::Key_Up:
case Qt::Key_F9:
case Qt::Key_Space:
if ( state == STATE_RUNNING )
{
if ( !replay && !press )
{
press = true;
replayList.append( new int( nrFrames ) );
}
}
else if ( state == STATE_CRASHED )
{
if ( e->key() == Key_Up )
state = STATE_NEWGAME;
}
break;
case Qt::Key_M:
case Qt::Key_Return:
case Qt::Key_Enter:
if ( state == STATE_CRASHED )
{
state = STATE_MENU;
currentMenuNr = 0;
currentMenuOption[currentMenuNr] = 0;
}
break;
case Qt::Key_Z:
showScoreZones = !showScoreZones;
break;
default:
e->ignore();
break;
}
}
}
void SFCave :: keyReleaseEvent( QKeyEvent *e )
{
if ( state == STATE_MENU )
{
}
else
{
switch( e->key() )
{
case Qt::Key_F9:
case Qt::Key_Space:
case Qt::Key_Up:
if ( state == STATE_RUNNING )
{
if ( !replay && press )
{
press = false;
replayList.append( new int( nrFrames ) );
}
}
break;
case Qt::Key_E:
showEyeCandy = !showEyeCandy;
break;
case Qt::Key_R:
if ( state == STATE_CRASHED )
state = STATE_REPLAY;
break;
case Qt::Key_Down:
if ( state == STATE_CRASHED )
state = STATE_NEWGAME;
break;
case Qt::Key_S:
if ( state == STATE_CRASHED )
saveReplay();
break;
case Qt::Key_L:
if ( state == STATE_CRASHED )
loadReplay();
break;
default:
e->ignore();
break;
}
}
}
void SFCave :: saveScore()
{
#ifdef QWS
Config cfg( "sfcave" );
cfg.setGroup( "settings" );
QString key = "highScore_";
cfg.writeEntry( key + gameTypes[currentGameType] + "_" + dificultyOption[currentGameDifficulty], highestScore[currentGameType][currentGameDifficulty] );
key += CURRENT_GAME_TYPE;
cfg.writeEntry( key, highestScore[currentGameType] );
#endif
}
void SFCave :: saveReplay()
{
FILE *out;
out = fopen( QFile::encodeName(replayFile).data(), "w" );
if ( !out )
{
printf( "Couldn't write to %s\n", QFile::encodeName(replayFile).data() );
return;
}
// Build up string of values
// Format is:: <landscape seed> <game type> <difficulty> <framenr> <framenr>.......
QString val;
val.sprintf( "%d %d %d ", currentSeed, currentGameType, currentGameDifficulty );
QListIterator<int> it( replayList );
while( it.current() )
{
QString tmp;
tmp.sprintf( "%d ", (*it.current()) );
val += tmp;
++it;
}
val += "\n";
QString line;
line.sprintf( "%d\n", val.length() );
fwrite( (const char *)line, 1, line.length(), out );
fwrite( (const char *)val, 1, val.length(), out );
fclose( out );
printf( "Replay saved to %s\n", QFile::encodeName(replayFile).data() );
}
void SFCave :: loadReplay()
{
FILE *in = fopen( QFile::encodeName(replayFile).data() , "r" );
if ( in == 0 )
{
printf( "Couldn't load replay file!\n" );
return;
}
// Read next line - contains the size of the options
char line[10+1];
fgets( line, 10, in );
int length = -1;
sscanf( line, "%d", &length );
char *data = new char[length+1];
fread( data, 1, length, in );
// printf( "data - %s", data );
QString sep = " ";
QStringList list = QStringList::split( sep, QString( data ) );
// print it out
QStringList::Iterator it = list.begin();
currentSeed = (*it).toInt();
++it;
currentGameType = (*it).toInt();
++it;
currentGameDifficulty = (*it).toInt();
++it;
replayList.clear();
for ( ; it != list.end(); ++it )
{
int v = (*it).toInt();
replayList.append( new int( v ) );
}
- delete data;
+ delete [] data;
fclose( in );
printf( "Replay loaded from %s\n", QFile::encodeName(replayFile).data() );
}
//--------------- MENU CODE ---------------------
void SFCave :: handleMenuKeys( QKeyEvent *e )
{
switch( e->key() )
{
case Qt::Key_Down:
currentMenuOption[currentMenuNr] ++;
if ( menuOptions[currentMenuNr][currentMenuOption[currentMenuNr]] == "" )
currentMenuOption[currentMenuNr] = 0;
break;
case Qt::Key_Up:
currentMenuOption[currentMenuNr] --;
if ( currentMenuOption[currentMenuNr] < 0 )
currentMenuOption[currentMenuNr] = nrMenuOptions[currentMenuNr]-1;
break;
case Qt::Key_Left:
if ( currentMenuNr == MENU_OPTIONS_MENU )
{
if ( currentMenuOption[currentMenuNr] == MENU_GAME_TYPE )
{
currentGameType --;
if ( currentGameType < 0 )
currentGameType = NR_GAME_TYPES - 1;
}
else if ( currentMenuOption[currentMenuNr] == MENU_GAME_DIFFICULTY )
{
currentGameDifficulty --;
if ( currentGameDifficulty < 0 )
currentGameDifficulty = NR_GAME_DIFFICULTIES - 1;
}
}
break;
case Qt::Key_Right:
if ( currentMenuNr == MENU_OPTIONS_MENU )
{
if ( currentMenuOption[currentMenuNr] == MENU_GAME_TYPE )
{
currentGameType ++;
if ( currentGameType == NR_GAME_TYPES )
currentGameType = 0;
}
else if ( currentMenuOption[currentMenuNr] == MENU_GAME_DIFFICULTY )
{
currentGameDifficulty ++;
if ( currentGameDifficulty == NR_GAME_DIFFICULTIES )
currentGameDifficulty = 0;
}
}
break;
case Qt::Key_Space:
case Qt::Key_Return:
case Qt::Key_Enter:
dealWithMenuSelection();
break;
}
}
void SFCave :: displayMenu()
{
offscreen->fill( Qt::black );
QPainter p( offscreen );
p.setPen( Qt::white );
QFont f( "Helvetica", 16 );
p.setFont( f );
QFontMetrics fm = p.fontMetrics();
QString text = "SFCave";
p.drawText( (sWidth/2) - (fm.width( text )/2), 60, text );
text = "Written by Andy Qua";
p.drawText( (sWidth/2) - (fm.width( text )/2), 85, text );
// Draw options
int pos = 140;
for ( int i = 0 ; menuOptions[currentMenuNr][i] != "" ; ++i, pos += 25 )
{
if ( currentMenuOption[currentMenuNr] == i )
p.setPen( Qt::yellow );
else
p.setPen( Qt::white );
QString text;
if ( menuOptions[currentMenuNr][i].find( "%s" ) != -1 )
{
QString val;
if ( i == MENU_GAME_TYPE )
val = gameTypes[currentGameType];
else
val = dificultyOption[currentGameDifficulty];
text.sprintf( (const char *)menuOptions[currentMenuNr][i], (const char *)val );
}
else
text = menuOptions[currentMenuNr][i];
p.drawText( (sWidth/2) - (fm.width( text )/2), pos, text );
}
p.end();
bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true );
}
void SFCave :: dealWithMenuSelection()
{
switch( currentMenuNr )
{
case MENU_MAIN_MENU:
{
switch( currentMenuOption[currentMenuNr] )
{
case MENU_START_GAME:
state = STATE_NEWGAME;
break;
case MENU_REPLAY:
currentMenuNr = MENU_REPLAY_MENU;
currentMenuOption[currentMenuNr] = 0;
break;
case MENU_OPTIONS:
currentMenuNr = MENU_OPTIONS_MENU;
currentMenuOption[currentMenuNr] = 0;
break;
case MENU_HELP:
{
// Display Help Menu
HelpWindow *win = new HelpWindow( );
QPEApplication::showWidget( win );
break;
}
case MENU_QUIT:
QApplication::exit();
break;
}
break;
}
case MENU_OPTIONS_MENU:
{
switch( currentMenuOption[currentMenuNr] )
{
case MENU_GAME_TYPE:
break;
case MENU_GAME_DIFFICULTY:
break;
case MENU_CLEAR_HIGHSCORES:
for ( int i = 0 ; i < 3 ; ++i )
highestScore[currentGameType][i] = 0;
break;
case MENU_BACK:
currentMenuNr = MENU_MAIN_MENU;
#ifdef QWS
Config cfg( "sfcave" );
cfg.setGroup( "settings" );
cfg.writeEntry( "difficulty", currentGameDifficulty );
cfg.writeEntry( "gameType", currentGameType );
#endif
break;
}
break;
}
case MENU_REPLAY_MENU:
{
switch( currentMenuOption[currentMenuNr] )
{
case MENU_REPLAY_START:
if ( currentSeed != 0 )
state = STATE_REPLAY;
// Display No Replay
break;
case MENU_REPLAY_LOAD:
loadReplay();
break;
case MENU_REPLAY_SAVE:
saveReplay();
break;
case MENU_REPLAY_BACK:
currentMenuNr = MENU_MAIN_MENU;
break;
}
}
}
}
diff --git a/noncore/settings/aqpkg/settingsimpl.cpp b/noncore/settings/aqpkg/settingsimpl.cpp
index 7ffa1d6..0886e69 100644
--- a/noncore/settings/aqpkg/settingsimpl.cpp
+++ b/noncore/settings/aqpkg/settingsimpl.cpp
@@ -1,490 +1,490 @@
/*
This file is part of the OPIE Project
=. Copyright (c) 2002 Andy Qua <andy.qua@blueyonder.co.uk>
.=l. Dan Williams <drw@handhelds.org>
.>+-=
_;:, .> :=|. This file is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This file is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU General
..}^=.= = ; Public License for more details.
++= -. .` .:
: = ...= . :.=- You should have received a copy of the GNU
-. .:....=;==+<; General Public License along with this file;
-_. . . )=. = see the file COPYING. If not, write to the
-- :-=` Free Software Foundation, Inc.,
59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "settingsimpl.h"
#include "global.h"
/* OPIE */
#include <opie2/otabwidget.h>
#include <opie2/oresource.h>
#include <qpe/config.h>
#include <qpe/qpeapplication.h>
/* QT */
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <qpushbutton.h>
using namespace Opie::Ui;
using namespace Opie::Ui;
SettingsImpl :: SettingsImpl( DataManager *dataManager, QWidget * parent, const char* name, bool modal, WFlags fl )
: QDialog( parent, name, modal, fl )
{
setCaption( tr( "Configuration" ) );
// Setup layout to make everything pretty
QVBoxLayout *layout = new QVBoxLayout( this );
layout->setMargin( 2 );
layout->setSpacing( 4 );
// Setup tabs for all info
OTabWidget *tabwidget = new OTabWidget( this );
layout->addWidget( tabwidget );
tabwidget->addTab( initServerTab(), "aqpkg/servertab", tr( "Servers" ) );
tabwidget->addTab( initDestinationTab(), "aqpkg/desttab", tr( "Destinations" ) );
tabwidget->addTab( initProxyTab(), "aqpkg/proxytab", tr( "Proxies" ) );
tabwidget->setCurrentTab( tr( "Servers" ) );
dataMgr = dataManager;
setupData();
changed = false;
newserver = false;
newdestination = false;
}
SettingsImpl :: ~SettingsImpl()
{
}
bool SettingsImpl :: showDlg()
{
QPEApplication::execDialog( this );
if ( changed )
dataMgr->writeOutIpkgConf();
return changed;
}
QWidget *SettingsImpl :: initServerTab()
{
QWidget *control = new QWidget( this );
QVBoxLayout *vb = new QVBoxLayout( control );
QScrollView *sv = new QScrollView( control );
vb->addWidget( sv, 0, 0 );
sv->setResizePolicy( QScrollView::AutoOneFit );
sv->setFrameStyle( QFrame::NoFrame );
QWidget *container = new QWidget( sv->viewport() );
sv->addChild( container );
QGridLayout *layout = new QGridLayout( container );
layout->setSpacing( 2 );
layout->setMargin( 4 );
servers = new QListBox( container );
servers->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
connect( servers, SIGNAL( highlighted(int) ), this, SLOT( editServer(int) ) );
layout->addMultiCellWidget( servers, 0, 0, 0, 1 );
QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ),
tr( "New" ), container );
connect( btn, SIGNAL( clicked() ), this, SLOT( newServer() ) );
layout->addWidget( btn, 1, 0 );
btn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), tr( "Delete" ), container );
connect( btn, SIGNAL( clicked() ), this, SLOT( removeServer() ) );
layout->addWidget( btn, 1, 1 );
QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "Server" ), container );
grpbox->layout()->setSpacing( 2 );
grpbox->layout()->setMargin( 4 );
layout->addMultiCellWidget( grpbox, 2, 2, 0, 1 );
QGridLayout *grplayout = new QGridLayout( grpbox->layout() );
QLabel *label = new QLabel( tr( "Name:" ), grpbox );
grplayout->addWidget( label, 0, 0 );
servername = new QLineEdit( grpbox );
grplayout->addWidget( servername, 0, 1 );
label = new QLabel( tr( "Address:" ), grpbox );
grplayout->addWidget( label, 1, 0 );
serverurl = new QLineEdit( grpbox );
grplayout->addWidget( serverurl, 1, 1 );
active = new QCheckBox( tr( "Active Server" ), grpbox );
grplayout->addMultiCellWidget( active, 2, 2, 0, 1 );
btn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), tr( "Update" ), grpbox );
connect( btn, SIGNAL( clicked() ), this, SLOT( changeServerDetails() ) );
grplayout->addMultiCellWidget( btn, 3, 3, 0, 1 );
return control;
}
QWidget *SettingsImpl :: initDestinationTab()
{
QWidget *control = new QWidget( this );
QVBoxLayout *vb = new QVBoxLayout( control );
QScrollView *sv = new QScrollView( control );
vb->addWidget( sv, 0, 0 );
sv->setResizePolicy( QScrollView::AutoOneFit );
sv->setFrameStyle( QFrame::NoFrame );
QWidget *container = new QWidget( sv->viewport() );
sv->addChild( container );
QGridLayout *layout = new QGridLayout( container );
layout->setSpacing( 2 );
layout->setMargin( 4 );
destinations = new QListBox( container );
destinations->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
connect( destinations, SIGNAL( highlighted(int) ), this, SLOT( editDestination(int) ) );
layout->addMultiCellWidget( destinations, 0, 0, 0, 1 );
QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ), tr( "New" ), container );
connect( btn, SIGNAL( clicked() ), this, SLOT( newDestination() ) );
layout->addWidget( btn, 1, 0 );
btn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), tr( "Delete" ), container );
connect( btn, SIGNAL( clicked() ), this, SLOT( removeDestination() ) );
layout->addWidget( btn, 1, 1 );
QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "Destination" ), container );
grpbox->layout()->setSpacing( 2 );
grpbox->layout()->setMargin( 4 );
layout->addMultiCellWidget( grpbox, 2, 2, 0, 1 );
QGridLayout *grplayout = new QGridLayout( grpbox->layout() );
QLabel *label = new QLabel( tr( "Name:" ), grpbox );
grplayout->addWidget( label, 0, 0 );
destinationname = new QLineEdit( grpbox );
grplayout->addWidget( destinationname, 0, 1 );
label = new QLabel( tr( "Location:" ), grpbox );
grplayout->addWidget( label, 1, 0 );
destinationurl = new QLineEdit( grpbox );
grplayout->addWidget( destinationurl, 1, 1 );
linkToRoot = new QCheckBox( tr( "Link to root" ), grpbox );
grplayout->addMultiCellWidget( linkToRoot, 2, 2, 0, 1 );
btn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), tr( "Update" ), grpbox );
connect( btn, SIGNAL( clicked() ), this, SLOT( changeDestinationDetails() ) );
grplayout->addMultiCellWidget( btn, 3, 3, 0, 1 );
return control;
}
QWidget *SettingsImpl :: initProxyTab()
{
QWidget *control = new QWidget( this );
QVBoxLayout *vb = new QVBoxLayout( control );
QScrollView *sv = new QScrollView( control );
vb->addWidget( sv, 0, 0 );
sv->setResizePolicy( QScrollView::AutoOneFit );
sv->setFrameStyle( QFrame::NoFrame );
QWidget *container = new QWidget( sv->viewport() );
sv->addChild( container );
QGridLayout *layout = new QGridLayout( container );
layout->setSpacing( 2 );
layout->setMargin( 4 );
QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "HTTP Proxy" ), container );
grpbox->layout()->setSpacing( 2 );
grpbox->layout()->setMargin( 4 );
layout->addMultiCellWidget( grpbox, 0, 0, 0, 1 );
QVBoxLayout *grplayout = new QVBoxLayout( grpbox->layout() );
txtHttpProxy = new QLineEdit( grpbox );
grplayout->addWidget( txtHttpProxy );
chkHttpProxyEnabled = new QCheckBox( tr( "Enabled" ), grpbox );
grplayout->addWidget( chkHttpProxyEnabled );
grpbox = new QGroupBox( 0, Qt::Vertical, tr( "FTP Proxy" ), container );
grpbox->layout()->setSpacing( 2 );
grpbox->layout()->setMargin( 4 );
layout->addMultiCellWidget( grpbox, 1, 1, 0, 1 );
grplayout = new QVBoxLayout( grpbox->layout() );
txtFtpProxy = new QLineEdit( grpbox );
grplayout->addWidget( txtFtpProxy );
chkFtpProxyEnabled = new QCheckBox( tr( "Enabled" ), grpbox );
grplayout->addWidget( chkFtpProxyEnabled );
QLabel *label = new QLabel( tr( "Username:" ), container );
layout->addWidget( label, 2, 0 );
txtUsername = new QLineEdit( container );
layout->addWidget( txtUsername, 2, 1 );
label = new QLabel( tr( "Password:" ), container );
layout->addWidget( label, 3, 0 );
txtPassword = new QLineEdit( container );
layout->addWidget( txtPassword, 3, 1 );
QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), tr( "Update" ), container );
connect( btn, SIGNAL( clicked() ), this, SLOT( proxyApplyChanges() ) );
layout->addMultiCellWidget( btn, 4, 4, 0, 1 );
return control;
}
void SettingsImpl :: setupData()
{
// add servers
QString serverName;
QListIterator<Server> it( dataMgr->getServerList() );
for ( ; it.current(); ++it )
{
serverName = it.current()->getServerName();
if ( serverName == LOCAL_SERVER || serverName == LOCAL_IPKGS )
continue;
servers->insertItem( serverName );
}
// add destinations
QListIterator<Destination> it2( dataMgr->getDestinationList() );
for ( ; it2.current(); ++it2 )
destinations->insertItem( it2.current()->getDestinationName() );
// setup proxy tab
txtHttpProxy->setText( dataMgr->getHttpProxy() );
txtFtpProxy->setText( dataMgr->getFtpProxy() );
txtUsername->setText( dataMgr->getProxyUsername() );
txtPassword->setText( dataMgr->getProxyPassword() );
chkHttpProxyEnabled->setChecked( dataMgr->getHttpProxyEnabled() );
chkFtpProxyEnabled->setChecked( dataMgr->getFtpProxyEnabled() );
}
//------------------ Servers tab ----------------------
void SettingsImpl :: editServer( int sel )
{
currentSelectedServer = sel;
Server *s = dataMgr->getServer( servers->currentText() );
if ( s )
{
serverName = s->getServerName();
servername->setText( s->getServerName() );
serverurl->setText( s->getServerUrl() );
active->setChecked( s->isServerActive() );
}
else
{
serverName = "";
servername->setText( "" );
serverurl->setText( "" );
active->setChecked( false );
}
}
void SettingsImpl :: newServer()
{
newserver = true;
servername->setText( "" );
serverurl->setText( "" );
servername->setFocus();
active->setChecked( true );
}
void SettingsImpl :: removeServer()
{
changed = true;
Server *s = dataMgr->getServer( servers->currentText() );
if ( s )
{
dataMgr->getServerList().removeRef( s );
servers->removeItem( currentSelectedServer );
}
}
void SettingsImpl :: changeServerDetails()
{
changed = true;
QString newName = servername->text();
// Convert any spaces to underscores
char *tmpStr = new char[newName.length() + 1];
for ( unsigned int i = 0 ; i < newName.length() ; ++i )
{
if ( newName[i] == ' ' )
tmpStr[i] = '_';
else
tmpStr[i] = newName[i].latin1();
}
tmpStr[newName.length()] = '\0';
newName = tmpStr;
- delete tmpStr;
+ delete [] tmpStr;
if ( !newserver )
{
Server *s = dataMgr->getServer( servers->currentText() );
if ( s )
{
// Update url
s->setServerUrl( serverurl->text() );
s->setActive( active->isChecked() );
// Check if server name has changed, if it has then we need to replace the key in the map
if ( serverName != newName )
{
// Update server name
s->setServerName( newName );
}
// Update list box
servers->changeItem( newName, currentSelectedServer );
}
}
else
{
Server s( newName, serverurl->text() );
dataMgr->getServerList().append( new Server( newName, serverurl->text() ) );
dataMgr->getServerList().last()->setActive( active->isChecked() );
servers->insertItem( newName );
servers->setCurrentItem( servers->count() );
newserver = false;
}
}
//------------------ Destinations tab ----------------------
void SettingsImpl :: editDestination( int sel )
{
currentSelectedDestination = sel;
Destination *d = dataMgr->getDestination( destinations->currentText() );
if ( d )
{
destinationName = d->getDestinationName();
destinationname->setText( d->getDestinationName() );
destinationurl->setText( d->getDestinationPath() );
linkToRoot->setChecked( d->linkToRoot() );
}
else
{
destinationName = "";
destinationname->setText( "" );
destinationurl->setText( "" );
linkToRoot->setChecked( false );
}
}
void SettingsImpl :: newDestination()
{
newdestination = true;
destinationname->setText( "" );
destinationurl->setText( "" );
destinationname->setFocus();
linkToRoot->setChecked( true );
}
void SettingsImpl :: removeDestination()
{
changed = true;
Destination *d = dataMgr->getDestination( destinations->currentText() );
if ( d )
{
dataMgr->getDestinationList().removeRef( d );
destinations->removeItem( currentSelectedDestination );
}
}
void SettingsImpl :: changeDestinationDetails()
{
changed = true;
#ifdef QWS
Config cfg( "aqpkg" );
cfg.setGroup( "destinations" );
#endif
QString newName = destinationname->text();
if ( !newdestination )
{
Destination *d = dataMgr->getDestination( destinations->currentText() );
if ( d )
{
// Update url
d->setDestinationPath( destinationurl->text() );
d->linkToRoot( linkToRoot->isChecked() );
// Check if server name has changed, if it has then we need to replace the key in the map
if ( destinationName != newName )
{
// Update server name
d->setDestinationName( newName );
// Update list box
destinations->changeItem( newName, currentSelectedDestination );
}
#ifdef QWS
QString key = newName;
key += "_linkToRoot";
int val = d->linkToRoot();
cfg.writeEntry( key, val );
#endif
}
}
else
{
dataMgr->getDestinationList().append( new Destination( newName, destinationurl->text() ) );
destinations->insertItem( newName );
destinations->setCurrentItem( destinations->count() );
newdestination = false;
#ifdef QWS
QString key = newName;
key += "_linkToRoot";
cfg.writeEntry( key, true );
#endif
}
}
//------------------ Proxy tab ----------------------
void SettingsImpl :: proxyApplyChanges()
{
changed = true;
dataMgr->setHttpProxy( txtHttpProxy->text() );
dataMgr->setFtpProxy( txtFtpProxy->text() );
dataMgr->setProxyUsername( txtUsername->text() );
dataMgr->setProxyPassword( txtPassword->text() );
dataMgr->setHttpProxyEnabled( chkHttpProxyEnabled->isChecked() );
dataMgr->setFtpProxyEnabled( chkFtpProxyEnabled->isChecked() );
}
diff --git a/noncore/settings/aqpkg/version.cpp b/noncore/settings/aqpkg/version.cpp
index 59e6f3f..ce2de7b 100644
--- a/noncore/settings/aqpkg/version.cpp
+++ b/noncore/settings/aqpkg/version.cpp
@@ -1,219 +1,219 @@
/*
* libdpkg - Debian packaging suite library routines
* vercmp.c - comparison of version numbers
*
* Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2,
* or (at your option) any later version.
*
* This is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with dpkg; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <qobject.h>
//# define _(Text) Text
class versionrevision
{
public:
versionrevision()
{
version = 0;
}
~versionrevision()
{
if ( version )
- delete version;
+ delete [] version;
}
void setVersion( const char *str )
{
version = new char[(strlen(str)+1)];
strcpy( version, str );
}
unsigned long epoch;
char *version;
const char *revision;
const char *familiar_revision;
};
static int verrevcmp(const char *val, const char *ref)
{
int vc, rc;
long vl, rl;
const char *vp, *rp;
if (!val) val= "";
if (!ref) ref= "";
for (;;) {
vp= val; while (*vp && !isdigit(*vp)) vp++;
rp= ref; while (*rp && !isdigit(*rp)) rp++;
for (;;) {
vc= val == vp ? 0 : *val++;
rc= ref == rp ? 0 : *ref++;
if (!rc && !vc) break;
if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
if (rc && !isalpha(rc)) rc += 256;
if (vc != rc) return vc - rc;
}
val= vp;
ref= rp;
vl=0; if (isdigit(*vp)) vl= strtol(val,(char**)&val,10);
rl=0; if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10);
if (vl != rl) return vl - rl;
if (!*val && !*ref) return 0;
if (!*val) return -1;
if (!*ref) return +1;
}
}
int versioncompare(const struct versionrevision *version,
const struct versionrevision *refversion)
{
int r;
if (version->epoch > refversion->epoch) return 1;
if (version->epoch < refversion->epoch) return -1;
r= verrevcmp(version->version,refversion->version); if (r) return r;
r= verrevcmp(version->revision,refversion->revision); if (r) return r;
return verrevcmp(version->familiar_revision,refversion->familiar_revision);
}
int versionsatisfied3(const struct versionrevision *it,
const struct versionrevision *ref,
const char *op)
{
int r;
r= versioncompare(it,ref);
if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0)
return r <= 0;
if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0)
return r >= 0;
if (strcmp(op, "<<") == 0)
return r < 0;
if (strcmp(op, ">>") == 0)
return r > 0;
if (strcmp(op, "=") == 0)
return r == 0;
// fprintf(stderr, "unknown operator: %s", op);
exit(1);
}
const char *parseversion(struct versionrevision *rversion, const char *string)
{
char *hyphen, *colon, *eepochcolon;
unsigned long epoch;
if ( !*string )
return QObject::tr( "Version string is empty." );
colon= strchr(string,':');
if (colon) {
epoch= strtoul(string,&eepochcolon,10);
if ( colon != eepochcolon )
return QObject::tr( "Epoch in version is not number." );
if ( !*++colon )
return QObject::tr( "Nothing after colon in version number." );
string= colon;
rversion->epoch= epoch;
} else {
rversion->epoch= 0;
}
rversion->revision = "";
rversion->familiar_revision = "";
rversion->setVersion( string );
hyphen= strrchr(rversion->version,'-');
if (hyphen) {
*hyphen++= 0;
if (strncmp("fam", hyphen, 3) == 0) {
rversion->familiar_revision=hyphen+3;
hyphen= strrchr(rversion->version,'-');
if (hyphen) {
*hyphen++= 0;
rversion->revision = hyphen;
}
} else {
rversion->revision = hyphen;
}
}
/*
fprintf(stderr,"Parsed version: %lu, %s, %s, %s\n",
rversion->epoch,
rversion->version,
rversion->revision,
rversion->familiar_revision);
*/
return 0;
}
int compareVersions( const char *v1, const char *v2 )
{
const char *err;
versionrevision ver, ref;
err = parseversion(&ref, v1);
if (err) {
// fprintf(stderr, "Invalid version `%s': %s\n", v2, err);
return -2;
}
err = parseversion(&ver, v2);
if (err) {
// fprintf(stderr, "Invalid version `%s': %s\n", v1, err);
return -2;
}
if ( versionsatisfied3( &ver, &ref, "=" ) )
return 0;
else if ( versionsatisfied3( &ver, &ref, "<" ) )
return -1;
else
return 1;
}
/*
int main(int argc, char *argv[])
{
const char *err;
versionrevision ver, ref;
if (argc < 4) {
fprintf(stderr, "usage: %s: version op refversion\n", argv[0]);
return 2;
}
err = parseversion(&ver, argv[1]);
if (err) {
fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err);
return 2;
}
err = parseversion(&ref, argv[3]);
if (err) {
fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err);
return 2;
}
printf( "Result: %d\n", versionsatisfied3(&ver, &ref, argv[2]) );
}
*/