summaryrefslogtreecommitdiff
path: root/xpsimplehelloworld/xpsimplehelloworld.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpsimplehelloworld/xpsimplehelloworld.c')
-rw-r--r--xpsimplehelloworld/xpsimplehelloworld.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/xpsimplehelloworld/xpsimplehelloworld.c b/xpsimplehelloworld/xpsimplehelloworld.c
new file mode 100644
index 0000000..064894c
--- /dev/null
+++ b/xpsimplehelloworld/xpsimplehelloworld.c
@@ -0,0 +1,374 @@
+/*
+ * $Xorg: xphelloworld.c,v 1.2 2002/05/10 06:54:^1 gisburn Exp $
+ *
+ * xphelloworld - Xprint version of hello world
+ *
+ *
+Copyright 2002-2004 Roland Mainz <roland.mainz@nrubsig.org>
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ *
+ * Author: Roland Mainz <roland.mainz@nrubsig.org>
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/XprintUtil/xprintutil.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/* Turn a NULL pointer string into an empty string */
+#define NULLSTR(x) (((x)!=NULL)?(x):(""))
+
+#define Log(x) { if(verbose) printf x; }
+
+static const char *ProgramName; /* program name (from argv[0]) */
+static Bool verbose = False; /* verbose output what the program is doing */
+
+static
+void usage(void)
+{
+ fprintf (stderr, "usage: %s [options]\n", ProgramName);
+ fprintf (stderr, "-printer printernname\tprinter to use\n");
+ fprintf (stderr, "-printfile file\tprint to file instead of printer\n");
+ fprintf (stderr, "-embedpsl2data string\tPostScript level 2 fragment to embed\n"
+ "\t\t(use 'xppsembeddemo1' to embed demo data)\n");
+ fprintf (stderr, "-v\tverbose output\n");
+ fprintf (stderr, "\n");
+ exit(EXIT_FAILURE);
+}
+
+/* strstr(), case-insensitive */
+static
+char *str_case_str(const char *s, const char *find)
+{
+ size_t len;
+ char c,
+ sc;
+
+ if ((c = tolower(*find++)) != '\0')
+ {
+ len = strlen(find);
+ do
+ {
+ do
+ {
+ if ((sc = tolower(*s++)) == '\0')
+ return NULL;
+ } while (sc != c);
+ } while (strncasecmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
+static
+int do_hello_world(const char *printername, const char *printerfile, const char *psembeddata )
+{
+ Display *pdpy; /* X connection */
+ XPContext pcontext; /* Xprint context */
+ void *printtofile_handle; /* "context" when printing to file */
+ int xp_event_base, /* XpExtension even base */
+ xp_error_base; /* XpExtension error base */
+ long dpi;
+ Screen *pscreen;
+ int pscreennumber;
+ Window pwin;
+ XGCValues gcvalues;
+ XEvent ev;
+ GC pgc;
+ unsigned short dummy;
+ XRectangle winrect;
+ char fontname[256]; /* BUG: is this really big enougth ? */
+ XFontStruct *font;
+
+ if( XpuGetPrinter(printername, &pdpy, &pcontext) != 1 )
+ {
+ fprintf(stderr, "Cannot open printer '%s'\n", printername);
+ return(EXIT_FAILURE);
+ }
+
+ if( XpQueryExtension(pdpy, &xp_event_base, &xp_error_base) == False )
+ {
+ fprintf(stderr, "XpQueryExtension() failed.\n");
+ XpuClosePrinterDisplay(pdpy, pcontext);
+ return(EXIT_FAILURE);
+ }
+
+ /* Listen to XP(Start|End)(Job|Doc|Page)Notify events).
+ * This is mantatory as Xp(Start|End)(Job|Doc|Page) functions are _not_
+ * syncronous !!
+ * Not waiting for such events may cause that subsequent data may be
+ * destroyed/corrupted!!
+ */
+ XpSelectInput(pdpy, pcontext, XPPrintMask);
+
+ /* Set job title */
+ XpuSetJobTitle(pdpy, pcontext, "Hello world for Xprint");
+
+ /* Set print context
+ * Note that this modifies the available fonts, including builtin printer prints.
+ * All XListFonts()/XLoadFont() stuff should be done _after_ setting the print
+ * context to obtain the proper fonts.
+ */
+ XpSetContext(pdpy, pcontext);
+
+ /* Get default printer reolution */
+ if( XpuGetResolution(pdpy, pcontext, &dpi) != 1 )
+ {
+ fprintf(stderr, "No default resolution for printer '%s'.\n", printername);
+ XpuClosePrinterDisplay(pdpy, pcontext);
+ return(EXIT_FAILURE);
+ }
+
+ if( printerfile )
+ {
+ Log(("starting job (to file '%s').\n", printerfile));
+ printtofile_handle = XpuStartJobToFile(pdpy, pcontext, printerfile);
+ if( !printtofile_handle )
+ {
+ fprintf(stderr, "%s: Error: %s while trying to print to file.\n",
+ ProgramName, strerror(errno));
+ XpuClosePrinterDisplay(pdpy, pcontext);
+ return(EXIT_FAILURE);
+ }
+
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartJobNotify);
+ }
+ else
+ {
+ Log(("starting job.\n"));
+ XpuStartJobToSpooler(pdpy);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartJobNotify);
+ }
+
+#ifdef MULTIPLE_DOCUMENTS_IN_ONE_JOB
+ /* Start document (one job can contain any number of "documents")
+ * XpStartDoc() isn't mandatory if job only contains one document - first
+ * XpStartPage() will generate a "synthetic" XpStartDoc() if one had not
+ * already been done.
+ */
+ XpStartDoc(pdpy, XPDocNormal);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartDocNotify);
+#endif /* MULTIPLE_DOCUMENTS_IN_ONE_JOB */
+
+ pscreen = XpGetScreenOfContext(pdpy, pcontext);
+ pscreennumber = XScreenNumberOfScreen(pscreen);
+
+ /* Obtain some info about page geometry */
+ XpGetPageDimensions(pdpy, pcontext, &dummy, &dummy, &winrect);
+
+ pwin = XCreateSimpleWindow(pdpy, XRootWindowOfScreen(pscreen),
+ winrect.x, winrect.y, winrect.width, winrect.height,
+ 10,
+ XBlackPixel(pdpy, pscreennumber),
+ XWhitePixel(pdpy, pscreennumber));
+
+ gcvalues.background = XWhitePixel(pdpy, pscreennumber);
+ gcvalues.foreground = XBlackPixel(pdpy, pscreennumber);
+
+ pgc = XCreateGC(pdpy, pwin, GCBackground|GCForeground, &gcvalues);
+
+ Log(("start page.\n"));
+ XpStartPage(pdpy, pwin);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartPageNotify);
+
+ /* Mapping the window inside XpStartPage()/XpEndPage()
+ * Set XCreateWindow/border_width to 0 or move XMapWindow in front of
+ * XpStartPage() to get rid of the surrounding black border lines.
+ * (This is usually done before XpStartPage() in real applications)
+ */
+ XMapWindow(pdpy, pwin);
+
+ /* usual rendering stuff..... */
+
+ sprintf(fontname, "-*-*-*-*-*-*-*-180-%ld-%ld-*-*-iso8859-1", dpi, dpi);
+ font = XLoadQueryFont(pdpy, fontname);
+ XSetFont(pdpy, pgc, font->fid);
+ XDrawString(pdpy, pwin, pgc, 100, 100, "hello world from X11 print system", 33);
+
+#define DO_EMBED_TEST 1
+
+#ifdef DO_EMBED_TEST
+ if( psembeddata )
+ {
+ char *embedded_formats_supported;
+
+ embedded_formats_supported = XpGetOneAttribute(pdpy, pcontext, XPPrinterAttr, "xp-embedded-formats-supported");
+
+ Log(("psembed: xp-embedded-formats-supported='%s'\n", NULLSTR(embedded_formats_supported)));
+
+ /* MAX(XExtendedMaxRequestSize(pdpy), XMaxRequestSize(pdpy)) defines the
+ * maximum length of emebdded PostScript data which can be send in one
+ * step using XpPutDocumentData() */
+ Log(("psembed: XExtendedMaxRequestSize=%ld\n", (long)XExtendedMaxRequestSize(pdpy)));
+ Log(("psembed: XMaxRequestSize=%ld\n", (long)XMaxRequestSize(pdpy)));
+
+ /* Should we embed the demo ? */
+ if( !strcmp(psembeddata, "xppsembeddemo1") )
+ {
+ Log(("psembed: Using PS embedding demo 1\n"));
+ psembeddata = "newpath\n270 360 moveto\n 0 72 rlineto\n"
+ "72 0 rlineto\n 0 -72 rlineto\n closepath\n fill\n";
+ }
+ else
+ {
+ Log(("psembed: Using user PS embedding data = '%s'\n", psembeddata));
+ }
+
+ /* Check whether "PostScript Level 2" is supported as embedding format
+ * (The content of the "xp-embedded-formats-supported" attribute needs
+ * to be searched in a case-insensitive way since the model-configs
+ * may use the same word with multiple variants of case
+ * (e.g. "PostScript" vs. "Postscript" or "PCL" vs. "Pcl" etc.")
+ * To avoid problems we simply use |str_case_str()| (case-insensitive
+ * strstr()) instead of |strstr()| here...)
+ */
+ if( embedded_formats_supported &&
+ (str_case_str(embedded_formats_supported, "PostScript 2") != NULL) )
+ {
+ /* Note that the emebdded PostScript code uses the same resolution and
+ * coordinate space as currently be used by the DDX (if you don not
+ * want that simply reset it yourself :) */
+ char *test = (char *)psembeddata;
+ int test_len = strlen(test);
+ char *type = "PostScript 2"; /* Format of embedded data
+ * (older PS DDX may be picky, fixed via
+ * http://xprint.mozdev.org/bugs/show_bug.cgi?id=4023)
+ */
+ char *option = ""; /* PostScript DDX does not support any options yet
+ * (in general |BadValue| will be returned for not
+ * supported options/option values) */
+ XpPutDocumentData(pdpy, pwin, test, test_len, type, option);
+ }
+ else
+ {
+ Log(("psembed: error: cannot embed data, 'PostScript 2' not supported as embedded data format for this printer\n"));
+ }
+ }
+#endif /* DO_EMBED_TEST */
+
+ XpEndPage(pdpy);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndPageNotify);
+ Log(("end page.\n"));
+
+#ifdef DO_SOME_MORE_RENDERING
+ XpStartPage(pdpy);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPStartPageNotify);
+
+ /* some more rendering..... */
+
+ XpEndPage(pdpy);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndPageNotify);
+#endif /* DO_SOME_MORE_RENDERING */
+
+#ifdef MULTIPLE_DOCUMENTS_IN_ONE_JOB
+ /* End document. Do _not_ use it if you did not explicitly used
+ * XpStartDoc() above (e.g. if XpStartDoc() was triggered by first
+ * XpStartPage() - see comment about XpStartDoc() above...
+ */
+ XpEndDoc(pdpy);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndDocNotify);
+#endif /* MULTIPLE_DOCUMENTS_IN_ONE_JOB */
+
+ /* End the print job - the final results are sent by the X print
+ * server to the spooler sub system.
+ */
+ XpEndJob(pdpy);
+ XpuWaitForPrintNotify(pdpy, xp_event_base, XPEndJobNotify);
+ Log(("end job.\n"));
+
+ if( printerfile )
+ {
+ if( XpuWaitForPrintFileChild(printtofile_handle) != XPGetDocFinished )
+ {
+ fprintf(stderr, "%s: Error while printing to file.\n", ProgramName);
+ XpuClosePrinterDisplay(pdpy, pcontext);
+ return(EXIT_FAILURE);
+ }
+ }
+
+ XpuClosePrinterDisplay(pdpy, pcontext);
+ return(EXIT_SUCCESS);
+}
+
+int main (int argc, char *argv[])
+{
+ const char *printername = NULL; /* printer to query */
+ const char *toFile = NULL; /* output file (instead of printer) */
+ const char *embedpsl2data = NULL; /* PS Level 2 code fragment for embedding in output */
+ XPPrinterList plist; /* list of printers */
+ int plist_count; /* number of entries in |plist|-array */
+ int i;
+ int retval;
+
+ ProgramName = argv[0];
+
+ for (i = 1; i < argc; i++)
+ {
+ char *arg = argv[i];
+ int len = strlen(arg);
+
+ if (!strncmp("-printer", arg, len))
+ {
+ if (++i >= argc)
+ usage();
+ printername = argv[i];
+ }
+ else if (!strncmp("-printfile", arg, len))
+ {
+ if (++i >= argc)
+ usage();
+ toFile = argv[i];
+ }
+ else if (!strncmp("-embedpsl2data", arg, len))
+ {
+ if (++i >= argc)
+ usage();
+ embedpsl2data = argv[i];
+ }
+ else if (!strncmp("-v", arg, len))
+ {
+ verbose = True;
+ }
+ else
+ {
+ usage();
+ }
+ }
+
+ plist = XpuGetPrinterList(printername, &plist_count);
+
+ if (!plist) {
+ fprintf(stderr, "%s: no printers found for printer spec \"%s\".\n",
+ ProgramName, NULLSTR(printername));
+ exit(EXIT_FAILURE);
+ }
+
+ Log(("Using printer '%s'\n", plist[0].name));
+
+ retval = do_hello_world(plist[0].name, toFile, embedpsl2data);
+
+ XpuFreePrinterList(plist);
+
+ return(retval);
+}
+
+