diff options
Diffstat (limited to 'xmover.c')
-rw-r--r-- | xmover.c | 777 |
1 files changed, 777 insertions, 0 deletions
diff --git a/xmover.c b/xmover.c new file mode 100644 index 0000000..241f0a7 --- /dev/null +++ b/xmover.c @@ -0,0 +1,777 @@ +/* + * xmover -- X11 frontend for scsi media changers + * + * (c) 2002 Gerd Knorr <kraxel@bytesex.org> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +#include <X11/Xlib.h> +#include <X11/Intrinsic.h> +#include <X11/Xatom.h> +#include <X11/cursorfont.h> +#include <Xm/Xm.h> +#include <Xm/Form.h> +#include <Xm/Label.h> +#include <Xm/RowColumn.h> +#include <Xm/CascadeB.h> +#include <Xm/PushB.h> +#include <Xm/DrawingA.h> +#include <Xm/Protocols.h> +#include <Xm/Separator.h> +#include <Xm/Frame.h> +#include <Xm/ScrolledW.h> +#include <Xm/MessageB.h> +#include <Xm/SelectioB.h> +#include <Xm/TransferP.h> +#include <Xm/Text.h> + +#include "chio.h" + +#include "RegEdit.h" +#include "list.h" +#include "man.h" + +/* --------------------------------------------------------------------- */ + +XtAppContext app_context; + +static String fallback_ressources[] = { +#include "xmover.h" + NULL +}; + +struct ARGS { + char *device; + int help; + int debug; +} args; + +XtResource args_desc[] = { + /* name, class, type, size, offset, default_type, default_addr */ + { + /* Strings */ + "device", + XtCString, XtRString, sizeof(char*), + XtOffset(struct ARGS*,device), + XtRString, "/dev/sch0", + },{ + /* Integer */ + "help", + XtCValue, XtRInt, sizeof(int), + XtOffset(struct ARGS*,help), + XtRString, "0" + },{ + "debug", + XtCValue, XtRInt, sizeof(int), + XtOffset(struct ARGS*,debug), + XtRString, "0" + } +}; +const int args_count = XtNumber(args_desc); + +XrmOptionDescRec opt_desc[] = { + { "-c", "device", XrmoptionSepArg, NULL }, + { "-device", "device", XrmoptionSepArg, NULL }, + + { "-debug", "debug", XrmoptionNoArg, "1" }, + { "-h", "help", XrmoptionNoArg, "1" }, + { "-help", "help", XrmoptionNoArg, "1" }, + { "--help", "help", XrmoptionNoArg, "1" }, +}; +const int opt_count = (sizeof(opt_desc)/sizeof(XrmOptionDescRec)); + +/* prototypes */ +static void elem_convert(Widget, XtPointer, XtPointer); +static void elem_destination(Widget, XtPointer, XtPointer); + +/* --------------------------------------------------------------------- */ +/* atoms */ + +static Atom XA_WM_DELETE_WINDOW; + +static Atom XA_TARGETS; +static Atom _MOTIF_EXPORT_TARGETS; + +static Atom _XMOVER_TYPEUNIT; +static Atom _XMOVER_REFRESH; + +static Atom targets[2]; +static Cardinal ntargets; + +void init_atoms(Display *dpy) +{ + XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + + XA_TARGETS = XInternAtom(dpy, "TARGETS", False); + _MOTIF_EXPORT_TARGETS = XInternAtom(dpy, "_MOTIF_EXPORT_TARGETS", False); + + _XMOVER_TYPEUNIT = XInternAtom(dpy, "_XMOVER_TYPEUNIT", False); + _XMOVER_REFRESH = XInternAtom(dpy, "_XMOVER_REFRESH", False); + + targets[ntargets++] = _XMOVER_TYPEUNIT; + targets[ntargets++] = _XMOVER_REFRESH; +} + +/* ---------------------------------------------------------------------- */ +/* redirect stderr to error dialog box */ + +struct stderr_handler { + Widget box; + XmString str; + int pipe; + XtInputId id; +}; + +static void +stderr_input(XtPointer clientdata, int *src, XtInputId *id) +{ + struct stderr_handler *h = clientdata; + XmString item; + Widget label; + char buf[1024]; + int rc; + + rc = read(h->pipe,buf,sizeof(buf)-1); + if (rc <= 0) { + /* Oops */ + XtRemoveInput(h->id); + close(h->pipe); + XtDestroyWidget(h->box); + free(h); + } + buf[rc] = 0; + item = XmStringGenerate(buf, NULL, XmMULTIBYTE_TEXT,NULL); + h->str = XmStringConcatAndFree(h->str,item); + label = XmMessageBoxGetChild(h->box,XmDIALOG_MESSAGE_LABEL); + XtVaSetValues(label,XmNlabelString,h->str,NULL); + XtManageChild(h->box); +}; + +static void +stderr_ok_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + struct stderr_handler *h = clientdata; + + XmStringFree(h->str); + h->str = XmStringGenerate("", NULL, XmMULTIBYTE_TEXT,NULL); + XtUnmanageChild(h->box); +} + +static void +stderr_close_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + struct stderr_handler *h = clientdata; + + XmStringFree(h->str); + h->str = XmStringGenerate("", NULL, XmMULTIBYTE_TEXT,NULL); +} + +static void +stderr_init(Widget parent) +{ + struct stderr_handler *h; + int p[2]; + + h = malloc(sizeof(*h)); + memset(h,0,sizeof(*h)); + h->str = XmStringGenerate("", NULL, XmMULTIBYTE_TEXT,NULL); + h->box = XmCreateErrorDialog(parent,"errbox",NULL,0); + XtUnmanageChild(XmMessageBoxGetChild(h->box,XmDIALOG_HELP_BUTTON)); + XtUnmanageChild(XmMessageBoxGetChild(h->box,XmDIALOG_CANCEL_BUTTON)); + XtAddCallback(h->box,XmNokCallback,stderr_ok_cb,h); + XtAddCallback(XtParent(h->box),XmNpopdownCallback,stderr_close_cb,h); + pipe(p); + dup2(p[1],2); + close(p[1]); + h->pipe = p[0]; + h->id = XtAppAddInput(app_context,h->pipe,(XtPointer)XtInputReadMask, + stderr_input,h); +} + +/* ---------------------------------------------------------------------- */ +/* pointer games */ + +struct ptr_list { + struct list_head list; + Widget widget; +}; +static struct list_head ptr_wins; +static Cursor ptr_idle; +static Cursor ptr_busy; + +void ptr_register(Widget widget) +{ + struct ptr_list *item; + + if (XtWindow(widget)) + XDefineCursor(XtDisplay(widget), XtWindow(widget),ptr_idle); + item = malloc(sizeof(*item)); + memset(item,0,sizeof(*item)); + item->widget = widget; + list_add_tail(&item->list,&ptr_wins); +} + +void ptr_unregister(Widget widget) +{ + struct list_head *item; + struct ptr_list *win,*del; + + del = NULL; + list_for_each(item,&ptr_wins) { + win = list_entry(item, struct ptr_list, list); + if (win->widget == widget) + del = win; + } + if (del) + list_del(&del->list); +} + +void ptr_set(Cursor ptr) +{ + struct list_head *item; + struct ptr_list *win; + Display *dpy = NULL; + + list_for_each(item,&ptr_wins) { + win = list_entry(item, struct ptr_list, list); + if (!XtWindow(win->widget)) + continue; + dpy = XtDisplay(win->widget); + XDefineCursor(dpy, XtWindow(win->widget),ptr); + } + if (dpy) + XSync(dpy,False); +} + +void ptr_init(Widget shell) +{ + XColor white,red,dummy; + Colormap cmap = DefaultColormapOfScreen(XtScreen(shell)); + + INIT_LIST_HEAD(&ptr_wins); + ptr_idle = XCreateFontCursor(XtDisplay(shell),XC_left_ptr); + ptr_busy = XCreateFontCursor(XtDisplay(shell),XC_watch); + if (XAllocNamedColor(XtDisplay(shell),cmap,"white",&white,&dummy) && + XAllocNamedColor(XtDisplay(shell),cmap,"red",&red,&dummy)) { + XRecolorCursor(XtDisplay(shell),ptr_idle,&red,&white); + XRecolorCursor(XtDisplay(shell),ptr_busy,&red,&white); + } +} + +/* --------------------------------------------------------------------- */ +/* handle changer elements */ + +struct changer_elem { + struct list_head list; + int type; + int unit; + Widget draw,label; + Widget menu,mref,mtag,msrc; + struct changer_get_element info; +}; + +static int fd; +static struct changer_params params; +static struct list_head elems; + +static struct changer_elem* +elem_by_typeunit(int type, int unit) +{ + struct list_head *item; + struct changer_elem *elem; + + list_for_each(item,&elems) { + elem = list_entry(item, struct changer_elem, list); + if (elem->type == type && + elem->unit == unit) + return elem; + } + return NULL; +} + +static void update_elem(struct changer_elem *elem) +{ + XmString item,str = NULL; + char buf[64]; + int err; + + /* query */ + elem->info.cge_type = elem->type; + elem->info.cge_unit = elem->unit; + err = ioctl(fd,CHIOGELEM,&elem->info); + if (-1 == err) { + fprintf(stderr,"CHIOGELEM(%d/%d): %s\n", + elem->type,elem->unit,strerror(errno)); + } + + /* build XmString */ + sprintf(buf,"#%03d",elem->unit); + item = XmStringGenerate(buf,NULL,XmMULTIBYTE_TEXT,NULL); + str = XmStringConcatAndFree(str,item); + if (elem->info.cge_flags & CGE_PVOLTAG) { + sprintf(buf," [%-32.32s]",elem->info.cge_pvoltag); + item = XmStringGenerate(buf,NULL,XmMULTIBYTE_TEXT,"voltag"); + str = XmStringConcatAndFree(str,item); + } + if (elem->info.cge_status & CESTATUS_FULL) { + item = XmStringGenerate(" full",NULL,XmMULTIBYTE_TEXT,"full"); + str = XmStringConcatAndFree(str,item); + } + if (elem->info.cge_status & CESTATUS_EXCEPT) { + item = XmStringGenerate(" error",NULL,XmMULTIBYTE_TEXT,"error"); + str = XmStringConcatAndFree(str,item); + } + + /* commit */ + XtVaSetValues(elem->label,XmNlabelString,str,NULL); + XmStringFree(str); +} + +static void +elem_tag_done_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + XmSelectionBoxCallbackStruct *cd = call_data; + struct changer_elem *elem = clientdata; + Widget text; + char *str; + + if (args.debug) + fprintf(stderr,"elem_tag_done_cb\n"); + if (cd->reason == XmCR_OK) { + struct changer_set_voltag tag; + text = XmSelectionBoxGetChild(widget,XmDIALOG_TEXT); + str = XmTextGetString(text); + memset(&tag,0,sizeof(tag)); + tag.csv_type = elem->type; + tag.csv_unit = elem->unit; + tag.csv_flags = CSV_PVOLTAG; + if (strlen(str) > 0) + strncpy(tag.csv_voltag,str,32); + else + tag.csv_flags |= CSV_CLEARTAG; + ptr_set(ptr_busy); + if (-1 == ioctl(fd,CHIOSVOLTAG,&tag)) + perror("CHIOSVOLTAG"); + update_elem(elem); + ptr_set(ptr_idle); + } + XtDestroyWidget(XtParent(widget)); +} + +static void +elem_tag_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + struct changer_elem *elem = clientdata; + Widget box,text; + + if (args.debug) + fprintf(stderr,"elem_tag_cb\n"); + box = XmCreatePromptDialog(elem->draw,"tag",NULL,0); + text = XmSelectionBoxGetChild(box,XmDIALOG_TEXT); + if (elem->info.cge_flags & CGE_PVOLTAG) + XmTextSetString(text,elem->info.cge_pvoltag); + + XtAddCallback(box,XmNokCallback,elem_tag_done_cb,elem); + XtAddCallback(box,XmNcancelCallback,elem_tag_done_cb,elem); + XmdRegisterEditres(XtParent(box)); + XtManageChild(box); +} + +static void +elem_src_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + struct changer_elem *elem = clientdata; + struct changer_elem *src; + struct changer_move move; + + if (args.debug) + fprintf(stderr,"elem_src_cb\n"); + src = elem_by_typeunit(elem->info.cge_srctype,elem->info.cge_srcunit); + memset(&move,0,sizeof(move)); + move.cm_fromtype = elem->type; + move.cm_fromunit = elem->unit; + move.cm_totype = elem->info.cge_srctype; + move.cm_tounit = elem->info.cge_srcunit; + ptr_set(ptr_busy); + if (-1 == ioctl(fd,CHIOMOVE,&move)) + perror("CHIOMOVE"); + update_elem(elem); + update_elem(src); + ptr_set(ptr_idle); +} + +static void +elem_refresh_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + struct changer_elem *elem = clientdata; + + ptr_set(ptr_busy); + update_elem(elem); + ptr_set(ptr_idle); +} + +static void +elem_menu_eh(Widget widget, XtPointer clientdata, XEvent *event, Boolean *cont) +{ + struct changer_elem *elem = clientdata; + Boolean tag,src; + + if (args.debug) + fprintf(stderr,"elem_menu_eh\n"); + tag = (elem->info.cge_status & CESTATUS_FULL) ? True : False; + XtVaSetValues(elem->mtag,XmNsensitive,tag,NULL); + if (elem->msrc) { + src = (elem->info.cge_status & CESTATUS_FULL) && + (elem->info.cge_flags & CGE_SRC); + XtVaSetValues(elem->msrc,XmNsensitive,src,NULL); + } + XmMenuPosition(elem->menu,(XButtonPressedEvent*)event); + XtManageChild(elem->menu); +} + +static struct changer_elem* +add_elem(Widget parent, int type, int unit) +{ + struct changer_elem *elem; + Cardinal n = 0; + Arg args[4]; + char name[32]; + + elem = malloc(sizeof(*elem)); + memset(elem,0,sizeof(*elem)); + sprintf(name,"%d/%d",type,unit); + elem->type = type; + elem->unit = unit; + elem->draw = XtVaCreateManagedWidget("d",xmDrawingAreaWidgetClass,parent, + NULL); + elem->label = XtVaCreateManagedWidget(name,xmLabelWidgetClass,elem->draw, + NULL); + update_elem(elem); + + /* dnd */ + XtAddCallback(elem->label,XmNconvertCallback,elem_convert,elem); + XtAddCallback(elem->draw,XmNdestinationCallback,elem_destination,elem); + XtSetArg(args[n], XmNimportTargets, targets); n++; + XtSetArg(args[n], XmNnumImportTargets, ntargets); n++; + XmeDropSink(elem->draw,args,n); + + /* context menu */ + elem->menu = XmCreatePopupMenu(elem->draw,"menu",NULL,0); + XtAddEventHandler(elem->draw,ButtonPressMask,False,elem_menu_eh,elem); + elem->mref = XtVaCreateManagedWidget("ref",xmPushButtonWidgetClass, + elem->menu,NULL); + XtAddCallback(elem->mref,XmNactivateCallback,elem_refresh_cb,elem); + elem->mtag = XtVaCreateManagedWidget("tag",xmPushButtonWidgetClass, + elem->menu,NULL); + XtAddCallback(elem->mtag,XmNactivateCallback,elem_tag_cb,elem); + if (elem->type == CHET_DT) { + elem->msrc = XtVaCreateManagedWidget("src",xmPushButtonWidgetClass, + elem->menu,NULL); + XtAddCallback(elem->msrc,XmNactivateCallback,elem_src_cb,elem); + } + + list_add_tail(&elem->list,&elems); + return elem; +} + +/* --------------------------------------------------------------------- */ +/* drag'n'drop stuff */ + +static void +elem_convert(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + XmConvertCallbackStruct *ccs = call_data; + struct changer_elem *elem = clientdata; + unsigned long *largs; + char *name; + Atom *targs; + int n; + + if (args.debug) { + name = XGetAtomName(XtDisplay(widget),ccs->target); + fprintf(stderr,"elem_convert %s\n",name); + XFree(name); + } + + if ((ccs->target == XA_TARGETS) || + (ccs->target == _MOTIF_EXPORT_TARGETS)) { + targs = (Atom*)XtMalloc(sizeof(Atom)*8); + n = 0; + targs[n++] = _XMOVER_TYPEUNIT; + targs[n++] = _XMOVER_REFRESH; + ccs->value = targs; + ccs->length = n; + ccs->type = XA_ATOM; + ccs->format = 32; + ccs->status = XmCONVERT_MERGE; + } + if (ccs->target == _XMOVER_TYPEUNIT) { + largs = (unsigned long*)XtMalloc(sizeof(*largs)); + largs[0] = (elem->type << 16) | elem->unit; + ccs->value = largs; + ccs->length = 1; + ccs->type = XA_INTEGER; + ccs->format = 32; + ccs->status = XmCONVERT_DONE; + } + if (ccs->target == _XMOVER_REFRESH) { + ptr_set(ptr_busy); + update_elem(elem); + ptr_set(ptr_idle); + ccs->value = NULL; + ccs->length = 0; + ccs->type = XA_INTEGER; + ccs->format = 32; + ccs->status = XmCONVERT_DONE; + } +} + +static void +elem_transfer(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + XmSelectionCallbackStruct *scs = call_data; + struct changer_elem *elem = clientdata; + unsigned long *ldata = scs->value; + XmTransferStatus status = XmTRANSFER_DONE_SUCCEED; + Time time = XtLastTimestampProcessed(XtDisplay(widget)); + int pending,i; + char *name; + + if (args.debug) { + name = XGetAtomName(XtDisplay(widget),scs->target); + fprintf(stderr,"elem_transfer %s\n",name); + XFree(name); + } + + pending = scs->remaining; + if (scs->target == XA_TARGETS) { + for (i = 0; i < scs->length; i++) { + if (ldata[i] == _XMOVER_TYPEUNIT) { + XmTransferValue(scs->transfer_id, ldata[i], elem_transfer, + elem, time); + pending++; + } + } + if (pending == scs->remaining) { + /* no target found */ + status = XmTRANSFER_DONE_FAIL; + } + } + if (scs->target == _XMOVER_TYPEUNIT) { + struct changer_move move; + + if (args.debug) + fprintf(stderr,"move: %ld/%ld => %d/%d\n", + ldata[0] >> 16, ldata[0] & 0xffff, + elem->type, elem->unit); + memset(&move,0,sizeof(move)); + move.cm_fromtype = ldata[0] >> 16; + move.cm_fromunit = ldata[0] & 0xffff; + move.cm_totype = elem->type; + move.cm_tounit = elem->unit; + ptr_set(ptr_busy); + if (move.cm_fromtype != move.cm_totype || + move.cm_fromunit != move.cm_tounit) + if (-1 == ioctl(fd,CHIOMOVE,&move)) + perror("CHIOMOVE"); + update_elem(elem); + ptr_set(ptr_idle); + XmTransferValue(scs->transfer_id, _XMOVER_REFRESH, elem_transfer, + elem, time); + pending++; + } + XFree(scs->value); + if (1 == pending) + XmTransferDone(scs->transfer_id, status); +} + +static void +elem_destination(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + XmDestinationCallbackStruct *dcs = call_data; + struct changer_elem *elem = clientdata; + Time time = XtLastTimestampProcessed(XtDisplay(widget)); + + if (args.debug) + fprintf(stderr,"elem_destination\n"); + XmTransferValue(dcs->transfer_id, XA_TARGETS, elem_transfer, elem, time); +} + +/* --------------------------------------------------------------------- */ +/* gui + basic callbacks */ + +void +destroy_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + XtDestroyWidget(clientdata); +} + +static void +about_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + Widget msgbox; + + msgbox = XmCreateInformationDialog(widget,"aboutbox",NULL,0); + XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_HELP_BUTTON)); + XtUnmanageChild(XmMessageBoxGetChild(msgbox,XmDIALOG_CANCEL_BUTTON)); + XtAddCallback(msgbox,XmNokCallback,destroy_cb,msgbox); + XtManageChild(msgbox); +} + +static void +close_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + Widget shell = clientdata; + XtDestroyWidget(shell); + exit(0); +} + +static void +refresh_cb(Widget widget, XtPointer clientdata, XtPointer call_data) +{ + struct list_head *item; + struct changer_elem *elem; + + ptr_set(ptr_busy); + list_for_each(item,&elems) { + elem = list_entry(item, struct changer_elem, list); + update_elem(elem); + } + ptr_set(ptr_idle); +} + +static void create_widgets(Widget shell) +{ + Widget form,menubar,menu,push,frame,scroll,rowcol; + int i; + + /* shell stuff */ + XmdRegisterEditres(shell); + XmAddWMProtocolCallback(shell,XA_WM_DELETE_WINDOW,close_cb,shell); + + /* form container */ + form = XtVaCreateManagedWidget("form", xmFormWidgetClass, shell, + NULL); + + /* menu- & toolbar */ + menubar = XmCreateMenuBar(form,"bar",NULL,0); + XtManageChild(menubar); + + /* menu -- file */ + menu = XmCreatePulldownMenu(menubar,"fileM",NULL,0); + XtVaCreateManagedWidget("file",xmCascadeButtonWidgetClass,menubar, + XmNsubMenuId,menu,NULL); + push = XtVaCreateManagedWidget("quit",xmPushButtonWidgetClass,menu,NULL); + XtAddCallback(push,XmNactivateCallback,close_cb,shell); + + /* menu -- changer */ + menu = XmCreatePulldownMenu(menubar,"changerM",NULL,0); + XtVaCreateManagedWidget("changer",xmCascadeButtonWidgetClass,menubar, + XmNsubMenuId,menu,NULL); + push = XtVaCreateManagedWidget("refresh",xmPushButtonWidgetClass,menu,NULL); + XtAddCallback(push,XmNactivateCallback,refresh_cb,NULL); + + /* menu - help */ + menu = XmCreatePulldownMenu(menubar,"helpM",NULL,0); + push = XtVaCreateManagedWidget("help",xmCascadeButtonWidgetClass,menubar, + XmNsubMenuId,menu,NULL); + XtVaSetValues(menubar,XmNmenuHelpWidget,push,NULL); + push = XtVaCreateManagedWidget("man",xmPushButtonWidgetClass,menu,NULL); + XtAddCallback(push,XmNactivateCallback,man_cb,"xmover"); + XtVaCreateManagedWidget("sep",xmSeparatorWidgetClass,menu,NULL); + push = XtVaCreateManagedWidget("about",xmPushButtonWidgetClass,menu,NULL); + XtAddCallback(push,XmNactivateCallback,about_cb,NULL); + + /* ie elems */ + frame = XtVaCreateManagedWidget("ie", xmFrameWidgetClass, form, NULL); + XtVaCreateManagedWidget("label",xmLabelWidgetClass,frame,NULL); + rowcol = XtVaCreateManagedWidget("rc",xmRowColumnWidgetClass, + frame,NULL); + for (i = 0; i < params.cp_nportals; i++) + add_elem(rowcol, CHET_IE, i); + + /* dt elems */ + frame = XtVaCreateManagedWidget("dt", xmFrameWidgetClass, form, NULL); + XtVaCreateManagedWidget("label",xmLabelWidgetClass,frame,NULL); + rowcol = XtVaCreateManagedWidget("rc",xmRowColumnWidgetClass, + frame,NULL); + for (i = 0; i < params.cp_ndrives; i++) + add_elem(rowcol, CHET_DT, i); + + /* st elems */ + frame = XtVaCreateManagedWidget("st", xmFrameWidgetClass, form, NULL); + XtVaCreateManagedWidget("label",xmLabelWidgetClass,frame,NULL); + scroll = XmCreateScrolledWindow(frame,"scroll",NULL,0); + XtManageChild(scroll); + rowcol = XtVaCreateManagedWidget("rc",xmRowColumnWidgetClass, + scroll,NULL); + for (i = 0; i < params.cp_nslots; i++) + add_elem(rowcol, CHET_ST, i); +} + +/* --------------------------------------------------------------------- */ +/* main */ + +static void usage(void) +{ + fprintf(stderr, + "xmover -- X11 frontend for scsi media changers\n" + "options:\n" + " -debug enable debug messages\n" + " -device <dev> use <dev> instead of /dev/sch0\n"); +} + +int +main(int argc, char *argv[]) +{ + Widget app_shell; + int err; + + /* init X11 */ + XtSetLanguageProc(NULL,NULL,NULL); + app_shell = XtVaAppInitialize(&app_context, "xmover", + opt_desc, opt_count, + &argc, argv, + fallback_ressources, + NULL); + XtGetApplicationResources(app_shell,&args, + args_desc,args_count, + NULL,0); + if (args.help) { + usage(); + exit(1); + } + + /* init changer */ + fd = open(args.device,O_RDONLY); + if (-1 == fd) { + fprintf(stderr,"open %s: %s\n",args.device,strerror(errno)); + exit(1); + } + err = ioctl(fd,CHIOGPARAMS,¶ms); + if (-1 == err) { + perror("CHIOGPARAMS"); + exit(1); + } + INIT_LIST_HEAD(&elems); + + init_atoms(XtDisplay(app_shell)); + if (!args.debug) + stderr_init(app_shell); + ptr_init(app_shell); + ptr_register(app_shell); + create_widgets(app_shell); + + XtRealizeWidget(app_shell); + XtAppMainLoop(app_context); + return 0; +} |