home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff290.lzh / IPC / Sources / FormatClient.c < prev    next >
C/C++ Source or Header  |  1989-12-11  |  12KB  |  329 lines

  1. /************************************************************
  2.  *                                                          *
  3.  *        Minimal Print server Client Demo for IPC          *
  4.  *                                                          *
  5.  *          -- Shared Library Version --                    *
  6.  *                                                          *
  7.  *                Pete Goodeve 89:11:27                     *
  8.  *                                                          *
  9.  *  [This module has only been compiled under Lattice;      *
  10.  *   it will need some modification for Manx/Aztec;         *
  11.  *   ... I'd be very grateful if someone would do the       *
  12.  *   conversion...]                                         *
  13.  *                                                          *
  14.  *                                                          *
  15.  *  This is a simple test module for the "Print Format"     *
  16.  *  server.  When you type the return key, it generates     *
  17.  *  a message with a set of items in various formats,       *
  18.  *  and sends it to the print server. (For test purposes    *
  19.  *  the items are fixed.)  If you simply type a return,     *
  20.  *  the formatted string generated from the message is      *
  21.  *  displayed in the print server's own window; if you      *
  22.  *  type an 'F' before the return, a file handle to this    *
  23.  *  Client program's console window is passed in the        *
  24.  *  message and the string will be output to this instead;  *
  25.  *  if you type an 'M' before the return, the string will   *
  26.  *  be passed back in the reply message and again shown     *
  27.  *  in the Client's console window.                         *
  28.  *                                                          *
  29.  *  Typing 'Q' will send a 'QUIT' message to the server     *
  30.  *  instead of a print request.  To exit the client         *
  31.  *  program type an 'end-of-file' (cntrl-'\'); the          *
  32.  *  print server is currently programmed to exit also       *
  33.  *  when there are no running clients left.                 *
  34.  *                                                          *
  35.  *  It is a simple "synchronous" client: when it sends a    *
  36.  *  message it waits for the reply before continuing        *
  37.  *  (unlike others that may continue with other activities  *
  38.  *  while the server is processing a message).  The main    *
  39.  *  loop is simple:                                         *
  40.  *                                                          *
  41.  *          Wait for keyboard command                       *
  42.  *          Send message                                    *
  43.  *          Wait for reply                                  *
  44.  *          Display string from reply if supplied           *
  45.  *          Loop to wait for keyboard again.                *
  46.  *                                                          *
  47.  *                                                          *
  48.  ************************************************************/
  49.  
  50. #ifdef LATTICE
  51. #if LATTICE_40 | LATTICE_50
  52. #include "IPC_proto.h"
  53. /* ...else (not recent Lattice) will need library linkage stubs (IPC.o) */
  54. #endif
  55. #endif
  56.  
  57. #include "IPC.h"
  58. #include "exec/memory.h"
  59.  
  60. #define LINESZ 120
  61. #define SHOWREAL 1
  62.  
  63. /*
  64.  *  Define the ID codes recognized by the print format server
  65.  *
  66.  *  (MAKE_ID is defined in IPC.h)
  67.  */
  68.  
  69. /* Message IDs: */
  70. #define CNVA  MAKE_ID('C','N','V','A')
  71.     /* CoNVert to Ascii */
  72. #define QUIT  MAKE_ID('Q','U','I','T')
  73.  
  74. /* Item IDs: */
  75. #define RETS  MAKE_ID('R','E','T','S')
  76.     /* RETurn String */
  77.  
  78. #define FILH  MAKE_ID('F','I','L','H')
  79.     /* FILe Handle */
  80.  
  81.  
  82. #define PATS  MAKE_ID('P','A','T','S')
  83.     /* PATtern String */
  84.  
  85. #define PAT1  MAKE_ID('P','A','T','1')
  86.     /* PATtern -- 1 item */
  87.  
  88. #define LINE  MAKE_ID('L','I','N','E')
  89.     /* indicates a complete line of text -- omitting newline */
  90.  
  91. #define TEXT  MAKE_ID('T','E','X','T')
  92.     /* Text block -- may include newlines */
  93.  
  94. #define STRG  MAKE_ID('S','T','R','G')
  95.     /* general non-specific ASCII STRinG */
  96.  
  97.     /* The above three categories are treated identically by Pserver
  98.        -- they may have distinct meanings to other servers */
  99.  
  100. #define CHAR  MAKE_ID('C','H','A','R')
  101.     /* A single character in L.S byte of ii_Ptr */
  102.  
  103. #define INTG  MAKE_ID('I','N','T','G')
  104.     /* A 32-bit INTeGer in ii_Ptr */
  105.  
  106. #define REAL  MAKE_ID('R','E','A','L')
  107.     /* A 32-bit floating point value in ii_Ptr (care in conversion!) */
  108.  
  109.  
  110. /*******************
  111. rather than the above if you prefer, with Lattice 4.0 you can simply
  112. use 4-character constants as in the following (compile with the -cm option):
  113.  
  114. #define CNVA 'CNVA'
  115. #define QUIT 'QUIT'
  116.  
  117. #define RETS 'RETS'
  118. #define FILH 'FILH'
  119.  
  120. #define PATS 'PATS'
  121. #define PAT1 'PAT1'
  122. #define LINE 'LINE'
  123. #define TEXT 'TEXT'
  124. #define STRG 'STRG'
  125. #define CHAR 'CHAR'
  126. #define INTG 'INTG'
  127. #define REAL 'REAL'
  128. *********************/
  129.  
  130. APTR IPCBase = NULL;
  131.  
  132. struct IPCPort *port=NULL; /* will point to server port */
  133. struct MsgPort *rport=NULL; /* where we get our replies */
  134. struct IPCMessage *imsg=NULL; /* this one message is used repeatedly */
  135.  
  136. struct MsgPort * CreatePort(char *, int);
  137. ULONG Output();
  138.  
  139. void Cleanup();
  140. void outputstr(char *);
  141.  
  142.  
  143. /***************************
  144.  *
  145.  *  Main program entry point:
  146.  *
  147.  *  -- Note that to save overhead we use '_main'; you should also compile
  148.  *  (under Lattice) using the -v switch, to suppress stack checking and
  149.  *  the associated baggage.
  150.  *
  151.  *  We avoid using any C level I/O also -- just AmigaDOS calls, so we
  152.  *  dont need <stdio.h>.
  153.  */
  154.  
  155. void _main()
  156. {
  157.     struct IPCItem *item, *item0; /* pointers to access message items */
  158.  
  159.     int count=0; /* dummy value used to stuff into message */
  160.     float realcount=0.0; /* -- ditto */
  161.  
  162.     char tbuf[22]; /* keyboard input dumped in here */
  163.  
  164.     /* Before anything else, we need the IPC Library: */
  165.     IPCBase = (APTR)OpenLibrary("ppipc.library",0);
  166.     if (!IPCBase) {
  167.         outputstr(
  168.         "Couldn't find ppipc.library!\nHave you installed it in LIBS: ?\n");
  169.         _exit(20);
  170.     }
  171.  
  172.     /* First we set up our ports: */
  173.  
  174.     port = LoadIPCPort("Print_Format"); /* try the Port Broker first */
  175.     if (!port)  /* gimmicked so it can be used with or without Broker */
  176.         port = GetIPCPort("Print_Format");
  177.     if (!port) {Cleanup(); _exit(21);}
  178.  
  179.     rport = CreatePort(NULL,0);
  180.     if (!rport) {Cleanup(); _exit(21);}
  181.  
  182.     /* ... then make a message block */
  183.     imsg = CreateIPCMsg(20,0,rport); /* large enough for playing with... */
  184.     if (!imsg) {Cleanup(); _exit(22);}
  185.  
  186.     item0 = &imsg->ipc_Items[0]; /* a convenient permanent reference */
  187.  
  188.  
  189.     /* The main program loop:
  190.      * -- continues until told to quit by end-of-file (ctrl-\)
  191.      */
  192.     while (1) {
  193.         item = item0; /* reset item pointer */
  194.         imsg->ipc_Id = CNVA; /* only message ID needed (except QUIT) */
  195.             /*
  196.              * Initially we assume that the first item will be a slot
  197.              * in which the server will return the formatted string.
  198.              * This will be overwritten if another option is chosen
  199.              */
  200.         item->ii_Id = RETS;
  201.         item->ii_Ptr = NULL; /* The server will provide the data block */
  202.         item->ii_Size = 0;
  203.         item->ii_Flags = imsg->ipc_Flags = 0;
  204.  
  205.         /* get keyboard input (terminated by return): */
  206.         /* E-O-F returns a length of zero, causing break from loop */
  207.         if (Read(Input(), tbuf, 21) <= 0) break;
  208.  
  209.         /*
  210.          * decode first character of input to decide action
  211.          *  (sorry about the crudity... but it suffices)
  212.          */
  213.         switch(*tbuf) {
  214.         case 'Q':   /* Send a QUIT message */
  215.         case 'q':
  216.         case '.':   imsg->ipc_Id = QUIT; /* all items are ignored */
  217.                     break;
  218.  
  219.         case 'm':   /* Request string in reply Message */
  220.         case 'M':
  221.         case '?':   item++; /* leave default RETS in place */
  222.                     item->ii_Id = STRG; /* Add in a string item to
  223.                                            distinguish displayed line */
  224.                     item->ii_Ptr = (void *)("Returned: ");
  225.                     item++;
  226.                     break;
  227.  
  228.         case 'F':   /* Pass File handle to this console */
  229.         case 'f':
  230.         case '^':   item->ii_Id = FILH; /* overwrites RETS */
  231.                     item++->ii_Ptr = (void *)Output(); /* the file handle */
  232.                     break;
  233.  
  234.         default:    /* anything else just overwrites RETS with output
  235.                        items, so string appears on Pserver window */
  236.                     break;
  237.         }
  238.  
  239.         /*
  240.          * The rest of the setup code simply stuffs a few values of
  241.          * different types into successive items -- rearrange to your
  242.          * own satisfaction...
  243.          * NOTE that we haven't bothered to put the strings into public
  244.          * memory, contrary to the suggestions of the IPC standard
  245.          *  [For shame, Peter!] but this is really only a restriction
  246.          * that needs to be observed for general messages that may have
  247.          * a destination outside the ken of the sender (or for a future
  248.          * machine that has process-private memory).  This isn't relevant
  249.          * to such a simple test program, so we've simplified things.
  250.          * At the same time, the ii_Size field for the string items is
  251.          * set to ZERO, indicating that the "data block" is Read-Only
  252.          * as far as the server is concerned.
  253.          */
  254.         item->ii_Id = STRG; /* A short string to start out with */
  255.         item->ii_Ptr = (void *)("Test line...");
  256.         item++;
  257.         item->ii_Id = PAT1; /* then a format specifier for a value */
  258.         item->ii_Ptr = (void *)(" #%3d");
  259.         item++;
  260.         item->ii_Id = INTG; /* the integer value to be formatted */
  261.         item->ii_Ptr = (void *)(count++); /* (just a sequential count...) */
  262.         item++;
  263.         item->ii_Id = STRG; /* another string... */
  264.         item->ii_Ptr = (void *)("... value=");
  265.         item++;
  266.         item->ii_Id = REAL; /* A float value in default format */
  267.             /* note the messy conversion to get it into the ii_Ptr field */
  268.         *(float *) &item->ii_Ptr = (realcount += 1.234);
  269.         item++;
  270.         item->ii_Id = CHAR; /* and a newline character to end the section */
  271.         item->ii_Ptr = (void *)('\n');
  272.         item++;
  273.         item->ii_Id = PATS; /* Multi item format specifier */
  274.         item->ii_Ptr = (void *)("formatted line #%2d %s\n");
  275.         item++;
  276.         item->ii_Id = INTG;
  277.         item->ii_Ptr = (void *)(count++);
  278.         item++;
  279.         item->ii_Id = STRG;
  280.         item->ii_Ptr = (void *)((count & 3) ? "..." : "tick...");
  281.         /* no more items allowed after PATS is satisfied */
  282.  
  283.         /* set actual ItemCount into message: */
  284.         imsg->ipc_ItemCount = item - item0 + 1;
  285.  
  286.         /* Send the message (if possible) */
  287.         if (!PutIPCMsg(port, imsg)) {
  288.                 outputstr("No server!\n");
  289.                 continue; /* don't wait for a reply that won't come! */
  290.         }
  291.         /* Wait at the reply port: */
  292.         WaitPort(rport);
  293.         GetMsg(rport);  /* we assume we know what's there! */
  294.         if (imsg->ipc_Flags & IPC_NOTKNOWN)
  295.             outputstr("Server barfed\n");
  296.         /*
  297.          * If we asked for a return string, display it in our
  298.          * window, then dispose of the block of memory passed to us
  299.          * by the server:
  300.          */
  301.         if (item0->ii_Id == RETS) {
  302.             Write(Output(), item0->ii_Ptr, strlen(item0->ii_Ptr));
  303.             /* note that we DON'T use the ii_Size value above!
  304.                There is no guarantee that it is exactly the size of
  305.                the string. */
  306.             FreeMem(item0->ii_Ptr, item0->ii_Size);
  307.         }
  308.     }
  309.     /*** end of main loop ***/
  310.  
  311.     Cleanup();
  312. }
  313.  
  314.  
  315. void Cleanup()
  316. {
  317.     if (port) DropIPCPort(port);
  318.     if (rport) DeletePort(rport);
  319.     if (imsg) DeleteIPCMsg(imsg);
  320.     CloseLibrary(IPCBase);
  321. }
  322.  
  323.  
  324. void outputstr(str) char *str;
  325. {
  326.     Write(Output(), str, strlen(str));
  327. }
  328.  
  329.