PageRenderTime 226ms CodeModel.GetById 80ms app.highlight 64ms RepoModel.GetById 77ms app.codeStats 0ms

/tags/harbour-3.0.0/contrib/hbzebra/code128.c

#
C | 399 lines | 299 code | 28 blank | 72 comment | 84 complexity | 654d1803af5afb5fa223af24ae929eec MD5 | raw file
  1/*
  2 * $Id: code128.c 15829 2010-11-17 11:19:59Z druzus $
  3 */
  4
  5/*
  6 * Harbour Project source code:
  7 * Zebra barcode library
  8 *
  9 * Copyright 2010 Mindaugas Kavaliauskas <dbtopas at dbtopas.lt>
 10 * www - http://harbour-project.org
 11 *
 12 * This program is free software; you can redistribute it and/or modify
 13 * it under the terms of the GNU General Public License as published by
 14 * the Free Software Foundation; either version 2, or (at your option)
 15 * any later version.
 16 *
 17 * This program is distributed in the hope that it will be useful,
 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20 * GNU General Public License for more details.
 21 *
 22 * You should have received a copy of the GNU General Public License
 23 * along with this software; see the file COPYING.  If not, write to
 24 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 25 * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
 26 *
 27 * As a special exception, the Harbour Project gives permission for
 28 * additional uses of the text contained in its release of Harbour.
 29 *
 30 * The exception is that, if you link the Harbour libraries with other
 31 * files to produce an executable, this does not by itself cause the
 32 * resulting executable to be covered by the GNU General Public License.
 33 * Your use of that executable is in no way restricted on account of
 34 * linking the Harbour library code into it.
 35 *
 36 * This exception does not however invalidate any other reasons why
 37 * the executable file might be covered by the GNU General Public License.
 38 *
 39 * This exception applies only to the code released by the Harbour
 40 * Project under the name Harbour.  If you copy code from other
 41 * Harbour Project or Free Software Foundation releases into a copy of
 42 * Harbour, as the General Public License permits, the exception does
 43 * not apply to the code that you add in this way.  To avoid misleading
 44 * anyone as to the status of such modified files, you must delete
 45 * this exception notice from them.
 46 *
 47 * If you write modifications of your own for Harbour, it is your choice
 48 * whether to permit this exception to apply to your modifications.
 49 * If you do not wish that, delete this exception notice.
 50 *
 51 */
 52
 53#include "hbzebra.h"
 54#include "hbapiitm.h"
 55#include "hbapierr.h"
 56
 57
 58static const unsigned short s_code[] = {
 59   00633,   /*            00  */
 60   00663,   /*  !    !    01  */
 61   01463,   /*  "    "    02  */
 62   00311,   /*  #    #    03  */
 63   00611,   /*  $    $    04  */
 64   00621,   /*  %    %    05  */
 65   00231,   /*  &    &    06  */
 66   00431,   /*  '    '    07  */
 67   00461,   /*  (    (    08  */
 68   00223,   /*  )    )    09  */
 69   00423,   /*  *    *    10  */
 70   00443,   /*  +    +    11  */
 71   00715,   /*  ,    ,    12  */
 72   00731,   /*  -    -    13  */
 73   01631,   /*  .    .    14  */
 74   00635,   /*  /    /    15  */
 75   00671,   /*  0    0    16  */
 76   01471,   /*  1    1    17  */
 77   01163,   /*  2    2    18  */
 78   00723,   /*  3    3    19  */
 79   01623,   /*  4    4    20  */
 80   00473,   /*  5    5    21  */
 81   00563,   /*  6    6    22  */
 82   01667,   /*  7    7    23  */
 83   00627,   /*  8    8    24  */
 84   00647,   /*  9    9    25  */
 85   01447,   /*  :    :    26  */
 86   00467,   /*  ;    ;    27  */
 87   00547,   /*  <    <    28  */
 88   01147,   /*  =    =    29  */
 89   00333,   /*  >    >    30  */
 90   01433,   /*  ?    ?    31  */
 91   01543,   /*  @    @    32  */
 92   00305,   /*  A    A    33  */
 93   00321,   /*  B    B    34  */
 94   01421,   /*  C    C    35  */
 95   00215,   /*  D    D    36  */
 96   00261,   /*  E    E    37  */
 97   01061,   /*  F    F    38  */
 98   00213,   /*  G    G    39  */
 99   00243,   /*  H    H    40  */
100   01043,   /*  I    I    41  */
101   00355,   /*  J    J    42  */
102   01615,   /*  K    K    43  */
103   01661,   /*  L    L    44  */
104   00335,   /*  M    M    45  */
105   01435,   /*  N    N    46  */
106   01561,   /*  O    O    47  */
107   01567,   /*  P    P    48  */
108   01613,   /*  Q    Q    49  */
109   01643,   /*  R    R    50  */
110   00273,   /*  S    S    51  */
111   01073,   /*  T    T    52  */
112   01673,   /*  U    U    53  */
113   00327,   /*  V    V    54  */
114   01427,   /*  W    W    55  */
115   01507,   /*  X    X    56  */
116   00267,   /*  Y    Y    57  */
117   01067,   /*  Z    Z    58  */
118   01307,   /*  [    [    59  */
119   01367,   /*  \    \    60  */
120   01023,   /*  ]    ]    61  */
121   01217,   /*  ^    ^    62  */
122   00145,   /*  _    _    63  */
123   00605,   /*  NUL   `   64  */
124   00151,   /*  SOH   a   65  */
125   01411,   /*  STX   b   66  */
126   00641,   /*  ETX   c   67  */
127   01441,   /*  EOT   d   68  */
128   00115,   /*  ENQ   e   69  */
129   00415,   /*  ACK   f   70  */
130   00131,   /*  BEL   g   71  */
131   01031,   /*  BS    h   72  */
132   00541,   /*  HT    i   73  */
133   01141,   /*  LF    j   74  */
134   01103,   /*  VT    k   75  */
135   00123,   /*  FF    l   76  */
136   01357,   /*  CR    m   77  */
137   00503,   /*  SO    n   78  */
138   01361,   /*  SI    o   79  */
139   00745,   /*  DLE   p   80  */
140   00751,   /*  DC1   q   81  */
141   01711,   /*  DC2   r   82  */
142   00475,   /*  DC3   s   83  */
143   00571,   /*  DC4   t   84  */
144   01171,   /*  NAK   u   85  */
145   00457,   /*  SYN   v   86  */
146   00517,   /*  ETB   w   87  */
147   01117,   /*  CAN   x   88  */
148   01733,   /*  EM    y   89  */
149   01573,   /*  SUB   z   90  */
150   01557,   /*  ESC   {   91  */
151   00365,   /*  FS    |   92  */
152   01705,   /*  GS    }   93  */
153   01721,   /*  RS    ~   94  */
154   00275,   /*  US   DEL  95  */
155   01075,   /*  FNC3 FNC3 96  */
156   00257,   /*  FNC2 FNC2 97  */
157   01057,   /*  ShiB ShiA 98  */
158   01735,   /*  CodC CodC 99  */
159   01675,   /*  CodB FNC4 CodB 100 */
160   01727,   /*  FNC4 CodA CodA 101 */
161   01657,   /*  FNC1 FNC1 FNC1 102 */
162   00413,   /*  Start Code A   103 */
163   00113,   /*  Start Code B   104 */
164   00713};  /*  Start Code C   105 */
165
166#define CODESET_A       0
167#define CODESET_B       1
168
169#define START_A       103
170#define START_B       104
171#define START_C       105
172
173#define SELECT_A      101
174#define SELECT_B      100
175#define SELECT_C       99
176
177#define SHIFT_AB       98
178
179
180static int _code128_charno( char ch, int iCodeSet )
181{
182   if( iCodeSet == CODESET_A )
183   {
184      if( ch >= ' ' && ch <= '_' )
185         return ch - ' ';
186      else if( ( unsigned char ) ch <= 31 )
187         return ch + 64;
188      else
189         return -1;
190   }
191   else if( iCodeSet == CODESET_B )
192   {
193      if( ch >= ' ' && ( unsigned char ) ch <= 127 )
194         return ch - ' ';
195      else
196         return -1;
197   }
198   return -1;
199}
200
201PHB_ZEBRA hb_zebra_create_code128( const char * szCode, HB_SIZE nLen, int iFlags )
202{
203   PHB_ZEBRA  pZebra;
204   int        i, j, k, csum, iCode, iCodeSet, iCodeLen, iLen = ( int ) nLen;
205   int *      pCode;
206
207   HB_SYMBOL_UNUSED( iFlags );
208
209   pZebra = hb_zebra_create();
210   pZebra->iType = HB_ZEBRA_TYPE_CODE128;
211
212   j = 0;
213   for( i = 0; i < iLen; i++ )
214   {
215      if( ( unsigned char ) szCode[ i ] >= 128 )
216      {
217         pZebra->iError = HB_ZEBRA_ERROR_INVALIDCODE;
218         return pZebra;
219      }
220      if( szCode[ i ] >= ' ' && szCode[ i ] <= 126 )
221         j++;
222   }
223
224   /* make print string */
225   pZebra->szCode = ( char * ) hb_xgrab( j + 1 );
226   j = 0;
227   for( i = 0; i < iLen; i++ )
228   {
229      if( szCode[ i ] >= 32 && szCode[ i ] <= 126 )
230         pZebra->szCode[ j++ ] = szCode[ i ];
231   }
232   pZebra->szCode[ j ] = '\0';
233
234   /* generate code set switch characters */
235   pCode = ( int * ) hb_xgrab( sizeof( int ) * iLen * 2 );
236   iCodeSet = CODESET_B; /* to pacify MSVC warning only. It will be assigned later */
237   iCodeLen = 0;
238   /* determine the first optimal codeset */
239   for( i = 0; i < iLen; i++ )
240   {
241      if( _code128_charno( szCode[ i ], CODESET_A ) == -1 )
242      {
243         iCodeSet = CODESET_B;
244         pCode[ iCodeLen++ ] = START_B;
245         break;
246      }
247      else if( _code128_charno( szCode[ i ], CODESET_B ) == -1 )
248      {
249         iCodeSet = CODESET_A;
250         pCode[ iCodeLen++ ] = START_A;
251         break;
252      }
253   }
254   if( iCodeLen == 0 )
255   {
256      iCodeSet = CODESET_B;
257      pCode[ iCodeLen++ ] = START_B;
258   }
259
260   /* encode source data */
261   /* Warning: digit optimizer works in optimal way with this encoder code. Be careful
262      if you'll change encoder code, digit optimizer canm require adjustment also [Mindaugas] */
263   for( i = 0; i < iLen; i++ )
264   {
265      iCode = _code128_charno( szCode[ i ], iCodeSet );
266      if( iCode != -1 )
267         pCode[ iCodeLen++ ] = iCode;
268      else
269      {
270         /* We should generate codeset switch instead of shift for the last character.
271            This will help digit optimizer to do its job [Mindaugas] */
272         if( i + 1 < iLen &&
273             _code128_charno( szCode[ i + 1 ], iCodeSet == CODESET_A ? CODESET_B : CODESET_A ) == -1 )
274         {
275            pCode[ iCodeLen++ ] = SHIFT_AB;
276            pCode[ iCodeLen++ ] = _code128_charno( szCode[ i ], iCodeSet == CODESET_A ? CODESET_B : CODESET_A );
277         }
278         else
279         {
280            if( iCodeSet == CODESET_A )
281            {
282               iCodeSet = CODESET_B;
283               pCode[ iCodeLen++ ] = SELECT_B;
284            }
285            else
286            {
287               iCodeSet = CODESET_A;
288               pCode[ iCodeLen++ ] = SELECT_A;
289            }
290            pCode[ iCodeLen++ ] = _code128_charno( szCode[ i ], iCodeSet );
291         }
292      }
293   }
294
295   /* optimize digits */
296   iCodeSet = pCode[ 0 ] == START_A ? CODESET_A : CODESET_B;
297   for( i = 1; i < iCodeLen; i++ )
298   {
299      if( iCodeSet == CODESET_A && pCode[ i ] == SELECT_B )
300         iCodeSet = CODESET_B;
301      else if( iCodeSet == CODESET_B && pCode[ i ] == SELECT_A )
302         iCodeSet = CODESET_A;
303
304      if( 16 <= pCode[ i ] && pCode[ i ] <= 25 )
305      {
306         for( j = i + 1; j < iCodeLen && 16 <= pCode[ j ] && pCode[ j ] <= 25; j++ );
307         if( j - i == 2 && i == 1 && j == iCodeLen )
308         {
309            /* [StartB] 1 2  -->  [StartC] [12] */
310            pCode[ 0 ] = START_C;
311            pCode[ 1 ] = ( pCode[ 1 ] - 16 ) * 10 + pCode[ 2 ] - 16;
312            iCodeLen = 2;
313            break;
314         }
315         else if( ( j - i >= 4 && ( i == 1 || j == iCodeLen || pCode[ j ] == SELECT_A || pCode[ j ] == SELECT_B ) ) ||
316                  j - i >= 6 )
317         {
318            if( i == 1 )
319            {
320               /* [StartN] 1 2 3 4  -->  [StartC] [12] [34] */
321               /* [StartN] 1 2 3 4 5  -->  [StartC] [12] [34] [CodeN] 5 */
322               /* [StartN] 1 2 3 4 X ... -->  [StartC] [12] [34] [CodeN] X ... */
323               /* [StartN] 1 2 3 4 5 X ... -->  [StartC] [12] [34] [CodeN] 5 X ... */
324               pCode[ 0 ] = START_C;
325               for( k = 1; k < j - 1; k += 2 )
326                  pCode[ i++ ] = ( pCode[ k ] - 16 ) * 10 + pCode[ k + 1 ] - 16;
327
328               if( k < iCodeLen )
329               {
330                  j = i;
331                  pCode[ i++ ] = iCodeSet == CODESET_A ? SELECT_A : SELECT_B;
332                  for( ; k < iCodeLen; k++ )
333                     pCode[ i++ ] = pCode[ k ];
334               }
335               iCodeLen = i;
336            }
337            else
338            {
339               /* ... X 1 2 3 4  -->  ... X [CodeC] [12] [34] */
340               /* ... X 1 2 3 4 [CodeN] ... -->  ... X [CodeC] [12] [34] [CodeN] ... */
341               /* ... X 1 2 3 4 5  -->  ... X 1 [CodeC] [23] [45] */
342               /* ... X 1 2 3 4 5 [CodeN] ...  -->  ... X 1 [CodeC] [23] [45] [CodeN] ... */
343               /* ... X 1 2 3 4 5 6 Y ...  -->  ... X [CodeC] [12] [34] [56] [CodeN] Y ... */
344               /* ... X 1 2 3 4 5 6 7 Y ...  -->  ... X 1 [CodeC] [23] [45] [67] [CodeN] Y ... */
345
346               if( ( j - i ) & 1 )
347               {
348                  /* digit count is odd */
349                  i++;
350               }
351
352               pCode[ i + 1 ] = ( pCode[ i ] - 16 ) * 10 + pCode[ i + 1 ] - 16;
353               pCode[ i ] = SELECT_C;
354               i += 2;
355               for( k = i; k < j; k += 2 )
356                  pCode[ i++ ] = ( pCode[ k ] - 16 ) * 10 + pCode[ k + 1 ] - 16;
357               j = i;
358               if( k < iCodeLen )
359               {
360                  if( pCode[ k ] != SELECT_A && pCode[ k ] != SELECT_B )
361                     pCode[ i++ ] = iCodeSet == CODESET_A ? SELECT_A : SELECT_B;
362
363                  for( ; k < iCodeLen; k++ )
364                     pCode[ i++ ] = pCode[ k ];
365               }
366               iCodeLen = i;
367            }
368         }
369         i = j - 1;
370      }
371   }
372
373   pZebra->pBits = hb_bitbuffer_create();
374   csum = pCode[ 0 ];
375   for( i = 0; i < iCodeLen; i++ )
376   {
377      hb_bitbuffer_cat_int( pZebra->pBits, s_code[ pCode[ i ] ], 11 );
378      csum += i * pCode[ i ];
379   }
380
381   hb_xfree( pCode );
382   /* checksum */
383   hb_bitbuffer_cat_int( pZebra->pBits, s_code[ csum % 103 ], 11 );
384
385   hb_bitbuffer_cat_int( pZebra->pBits, 0x1AE3, 13 );
386   return pZebra;
387}
388
389
390HB_FUNC( HB_ZEBRA_CREATE_CODE128 )
391{
392   PHB_ITEM pItem = hb_param( 1, HB_IT_STRING );
393   if( pItem )
394   {
395      hb_zebra_ret( hb_zebra_create_code128( hb_itemGetCPtr( pItem ), hb_itemGetCLen( pItem ), hb_parni( 2 ) ) );
396   }
397   else
398      hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
399}