This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Compiler error
- To: egcs-bugs at egcs dot cygnus dot com
- Subject: Compiler error
- From: "Sheldon Lee Wen" <sheldonl at nortelnetworks dot com>
- Date: Tue, 23 Mar 1999 22:05:37 +0000
- Organization: Nortel
- Reply-To: "Sheldon Lee Wen" <sheldonl at nortelnetworks dot com>
HI,
I'm being a good boy and reporting this:
I was compiling vdkbuilder.
[root@localhost vdkbuilder]# gcc -c -g -Wall -DVDKBDEBUG -DHAVE_SYNTAX -DHAVE_HINTS -I./ `vdk-config --cflags` -o vdkb_editor.o vdkb_editor.c
c
vdkb_editor.cc:44: warning: ANSI C++ forbids declaration `last_pos' with no type
/usr/local/include/vdk/vdkbtrees.h: In instantiation of `RedBlackNode<VDKBHint>':
/usr/local/include/vdk/vdkbtrees.h:555: instantiated from `AbstractBinaryTree<VDKBHint,RedBlackNode<VDKBHint> >::find<VDKBHint, RedBlackNode<VDKBHint>>(const VDKBHint &)'
vdkb_editor.cc:57: instantiated from here
/usr/local/include/vdk/vdkbtrees.h:555: Internal compiler error.
/usr/local/include/vdk/vdkbtrees.h:555: Please submit a full bug report to `egcs-bugs@egcs.cygnus.com'.
/usr/local/include/vdk/vdkbtrees.h:555: See <URL:http://egcs.cygnus.com/faq.html#bugreport> for details.
/*
* ===========================
* VDK Visual Development Kit
* Version 0.5
* November 1998
* ===========================
*
* Copyright (C) 1998, Mario Motta
* Developed by Mario Motta <mmotta@guest.net>
*
* 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#ifndef VDKBTREES_H
#define VDKBTREES_H
// --------------------------
// Abstract class template,
// --------------------------
template<class T, class Node>
class AbstractBinaryNode {
public:
AbstractBinaryNode() { }
AbstractBinaryNode(const T& _object,
Node *_parent = 0,
Node *_left = 0,
Node *_right = 0);
virtual ~AbstractBinaryNode() { }
// Subtree arrangement
virtual Node *Clone(Node *_parent) const;
virtual void RemoveSubtree();
virtual Node *LeftRotate(Node *root);
virtual Node *RightRotate(Node *root);
virtual int CheckTreeProperties(const Node *);
virtual int IsLeftChild() const;
virtual int IsRightChild() const;
// Adding a node and deleting
virtual Node *add(const T& x);
virtual Node *unlink(Node *z);
// Find
virtual Node *find(const T& x);
virtual Node *findNearest(const T& x);
// Tree trasverse
virtual Node *Minimum();
virtual Node *Maximum();
virtual Node *Predecessor();
virtual Node *Successor();
// Miscellaneous
virtual T *Object();
public:
T object;
Node *left, *right, *parent;
};
template<class T>
class BinaryNode : public AbstractBinaryNode<T, BinaryNode<T> > {
public:
// Constructors and destructor
BinaryNode() { }
BinaryNode(const T& object,
BinaryNode<T> *parent = 0,
BinaryNode<T> *left = 0,
BinaryNode<T> *right = 0):
AbstractBinaryNode<T, BinaryNode<T> >(object, parent, left, right) { }
virtual ~BinaryNode() { }
};
//////////////////////////////////////////////////////
// Different ways to iterate on the binary tree.
enum BtreeIteratorMode { BtMinKey, BtRootKey, BtMaxKey };
template<class T, class Node>
class AbstractBinaryTree {
public:
AbstractBinaryTree();
AbstractBinaryTree(const AbstractBinaryTree<T, Node>&);
AbstractBinaryTree<T, Node>& operator=(const AbstractBinaryTree<T, Node>&);
virtual ~AbstractBinaryTree();
virtual void add(const T&); // Add a node
virtual void unlink(const T&); // Remove a node
virtual T *find(const T& q);
virtual int IsEmpty() const { return root == 0; }
virtual Node *IteratorRoot() const;
virtual Node *IteratorFind(const T& x) const;
virtual int CheckTreeProperties();
unsigned int size() { return count; }
// Iterator class
class Iterator {
public:
Iterator(const AbstractBinaryTree<T, Node>& _tree,
enum BtreeIteratorMode start = BtMinKey)
{
tree = (AbstractBinaryTree<T, Node> *) (&_tree);
StartAt(start);
}
// Start iterator over at the minimum, maximum or
// root node of the binary tree.
void StartAt(enum BtreeIteratorMode start)
{
ptr = tree->IteratorRoot();
if (start == BtMinKey)
ptr = ptr->Minimum();
else if (start == BtMaxKey)
ptr = ptr->Maximum();
}
virtual ~Iterator() { }
virtual void Previous()
{
if (ptr)
ptr = ptr->Predecessor();
}
virtual void Next()
{
if (ptr)
ptr = ptr->Successor();
}
virtual void Parent()
{
if (ptr)
ptr = ptr->parent;
}
virtual void find(const T& x)
{
ptr = tree->IteratorFind(x);
}
virtual operator int() const
{
return ptr != 0;
}
// Dereferencing operator returns the object of the
// node currently pointed to by the iterator.
virtual T operator*() const { return ptr->object; }
virtual T current() const { return ptr->object; }
virtual Node* current_node() const
{ return ptr; }
// Object returns a pointer to the object of the
// node currently pointed to (as opposed to returning
// a copy of the node, as the dereferencing operator
// above does).
virtual const T *Object() const
{
if (ptr)
return &ptr->object;
return (T*) 0;
}
virtual T *Object()
{
if (ptr)
return &ptr->object;
return 0;
}
virtual void operator++() { Next(); }
virtual void operator++(int) { Next(); }
virtual void operator--() { Previous(); }
virtual void operator--(int) { Previous(); }
protected:
Node *ptr;
AbstractBinaryTree<T, Node> *tree;
};
protected:
Node *root;
unsigned int count;
};
///////////////////////////////////////
template<class T>
class BinaryTree : public AbstractBinaryTree<T, BinaryNode<T> > {
public:
BinaryTree() { }
};
// --------------------------------------------------------
// AbstractBinaryNode implementation.
// --------------------------------------------------------
template<class T, class Node>
AbstractBinaryNode<T, Node>::AbstractBinaryNode(const T& _object,
Node *_parent,
Node *_left,
Node *_right)
{
object = _object;
parent = _parent;
left = _left;
right = _right;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Clone(Node *_parent) const
{
Node *ret = new Node( *((Node *) this));
if (left)
ret->left = left->Clone(ret);
if (right)
ret->right = right->Clone(ret);
ret->parent = _parent;
return ret;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::LeftRotate(Node *root)
{
Node *ret = root;
Node *y = right;
right = y->left;
if (right)
right->parent = (Node *) this;
y->parent = parent;
if (parent) {
if (this == parent->left)
parent->left = y;
else
parent->right = y;
}
else
ret = y;
y->left = (Node *) this;
parent = y;
return ret;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::RightRotate(Node *root)
{
Node *ret = root;
Node *x = left;
left = x->right;
if (left)
left->parent = (Node *) this;
x->parent = parent;
if (parent) {
if (this == parent->left)
parent->left = x;
else
parent->right = x;
}
else
ret = x;
x->right = (Node *) this;
parent = x;
return ret;
}
template<class T, class Node>
int
AbstractBinaryNode<T, Node>::IsLeftChild() const
{
return (parent && parent->left == (Node *) this);
}
template<class T, class Node>
int
AbstractBinaryNode<T, Node>::IsRightChild() const
{
return (parent && parent->right == (Node *) this);
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::find(const T& x)
{
Node *sc = (Node *) this;
while (sc) {
if (x == sc->object)
return sc;
if (x < sc->object)
sc = sc->left;
else
sc = sc->right;
}
return 0;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::findNearest(const T& x)
{
Node *sc = (Node *) this;
Node *prev = 0;
while (sc) {
prev = sc;
if (x < sc->object)
sc = sc->left;
else
sc = sc->right;
}
return prev;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::add(const T& x)
{
Node *nearest = findNearest(x);
if (x < nearest->object)
nearest->left = new Node(x, nearest);
else
nearest->right = new Node(x, nearest);
return (Node *) this;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::unlink(Node *z)
{
Node *root = (Node *) this;
Node *x, *y;
if (! z)
return root;
if (! z->left || ! z->right)
y = z;
else
y = z->Successor();
if (y->left)
x = y->left;
else
x = y->right;
if (x)
x->parent = y->parent;
if (y->parent) {
if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
}
else
root = x;
if (y != z)
z->object = y->object;
delete y;
return root;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Minimum()
{
Node *sc = (Node *) this;
while (sc && sc->left)
sc = sc->left;
return sc;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Maximum()
{
Node *sc = (Node *) this;
while (sc && sc->right)
sc = sc->right;
return sc;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Predecessor()
{
if (left)
return left->Maximum();
Node *x = (Node *) this;
Node *y = parent;
while (y && x == y->left) {
x = y;
y = y->parent;
}
return y;
}
template<class T, class Node>
Node *
AbstractBinaryNode<T, Node>::Successor()
{
if (right)
return right->Minimum();
Node *x = (Node *) this;
Node *y = parent;
while (y && x == y->right) {
x = y;
y = y->parent;
}
return y;
}
template<class T, class Node>
void
AbstractBinaryNode<T, Node>::RemoveSubtree()
{
if (left) {
left->RemoveSubtree();
delete left;
}
if (right) {
right->RemoveSubtree();
delete right;
}
}
template<class T, class Node>
T *
AbstractBinaryNode<T, Node>::Object()
{
return &object;
}
template<class T, class Node>
int
AbstractBinaryNode<T, Node>::CheckTreeProperties(const Node *_parent)
{
if (parent != _parent)
return 0;
if (left) {
if (object < left->object)
return 0;
if (! left->CheckTreeProperties((Node *) this))
return 0;
}
if (right) {
if (right->object < object)
return 0;
if (! right->CheckTreeProperties((Node *) this))
return 0;
}
return 1;
}
// --------------------------------------------------------
// AbstractBinaryTree class template implementation.
// --------------------------------------------------------
template<class T, class Node>
AbstractBinaryTree<T, Node>::AbstractBinaryTree()
{
root = 0;
count = 0;
}
template<class T, class Node>
AbstractBinaryTree<T, Node>::AbstractBinaryTree(const AbstractBinaryTree<T, Node>& x)
{
if (x.root)
root = x.root->Clone(0);
else
root = 0;
count = x.count;
}
template<class T, class Node>
AbstractBinaryTree<T, Node>&
AbstractBinaryTree<T, Node>::operator=(const AbstractBinaryTree<T, Node>& x)
{
if (root) {
root->RemoveSubtree();
delete root;
}
if (x.root)
root = x.root->Clone(0);
else
root = 0;
count = x.count;
return *this;
}
template<class T, class Node>
AbstractBinaryTree<T, Node>::~AbstractBinaryTree()
{
if (root) {
root->RemoveSubtree();
delete root;
}
}
template<class T, class Node>
void
AbstractBinaryTree<T, Node>::add(const T& x)
{
count++;
if (root == 0)
root = new Node(x);
else
root = root->add(x);
}
template<class T, class Node>
Node *
AbstractBinaryTree<T, Node>::IteratorRoot() const
{
return root;
}
template<class T, class Node>
Node *
AbstractBinaryTree<T, Node>::IteratorFind(const T& x) const
{
return (root) ? root->find(x) : 0;
}
template<class T, class Node>
void
AbstractBinaryTree<T, Node>::unlink(const T& _x)
{
count--;
if (! root)
return;
root = root->unlink(root->find(_x));
}
template<class T, class Node>
T *
AbstractBinaryTree<T, Node>::find(const T& q)
{
Node *p = (root) ? root->find(q) : 0;
return (p) ? &p->object : 0;
}
template<class T, class Node>
int
AbstractBinaryTree<T, Node>::CheckTreeProperties()
{
if (root->CheckTreeProperties(0) == 0)
return 0;
return 1;
}
/////////////////////////////
// balanced binary trees
// (using red & black trees)
/////////////////////////////
template<class T, class Node>
class AbstractRedBlackNode : public AbstractBinaryNode<T, Node> {
public:
enum RedBlack { Black, Red } clr;
// Constructors. Node always starts out red.
AbstractRedBlackNode() { clr = Red; }
AbstractRedBlackNode(const T& X,
Node *P = 0,
Node *L = 0,
Node *R = 0):
AbstractBinaryNode<T, Node>(X, P, L, R) { }
AbstractRedBlackNode(const T& X, enum RedBlack Clr, Node *P = 0,
Node *L = 0, Node *R = 0):
AbstractBinaryNode<T, Node>(X, P, L, R), clr(Clr) { }
virtual ~AbstractRedBlackNode() { }
// Tree manipulations used during insertion and deletion
virtual Node *RemoveFixup(Node *x, Node *p);
// Operations defined on binary trees. All run in O(lgN) time.
virtual Node *add(const T& AddMe);
virtual Node *unlink(Node *z);
// Returns 0 if the red-black invariant holds.
virtual int CheckTreeProperties(const Node *);
};
template<class T>
class RedBlackNode : public AbstractRedBlackNode<T, RedBlackNode<T> > {
public:
// Constructors. Node always starts out red.
RedBlackNode() { }
RedBlackNode(const T& X,
RedBlackNode<T> *P = 0,
RedBlackNode<T> *L = 0,
RedBlackNode<T> *R = 0):
AbstractRedBlackNode<T, RedBlackNode<T> >(X, P, L, R) { }
RedBlackNode(const T& X, enum RedBlack Clr, RedBlackNode<T> *P = 0,
RedBlackNode<T> *L = 0, RedBlackNode<T> *R = 0):
AbstractRedBlackNode<T, RedBlackNode<T> >(X, clr, P, L, R) { }
virtual ~RedBlackNode() { }
};
// --------------------------------------------------------
// AbstractRedBlackTree class template.
// --------------------------------------------------------
template<class T, class Node>
class AbstractRedBlackTree : public AbstractBinaryTree<T, Node> {
// The following is accessible only to classes that inherit
// from AbstractRedBlackTree, since they deal directly with RedBlackNodes.
protected:
virtual Node *FindNode(T q) const
{ return (root) ? (Node *) root->find(q) : 0; }
};
template <class T>
class VDKBtree : public AbstractRedBlackTree<T, RedBlackNode<T> > {
public:
VDKBtree() { }
};
template<class T, class Node>
Node *
AbstractRedBlackNode<T, Node>::add(const T& AddMe)
{
Node *root = (Node *) this;
Node *x = (Node *) this;
Node *y = 0;
while (x) {
y = x;
x = (AddMe < x->object) ? x->left : x->right;
}
Node *addme = new Node(AddMe, y);
if (! y)
root = addme;
else {
if (AddMe < y->object)
y->left = addme;
else
y->right = addme;
}
addme->clr = Red;
while (addme != root &&
addme->parent->parent &&
addme->parent->clr == Red) {
Node *y;
if (addme->parent == addme->parent->parent->left) {
y = addme->parent->parent->right;
if (y && y->clr == Red) {
// Case 1: x's uncle is red
addme->parent->clr = Black;
y->clr = Black;
addme->parent->parent->clr = Red;
addme = addme->parent->parent;
}
else {
if (addme == addme->parent->right) {
// Case 2: x is a right child
// Rotate to transform to case 3
addme = addme->parent;
root = addme->LeftRotate(root);
}
// Case 3: x is a left child
addme->parent->clr = Black;
if (addme->parent->parent) {
addme->parent->parent->clr = Red;
root = addme->parent->parent->RightRotate(root);
}
// The while loop will terminate
// on the next iteration.
}
}
else {
y = addme->parent->parent->left;
if (y && y->clr == Red) {
addme->parent->clr = Black;
y->clr = Black;
addme->parent->parent->clr = Red;
addme = addme->parent->parent;
}
else {
if (addme == addme->parent->left) {
addme = addme->parent;
root = addme->RightRotate(root);
}
addme->parent->clr = Black;
if (addme->parent->parent) {
addme->parent->parent->clr = Red;
root = addme->parent->parent->LeftRotate(root);
}
}
}
}
root->clr = Black;
return root;
}
template<class T, class Node>
Node *
AbstractRedBlackNode<T, Node>::RemoveFixup(Node *x, Node *p)
{
Node *root = (Node *) this;
while (x != root && (! x || x->clr == Black)) {
Node *w;
if (x == p->left) {
if (! p)
return root;
w = p->right;
if (! w)
return root;
if (w->clr == Red) {
w->clr = Black;
p->clr = Red;
root = p->LeftRotate(root);
w = p->right;
if (! p || ! w)
return root;
}
if ( ((! w->left) || w->left->clr == Black) &&
((! w->right) || w->right->clr == Black)) {
w->clr = Red;
x = p;
p = p->parent;
continue;
}
else if ((! w->right) || w->right->clr == Black) {
w->left->clr = Black;
w->clr = Red;
root = w->RightRotate(root);
w = p->right;
if (! p || ! w)
return root;
}
w->clr = p->clr;
if (p)
p->clr = Black;
w->right->clr = Black;
if (p)
root = p->LeftRotate(root);
x = root;
}
else {
if (! p)
return root;
w = p->left;
if (! p || ! w)
return root;
if (w->clr == Red) {
w->clr = Black;
p->clr = Red;
root = p->RightRotate(root);
w = p->left;
if (! p || ! w)
return root;
}
if ( ((! w->right) || w->right->clr == Black) &&
((! w->left) || w->left->clr == Black)) {
w->clr = Red;
x = p;
p = p->parent;
continue;
}
else if ((! w->left) || w->left->clr == Black) {
w->right->clr = Black;
w->clr = Red;
root = w->LeftRotate(root);
w = p->left;
if (! p || ! w)
return root;
}
w->clr = p->clr;
if (p)
p->clr = Black;
w->left->clr = Black;
if (p)
root = p->RightRotate(root);
x = root;
}
}
if (x)
x->clr = Black;
return root;
}
template<class T, class Node>
Node *
AbstractRedBlackNode<T, Node>::unlink(Node *z)
{
Node *root = (Node *) this;
Node *x, *y;
if (! z)
return root;
y = (! z->left || ! z->right) ? z : (Node *) z->Successor();
x = (y->left) ? y->left : y->right;
if (x)
x->parent = y->parent;
if (y->parent) {
if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
}
else
root = x;
if (y != z)
z->object = y->object;
if (y->clr == Black) {
if (root)
root = root->RemoveFixup(x, y->parent);
}
delete y;
return root;
}
template<class T, class Node>
int
AbstractRedBlackNode<T, Node>::CheckTreeProperties(const Node *_parent)
{
static int BlackHeight;
if (_parent == 0)
BlackHeight = -1;
// Check binary tree properties.
if (parent != _parent)
return 0;
if (left) {
if (object < left->object)
return 0;
}
if (right) {
if (right->object < object)
return 0;
}
// Now check red-black tree properties.
// If a node is red, then both its children are black
// (NULL nodes are black).
if (clr == Red) {
if ((left && left->clr != Black) ||
(right && right->clr != Black))
return 0;
}
// The black-heights of all leaf nodes are equal.
int bh = 0;
if ((! left) && (! right)) {
// Compute black-height of node
for (Node *sc = (Node *) this; sc; sc = sc->parent)
if (sc->clr == Black)
bh += 1;
if (BlackHeight == -1) {
BlackHeight = bh;
}
else {
if (bh != BlackHeight)
return 0;
}
}
if (left && (! left->CheckTreeProperties((Node *) this)))
return 0;
if (right && (! right->CheckTreeProperties((Node *) this)))
return 0;
return 1;
}
#endif
/*
* ===========================
* VDK Builder
* Version 0.1
* Revision 0.0
* November 1998
* ===========================
*
* Copyright (C) 1998,1999 Mario Motta
* Developed by Mario Motta <mmotta@guest.net>
*
* Based on VDK Library
* Copyright (C) 1998, Mario Motta
*
* 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#include <vdkb_editor.h>
#include <vdkb.h>
#include <vdkb_locale.h>
#include <vdkb_utils.h>
#include <vdk/FileDialog.h>
#include <vdk/FileSaveAsDialog.h>
#include <vdkb_search.h>
#include <vdkb_replace.h>
static char buff[512];
/*
search stuff
*/
static last_pos = 0;
static char* match = NULL;
/*
*/
#ifdef HAVE_HINTS
char*
VDKBEditor::HintCallback (char *match, gpointer data)
{
VDKBEditor* editor = (VDKBEditor*) data;
VDKBHint hint,*found = NULL;
hint.match = match;
if(editor->hintDb)
found = editor->hintDb->find(hint);
return found ? (char*) found->text : NULL;
}
#endif
///////////////// signal stuff //////////
DEFINE_SIGNAL_LIST(VDKBEditor,VDKForm);
DEFINE_SIGNAL_MAP(VDKBEditor,VDKForm)
ON_SIGNAL(nbook,switch_page_signal,OnPageChanged),
ON_SIGNAL(messages,select_row_signal,JumpToError),
ON_SIGNAL(closePage,activate_signal,OnClosePage),
ON_SIGNAL(toggleHeader,activate_signal,OnToggleHeader),
ON_SIGNAL(saveas,activate_signal,SaveAs),
ON_SIGNAL(search,activate_signal,Search),
ON_SIGNAL(repeatsearch,activate_signal,RepeatSearch),
ON_SIGNAL(hilite,activate_signal,Hilite)
END_SIGNAL_MAP
//////////////////////////////////////////////////
/*
*/
VDKBEditor::VDKBEditor(VDKForm* owner):
VDKForm(owner)
{
ForceToClose = false;
#ifdef HAVE_HINTS
// load hints database
hintDb = new HintDb;
VDKBuilder *app = (VDKBuilder*) Application();
VDKString user = app->user_home;
sprintf(buff,"%s/.vdkb/lang/%s.%s",
(char*) user,"vdkhints","en");
if (LoadHintDb(buff))
{
#ifdef VDKBDEBUG
printf("\n%s successfully loaded",buff);
fflush(stdout);
#endif
;
}
else
{
#ifdef VDKBDEBUG
printf("\n%s error loading",buff);
fflush(stdout);
#endif
;
}
#endif
}
/*
*/
VDKBEditor::~VDKBEditor()
{
#ifdef HAVE_HINTS
if(hintDb)
delete hintDb;
#endif
}
/*
*/
void
VDKBEditor::Setup()
{
Title = editor_prompts[0];
VDKPaned* paned = new VDKPaned(this);
nbook = new VDKBNotebook(this);
paned->Pack(nbook,1,true,false);
messages = new VDKCustomList(this,1,NULL,GTK_SELECTION_EXTENDED);
paned->Pack(messages,2,false,true);
Add(paned);
bar = new VDKPanelbar(this,3);
bar->Panels()[2]->Justify = GTK_JUSTIFY_RIGHT;
Add(bar,r_justify,false,false,false);
// makes a pop menu
popmenu = new VDKMenu(this);
toggleHeader = new VDKMenuItem(popmenu,editor_prompts[3]);
closePage = new VDKMenuItem(popmenu,editor_prompts[4]);
saveas = new VDKMenuItem(popmenu,editor_prompts[5]);
popmenu->Separator();
search = new VDKMenuItem(popmenu,main_menu_prompts[30]);
sprintf(buff,"%s (F3)",main_menu_prompts[31]);
repeatsearch = new VDKMenuItem(popmenu,buff);
sprintf(buff,"%s (F4)",main_menu_prompts[33]);
undo = new VDKMenuItem(popmenu,buff);
sprintf(buff,"%s (F5)",main_menu_prompts[34]);
redo = new VDKMenuItem(popmenu,buff);
hilite = new VDKMenuItem(popmenu,main_menu_prompts[35]);
// since redo capabilty isn't yet implemented, set them as disabled
redo->Enabled = false;
// hilite enabled in HAVE_SYNTAX only
#ifndef HAVE_SYNTAX
hilite->Enabled = false;
#endif
/*
since popmenu could never be popped
better add it to form items even if VDKMenu::Popup()
does the job. VDKList::add() will ensure won't be added twice
and GC will detect it even if never popped.
*/
AddItem(popmenu);
/*
Signals will come up from one of VDKBText's
contained into VDKBNotebook pages.
Since these signals are not provided by gtk+
put <gtk> arg as false, so will be dispatched by VDK
*/
SignalConnect(nbook,"text_changed",&VDKBEditor::OnTextChanged,false);
SignalConnect(nbook,"line_changed",&VDKBEditor::OnLineChanged,false);
SignalConnect(nbook,"pop_menu",&VDKBEditor::OnPopMenu,false);
SignalConnect(nbook,"repeat_search_text",&VDKBEditor::RepeatSearch,false);
SignalConnect(nbook,"no_more_undo",&VDKBEditor::NoMoreUndo,false);
}
/*
*/
void
VDKBEditor::OnShow(VDKForm*)
{
VDKPoint ownerPos = Owner()->Position;
VDKPoint ownerSize = Owner()->Usize;
VDKPoint p(270,ownerPos.Y()+ownerSize.Y()+60);
Position = p;
VDKPoint size = VDKBuilder::ideDefaults.editor.size;
SetSize(size.X(),size.Y());
}
/*
*/
void VDKBEditor::AddNewUnit()
{
// read defaults
char* cc_ext = (char*) VDKBuilder::ideDefaults.unit.cc_ext;
char* h_ext = (char*) VDKBuilder::ideDefaults.unit.h_ext;
char* unit = (char*) VDKBuilder::ideDefaults.unit.def_name;
int count = VDKBuilder::ideDefaults.unit.count;
VDKBText *text;
// add .cc
sprintf(buff,"%s%d.%s",unit,count,cc_ext);
text = new VDKBText(this,true,buff);
textlist.add(text);
#ifdef HAVE_SYNTAX
text->Hilite = true;
#ifdef HAVE_HINTS
text->InstallHints(VDKBEditor::HintCallback,this);
#endif
#endif
nbook->AddPage(text,buff);
// add .h
sprintf(buff,"%s%d.%s",unit,count,h_ext);
text = new VDKBText(this,true,buff);
#ifdef HAVE_SYNTAX
text->Hilite = true;
#ifdef HAVE_HINTS
text->InstallHints(VDKBEditor::HintCallback,this);
#endif
#endif
textlist.add(text);
nbook->AddPage(text,buff);
// sets active page
nbook->ActivePage = textlist.size()-1;
// finished, update unit count
VDKBuilder::ideDefaults.unit.count += 1;
}
/*
*/
void VDKBEditor::AddText(char* text_name, bool editable,bool hilite)
{
VDKBText *text = new VDKBText(this,editable,text_name);
// add a text to textlist
textlist.add(text);
#ifdef HAVE_HINTS
text->InstallHints(VDKBEditor::HintCallback,this);
#endif
nbook->AddText(text,text->ShortName(),hilite);
}
//////////////////////// signal process ////////////////////
bool
VDKBEditor::JumpToError(VDKObject* )
{
char *tokens = "$%";
int t,z;
int row = messages->Selected.Row();
if(row < 0 || row >= messages->Tuples.size())
return true;
VDKString errmess = messages->Tuples[row][0];
VDKString file;
int line = 0;
char* err = new char[strlen((char*) errmess)+1];
strcpy(err,(char*) errmess);
// change first two ":" with tokens
for(t = 0,z=0; err[t]; t++)
{
if( err[t] == ':')
{
err[t] = tokens[z++];
if(!tokens[z])
break;
}
}
char * p;
if( (p = ExtractWord(err,buff,"","$")) )
file = buff;
if ( (p = ExtractWord(err,buff,"$","%")) )
line = atoi(buff);
if((line == 0) || access((char*) file ,F_OK) || ( ! GoToLine(file,line)) )
{
gdk_beep();
bar->Panels()[0]->Caption = "no error to go";
}
delete err;
return true;
}
/*
*/
bool
VDKBEditor::GoToLine(VDKString& file, int line)
{
int t;
TextListIterator li(textlist);
// activate or load a new text
for(t=0;li;li++,t++)
{
VDKString temp = li.current()->Filename();
if( temp == file)
{
nbook->ActivePage = t;
break;
}
}
// not found, so load a new text
if(t >= textlist.size())
{
AddText((char*) file, true,true);
nbook->ActivePage = t;
}
// finally goes to line
return textlist[t]->GoToLine(line);
}
/*
*/
bool
VDKBEditor::OnTextChanged(VDKObject* )
{
// editor says that some text was changed
// so let's user to know
int activePage = nbook->ActivePage;
char* p = textlist[activePage]->ShortName();
if(textlist[activePage]->Changed)
{
sprintf(buff,"%s%s",editor_prompts[1],p);
bar->Panels()[0]->Caption = buff;
}
int line = textlist[activePage]->CurrentLine;
sprintf(buff,"%s%d",editor_prompts[2],line);
bar->Panels()[2]->Caption = buff;
return true;
}
/*
*/
bool
VDKBEditor::OnPageChanged(VDKObject* )
{
int activePage = nbook->ActivePage;
char* p = textlist[activePage]->ShortName();
if(textlist[activePage]->Changed)
{
sprintf(buff,"%s%s",editor_prompts[1],p);
bar->Panels()[0]->Caption = buff;
}
else
bar->Panels()[0]->Caption = " ";
int line = textlist[activePage]->CurrentLine;
sprintf(buff,"%s%d",editor_prompts[2],line);
bar->Panels()[2]->Caption = buff;
// set to 0 last pos in search.
last_pos = 0;
return true;
}
/*
*/
bool
VDKBEditor::OnLineChanged(VDKObject* )
{
int activePage = nbook->ActivePage;
int line = textlist[activePage]->CurrentLine;
sprintf(buff,"%s%d",editor_prompts[2],line);
bar->Panels()[2]->Caption = buff;
return true;
}
/*
*/
bool
VDKBEditor::CanClose()
{
UpdateFiles();
return true;
/*
// can be closed via mainform only.
if(ForceToClose)
return true;
else
{
Visible = false;
return false;
}
*/
}
/*
*/
void
VDKBEditor::UpdateFiles()
{
TextListIterator li(textlist);
// skip first page that is always
// an uneditable makefile image
li++;
for(;li;li++)
{
// has to be saved ?
if(li.current()->Changed)
{
sprintf(buff,"%s\n%s",
(char*) li.current()->Filename(),
user_messages[user_request_save]);
if(Application()->MessageBox(APPNAME,
buff,
MB_ICONINFORMATION|MB_YESNO,
user_messages[user_ok],
user_messages[user_no]) == IDYES)
{
// never saved
// it's a new unit, changes sentinel in .h
if(access(li.current()->Filename(),F_OK))
{
// ask to user
FileStringArray selections;
VDKFileSaveAsDialog *child =
new VDKFileSaveAsDialog(this,&selections,
file_dialog_prompts[3]);
child->ShowModal();
if(selections.size() > 0)
{
UpdateUnit(li.current(),selections[0]);
li.current()->SaveToFile(selections[0]);
}
}
// or unsaved ?
else
li.current()->SaveToFile((char*) li.current()->Filename());
li.current()->Changed = false;
}
else
// user forced to be considered saved
li.current()->Changed = false;
}
}
}
/*
*/
void
VDKBEditor::FillMessages(VDKBStringList* list)
{
messages->Clear();
messages->Freeze();
VDKBStringListIterator li(*list);
for(;li;li++)
{
char* p = (char*) li.current();
messages->AddRow(&p);
}
messages->Thaw();
if(list->size() > 0)
messages->SelectRow(0,0);
}
/*
*/
bool
VDKBEditor::OnPopMenu(VDKObject* )
{
int activePage = nbook->ActivePage;
if(activePage == 0)
return true;
repeatsearch->Enabled = match != NULL;
popmenu->Popup();
return TRUE;
}
/*
*/
bool
VDKBEditor::OnClosePage(VDKObject* )
{
int activePage = nbook->ActivePage;
VDKBText* text;
if(activePage < 0 || activePage >= textlist.size())
return true;
else
text = textlist[activePage];
//
if(text->Changed)
{
sprintf(buff,"%s\n%s",
(char*) text->Filename(),
user_messages[user_request_save]);
if(Application()->MessageBox(APPNAME,
buff,
MB_ICONINFORMATION|MB_YESNO,
user_messages[user_ok],
user_messages[user_no]) == IDYES)
{
// never saved
if(access(text->Filename(),F_OK))
{
// ask to user
FileStringArray selections;
VDKFileSaveAsDialog *child =
new VDKFileSaveAsDialog(this,&selections,
file_dialog_prompts[3]);
child->ShowModal();
if(selections.size() > 0)
{
UpdateUnit(text,selections[0]);
text->SaveToFile(selections[0]);
}
}
// or unsaved ?
else
text->SaveToFile((char*) text->Filename());
text->Changed = false;
}
}
/* removes text from list and notebook
currently a bug into gtk_notebook_remove_page(int)
when gtk_text is patched by Mailund patch.
this sequence sigsegvs:
1. open a page into editor
2. close the page
3. open it again
4. close it: sigsegv's gtk_note_book_remove_page()
sigh :-(
*/
if(textlist.unlink(activePage))
nbook->RemovePage(activePage);
OnPageChanged(NULL);
return true;
}
/*
*/
void
VDKBEditor::UpdateUnit(VDKBText* text, VDKString& rep_s)
{
// char* cc_ext = (char*) VDKBuilder::ideDefaults.unit.cc_ext;
char* h_ext = (char*) VDKBuilder::ideDefaults.unit.h_ext;
VDKString ext;
VDKString name = text->ShortName();
VDKString replace;
char *z = get_shortfilename(rep_s);
if(z) replace = z;
else return;
if(!name.isNull())
{
// extract name and extension
char *p = get_extension((char*) name);
if(p) { *p = '\0'; p++; ext = p; }
else return;
p = get_extension(replace);
if(p) *p = '\0';
else return;
}
else
return;
// change sentinel
if(!strcmp(ext,h_ext))
{
sprintf(buff,"_%s_h",(char*) name);
VDKString match = buff;
sprintf(buff,"_%s_h",(char*) replace);
replace = buff;
int pos = text->Search(match, 0, true);
if(pos>=0)
{
pos = Replace(text,pos,match,replace);
pos = text->Search(match, pos, true);
}
if(pos>=0)
pos = Replace(text,pos,match,replace);
}
}
int
VDKBEditor::Replace(VDKBText* text, int pos, char* match, char* replace)
{
text->Pointer = pos;
text->ForwardDelete(strlen(match));
text->Pointer = pos;
text->TextInsert(replace);
return pos+strlen(replace);
}
/*
*/
bool
VDKBEditor::OnToggleHeader(VDKObject* )
{
char* cc_ext = (char*) VDKBuilder::ideDefaults.unit.cc_ext;
char* h_ext = (char*) VDKBuilder::ideDefaults.unit.h_ext;
int activePage = nbook->ActivePage;
VDKBText* text;
if(activePage < 0 || activePage >= textlist.size())
return true;
else
text = textlist[activePage];
// look for that
VDKString name = text->Filename();
VDKString ext;
char* p = get_extension((char*) name);
if(p)
{
*p++ = '\0';
ext = p;
sprintf(buff,"%s.%s",(char*) name,
(!strcmp(ext,cc_ext)) || (!strcmp(ext,"c")) ?
h_ext :
cc_ext);
name = buff;
}
else
return true;
// search in list
int t = 0;
bool found = false;
bool exists = !access(name,F_OK);
TextListIterator li(textlist);
for(;li;li++,t++)
{
if(! strcmp(li.current()->Filename(),name))
{
found = true;
break;
}
}
if(found && exists)
{
nbook->ActivePage = t;
return true;
}
else if(! found && exists)
{
AddText(name,true,true);
nbook->ActivePage = textlist.size()-1;
}
else if(! exists)
{
FileStringArray selections;
VDKFileDialog *child = new VDKFileDialog(this,&selections,
file_dialog_prompts[0]);
sprintf(buff,"*.%s",
(!strcmp(ext,cc_ext)) || (!strcmp(ext,"c")) ?
h_ext :
cc_ext);
child->Filter = buff;
child->ShowModal();
if(selections.size() > 0)
AddText(selections[0],true,true);
}
return true;
}
/*
*/
bool
VDKBEditor::SaveAs(VDKObject* )
{
int activePage = nbook->ActivePage;
FileStringArray selections;
VDKFileSaveAsDialog *child =
new VDKFileSaveAsDialog(this,&selections,
file_dialog_prompts[3]);
child->ShowModal();
if(selections.size() <= 0)
return true;
VDKBText* text = textlist[activePage];
text->Filename(selections[0]);
text->SaveToFile((char*) text->Filename());
text->Changed = false;
#ifdef VDKBDEBUG
printf("\nsaved:%s",(char*) text->Filename());
fflush(stdout);
#endif
nbook->Pages[activePage]->TabLabel->Caption = text->ShortName();
return true;
}
/*
*/
bool
VDKBEditor::Search(VDKObject*)
{
char* st = NULL;
int activePage = nbook->ActivePage;
if(activePage == 0)
return true;
VDKBSearchForm *dlg = new VDKBSearchForm(this,&st);
dlg->Setup();
dlg->ShowModal();
// dlg return st to search newly allocated (or NULL)
if(st)
{
last_pos = 0;
if(match)
delete match;
match = new char[strlen(st)+1];
strcpy(match,st);
delete st;
VDKBText* text;
text = textlist[activePage];
last_pos = text->Search(match, last_pos, true);
last_pos = last_pos > 0 ? last_pos + strlen(match): last_pos;
}
return true;
}
/*
*/
bool
VDKBEditor::RepeatSearch(VDKObject*)
{
VDKBText* text;
int activePage = nbook->ActivePage;
if(activePage == 0 || ! match)
return true;
else
text = textlist[activePage];
int pos = text->Search(match, last_pos, true);
sprintf(buff,"%s\n%s",
search_dialog_prompts[19],
search_dialog_prompts[20]);
if(pos >= 0)
last_pos = pos+strlen(match);
else if(Application()->MessageBox(APPNAME,
buff,
MB_ICONINFORMATION|MB_YESNO,
user_messages[user_ok],
user_messages[user_no]) == IDYES)
{
last_pos = 0;
RepeatSearch(NULL);
}
return true;
}
/*
*/
bool
VDKBEditor::NoMoreUndo(VDKObject*)
{
sprintf(buff,"%s",editor_prompts[6]);
bar->Panels()[0]->Caption = buff;
gdk_beep();
return true;
}
/*
*/
void
VDKBEditor::ReplaceText(void)
{
VDKBText* text;
int activePage = nbook->ActivePage;
if(activePage <= 0)
return ;
else
text = textlist[activePage];
VDKBReplaceForm *dlg = new VDKBReplaceForm(this,text);
dlg->Setup();
dlg->ShowModal();
}
/*
*/
/*
*/
bool
VDKBEditor::Hilite(VDKObject* )
{
VDKBText* text;
int activePage = nbook->ActivePage;
if(activePage <= 0)
return true;
else
text = textlist[activePage];
#ifdef HAVE_SYNTAX
VDKBMainForm* ownerform = (VDKBMainForm*) Owner();
ownerform->StartTimer();
sprintf(buff,"%s:%s",editor_prompts[7],text->Filename());
bar->Panels()[0]->Caption = buff;
gtk_editor_hilite_buffer (GTK_EDITOR(text->WrappedWidget()));
bar->Panels()[0]->Caption = editor_prompts[8];
ownerform->StopTimer();
#endif
return true;
}
#ifdef HAVE_HINTS
/*
*/
bool
VDKBEditor::LoadHintDb(char* fn)
{
VDKBHint hint;
char line[1024],c,*p;
char match[128],text[1024];
if(! hintDb)
return false;
FILE *fp = fopen(fn,"r");
if(!fp )
return false;
p = line;
while ((c = fgetc(fp)) != EOF )
{
// only tab is used to format hints
if(c != '\t')
*p++ = c;
if(c == '}')
{
*++p = '\0';
p = line;
if(ExtractWord(line,match,"[","]") &&
ExtractWord(line,text,"{","}") )
{
hint.match = match;
hint.text = text;
hintDb->add(hint);
}
}
}
fclose(fp);
return true;
}
#endif
/*
* ===========================
* VDK Builder
* Version 0.1
* Revision 0.0
* November 1998
* ===========================
*
* Copyright (C) 1998,1999 Mario Motta
* Developed by Mario Motta <mmotta@guest.net>
*
* Based on VDK Library
* Copyright (C) 1998, Mario Motta
*
* 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#ifndef _vdkb_editor_h
#define _vdkb_editor_h
///////////////////////
#include <vdk/vdk.h>
#include <vdkb_text.h>
#include <vdkb_nbook.h>
#include <vdkb_unit.h>
#include <vdkb_types.h>
#include <vdk/panelbar.h>
// for safe
#ifndef HAVE_SYNTAX
#undef HAVE_HINTS
#endif
#ifdef HAVE_HINTS
#include <vdk/vdkbtrees.h>
struct VDKBHint
{
VDKString match,text;
bool operator==(VDKBHint& hint)
{ return match == hint.match; }
bool operator<(VDKBHint& hint)
{ return match < hint.match; }
} ;
typedef VDKBtree<VDKBHint> HintDb;
#endif
typedef VDKValueList<VDKBText*> TextList;
typedef VDKValueListIterator<VDKBText*> TextListIterator;
class VDKBEditor: public VDKForm
{
#ifdef HAVE_HINTS
protected:
HintDb* hintDb;
bool LoadHintDb(char* fn);
static char* HintCallback (char *match, gpointer data);
#endif
protected:
VDKPanelbar *bar;
bool GoToLine(VDKString& file, int line);
VDKMenu *popmenu;
VDKMenuItem *toggleHeader,*closePage,*saveas,*search,*repeatsearch;
VDKMenuItem *undo,*redo,*hilite;
void UpdateUnit(VDKBText* text,VDKString& rep);
int Replace(VDKBText* text, int pos, char* match, char* replace);
public:
//
TextList textlist;
VDKBNotebook *nbook;
VDKCustomList *messages;
bool ForceToClose;
VDKBEditor(VDKForm* owner);
virtual ~VDKBEditor();
void Setup();
void AddNewUnit();
void AddText(char* text_name, bool editable,bool hilite);
bool CanClose();
void OnShow(VDKForm*);
void FillMessages(VDKBStringList* list);
bool Search(VDKObject*);
bool RepeatSearch(VDKObject*);
void ReplaceText();
void UpdateFiles();
///////
bool OnTextChanged(VDKObject* );
bool OnPageChanged(VDKObject* );
bool OnLineChanged(VDKObject* );
bool JumpToError(VDKObject* );
bool OnPopMenu(VDKObject* );
bool OnClosePage(VDKObject* );
bool OnToggleHeader(VDKObject* );
bool SaveAs(VDKObject* );
bool NoMoreUndo(VDKObject*);
bool Hilite(VDKObject* );
DECLARE_SIGNAL_LIST(VDKBEditor);
DECLARE_SIGNAL_MAP(VDKBEditor);
};
////////////////////////
#endif