/* ************************************************************************* Module: lexroutines.c Author: Matt Simpson Arlington, TX matthewsimpson@home.com Date: August, 2000 Description: Various routines for Pup. Changes: **************************************************************************** COPYRIGHT (C) 1999, 2000 Matt Simpson GNU General Public License See lexgui.c for full notice. **************************************************************************** */ #include #include #include #include #include /* for extern int errno */ #include /* for getting the file type */ #include /* for open */ #include /* for read & close */ #include /* for SIGALRM */ #include "lexgui.h" /* ------------------------------------------------------------------------- stat_output() Checks the file type. Returns: 0 for default (assume a file) 1 for character device (like /dev/lp0) 2 for |shell_command (like |lpr) ------------------------------------------------------------------------- */ int stat_output(char *filename) { struct stat buffer; if(filename[0] == '|') return(2); /* Shell command as in |lpr (so popen is used) */ stat(filename, &buffer); /* printf("File mode = %d\n", buffer.st_mode); printf("S_ISDIR= %d\n", S_ISDIR(buffer.st_mode)); printf("S_ISCHR= %d\n", S_ISCHR(buffer.st_mode)); printf("S_ISBLK= %d\n", S_ISBLK(buffer.st_mode)); printf("S_ISREG= %d\n", S_ISREG(buffer.st_mode)); printf("S_ISFIFO= %d\n", S_ISFIFO(buffer.st_mode)); printf("S_ISLNK= %d\n", S_ISLNK(buffer.st_mode)); printf("S_ISSOCK= %d\n", S_ISSOCK(buffer.st_mode)); */ if(S_ISCHR(buffer.st_mode)) /* Character device */ return(1); else return(0); /* treat as file */ /* if you want to check for a file specifically then use: if(S_ISREG(buffer.st_mode)) */ } /* ------------------------------------------------------------------------- set_sensitize() Sensitizes or Insensitizes specified widgets ------------------------------------------------------------------------- */ void set_sensitize(topwin_struct *top, int s) { gint i; for(i = 0; i < NUMPAGE; i++) { if(s) { if(!top->prefs.t_inhibit[i]) gtk_widget_set_sensitive(top->bt.table[i], TRUE); } else gtk_widget_set_sensitive(top->bt.table[i], FALSE); } } /* ------------------------------------------------------------------------- blank() Adds blank label to box ------------------------------------------------------------------------- */ void blank(GtkWidget *box) { GtkWidget *label; label = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); gtk_widget_show(label); } /* ------------------------------------------------------------------------- gtk_msg_timer() Waits TIMELIMIT seconds, then clears the message in a message box. ------------------------------------------------------------------------- */ gint gtk_msg_timer(msgbox_struct *msgbox) { int TIMELIMIT = 5; /* Clear the message after waiting the specified time. */ if(msgbox->timecount >= TIMELIMIT) { msgbox->timecount = 0; if(!msgbox->freeze) /* freeze gets set for fixed messages */ if(GTK_IS_WIDGET(msgbox->msglabel)) gtk_label_set_text(GTK_LABEL(msgbox->msglabel), ""); return(FALSE); /* returning FALSE will automatically remove the timer */ } else { msgbox->timecount++; return(TRUE); } } /* ------------------------------------------------------------------------- clear_message() Calls timeout to clear message in a message box. ------------------------------------------------------------------------- */ void clear_message(msgbox_struct *msgbox) { if(msgbox->timer) { /* in case it already exisis -- e.g. if another button is pressed before this one's time runs out. */ gtk_timeout_remove(msgbox->timer); msgbox->timer = 0; } msgbox->timecount = 0; msgbox->timer = gtk_timeout_add(1000, (GtkFunction)gtk_msg_timer, msgbox); } /* ------------------------------------------------------------------------- make_separator() ------------------------------------------------------------------------- */ void make_separator(GtkWidget *box) { GtkWidget *separator; separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 6); gtk_widget_show (separator); } /* ------------------------------------------------------------------------- close_ibutton() Makes close button for info window, about window, and explain window. Close callback does not affect or clear top msglabel, nor clears the timer. ------------------------------------------------------------------------- */ void close_ibutton(GtkWidget **ibox, GtkWidget **itopwin) { GtkWidget *iquitbox, *ibutton; iquitbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_end(GTK_BOX(*ibox), iquitbox, FALSE, FALSE, 6); gtk_widget_show(iquitbox); ibutton = gtk_button_new_with_label("Close"); gtk_box_pack_start(GTK_BOX(iquitbox), ibutton, TRUE, FALSE, 0); /* Add close callback */ gtk_signal_connect(GTK_OBJECT (ibutton), "clicked", GTK_SIGNAL_FUNC (close_iwindow), (gpointer) itopwin); gtk_widget_show(ibutton); } /* ------------------------------------------------------------------------- make_framebox() ------------------------------------------------------------------------- */ void make_framebox(framebox_struct *fb, GtkWidget **box, gint width, gint height, gchar *title) { fb->frame = gtk_frame_new(title); gtk_frame_set_shadow_type( GTK_FRAME(fb->frame), GTK_SHADOW_ETCHED_OUT); gtk_frame_set_label_align( GTK_FRAME(fb->frame), 0.02, 0.0); gtk_box_pack_start(GTK_BOX(*box), fb->frame, FALSE, FALSE, 10); gtk_widget_show(fb->frame); fb->align = gtk_alignment_new (0.5, 0.4, 0, 0); gtk_widget_set_usize(fb->align, width, height); gtk_container_add(GTK_CONTAINER(fb->frame), fb->align); gtk_widget_show(fb->align); fb->hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(fb->align), fb->hbox); gtk_widget_show(fb->hbox); fb->pbox = gtk_hbox_new(FALSE, 0); /* for pixmap */ gtk_box_pack_start(GTK_BOX(fb->hbox), fb->pbox, FALSE, FALSE, 0); gtk_widget_show(fb->pbox); } /* ------------------------------------------------------------------------- about_event() ------------------------------------------------------------------------- */ void about_event(topwin_struct *top) { GtkWidget *frame, *label, *box, *lbox; GtkWidget *pixmaplogo; char tmp_str[500]; /* In case it already exists. Note when destroyed, it must be set to NULL */ if(GTK_IS_WIDGET(top->aboutwin)) return; top->aboutwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(top->aboutwin), "Credits"); gtk_container_border_width(GTK_CONTAINER(top->aboutwin), 5); set_color(&(top->aboutwin), WHITE, BG, NORMAL); frame = gtk_frame_new(NULL); gtk_container_add(GTK_CONTAINER(top->aboutwin), frame); gtk_frame_set_label_align( GTK_FRAME(frame), 0.5, 0.0); gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT); gtk_widget_show(frame); box = gtk_vbox_new(FALSE, 0); gtk_container_border_width(GTK_CONTAINER(box), 10); gtk_container_add(GTK_CONTAINER(frame), box); gtk_widget_show(box); lbox = gtk_hbox_new(FALSE, 0); /* for logo defined below */ gtk_box_pack_start(GTK_BOX(box), lbox, FALSE, FALSE, 0); gtk_widget_show(lbox); blank(box); put_title(&box); label = gtk_label_new(VERSION); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); gtk_widget_show(label); sprintf(tmp_str, "(c)%s Matt Simpson\nmatthewsimpson@home.com\n\n" "Copyrighted under the\n" "GNU General Public License.\n", CURYEAR); label = gtk_label_new(""); gtk_label_set_text(GTK_LABEL(label), tmp_str); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); gtk_widget_show(label); label = gtk_label_new(""); gtk_label_set_text(GTK_LABEL(label), "This program uses the libc, glib, GTK+, and zlib libraries " "which fall under the terms of the GNU Library General " "Public License, version 2 or later. Depending on how " "this program was compiled, other licenses may apply. " "For example if this program was compiled under " "XFree86, the XFree86 Copyright and the copyrights " "it contains may apply.\n" "\n" "Lexmark and Optra are trademarks of Lexmark International, " "Inc. Printer specific calls courtesy of Lexmark International, " "Inc. with permission from (and thanks to) David Lane of " "Lexmark. All Lexmark specific printer command strings in this " "application have been released for public distribution.\n" "\n" "This program comes with ABSOLUTELY NO WARRANTY. " "This is free software, and you are welcome to redistribute " "it under certain conditions. For details, see the GNU " "General Public License.\n\n" "The initial release of Pup was v1.0 in August, 1999."); gtk_widget_set_usize(label, 330, 320); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_FILL); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); gtk_widget_show(label); close_ibutton(&box, &(top->aboutwin)); /* For the X delete */ gtk_signal_connect(GTK_OBJECT(top->aboutwin), "delete_event", GTK_SIGNAL_FUNC(close_iwindowX), (gpointer)&(top->aboutwin)); gtk_widget_show(top->aboutwin); /* must be defined after aboutwin is realized */ pixmaplogo = create_pix(&(top->aboutwin), 2); gtk_box_pack_start(GTK_BOX(lbox), pixmaplogo, TRUE, FALSE, 0); } /* ------------------------------------------------------------------------- make_pix_label_box() Makes horiz box and puts it in vert box, then puts the pixmap and label boxes into it. ------------------------------------------------------------------------- */ void make_pix_label_box(GtkWidget **vsbox, GtkWidget **p_box, GtkWidget **l_box) { GtkWidget *pl_box; pl_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(*vsbox), pl_box, FALSE, TRUE, 0); gtk_widget_show(pl_box); gtk_box_pack_start(GTK_BOX(pl_box), *p_box, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(pl_box), *l_box, FALSE, TRUE, 15); } /* ------------------------------------------------------------------------- make_pix_box() Makes box for pixmap. The pixmaps are not placed in the box yet because the window has to be shown first. The box is not packed into something here; it gets packed in make_pix_label_box(). ------------------------------------------------------------------------- */ GtkWidget *make_pix_box(void) { GtkWidget *pbox; pbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(pbox); return(pbox); } /* ------------------------------------------------------------------------- make_label_box() Makes box with label. The box is not packed here, so pack it after returning. The label is full justified. ------------------------------------------------------------------------- */ GtkWidget *make_label_box(char *imessage, gint font, gint width) { GtkWidget *lab, *hbox; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); lab = gtk_label_new(""); gtk_label_set_text(GTK_LABEL(lab), imessage); set_font(&lab, font); gtk_label_set_line_wrap (GTK_LABEL (lab), TRUE); gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_FILL); gtk_widget_set_usize(lab, width, 0); gtk_box_pack_start(GTK_BOX(hbox), lab, FALSE, TRUE, 0); gtk_widget_show(lab); return(hbox); } /* ------------------------------------------------------------------------- make_underlinedlabel_box() Makes box with underlined label. The box is not packed here, so pack it after returning. The label is left justified, as underlining does not work on full justified. ------------------------------------------------------------------------- */ GtkWidget *make_underlinedlabel_box(char *imessage, gint font) { gint i; GtkWidget *lab, *hbox; gchar pattern[256]; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); lab = gtk_label_new(""); gtk_label_set_text(GTK_LABEL(lab), imessage); for(i = 0; i < strlen(imessage); i++) pattern[i] = '_'; pattern[i] = 0; gtk_label_set_pattern(GTK_LABEL(lab), pattern); set_font(&lab, font); gtk_label_set_justify(GTK_LABEL(lab), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(hbox), lab, FALSE, TRUE, 0); gtk_widget_show(lab); return(hbox); } /* ------------------------------------------------------------------------- put_info() For help window. Uses these functions which go together: make_label_box() make_pix_box() make_pix_label_box() ------------------------------------------------------------------------- */ void put_info(GtkWidget *vsbox, GtkWidget **pixbox) { GtkWidget *vlabbox, *labbox, *pbox; char lmessage[2500]; gint width = 380; gint width1 = width - 47; /* with when pixmap is on left. */ /* -------------------------------------------------------------- */ labbox = make_label_box("Output Box", 8, width); gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 6); sprintf(lmessage, "This may be a device (e.g. /dev/lp0), a filename, or a command " "preceeded by a '|'. If a filename, the commands are written to " "the specified file (overwriting it if it already exists) which " "then may be executed with cat (e.g. cat filename >/dev/lp0), or can " "be sent to a remote printer using FTP. The printer must support " "the commands Pup outputs, which depending on the command you " "selected may be binary, PJL, or PostScript.\n" "\n" "When creating commands in a file you should make separate files " "as necessary. For example the install and park commands should " "be placed in separate files to be executed when appropriate. If " "the first character is a '|' then the command following it is " "executed. For example if your printer name is 'printer1' (see " "/etc/printcap) then you may specify |lpr -Pprinter1 or simply " "|lpr to use your default printer. This would work on local and " "network printers if set up.\n" "\n" "If the output is a file, the first time you send a command the " "file will be opened and then stay open for subsequent commands " "to be appended. If you change the filename the previous file " "will be closed and a new file will be opened for subsequent " "commands. If the output is a device or command, it will not be " "opened until a command is actually sent, and then the device is " "closed. This frees the device for printing other jobs while Pup is " "running.\n" "\n" "The default name listed in this box is set by this program; This can " "be changed in Pup's preferences window under the File menu.\n"); labbox = make_label_box(lmessage, 0, width); gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 0); /* -------------------------------------------------------------- */ labbox = make_label_box("Printer", 8, width); gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 6); sprintf(lmessage, "The listed printer model, which may be set in Pup's preferences " "window, is used to determine printer specific commands. This is " "not used on Query printer settings and Set Printer Defaults -- " "Dynamic choices, because Pup queries the printer for the correct " "commands. The printer model is also not used on Printer Status, " "Print Pup test page, and Print TTF page, because these are PostScript " "commands which will work on any PostScript compatible printer.\n"); labbox = make_label_box(lmessage, 0, width); gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 0); /* -------------------------------------------------------------- */ labbox = make_label_box("Settings", 8, width); gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 6); vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Query printer settings.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This is used to query the printer and read back its settings (bi- " "directional communication). It only works if you have read back " "support in your kernal. Since this is a read-only window, no " "information is filtered out by Pup.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[6] = pbox; /* These are for putting the pixmaps in after returning */ vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Set printer defaults - Dynamic choices.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This queries the printer and builds a list of printer settings " "based on what comes back from the printer. It only works if you " "have read back support in your kernal. Some settings are filtered " "out. To see all settings, use the Query printer settings command. " "The settings are shown as choices that can be changed; after " "changing, a new query is performed to show the new settings for " "verification. This window is called 'Dynamic choices' because " "it builds the choices based on what a printer says it has. " "Therefore it will work on many printers, not just those listed " "in the preferences window. However, the printer must support " "PJL (Printer Job Language). For more information on this window, " "click the Help button on it.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[7] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Set printer defaults - Fixed choices.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This is similar to the Dynamic choices window except it works in " "uni-directional mode for those systems that do not have read back " "support in the kernel. The choices are based on queries performed " "before hand by the author and hard-coded into Pup. Supported " "printers are listed in the preferences window. The only way to " "verify changed settings in this uni-directional mode is to print " "a settings page. Although the printer may have more settings " "available, the only choices allowed are those that can be verified " "on the printed settings page. Therefore the 'Dynamic choices' " "window offers more; it is advisable to get read back support " "for your system.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[8] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Printer status.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This issues a PostScript status command (ctrl-t) to read back " "the printer's status. It only works if you have read back " "and PostScript support.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[9] = pbox; /* -------------------------------------------------------------- */ labbox = make_label_box("Printouts", 8, width); gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 6); vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Print Pup test page.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This prints a PostScript test page showing information about " "the host and the printer. All commands are in PostScript, so " "this will work on any PostScript compatible printer. You can " "also print this page to a file that can be sent to a printer " "on another system not running Pup, but the host information " "will apply to the host used by Pup to generate this page. The " "printer information will apply to the actual printer printing " "this page, unless you go through GhostScript or another " "interface in which case it will show information on these. " "The printer does not have to support PJL.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[10] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Print PostScript font listing.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "Issues the command to print the PS fonts available on the " "printer. The command depends on the Printer Model selected.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[11] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Print PCL font listing.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "Issues the command to print the PCL fonts available on the " "printer. The command depends on the Printer Model selected.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[12] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Print the settings page.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "Issues the command to print the printer's current settings. " "The command depends on the Printer Model selected. This " "command is handy to use in conjunction with the 'Fixed " "choices' page.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[13] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Print demo page.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "Issues the command to print the printer's built-in demo " "page. The command depends on the Printer Model selected.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[14] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Print TTF test page.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This prints a PostScript True-type font test page showing " "a custom font in various sizes. As with the Pup Test Page, " "this can be printed to a file and sent to a PostScript " "supporting printer on another system.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[15] = pbox; /* -------------------------------------------------------------- */ labbox = make_label_box("Cartridge Maintainance", 8, width); gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 6); vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Install or replace a cartridge.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This page contains commands that allow access and set " "up of the print cartridges. Access is gained by commanding " "the carrier to move to the extreme left.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[0] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Park the cartridges.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This command moves the cartridge carrier back to the " "maintenance station. It should always be performed " "after installing or replacing a cartridge.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[1] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Align the cartridges.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This page prints the alignment value choices and " "allows modification of values. These alignment values " "compensate for small position variations. They should " "be adjusted every time a cartridge is replaced.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[2] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Reset the ink level gauges.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "The menu page contains ink level gauges for the Black, " "Color, and Photo cartridges. The appropriate gauge " "should be reset to full when a new cartridge is installed.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[3] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Print the menu settings page.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This page contains the ink level gauges and system settings.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[4] = pbox; vlabbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vlabbox); labbox = make_underlinedlabel_box("Clean the nozzles.", 0); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); sprintf(lmessage, "This prints a test page which should flush any blocked or " "partially blocked nozzles.\n\n"); labbox = make_label_box(lmessage, 0, width1); gtk_box_pack_start(GTK_BOX(vlabbox), labbox, FALSE, TRUE, 0); pbox = make_pix_box(); make_pix_label_box(&vsbox, &pbox, &vlabbox); pixbox[5] = pbox; /* -------------------------------------------------------------- */ sprintf(lmessage, "Note: Although some messages appearing at the bottom of " "each window (whenever a command is used) last for 5 " "seconds, the command is actually instantaneous; other " "commands can be used without having to wait for this " "message to disappear.\n"); labbox = make_label_box(lmessage, 0, width); /* Don't have a pixmap so we just pack the box */ gtk_box_pack_start(GTK_BOX(vsbox), labbox, FALSE, TRUE, 0); } /* ------------------------------------------------------------------------- infow_event() Make the scrolled "infowin" window. ------------------------------------------------------------------------- */ void infow_event(topwin_struct *top) { int i; int NUMPIX = 16; GtkWidget *pixbox[NUMPIX], *ipix[NUMPIX]; /* In case it already exists. Note when destroyed, it must be set to NULL */ if(GTK_IS_WIDGET(top->infowin.topwin)) return; top->infowin.info_only_flag = 1; top->infowin.aj.tba = 0; /* Hand scroll mode active */ make_sc_win(&(top->infowin), "More Info", 450, 600); put_info(top->infowin.sc_vbox, &pixbox[0]); /* Add the pixmaps to the hboxes */ for(i = 0; i < NUMPIX; i++) { ipix[i] = create_nbpix(&(top->infowin.topwin), i); gtk_box_pack_start(GTK_BOX(pixbox[i]), ipix[i], FALSE, FALSE, 0); } } /* ------------------------------------------------------------------------- set_tool_color() Workaround for GTK 1.2 gtk_tooltips_set_colors() bug. ------------------------------------------------------------------------- */ void set_tool_color(GtkTooltips **tooltips) { int j; static GtkStyle *current_style; static int tinit = 0; gtk_tooltips_force_window(*tooltips); /* Otherwise the next call fails. */ /* Allocate the new style only once */ if(!tinit) { tinit = 1; current_style = gtk_style_copy(gtk_widget_get_style((*tooltips)->tip_window)); for(j = 0; j < 5; j++) { current_style->fg[j] = get_color(BLACK); current_style->bg[j] = get_color(YELLOW); } } gtk_widget_set_style((*tooltips)->tip_window, current_style); } /* ------------------------------------------------------------------------- put_msg() Puts message in a message box. *msgbox = Pointer to message box structure. msgbox->msglabel Gets set with *mess. (already created) msgbox->expbutton Gets created. Gets destroyed when cleared. msgbox->h_msgbox Horiz box for msglabel. (already created) *mess = Text to put in label widget. lcolor = color to make text (see set_color()). explain = Explain button for more info-- if 0, don't make one. See explain_CB() for info on the explain messages available. msgbox is already created once per window in make_messageBox(). ------------------------------------------------------------------------- */ void put_msg(msgbox_struct *msgbox, char *mess, int lcolor, int explain) { GtkWidget *label; GtkTooltips *tooltips; tooltips = gtk_tooltips_new(); set_tool_color(&tooltips); set_color(&(msgbox->msglabel), lcolor, FG, NORMAL); gtk_label_set_text(GTK_LABEL(msgbox->msglabel), mess); msgbox->explain = explain; if(explain && GTK_IS_WIDGET(msgbox->h_msgbox)) { msgbox->expbutton = gtk_button_new(); gtk_box_pack_start(GTK_BOX(msgbox->h_msgbox), msgbox->expbutton, TRUE, FALSE, 0); gtk_signal_connect(GTK_OBJECT (msgbox->expbutton), "clicked", GTK_SIGNAL_FUNC (explain_CB), (gpointer)msgbox); gtk_tooltips_set_tip(tooltips, msgbox->expbutton, "Press for more info", NULL); gtk_widget_show(msgbox->expbutton); /* set fancy cursor for this button. By the time the program gets here the top window this button is in is already 'shown', if you are wondering about the note on cursors above. */ gdk_window_set_cursor ((msgbox->expbutton)->window, gdk_cursor_new (GDK_QUESTION_ARROW)); label = gtk_label_new("Explain"); set_color(&label, lcolor, FG, NORMAL); set_font(&label, 2); gtk_container_add(GTK_CONTAINER(msgbox->expbutton), label); gtk_widget_show(label); } } /* ------------------------------------------------------------------------- open_output() Opens file. If there is a problem opening the output, the tables of choices become insensitive but the text entry box stays sensitive to allow a change. An error message and explain button also appear at the bottom of the main window. When the entry box changes, the tables of choices then become sensitive and the error message and explain button go away. Upon pressing a button for a new task from the choices, and the file still cannot be opened for whatever is now in the text field, the tables of choices again become insensitive and the error message again appears. If all is well, the previously opened file closes and the new file is opened. See entry_callback(). Note for open_pipe() and open_output_dev() below, these happen just-in-time, that is only when the command is needed; therefore on errors the tables of choices are already insensitive and the call to set_sensitize() is not needed. ------------------------------------------------------------------------- */ int open_output(topwin_struct *top) { extern gchar *output; extern FILE *fp; char message[50]; extern int errno; /* in errno.h */ extern int open_file_errno; open_file_errno = 0; if(fp) { /* will get here only if previously opened fp was a file */ fclose(fp); fp = NULL; } /* if blank */ if(output[0] == 0 || output[0] == ' ') { set_sensitize(top, 0); top->msgbox.freeze = 1; /* make this a fixed message */ sprintf(message, "%s", "Error: Output box is empty."); put_msg(&(top->msgbox), message, RED, 0); return(1); } if((fp = fopen(output, "w")) == NULL) { open_file_errno = errno; set_sensitize(top, 0); top->msgbox.freeze = 1; /* make this a fixed message */ sprintf(message, "%s", "Error: Can't open output."); put_msg(&(top->msgbox), message, RED, 1); return(1); } else { top->entry_state = 2; set_sensitize(top, 1); } return(0); } /* ------------------------------------------------------------------------- open_pipe() Opens output pipe for commands like |lpr ------------------------------------------------------------------------- */ int open_pipe(msgbox_struct *msgbox) { extern gchar *output; extern FILE *fp; char message[50]; extern int errno; /* in errno.h */ extern int open_file_errno; open_file_errno = 0; /* if blank */ if((output[0] == '|' && strlen(output+1) < 1) /* Cont. by Grant Taylor */ || (output[0] == '|' && output[1] == ' ')) { msgbox->freeze = 1; sprintf(message, "%s", "Error: Output box pipe is empty."); put_msg(msgbox, message, RED, 0); /* don't need to set the choices insensitive because they already are. */ return(1); } if((fp = popen(output+1, "w")) == NULL) /* Contributed by Grant Taylor */ { open_file_errno = errno; msgbox->freeze = 1; sprintf(message, "%s", "Error: Can't open output pipe."); put_msg(msgbox, message, RED, 1); /* don't need to set the choices insensitive because they already are. */ return(1); } else return(0); } /* ------------------------------------------------------------------------- catch_alarm() Signal Handler ------------------------------------------------------------------------- */ void catch_alarm(int sig) { return; } /* ------------------------------------------------------------------------- open_output_dev() Opens output device. Any errors are reported upon returning to opendev(). ------------------------------------------------------------------------- */ int open_output_dev(msgbox_struct *msgbox) { extern gchar *output; extern FILE *fp; extern int errno; /* in errno.h */ extern int open_file_errno; int fd, numwrite; char buff[1] = "\0"; open_file_errno = 0; if(fp) { fclose(fp); fp = NULL; } /* First we see if we can do a low level write, to check for something like the printer being powered off. An alarm signal is used to interrupt the write in case it stops due to the device not being ready. The alarm is used because I could not get non-blocking to work on a write() (e.g. on non-blocking it would return immediately if it couldn't write). Non-blocking does work on a read() which returns immediately if it can't. But I did not use a read() here because the system running Pup might not have a kernel configured with CONFIG_PRINTER_READBACK = y and therefore the device could not be read (only witten to); since Pup likes to offer what it can, a read() should not be attempted at this point in the program in order to at least offer the 'output only' features (the non-query stuff like replacing the cartridges). Note the read() returns are checked in the query routines because by definition the kernel must have the readback flag set in order to use these (and if not Pup issues the appropriate error). This sectin originally used a read() test (in Pup 1.0.1) but after some folks complained about Pup not working (they had a kernel without the readback flag set), I deleted the test altogether (in Pup 1.0.2). I did not like this because if the printer is powered off, Pup would just hang up whenever attempting to open /dev/lp0. So I rewrote the test to use a write() with an alarm. */ /* Establish a handler for SIGALRM signals. Used with alarm(). */ signal (SIGALRM, catch_alarm); fd = open(output, O_WRONLY); if(fd >= 0) { alarm(2); /* Set alarm for 2 sec */ /* If the write() hangs up then the alarm signal interrupts it */ numwrite = write(fd, buff, sizeof(buff)); /* just writing a NULL */ if(numwrite) alarm(0); /* cancel alarm */ /* If no problem, we cancelled the alarm above; else the alarm signal interrupts the above write() with a EINTR */ if(errno == EINTR) /* defined in errno.h */ { open_file_errno = errno; msgbox->freeze = 1; close(fd); /* don't need to set the choices insensitive because they already are. */ return(1); } close(fd); } /* Now open the output as a file pointer for doing commands. */ if((fp = fopen(output, "w+")) == NULL) { open_file_errno = errno; msgbox->freeze = 1; /* don't need to set the choices insensitive because they already are. */ return(1); } else return(0); } /* ------------------------------------------------------------------------- closedev() If output is a device or |, close it. ------------------------------------------------------------------------- */ void closedev(void) { extern FILE *fp; extern int devtype; if(fp) { if(devtype == 1){ fclose(fp); fp = NULL; } else if(devtype == 2){ pclose(fp); fp = NULL; } } /* won't close if a file */ } /* ------------------------------------------------------------------------- opendev() If output is a device, call open_output_dev(). ------------------------------------------------------------------------- */ int opendev(msgbox_struct *msgbox, int ex) { char message[50]; extern int devtype; if(devtype == 1) { if(open_output_dev(msgbox)) { sprintf(message, "%s", "Error: Can't open output device."); put_msg(msgbox, message, RED, ex); return(1); } } else if(devtype == 2) if(open_pipe(msgbox)) return(1); /* Returning 0 means: it was a device or pipe that was successfully opened, or it was a file and therefore is already open at this point. */ return(0); } /* ------------------------------------------------------------------------- reset_top() ------------------------------------------------------------------------- */ void reset_top(topwin_struct *top, int now) { if(!now) clear_message(&(top->msgbox)); else { /* if now is passed in as not 0, clear message immediately instead of using a timer */ gtk_label_set_text(GTK_LABEL(top->msgbox.msglabel), ""); } gtk_widget_set_sensitive(top->entry, TRUE); gtk_widget_set_sensitive(top->prefmenu, TRUE); set_sensitize(top, 1); } /* ------------------------------------------------------------------------- setactivebutn_CB() Callback for pushbuttons in table of choices. Sets the active button number. ------------------------------------------------------------------------- */ void setactivebut_CB(GtkWidget *widget, curbut_struct *b) { (b->topptr)->activebut = b->butnum; } /* ------------------------------------------------------------------------- put_mstring() Puts string into table of choices. The column is hard coded 1 to 2, and the rows are passed in. ------------------------------------------------------------------------- */ void put_mstring(GtkWidget **toptable, char *m_str, int top, int btm) { GtkWidget *label, *hbox; hbox = gtk_hbox_new(FALSE, 0); gtk_table_attach_defaults (GTK_TABLE(*toptable), hbox, 1, 2, top, btm); gtk_widget_show(hbox); label = gtk_label_new(""); gtk_label_set_text(GTK_LABEL(label), m_str); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); } /* ------------------------------------------------------------------------- make_messageBox() Makes box for putting messages in. Do this only once per window. ------------------------------------------------------------------------- */ void make_messageBox(GtkWidget **vbox, msgbox_struct *msgbox) { msgbox->h_msgbox = gtk_hbox_new(FALSE, 0); gtk_widget_set_usize(msgbox->h_msgbox, 100, 40); gtk_box_pack_end(GTK_BOX(*vbox), msgbox->h_msgbox, FALSE, FALSE, 0); gtk_widget_show(msgbox->h_msgbox); msgbox->msglabel = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(msgbox->h_msgbox), msgbox->msglabel, TRUE, FALSE, 0); gtk_widget_show(msgbox->msglabel); } /* ------------------------------------------------------------------------- entry_callback() Also see prefentry_callback() in fixed.c ------------------------------------------------------------------------- */ void entry_callback(GtkWidget *widget, topwin_struct *top) { extern gchar *output; if(!top->pflag) { gtk_widget_set_sensitive(top->prefmenu, TRUE); set_sensitize(top, 1); /* Clear the possible error message */ clear_msgbox(&(top->msgbox)); } top->entry_state = 1; output = gtk_entry_get_text(GTK_ENTRY(top->entry)); /* does not set top->prefs.outfile because the user may want this to be temporary. */ } /* ------------------------------------------------------------------------- make_entry() ------------------------------------------------------------------------- */ void make_entry(topwin_struct *top) { extern gchar *output; GtkWidget *hbox, *hbox1, *table, *label; hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(top->vbox_main), hbox, FALSE, FALSE, 5); gtk_widget_show(hbox); table = gtk_table_new(2, 2, FALSE); gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, FALSE, 0); gtk_widget_show(table); label = gtk_label_new("Output:"); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_EXPAND, GTK_EXPAND, 5, 5); gtk_widget_show(label); top->entry = gtk_entry_new(); gtk_widget_set_usize(top->entry, 150, 20); gtk_entry_set_text(GTK_ENTRY(top->entry), output); /* Note output was set when Pup was invoked; if .puprc exists, output was set to top->prefs.outfile (if not NULL); if not, output was set to DEFAULT_DEV. */ gtk_signal_connect(GTK_OBJECT(top->entry), "changed", GTK_SIGNAL_FUNC(entry_callback), (gpointer)top); gtk_table_attach(GTK_TABLE(table), top->entry, 1, 2, 0, 1, GTK_EXPAND, GTK_EXPAND, 5, 5); gtk_widget_show(top->entry); label = gtk_label_new("Printer:"); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_EXPAND, GTK_EXPAND, 5, 5); gtk_widget_show(label); hbox1 = gtk_hbox_new(FALSE, 0); gtk_widget_set_usize(hbox1, 150, 20); gtk_table_attach(GTK_TABLE(table), hbox1, 1, 2, 1, 2, GTK_EXPAND, GTK_EXPAND, 5, 5); gtk_widget_show(hbox1); top->printerlabel = gtk_label_new(top->prefs.printer); gtk_label_set_justify(GTK_LABEL(top->printerlabel), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(hbox1), top->printerlabel, FALSE, FALSE, 0); gtk_widget_show(top->printerlabel); }