home *** CD-ROM | disk | FTP | other *** search
/ WordPerfect for Linux Bible / WP4LinuxBible.iso / sdk / wpc / code / unixtpi.c next >
C/C++ Source or Header  |  1999-06-25  |  10KB  |  388 lines

  1. /** Sample third-party interface, loaded from the "third.ini" file **/
  2.  
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include "unixtpi.h"
  8.  
  9. #define WRULER        0x6f
  10. #define WPRTSLC        0xcf
  11. #define FUNCT        0x80
  12. #define DUP            0x40
  13.  
  14. static unsigned char buf[256];
  15. static char macbuf[2048];
  16. static int fd;
  17. static int in,out;
  18.  
  19. static int system = 0;
  20. static int sysoff = 0;
  21.  
  22. /* data for xwp */
  23. static char amessage[] = "You pressed the Ctrl-Shift-3 key!";
  24.  
  25.  
  26. /* data for wp */
  27. static char msg[] = {
  28.     0, 0,        /* space for the length - calculated as needed */
  29.     0, 0, 0, 0,    /* space for state */
  30.     'Y', 0,    'o', 0,    'u', 0, ' ', 0,
  31.     'p', 0,    'r', 0,    'e', 0,    's', 0,
  32.     's', 0,    'e', 0,    'd', 0,    ' ', 0,
  33.     't', 0,    'h', 0,    'e', 0,    ' ', 0,
  34.     'C', 0,    't', 0,    'r', 0,    'l', 0,
  35.     '-', 0,    'S', 0,    'h', 0,    'i', 0,
  36.     'f', 0,    't', 0,    '-', 0,    '3', 0,
  37.     ' ', 0,    'k', 0,    'e', 0,    'y', 0,
  38.     '!', 0, 0 ,0
  39. };
  40.  
  41. static char Alt_F4[] = {
  42.     12, 0,            /* length */
  43.     0,0,0,0,        /* state */
  44.     0xd, 0xfc,        /* display on */
  45.     0x32,0x80,        /* Print key */
  46.     'S',0,            /* "Select" */
  47.     0, 0            /* NULL terminate macro */
  48. };
  49.  
  50. static char Menu_number[] = {
  51.     14, 0,            /* length */
  52.     0,0,0,0,        /* state */
  53.     0x35, 0xfc,        /* SYSTEM macro command */
  54.     '1', 0,            /* SYSTEM variable number */
  55.     '3', 0,            /* SYSTEM variable number */
  56.     '~', 0,            /* end of SYSTEM command */
  57.     0, 0            /* NULL terminate macro */
  58. };
  59.  
  60. static char Menu_prompt[] = {
  61.     46, 0,          /* length */
  62.     0,0,0,0,        /* state */
  63.     0xd, 0xfc,        /* display on */
  64.     0x1f, 0xfc,        /* PROMPT command */
  65.     0x10, 0x80,        /* PROMPT POSITION command */
  66.     0x01, 0x80,        /* column */
  67.     0x01, 0x80,     /* row */
  68.     'M', 0,
  69.     'e', 0,
  70.     'n', 0,
  71.     'u', 0,
  72.     ' ', 0,
  73.     '=', 0,
  74.     ' ', 0,
  75.     ' ', 0,
  76.     ' ', 0,
  77.     ' ', 0,
  78.     ' ', 0,
  79.     ' ', 0,
  80.     ' ', 0,
  81.     ' ', 0,
  82.     ' ', 0,
  83.     0,0                /* NULL terminate macro */
  84. };
  85.  
  86. /* convert 4 bytes in Intel order into an unsigned int (32 bits) */
  87. unsigned long BtoI(b)
  88. unsigned char *b;
  89. {
  90.     unsigned long val;
  91.  
  92.     val = *b++;
  93.     val += (unsigned int)*b++ << 8;
  94.     val += (unsigned int)*b++ << 16;
  95.     val += (unsigned int)*b << 24;
  96.     return val;
  97. }
  98.  
  99. /********************************************************************
  100.  * Function: bread                                                  *
  101.  *                                                                  *
  102.  * WordPerfect 5.1 doesn't put information in the pipe all at once. *
  103.  * It will get some information, put it in the pipe, get the next   *
  104.  * piece of information, put it in the pipe, and so on.             *
  105.  *                                                                  *
  106.  * WP 5.1 may do several "gets" to produce one buffer.  Because of  *
  107.  * this, your TPI program should NEVER read the pipe directly.  If  *
  108.  * it does, you will never have a complete buffer to read from and  *
  109.  * you will not know which part of the current buffer you are       *
  110.  * getting the information for.                                     *
  111.  *                                                                  *
  112.  * The function "bread" has been provided for this purpose.  This   *
  113.  * function will gather the size of the current buffer and will     *
  114.  * return the information for a buffer only when the buffer is      *
  115.  * complete.  Your program should always use this function.         *
  116.  ********************************************************************/
  117. /* read cnt bytes from file decriptor fd */
  118. bread(fd,buf,cnt)
  119. int fd,cnt;
  120. char *buf;
  121. {
  122.     int br = 0;
  123.  
  124.     for (;;) {
  125.         br += read(fd,buf+br,cnt-br);    /* read bytes */
  126.         if (br == cnt) {                /* did we get them all ? */
  127.             break;                        /* yes - return */
  128.         }                                /* no - loop for another read */
  129.     }
  130. }
  131.  
  132. /* convert a character string to 2 byte tokens */
  133. char *str2tok(str,len)
  134. char *str;
  135. int *len;
  136. {
  137.     static char *buf = 0;
  138.     char *calloc();
  139.     int i;
  140.     char *tptr;
  141.  
  142.     if (buf) {
  143.         free(buf);    /* free the previous malloc if needed */
  144.     }
  145.  
  146.     *len = 2*strlen(str);
  147.  
  148.     buf = calloc(*len,1);
  149.     tptr = buf;
  150.     
  151.     for (i=0;i<strlen(str);i++) {
  152.         *tptr++ = str[i];
  153.         tptr++;
  154.     }
  155.  
  156.     return buf;
  157. }
  158.  
  159. /* return a character unchanged to WP */
  160. sendback()
  161. {
  162.     write(out,buf,8);
  163. }
  164.  
  165. main(argc,argv)
  166. char *argv[];
  167. {
  168.     int cnt,i,gui,len;
  169.     char *tptr;
  170.     unsigned long fsize, macoff, state;
  171.  
  172.     in = atoi(argv[1]);        /* get the input file descriptor */
  173.     out = atoi(argv[2]);    /* get the output file descriptor */
  174.  
  175.     bread(in,buf,2);    /* read the length field from the first packet */
  176.  
  177.     cnt = buf[0] + ((int)buf[1] << 8);    /* read the intialization packet */
  178.     bread(in,buf+2,cnt);                /* it is cnt bytes long */
  179.  
  180.     /* return a packet to let the WPApp know we are here */
  181.     len = buf[8] + ((int)buf[9] << 8);
  182.  
  183.     /* determine if WP is character or GUI version */
  184.     gui = buf[10+len] == 1;
  185.  
  186.     if (gui) {            /* message from xwp ? */
  187.                         /* yes */
  188.         buf[2] = 2;        /* token lower bound (lo byte) */
  189.         buf[3] = 0xfe;    /* token lower bound (hi byte) */
  190.         buf[4] = 7;        /* token upper bound (lo byte) */
  191.         buf[5] = 0xfe;    /* token upper bound (hi byte) */
  192.     }
  193.     else {
  194.                         /* from character wp */
  195.         buf[2] = 0x1;    /* token lower bound (lo byte) */
  196.         buf[3] = 0xff;    /* token lower bound (hi byte) */
  197.         buf[4] = 0x5;    /* token upper bound (lo byte) */
  198.         buf[5] = 0xff;    /* token upper bound (hi byte) */
  199.     }
  200.     buf[0] = 4;                /* length of return packet (lo byte) */
  201.     buf[1] = 0;             /* length of return packet (hi byte) */
  202.     write(out,buf,6);        /* send the packet */
  203.  
  204.     for (;;) {        /* handle tokens */
  205.         bread(in,buf,2);                    /* read the count bytes */
  206.         cnt = buf[0] + ((int)(buf[1]) << 8);
  207.         bread(in,buf+2,cnt);                /* read the rest of the packet */
  208.  
  209.         state = BtoI(buf+2);                /* get WP state */
  210.  
  211.         if (state == EXITING) {            /* Is WP about to exit ? */
  212.             exit(0);                    /* yes - exit now */
  213.         }
  214.  
  215.         if (cnt == 6) {        /* regular characters */
  216.             if (gui) {        /* this branch is for GUI wp (xwp) */
  217.                 if (buf[7] == 0xfe) {    /* Ctrl-Shift-# key ? */
  218.                     switch (buf[6]) {    /* yes */
  219.                         case 2:            /* Ctrl-Shift-1 */
  220.                                         /* Enter an 'A' */
  221.                             buf[0] = 6;
  222.                             buf[1] = 0;
  223.                             buf[6] = 'A';
  224.                             buf[7] = 0;
  225.                             write(out,buf,8);
  226.                             break;
  227.  
  228.                         case 4:            /* Ctrl-Shift-3 */
  229.                                         /* send back a string */
  230.                             tptr = str2tok(amessage,&len);
  231.                             memcpy(buf+6,tptr,len);
  232.                             buf[0] = len+4;
  233.                             buf[1] = 0;
  234.                             write(out,buf,len+6);
  235.                             break;
  236.  
  237.                         case 5:        /* Ctrl-Shift-4 */
  238.                                     /* Printer Select Dialog */
  239.                             buf[0] = 6;
  240.                             buf[1] = 0;
  241.                             buf[6] = WPRTSLC;
  242.                             buf[7] = DUP;
  243.                             write(out,buf,8);
  244.                             break;
  245.  
  246.                         case 6:            /* Ctrl-Shift-5 */
  247.                                         /* execute hex conversion macro */
  248.                             fd = open("unixtest.wgm",O_RDONLY);
  249.                             if (fd != -1) {
  250.                                 bread(fd,macbuf,8);
  251.                                 macoff = BtoI(macbuf+4);
  252.                                 fsize = lseek(fd,0L,SEEK_END);
  253.                                 fsize -= macoff;
  254.                                 lseek(fd,macoff,SEEK_SET);    
  255.                                 bread(fd,macbuf+6,fsize);
  256.                                 macbuf[0] = (fsize+4) & 0xff;
  257.                                 macbuf[1] = ((fsize+4) >> 8) & 0xff;
  258.                                 macbuf[2] = buf[2];
  259.                                 macbuf[3] = buf[3];
  260.                                 macbuf[4] = buf[4];
  261.                                 macbuf[5] = buf[5];
  262.                                 write(out,macbuf,fsize+6);
  263.                                 break;
  264.                             }
  265.                             /* fall through and send it back if the open failed */
  266.                         default:    /* keys we don't care about */
  267.                         case 3:    /* Ctrl-Shift-2 */
  268.                             sendback();
  269.                             break;
  270.  
  271.                         case 7:            /* Ctrl-Shift-6 */
  272.                                         /* toggle the ruler */
  273.                             buf[0] = 8;    
  274.                             buf[1] = 0;
  275.                             buf[6] = WRULER;
  276.                             buf[7] = FUNCT;
  277.                             buf[8] = buf[9] = 0;
  278.                             write(out,buf,10);
  279.                             break;
  280.                     }
  281.                 }
  282.                 else {
  283.                     sendback();
  284.                 }
  285.             }
  286.             else {        /* character branch */
  287.                 if (system) {    /* in the process of saving a system var ? */
  288.                     if (!(state & MACEXE)) {    /* done ? */
  289.                                                 /* yes */
  290.                         write(out,Menu_prompt,sizeof(Menu_prompt));
  291.                         system = 0;
  292.                     }
  293.                     else if (state & POLLING) {
  294.                         buf[0] = 4;
  295.                         buf[1] = 0;
  296.                         write(out,buf,6);
  297.                         continue;
  298.                     }
  299.                     else if (buf[7] <= 0x0d) {            /* regular char */
  300.                         Menu_prompt[sysoff] = buf[6];    /* save the character */
  301.                         sysoff += 2;
  302.                         buf[0] = 4;        /* tell WP it's deleted */
  303.                         buf[1] = 0;
  304.                         write(out,buf,6);
  305.                     }
  306.                     else {            /* send back everything but chars */
  307.                         sendback();
  308.                     }
  309.                 }
  310.                 else if (state & POLLING) {
  311.                     buf[0] = 4;
  312.                     buf[1] = 0;
  313.                     write(out,buf,6);
  314.                     continue;
  315.                 }
  316.                 else if (state & MACEXE) {
  317.                     sendback();
  318.                 }
  319.                 else if (buf[7] == 0xff) {    /* Ctrl-Shift-# key ? */
  320.                     switch (buf[6]) {        /* yes */
  321.                         case 1:                /* Ctrl-Shift-1 */
  322.                                             /* Enter an 'A' */
  323.                             buf[0] = 6;
  324.                             buf[1] = 0;
  325.                             buf[6] = 'A';
  326.                             buf[7] = 0;
  327.                             write(out,buf,8);
  328.                             break;
  329.  
  330.                         case 2:    /* Ctrl-Shift-2 */
  331.                                 /* display value of SYSTEM menu variable */
  332.                             for (i=0;i<8;i++) {
  333.                                 Menu_prompt[(2*i)+30] = ' ';
  334.                             }
  335.                             system = 1;        /* getting value of system var */
  336.                             sysoff = 30;
  337.                             write(out,Menu_number,sizeof(Menu_number));
  338.                             break;
  339.  
  340.                         case 3:    /* Ctrl-Shift-3 */
  341.                                 /* send back a string */
  342.                             msg[0] = sizeof(msg) - 2;
  343.                             write(out,msg,sizeof(msg));
  344.                             break;
  345.  
  346.                         case 4:    /* Ctrl-Shift-4 */
  347.                                 /* Printer Select Dialog */
  348.                             write(out,Alt_F4,sizeof(Alt_F4));
  349.                             break;
  350.  
  351.                         case 5:    /* Ctrl-Shift-5 */
  352.                                 /* execute hex conversion macro */
  353.                             fd = open("unixtest.wpm",O_RDONLY);
  354.                             if (fd != -1) {
  355.                                 bread(fd,macbuf,8);
  356.                                 macoff = BtoI(macbuf+4);
  357.                                 fsize = lseek(fd,0L,SEEK_END);
  358.                                 fsize -= macoff;
  359.                                 lseek(fd,macoff,SEEK_SET);
  360.                                 bread(fd,macbuf+8,fsize);
  361.                                 fsize += 6;    /* two bytes for display on code */
  362.                                             /* and 4 for state bytes */
  363.                                 macbuf[0] = fsize & 0xff;
  364.                                 macbuf[1] = (fsize >> 8) & 0xff;
  365.                                 macbuf[6] = 0xd;    /* force display on */
  366.                                 macbuf[7] = 0xfc;
  367.                                 write(out,macbuf,fsize+2);
  368.                                 break;
  369.                             }
  370.                         /* fall through and send it back if the open failed */
  371.                         default:    /* keys we don't care about */
  372.                             sendback();
  373.                             break;
  374.                     }
  375.                 }
  376.                 else {
  377.                     sendback();
  378.                 }
  379.             }
  380.         }
  381.         else {
  382.             /* not a regular character - send buffer back unchanged */
  383.             write(out,buf+2,cnt+2);
  384.         }
  385.     }
  386. }
  387.  
  388.