Files
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

479 lines
10 KiB
C

#ifndef lint
static char sccsid[] = "@(#)buttons.c 1.1 94/10/31 Copyr 1987 Sun Micro";
#endif
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
#include <suntool/sunview.h>
#include <suntool/panel.h>
#include <suntool/selection.h>
#include <suntool/textsw.h>
#include <suntool/ttysw.h>
#undef ord
#include "defs.h"
#include "pipeout.h"
#include "typedefs.h"
#include "buttons.h"
#include "cmd.h"
#include "dbxenv.h"
#include "dbxlib.h"
#include "dbxtool.h"
#include "selection.h"
#include "menu.h"
#define BUTTON_VSPACE 3 /* Vertical space between buttons */
#define BUTTON_HSPACE 2 /* Horizontal space between buttons */
#define BUTTON_VBORDER 3 /* # pixels between button and border */
#define BUTTON_EXTRA_HEIGHT 4 /* Diff between button/font heights */
#define MINLEN 4 /* Min size button, in chars */
#define MAXLEN 10 /* Max size button, in chars */
typedef struct Button *Button;
struct Button {
char *text; /* Text of the button */
Strfunc sel_inter; /* Selection interpretation routine */
char *show_text; /* Text that is shown */
Pixrectp image; /* Button image */
Panel_item handle; /* Button handle */
Button next; /* Linked list */
};
/*
* The default buttons.
*/
private struct Button def_buttons[] = {
{ "print", sel_expand },
{ "print *", sel_expand },
{ "next", sel_ignore },
{ "step", sel_ignore },
{ "stop at", sel_lineno },
{ "cont", sel_ignore },
{ "stop in", sel_expand },
{ "clear", sel_lineno },
{ "where", sel_ignore },
{ "up", sel_ignore },
{ "down", sel_ignore },
{ "run", sel_ignore },
{ nil, nil }
};
private Button button_hdr; /* List of buttons */
private Button *bpatch = &button_hdr; /* Place to add a new button */
private Panel buttons; /* Buttons panel subwin struct */
private int button_sw_height; /* Height of the buttons subwindow */
private int button_width; /* Width of a button */
private int button_height; /* Height of a button */
private int nbuttons; /* Number of buttons */
private int maxlen; /* Max length of text in a button */
private Pixfontp button_font; /* Button font */
private Boolean buttons_displayed; /* Have the buttons been displayed? */
private int button_cmd();
private Notify_value button_event();
/*
* Create the buttons subwindow
*/
public create_buttons_sw(base_frame, pixfont)
Frame base_frame;
Pixfontp pixfont;
{
/* Height will be calculated by window_fit_height */
buttons = window_create( base_frame, PANEL,
PANEL_SHOW_MENU, FALSE,
PANEL_PAINT, PANEL_NONE,
0);
if (buttons == nil) {
fprintf(stderr, "Could not create the buttons subwindow\n");
exit(1);
}
(void)notify_interpose_event_func(buttons, button_event, NOTIFY_SAFE);
button_font = pixfont;
buttons_default();
menu_default();
}
/*
* Initialize the command buttons to their default values.
*/
private buttons_default()
{
Button bp;
button_hdr = def_buttons;
nbuttons++;
bpatch = &def_buttons[0].next;
for (bp = &def_buttons[1]; bp->text != nil; bp++) {
*bpatch = bp;
bpatch = &bp->next;
nbuttons++;
}
button_hdr = &def_buttons[0];
/*
* Dynamically allocate the strings for the default
* buttons so the deallocator doesn't need to know
* the difference.
*/
for (bp = def_buttons; bp->text != nil; bp++) {
bp->text = strdup(bp->text);
}
}
/*
* Add a button to the list.
*/
private add_button(str, func)
char *str;
Strfunc func;
{
Button bp;
int oldheight;
oldheight = buttons_height();
bp = new(Button);
bp->text = strdup(str);
bp->sel_inter = func;
bp->next = nil;
*bpatch = bp;
bpatch = &bp->next;
nbuttons++;
if (buttons_displayed) {
show_button(bp);
redraw_buttons(oldheight);
}
}
/*
* Redraw the buttons subwindow. A button has been added or deleted.
* If the height of the subwindow has changed, do lots of work,
* otherwise, just redraw this subwindow.
*/
private redraw_buttons(oldheight)
int oldheight;
{
if (buttons_displayed) {
if (oldheight != buttons_height()) {
change_size(false);
} else {
button_resize();
}
}
}
/*
* Make all the buttons. Make a pass over all the buttons to
* find the longest string and make all the buttons the same width.
*/
private make_buttons()
{
Button bp;
int len;
maxlen = 0;
for (bp = button_hdr; bp != nil; bp = bp->next) {
len = strlen(bp->text);
if (len > maxlen) {
maxlen = len;
}
}
if (maxlen < MINLEN) {
maxlen = MINLEN;
} else if (maxlen > MAXLEN) {
maxlen = MAXLEN;
}
window_set(buttons, PANEL_FONT, button_font, 0);
for (bp = button_hdr; bp != nil; bp = bp->next) {
show_button(bp);
}
button_width = button_hdr->image->pr_size.x;
button_height = button_hdr->image->pr_size.y;
buttons_displayed = true;
window_fit_height( buttons );
}
/*
* Show a button. Create an image.
*/
private show_button(bp)
Button bp;
{
if (bp->show_text == nil) {
bp->show_text = strdup(bp->text);
if (strlen(bp->show_text) > maxlen) {
bp->show_text[maxlen - 1] = '*';
bp->show_text[maxlen] = '\0';
}
}
bp->image = panel_button_image(buttons, bp->show_text, maxlen,
button_font);
bp->handle = panel_create_item(buttons, PANEL_BUTTON,
PANEL_LABEL_IMAGE, bp->image,
PANEL_NOTIFY_PROC, button_cmd,
PANEL_SHOW_ITEM, (bp->text[0] != '\0'),
0);
}
/*
* A command button has been picked.
* Search the list of buttons for a matching handle and process
* the command.
* ARGSUSED
*/
private button_cmd(handle)
Panel_item handle;
{
Button bp;
for (bp = button_hdr; bp != nil; bp = bp->next) {
if (handle == bp->handle) {
interpret_selection(bp->sel_inter, bp->text);
break;
}
}
}
/*
* Interpret the selection.
* Build a command and pass it to dbx.
*/
public interpret_selection(func, text)
Strfunc func;
char *text;
{
char *sel;
char buf[512];
sel = func();
if (sel != nil) {
if (func == sel_command) {
sprintf(buf, "%s", sel);
} else {
sprintf(buf, "%s %s\n", text, sel);
}
} else {
strcpy(buf, "\n");
}
ttysw_cmd(get_cmd_sw_h(), buf, strlen(buf));
}
/*
* Notification routine for events coming into the buttons subwindow.
* Look for the RESIZE event to lay out the buttons again.
* ARGSUSED
*/
private Notify_value button_event(client, event, arg, when)
Panel client;
Eventp event;
Notify_arg arg;
Notify_event_type when;
{
Notify_value r;
if (event_id(event) == MS_RIGHT) {
menu_show(get_menu(), get_buttonw_h(), event, 0);
r = NOTIFY_DONE;
} else {
r = notify_next_event_func(client, event, arg, when);
if (event_id(event) == WIN_RESIZE) {
button_resize();
}
}
return(r);
}
/*
* The size of the buttons subwindow has changed.
* Layout the buttons again.
* Center the buttons in the subwindow, and use as many rows as
* necessary.
*
*/
public button_resize()
{
Button bp;
int left;
int top;
int buttons_perrow;
int width;
int row_width;
int remaining;
int i;
int buttons_this_row;
width = (int) get_toolwidth();
buttons_perrow = buttons_per_row(nbuttons);
i = buttons_perrow; /* Force start of new row */
top = -(button_height + BUTTON_VSPACE - BUTTON_VBORDER);
remaining = nbuttons;
for (bp = button_hdr; bp != nil; bp = bp->next) {
if (++i >= buttons_perrow) {
if (remaining < buttons_perrow) {
buttons_this_row = remaining;
} else {
buttons_this_row = buttons_perrow;
}
row_width = buttons_this_row * button_width +
(buttons_this_row - 1) * BUTTON_HSPACE;
left = (width - row_width)/2;
top += button_height + BUTTON_VSPACE;
i = 0;
}
panel_set(bp->handle,
PANEL_LABEL_Y, top,
PANEL_LABEL_X, left,
PANEL_PAINT, PANEL_NONE,
0);
left += button_width + BUTTON_HSPACE;
remaining--;
}
panel_paint(buttons, PANEL_CLEAR);
}
/*
* A user defined button.
* If it is the first button clear the default ones.
*/
public dbx_new_button(seltype, str)
Seltype seltype;
char *str;
{
Strfunc func;
func = sel_func(seltype);
add_button(str, func);
}
/*
* Delete an existing button.
* Find the button in the linked list of buttons and remove it.
* Repaint the subwindow and adjust the back patch pointer.
*/
public dbx_unbutton(str)
char *str;
{
Button bp;
Button next;
int oldheight;
oldheight = buttons_height();
bpatch = &button_hdr;
for (bp = button_hdr; bp != nil; bp = next) {
next = bp->next;
if (streq(bp->text, str)) {
nbuttons--;
*bpatch = next;
if (bp->handle != nil) {
panel_free(bp->handle);
}
dispose(bp->text);
if (bp->show_text != nil) {
dispose(bp->show_text);
}
dispose(bp);
} else {
bpatch = &bp->next;
}
}
for (bp = button_hdr; bp != nil; bp = bp->next) {
bpatch = &bp->next;
}
redraw_buttons(oldheight);
}
/*
* Return the handle for the buttons subwindow
*/
public Panel get_buttonw_h()
{
return( buttons );
}
/*
* Taking the width of the tool into account,
* return the desired number of buttons per row of the subwindow.
*/
private buttons_per_row(max_per_row)
int max_per_row;
{
int fakewidth;
register int per_row;
fakewidth = get_toolwidth() - (2 * TOOL_BORDERWIDTH) + BUTTON_HSPACE;
per_row = fakewidth / (button_width + BUTTON_HSPACE);
if (per_row > max_per_row) {
per_row = max_per_row;
}
if (per_row <= 0) {
per_row = 1;
}
return(per_row);
}
/*
* Taking the width of the tool into account,
* return the desired height of the buttons subwindow.
*/
public buttons_height()
{
Frame base_frame;
Rectp rp;
int buttons_perrow;
int maxheight;
int rows;
int height;
if (nbuttons == 0) {
return(button_sw_height);
}
buttons_perrow = buttons_per_row(nbuttons);
rows = nbuttons/buttons_perrow;
if ((nbuttons % buttons_perrow) != 0) {
rows++;
}
button_sw_height = rows * (button_height + BUTTON_VSPACE) -
BUTTON_VSPACE + 2*BUTTON_VBORDER;
base_frame = get_base_frame();
rp = get_screenrect();
maxheight = rp->r_height -
(tool_stripeheight(base_frame)+2) -
get_statusmin() -
tool_subwindowspacing(base_frame) -
get_srcmin() -
tool_subwindowspacing(base_frame) -
/* button subwindow lives here */
tool_subwindowspacing(base_frame) -
get_cmdmin() -
tool_subwindowspacing(base_frame) -
get_dispmin() -
tool_borderwidth(base_frame);
if (button_sw_height > maxheight) {
button_sw_height = maxheight;
}
return(button_sw_height);
}
/*
* The font has changed. Must remove all the buttons and create new
* ones.
*/
public new_buttonsfont(font)
Pixfontp font;
{
Panel_item item;
button_font = font;
panel_each_item(buttons, item)
panel_free(item);
panel_end_each;
make_buttons();
}