MSNULL.C
上传用户:yuandong
上传日期:2022-08-08
资源大小:954k
文件大小:22k
源码类别:

Delphi控件源码

开发平台:

C++ Builder

  1. /*++
  2. Copyright (c) 1990-1994  Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5.     MsNull.c
  6. Abstract:
  7.     Implements lanman's msnull type parsing for FFs.
  8. Author:
  9. Environment:
  10.     User Mode -Win32
  11. Revision History:
  12. --*/
  13. #include <windows.h>
  14. #include "winprint.h"
  15. #include "msnull.h"
  16. #define sgn(x) (((x)>0) ? 1:-1)
  17. struct EscapeSequence EscapeStrings[] =
  18.     {
  19.         { "-",prdg_ActConstIgnore, 1},
  20.         { "0",prdg_ActNull,0},
  21.         { "1",prdg_ActNull,0},
  22.         { "2",prdg_ActNull,0},
  23.         { "3",prdg_ActConstIgnore, 1},
  24.         { "4",prdg_ActNull,0},
  25.         { "5",prdg_ActConstIgnore, 1},
  26.         { "6",prdg_ActNull,0},
  27.         { "7",prdg_ActNull,0},
  28.         { ":",prdg_ActNull,0},
  29.         { "=",prdg_ActNull,0},
  30.         { "A",prdg_ActConstIgnore, 1},
  31.         { "B",prdg_ActDelimited, ''},
  32.         { "C",prdg_ActConstIgnore, 1},
  33.         { "D",prdg_ActDelimited, ''},
  34.         { "E",prdg_ActReset,0},
  35.         { "F",prdg_ActNull,0},
  36.         { "G",prdg_ActNull,0},
  37.         { "H",prdg_ActNull,0},
  38.         { "I",prdg_ActConstIgnore, 1},
  39.         { "J",prdg_ActConstIgnore, 1},
  40.         { "K",prdg_ActCountIgnore, 0},
  41.         { "L",prdg_ActCountIgnore, 0},
  42.         { "N",prdg_ActConstIgnore, 1},
  43.         { "O",prdg_ActNull,0},
  44.         { "P",prdg_ActConstIgnore, 1},
  45.         { "Q",prdg_ActConstIgnore, 1},
  46.         { "R",prdg_ActNull,0},
  47.         { "S",prdg_ActConstIgnore, 1},
  48.         { "T",prdg_ActNull,0},
  49.         { "U",prdg_ActConstIgnore, 1},
  50.         { "W",prdg_ActConstIgnore, 1},
  51.         { "X",prdg_ActConstIgnore, 2},
  52.         { "Y",prdg_ActCountIgnore, 0},
  53.         { "Z",prdg_ActCountIgnore, 0},
  54.         { "[@",prdg_ActCountIgnore, 0},
  55.         { "[C",prdg_ActCountIgnore, 0},
  56.         { "[F",prdg_ActCountIgnore, 0},
  57.         { "[I",prdg_ActCountIgnore, 0},
  58.         { "[S",prdg_ActCountIgnore, 0},
  59.         { "[T",prdg_ActCountIgnore, 0},
  60.         { "[\",prdg_ActCountIgnore, 0},
  61.         { "[g",prdg_ActCountIgnore, 0},
  62.         { "\",prdg_ActCountIgnore, 0},
  63.         { "]",prdg_ActNull,0},
  64.         { "^",prdg_ActNull,0},
  65.         { "_",prdg_ActConstIgnore, 1},
  66.         { "d",prdg_ActConstIgnore, 2},
  67.         { "e",prdg_ActConstIgnore, 2},
  68.         { "j",prdg_ActNull,0},
  69.         { "n",prdg_ActNull,0},
  70.         { "x6f", prdg_ActFF, 0}
  71.     };
  72. VOID
  73. CheckFormFeedStream(
  74.     lpDCI           pDCIData,
  75.     unsigned char   inch)
  76. /**********************************************************************/
  77. /*                                                                    */
  78. /*   FUNCTION: prdg_ParseRawData                                      */
  79. /*                                                                    */
  80. /*   PARAMETERS:                                                      */
  81. /*                                                                    */
  82. /*   lpDCI           pDCIData;  Pointer to DC instance data           */
  83. /*   unsigned char   inch;     The next byte in data stream           */
  84. /*                                                                    */
  85. /*   DESCRIPTION:                                                     */
  86. /*                                                                    */
  87. /*   This function parses the stream of raw data which is being       */
  88. /*   passed to the printer so that the driver can handle form feeds   */
  89. /*   correctly.  The function must follow all the escape sequences    */
  90. /*   which occur in the sequence of raw data.                         */
  91. /*                                                                    */
  92. /*   CHANGES:                                                         */
  93. /*                                                                    */
  94. /*   This function is table driven (from the table in in the ddata    */
  95. /*   module) so it should hopefully only require this to be changed   */
  96. /*   to reflect the escape sequences for a different printer.  If     */
  97. /*   however there are escape sequneces which don't fall into the     */
  98. /*   categories this parser can handle then extra code will have      */
  99. /*   to be written to handle them.  The parser can handle escape      */
  100. /*   sequences with any number of unique identifying characters       */
  101. /*   possibly followed by: a count then the number of charcters given */
  102. /*   in the count; a fixed number of characters; a stream of          */
  103. /*   characters followed by a delimeter.                              */
  104. /*                                                                    */
  105. /**********************************************************************/
  106. {
  107.     /******************************************************************/
  108.     /* Local Variables                                                */
  109.     /******************************************************************/
  110.     INT                    Direction;   /* Variables used in the      */
  111.     UINT                   HiIndex;     /* binary chop routine for    */
  112.     UINT                   LoIndex;     /* searching for a matching   */
  113.     UINT                   Index;       /* escape sequence            */
  114.     UINT                   PrevIndex;
  115.     char *                 optr;        /* Pointers to access the     */
  116.     char *                 nptr;        /* escape sequence strings    */
  117.     struct EscapeSequence *NewSequence; /* Pointer to an escape       */
  118.                                         /* sequence                   */
  119.     /******************************************************************/
  120.     /* Process the input character through the parsing function.      */
  121.     /* Switch depending on which state we are currently in.  One of   */
  122.     /* prdg_Text, prdg_ESC_match, prdg_ESC_n_ignore, prdg_ESC_d_ignore*/
  123.     /* prdg_ESC_read_lo_count, prdg_ESC_read_hi_count.                */
  124.     /******************************************************************/
  125.     switch (pDCIData->ParserState)
  126.     {
  127.         case prdg_Text:
  128.             /**********************************************************/
  129.             /* Text state. Usual state, handled in line by a macro.   */
  130.             /* The code is included here for completeness only.       */
  131.             /* The FFaction (Form Feed action) state is maintained -  */
  132.             /* if the character is text (ie >= 0x20) then set it to   */
  133.             /* prdg_FFstate, if the character is a FF then set it to  */
  134.             /* prdg_FFx0c.  If the input character is an escape then  */
  135.             /* start up the sequence matching mode.                   */
  136.             /**********************************************************/
  137.             if (inch >= 0x20)
  138.                 pDCIData->FFstate = prdg_FFtext;
  139.             else if (inch == 0x0c)
  140.                 pDCIData->FFstate = prdg_FFx0c;
  141.             else if (inch == 0x1b)
  142.             {
  143.                 /******************************************************/
  144.                 /* The character is an escape so set ParserState and  */
  145.                 /* indicate we have not matched a sequence yet by     */
  146.                 /* setting ParserSequence to NULL.                    */
  147.                 /******************************************************/
  148.                 pDCIData->ParserState = prdg_ESC_match;
  149.                 pDCIData->ParserSequence = NULL;
  150.             }
  151.             break;
  152.         case prdg_ESC_match:
  153.             /**********************************************************/
  154.             /* Matching an escape sequence so try to match a new      */
  155.             /* character.                                             */
  156.             /**********************************************************/
  157.             if (!pDCIData->ParserSequence)
  158.             {
  159.                 /******************************************************/
  160.                 /* ParserSequence is NULL indicating that this is the */
  161.                 /* first character of an escape sequence so use a     */
  162.                 /* binary chop to get to the correct area of the      */
  163.                 /* table of escape sequences (based on the first      */
  164.                 /* character of the escape sequence which is the      */
  165.                 /* cuurent input character).                          */
  166.                 /******************************************************/
  167.                 HiIndex = MaxEscapeStrings;
  168.                 LoIndex = 0;
  169.                 Index = (LoIndex + HiIndex)/2;
  170.                 PrevIndex = MaxEscapeStrings;
  171.                 /******************************************************/
  172.                 /* while inch does not match the first character of   */
  173.                 /* the sequence indicated by Index move up or down    */
  174.                 /* the table depending on whether inch is < or > the  */
  175.                 /* first character of the escape sequence at Index.   */
  176.                 /******************************************************/
  177.                 while (Direction =
  178.                                (inch - *EscapeStrings[Index].ESCString))
  179.                 {
  180.                     if (Direction > 0)
  181.                     {
  182.                         LoIndex = Index;
  183.                     }
  184.                     else
  185.                     {
  186.                         HiIndex = Index;
  187.                     };
  188.                     PrevIndex = Index;
  189.                     if (PrevIndex == (Index = (LoIndex + HiIndex)/2))
  190.                     {
  191.                         /**********************************************/
  192.                         /* There is no escape sequence with a first   */
  193.                         /* character matching the current input       */
  194.                         /* character so resume text mode.             */
  195.                         /**********************************************/
  196.                         pDCIData->ParserState = prdg_Text;
  197.                         return;
  198.                     }
  199.                 }
  200.                 /*.. while (Direction = ...no match yet...............*/
  201.                 /******************************************************/
  202.                 /* Set up the ParserSequence and ParserString for the */
  203.                 /* first match found.                                 */
  204.                 /******************************************************/
  205.                 pDCIData->ParserSequence = &EscapeStrings[Index];
  206.                 pDCIData->ParserString = EscapeStrings[Index].ESCString;
  207.             };
  208.             /*.. if (!pDCIData->ParserSequence) .......................*/
  209.             /**********************************************************/
  210.             /* Loop forever trying to match escape sequences.         */
  211.             /* First, try the new character against the current       */
  212.             /* escape sequence and if it matches then check if it is  */
  213.             /* the end of the sequence and if it is switch to the     */
  214.             /* appropriate matching mode.  If the new character does  */
  215.             /* not match try the next escape sequence (in either      */
  216.             /* ascending or descending order depending on whether the */
  217.             /* current character was < or > the character we were     */
  218.             /* trying to match it to).  If the new sequence we are    */
  219.             /* trying to match against does not exist (ie we are at   */
  220.             /* one end of the table) or it does not match upto (but   */
  221.             /* not including) the position we are currently at then   */
  222.             /* the escape sequence in the raw data we are trying to   */
  223.             /* match is invalid so revert to prdg_Text mode.  If it   */
  224.             /* does match upto (but not including) the position we    */
  225.             /* are currently trying to match then go back to try and  */
  226.             /* match.                                                 */
  227.             /**********************************************************/
  228.             for (Direction = sgn(inch - *pDCIData->ParserString);;)
  229.             {
  230.                 /******************************************************/
  231.                 /* Partway along a sequence, try the new character and*/
  232.                 /* if it matches then check for end of string.        */
  233.                 /******************************************************/
  234.                 if (!(inch - *pDCIData->ParserString))
  235.                 {
  236.                     if (*++pDCIData->ParserString != '')
  237.                         /**********************************************/
  238.                         /* Escape sequence not finished yet so return */
  239.                         /* and wait for the next character.  Note that*/
  240.                         /* this is where the pointer to the position  */
  241.                         /* in the escape sequence we are checking is  */
  242.                         /* updated.                                   */
  243.                         /**********************************************/
  244.                         return;
  245.                     else
  246.                         /**********************************************/
  247.                         /* The escape sequence has matched till the   */
  248.                         /* end so break to the next section which will*/
  249.                         /* take the appropriate action.               */
  250.                         /**********************************************/
  251.                         break;
  252.                 }
  253.                 /*.. if (!(inch - *pDCIData->ParserString)) ...match...*/
  254.                 else
  255.                 {
  256.                     /**************************************************/
  257.                     /* The current sequence does not match so we must */
  258.                     /* try another sequence.  Direction determines    */
  259.                     /* which way in the table we should go.           */
  260.                     /**************************************************/
  261.                     NewSequence = pDCIData->ParserSequence + Direction;
  262.                     if (NewSequence < EscapeStrings ||
  263.                         NewSequence> &EscapeStrings[MaxEscapeStrings-1])
  264.                     {
  265.                         /**********************************************/
  266.                         /* The new sequence is beyond one end of the  */
  267.                         /* table so revert to prdg_Text mode because  */
  268.                         /* we will not be able to find a match.       */
  269.                         /**********************************************/
  270.                         pDCIData->ParserState = prdg_Text;
  271.                         return;
  272.                     }
  273.                     /**************************************************/
  274.                     /* Check that all the characters in the new       */
  275.                     /* escape sequence upto (but not including) the   */
  276.                     /* current one match the old escape sequence      */
  277.                     /* (because those characters from the old escape  */
  278.                     /* sequence have already been matched to the      */
  279.                     /* raw data).                                     */
  280.                     /**************************************************/
  281.                     for (optr=pDCIData->ParserSequence->ESCString,
  282.                          nptr=NewSequence->ESCString;
  283.                          optr<pDCIData->ParserString; ++optr,++nptr)
  284.                          if (*nptr != *optr)
  285.                          {
  286.                              /*****************************************/
  287.                              /* If the new sequence does not match the*/
  288.                              /* old then a match is not possible so   */
  289.                              /* return.                               */
  290.                              /*****************************************/
  291.                              pDCIData->ParserState = prdg_Text;
  292.                              return;
  293.                          }
  294.                     /**************************************************/
  295.                     /* The new sequence is correct upto the character */
  296.                     /* before the current character so loop back and  */
  297.                     /* check the current character.                   */
  298.                     /**************************************************/
  299.                     pDCIData->ParserSequence = NewSequence;
  300.                     pDCIData->ParserString = nptr;
  301.                 }
  302.                 /*.. else ! (!(inch - *pDCIData->ParserString.no match.*/
  303.             }
  304.             /*.. for ( ... ;;) ....for ever...........................*/
  305.             /**********************************************************/
  306.             /* The escape sequence has been matched from our table of */
  307.             /* escape sequences so take the appropriate action for    */
  308.             /* the particular sequence.                               */
  309.             /**********************************************************/
  310.             switch (pDCIData->ParserSequence->ESCAction)
  311.             {
  312.                 case prdg_ActNull:
  313.                     /**************************************************/
  314.                     /* No further action so revert to prdg_Text mode  */
  315.                     /**************************************************/
  316.                     pDCIData->ParserState = prdg_Text;
  317.                     break;
  318.                 case prdg_ActDelimited:
  319.                     /**************************************************/
  320.                     /* Ignore subsequent characters upto a specified  */
  321.                     /* delimeter.                                     */
  322.                     /**************************************************/
  323.                     pDCIData->ParserState = prdg_ESC_d_ignore;
  324.                     pDCIData->ParserDelimiter =
  325.                                (char)pDCIData->ParserSequence->ESCValue;
  326.                     break;
  327.                 case prdg_ActConstIgnore:
  328.                     /**************************************************/
  329.                     /* Ignore a specified number of characters.       */
  330.                     /**************************************************/
  331.                     pDCIData->ParserState = prdg_ESC_n_ignore;
  332.                     pDCIData->ParserCount =
  333.                                       pDCIData->ParserSequence->ESCValue;
  334.                     break;
  335.                 case prdg_ActCountIgnore:
  336.                     /**************************************************/
  337.                     /* A two byte count follows so prepare to read it */
  338.                     /* in.                                            */
  339.                     /**************************************************/
  340.                     pDCIData->ParserState = prdg_ESC_read_lo_count;
  341.                     break;
  342.                 case prdg_ActFF:
  343.                     /**************************************************/
  344.                     /* A special action for recognising the 0x1b6f    */
  345.                     /* "No Formfeed" sequence                         */
  346.                     /**************************************************/
  347.                     pDCIData->ParserState = prdg_Text;
  348.                     pDCIData->FFstate = prdg_FFx1b6f;
  349.                     break;
  350.                 case prdg_ActReset:
  351.                     /**************************************************/
  352.                     /* On Esc-E (reset) don't eject a page if this is */
  353.                     /* the last sequence in the stream.               */
  354.                     /**************************************************/
  355.                     pDCIData->ParserState = prdg_Text;
  356.                     pDCIData->FFstate = prdg_FFx1b45;
  357.                     break;
  358.             }
  359.             /*.. switch (pDCIData->ParserSequence->ESCAction) .........*/
  360.             break;
  361.         case prdg_ESC_n_ignore:
  362.             /**********************************************************/
  363.             /* Ignoring n characters. Decrement the count, move back  */
  364.             /* to text state if all ignored.                          */
  365.             /**********************************************************/
  366.             if (!(--pDCIData->ParserCount))
  367.                 pDCIData->ParserState = prdg_Text;
  368.             break;
  369.         case prdg_ESC_d_ignore:
  370.             /**********************************************************/
  371.             /* Ignoring up to a delimiter. If this is it, then stop   */
  372.             /* ignoring.                                              */
  373.             /**********************************************************/
  374.             if (inch == pDCIData->ParserDelimiter)
  375.                 pDCIData->ParserState = prdg_Text;
  376.             break;
  377.         case prdg_ESC_read_lo_count:
  378.             /**********************************************************/
  379.             /* Reading first byte of count. Save it, advance state.   */
  380.             /**********************************************************/
  381.             pDCIData->ParserCount = (UINT)inch;
  382.             pDCIData->ParserState = prdg_ESC_read_hi_count;
  383.             break;
  384.         case prdg_ESC_read_hi_count:
  385.             /**********************************************************/
  386.             /* Reading second byte of count. Save it, move to ignore  */
  387.             /* a specified number of characters if there are any.     */
  388.             /**********************************************************/
  389.             pDCIData->ParserCount += 256*(UINT)inch;
  390.             if (pDCIData->ParserCount)
  391.                 pDCIData->ParserState = prdg_ESC_n_ignore;
  392.             else
  393.                 pDCIData->ParserState = prdg_Text;
  394.             break;
  395.     };
  396.     /*.. switch (pDCIData->ParserState) ...............................*/
  397.     return;
  398. }
  399. BOOL
  400. CheckFormFeed(
  401.     lpDCI pDCIData)
  402. {
  403.     return FALSE;
  404. }