cdesktopenv/cde/programs/dtprintinfo/libUI/BaseUI.C

1041 lines
24 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: BaseUI.C /main/10 1998/07/24 16:14:23 mgreess $ */
/* *
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
* (c) Copyright 1993, 1994 International Business Machines Corp. *
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
* (c) Copyright 1993, 1994 Novell, Inc. *
*/
#include "BaseUI.h"
#ifdef NO_REGCOMP
#include <ctype.h>
#if defined(SVR4) || defined(SYSV)
#include <libgen.h>
#endif
#else
#include <regex.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(__linux__)
#include <sys/time.h>
#else
#include <sys/select.h>
#endif /* linux */
#ifdef _AIX
#include <strings.h> /* need to get bzero defined */
#endif /* _AIX */
#if defined(aix)
extern "C"
{
extern int strcasecmp(const char *, const char *);
}
#endif
#define IsContainer(p) (p->UIClass() == CONTAINER)
#ifdef DEBUG
#define PrintObject() if (trace_calls) fprintf(stderr, " %s\n", _name);
#else
#define PrintObject()
#endif
int BaseUI::_UniqueID = 1;
BaseUI::BaseUI(BaseUI *parent,
const char *name,
const char *category)
{
EnterFunction("BaseUI::BaseUI");
_id = _UniqueID++;
_name = STRDUP(name);
PrintObject();
_category = STRDUP(category);
if (parent)
{
_viewStyle = parent->_viewStyle;
_iconStyle = parent->_iconStyle;
_visible = parent->_visible;
_active = parent->_active;
}
else
{
_viewStyle = GRID;
_iconStyle = LARGE_ICON;
_visible = true;
_active = true;
}
_update_message = NULL;
_selected = false;
_parent = parent;
_children = NULL;
_numChildren = 0;
_allChildren = NULL;
_numAllChildren = 0;
_has_been_opened = false;
_opened = false;
AddToParent();
AddToParentContainer();
BaseUI *p = _parent;
while (p && !IsContainer(p))
{
p->NotifyCreate(this);
p = p->_parent;
}
if (p && IsContainer(p))
p->NotifyCreate(this);
LeaveFunction("BaseUI::BaseUI");
PrintObject();
}
BaseUI::~BaseUI()
{
EnterFunction("BaseUI::~BaseUI()");
PrintObject();
BaseUI *p = _parent;
DeleteChildren();
DeleteFromParent();
DeleteFromParentContainer();
while (p)
{
if (IsContainer(p))
{
if (p->UISubClass() == ICON_LIST ||
p->UISubClass() == SCROLLED_ICON_LIST)
break;
if (!IsContainer(p->_parent) && p->_parent->UIClass() != ICON)
break;
}
p->NotifyDelete(this);
p = p->_parent;
}
if (p && IsContainer(p))
p->NotifyDelete(this);
delete(_update_message);
delete []_children;
delete []_allChildren;
LeaveFunction("BaseUI::~BaseUI()");
PrintObject();
free(_category);
free(_name);
}
void BaseUI::ContextualHelp()
{
DoContextualHelp();
}
void BaseUI::Refresh()
{
DoRefresh();
}
void BaseUI::ToFront()
{
DoToFront();
}
void BaseUI::Parent(BaseUI *new_parent)
{
if (SetParent(new_parent))
{
// need to write this
;
}
}
void BaseUI::Open(boolean flag)
{
if (SetOpen(flag))
{
_has_been_opened = true;
_opened = flag;
BaseUI *p = _parent;
while (p && !IsContainer(p))
{
p->NotifyOpen(this);
p = p->_parent;
}
if (p && IsContainer(p))
p->NotifyOpen(this);
}
}
void BaseUI::AddToParent()
{
if (!_parent)
return;
BaseUI **new_children;
int i;
new_children = new BaseUI*[_parent->_numChildren + 1];
for (i = 0; i < _parent->_numChildren; i++)
new_children[i] = _parent->_children[i];
delete []_parent->_children;
_parent->_children = new_children;
_parent->_children[_parent->_numChildren] = this;
_parent->_numChildren++;
}
void BaseUI::DeleteFromParent()
{
if (!_parent)
return;
BaseUI **new_children;
int i, index;
index = 0;
new_children = new BaseUI*[_parent->_numChildren - 1];
for (i = 0; i < _parent->_numChildren; i++)
if (_parent->_children[i] != this)
new_children[index++] = _parent->_children[i];
delete []_parent->_children;
_parent->_children = new_children;
_parent->_numChildren--;
}
void BaseUI::DeleteChildren()
{
EnterFunction("BaseUI::DeleteChildren()");
PrintObject();
if (_numChildren)
{
BaseUI **kids = new BaseUI*[_numChildren];
int i, j, n = _numChildren;
// Save children first before deleting a child since the destructor
// updates the _children variable
for (i = 0; i < n; i++)
kids[i] = _children[i];
for (i = 0; i < n; i++)
{
for (j = 0; j < _numChildren; j++)
if (_children[j] == kids[i])
{
delete kids[i];
break;
}
}
delete []kids;
}
LeaveFunction("BaseUI::DeleteChildren()");
PrintObject();
}
BaseUI * BaseUI::ContainerParent()
{
BaseUI *parent = this;
while (parent && !IsContainer(parent))
parent = parent->_parent;
return parent;
}
void BaseUI::AddToParentContainer()
{
BaseUI *parent;
if (!(parent = ContainerParent()))
return;
BaseUI **new_children;
int i;
new_children = new BaseUI*[parent->_numAllChildren + 1];
for (i = 0; i < parent->_numAllChildren; i++)
new_children[i] = parent->_allChildren[i];
delete []parent->_allChildren;
parent->_allChildren = new_children;
parent->_allChildren[parent->_numAllChildren] = this;
parent->_numAllChildren++;
}
void BaseUI::DeleteFromParentContainer()
{
BaseUI *parent;
if (!(parent = ContainerParent()))
return;
BaseUI **new_children;
int i, index;
index = 0;
new_children = new BaseUI*[parent->_numAllChildren - 1];
for (i = 0; i < parent->_numAllChildren; i++)
if (parent->_allChildren[i] != this)
new_children[index++] = parent->_allChildren[i];
delete []parent->_allChildren;
parent->_allChildren = new_children;
parent->_numAllChildren--;
}
boolean BaseUI::HandleHelpRequest()
{
BaseUI *parent = _parent;
while (parent && parent->HandleHelpRequest() == false)
parent = parent->_parent;
return true;
}
void BaseUI::SetVisible(boolean flag)
{
if (SetVisiblity(flag))
{
_visible = flag;
BaseUI *p = _parent;
while (p)
{
if (IsContainer(p))
{
if (p->UISubClass() == ICON_LIST ||
p->UISubClass() == SCROLLED_ICON_LIST)
break;
if (!IsContainer(p->_parent) && p->_parent->UIClass() != ICON)
break;
}
p->NotifyVisiblity(this);
p = p->_parent;
}
if (p && IsContainer(p))
p->NotifyVisiblity(this);
}
}
// Set visiblity, calls derived function SetVisiblity
void BaseUI::Visible(boolean flag)
{
if (UIClass() != CONTAINER &&
UIClass() != MAIN_WINDOW &&
UIClass() != DIALOG &&
UIClass() != APPLICATION)
{
int i;
SetVisible(flag);
for (i = 0; i < _numChildren; i++)
if (!IsContainer(_children[i]))
_children[i]->Visible(flag);
}
else
SetVisible(flag);
}
// Set sensitivity, calls derived function SetActivity
void BaseUI::Active(boolean flag)
{
if (UIClass() != CONTAINER)
{
int i;
if (flag == true)
{
if (SetActivity(flag))
_active = flag;
for (i = 0; i < _numChildren; i++)
if (!IsContainer(_children[i]))
_children[i]->Active(flag);
}
else
{
for (i = 0; i < _numChildren; i++)
if (!IsContainer(_children[i]))
_children[i]->Active(flag);
if (SetActivity(flag))
_active = flag;
}
}
else if (SetActivity(flag))
_active = flag;
}
// Set view, calls derived function SetIcon
void BaseUI::ContainerView(ViewStyle viewStyle)
{
if (UIClass() == CONTAINER)
{
int i;
for (i = 0; i < _numAllChildren; i++)
if (!IsContainer(_allChildren[i]))
_allChildren[i]->ContainerView(viewStyle);
}
_viewStyle = viewStyle;
}
// Set view, calls derived function SetIcon
void BaseUI::IconView(IconStyle iconStyle)
{
if (UIClass() == CONTAINER)
{
int i;
for (i = 0; i < _numAllChildren; i++)
if (IsContainer(_allChildren[i]))
{
if (UISubClass() == SCROLLED_ICON_LIST || UISubClass() == ICON_LIST)
_allChildren[i]->IconView(iconStyle);
}
else
_allChildren[i]->IconView(iconStyle);
}
if (SetIcon(iconStyle))
_iconStyle = iconStyle;
}
// Set selected status, calls derived function SetSelected
void BaseUI::Selected(boolean flag)
{
if (SetSelected(flag))
{
_selected = flag;
BaseUI *p = _parent;
while (p)
{
if (IsContainer(p))
{
if (p->UISubClass() == ICON_LIST ||
p->UISubClass() == SCROLLED_ICON_LIST)
break;
if (!IsContainer(p->_parent) && p->_parent->UIClass() != ICON)
break;
}
p->NotifySelected(this);
p = p->_parent;
}
if (p && IsContainer(p))
p->NotifySelected(this);
}
}
// Set name, calls derived function SetCategory
void BaseUI::Category(char *category)
{
if (SetCategory(category))
{
free(_category);
_category = STRDUP(category);
}
}
// Set name, calls derived function SetName
void BaseUI::Name(char *name)
{
if (SetName(name))
{
free(_name);
_name = STRDUP(name);
}
}
// Select/UnSelected all immediate children
void BaseUI::SelectAll(boolean select_status)
{
int i;
for (i = 0; i < _numChildren; i++)
{
_children[i]->Selected(select_status);
if (UISubClass() == SCROLLED_ICON_LIST || UISubClass() == ICON_LIST)
_children[i]->SelectAll(select_status);
}
}
// Select/UnSelected all children, and their children, etc...
void BaseUI::SelectAllDescendants(boolean select_status)
{
int i;
if (UIClass() == CONTAINER)
for (i = 0; i < _numChildren; i++)
_children[i]->Selected(select_status);
else
for (i = 0; i < _numChildren; i++)
{
_children[i]->Selected(select_status);
if (!IsContainer(_children[i]))
_children[i]->SelectAllDescendants(select_status);
}
}
// Open/Close all children, and their children, etc...
void BaseUI::OpenAllDescendants(boolean opened)
{
int i;
if (UIClass() == CONTAINER)
for (i = 0; i < _numChildren; i++)
_children[i]->Open(opened);
else
{
if (opened)
for (i = 0; i < _numChildren; i++)
{
_children[i]->Open(opened);
if (!IsContainer(_children[i]))
_children[i]->OpenAllDescendants(opened);
}
else
for (i = 0; i < _numChildren; i++)
{
if (!IsContainer(_children[i]))
_children[i]->OpenAllDescendants(opened);
_children[i]->Open(opened);
}
}
}
void BaseUI::Selection(int *n_items,
BaseUI ***items)
{
if (UIClass() != CONTAINER)
{
if (items)
*items = NULL;
*n_items = 0;
return;
}
boolean isScrolledList;
if (UISubClass() == SCROLLED_ICON_LIST || UISubClass() == ICON_LIST)
isScrolledList = true;
else
isScrolledList = false;
int i;
*n_items = 0;
for (i = 0; i < _numAllChildren; i++)
if (!IsContainer(_allChildren[i]) && _allChildren[i]->Selected())
(*n_items)++;
else if (IsContainer(_allChildren[i]) && isScrolledList)
{
int tmp;
_allChildren[i]->Selection(&tmp);
(*n_items) += tmp;
}
if (!items)
return;
if (*n_items == 0)
*items = NULL;
else
{
BaseUI **list = new BaseUI*[*n_items];
*n_items = 0;
for (i = 0; i < _numAllChildren; i++)
if (!IsContainer(_allChildren[i]) && _allChildren[i]->Selected())
list[(*n_items)++] = _allChildren[i];
else if (IsContainer(_allChildren[i]) && isScrolledList)
{
int tmp;
BaseUI **tmp1;
_allChildren[i]->Selection(&tmp, &tmp1);
int j, k = *n_items + tmp;
for (j = *n_items; j < k; j++)
list[(*n_items)++] = tmp1[j];
delete []tmp1;
}
*items = list;
}
}
int BaseUI::NumContainerChildren()
{
BaseUI *container = ContainerParent();
if (container)
return container->_numAllChildren;
else
return 0;
}
BaseUI ** BaseUI::ContainerChildren()
{
BaseUI *container = ContainerParent();
if (container)
return container->_allChildren;
else
return NULL;
}
int BaseUI::NumSiblings()
{
if (_parent)
return _parent->_numChildren;
else
return 0;
}
BaseUI ** BaseUI::Siblings()
{
if (_parent)
return _parent->_children;
else
return NULL;
}
void BaseUI::_Find(void *pattern, int depth, int *n_matches,
BaseUI ***matches, SelectProc select_proc,
boolean regular_expression, boolean case_sensitive,
boolean find_by_name, int cur_depth)
{
if (depth != 0 && cur_depth == depth)
return;
BaseUI **children = _children;
int n_children = _numChildren;
int i;
for (i = 0; i < n_children; i++)
{
int tmp = 0;
BaseUI **tmp1 = NULL;
children[i]->_Find(pattern, depth, &tmp, &tmp1, select_proc,
regular_expression, case_sensitive,
find_by_name, cur_depth + 1);
if (tmp)
{
int j;
if (*n_matches == 0)
*matches = (BaseUI **)malloc(sizeof(BaseUI **) * tmp);
else
*matches = (BaseUI **)realloc(*matches, sizeof(BaseUI **) *
(*n_matches + tmp));
for (j = 0; j < tmp; j++)
(*matches)[(*n_matches)++] = tmp1[j];
free(tmp1);
tmp = 0;
}
char *value;
int is_match;
if (find_by_name)
value = children[i]->_name;
else
value = children[i]->_category;
if (value)
{
if (case_sensitive)
{
if (regular_expression)
#ifdef NO_REGCOMP
is_match = (int)regex((char *)pattern, value);
#else
is_match = !regexec((regex_t *)pattern, value, (size_t)0,NULL,0);
#endif
else
is_match = !strcmp(value, (char *)pattern);
}
else
{
if (regular_expression)
#ifdef NO_REGCOMP
is_match = (int)regex((char *)pattern, value);
#else
is_match = !regexec((regex_t *)pattern, value, (size_t)0,NULL,0);
#endif
else
is_match = !strcasecmp(value, (char *)pattern);
}
}
else
is_match = 0;
if (is_match && select_proc)
is_match = (*select_proc)(children[i]);
if (is_match)
{
if (*n_matches == 0)
*matches = (BaseUI **)malloc(sizeof(BaseUI **));
else
*matches = (BaseUI **)realloc(*matches, sizeof(BaseUI **) *
(*n_matches + 1));
(*matches)[(*n_matches)++] = children[i];
}
}
}
BaseUI *BaseUI::_FindBy(char *pattern, int depth, int *n_matches,
BaseUI ***matches, SelectProc select_proc,
boolean regular_expression, boolean case_sensitive,
boolean find_by_name)
{
void *reg_expr = pattern;
#ifdef NO_REGCOMP
if (regular_expression)
{
if (case_sensitive == false)
{
char *new_pattern = new char[(strlen(pattern) * 4) + 1];
int i = 0;
char *s;
for (s = pattern; *s; s++)
{
if (isalpha((int)*s))
{
new_pattern[i++] = '[';
new_pattern[i++] = *s;
if (islower(*s))
new_pattern[i++] = (char)toupper((int)*s);
else
new_pattern[i++] = (char)tolower((int)*s);
new_pattern[i++] = ']';
}
else
new_pattern[i++] = *s;
}
new_pattern[i] = '\0';
reg_expr = regcmp(new_pattern, (char *)NULL);
delete new_pattern;
}
else
reg_expr = regcmp(pattern, (char *)NULL);
}
#else
regex_t re;
if (regular_expression)
{
int compile_flags;
if (case_sensitive)
compile_flags = REG_NOSUB;
else
compile_flags = REG_ICASE|REG_NOSUB;
if (regcomp(&re, pattern, compile_flags) != 0)
reg_expr = NULL;
else
reg_expr = &re;
}
#endif
if (!reg_expr)
{
if (n_matches)
*n_matches = 0;
if (matches)
matches = NULL;
return NULL;
}
BaseUI **_matches = NULL;
int _n_matches = 0;
_Find(reg_expr, depth, &_n_matches, &_matches, select_proc,
regular_expression, case_sensitive, find_by_name, 0);
#ifndef NO_REGCOMP
if (regular_expression)
regfree(&re);
#endif
if (n_matches)
*n_matches = _n_matches;
if (matches)
{
*matches = _matches;
if (_n_matches)
return _matches[0];
else
return NULL;
}
else if (_n_matches)
{
BaseUI *a_match = _matches[0];
free(_matches);
return a_match;
}
return NULL;
}
BaseUI *BaseUI::FindByName(char *pattern, int depth, int *n_matches,
BaseUI ***matches, SelectProc select_proc,
boolean regular_expression, boolean case_sensitive)
{
return _FindBy(pattern, depth, n_matches, matches, select_proc,
regular_expression, case_sensitive, true);
}
BaseUI *BaseUI::FindByCategory(char *pattern, int depth, int *n_matches,
BaseUI ***matches, SelectProc select_proc,
boolean regular_expression,
boolean case_sensitive)
{
return _FindBy(pattern, depth, n_matches, matches, select_proc,
regular_expression, case_sensitive, false);
}
void BaseUI::OrderByName(boolean /*flag*/)
{
}
void BaseUI::GroupByCategory(boolean /*flag*/)
{
}
// Calls derived class's SetOrder function
void BaseUI::Order(int new_position)
{
if (!_parent || new_position < 0 || new_position > _parent->_numChildren)
return;
int current_position = Order();
if (new_position == current_position)
return;
BaseUI **children = _parent->_children;
int i;
if (current_position < new_position)
for (i = current_position; i < new_position; i++)
children[i] = children[i + 1];
else
for (i = current_position; i > new_position; i--)
children[i] = children[i - 1];
children[new_position] = this;
(void) SetOrder(new_position);
}
int BaseUI::Order()
{
int i = 0;
if (_parent)
{
for (i = 0; i < _parent->_numChildren; i++)
if (_parent->_children[i] == this)
break;
}
return i;
}
boolean BaseUI::IsVisible()
{
return DoIsVisible();
}
void BaseUI::MakeVisible()
{
if (_visible == false)
return;
BaseUI *parent = Parent();
if (parent)
parent->MakeVisible();
if (_visible && parent)
DoMakeVisible();
}
void BaseUI::BeginUpdate()
{
_update = false;
DoBeginUpdate();
}
void BaseUI::EndUpdate()
{
_update = true;
DoEndUpdate();
}
void BaseUI::UpdateMessage(const char *message)
{
free(_update_message);
_update_message = STRDUP(message);
DoUpdateMessage(_update_message);
}
boolean BaseUI::ObjectExists(int unique_id)
{
int i;
boolean found = false;
for (i = 0; i < _numChildren; i++)
{
BaseUI *child = _children[i];
if (unique_id == _children[i]->_id)
{
found = true;
break;
}
else if (found = _children[i]->ObjectExists(unique_id))
break;
}
return found;
}
#define PrintBoolean(flag) flag ? "True" : "False"
// Dump object to stdout
void BaseUI::Dump(boolean verbose, int level)
{
int i;
for (i = 0; i < level; i++)
printf(" ");
printf("%s : %s\n", _name, UIClassName());
if (verbose)
{
for (i = -1; i <= level; i++) printf(" ");
printf("Category : %s\n", _category ? _category : "");
for (i = -1; i <= level; i++) printf(" ");
printf("HasBeenOpened : %s\n", PrintBoolean(_has_been_opened));
for (i = -1; i <= level; i++) printf(" ");
printf("Opened : %s\n", PrintBoolean(_opened));
for (i = -1; i <= level; i++) printf(" ");
printf("Visible : %s\n", PrintBoolean(_visible));
for (i = -1; i <= level; i++) printf(" ");
printf("Active : %s\n", PrintBoolean(_active));
for (i = -1; i <= level; i++) printf(" ");
printf("Selected : %s\n", PrintBoolean(_selected));
for (i = -1; i <= level; i++) printf(" ");
switch (_viewStyle)
{
case AS_PLACED: printf("ViewStyle : AS_PLACED\n"); break;
case GRID: printf("ViewStyle : GRID\n"); break;
case BROWSER: printf("ViewStyle : BROWSER\n"); break;
case TREE: printf("ViewStyle : TREE\n"); break;
case PROPERTIES: printf("ViewStyle : PROPERTIES\n"); break;
}
for (i = -1; i <= level; i++) printf(" ");
switch (_iconStyle)
{
case NAME_ONLY: printf("IconStyle : NAME_ONLY\n"); break;
case LARGE_ICON: printf("IconStyle : LARGE_ICON\n"); break;
case SMALL_ICON: printf("IconStyle : SMALL_ICON\n"); break;
case DETAILS: printf("IconStyle : DETAILS\n"); break;
}
for (i = -1; i <= level; i++) printf(" ");
printf("Number Children = %d\n", _numChildren);
}
}
// Dump object hierarchy to stdout
void BaseUI::DumpHierarchy(boolean verbose, int level)
{
Dump(verbose, level);
int i;
for (i = 0; i < _numChildren; i++)
_children[i]->DumpHierarchy(verbose, level + 1);
}
void BaseUI::AddTimeOut(TimeOutCallback timeoutCB, void *data, long interval)
{
if (timeoutCB)
{
if (data)
SetAddTimeOut(timeoutCB, data, interval);
else
SetAddTimeOut(timeoutCB, this, interval);
}
}
int BaseUI::MicroSleep(long usecs)
{
struct timeval timeoutVal;
timeoutVal.tv_sec = usecs / 1000000;
timeoutVal.tv_usec = usecs & 1000000;
fd_set rdmask;
fd_set wrmask;
fd_set exmask;
FD_ZERO(&rdmask);
FD_ZERO(&wrmask);
FD_ZERO(&exmask);
return select(0,&rdmask,&wrmask,&exmask,&timeoutVal);
}
// DEBUG STUFF
#ifdef DEBUG
int BaseUI::indent = 0;
boolean BaseUI::trace_calls = false;
static char * make_header_buffer(int indent)
{
static char header_buffer[1024];
static char *leading_chars="1234567890abcdefghijklmnop";
int indx;
char c;
header_buffer[0] = '\0';
for (indx = 0 ; indx < indent; indx++)
{
c = leading_chars[indx];
header_buffer[2*indx] = leading_chars[indx];
header_buffer[2*indx +1] = ' ';
}
header_buffer[2*indx] = '\0';
return(header_buffer);
}
void BaseUI::EnterFunction(char *FunctionName)
{
char *format_buffer = new char[1024];
char *header_buffer;
if (trace_calls)
{
header_buffer = make_header_buffer(indent);
sprintf(format_buffer,"%s>: %%s %d ",header_buffer,indent);
fprintf(stderr,format_buffer,FunctionName);
indent++;
}
delete [] format_buffer;
}
void BaseUI::LeaveFunction(char *FunctionName)
{
char *format_buffer = new char[1024];
char *header_buffer;
if (trace_calls)
{
indent--;
header_buffer = make_header_buffer(indent);
sprintf(format_buffer,"%s<: %%s %d ",header_buffer,indent);
fprintf(stderr,format_buffer,FunctionName);
}
delete [] format_buffer;
}
#endif // DEBUG