/* ************************************************************************* Module: lexgui.c Author: Matt Simpson Arlington, TX matthewsimpson@home.com Date: August, 2000 Description: Main for pup (Printer Utility Program), a GTK+ GUI program for managing printer settings. Currently it supports the following printers: Lexmark Optra Color 40/45 Lexmark Optra E310 HP 2100M HP 4000 HP LJ4 Plus Other PJL printers ...with the following tasks: Printer cartridge setup and maintainance (Optra 40/45 only). Generating and printing test pages. Querying of printer defaults. Querying of printer status. Setting of printer defaults. **************************************************************************** COPYRIGHT (C) 1999, 2000 Matt Simpson The start of pup's COPYRIGHT occurred with the initial release of pup, version 1.0, in August, 1999. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Lexmark and Optra are trademarks of Lexmark International, Inc. ***************************************************************************** Contributors: See README file accompanying Pup. **************************************************************************** */ #include #include #include #include #include /* for struct utsname and uname() */ #include "lexgui.h" /* Globals */ gchar *output; /* current output */ FILE *fp = NULL; int devtype; int open_file_errno; /* stores the extern int errno from errno.h */ /* ------------------------------------------------------------------------- get_uinfo() Gets info about computer ------------------------------------------------------------------------- */ char *get_uinfo(gint u) { static gint init = 0; static gint uflag = 0; static struct utsname unameinfo; gchar *ret_ptr; if(!init) { init = 1; if(uname(&unameinfo) >= 0) uflag = 1; } if(uflag) { switch (u) { case USYSNAME: ret_ptr = unameinfo.sysname; break; case UNODENAME: ret_ptr = unameinfo.nodename; break; case URELEASE: ret_ptr = unameinfo.release; break; case UVERSION: ret_ptr = unameinfo.version; break; case UMACHINE: ret_ptr = unameinfo.machine; break; default: ret_ptr = NULL; } } else ret_ptr = NULL; return(ret_ptr); } /* ------------------------------------------------------------------------- get_default_dev() Gets default output device, which is used if $HOME/.puprc does not exist. ------------------------------------------------------------------------- */ char *get_default_dev(void) { char *sysname, *machine; char *ret_ptr = NULL; /* -------------------------------------------- This info is not complete. You: Please help me correct or add the default output device for your machine and your OS. -------------------------------------------- */ static char X86_LINUX[] = "/dev/lp0"; static char X86_SOLARIS[] = "/dev/lp1"; static char FREEBSD[] = "/dev/lpt0"; static char ALPHA_LINUX[] = "/dev/lp0"; static char ALPHA_DUNIX[] = "/dev/lp0"; static char SPARC_LINUX[] = "/dev/lp0"; /* static char SPARC_SOLARIS_OLD[] = "/dev/bpp0";*/ static char SPARC_SOLARIS_NEW[] = "/dev/ecpp0"; static char HPUX[] = "/dev/lpi0"; static char MIPS_IRIX[] = "/dev/plp"; /* -------------------------------------------- */ sysname = get_uinfo(USYSNAME); machine = get_uinfo(UMACHINE); if(sysname == NULL || machine == NULL) { ret_ptr = X86_LINUX; return(ret_ptr); } /* ----- x86 or FreeBSD ----- */ if(strstr(machine, "i386") || strstr(machine, "i486") || strstr(machine, "i586") || strstr(machine, "i686") || strstr(machine, "x86")) { if(!strcasecmp(sysname, "Linux")) ret_ptr = X86_LINUX; else if(!strcasecmp(sysname, "Solaris")) ret_ptr = X86_SOLARIS; else if(!strcasecmp(sysname, "FreeBSD")) ret_ptr = FREEBSD; } /* ----- Alpha ----- */ else if(strstr(machine, "Alpha") || strstr(machine, "alpha")) { if(!strcasecmp(sysname, "Linux")) ret_ptr = ALPHA_LINUX; else if(strstr(sysname, "OSF")) ret_ptr = ALPHA_DUNIX; } /* ----- Sparc ----- */ else if(strstr(machine, "Sparc") || strstr(machine, "SPARC") || strstr(machine, "sun4u")) { if(!strcasecmp(sysname, "Linux")) ret_ptr = SPARC_LINUX; if(!strcasecmp(sysname, "SunOS")) ret_ptr = SPARC_SOLARIS_NEW; else if(!strcasecmp(sysname, "Solaris")) ret_ptr = SPARC_SOLARIS_NEW; } /* ---- HP-UX ---- */ else if(strstr(machine, "9000")) { if(!strcasecmp(sysname, "HP-UX")) ret_ptr = HPUX; } /* ----- SGI ----- */ else if(strstr(machine, "IP")) { if(strstr(sysname, "IRIX")) ret_ptr = MIPS_IRIX; } if(ret_ptr == NULL) ret_ptr = X86_LINUX; return(ret_ptr); } /* ------------------------------------------------------------------------- deleteW() For the delete signal (when the X is pressed) Note the deleteW() and destroyW() functions are events rather than callbacks. These have one extra parameter, the event (listed as 'GdkEventAny *gevent' below). See 2.4 of the GTK tutorial. See 2.3 for callbacks. For callbacks, the parameters are (GtkWidget *widget, gpointer data), and for events, the parameters are (GtkWidget *widget, GdkEventAny *gevent, gpointer data). The data is your own data, passed as the last argument in the gtk_signal_connect call. It is of type gpointer, which is void *, so to use it you must cast it. Events are also used for the "X" destroy window button (upper right hand corner of the window) on all child popup windows. These functions are designated with an X in the name of the function; the close button callbacks on these windows have the same function name but without the X. ------------------------------------------------------------------------- */ gint deleteW(GtkWidget *widget, GdkEventAny *gevent, gpointer data) { /* Returning FALSE will automatically destroy the window; additionally, since the top master window also has a callback for the destroy event, it goes to destroyW to quit the program. */ return(FALSE); } /* ------------------------------------------------------------------------- destroyW() For quitting pup. ------------------------------------------------------------------------- */ void destroyW(GtkWidget *widget, GdkEventAny *gevent, gpointer gdata) { extern FILE *fp; extern int devtype; if(fp) { if(devtype == 2) pclose(fp); else fclose(fp); fp = NULL; } g_print("(c)%s Matt Simpson\n", CURYEAR); g_print("Thank You.\n"); gtk_main_quit(); } /* ------------------------------------------------------------------------- cleanTaskWin() Cleans up a task window for deletion. ------------------------------------------------------------------------- */ void cleanTaskWin(task_struct *task) { /* Clear possible timer in task window. For future reference, note task->msgbox and (task->top)->msgbox are two different things. */ if(task->msgbox.timer) { gtk_timeout_remove(task->msgbox.timer); task->msgbox.timer = 0; } if(task->top)/*Clear top message field & sensitize entry, toptable, & pref */ reset_top(task->top, 1); if(GTK_IS_WIDGET(task->dialog)) { gtk_widget_destroy(task->dialog); task->dialog = NULL; } if(GTK_IS_WIDGET(task->msgbox.explain_dialog)) { gtk_widget_destroy(task->msgbox.explain_dialog); task->msgbox.explain_dialog = NULL; } } /* ------------------------------------------------------------------------- deleteTWX() Delete task window with the X. ------------------------------------------------------------------------- */ gint deleteTWX(GtkWidget *widget, GdkEventAny *gevent, task_struct *task) { cleanTaskWin(task); /* Returning FALSE will automatically destroy the window task->tasktop */ return(FALSE); } /* ------------------------------------------------------------------------- deleteTW() Delete task window with the close button. ------------------------------------------------------------------------- */ void deleteTW(GtkWidget *widget, task_struct *task) { cleanTaskWin(task); gtk_widget_destroy(GTK_WIDGET(task->tasktop)); task->tasktop = NULL; } /* ------------------------------------------------------------------------- close_iwindowX() Delete an info, about, or explain_dialog window with the X. Note deleteTWX(), deleteTW(), deleteDCX(), deleteDC(), deleteSTWX(), and deleteSTW() are used to delete task, non-infowin scrolled windows, and text windows; these functions also delete the child popup info windows they called (explain_dialog, dialog created in pop_set_note(), etc) if they exist, as well as resets the top message box. Conversely, close_iwindowX(), close_iwindow(), rswinX(), and rswin() are used for the X and close buttons within the info windows themselves (i.e. the top message box is not reset and there's no child popups to delete). ------------------------------------------------------------------------- */ gint close_iwindowX(GtkWidget *widget, GdkEventAny *gevent, GtkWidget **win) { /* Returning FALSE automatically destroys the window; since we return TRUE we don't destroy it, because we want to destroy it manually in order to set the pointer to NULL so the GTK_IS_WIDGET test will work next time one of these is called up. */ /* destroy the window or dialog manually */ gtk_widget_destroy(GTK_WIDGET(*win)); *win = NULL; /* Since we already destroyed it, return TRUE */ return(TRUE); } /* ------------------------------------------------------------------------- close_iwindow() Delete an info, about, or explain_dialog window. ------------------------------------------------------------------------- */ void close_iwindow(GtkWidget *widget, GtkWidget **win) { gtk_widget_destroy(GTK_WIDGET(*win)); *win = NULL; } /* ------------------------------------------------------------------------- make_menu() ------------------------------------------------------------------------- */ void make_menu(topwin_struct *top) { GtkTooltips *tooltips; GtkWidget *menubar, *menu_items, *menuF, *menuH, *file_menu, *help_menu; GtkAccelGroup *accel_group, *menuF_accels, *menuH_accels; guint akey; tooltips = gtk_tooltips_new(); set_tool_color(&tooltips); accel_group = gtk_accel_group_new (); gtk_accel_group_attach (accel_group, GTK_OBJECT (top->topwindow)); /* ========== Manual Menu ========== */ /* Menu Bar Container */ menubar = gtk_menu_bar_new (); gtk_box_pack_start(GTK_BOX(top->vbox_top), menubar, FALSE, TRUE, 0); gtk_widget_show(menubar); /* init the menu widgets -- don't widget_show */ menuF = gtk_menu_new(); /* Stuff under File menu */ menuH = gtk_menu_new(); /* Stuff under Help menu */ /* ----- File Menu ----- */ file_menu = gtk_menu_item_new_with_label (""); akey = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(file_menu)->child), ("_File")); gtk_widget_add_accelerator (file_menu, "activate_item", accel_group, akey, GDK_MOD1_MASK, (GtkAccelFlags)0); gtk_widget_show (file_menu); menuF_accels = gtk_menu_ensure_uline_accel_group(GTK_MENU (menuF)); gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_menu), menuF); /* Preferences Menu -- under File */ top->prefmenu = gtk_menu_item_new_with_label(""); akey = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(top->prefmenu)->child), ("_Preferences")); gtk_widget_add_accelerator(top->prefmenu, "activate_item", menuF_accels, akey, 0, (GtkAccelFlags)0); gtk_menu_append (GTK_MENU (menuF), top->prefmenu); gtk_signal_connect_object (GTK_OBJECT (top->prefmenu), "activate", GTK_SIGNAL_FUNC (pref_event), (gpointer)top); gtk_tooltips_set_tip(tooltips, top->prefmenu, "Set Pup Defaults", NULL); gtk_widget_show(top->prefmenu); /* Quit Menu -- under File */ menu_items = gtk_menu_item_new_with_label(""); akey = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(menu_items)->child),("_Quit")); gtk_widget_add_accelerator(menu_items, "activate_item", menuF_accels, akey, 0, (GtkAccelFlags)0); gtk_menu_append (GTK_MENU (menuF), menu_items); gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate", GTK_SIGNAL_FUNC (destroyW), NULL); gtk_tooltips_set_tip(tooltips, menu_items, "Good Bye", NULL); gtk_widget_show (menu_items); /* ----- Help Menu ----- */ help_menu = gtk_menu_item_new_with_label(""); akey = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(help_menu)->child), ("_Help")); gtk_widget_add_accelerator (help_menu, "activate_item", accel_group, akey, GDK_MOD1_MASK, (GtkAccelFlags)0); gtk_widget_show (help_menu); gtk_menu_item_right_justify(GTK_MENU_ITEM (help_menu)); menuH_accels = gtk_menu_ensure_uline_accel_group(GTK_MENU (menuH)); gtk_menu_item_set_submenu (GTK_MENU_ITEM (help_menu), menuH); /* Info menu -- under Help */ menu_items = gtk_menu_item_new_with_label(""); akey = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(menu_items)->child),("_Info")); gtk_widget_add_accelerator(menu_items, "activate_item", menuH_accels, akey, 0, (GtkAccelFlags)0); gtk_menu_append (GTK_MENU (menuH), menu_items); gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate", GTK_SIGNAL_FUNC (infow_event), (gpointer)top); gtk_tooltips_set_tip(tooltips, menu_items, "More info on choices", NULL); gtk_widget_show (menu_items); /* About menu -- under Help */ menu_items = gtk_menu_item_new_with_label(""); akey = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(menu_items)->child), ("_About")); gtk_widget_add_accelerator(menu_items, "activate_item", menuH_accels, akey, 0, (GtkAccelFlags)0); gtk_menu_append (GTK_MENU (menuH), menu_items); gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate", GTK_SIGNAL_FUNC (about_event), (gpointer)top); gtk_tooltips_set_tip(tooltips, menu_items, "Show Credits", NULL); gtk_widget_show (menu_items); gtk_menu_bar_append (GTK_MENU_BAR (menubar), file_menu); gtk_menu_bar_append (GTK_MENU_BAR (menubar), help_menu); } /* ------------------------------------------------------------------------- put_title() ------------------------------------------------------------------------- */ void put_title(GtkWidget **vbox) { GtkWidget *label; label = gtk_label_new(""); set_font(&label, 4); set_color(&label, RED, FG, NORMAL); gtk_label_set_text(GTK_LABEL(label), "Printer Utility Program"); gtk_box_pack_start(GTK_BOX(*vbox), label, FALSE, FALSE, 0); gtk_widget_show(label); label = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(*vbox), label, FALSE, FALSE, 0); gtk_widget_show(label); } /* ------------------------------------------------------------------------- init_msgbox() Initializes message box. ------------------------------------------------------------------------- */ void init_msgbox(msgbox_struct *msgbox) { msgbox->msglabel = NULL; msgbox->expbutton = NULL; msgbox->h_msgbox = NULL; msgbox->explain_dialog = NULL; msgbox->explain = 0; msgbox->freeze = 0; msgbox->timer = 0; msgbox->timecount = 0; } /* ------------------------------------------------------------------------- init_inhibit() Sets all inhibit flags to 0. ------------------------------------------------------------------------- */ void init_inhibit(prefs_struct *prefs) { gint i; for(i = 0; i < NUMPAGE; i++) prefs->t_inhibit[i] = 0; for(i = 0; i < NUMBUT; i++) prefs->b_inhibit[i] = 0; } /* ------------------------------------------------------------------------- init_prefs() Initializes a pref_struct ------------------------------------------------------------------------- */ void init_prefs(prefs_struct *prefs) { strcpy(prefs->outfile, get_default_dev()); init_printer_name(prefs); prefs->index = 0; prefs->family = 0; init_inhibit(prefs); } /* ------------------------------------------------------------------------- init_top() Initializes top window stuff not immediately defined by main(). ------------------------------------------------------------------------- */ void init_top(topwin_struct *top) { int i; top->prefmenu = NULL; top->entry = NULL; top->printerlabel = NULL; top->notebook = NULL; top->activebut = 0; top->entry_state = 0; top->infowin.topwin = NULL; top->aboutwin = NULL; init_msgbox(&(top->msgbox)); init_prefs(&(top->prefs)); top->pflag = 0; for(i = 0; i < NUMPAGE; i++) { top->bt.vbox[i] = NULL; top->bt.table[i] = NULL; } for(i = 0; i < NUMBUT; i++) { top->bt.button[i] = NULL; top->bt.blabel[i] = NULL; } } /* ------------------------------------------------------------------------- init_task() Initializes task window stuff. ------------------------------------------------------------------------- */ void init_task(topwin_struct *top, task_struct *task) { task->top = top; task->dialog = NULL; init_msgbox(&(task->msgbox)); } /* ------------------------------------------------------------------------- init_io() Initializes io_struct. ------------------------------------------------------------------------- */ void init_io(io_struct *io, int btdt) { int i; init_msgbox(&(io->msgbox)); for(i = 0; i < NUMCLOCKS; i++) io->clock[i] = 0; io->fd = 0; io->count = 0; io->start_read = 0; io->terminate = 0; io->j = 0; io->timeout_count = 0; io->busy = 0; if(!btdt) /* btdt = Been There Done That */ { io->qlength = 0; io->query = NULL; } io->command = 0; io->aj_ptr = NULL; io->dc_ptr = NULL; } /* ------------------------------------------------------------------------- init_texwin() Initializes scrolled text query window. ------------------------------------------------------------------------- */ void init_texwin(topwin_struct *top, tx_struct *tw, gint btdt) { tw->top = top; init_io(&(tw->io), btdt); } /* ------------------------------------------------------------------------- init_dc() Initializes scrolled dynamic choices window. ------------------------------------------------------------------------- */ void init_dc(topwin_struct *top, dc_struct *dc, gint btdt) { dc->top = top; dc->sw.topwin = NULL; /* make_sc_win() must be called on dc.sw after returning */ dc->dc_vbox = NULL; dc->ac_button = NULL; dc->fc_button = NULL; dc->rf_button = NULL; dc->gcount = 0; if(!btdt) { dc->gcount = 0; dc->gr_alloc_count = 0; dc->gr = NULL; /* need to malloc this when used */ } dc->msgbox_ptr = NULL; dc->dialog = NULL; dc->help.topwin = NULL; /* make_sc_win() must be called before using dc.help */ dc->fp = NULL; dc->numtochange = 0; dc->numchanged = 0; dc->ad_count = 0; dc->fixq = 0; dc->fixinit = 0; } /* ------------------------------------------------------------------------- ------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { char windowtitle[50] = TITLE; topwin_struct top; GtkWidget *lbox; GtkWidget *pixmaplogo; GtkStyle *defstyle, *newstyle; GdkFont *dfont; gchar *default_font = "-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1"; gtk_init(&argc, &argv); output = (gchar *) malloc(MAXLINELENGTH * sizeof(gchar)); strcpy(output, get_default_dev()); /* Set the default colors and font */ defstyle = gtk_widget_get_default_style(); newstyle = gtk_style_copy(defstyle); newstyle->bg[0] = get_color(BROWN1); /* Normal bkgnd */ newstyle->bg[1] = get_color(BROWN2); /* Active bkgnd */ newstyle->bg[2] = get_color(BROWN3); /* Prelight bkgnd */ newstyle->fg[4] = get_color(BROWN4); /* Insensitive fgnd */ newstyle->bg[4] = get_color(BROWN1); /* Insensitive bkgnd */ newstyle->text[0] = get_color(BLACK); /* Normal text */ newstyle->text[4] = get_color(BROWN1); /* Insensitive text */ dfont = gdk_font_load(default_font); newstyle->font = dfont; gtk_widget_set_default_style(newstyle); /* --- Main top level window --------------------------------------------- */ init_top(&top); top.topwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); strcat(windowtitle, " "); strcat(windowtitle, VERSION); gtk_window_set_title(GTK_WINDOW(top.topwindow), windowtitle); gtk_container_border_width(GTK_CONTAINER(top.topwindow), 5); gtk_widget_set_usize(top.topwindow, 320, 522); gtk_signal_connect(GTK_OBJECT(top.topwindow), "delete_event", GTK_SIGNAL_FUNC(deleteW), NULL); gtk_signal_connect(GTK_OBJECT(top.topwindow), "destroy", GTK_SIGNAL_FUNC(destroyW), NULL); top.vbox_top = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(top.topwindow), top.vbox_top); gtk_widget_show(top.vbox_top); make_menu(&top); top.frame = gtk_frame_new(NULL); gtk_container_border_width(GTK_CONTAINER(top.frame), 5); gtk_frame_set_shadow_type( GTK_FRAME(top.frame), GTK_SHADOW_ETCHED_OUT); gtk_box_pack_start(GTK_BOX(top.vbox_top), top.frame, TRUE, TRUE, 0); gtk_widget_show(top.frame); top.vbox_main = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(top.frame), top.vbox_main); gtk_container_border_width(GTK_CONTAINER(top.vbox_main), 10); gtk_widget_show(top.vbox_main); lbox = gtk_hbox_new(FALSE, 0); /* for logo defined below */ gtk_box_pack_start(GTK_BOX(top.vbox_main), lbox, FALSE, FALSE, 0); gtk_widget_show(lbox); read_prefs(&top); make_entry(&top); make_messageBox(&(top.vbox_main), &(top.msgbox)); /* --- Show top & main loop ---------------------------------------------- */ gtk_widget_show(top.topwindow); /* These were placed after showing the topwindow because the realized topwindow is required for showing the pixmaps. make_messageBox() actually places the message box after the following because gtk_box_pack_end is used for the box. */ pixmaplogo = create_pix(&(top.topwindow), 2); gtk_box_pack_start(GTK_BOX(lbox), pixmaplogo, TRUE, FALSE, 0); make_notebook(&top); make_nbtable(&top, 2, 0, 5); /* Cartridge Main. page */ make_nbtable(&top, 0, 6, 9); /* Settings page */ make_nbtable(&top, 1, 10, 15); /* Printout page */ set_inhibit(&top); gtk_main(); exit(0); }