I am trying to compile this excerpt of code without errors:
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/List.h>
/* FUNCTION DECLARATION */
void add_printers();
void add_printer(char *printer_name);
void add_command_groups(char *printer_name);
void read_printer_file(char *printer_name);
Widget make_menu_item(char *item_name, Widget menu);
void select_printer(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *call_data);
/* XT/XM RELATED VARIABLES */
XtAppContext context;
XmStringCharSet char_set = XmSTRING_DEFAULT_CHARSET;
/* WIDGETS */
Widget toplevel;
Widget form;
Widget printer_pulldown_menu;
Widget printer_option_menu;
Widget printer_option_item[100];
int printer_menu_items = 0;
Widget command_group_list;
Widget command_list;
int main(int argc, char *argv[]) {
Arg al[10];
int ac;
/* CREATE TOP SHELL WIDGET */
toplevel = XtAppInitialize(&context, "", NULL, 0, &argc, argv, NULL, NULL, 0);
/* RESIZE TOP LEVEL*/
ac = 0;
XtSetArg(al[ac], XmNheight, 900); ac++;
XtSetArg(al[ac], XmNwidth, 600); ac++;
XtSetValues(toplevel, al, ac);
/* CREATE FORM MANAGER WIDGET */
form = XmCreateForm(toplevel, "form", al, ac);
XtManageChild(form);
/* SELECT PRINTER PULLDOWN */
ac = 0;
XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
printer_pulldown_menu= XmCreatePulldownMenu(form, "printer_pulldown_menu", al, ac);
ac = 0;
XtSetArg(al[ac], XmNsubMenuId, printer_pulldown_menu); ac++;
XtSetArg(al[ac], XmNlabelString, XmStringCreate("Printer", char_set)); ac++;
/* SELECT PRINTER OPTIONS */
printer_option_menu = XmCreateOptionMenu(form, "printer_option_menu", al, ac);
add_printers();
XtManageChild(printer_option_menu);
/* COMMAND GROUP LIST */
ac = 0;
XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
XtSetArg(al[ac], XmNtopWidget, printer_option_menu); ac++;
XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_POSITION); ac++;
XtSetArg(al[ac], XmNbottomPosition, 50); ac++;
command_group_list = XmCreateScrolledList(form, "command_group_list", al, ac);
XtManageChild(command_group_list);
/* COMMAND LIST */
ac = 0;
XtSetArg(al[ac], XmNselectionPolicy, XmSINGLE_SELECT); ac++;
XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
XtSetArg(al[ac], XmNtopWidget, command_group_list); ac++;
XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
command_list = XmCreateScrolledList(form, "command_list", al, ac);
XtManageChild(command_list);
/* REALIZE TOPLEVEL */
XtRealizeWidget(toplevel);
XtAppMainLoop(context);
return 0;
}
/* THIS FUNCTION READS FILES UNDER /etc/xcmdprinter AND ADDS EACH PRINTER TO THE MENU */
void add_printers() {
DIR *dd;
struct dirent *entry;
dd = opendir("/etc/xcmdprinter");
while((entry = readdir(dd))!=NULL) {
/* PROCESS ONLY FILES AND SYMBOLIC LINKS */
int i = 0;
if(entry->d_type == DT_REG || entry->d_type == DT_LNK) {
/* OPEN FILE AND READ LINE BY LINE */
add_printer(entry->d_name);
}
}
closedir(dd);
}
void read_printer_file(char *printer_name) {
}
void add_printer(char *printer_name) {
if(printer_menu_items==100) {
fprintf(stderr, "ERROR: Maximum number of available printers is 100\n");
exit(1);
}
printer_option_item[printer_menu_items] = make_menu_item(printer_name, printer_pulldown_menu);
printer_menu_items++;
}
Widget make_menu_item(char *item_name, Widget menu) {
int ac;
Arg al[10];
Widget item;
ac = 0;
XtSetArg(al[ac], XmNlabelString, XmStringCreateLtoR(item_name, char_set)); ac++;
item = XmCreatePushButton(menu, item_name, al, ac);
XtManageChild(item);
XtAddCallback(item, XmNactivateCallback, select_printer, NULL);
XtSetSensitive(item, True);
return(item);
}
void select_printer(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *call_data) {
printf("BUTTON SELECTED\n");
}
void add_command_groups(char *printer_name) {
}
This is the makefile:
xcmdprinter: xcmdprinter.o
cc -std=c89 xcmdprinter.o -o xcmdprinter -L/usr/local/lib -I/usr/local/include -lXm -lXt -lX11
xcmdprinter.o: xcmdprinter.c
cc -g -std=c89 -c xcmdprinter.c -o xcmdprinter.o -I/usr/local/include
clean:
rm */*.o
rm xcmdprinter
rm *.core
However I get the following Warning when implementing the callback for the option menu item selection and I am struggling to understand why this warning is being generated and how can I fix it.
cc -g -std=c89 -c xcmdprinter.c -o xcmdprinter.o -I/usr/local/include
xcmdprinter.c:154:43: warning: incompatible pointer types passing 'void (Widget, XtPointer, XmPushButtonCallbackStruct *)' (aka 'void (struct _WidgetRec *, void *, XmPushButtonCallbackStruct *)') to parameter of
type 'XtCallbackProc' (aka 'void (*)(struct _WidgetRec *, void *, void *)') [-Wincompatible-pointer-types]
XtAddCallback(item, XmNactivateCallback, select_printer, NULL);
^~~~~~~~~~~~~~
/usr/local/include/X11/Intrinsic.h:1247:35: note: passing argument to parameter here
XtCallbackProc /* callback */,
^
1 warning generated.
The type of the last argument for select_printer
doesn't match what XtAddCallback
expected for its callback.
The select_printer
function have a XmPushButtonCallbackStruct *
argument, while the callback should have a void *
argument.
My suggested fix is to change the last argument of select_printer
to a void *
, and then inside select_printer
cast the argument to its correct type. Like:
// Prototype declaration
void select_printer(Widget w, XtPointer client_data, XtPointer *call_data);
// ...
// Function definition
void select_printer(Widget w, XtPointer client_data, XtPointer *call_data_voidp)
{
XmPushButtonCallbackStruct *call_data = (XmPushButtonCallbackStruct *) call_data_voidp;
// ...
}