cdesktopenv/cde/programs/dtappbuilder/src/ab/ab_utils.c

1365 lines
34 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
*/
/*
* $XConsortium: ab_utils.c /main/3 1995/11/06 17:13:58 rswiston $
*
* @(#)ab_utils.c 1.27 08 May 1995
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*/
/*
* File: ab_utils.c - file containing ab utilities
*/
#include <sys/param.h>
#include <Xm/Xm.h>
#include <Xm/MessageB.h>
#include <X11/cursorfont.h>
#include <ab_private/ab.h>
#include <ab_private/abobj.h>
#include <ab_private/abobj_set.h>
#include <ab_private/ab_utils.h>
#include <ab_private/pal.h>
#include <ab_private/proj.h>
#include <ab_private/trav.h>
#include <ab_private/obj.h>
#include <ab_private/objxm.h>
#include <ab_private/cgen.h>
#include <ab_private/ui_util.h>
#include "palette_ui.h"
#include "dtb_utils.h"
typedef struct INIT_WIN_POS {
Widget ref_widget;
AB_WPOS_TYPE type;
} InitWinPos;
/*************************************************************************
** **
** Private Function Declarations **
** **
**************************************************************************/
static int format_dir_name_for_user(
STRING ugly_dir,
STRING pretty_dir,
int pretty_dir_size
);
static int format_dir_name_for_system(
STRING user_dir_name,
STRING system_dir,
int system_dir_size
);
static void set_cursor(
Widget widget,
Cursor cursor,
BOOL on
);
static void track_win_iconify(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *cont_disp
);
static void track_win_leader_iconify(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *cont_disp
);
static void popdown_winCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void position_winCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void track_win_popupCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void track_win_popdownCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void track_win_destroyCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void set_windows_visibility(
BOOL show
);
static void set_window_objects_visibility(
BOOL show
);
static void exit_mboxCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void destroy_mboxCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void mwm_close_mboxCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
/*************************************************************************
** **
** Data **
** **
**************************************************************************/
static ISTRING current_dir = NULL; /* formatted for user */
static ISTRING raw_current_dir = NULL; /* full path for system */
static STRING home_env_var_name = "HOME";
static ABWindow *AB_win_head = NULL;
static ABWindow *AB_win_tail = NULL;
static ABWindow *AB_win_leader = NULL;
static int AB_stack_offset = 50;
static int AB_frame_title_height = 25;
static int AB_frame_edge_width = 5;
static int AB_min_dimension = 20;
/*************************************************************************
** **
** Function Definitions **
** **
**************************************************************************/
void
ab_position_window(
Widget widget,
Widget ref_widget,
AB_WPOS_TYPE pos_type
)
{
Widget shell, ref_shell;
Dimension shell_w, shell_h, ref_w, ref_h;
Position shell_x, shell_y, ref_x, ref_y;
int screen_w, screen_h;
int delta_w, delta_h;
if (widget == NULL || ref_widget == NULL ||
!XtIsRealized(ref_widget))
return;
shell_w = shell_h = shell_x = shell_y = 0;
ref_w = ref_h = ref_x = ref_y = 0;
/*
* Get Shell widget-id and geometry of window and its
* reference-window
*/
shell = ui_get_ancestor_shell(widget);
XtVaGetValues(shell,
XmNwidth, &shell_w,
XmNheight, &shell_h,
NULL);
ref_shell = ui_get_ancestor_shell(ref_widget);
XtVaGetValues(ref_shell,
XmNx, &ref_x,
XmNy, &ref_y,
XmNwidth, &ref_w,
XmNheight, &ref_h,
NULL);
/*
* Adjust geometry values to accommodate window-frame
*
* Also, if this routine is called before a window's contents have
* been managed, its current available dimensions may be misleadingly
* small. If so, print out a warning in debug mode...
*/
if ((int)shell_w < AB_min_dimension || (int)shell_h < AB_min_dimension)
util_dprintf(1, "ab_position_window: %s - %dx%d - size under minimum\n",
XtName(shell), shell_w, shell_h);
shell_w += (2 * AB_frame_edge_width);
shell_h += (AB_frame_title_height + AB_frame_edge_width);
ref_y -= AB_frame_title_height;
ref_x -= AB_frame_edge_width;
ref_w += (2 * AB_frame_edge_width);
ref_h += (AB_frame_title_height + AB_frame_edge_width);
screen_w = WidthOfScreen(XtScreen(widget));
screen_h = HeightOfScreen(XtScreen(widget));
switch(pos_type)
{
case AB_WPOS_TILE_RIGHT:
shell_y = ref_y;
shell_x = ref_x + ref_w;
break;
case AB_WPOS_TILE_LEFT:
shell_y = ref_y;
shell_x = ref_x - shell_w;
break;
case AB_WPOS_TILE_HORIZONTAL:
shell_y = ref_y;
/* Determine side for best fit... */
if ((int)ref_x >= (int)(screen_w - (ref_x + ref_w)) ||
(int)shell_w <= (int)ref_x)
shell_x = ref_x - shell_w; /* TILE LEFT*/
else
shell_x = ref_x + ref_w; /* TILE RIGHT */
break;
case AB_WPOS_TILE_ABOVE:
shell_x = ref_x;
shell_y = ref_y - shell_h;
break;
case AB_WPOS_TILE_BELOW:
shell_x = ref_x;
shell_y = ref_y + ref_h;
break;
case AB_WPOS_TILE_VERTICAL:
shell_x = ref_x;
/* Determine side for best fit... */
if ((int)ref_y >= (int)(screen_h - (ref_y + ref_h)) ||
(int)shell_h <= (int)ref_y)
shell_y = ref_y - shell_h; /* TILE ABOVE */
else
shell_y = ref_y + ref_h; /* TILE_BELOW */
break;
case AB_WPOS_STACK_DIAGONAL:
shell_x = ref_x + AB_stack_offset;
shell_y = ref_y + AB_stack_offset;
break;
default:
case AB_WPOS_STACK_CENTER:
delta_w = ref_w - shell_w;
shell_x = ref_x + (delta_w/2);
delta_h = ref_h - shell_h;
shell_y = ref_y + (delta_h/2);
break;
}
XtVaSetValues(shell,
XmNx, shell_x,
XmNy, shell_y,
NULL);
}
BOOL
ab_window_leader_iconified(
)
{
return(AB_win_leader->state & WindowIconified);
}
void
ab_register_window(
Widget widget,
AB_WIN_TYPE type,
unsigned long init_state,
Widget init_pos_ref_widget,
AB_WPOS_TYPE init_pos_type,
XtCallbackProc close_callback,
XtPointer close_clientdata
)
{
ABWindow *newwin;
InitWinPos *init_pos;
Widget shell = ui_get_ancestor_shell(widget);
newwin = (ABWindow*)util_malloc(sizeof(ABWindow));
newwin->widget = widget;
newwin->type = type;
newwin->state = init_state;
newwin->next = NULL;
/*
* Install a Window close callback and ensure the deleteResponse
* gets set to XmDO_NOTHING (to prevent automatic unmanaging of the
* shell's first child).
* Use parameter callback if specified, else use default which just
* pops the window down.
*/
ui_add_window_close_callback(shell,
close_callback? close_callback : popdown_winCB,
close_callback? close_clientdata : NULL,
XmDO_NOTHING);
if (type == AB_WIN_LEADER)
{
/* The Window leader is stored separately */
if (AB_win_leader == NULL)
{
AB_win_leader = newwin;
ui_add_window_iconify_handler(shell,
track_win_leader_iconify, (XtPointer)newwin);
return;
}
else
util_dprintf(1, "ab_register_window: can only have 1 Window Leader\n");
}
/*
* Append new Win Record onto linked-list
*/
if (AB_win_head == NULL) /* first one */
AB_win_head = AB_win_tail = newwin;
else
{
AB_win_tail->next = newwin;
AB_win_tail = newwin;
}
/*
* Set up handlers to track window behavior
*/
if (type == AB_WIN_WINDOW)
ui_add_window_iconify_handler(shell,
track_win_iconify, (XtPointer)newwin);
XtAddCallback(shell, XtNpopupCallback, track_win_popupCB,
(XtPointer)newwin);
XtAddCallback(shell, XtNpopdownCallback, track_win_popdownCB,
(XtPointer)newwin);
XtAddCallback(shell, XtNdestroyCallback, track_win_destroyCB,
(XtPointer)newwin);
/*
* Set up general window resources to get popup/popdown to work correctly
* We will not be using Motif's method of Managing the first child of the
* shell to get the window to popup!
*/
XtSetMappedWhenManaged(shell, False);
XtManageChild(widget);
if (init_pos_type != AB_WPOS_UNSPECIFIED)
{
init_pos = (InitWinPos*)util_malloc(sizeof(InitWinPos));
init_pos->ref_widget = init_pos_ref_widget;
init_pos->type = init_pos_type;
XtAddCallback(shell, XtNpopupCallback, position_winCB,
(XtPointer)init_pos);
}
}
void
ab_show_window(
Widget widget
)
{
ABWindow *win;
for(win = AB_win_head; win != NULL; win = win->next)
{
if (win->widget == widget)
{
if (win->state & WindowUp)
{
if (win->state & WindowIconified &&
!(AB_win_leader->state & WindowIconified))
{
/* Window is iconified, unmap it so we can change its
* initial state and remap it as Opened
*/
ui_win_show(widget, False, XtGrabNone);
}
else /* Window is already Open */
{
ui_win_front(win->widget);
}
}
/* Popup Window */
XtSetMappedWhenManaged(ui_get_ancestor_shell(win->widget), True);
switch(win->type)
{
case AB_WIN_MODAL:
ui_win_show(win->widget, True, XtGrabExclusive);
break;
default:
ui_win_show(win->widget, True, XtGrabNone);
break;
}
return;
}
}
util_dprintf(1, "ab_show_window: %s is not a registered window\n",
XtName(widget));
}
BOOL
ab_window_is_open(
Widget widget
)
{
ABWindow *win;
for(win = AB_win_head; win != NULL; win = win->next)
{
if (win->widget == widget)
return((win->state & WindowUp) &&
!(win->state & WindowIconified));
}
util_dprintf(1, "ab_window_is_open: %s is not a registered window\n",
XtName(widget));
return False;
}
static void
track_win_leader_iconify(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *cont_dispatch
)
{
switch (event->type)
{
case MapNotify: /* Leader Window Opened */
AB_win_leader->state &= (~WindowIconified);
if (InBuildMode)
{
/*
** Order is important. Objects need to be first. Modal
** dialogs can be parented off of main windows. If the
** parent is not mapped first, the dialog loses it's
** modality.
*/
set_window_objects_visibility(True);
set_windows_visibility(True);
}
break;
case UnmapNotify: /* Leader Window Iconified */
AB_win_leader->state |= WindowIconified;
if (InBuildMode)
{
set_windows_visibility(False);
set_window_objects_visibility(False);
}
break;
}
}
static void
track_win_iconify(
Widget widget,
XtPointer client_data,
XEvent *event,
Boolean *cont_disp
)
{
ABWindow *win = (ABWindow*)client_data;
switch (event->type)
{
case MapNotify:
if (InBuildMode &&
win->state & WindowIconified &&
!(AB_win_leader->state & WindowIconified))
{
win->state &= (~WindowIconified);
XtVaSetValues(widget, XtNinitialState, NormalState, NULL);
}
break;
case UnmapNotify:
/*
* We can detect that the window has been iconified
* (not popped-down) because the track_win_popdownCB
* was not called (so WindowUp is still set).
*
* Note: XtNiconic is not being used because it doesn't
* reflect the current state of the window (Xt bug??)
*/
if (InBuildMode &&
win->state & WindowUp &&
!(win->state & WindowIconified) &&
!(AB_win_leader->state & WindowIconified))
{
win->state |= WindowIconified;
XtVaSetValues(widget, XtNinitialState, IconicState, NULL);
}
break;
}
}
static void
popdown_winCB(
Widget shell,
XtPointer client_data,
XtPointer call_data
)
{
ui_win_show(shell, False, XtGrabNone);
}
static void
position_winCB(
Widget shell,
XtPointer client_data,
XtPointer call_data
)
{
InitWinPos *init_pos = (InitWinPos*)client_data;
ab_position_window(shell, init_pos->ref_widget, init_pos->type);
/* We only position the window the first time it is invoked; after
* this, the user is in control, so remove this callback and destroy
* the init data.
*/
XtRemoveCallback(shell, XtNpopupCallback, position_winCB, client_data);
util_free(init_pos);
}
static void
track_win_popupCB(
Widget shell,
XtPointer client_data,
XtPointer call_data
)
{
ABWindow *win = (ABWindow*)client_data;
win->state |= WindowUp;
}
static void
track_win_popdownCB(
Widget shell,
XtPointer client_data,
XtPointer call_data
)
{
ABWindow *win = (ABWindow*)client_data;
if (InBuildMode &&
!(AB_win_leader->state & WindowIconified))
{
win->state &= (~WindowUp);
if (win->state & WindowIconified)
{
XtVaSetValues(shell, XtNinitialState, NormalState, NULL);
win->state &= (~WindowIconified);
}
}
}
static void
track_win_destroyCB(
Widget shell,
XtPointer client_data,
XtPointer call_data
)
{
ABWindow *win = (ABWindow*)client_data;
ABWindow *prev = NULL;
ABWindow *p;
/*
* Adjust linked-list for removal of Window
*/
if (AB_win_head == win)
AB_win_head = win->next;
else
{
/* Find previous window in linked-list */
p = AB_win_head;
while (p != win)
{
prev = p;
p = p->next;
}
prev->next = win->next;
if (AB_win_tail == win)
AB_win_tail = prev;
}
/*
* Remove all tracker routines, and free Win record
*/
if (win->type == AB_WIN_WINDOW)
ui_remove_window_iconify_handler(shell, track_win_iconify,
(XtPointer)win);
XtRemoveCallback(shell, XtNpopupCallback, track_win_popupCB,
(XtPointer)win);
XtRemoveCallback(shell, XtNpopdownCallback, track_win_popdownCB,
(XtPointer)win);
util_free(win);
}
static void
set_windows_visibility(
BOOL show
)
{
ABWindow *win;
for(win = AB_win_head; win != NULL; win = win->next)
{
if (win->state & WindowUp)
{
switch(win->type)
{
case AB_WIN_MODAL:
ui_win_show(win->widget, show, XtGrabExclusive);
break;
default:
ui_win_show(win->widget, show, XtGrabNone);
break;
}
}
}
}
void
ab_takedown_windows(
)
{
set_windows_visibility(False);
}
void
ab_putback_windows(
)
{
set_windows_visibility(True);
}
static void
set_window_objects_visibility(
BOOL show
)
{
AB_TRAVERSAL trav;
ABObj project = proj_get_project();
ABObj winobj;
for (trav_open(&trav, project, AB_TRAV_WINDOWS);
(winobj = trav_next(&trav)) != NULL; )
{
if (obj_is_base_win(winobj) &&
obj_has_flag(winobj, MappedFlag))
ui_win_show(objxm_get_widget(winobj), show, XtGrabNone);
}
trav_close(&trav);
}
int
ab_update_stat_region(
AB_STATUS_INFO type,
String value
)
{
static Widget obj_type = NULL;
static Widget obj_name = NULL;
static Widget obj_pos = NULL;
static Widget obj_size = NULL;
static Widget curs_pos = NULL;
static Widget cur_module = NULL;
Widget widget = NULL;
String nullstr = " ";
switch(type)
{
case AB_STATUS_OBJ_TYPE:
if (obj_type == NULL)
obj_type = dtb_palette_ab_palette_main.object_type_field;
widget = obj_type;
break;
case AB_STATUS_OBJ_NAME:
if (obj_name == NULL)
obj_name = dtb_palette_ab_palette_main.object_name_field;
widget = obj_name;
break;
case AB_STATUS_OBJ_POS:
if (obj_pos == NULL)
obj_pos = dtb_palette_ab_palette_main.position_field;
widget = obj_pos;
break;
case AB_STATUS_OBJ_SIZE:
if (obj_size == NULL)
obj_size = dtb_palette_ab_palette_main.size_field;
widget = obj_size;
break;
case AB_STATUS_CURS_POS:
if (curs_pos == NULL)
curs_pos = dtb_palette_ab_palette_main.cursor_position_field;
widget = curs_pos;
break;
case AB_STATUS_CUR_MODULE:
if (cur_module == NULL)
cur_module = dtb_palette_ab_palette_main.editing_module_field;
widget = cur_module;
if (value == NULL)
value = "( None )";
}
if (value == NULL)
value = nullstr;
/* Update the footer to display the current object-type */
if (widget != NULL)
XtVaSetValues(widget,
XtVaTypedArg, XmNlabelString, XtRString,
value, strlen(value)+1,
NULL);
return 0;
}
/*
* Set the busy-cursor ON or OFF on all AB Windows
*/
void
ab_set_busy_cursor(
BOOL on
)
{
AB_TRAVERSAL trav;
ABObj project = proj_get_project();
ABWindow *win;
ABObj module;
ABObj winobj;
static Cursor busy_cursor = 0;
Cursor new_cursor = 0;
int num_wins;
int i;
if (busy_cursor == 0)
busy_cursor = XCreateFontCursor(XtDisplay(AB_toplevel), XC_watch);
if (on)
new_cursor = busy_cursor;
set_cursor(AB_toplevel, new_cursor, on);
/*
* Loop through Windows and set cursor on any that
* are currently UP
*/
for(win = AB_win_head; win != NULL; win = win->next)
{
if (win->state & WindowUp)
set_cursor(win->widget, new_cursor, on);
}
/* Set busy cursor for any AB windows currently up */
for (trav_open(&trav, project, AB_TRAV_MODULES);
(module = trav_next(&trav)) != NULL; )
{
num_wins = obj_get_num_children(module);
for (i = 0; i < num_wins; i++)
{
winobj = obj_get_child(module, i);
if (obj_is_window(winobj) && winobj->ui_handle != NULL)
set_cursor((Widget)winobj->ui_handle, new_cursor, on);
}
}
trav_close(&trav);
}
/*
* This function is used as a callback for libABobjXm. Currently, it
* only calls a dtb_ function, but if the dtb_functions change, or
* we need to do more, here, we won't have to modify libABobjXm.
*/
int
ab_cvt_image_file_to_pixmap(
Widget widget,
STRING file_name,
Pixmap *pixmap_out
)
{
return dtb_cvt_image_file_to_pixmap(widget, file_name, pixmap_out);
}
/*
* This function is the post instantiate callback for libABobjXm. Currently, it
* only calls the group layout function, but if we need to do more here,
* we won't have to modify libABobjXm.
*/
int
ab_post_instantiate(
ABObj obj
)
{
if (obj && obj_is_group(obj) && (obj_get_group_type(obj) != AB_GROUP_IGNORE))
{
Widget group_w;
abobj_disable_save_needed();
abobj_layout_group(obj, TRUE);
group_w = objxm_get_widget(obj);
/*
* Register expose handler
* Some group objects depend on it's members' sizes for their layout.
* Unfortunately, some group members have invalid sizes prior to
* XtRealize(), so the group layout has to be recalculated after the
* group is realized or exposed in this case, since there is no realize
* callback.
*/
if (group_w)
{
ABObj parent = NULL;
Widget parent_w = NULL;
/*
* Get (root) parent ABObj
*/
parent = obj_get_parent(obj);
if (parent)
parent = obj_get_root(parent);
/*
* Get parent widget
*/
if (parent)
parent_w = objxm_get_widget(parent);
if (parent_w)
{
/*
* If parent widget is not realized, register expose handler
*/
if (!XtIsRealized(parent_w))
abobj_register_group_expose_handler(obj);
}
}
abobj_enable_save_needed();
}
return (0);
}
/*
* Accepts NULL and "" as valid directories ( == "." )
*/
int
ab_change_dir(STRING request_dir)
{
char pretty_dir[MAXPATHLEN+1];
BOOL dir_changed = TRUE; /* if path string changed */
BOOL force_update = FALSE;
*pretty_dir = 0;
/*
* Determine the new directory
*/
if (current_dir == NULL)
{
ab_get_cur_dir(); /* initialize it! */
}
if (request_dir == NULL)
{
dir_changed = FALSE;
force_update = TRUE;
request_dir = istr_string(raw_current_dir);
}
else
{
/* see if the path we present to the user will change because of
* this.
*/
if (format_dir_name_for_user(request_dir, pretty_dir, MAXPATHLEN) >= 0)
{
dir_changed = !(istr_equalstr(current_dir, pretty_dir));
}
}
/*
* See if any work actually needs to be done
*/
if ((!dir_changed) && (!force_update))
{
/* no action necessary */
return 0;
}
/*
* Actually change directories and update info
*/
if (dir_changed)
{
{
char sys_dir[MAXPATHLEN+1];
if (format_dir_name_for_system(
request_dir, sys_dir, MAXPATHLEN+1) >= 0)
{
/*
* We may have changed paths but still be in the same actual
* directory. Only chdir if we've actually moved.
*/
if (!util_paths_are_same_file(".", sys_dir))
{
if (chdir(sys_dir) != 0)
{
return -1;
}
}
}
}
if ((*pretty_dir) == 0) /* we may have done this above */
{
format_dir_name_for_user(request_dir, pretty_dir, MAXPATHLEN);
}
istr_destroy(raw_current_dir);
raw_current_dir = istr_create(request_dir);
istr_destroy(current_dir);
current_dir = istr_create(pretty_dir);
}
/*
* Update other subsystems.
*/
cgen_notify_new_directory(istr_string(current_dir));
return 0;
}
BOOL
ab_is_cur_dir(STRING dir)
{
char pretty_dir[MAXPATHLEN];
BOOL is_cur_dir= FALSE;
*pretty_dir = 0;
if (current_dir == NULL)
{
ab_get_cur_dir(); /* initialize it! */
}
if ((dir == NULL) || (*dir == 0) || (*dir == '.'))
{
return TRUE;
}
format_dir_name_for_user(dir, pretty_dir, MAXPATHLEN);
is_cur_dir = istr_equalstr(current_dir, pretty_dir);
return is_cur_dir;
}
STRING
ab_get_cur_dir(void)
{
static BOOL initialized = FALSE;
char formatted_cur_dir[MAXPATHLEN];
char cur_dir[MAXPATHLEN];
STRING new_raw_dir = NULL;
STRING new_dir = NULL;
*formatted_cur_dir = 0;
*cur_dir = 0;
if ( initialized &&
(raw_current_dir != NULL) &&
util_paths_are_same_file(istr_string(raw_current_dir), ".") )
{
goto epilogue; /* no change */
}
/*
* Get the raw current directory
*/
new_raw_dir = NULL;
if (!initialized)
{
initialized = TRUE;
new_raw_dir = getenv("PWD");
}
if (new_raw_dir == NULL)
{
if (getcwd(cur_dir, MAXPATHLEN) != NULL)
{
new_raw_dir = cur_dir;
}
}
/*
* Get the pretty version of the current directory
*/
if (new_raw_dir == NULL)
{
new_raw_dir = ".";
new_dir = "* Indeterminable *";
}
else
{
format_dir_name_for_user(new_raw_dir, formatted_cur_dir, MAXPATHLEN);
new_dir = formatted_cur_dir;
}
istr_destroy(current_dir);
istr_destroy(raw_current_dir);
current_dir = istr_create(new_dir);
raw_current_dir = istr_create(new_raw_dir);
epilogue:
return istr_string(current_dir);
}
/*
* Takes a directory name and formats it so that it will look good
* to the user.
* Guarantees: no trailing slashes (except for / directory)
*/
static int
format_dir_name_for_user(
STRING ugly_dir,
STRING pretty_dir,
int pretty_dir_size
)
{
STRING home= getenv(home_env_var_name);
int home_name_len = 0;
int i= 0;
if (home != NULL)
{
char home_relative[MAXPATHLEN];
home_name_len = strlen(home);
*home_relative = 0;
util_cvt_path_to_relative(ugly_dir, home, home_relative, MAXPATHLEN);
*pretty_dir = 0;
if (home_relative[0] == '/')
{
strncpy(pretty_dir, home_relative, pretty_dir_size);
pretty_dir[pretty_dir_size-1]= 0;
}
else
{
/* relative to home (but avoid "~/." if actually in home dir)*/
strcpy(pretty_dir, "~");
if (!util_streq(home_relative, "."))
{
strcat(pretty_dir, "/");
strncat(pretty_dir, home_relative, pretty_dir_size-2);
}
pretty_dir[pretty_dir_size-1]= 0;
}
}
else
{
strncpy(pretty_dir, ugly_dir, pretty_dir_size);
pretty_dir[pretty_dir_size-1]= 0;
}
/*
* strip trailing slashes
*/
for (i= strlen(pretty_dir)-1; i > 0; --i)
{
if (pretty_dir[i] == '/')
{
pretty_dir[i]= 0;
}
else
{
break;
}
}
util_dprintf(2,"user format dir '%s' -> '%s'\n", ugly_dir, pretty_dir);
return 0;
}
/*
* Takes a directory name that may or may not be formatted to look
* good to the user, and converts it to a path that will work with
* chdir().
*/
static int
format_dir_name_for_system(
STRING user_dir_name,
STRING system_dir,
int system_dir_size
)
{
int return_value = 0;
char *user_dir_ptr = user_dir_name;
STRING homeVar = NULL;
*system_dir = 0;
if (util_strempty(user_dir_name))
{
goto epilogue;
}
if (user_dir_name[0] == '~')
{
if ((homeVar = getenv(home_env_var_name)) != NULL)
{
util_strncpy(system_dir, homeVar, system_dir_size);
++user_dir_ptr;
}
if ((*user_dir_ptr) == '/')
{
strcat(system_dir, "/");
++user_dir_ptr;
}
}
strcat(system_dir, user_dir_ptr);
epilogue:
util_dprintf(2,"sys format dir '%s' -> '%s'\n", user_dir_name, system_dir);
return return_value;
}
static void
set_cursor(
Widget widget,
Cursor cursor,
BOOL on
)
{
Window win;
Display *dpy;
if (widget && XtIsRealized(widget))
{
dpy = XtDisplay(widget);
win = XtWindow(widget);
if (on)
XDefineCursor(dpy, win, cursor);
else
XUndefineCursor(dpy, win);
}
}
void
ab_palette_set_active(
BOOL active
)
{
static Widget palette_cpanel = NULL;
static Widget palette_footer = NULL;
/* REMIND andy: take out when working */
if (palette_cpanel == NULL)
{
palette_cpanel = dtb_palette_ab_palette_main.palette_cpanel;
palette_footer = dtb_palette_ab_palette_main.palette_footer;
}
ui_set_active(palette_cpanel, active);
ui_set_active(palette_footer, active);
}
void
ab_exit_dtbuilder()
{
static DTB_MODAL_ANSWER answer;
XtAppContext app;
static BOOL Up = False;
Widget dlg = (Widget) NULL;
Widget shell = (Widget) NULL;
Widget mbox = (Widget) NULL;
Arg args[10];
int n = 0;
answer = DTB_ANSWER_NONE;
if ( !Up )
{
if (proj_check_unsaved_edits(proj_get_project()))
{
Up = True;
dtb_palette_exit_msg_initialize(&dtb_palette_exit_msg);
if (ab_window_leader_iconified())
{
shell = XtCreatePopupShell("exit_dtbuilder",
topLevelShellWidgetClass,
dtb_get_toplevel_widget(),
(ArgList) NULL, (Cardinal) 0);
n = 0;
XtSetArg(args[n], XmNdialogType,
dtb_palette_exit_msg.type); n++;
XtSetArg(args[n], XmNmessageString,
dtb_palette_exit_msg.message); n++;
XtSetArg(args[n], XmNdialogTitle,
dtb_palette_exit_msg.title); n++;
XtSetArg(args[n], XmNokLabelString,
dtb_palette_exit_msg.action1_label); n++;
XtSetArg(args[n], XmNdefaultButtonType,
XmDIALOG_CANCEL_BUTTON); n++;
XtSetArg(args[n], XmNuserData, &answer); n++;
mbox = XmCreateMessageBox(shell, "exit_mbox", args, n);
XtManageChild(mbox);
XtAddCallback(mbox, XmNokCallback, exit_mboxCB,
(XtPointer) DTB_ANSWER_ACTION1);
XtAddCallback(mbox, XmNcancelCallback, exit_mboxCB,
(XtPointer) DTB_ANSWER_CANCEL);
XtAddCallback(shell, XmNpopdownCallback, destroy_mboxCB,
(XtPointer) NULL);
ui_add_window_close_callback(shell, mwm_close_mboxCB,
(XtPointer) &answer, XmDO_NOTHING);
XtRealizeWidget(shell);
XtPopup(shell, XtGrabExclusive);
ui_win_front(shell);
app = XtDisplayToApplicationContext(XtDisplay(mbox));
while (answer == DTB_ANSWER_NONE)
{
XtAppProcessEvent(app, XtIMAll);
}
}
else if (shell == NULL)
{
/* Display the "unsaved edits" message DIALOG if the
* "unsaved edits" message topLevelShell is not already
* up.
*/
answer = dtb_show_modal_message(dtb_get_toplevel_widget(),
&dtb_palette_exit_msg, NULL, NULL, &dlg);
}
switch (answer)
{
case DTB_ANSWER_ACTION1:
exit(0);
case DTB_ANSWER_CANCEL:
break;
}
Up = False;
}
else
{
exit(0);
}
}
else
{
if (dlg != NULL)
ui_win_front(dlg);
else if (shell != NULL)
ui_win_front(shell);
}
}
static void
exit_mboxCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
)
{
DTB_MODAL_ANSWER op = (DTB_MODAL_ANSWER) client_data;
DTB_MODAL_ANSWER *answerp = NULL;
XtVaGetValues(widget, XmNuserData, &answerp, NULL);
/* Dismiss the "unsaved edits" message. */
XtPopdown(ui_get_ancestor_shell(widget));
*answerp = op;
}
/*
* popdownCallback for Exit MessageBox.
*/
static void
destroy_mboxCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
)
{
XtDestroyWidget(widget);
}
static void
mwm_close_mboxCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
)
{
DTB_MODAL_ANSWER *op = (DTB_MODAL_ANSWER *) client_data;
/* Dismiss the "unsaved edits" message. */
XtPopdown(widget);
*op = DTB_ANSWER_CANCEL;
}