/* buttons.c */
#include "ml.h"
#ifdef __STDC__
ButtonList *new_buttonlist(void)
#else
ButtonList *new_buttonlist()
#endif
{
ButtonList *buttonlist = (ButtonList *) fs_get(sizeof(ButtonList));
buttonlist->w = NULL;
buttonlist->state = 0L;
buttonlist->next = NULL;
return(buttonlist);
}
#ifdef __STDC__
void free_buttonlist(ButtonList *buttonlist)
#else
void free_buttonlist(buttonlist)
ButtonList *buttonlist;
#endif
{
if(buttonlist == NULL)
return;
free_buttonlist(buttonlist->next);
fs_give((void **) &buttonlist);
return;
}
/*
* A window flush is added to each button callback so that
* we can debug the program. Otherwise, the button retains focus
* after breakpoints, and the debugger can't get input.
*/
#ifdef __STDC__
void flush_windows(Widget w, XtPointer xp, XtPointer cb)
#else
void flush_windows(w,xp,cb)
Widget w;
XtPointer xp;
XtPointer cb;
#endif
{
XFlush(display);
}
#ifdef __STDC__
void make_pbuttons(Widget rowcol, Button_Menu *button_menu,
unsigned long state, XtPointer callback)
#else
void make_pbuttons(rowcol, button_menu, state, callback)
Widget rowcol;
Button_Menu *button_menu;
unsigned long state;
XtPointer callback;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
Button_Menu *bmenu;
Dimension height = 0;
for(bmenu = button_menu; bmenu; bmenu = bmenu->next) {
if(bmenu->label) {
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
if(state & bmenu->statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
bmenu->widget = XmCreatePushButton(rowcol, bmenu->label, args, n);
n = 0;
XtManageChild(bmenu->widget);
if(height == 0)
XtVaGetValues(bmenu->widget, XmNheight, &height, NULL);
else
XtVaSetValues(bmenu->widget, XmNheight, height, NULL);
XtAddCallback(bmenu->widget,XmNactivateCallback, flush_windows, NULL );
XtAddCallback(bmenu->widget,XmNactivateCallback, bmenu->func, callback);
}
}
}
#ifdef __STDC__
void make_secondbuttons(ButtonList *bl,
Widget rowcol,
Button_Menu *button_menu,
int total,
ButtonState state,
XtPointer callback)
#else
void make_secondbuttons(bl, rowcol, button_menu, total, state, callback)
ButtonList *bl;
Widget rowcol;
Button_Menu *button_menu;
int total;
unsigned long state;
XtPointer callback;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
int count = 0;
ButtonList *buttonlist;
ButtonList *prev;
for(count = 0; count < total; count ++) {
buttonlist = new_buttonlist();
for(prev = bl; prev->next; prev = prev->next)
;
prev->next = buttonlist;
buttonlist->state = button_menu[count].statemap;
if(button_menu[count].label) {
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
if(state & button_menu[count].statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
buttonlist->w = XmCreatePushButton(rowcol,
button_menu[count].label,
args,
n);
n = 0;
XtManageChild(buttonlist->w);
XtAddCallback(buttonlist->w,XmNactivateCallback,
flush_windows, NULL );
XtAddCallback(buttonlist->w,XmNactivateCallback,
button_menu[count].func, callback);
}
}
return;
}
/*
* void create_buttons();
*
* Creates cascading menus on a menubar (parent widget must be a menubar).
* If a menulist item already contains a callback data item it will
* be used. Otherwise the data passed to the function will be used.
* A button name containing the string "HELP" will be set up on the
* right hand side of the menubar. Names _should_ be unique. This allows
* us to track down the buttons later and change their state or callback,
* regardless of the label -- which may have been changed.
* Button state is determined by the menulist->state variable. Each bit
* indicates a condition this button should be checked against ( a '1' bit
* indicates the button should be insensitive when the condition matches.
* The state variable passed to this function is used to determine initial
* sensitive state.
* Actually this function is overkill. But it does all the work of managing
* buttons. I've had to abandon some of the functionality in order to
* provide internationalization and customization. It's there if I ever need
* hyper linked buttons which can change state and function at will.
*/
#ifdef __STDC__
void create_buttons(char *name, Widget menu,
Menu *menulist, int size,
unsigned long state, XtPointer callback, int level)
#else
void create_buttons(name, menu, menulist, size, state, callback, level )
char *name;
Widget menu;
Menu *menulist;
int size;
unsigned long state;
XtPointer callback;
int level;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
int cnt;
WidgetList buttons;
XmString label;
char buffer[256];
buttons = (WidgetList) XtMalloc(size * sizeof(Widget));
for(cnt = 0; cnt < size; cnt ++) {
if(menulist[cnt].func) {
if(menulist[cnt].label) {
label = XmStringCreateSimple(menulist[cnt].label);
XtSetArg(args[n], XmNlabelString, label); n ++;
}
XtSetArg(args[n], XmNborderWidth, 0); n ++;
if(menulist[cnt].mnemonic) {
XtSetArg(args[n], XmNmnemonic, menulist[cnt].mnemonic); n ++;
}
if(state & menulist[cnt].statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
if(level == ROOTMENULEVEL)
buttons[cnt] = XmCreateCascadeButton(menu, menulist[cnt].name,
args,n);
else
buttons[cnt] = XmCreatePushButton(menu, menulist[cnt].name, args, n);
n = 0;
menulist[cnt].widget = buttons[cnt];
if(menulist[cnt].label)
XmStringFree(label);
XtAddCallback(buttons[cnt],XmNactivateCallback, flush_windows, NULL );
XtAddCallback(buttons[cnt],XmNactivateCallback, menulist[cnt].func,
(menulist[cnt].data) ? menulist[cnt].data : callback);
}
else {
Widget submenu;
#ifndef NO_TEAROFF
if(preferences.tear_off == TRUE) {
XtSetArg(args[n], XmNtearOffModel, XmTEAR_OFF_ENABLED ); n ++;
}
#endif
sprintf(buffer,"%s_PDmenu",menulist[cnt].name);
submenu = XmCreatePulldownMenu(menu,buffer,args,n); n = 0;
if(menulist[cnt].label) {
label = XmStringCreateSimple(menulist[cnt].label);
XtSetArg(args[n], XmNlabelString, label); n ++;
}
XtSetArg(args[n], XmNsubMenuId, submenu); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
if(menulist[cnt].mnemonic) {
XtSetArg(args[n], XmNmnemonic, menulist[cnt].mnemonic); n ++;
}
if(state & menulist[cnt].statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
buttons[cnt] = XmCreateCascadeButton(menu, menulist[cnt].name, args, n);
n = 0;
menulist[cnt].widget = buttons[cnt];
if(menulist[cnt].label)
XmStringFree(label);
create_buttons(menulist[cnt].label, submenu, menulist[cnt].sub_menu,
menulist[cnt].size, state, callback, level + 1);
}
}
XtManageChildren(buttons, size);
for(cnt = 0; cnt < size; cnt ++) {
if((ML_Strstr(menulist[cnt].name,"HELP")) != NULL) {
XtSetArg(args[n],XmNmenuHelpWidget, buttons[cnt]); n ++;
XtSetValues(menu, args, n);
n = 0;
}
}
return;
}
#ifdef __STDC__
void make_buttons(ButtonList **bl, char *name, Widget menu,
Menu *menulist, int size,
unsigned long state, XtPointer callback, int level)
#else
void make_buttons(bl,name, menu, menulist, size, state, callback, level )
ButtonList **bl;
char *name;
Widget menu;
Menu *menulist;
int size;
unsigned long state;
XtPointer callback;
int level;
#endif
{
ButtonList *curr;
ButtonList *prev = NULL;
Arg args[ARGLISTSIZE];
int n = 0;
int cnt;
WidgetList buttons;
XmString label;
char buffer[256];
buttons = (WidgetList) XtMalloc(size * sizeof(Widget));
for(cnt = 0; cnt < size; cnt ++) {
curr = new_buttonlist();
if(*bl == NULL)
*bl = curr;
else {
for(prev = *bl; prev->next; prev = prev->next)
;
prev->next = curr;
}
curr->state = menulist[cnt].statemap;
if(menulist[cnt].func) {
if(menulist[cnt].label) {
label = XmStringCreateSimple(menulist[cnt].label);
XtSetArg(args[n], XmNlabelString, label); n ++;
}
XtSetArg(args[n], XmNborderWidth, 0); n ++;
if(menulist[cnt].mnemonic) {
XtSetArg(args[n], XmNmnemonic, menulist[cnt].mnemonic); n ++;
}
if(state & menulist[cnt].statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
if(level == ROOTMENULEVEL)
buttons[cnt] = XmCreateCascadeButton(menu, menulist[cnt].name,
args,n);
else
buttons[cnt] = XmCreatePushButton(menu, menulist[cnt].name, args, n);
n = 0;
menulist[cnt].widget = curr->w = buttons[cnt];
if(menulist[cnt].label)
XmStringFree(label);
XtAddCallback(buttons[cnt],XmNactivateCallback, flush_windows, NULL );
XtAddCallback(buttons[cnt],XmNactivateCallback, menulist[cnt].func,
(menulist[cnt].data) ? menulist[cnt].data : callback);
}
else {
Widget submenu;
#ifndef NO_TEAROFF
if(preferences.tear_off == TRUE) {
XtSetArg(args[n], XmNtearOffModel, XmTEAR_OFF_ENABLED ); n ++;
}
#endif
sprintf(buffer,"%s_PDmenu",menulist[cnt].name);
submenu = XmCreatePulldownMenu(menu,buffer,args,n); n = 0;
if(menulist[cnt].label) {
label = XmStringCreateSimple(menulist[cnt].label);
XtSetArg(args[n], XmNlabelString, label); n ++;
}
XtSetArg(args[n], XmNsubMenuId, submenu); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
if(menulist[cnt].mnemonic) {
XtSetArg(args[n], XmNmnemonic, menulist[cnt].mnemonic); n ++;
}
if(state & menulist[cnt].statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
buttons[cnt] = XmCreateCascadeButton(menu, menulist[cnt].name, args, n);
n = 0;
menulist[cnt].widget = curr->w = buttons[cnt];
if(menulist[cnt].label)
XmStringFree(label);
make_buttons(bl,menulist[cnt].label, submenu, menulist[cnt].sub_menu,
menulist[cnt].size, state, callback, level + 1);
}
}
XtManageChildren(buttons, size);
for(cnt = 0; cnt < size; cnt ++) {
if((ML_Strstr(menulist[cnt].name,"HELP")) != NULL) {
XtSetArg(args[n],XmNmenuHelpWidget, buttons[cnt]); n ++;
XtSetValues(menu, args, n);
n = 0;
}
}
return;
}
#ifdef __STDC__
void update_buttons(ButtonList *buttonlist, ButtonState state)
#else
void update_buttons(buttonlist, state)
ButtonList *buttonlist;
ButtonState state;
#endif
{
ButtonList *curr;
for(curr = buttonlist; curr; curr = curr->next)
if(curr->state & state)
XtVaSetValues(curr->w, XmNsensitive, FALSE, NULL);
else
XtVaSetValues(curr->w, XmNsensitive, TRUE, NULL);
return;
}
/*
* Given a top-level menu structure, and a statemap of conditions
* where the button would be insensitive, walk the entire tree of
* buttons emanating from this menu and set the state of each button.
* See buttons.h for the bitmask associations.
*/
#ifdef __STDC__
void check_buttons(Menu *menulist, int size,
Button_Menu *button_menu, unsigned long state)
#else
void check_buttons(menulist, size, button_menu, state)
Menu *menulist;
int size;
Button_Menu *button_menu;
unsigned long state;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
Button_Menu *bmenu;
int cnt;
for(cnt = 0; cnt < size; cnt ++) {
if(menulist[cnt].func) {
if(state & menulist[cnt].statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
else {
XtSetArg(args[n],XmNsensitive, TRUE); n ++;
}
XtSetValues(menulist[cnt].widget, args, n); n = 0;
}
else {
if(state & menulist[cnt].statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
else {
XtSetArg(args[n],XmNsensitive, TRUE); n ++;
}
XtSetValues(menulist[cnt].widget, args, n); n = 0;
check_buttons(menulist[cnt].sub_menu,menulist[cnt].size,
button_menu,state);
}
}
if(button_menu) {
for(bmenu = button_menu; bmenu; bmenu = bmenu->next) {
if(bmenu->label) {
if(state & bmenu->statemap) {
XtSetArg(args[n],XmNsensitive, FALSE); n ++;
}
else {
XtSetArg(args[n],XmNsensitive, TRUE); n ++;
}
XtSetValues(bmenu->widget, args, n); n = 0;
}
}
}
return;
}
syntax highlighted by Code2HTML, v. 0.9.1