home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 110
/
EnigmaAmiga110CD.iso
/
indispensabili
/
utility
/
apdf
/
xpdf-0.80
/
ltk
/
ltklist.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1998-11-27
|
8KB
|
314 lines
//========================================================================
//
// LTKList.cc
//
// Copyright 1997 Derek B. Noonburg
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "gmem.h"
#include "LTKList.h"
#define horizBorder 4
#define vertBorder 2
LTKList::LTKList(char *name1, int widgetNum1,
int minWidth1, int minLines1,
GBool allowSelection1, char *fontName1):
LTKWidget(name1, widgetNum1) {
minWidth = minWidth1;
minLines = minLines1;
allowSelection = allowSelection1;
clickCbk = NULL;
dblClickCbk = NULL;
text = NULL;
numLines = 0;
textSize = 0;
topLine = 0;
horizOffset = 0;
selection = -1;
fontName = fontName1;
fontStruct = NULL;
textGC = None;
}
LTKList::~LTKList() {
int i;
for (i = 0; i < numLines; ++i)
delete text[i];
gfree(text);
if (fontName && fontStruct) {
XFreeFont(getDisplay(), fontStruct);
XFreeGC(getDisplay(), textGC);
}
}
long LTKList::getEventMask() {
return LTKWidget::getEventMask() | ButtonPressMask | ButtonReleaseMask;
}
void LTKList::insertLine(int line, char *s) {
XCharStruct extents;
int direction, ascent, descent;
int i;
if (line <= numLines) {
if (numLines >= textSize) {
textSize += 32;
text = (GString **)grealloc(text, textSize * sizeof(GString *));
}
for (i = numLines-1; i >= line; --i)
text[i+1] = text[i];
text[line] = new GString(s);
++numLines;
if (getXWindow() != None) {
XTextExtents(fontStruct, text[line]->getCString(),
text[line]->getLength(),
&direction, &ascent, &descent, &extents);
if (extents.width + 2*horizBorder > maxWidth)
maxWidth = extents.width + 2*horizBorder;
redrawBelow(line);
}
}
}
void LTKList::replaceLine(int line, char *s) {
XCharStruct extents;
int direction, ascent, descent;
if (line < numLines) {
delete text[line];
text[line] = new GString(s);
if (getXWindow() != None) {
XTextExtents(fontStruct, text[line]->getCString(),
text[line]->getLength(),
&direction, &ascent, &descent, &extents);
if (extents.width + 2*horizBorder > maxWidth)
maxWidth = extents.width + 2*horizBorder;
redrawLine(line);
}
}
}
//~ this should reduce size of text array
void LTKList::deleteLine(int line) {
int i;
if (line < numLines) {
delete text[line];
for (i = line; i < numLines - 1; ++i)
text[i] = text[i+1];
text[numLines-1] = NULL;
--numLines;
if (selection == line) {
xorSelection();
selection = -1;
}
if (getXWindow() != None)
redrawBelow(line);
}
}
void LTKList::deleteAll() {
int line;
for (line = 0; line < numLines; ++line)
delete text[line];
delete text;
text = NULL;
numLines = 0;
textSize = 0;
topLine = 0;
horizOffset = 0;
selection = -1;
if (getXWindow() != None) {
maxWidth = 0;
redraw();
}
}
void LTKList::setSelection(int line) {
if (allowSelection) {
xorSelection();
selection = line;
xorSelection();
}
}
int LTKList::getDisplayedLines() {
return (height - 2 * vertBorder) / textHeight;
}
void LTKList::scrollTo(int line, int horiz) {
GBool changed;
changed = gFalse;
if (line != topLine && line < numLines) {
topLine = line;
changed = gTrue;
}
if (horiz != horizOffset) {
horizOffset = horiz;
changed = gTrue;
}
//~ blit-scroll if possible
if (changed && getXWindow() != None)
redraw();
}
void LTKList::makeVisible(int line) {
int dispLines;
dispLines = getDisplayedLines();
if (line < topLine)
scrollTo(line, horizOffset);
else if (line >= topLine + dispLines)
scrollTo(line - dispLines + 1, horizOffset);
}
void LTKList::layout1() {
XGCValues gcValues;
XCharStruct extents;
int direction, ascent, descent;
int line;
// get/create GCs
if (textGC == None) {
if (fontName &&
(fontStruct = XLoadQueryFont(getDisplay(), fontName))) {
XGetGCValues(getDisplay(), getFgGC(),
GCForeground | GCBackground | GCGraphicsExposures,
&gcValues);
gcValues.font = fontStruct->fid;
textGC = XCreateGC(getDisplay(), parent->getXWindow(),
GCForeground | GCBackground | GCGraphicsExposures |
GCFont,
&gcValues);
} else {
fontName = NULL;
fontStruct = parent->getXFontStruct();
textGC = getFgGC();
}
}
// compute max line width
maxWidth = 0;
for (line = 0; line < numLines; ++line) {
XTextExtents(fontStruct, text[line]->getCString(), text[line]->getLength(),
&direction, &ascent, &descent, &extents);
if (extents.width > maxWidth)
maxWidth = extents.width;
}
maxWidth += 2 * horizBorder;
// text parameters
textHeight = fontStruct->ascent + fontStruct->descent;
textBase = fontStruct->ascent;
// compute min width/height
width = minWidth + 2 * horizBorder;
height = minLines * textHeight + 2 * vertBorder;
}
void LTKList::layout3() {
XRectangle rect;
LTKWidget::layout3();
rect.x = horizBorder;
rect.y = vertBorder;
rect.width = width - 2 * horizBorder;
rect.height = height - 2 * vertBorder;
XSetClipRectangles(getDisplay(), textGC, 0, 0, &rect, 1, Unsorted);
}
void LTKList::redraw() {
int y;
int i;
XFillRectangle(getDisplay(), xwin, getBgGC(), 0, 0, width, height);
y = vertBorder;
for (i = topLine;
i < numLines && y < height - vertBorder;
++i, y += textHeight) {
XDrawString(getDisplay(), xwin, textGC,
horizBorder - horizOffset, y + textBase,
text[i]->getCString(), text[i]->getLength());
}
xorSelection();
}
void LTKList::redrawLine(int line) {
int y;
if (line < topLine ||
line >= topLine +
(height - 2*vertBorder + textHeight - 1) / textHeight)
return;
y = vertBorder + (line - topLine) * textHeight;
XFillRectangle(getDisplay(), xwin, getBgGC(),
horizBorder, y, width - 2*horizBorder, textHeight);
XDrawString(getDisplay(), xwin, textGC,
horizBorder - horizOffset, y + textBase,
text[line]->getCString(), text[line]->getLength());
if (selection == line)
xorSelection();
}
void LTKList::redrawBelow(int line) {
int y;
int i;
if (line >= topLine +
(height - 2*vertBorder + textHeight - 1) / textHeight)
return;
y = vertBorder + (line - topLine) * textHeight;
XFillRectangle(getDisplay(), xwin, getBgGC(),
horizBorder, y,
width - 2*horizBorder, height - vertBorder - y);
for (i = line;
i < numLines && y < height - vertBorder;
++i, y += textHeight) {
XDrawString(getDisplay(), xwin, textGC,
horizBorder - horizOffset, y + textBase,
text[i]->getCString(), text[i]->getLength());
}
if (selection >= line)
xorSelection();
}
void LTKList::xorSelection() {
if (selection < topLine ||
selection >= topLine +
(height - 2*vertBorder + textHeight - 1) / textHeight)
return;
y = vertBorder + (selection - topLine) * textHeight;
XFillRectangle(getDisplay(), xwin, getXorGC(),
horizBorder, y, width - 2*horizBorder, textHeight);
}
void LTKList::buttonPress(int mx, int my, int button, GBool dblClick) {
int line;
line = topLine + (my - vertBorder) / textHeight;
if (line < numLines) {
setSelection(line);
if (dblClick) {
if (dblClickCbk)
(*dblClickCbk)(this, widgetNum, selection);
} else {
if (clickCbk)
(*clickCbk)(this, widgetNum, selection);
}
}
}