1684 lines
49 KiB
C
1684 lines
49 KiB
C
#ifndef lint
|
|
#ifdef sccs
|
|
static char sccsid[] = "@(#)alert.c 1.1 94/10/31";
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifndef ecd.alert
|
|
|
|
/*
|
|
* Copyright (c) 1986, 1987 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <varargs.h>
|
|
#include <sys/file.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sundev/kbd.h>
|
|
#include <sundev/kbio.h>
|
|
#include <sunwindow/sun.h>
|
|
#include <sunwindow/defaults.h>
|
|
#include <sunwindow/window_hs.h>
|
|
#include <sunwindow/win_enum.h>
|
|
#include <sunwindow/win_ioctl.h> /* for journaling */
|
|
#include <suntool/fullscreen.h>
|
|
#include <suntool/sunview.h>
|
|
#include <suntool/tool_struct.h>
|
|
#include <suntool/panel.h>
|
|
#include <suntool/help.h>
|
|
#include <suntool/alert.h>
|
|
#include <suntool/alert_impl.h>
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* --------------------------- Globals ------------------------------ */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static alert_handle saved_alert;
|
|
static struct pixfont *button_font;
|
|
static int default_beeps;
|
|
static int alert_use_audible_bell;
|
|
static int alert_jump_cursor;
|
|
static int alert_ignore_optional;
|
|
static int alert_fd;
|
|
static Rect alert_screen_rect;
|
|
static struct rect irect, orect;
|
|
|
|
static short alert_arrow_right[] = {
|
|
#include <images/rightswoosh.icon>
|
|
};
|
|
mpr_static(alert_arrow_right_pr, 64, 64, 1, alert_arrow_right);
|
|
|
|
static short alert_leftswoosh[] = {
|
|
#include <images/leftswoosh.icon>
|
|
};
|
|
mpr_static(alert_leftswoosh_pr, 64, 64, 1, alert_leftswoosh);
|
|
|
|
static short alert_bang[] = {
|
|
#include <images/alert_bang32.pr>
|
|
};
|
|
mpr_static(alert_bang_pr, 32, 32, 1, alert_bang);
|
|
|
|
static short alert_qmark[] = {
|
|
#include <images/alert_qmark32.pr>
|
|
};
|
|
mpr_static(alert_qmark_pr, 32, 32, 1, alert_qmark);
|
|
|
|
static short alert_gray50_data[] = {
|
|
#include <images/square_50.pr>
|
|
};
|
|
mpr_static(alert_gray50_patch, 16, 16, 1, alert_gray50_data);
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* --------------------------- DISPLAY PROCS ------------------------ */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static int alert_show(); /* display alert */
|
|
static void alert_get_alert_size(); /* determine rect */
|
|
static Pw_pixel_cache *alert_drawbox(); /* draw outline & shadow */
|
|
static void alert_layout(); /* draw items */
|
|
static void alert_build_button(); /* compute button pr */
|
|
static void alert_outline_button(); /* draw std button */
|
|
static void alert_yes_outline_button(); /* draw YES button */
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* --------------------------- UTILITY PROCS ------------------------ */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static void alert_select_button();
|
|
static void alert_unselect_button();
|
|
static void alert_preview_message_font();
|
|
static void alert_preview_button_font();
|
|
static void alert_set_avlist();
|
|
static void alert_default();
|
|
static void alert_add_button_to_list();
|
|
static int alert_text_width();
|
|
static int alert_button_width();
|
|
static int alert_get_fd();
|
|
static button_handle alert_button_for_event();
|
|
static int alert_offset_from_baseline();
|
|
static int calc_max();
|
|
static button_handle create_button_struct();
|
|
static void free_button_structs();
|
|
static void alert_copy_event();
|
|
static void alert_do_bell();
|
|
static void alert_blocking_wait();
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* --------------------------- STATICS ------------------------------ */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static int left_marg = 5;
|
|
static int right_marg = 5;
|
|
static int top_marg = 5;
|
|
static int bottom_marg = 10;
|
|
static int row_gap = 4;
|
|
static int button_gap;
|
|
static int min_button_gap = 4;
|
|
/*
|
|
* In the case that the height of the swoosh is larger than the height of
|
|
* the total text, short_text_line is the number of the lines in the text.
|
|
* Otherwise, it's 0.
|
|
*/
|
|
static int short_text_line;
|
|
static struct pixfont *defpf;
|
|
static int swoosh_height;
|
|
|
|
#define BORDER 3 /* white space surounding text */
|
|
#define SHADOW 6 /* thickness of shadow */
|
|
#define BUTTON_HEIGHT_EXTRA 8 /* max extra needed for yes button */
|
|
#define YES_BUTTON_Y_DIFF 4 /* height diff between yes and no */
|
|
#define ALERT_ACTION_DO_IT '\015' /* simple return */
|
|
#define SWOOSH_PIXRECTS_H_OFFSET 16
|
|
#define SWOOSH_PIXRECTS_V_OFFSET 16
|
|
#define MENU_BORDER 2
|
|
|
|
/*
|
|
* Number of pixels of the swoosh that is hanging outside the alert_box
|
|
*/
|
|
#define SWOOSH_OUTSIDE_BOX 52
|
|
|
|
/*
|
|
* journaling
|
|
*/
|
|
extern int sv_journal;
|
|
extern void win_sync();
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* ----------------------- Public Interface ------------------------- */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
int
|
|
alert_init()
|
|
{
|
|
if (!saved_alert) {
|
|
char *font_name;
|
|
int my_fd;
|
|
|
|
saved_alert = (struct alert *)calloc(1, sizeof(struct alert));
|
|
if (!saved_alert) {
|
|
(void)printf(stderr, "Alert ERROR: malloc failed.");
|
|
return (1);
|
|
}
|
|
alert_use_audible_bell = (int)defaults_get_boolean(
|
|
"/SunView/Audible_Bell", (Bool)TRUE, (int *)NULL);
|
|
alert_jump_cursor = (int)defaults_get_boolean(
|
|
"/SunView/Alert_Jump_Cursor", (Bool)TRUE, (int *)NULL);
|
|
alert_ignore_optional = (int)defaults_get_boolean(
|
|
"/SunView/Ignore_Optional_Alerts", (Bool)FALSE , (int *)NULL);
|
|
font_name = defaults_get_string(
|
|
"/Menu/Font",
|
|
"/usr/lib/fonts/fixedwidthfonts/screen.b.14",
|
|
(int *)0);
|
|
button_font = pf_open(font_name);
|
|
default_beeps = defaults_get_integer(
|
|
"/SunView/Alert_Bell", 1, (int *)NULL);
|
|
defpf = pw_pfsysopen();
|
|
if (!button_font)
|
|
button_font = defpf;
|
|
|
|
/*
|
|
* assuming that the swoosh from the top of the alert_box proper, then
|
|
* swoosh_height is the number of pixels from the top of the alert_box to
|
|
* lowest point of the swoosh glyph.
|
|
*/
|
|
swoosh_height = alert_leftswoosh_pr.pr_size.x + SWOOSH_PIXRECTS_V_OFFSET +
|
|
(alert_arrow_right_pr.pr_size.x - alert_leftswoosh_pr.pr_size.x);
|
|
}
|
|
|
|
if (alert_fd) {
|
|
win_getrect(alert_fd, &irect);
|
|
win_getsavedrect(alert_fd, &orect);
|
|
}
|
|
else {
|
|
if (alert_get_fd(&saved_alert->fd_for_fullscreen) == 0) {
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
/* VARARGS */
|
|
|
|
int
|
|
alert_prompt(client_frame, event, va_alist)
|
|
Frame client_frame;
|
|
Event *event;
|
|
va_dcl
|
|
{
|
|
va_list valist;
|
|
int result;
|
|
|
|
for (;;) {
|
|
va_start(valist);
|
|
result = alert_show(client_frame, event, valist);
|
|
va_end(valist);
|
|
if (result != ALERT_HELP)
|
|
break;
|
|
help_request(client_frame, saved_alert->help_data, event);
|
|
}
|
|
|
|
win_setrect(alert_fd, &irect);
|
|
win_setsavedrect(alert_fd, &orect);
|
|
|
|
return (result);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* ----------------------PRIVATE PROCS------------------------------- */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static int
|
|
alert_show(client_frame, event, valist)
|
|
Frame client_frame;
|
|
Event *event;
|
|
va_list valist;
|
|
{
|
|
Event ie;
|
|
Alert_attribute avlist[ATTR_STANDARD_SIZE];
|
|
register alert_handle alert;
|
|
int result, fd;
|
|
Pw_pixel_cache *bitmap_under;
|
|
struct rect rectsaved, rect;
|
|
struct fullscreen *fs;
|
|
|
|
button_handle button;
|
|
button_handle current_button = NULL;
|
|
int is_highlighted = FALSE;
|
|
int old_mousex, old_mousey;
|
|
unsigned short this_event;
|
|
|
|
if (alert_init())
|
|
return (ALERT_FAILED);
|
|
|
|
alert = saved_alert;
|
|
fd = alert->fd_for_fullscreen;
|
|
|
|
(void) alert_default(alert);
|
|
|
|
alert->event = (Event *)event;
|
|
alert->client_frame = client_frame;
|
|
|
|
attr_make (avlist, ATTR_STANDARD_SIZE, valist);
|
|
(void)alert_set_avlist (alert, avlist, FALSE);
|
|
|
|
/* only if ALERT_OPTIONAL && ALERT_BUTTON_YES && default option */
|
|
if (alert->is_optional &&
|
|
alert->yes_button_exists &&
|
|
(alert_ignore_optional == TRUE))
|
|
return (ALERT_YES);
|
|
|
|
alert_do_bell(alert, fd);
|
|
|
|
fs = fullscreen_init(fd); /* go fullscreen first */
|
|
if (fs == 0) {
|
|
return (ALERT_FAILED); /* probably out of fds */
|
|
}
|
|
|
|
/*
|
|
* should get FULLSCREEN from <sunwindow/cursor_impl.h>
|
|
* but "fullscreen" macro conflicts with the use of
|
|
* "fullscreen" struct in <suntool/fullscreen.h>
|
|
*/
|
|
#define FULLSCREEN 0x10
|
|
fs->fs_cachedcursor.flags = FULLSCREEN;
|
|
(void)win_setcursor(fs->fs_windowfd, &fs->fs_cachedcursor);
|
|
|
|
/* now determine the size of the alert */
|
|
(void)alert_get_alert_size(alert, &rect, fs->fs_windowfd);
|
|
if ((bitmap_under = alert_drawbox( /* then draw empty box */
|
|
fs->fs_pixwin, &rect, &rectsaved, fs)) == NULL)
|
|
goto RestoreState;
|
|
/* now fill in the box with the image, text, buttons etc */
|
|
(void)alert_layout(alert, &rect, fs->fs_pixwin);
|
|
|
|
if (alert_jump_cursor && alert->yes_button_exists) {
|
|
button_handle curr;
|
|
old_mousex = win_get_vuid_value(fd, LOC_X_ABSOLUTE);
|
|
old_mousey = win_get_vuid_value(fd, LOC_Y_ABSOLUTE);
|
|
for (curr = alert->button_info; curr != NULL; curr = curr->next)
|
|
if (curr->is_yes)
|
|
win_setmouseposition(fd,
|
|
curr->button_rect.r_left + curr->button_rect.r_width / 2,
|
|
curr->button_rect.r_top + curr->button_rect.r_height / 2
|
|
);
|
|
}
|
|
|
|
/*
|
|
* if journaling, send sync point.
|
|
*/
|
|
if (sv_journal)
|
|
win_sync(WIN_SYNC_ALERT, fd);
|
|
/*
|
|
* Change the owner of the windowfd(WMGR_ENV_PLACEHOLDER) so that
|
|
* when we go into the loop to read event, we will be able to do so.
|
|
* Otherwise the events will go to the original owner of the window,
|
|
* which is sunview.
|
|
*/
|
|
win_setowner(fs->fs_windowfd, getpid());
|
|
/* Stay in fullscreen until a button is pressed, or trigger used */
|
|
for (;;) {
|
|
unsigned short trigger = alert->default_input_code;
|
|
|
|
if (input_readevent(fs->fs_windowfd, &ie) == -1)
|
|
break;
|
|
this_event = event_action(&ie); /* get encoded event */
|
|
|
|
button = alert_button_for_event(alert, &ie);
|
|
|
|
if ((this_event == trigger) && ((trigger == (int)MS_LEFT) ?
|
|
(event_is_up(&ie) && (current_button == NULL)) : 1)) {
|
|
/* catch UP mouse left */
|
|
alert->result = ALERT_TRIGGERED;
|
|
(void) alert_copy_event(alert, &ie);
|
|
goto Done;
|
|
} else if (((this_event == ACTION_STOP) || (this_event == WIN_STOP))
|
|
&& saved_alert->no_button_exists) {
|
|
alert->result = ALERT_NO;
|
|
(void) alert_copy_event(alert, &ie);
|
|
goto Done;
|
|
} else if ((this_event == ACTION_DO_IT
|
|
|| this_event == ALERT_ACTION_DO_IT)
|
|
&& saved_alert->yes_button_exists) {
|
|
alert->result = ALERT_YES;
|
|
(void) alert_copy_event(alert, &ie);
|
|
goto Done;
|
|
} else if ((this_event == MS_LEFT) && (alert->button_info)) {
|
|
if (event_is_down(&ie) && (button != NULL)) {
|
|
alert_select_button(fs->fs_pixwin, button);
|
|
current_button = button;
|
|
is_highlighted = TRUE;
|
|
} else if (event_is_up(&ie)) {
|
|
if ((current_button && is_highlighted)
|
|
&& (button != NULL)
|
|
&& (button == current_button)) {
|
|
alert->result = button->value;
|
|
(void) alert_copy_event(alert, &ie);
|
|
goto Done;
|
|
} else if ((current_button && is_highlighted)
|
|
&& (button != NULL)
|
|
&& (button != current_button)) {
|
|
alert->result = button->value;
|
|
(void) alert_copy_event(alert, &ie);
|
|
goto Done;
|
|
}
|
|
}
|
|
} else if (this_event == ACTION_HELP) {
|
|
if (event_is_down(&ie)) {
|
|
alert->result = ALERT_HELP;
|
|
(void) alert_copy_event(alert, &ie);
|
|
goto Done;
|
|
}
|
|
} else if (this_event == LOC_DRAG) {/* mouse moved w/MS down */
|
|
if (((current_button != NULL) && is_highlighted)
|
|
&& ((button == NULL))
|
|
&& (button != current_button)) {
|
|
alert_unselect_button(fs->fs_pixwin, current_button);
|
|
current_button = NULL;
|
|
is_highlighted = FALSE;
|
|
}
|
|
if ((button != current_button) && (is_highlighted == FALSE)) {
|
|
alert_select_button(fs->fs_pixwin, button);
|
|
current_button = button;
|
|
is_highlighted = TRUE;
|
|
}
|
|
}
|
|
}
|
|
Done:
|
|
pw_restore_pixels(fs->fs_pixwin, bitmap_under);
|
|
RestoreState:
|
|
if (alert_jump_cursor && alert->yes_button_exists)
|
|
win_setmouseposition(fd, old_mousex, old_mousey);
|
|
fullscreen_destroy(fs);
|
|
|
|
free_button_structs(alert->button_info);
|
|
result = alert->result;
|
|
|
|
return (result);
|
|
}
|
|
|
|
static void
|
|
alert_copy_event(alert, event)
|
|
register alert_handle alert;
|
|
Event *event;
|
|
{
|
|
if (saved_alert->event == (Event *) 0) {
|
|
return;
|
|
} else {
|
|
saved_alert->event->ie_code = event->ie_code;
|
|
saved_alert->event->ie_flags = event->ie_flags;
|
|
saved_alert->event->ie_shiftmask = event->ie_shiftmask;
|
|
saved_alert->event->ie_locx = event->ie_locx;
|
|
saved_alert->event->ie_locy = event->ie_locy;
|
|
saved_alert->event->ie_time.tv_sec = event->ie_time.tv_sec;
|
|
saved_alert->event->ie_time.tv_usec = event->ie_time.tv_usec;
|
|
}
|
|
/*
|
|
saved_alert->event->ie_locx = (event_x(event) < 0) ?
|
|
(saved_alert->position_x - abs(event_x(event))) :
|
|
(saved_alert->position_x + event_x(event));
|
|
saved_alert->event->ie_locy = (event_y(event) < 0) ?
|
|
(saved_alert->position_y - abs(event_y(event))) :
|
|
(saved_alert->position_y + event_y(event));
|
|
*/
|
|
if (saved_alert->client_frame) { /* make event client relative */
|
|
Rect client_frame_place;
|
|
|
|
window_getrelrect(0,
|
|
window_fd(saved_alert->client_frame), &client_frame_place);
|
|
saved_alert->event->ie_locx -= client_frame_place.r_left;
|
|
saved_alert->event->ie_locy -= client_frame_place.r_top;
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* --------------------------- Statics ------------------------------ */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static int
|
|
alert_preview_avlist_for_int_value(attr, avlist, default_if_not_present)
|
|
Alert_attribute attr;
|
|
register Alert_attribute *avlist;
|
|
int default_if_not_present;
|
|
{
|
|
Alert_attribute current_attr;
|
|
int value = default_if_not_present;
|
|
|
|
for (; *avlist; avlist = alert_attr_next(avlist)) {
|
|
current_attr = avlist[0];
|
|
if (attr == current_attr) value = (int)avlist[1];
|
|
}
|
|
return (int)value;
|
|
}
|
|
|
|
static void
|
|
alert_preview_button_font(alert, avlist)
|
|
register alert_handle alert;
|
|
register Alert_attribute *avlist;
|
|
{
|
|
Alert_attribute attr;
|
|
caddr_t value;
|
|
|
|
for (; *avlist; avlist = alert_attr_next(avlist)) {
|
|
attr = avlist[0]; value = (caddr_t)avlist[1];
|
|
switch (attr) {
|
|
case ALERT_BUTTON_FONT:
|
|
alert->button_font = (struct pixfont *) value;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
alert_preview_message_font(alert, avlist)
|
|
register alert_handle alert;
|
|
register Alert_attribute *avlist;
|
|
{
|
|
Alert_attribute attr;
|
|
caddr_t value;
|
|
|
|
for (; *avlist; avlist = alert_attr_next(avlist)) {
|
|
attr = avlist[0]; value = (caddr_t)avlist[1];
|
|
switch (attr) {
|
|
case ALERT_MESSAGE_FONT:
|
|
alert->message_font = (struct pixfont *) value;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
alert_set_avlist(alert, avlist, caller_external)
|
|
register alert_handle alert;
|
|
register Alert_attribute *avlist;
|
|
int caller_external;
|
|
{
|
|
int i;
|
|
int yes_button_seen = FALSE;
|
|
int no_button_seen = FALSE;
|
|
int number_of_buttons_seen = 0;
|
|
int trigger_set = 0;
|
|
Alert_attribute attr;
|
|
caddr_t value;
|
|
int image_attr_seen = 0; /* use default if haven't */
|
|
|
|
alert_preview_button_font(alert, avlist);
|
|
alert_preview_message_font(alert, avlist);
|
|
|
|
for (; *avlist; avlist = alert_attr_next(avlist)) {
|
|
attr = avlist[0]; value = (caddr_t)avlist[1];
|
|
switch (attr) {
|
|
|
|
case WIN_X:
|
|
alert->client_offset_x = (int)value;
|
|
break;
|
|
|
|
case WIN_Y:
|
|
alert->client_offset_y = (int)value;
|
|
break;
|
|
|
|
case ALERT_POSITION:
|
|
if ((int)value == (int)ALERT_SCREEN_CENTERED ||
|
|
(int)value == (int)ALERT_CLIENT_CENTERED ||
|
|
(int)value == (int)ALERT_CLIENT_OFFSET)
|
|
alert->position = (int)value;
|
|
break;
|
|
|
|
case ALERT_OPTIONAL:
|
|
alert->is_optional = ((int)value == 1) ? 1 : 0;
|
|
break;
|
|
|
|
case ALERT_NO_BEEPING:
|
|
if ((int)value == 1) alert->dont_beep = 1;
|
|
break;
|
|
|
|
case ALERT_TRIGGER:
|
|
alert->default_input_code = (int)avlist[1];
|
|
trigger_set = 1;
|
|
break;
|
|
|
|
case ALERT_MESSAGE_STRINGS_ARRAY_PTR:
|
|
alert->message_items = (char **)value;
|
|
break;
|
|
|
|
case ALERT_MESSAGE_STRINGS:
|
|
alert->message_items = (char **)&avlist[1];
|
|
break;
|
|
|
|
/*
|
|
* ALERT_NO_IMAGE and ALERT_IMAGE are obsolete attributes.
|
|
*/
|
|
case ALERT_NO_IMAGE:
|
|
case ALERT_IMAGE:
|
|
break;
|
|
|
|
case ALERT_BUTTON_YES: {
|
|
struct pixrect *image;
|
|
button_handle button;
|
|
|
|
if (!yes_button_seen) {
|
|
yes_button_seen = TRUE;
|
|
} else {
|
|
fprintf(
|
|
stderr,
|
|
"alert: Only one ALERT_BUTTON_YES allowed. Attr ignored.\n");
|
|
break;
|
|
}
|
|
button = (button_handle)create_button_struct();
|
|
button->string = (char *)avlist[1];
|
|
button->is_yes = TRUE;
|
|
button->value = ALERT_YES;
|
|
alert->yes_button_exists = TRUE;
|
|
number_of_buttons_seen++;
|
|
(void) alert_add_button_to_list(alert, button);
|
|
break;
|
|
}
|
|
|
|
case ALERT_BUTTON_NO: {
|
|
struct pixrect *image;
|
|
button_handle button;
|
|
|
|
if (!no_button_seen){
|
|
no_button_seen = TRUE;
|
|
} else {
|
|
fprintf(
|
|
stderr,
|
|
"alert: Only one ALERT_BUTTON_NO allowed. Attr ignored.\n");
|
|
break;
|
|
}
|
|
button = (button_handle)create_button_struct();
|
|
button->string = (char *)avlist[1];
|
|
button->is_no = TRUE;
|
|
button->value = ALERT_NO;
|
|
alert->no_button_exists = TRUE;
|
|
number_of_buttons_seen++;
|
|
(void) alert_add_button_to_list(alert, button);
|
|
break;
|
|
}
|
|
|
|
case ALERT_BUTTON: {
|
|
button_handle button;
|
|
|
|
button = (button_handle)create_button_struct();
|
|
button->string = (char *)avlist[1];
|
|
button->value = (int)avlist[2];
|
|
(void) alert_add_button_to_list(alert, button);
|
|
number_of_buttons_seen++;
|
|
break;
|
|
}
|
|
|
|
case ALERT_BUTTON_FONT:
|
|
case ALERT_MESSAGE_FONT:
|
|
/* already previewed above */
|
|
break;
|
|
|
|
case HELP_DATA:
|
|
alert->help_data = value;
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "alert: attribute not allowed.\n");
|
|
break;
|
|
}
|
|
}
|
|
if ((number_of_buttons_seen == 0) && (trigger_set == 0))
|
|
alert->default_input_code = (int)ACTION_STOP;
|
|
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static void
|
|
alert_get_alert_size(alert, rect, fd)
|
|
register alert_handle alert;
|
|
struct rect *rect;
|
|
int fd;
|
|
{
|
|
Rect r;
|
|
int x, y, height, width, i, left, top, num_lines = 0;
|
|
int swoosh_offset =
|
|
((struct pixrect *)&alert_arrow_right_pr)->pr_size.x - 4;
|
|
|
|
short_text_line = 0;
|
|
x = 0; y = 0; /* start calculations out at zero, add margins later */
|
|
|
|
#ifdef OLD_ALERT_IMAGES
|
|
if (alert->image_item)
|
|
x += alert->image_item->pr_size.x + left_marg;
|
|
#else
|
|
/*
|
|
x += ((struct pixrect *)&alert_arrow_right_pr)->pr_size.x +
|
|
((struct pixrect *)&alert_leftswoosh_pr)->pr_size.x;
|
|
*/
|
|
#endif OLD_ALERT_IMAGES
|
|
|
|
if (alert->message_items) {
|
|
char **strs;
|
|
char **tmp_strings;
|
|
int max_width = 0;
|
|
int str_width = 0;
|
|
Pixfont *mess_font = (alert->message_font) ?
|
|
alert->message_font : defpf;
|
|
|
|
strs = (char **)alert->message_items;
|
|
tmp_strings = (char **)alert->message_items;
|
|
while (*strs) {
|
|
str_width = alert_text_width(mess_font, (char *)*strs);
|
|
max_width = calc_max(str_width, max_width);
|
|
num_lines++;
|
|
strs++;
|
|
}
|
|
/*
|
|
* The two pixrects are layed out such that the right arrow pixrect
|
|
* is layered 16 pixels both to the right and down of the swoosh pixrect.
|
|
* The assumption is that the arrow comes in pointing pretty much
|
|
* at the text. The pixrect of the arrow is 64 pixels wide, but
|
|
* only 60 of them are in the border of the alert box.
|
|
* The layout is such that the text is 60 pixels plus the left
|
|
* margin inside of the alert_box on the left and is 60 pixels plus
|
|
* the right margin inside of the alert_box on the right. The
|
|
* buttons are layed out such that the first button is "left_margin"
|
|
* pixels inside the alert_box and the last is "right_margin" pixels
|
|
* inside the alert_box.
|
|
*/
|
|
x += max_width + swoosh_offset * 2;
|
|
y += (num_lines*mess_font->pf_defaultsize.y);
|
|
}
|
|
|
|
/*
|
|
* Make sure that the text part is at least as high as the
|
|
* height of the swoosh glyph
|
|
*/
|
|
if (y + row_gap + top_marg > swoosh_height) {
|
|
y += row_gap;
|
|
short_text_line = 0;
|
|
} else {
|
|
short_text_line = num_lines;
|
|
y = swoosh_height;
|
|
}
|
|
|
|
i = 0;
|
|
if (alert->button_info) {
|
|
int max_buttons_width = 0;
|
|
int width = 0;
|
|
int total = 0;
|
|
button_handle curr;
|
|
struct pixfont *font = alert->button_font;
|
|
|
|
for (curr = alert->button_info; curr != NULL; curr = curr->next) {
|
|
width = alert_button_width(font, curr);
|
|
max_buttons_width += width;
|
|
i++;
|
|
}
|
|
y += font->pf_defaultsize.y + BUTTON_HEIGHT_EXTRA;
|
|
/*
|
|
* figure out the total pixels needed to fit buttons and text, which
|
|
* ever is longer. This is just for the actual buttons and/or text,
|
|
* and not including the margins
|
|
*/
|
|
x = calc_max(max_buttons_width, x);
|
|
total = x + left_marg + right_marg + (4*BORDER);
|
|
if (total >= alert_screen_rect.r_width) {
|
|
/* if buttons too wide, then they clip just like the text will.
|
|
* this is not very nice, but TOO BAD!! it's a rough job attempting
|
|
* to handle their wraping.
|
|
*/
|
|
button_gap = 0;
|
|
} else {
|
|
if (i==1) {
|
|
button_gap = calc_max(0, (x - max_buttons_width)/2);
|
|
} else { /* >1 */
|
|
button_gap = calc_max(0, (x - max_buttons_width)/(i-1));
|
|
}
|
|
if (i>1 && button_gap == 0 && (((i-1)*min_button_gap) < total)) {
|
|
button_gap = min_button_gap;
|
|
x += (i-1) * min_button_gap;
|
|
}
|
|
}
|
|
}
|
|
y += top_marg + bottom_marg + (2*BORDER);
|
|
/*
|
|
* add in the borders and the SWOOSH_OUTSIDE_BOX pixels that are outside of the
|
|
* alert_box, but is regarded as alert_box-metro area
|
|
*/
|
|
x += left_marg + right_marg + (4*BORDER) + SWOOSH_OUTSIDE_BOX;
|
|
|
|
/*
|
|
* discount the SWOOSH_OUTSIDE_BOX pixels of the swoosh for centering purpose
|
|
*/
|
|
width = x;
|
|
height = y;
|
|
|
|
/*
|
|
* now try and position the alert and make it pretty
|
|
*/
|
|
/* if ((alert->client_frame == (Frame)0)
|
|
|| (window_get(alert->client_frame, FRAME_CLOSED)))
|
|
alert->position = (int)ALERT_SCREEN_CENTERED;
|
|
*/
|
|
if (alert->client_frame == (Frame)0)
|
|
alert->position = (int)ALERT_SCREEN_CENTERED;
|
|
if (alert->client_frame != (Frame)0)
|
|
window_getrelrect(0, window_fd(alert->client_frame), &r);
|
|
if ((alert->position == (int)ALERT_SCREEN_CENTERED)
|
|
|| (alert->client_frame == (Frame)0)) {
|
|
/*
|
|
* Disregard the part of swoosh outside of the box when centering
|
|
*/
|
|
left = calc_max(0, (alert_screen_rect.r_width - width - SWOOSH_OUTSIDE_BOX)/2);
|
|
top = calc_max(0, (alert_screen_rect.r_height - height)/2);
|
|
} else {
|
|
/*
|
|
* Disregard the part of swoosh outside of the box when centering
|
|
*/
|
|
left = calc_max(0, r.r_left + (r.r_width - width - SWOOSH_OUTSIDE_BOX)/2);
|
|
top = calc_max(0, r.r_top + (r.r_height - height)/2);
|
|
|
|
if (alert->position == (int)ALERT_CLIENT_OFFSET) {
|
|
left = alert->client_offset_x + r.r_left-(calc_max(0, width/2));
|
|
top = alert->client_offset_y + r.r_top-(calc_max(0, height/2));
|
|
}
|
|
/* try to reposition alert near frame for aesthetics, if near boarder */
|
|
if ((left <= (r.r_left)) && (width >= r.r_width)) {
|
|
if ((left == 0)
|
|
&& ((r.r_left + (r.r_width/2)) <= alert_screen_rect.r_width)) {
|
|
left += (r.r_width/2);
|
|
}
|
|
if ((left < r.r_left) && ((left + width +
|
|
(BORDER + SHADOW)) >= alert_screen_rect.r_width)) {
|
|
left -= (r.r_width/2);
|
|
if ((left + width + (BORDER + SHADOW)) >=
|
|
alert_screen_rect.r_width) { /* still overflows */
|
|
left = alert_screen_rect.r_width - width -
|
|
(BORDER + SHADOW);
|
|
if ((left - (r.r_width/2)) >= 0)
|
|
left -= (r.r_width/2);
|
|
}
|
|
}
|
|
}
|
|
if ((top <= (r.r_top)) && (height >= r.r_height)) {
|
|
if ((top == 0)
|
|
&& ((r.r_top + (r.r_height/2)) <= alert_screen_rect.r_height)) {
|
|
top += (r.r_height/2);
|
|
}
|
|
if ((top < r.r_top) && ((top + height +
|
|
(BORDER + SHADOW)) > alert_screen_rect.r_height)) {
|
|
top -= (r.r_height/2);
|
|
if ((top + height + (BORDER + SHADOW)) >=
|
|
alert_screen_rect.r_height) { /* still overflows */
|
|
top = alert_screen_rect.r_height - height -
|
|
(BORDER + SHADOW);
|
|
if ((top - (r.r_height/2)) >= 0)
|
|
top -= (r.r_height/2);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
if (width > alert_screen_rect.r_width) left = 0;
|
|
if (height > alert_screen_rect.r_height) top = 0;
|
|
rect->r_top = top;
|
|
rect->r_left = left;
|
|
rect->r_width = x;
|
|
rect->r_height = y;
|
|
}
|
|
|
|
static void
|
|
alert_layout(alert, rect, pw)
|
|
register alert_handle alert;
|
|
struct rect *rect;
|
|
struct pixwin *pw;
|
|
{
|
|
Rect r;
|
|
int x, y, width, height, i, j, remembered_x;
|
|
int y_before_buttons, y_after_buttons;
|
|
int alert_too_wide = 0;
|
|
int alert_too_tall = 0;
|
|
button_handle curr;
|
|
int offset;
|
|
/*
|
|
* swoosh_offset is the number of pixels of the swoosh glyph that
|
|
* is outside the alert_box. It changes when the glyphs change
|
|
*/
|
|
int swoosh_offset = SWOOSH_OUTSIDE_BOX;
|
|
|
|
x = rect->r_left;
|
|
y = rect->r_top;
|
|
|
|
pw_lock(pw, &alert_screen_rect);
|
|
|
|
#ifdef OLD_ALERT_IMAGES
|
|
x = rect->r_left + left_marg + BORDER;
|
|
if (alert->image_item) {
|
|
pw_write(pw, x, y,
|
|
alert->image_item->pr_size.x, alert->image_item->pr_size.y,
|
|
PIX_SRC, alert->image_item, 0, 0);
|
|
x += alert->image_item->pr_size.x + left_marg;
|
|
}
|
|
#else
|
|
pw_write(pw, x, y,
|
|
((struct pixrect *)&alert_leftswoosh_pr)->pr_size.x,
|
|
((struct pixrect *)&alert_leftswoosh_pr)->pr_size.y,
|
|
PIX_SRC|PIX_DST, ((struct pixrect *)&alert_leftswoosh_pr), 0, 0);
|
|
/*
|
|
* even though we've drawn alert_leftswoosh_pr->pr_size.x pixels,
|
|
* we only increment the position pointer by
|
|
* (alert_leftswoosh_pr->pr_size.x pixels-SWOOSH_PIXRECTS_H_OFFSET) pixels
|
|
* because the arrow pr is layered on top of leftswoosh pr and offset
|
|
* by SWOOSH_PIXRECTS_H_OFFSET
|
|
*/
|
|
x += (((struct pixrect *)&alert_leftswoosh_pr)->pr_size.x - SWOOSH_PIXRECTS_H_OFFSET);
|
|
y += SWOOSH_PIXRECTS_V_OFFSET;
|
|
pw_write(pw, x, y,
|
|
((struct pixrect *)&alert_arrow_right_pr)->pr_size.x,
|
|
((struct pixrect *)&alert_arrow_right_pr)->pr_size.y,
|
|
PIX_SRC|PIX_DST, ((struct pixrect *)&alert_arrow_right_pr), 0, 0);
|
|
x += ((struct pixrect *)&alert_arrow_right_pr)->pr_size.x + left_marg;
|
|
#endif OLD_ALERT_IMAGES
|
|
|
|
if (alert->message_items) {
|
|
char **strs;
|
|
int num_lines;
|
|
Pixfont *font = (alert->message_font) ? alert->message_font : defpf;
|
|
int offset = alert_offset_from_baseline(font);
|
|
|
|
/*
|
|
* if short_text is TRUE, then reposition the text
|
|
* so that the arrow sort of points at the text.
|
|
*/
|
|
if (short_text_line) {
|
|
y = rect->r_top +
|
|
(swoosh_height - top_marg - row_gap) / (short_text_line + 1);
|
|
} else {
|
|
y = rect->r_top + top_marg + row_gap;
|
|
}
|
|
strs = (char **)alert->message_items;
|
|
while (*strs) {
|
|
pw_text(pw, x, (offset >= 0) ? y + offset : y - offset,
|
|
PIX_SRC, font, (char *)*strs);
|
|
num_lines++;
|
|
y += font->pf_defaultsize.y;
|
|
strs++;
|
|
}
|
|
}
|
|
|
|
x = rect->r_left + left_marg + BORDER + swoosh_offset;
|
|
y = (short_text_line ? rect->r_top + swoosh_height + row_gap : y + row_gap);
|
|
|
|
if (alert->button_info && (alert->number_of_buttons==1)) {
|
|
x += button_gap;
|
|
alert_build_button(pw, rect,
|
|
x, (alert->button_info->is_yes) ? y : y + (YES_BUTTON_Y_DIFF / 2),
|
|
alert->button_info, alert->button_font);
|
|
} else if (alert->button_info && (alert->number_of_buttons>1)) {
|
|
for (curr = alert->button_info; curr != NULL; curr = curr->next) {
|
|
alert_build_button(pw, rect, x,
|
|
(curr->is_yes) ? y : y + (YES_BUTTON_Y_DIFF / 2),
|
|
curr, alert->button_font);
|
|
x += curr->button_rect.r_width + button_gap;
|
|
i++;
|
|
}
|
|
}
|
|
pw_unlock(pw);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* ---------------------- Misc Utilities ------------------------ */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static void
|
|
alert_default(alert)
|
|
alert_handle alert;
|
|
{
|
|
alert->beeps = default_beeps;
|
|
alert->default_input_code = '\0'; /* ASCII NULL */
|
|
alert->button_font = button_font;
|
|
alert->message_font = (Pixfont *) 0;
|
|
alert->position = (int)ALERT_CLIENT_CENTERED;
|
|
alert->client_offset_x = FALSE;
|
|
alert->client_offset_y = FALSE;
|
|
alert->dont_beep = FALSE;
|
|
alert->yes_button_exists = FALSE;
|
|
alert->no_button_exists = FALSE;
|
|
alert->is_optional = FALSE;
|
|
alert->event = (Event *) 0;
|
|
alert->button_info = (button_handle) 0;
|
|
alert->number_of_buttons = 0;
|
|
alert->help_data = "sunview:alert";
|
|
button_gap = 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static int
|
|
calc_max(a, b) /* calculate rather than macro */
|
|
int a, b;
|
|
{
|
|
return ((a>b) ? a : b);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static void
|
|
alert_add_button_to_list(alert, button)
|
|
register alert_handle alert;
|
|
button_handle button;
|
|
{
|
|
button_handle curr;
|
|
|
|
if (alert->button_info) {
|
|
for (curr = alert->button_info; curr; curr = curr->next)
|
|
if (curr->next == NULL) {
|
|
curr->next = button;
|
|
break;
|
|
}
|
|
} else
|
|
alert->button_info = button;
|
|
alert->number_of_buttons++;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static button_handle
|
|
create_button_struct()
|
|
{
|
|
button_handle pi = NULL;
|
|
|
|
pi = (button_handle) calloc(1, sizeof(struct buttons));
|
|
if (!pi)
|
|
fprintf(stderr, "alert: Malloc failed in create_button_struct.\n");
|
|
return pi;
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static void
|
|
free_button_structs(first)
|
|
button_handle first;
|
|
{
|
|
button_handle current;
|
|
button_handle next;
|
|
|
|
if (!first)
|
|
return;
|
|
for (current=first; current != NULL; current=current->next) {
|
|
next = current->next;
|
|
free(current);
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* font char/pixel conversion routines */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static int
|
|
alert_offset_from_baseline(font)
|
|
Pixfont *font;
|
|
{
|
|
if (font == NULL)
|
|
return (0);
|
|
return (font->pf_char[32].pc_home.y); /* space char */
|
|
}
|
|
|
|
static int
|
|
alert_text_width(font, str)
|
|
Pixfont *font;
|
|
char *str;
|
|
{
|
|
struct pr_size size;
|
|
|
|
size = pf_textwidth(strlen(str), font, str);
|
|
return (size.x);
|
|
}
|
|
|
|
static int
|
|
alert_button_width(font, button)
|
|
Pixfont *font;
|
|
button_handle button;
|
|
{
|
|
int text_width = alert_text_width(font, button->string);
|
|
return (text_width + ((button->is_yes) ? 16 : 12));
|
|
}
|
|
|
|
static Pw_pixel_cache *
|
|
alert_drawbox(pw, rectp, rectsavep, fs)
|
|
struct pixwin *pw;
|
|
struct rect *rectp;
|
|
struct rect *rectsavep;
|
|
struct fullscreen *fs;
|
|
{
|
|
struct rect temp_rect;
|
|
Pw_pixel_cache *bitmap_under;
|
|
Pw_pixel_cache *pw_save_pixels();
|
|
int swoosh_x_offset =
|
|
((struct pixrect *)&alert_leftswoosh_pr)->pr_size.x - 4
|
|
- (2 * MENU_BORDER);
|
|
|
|
struct pixrect *pr;
|
|
struct rect rect;
|
|
int x,y; /* XXX workaround */
|
|
|
|
temp_rect = *rectp;
|
|
rect = *rectp;
|
|
rect.r_width += SHADOW;
|
|
rect.r_height += SHADOW;
|
|
if ((bitmap_under = pw_save_pixels(pw, &rect)) == 0)
|
|
return(0);
|
|
*rectsavep = rect;
|
|
rect.r_width -= SHADOW;
|
|
rect.r_height -= SHADOW;
|
|
|
|
/*
|
|
* In order to be able to see the swoosh that lies outside the
|
|
* alert box, pw_preparesurface has to be done for each column
|
|
* of the swoosh. Hence the numerous pw_preparesurface calls.
|
|
*/
|
|
|
|
rect_marginadjust(&temp_rect, - (2 * MENU_BORDER));
|
|
y = temp_rect.r_top;
|
|
temp_rect.r_left += 18;
|
|
temp_rect.r_top = y + 6;
|
|
temp_rect.r_width = 1;
|
|
temp_rect.r_height = 11;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 10;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 13;
|
|
temp_rect.r_height = 12;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 15;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 17;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 18;
|
|
temp_rect.r_height = 13;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 19;
|
|
temp_rect.r_height = 14;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 20;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 21;
|
|
temp_rect.r_height = 15;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 22;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 23;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 23;
|
|
temp_rect.r_height = 17;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 24;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 25;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 25;
|
|
temp_rect.r_height = 18;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 26;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 27;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 27;
|
|
temp_rect.r_height = 19;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 28;
|
|
temp_rect.r_height = 18;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 28;
|
|
temp_rect.r_height = 19;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 29;
|
|
temp_rect.r_height = 20;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 29;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 30;
|
|
temp_rect.r_height = 19;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 30;
|
|
temp_rect.r_height = 20;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 30;
|
|
temp_rect.r_height = 21;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 31;
|
|
temp_rect.r_height = 20;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 31;
|
|
temp_rect.r_height = 21;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 32;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 32;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 32;
|
|
temp_rect.r_height = 22;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 33;
|
|
temp_rect.r_height = 21;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
y += SWOOSH_PIXRECTS_V_OFFSET;
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 17;
|
|
temp_rect.r_height = 22;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 17;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 17;
|
|
temp_rect.r_height = 23;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
temp_rect.r_left += 1;
|
|
temp_rect.r_top = y + 17;
|
|
temp_rect.r_height = 24;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
/*
|
|
* shrink the surface to be prepared by the number of pixels that
|
|
* are hanging outside of the "Big alert_box". This way, the
|
|
* pw_preparesurface is called(clearing the underlying bits) only
|
|
* on the inner alert box.
|
|
*/
|
|
|
|
/* draw prompt box */
|
|
temp_rect = *rectp;
|
|
temp_rect.r_left += swoosh_x_offset;
|
|
temp_rect.r_width -= swoosh_x_offset;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
|
|
/* draw shadow of prompt box */
|
|
temp_rect.r_left += SHADOW;
|
|
temp_rect.r_top += SHADOW;
|
|
pw_preparesurface_full(pw, &temp_rect, 1);
|
|
temp_rect.r_left -= SHADOW;
|
|
temp_rect.r_top -= SHADOW;
|
|
|
|
pw_lock(pw, &alert_screen_rect); /* protect underling pr */
|
|
|
|
/* restore stuff bitmap_under shadow */
|
|
pr = pw_primary_cached_mpr(fs->fs_pixwin, bitmap_under);
|
|
pw_write(pw, rect.r_left+rect.r_width, rect.r_top + SHADOW,
|
|
SHADOW, rect.r_height, PIX_SRC, pr,
|
|
rect.r_width, SHADOW);
|
|
pw_write(pw, rect.r_left+swoosh_x_offset+SHADOW,
|
|
rect.r_top + rect.r_height, rect.r_width-swoosh_x_offset,
|
|
SHADOW, PIX_SRC, pr, SHADOW, rect.r_height);
|
|
|
|
/*
|
|
* XXX Workaround for pw_replrop bug. Get pixwin by hand instead
|
|
*/
|
|
/* pw_replrop(pw, rect.r_left + SHADOW, rect.r_top + SHADOW,
|
|
rect.r_width, rect.r_height, PIX_SRC|PIX_DST, &alert_gray50_patch, 0, 0);
|
|
*/
|
|
|
|
/* draw drop shadow as source instead of OR (|PIX_DST) */
|
|
x = pw->pw_clipdata->pwcd_clipping.rl_bound.r_left;
|
|
y = pw->pw_clipdata->pwcd_clipping.rl_bound.r_top;
|
|
/* this rect includes a left-offset for the swoosh image */
|
|
pr_replrop(pw->pw_clipdata->pwcd_prsingle,
|
|
rect.r_left + rect.r_width - x,
|
|
rect.r_top + SHADOW - y,
|
|
SHADOW, rect.r_height, PIX_SRC,
|
|
&alert_gray50_patch,
|
|
rect.r_left + rect.r_width - x + swoosh_x_offset,
|
|
rect.r_top + SHADOW - y);
|
|
pr_replrop(pw->pw_clipdata->pwcd_prsingle,
|
|
rect.r_left + SHADOW - x + swoosh_x_offset,
|
|
rect.r_top + rect.r_height - y,
|
|
rect.r_width - SHADOW - swoosh_x_offset, SHADOW, PIX_SRC,
|
|
&alert_gray50_patch,
|
|
rect.r_left + SHADOW - x + swoosh_x_offset,
|
|
rect.r_top + rect.r_height - y);
|
|
|
|
/* draw border of prompt box */
|
|
pw_writebackground(pw,
|
|
rect.r_left + swoosh_x_offset,
|
|
rect.r_top,
|
|
rect.r_width - swoosh_x_offset,
|
|
rect.r_height, PIX_SET);
|
|
rect_marginadjust(&rect, - (2 * MENU_BORDER));
|
|
pw_writebackground(pw,
|
|
rect.r_left + swoosh_x_offset,
|
|
rect.r_top,
|
|
rect.r_width - swoosh_x_offset,
|
|
rect.r_height, PIX_CLR);
|
|
|
|
pw_unlock(pw);
|
|
|
|
*rectp = rect;
|
|
return(bitmap_under);
|
|
}
|
|
|
|
static void
|
|
alert_build_button(pw, rect, x, y, button, font)
|
|
struct pixwin *pw;
|
|
struct rect *rect;
|
|
int x, y;
|
|
button_handle button;
|
|
struct pixfont *font;
|
|
{
|
|
struct pr_prpos where; /* where to write the string */
|
|
struct pr_size size; /* size of the pixrect */
|
|
int width, height;
|
|
char *string = button->string;
|
|
int special = button->is_yes;
|
|
|
|
size = pf_textwidth(strlen(string), font, string);
|
|
width = size.x;
|
|
|
|
where.pr = (special) ?
|
|
mem_create(width + 16, size.y + 8, 1)
|
|
: mem_create(width + 12, size.y + 4, 1);
|
|
|
|
if (!where.pr)
|
|
return;
|
|
|
|
where.pos.x = (special) ?
|
|
8 + (width - size.x) / 2
|
|
: 6 + (width - size.x) / 2;
|
|
where.pos.y = (special) ?
|
|
4 + panel_fonthome(font)
|
|
: 2 + panel_fonthome(font);
|
|
|
|
(void)pf_text(where, PIX_SRC, font, string);
|
|
|
|
if (special) {
|
|
alert_yes_outline_button(where.pr);
|
|
} else alert_outline_button(where.pr);
|
|
|
|
width += ((special) ? 16 : 12);
|
|
height = size.y + ((special) ? 8 : 4);
|
|
|
|
button->button_rect.r_top = y;
|
|
button->button_rect.r_left = x;
|
|
button->button_rect.r_width = width;
|
|
button->button_rect.r_height = height;
|
|
|
|
pw_write(pw, x, y, width, height, PIX_SRC, where.pr, 0, 0);
|
|
}
|
|
|
|
/* returns 0 if fails to open fd */
|
|
static int
|
|
alert_get_fd(fd)
|
|
int *fd;
|
|
{
|
|
int windowfd, result, parentlink, parentfd;
|
|
Inputmask new_kbd_mask, new_pick_mask;
|
|
char name[WIN_NAMESIZE];
|
|
char *filename;
|
|
extern char *getenv();
|
|
|
|
/* Open WMGR_ENV_PLACEHOLDER to get an fd for input_readevent;
|
|
* this fd is kept open for the duration of the application, its
|
|
* closing is left to be taken care of by the death of the application.
|
|
* Saving the placeholder icon rect and open rect here, and restoring
|
|
* them in alert_prompt.
|
|
*/
|
|
if ((filename = getenv("WMGR_ENV_PLACEHOLDER")) == (char *) NULL) {
|
|
(void)fprintf(stderr, "No placeholder name in environment?\n");
|
|
return 0;
|
|
}
|
|
if ((windowfd = open(filename, O_RDWR, 0)) == -1) {
|
|
perror("Couldn't open placeholder for alert.\n");
|
|
return 0;
|
|
}
|
|
win_getrect(windowfd, &irect);
|
|
win_getsavedrect(windowfd, &orect);
|
|
|
|
if (windowfd < 0)
|
|
return(0);
|
|
if (we_getparentwindow(name))
|
|
return(0);
|
|
if ((parentfd = open(name, O_RDONLY, 0)) < 0)
|
|
return(0);
|
|
parentlink = win_nametonumber(name);
|
|
(void)win_setlink(windowfd, WL_PARENT, parentlink);
|
|
|
|
(void)win_getrect(parentfd, &alert_screen_rect);
|
|
close(parentfd);
|
|
(void)win_setrect(windowfd, &alert_screen_rect);
|
|
|
|
(void)input_imnull(&new_kbd_mask);
|
|
new_kbd_mask.im_flags |= IM_ASCII | IM_META | IM_NEGMETA | IM_NEGEVENT;
|
|
(void)win_setinputcodebit(&new_kbd_mask, WIN_STOP);
|
|
(void)win_keymap_set_smask(windowfd, ACTION_HELP);
|
|
win_keymap_set_imask_from_std_bind(&new_kbd_mask, ACTION_HELP);
|
|
(void)win_set_kbd_mask(windowfd, &new_kbd_mask);
|
|
|
|
(void)input_imnull(&new_pick_mask);
|
|
new_pick_mask.im_flags |= IM_NEGEVENT;
|
|
(void)win_setinputcodebit(&new_pick_mask, WIN_STOP);
|
|
(void)win_setinputcodebit(&new_pick_mask, MS_LEFT);
|
|
(void)win_setinputcodebit(&new_pick_mask, MS_MIDDLE);
|
|
(void)win_setinputcodebit(&new_pick_mask, MS_RIGHT);;
|
|
(void)win_setinputcodebit(&new_pick_mask, LOC_DRAG);;
|
|
(void)win_set_pick_mask(windowfd, &new_pick_mask);
|
|
|
|
/*
|
|
* Need to open and close a pixwin on the window once to initialize
|
|
* the window before using it to do fullscreen access. Don't know
|
|
* why, but this is the only place that a window is being used to
|
|
* go directly to fullscreen access instead of being used for screen
|
|
* rendering (bug number 1010749).
|
|
*/
|
|
pw_close(pw_open_monochrome(windowfd));
|
|
|
|
*fd = windowfd;
|
|
alert_fd = windowfd;
|
|
return (1);
|
|
}
|
|
|
|
static void
|
|
alert_outline_button(pr)
|
|
register Pixrect *pr;
|
|
/* outline_button draws an outline of a button in pr.
|
|
*/
|
|
{
|
|
int x_left = 0;
|
|
int x_right = pr->pr_size.x - 1;
|
|
int y_top = 0;
|
|
int y_bottom = pr->pr_size.y - 1;
|
|
int x1 = 3;
|
|
int x2 = x_right - 3;
|
|
int y1 = 3;
|
|
int y2 = y_bottom - 3;
|
|
|
|
/* horizontal lines */
|
|
(void)pr_vector(pr, x1, y_top, x2, y_top, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x1, y_top + 1, x2, y_top + 1, PIX_SRC, 1);
|
|
|
|
(void)pr_vector(pr, x1, y_bottom, x2, y_bottom, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x1, y_bottom - 1, x2, y_bottom - 1, PIX_SRC, 1);
|
|
|
|
/* vertical lines */
|
|
(void)pr_vector(pr, x_left, y1, x_left, y2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left + 1, y1, x_left + 1, y2, PIX_SRC, 1);
|
|
|
|
(void)pr_vector(pr, x_right, y1, x_right, y2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 1, y1, x_right - 1, y2, PIX_SRC, 1);
|
|
|
|
/* left corners */
|
|
(void)pr_vector(pr, x_left, y1, x1, y_top, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left + 1, y1, x1 + 1, y_top, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left + 1, y1 + 1, x1 + 2, y_top, PIX_SRC, 1);
|
|
|
|
(void)pr_vector(pr, x_left, y2, x1, y_bottom, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left + 1, y2, x1 + 1, y_bottom, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left + 1, y2 - 1, x1 + 2, y_bottom, PIX_SRC, 1);
|
|
|
|
/* right corners */
|
|
(void)pr_vector(pr, x_right, y1, x2, y_top, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 1, y1, x2 - 1, y_top, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 1, y1 + 1, x2 - 2, y_top, PIX_SRC, 1);
|
|
|
|
(void)pr_vector(pr, x_right, y2, x2, y_bottom, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 1, y2, x2 - 1, y_bottom, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 1, y2 - 1, x2 - 2, y_bottom, PIX_SRC, 1);
|
|
}
|
|
|
|
/* below draws a double, then single outlined button image */
|
|
static void
|
|
alert_yes_outline_button(pr)
|
|
register Pixrect *pr;
|
|
{
|
|
int x_left = 0;
|
|
int x_right = pr->pr_size.x - 1;
|
|
int y_top = 0;
|
|
int y_bottom = pr->pr_size.y - 1;
|
|
int x1 = 3;
|
|
int x2 = x_right - 3;
|
|
int y1 = 3;
|
|
int y2 = y_bottom - 3;
|
|
|
|
/* top horizontal lines */
|
|
(void)pr_vector(
|
|
pr, x1, y_top, x2, y_top, PIX_SRC, 1); /*top, single*/
|
|
(void)pr_vector(
|
|
pr, x1, y_top+1, x2, y_top+1, PIX_SRC, 1); /*no blank line*/
|
|
(void)pr_vector(
|
|
pr, x1+1, y_top + 2, x2-1, y_top + 2, PIX_SRC, 1);/*1st dbl line*/
|
|
(void)pr_vector(
|
|
pr, x1+1, y_top + 3, x2-1, y_top + 3, PIX_SRC, 1);/*2nd dbl line*/
|
|
|
|
/* bottom horizontal lines */
|
|
(void)pr_vector(
|
|
pr, x1, y_bottom, x2, y_bottom, PIX_SRC, 1); /*bottom single*/
|
|
(void)pr_vector(
|
|
pr, x1, y_bottom - 1, x2, y_bottom - 1, PIX_SRC, 1); /*no blank line*/
|
|
(void)pr_vector(
|
|
pr, x1+1, y_bottom - 2, x2-1, y_bottom - 2, PIX_SRC, 1);/*1st above*/
|
|
(void)pr_vector(
|
|
pr, x1+1, y_bottom - 3, x2-1, y_bottom - 3, PIX_SRC, 1);/*2nd above*/
|
|
|
|
/* left vertical lines (left to right)*/
|
|
(void)pr_vector(pr, x_left, y1, x_left, y2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+1, y1, x_left+1, y2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left + 2, y1+1, x_left + 2, y2-1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left + 3, y1+1, x_left + 3, y2-1, PIX_SRC, 1);
|
|
|
|
/* right vertical lines (right to left)*/
|
|
(void)pr_vector(pr, x_right, y1, x_right, y2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 1, y1, x_right - 1, y2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 2, y1+1, x_right - 2, y2-1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right - 3, y1+1, x_right - 3, y2-1, PIX_SRC, 1);
|
|
|
|
/* left top corners */
|
|
(void)pr_vector(pr, x_left, y1, x1, y_top, PIX_SRC, 1); /*single */
|
|
(void)pr_vector(pr, x_left+1, y1, x1, y_top+1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+1, y1+1, x1+1, y_top+1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+2, y1+1, x1+1, y_top+2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+3, y1+1, x1+2, y_top+2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+3, y1+2, x1+3, y_top+2, PIX_SRC, 1);
|
|
|
|
/* left bottom corners */
|
|
(void)pr_vector(pr, x_left, y2, x1, y_bottom, PIX_SRC, 1); /*single */
|
|
(void)pr_vector(pr, x_left+1, y2, x1, y_bottom-1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+1, y2-1, x1+1, y_bottom-1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+2, y2-1, x1+1, y_bottom-2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+3, y2-1, x1+2, y_bottom-2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_left+3, y2-2, x1+3, y_bottom-2, PIX_SRC, 1);
|
|
|
|
/* right top corners */
|
|
(void)pr_vector(pr, x_right, y1, x2, y_top, PIX_SRC, 1); /*single */
|
|
(void)pr_vector(pr, x_right-1, y1, x2, y_top+1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-1, y1+1, x2-1, y_top+1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-2, y1+1, x2-1, y_top+2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-3, y1+1, x2-2, y_top+2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-3, y1+2, x2-3, y_top+2, PIX_SRC, 1);
|
|
|
|
/* right bottom corners */
|
|
(void)pr_vector(pr, x_right, y2, x2, y_bottom, PIX_SRC, 1); /*single */
|
|
(void)pr_vector(pr, x_right-1, y2, x2, y_bottom-1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-1, y2-1, x2-1, y_bottom-1, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-2, y2-1, x2-1, y_bottom-2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-3, y2-1, x2-2, y_bottom-2, PIX_SRC, 1);
|
|
(void)pr_vector(pr, x_right-3, y2-2, x2-3, y_bottom-2, PIX_SRC, 1);
|
|
}
|
|
|
|
static void
|
|
alert_select_button(pw, button)
|
|
struct pixwin *pw;
|
|
button_handle button;
|
|
{
|
|
if (!button)
|
|
return; /* just in case this sneaked by above */
|
|
pw_writebackground(pw,
|
|
button->button_rect.r_left, button->button_rect.r_top,
|
|
button->button_rect.r_width, button->button_rect.r_height,
|
|
PIX_NOT(PIX_DST)); /* invert button rectangle */
|
|
}
|
|
|
|
static void
|
|
alert_unselect_button(pw, button)
|
|
struct pixwin *pw;
|
|
button_handle button;
|
|
{
|
|
(void)alert_select_button(pw, button);
|
|
}
|
|
|
|
static button_handle
|
|
alert_button_for_event(alert, event)
|
|
register alert_handle alert;
|
|
Event *event;
|
|
{
|
|
button_handle curr;
|
|
int x, y;
|
|
int action = event_action(event);
|
|
|
|
if (alert->button_info == NULL)
|
|
return (NULL);
|
|
|
|
if ((action != MS_LEFT) && (action != LOC_DRAG))
|
|
return (NULL);
|
|
|
|
x = event->ie_locx; y = event->ie_locy;
|
|
for (curr = alert->button_info; curr; curr = curr->next) {
|
|
if ( (x >= curr->button_rect.r_left)
|
|
&& (x <= (curr->button_rect.r_left
|
|
+ curr->button_rect.r_width))
|
|
&& (y >= curr->button_rect.r_top)
|
|
&& (y <= (curr->button_rect.r_top
|
|
+ curr->button_rect.r_height)) ) {
|
|
return (curr);
|
|
}
|
|
}
|
|
return ((button_handle) 0);
|
|
}
|
|
|
|
static void
|
|
alert_do_bell(alert, fd)
|
|
alert_handle alert;
|
|
int fd;
|
|
{
|
|
struct timeval wait;
|
|
|
|
if (!alert_use_audible_bell)
|
|
return;
|
|
|
|
wait.tv_sec = 0;
|
|
wait.tv_usec = 100000;
|
|
|
|
if (!alert->dont_beep && (alert->beeps > 0)) {
|
|
int i = alert->beeps;
|
|
int cmd, kbdfd;
|
|
struct screen screen;
|
|
|
|
(void)win_screenget(fd, &screen);
|
|
if ((kbdfd = open(screen.scr_kbdname, O_RDWR, 0)) < 0)
|
|
return;
|
|
while (i--) {
|
|
cmd = KBD_CMD_BELL;
|
|
(void) ioctl(kbdfd, KIOCCMD, &cmd);
|
|
(void)alert_blocking_wait(wait);
|
|
cmd = KBD_CMD_NOBELL;
|
|
(void) ioctl(kbdfd, KIOCCMD, &cmd);
|
|
}
|
|
(void)close(kbdfd);
|
|
}
|
|
|
|
}
|
|
|
|
/* below stolen from win_bell */
|
|
static void
|
|
alert_blocking_wait(wait_tv)
|
|
struct timeval wait_tv;
|
|
{
|
|
extern struct timeval ndet_tv_subt(); /* From notifier code */
|
|
struct timeval start_tv, now_tv, waited_tv;
|
|
int bits;
|
|
|
|
/* Get starting time */
|
|
(void)gettimeofday(&start_tv, (struct timezone *)0);
|
|
/* Wait */
|
|
while (timerisset(&wait_tv)) {
|
|
/* Wait for awhile in select */
|
|
bits = 0;
|
|
(void) select(0, &bits, &bits, &bits, &wait_tv);
|
|
/* Get current time */
|
|
(void)gettimeofday(&now_tv, (struct timezone *)0);
|
|
/* Compute how long waited */
|
|
waited_tv = ndet_tv_subt(now_tv, start_tv);
|
|
/* Subtract time waited from time left to wait */
|
|
wait_tv = ndet_tv_subt(wait_tv, waited_tv);
|
|
}
|
|
}
|
|
|
|
#endif ecd.alert
|