home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / DOCJET.ZIP / data.z / vmrtf.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-18  |  8.5 KB  |  365 lines

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <assert.h>
  5. #include <string.h>
  6. #include <malloc.h>
  7.  
  8. #include <VM Extension.h>
  9.  
  10. extern "C" DLLEXPORT char *RTFColorTable()
  11. {
  12.     return( strdup( "{\\colortbl;"
  13.             "\\red0\\green0\\blue0;"
  14.             "\\red0\\green0\\blue255;"
  15.             "\\red0\\green255\\blue255;"
  16.             "\\red0\\green255\\blue0;"
  17.             "\\red255\\green0\\blue255;"
  18.             "\\red255\\green0\\blue0;"
  19.             "\\red255\\green255\\blue0;"
  20.             "\\red255\\green255\\blue255;"
  21.             "\\red0\\green0\\blue128;"
  22.             "\\red0\\green128\\blue128;"
  23.             "\\red0\\green128\\blue0;"
  24.             "\\red128\\green0\\blue128;"
  25.             "\\red128\\green0\\blue0;"
  26.             "\\red128\\green128\\blue0;"
  27.             "\\red128\\green128\\blue128;"
  28.             "\\red192\\green192\\blue192;}" ) );
  29. }
  30.  
  31. static int colortable[][3] = {
  32.     {0,0,0},
  33.     {0,0,255},
  34.     {0,255,255},
  35.     {0,255,0},
  36.     {255,0,255},
  37.     {255,0,0},
  38.     {255,255,0},
  39.     {255,255,255},
  40.     {0,0,128},
  41.     {0,128,128},
  42.     {0,128,0},
  43.     {128,0,128},
  44.     {128,0,0},
  45.     {128,128,0},
  46.     {128,128,128},
  47.     {192,192,192},
  48.     {-1,-1,-1}
  49. };
  50.  
  51. extern "C" DLLEXPORT const char *RTFColorMatch( const char *cstr )
  52. {
  53.     int c;
  54.     sscanf( cstr+1, "%x", &c );
  55.     int red = (c >> 16) & 0xff;
  56.     int green = (c>>8) & 0xff;
  57.     int blue = (c & 0xff);
  58.  
  59.     int bestMatch = 0x7fffffff;
  60.     int bestMatchIndex = -1;
  61.     for ( int i = 0; colortable[i][0] >= 0; i++ ) {
  62.         int diff = abs( red-colortable[i][0] ) +
  63.                abs( green-colortable[i][1] ) +
  64.                abs( blue-colortable[i][2] );
  65.         if ( diff < bestMatch) {
  66.             bestMatch = diff;
  67.             bestMatchIndex = i;
  68.         }
  69.     }
  70.     assert( bestMatchIndex >= 0 );
  71.     char buf[10];
  72.     sprintf( buf, "%d", bestMatchIndex+1 );
  73.     return( strdup( buf ) );
  74. }
  75.  
  76. extern "C" DLLEXPORT const char *RTFLoseLastParaMarker( const char *cstr )
  77. {
  78.     if ( strlen(cstr) <= 4 )
  79.       return strdup( cstr );
  80. //      Bomb( "Not a markup string, '%s'", cstr );
  81.     assert( strlen(cstr) > 4 );
  82.     char *rc = strdup(cstr);
  83.     char *s = rc+strlen(cstr)-4;
  84.     while ( 0 != strnicmp( s, "\\par", 4 ) ) {
  85.         if ( s == rc ) {
  86.             return strdup( cstr );
  87.             // Bomb( "No paragraph marker in '%s'", cstr );
  88.         }
  89.         --s;
  90.     }
  91.     *s = '\0';
  92.     return( rc );
  93. }
  94.  
  95. struct AliasBuf {
  96.     char *buffer;
  97.     unsigned int total;
  98.     unsigned int used;
  99.  
  100.     AliasBuf() {
  101.         total = 100;
  102.         used = 0;
  103.         buffer = (char *)malloc( total );
  104.         buffer[0] = '\0';
  105.     }
  106.  
  107.     void AddChar( char c ) {
  108.         if ( used+1 == total ) {
  109.             total *= 2;
  110.             buffer = (char *)realloc( buffer, total );
  111.         }
  112.         buffer[used++] = c;
  113.         buffer[used] = '\0';
  114.     }
  115.     void AddAlias( const char *s, int dotseparated ) {
  116.         char *dot = strchr( s, '.' );
  117.         if ( dot != 0 )
  118.           AddAlias( dot+1, dotseparated );
  119.         const char *firstSub = 0;
  120.         if ( used > 0 )
  121.           AddChar( ';' );
  122.         while ( *s != '\0' ) {
  123.             if ( *s == '.' ) {
  124.                 if ( dotseparated )
  125.                   AddChar( '.' );
  126.                 else {
  127.                     AddChar( ':' );
  128.                     AddChar( ':' );
  129.                 }
  130.                 ++s;
  131.                 if ( firstSub == 0 )
  132.                   firstSub = s;
  133.             }
  134.             else if ( *s == ':' && s[1] == ':' ) {
  135.                 if ( dotseparated )
  136.                   AddChar( '.' );
  137.                 else {
  138.                     AddChar( ':' );
  139.                     AddChar( ':' );
  140.                 }
  141.                 s += 2;
  142.                 if ( firstSub == 0 )
  143.                   firstSub = s;
  144.             }
  145.             else {
  146.                 AddChar( *s );
  147.                 ++s;
  148.             }
  149.         }
  150.         if ( firstSub != 0 )
  151.           AddAlias( firstSub, dotseparated );
  152.     }
  153. };
  154.  
  155. extern "C" DLLEXPORT const char *RTFAliasListToKeywordList
  156.     ( const char *fullname, const char *aliases )
  157. {
  158.     // What we get in is something like  Foo.Bar;Foo.Baz;Zoobie
  159.     //   what we want to put out is "Foo::Bar;Bar;Foo::Baz;Baz;Zoobie"
  160.     //   That is, we break it into semicolon-separated strings, then
  161.     //   we add every possible sub-context.
  162.  
  163.     // We need fullname to find out if this is the sort of object
  164.     //   that is :: separated or . separated...
  165.     int dotseparated = (0 == strstr( fullname, "::" ));
  166.  
  167.     AliasBuf buf;
  168.  
  169.     const char *s = aliases;
  170.     while ( s != 0 ) {
  171.         const char *nexts = strchr( s, ';' );
  172.         if ( nexts != 0 )
  173.           *(char *)nexts = '\0';
  174.         buf.AddAlias( s, dotseparated );
  175.         if ( nexts != 0 ) {
  176.             *(char *)nexts = ';';
  177.             s = nexts+1;
  178.         }
  179.         else
  180.           s = 0;
  181.     }
  182.     return( buf.buffer );
  183. }
  184.  
  185. extern "C" DLLEXPORT const char *RTFRemoveMarkups( const char *text )
  186. {
  187.     char *rc = strdup( text );
  188.     char *r = rc;
  189.     const char *s = text;
  190.     bool realStuffSeen = false;
  191.     while ( *s != '\0' ) {
  192.         if ( s[0] == '{' && s[1] == '\\' && s[2] == 'b' && s[3] == ' ' ) {
  193.             s += 4;
  194.             while ( *s != '}' )
  195.               *r++ = *s++;
  196.             ++s;
  197.         }
  198.         else if ( s[0] == '{' && s[1] == '\\' &&
  199.               s[2] == 'u' && s[3] == 'l' &&
  200.               s[4] == 'd' && s[5] == 'b' && s[6] == ' ' ) {
  201.             s += 7;
  202.             while ( *s != '}' )
  203.               *r++ = *s++;
  204.             ++s;
  205.             while ( *s != '}' )
  206.               ++s;
  207.             ++s;
  208.         }
  209.         else if ( s[0] == '\\' && s[1] == 'p' && s[2] == 'a' &&
  210.               s[3] == 'r' && !isalnum(s[4]) ) {
  211.             *r++ = '\\';
  212.             *r++ = 'l';
  213.             *r++ = 'i';
  214.             *r++ = 'n';
  215.             *r++ = 'e';
  216.             s += 4;
  217.         }
  218.         else if ( s[0] == '\\' && s[1] == 'l' && s[2] == 'i' &&
  219.               s[3] == 'n' && s[4] == 'e' && !isalnum(s[5]) ) {
  220.             *r++ = '\\';
  221.             *r++ = 'l';
  222.             *r++ = 'i';
  223.             *r++ = 'n';
  224.             *r++ = 'e';
  225.             s += 5;
  226.         }
  227.         else if ( s[0] == '\\' && isalnum(s[1]) ) {
  228.             s += 2;
  229.             while ( isalnum(*s) )
  230.               ++s;
  231.         }
  232.         else if ( s[0] == '\\' ) {
  233.             realStuffSeen = true;
  234.             *r++ = *s++;
  235.             *r++ = *s++;
  236.         }
  237.         else if ( s[0] == '{' || s[0] == '}' ||
  238.               s[0] == '\r' || s[0] == '\n' ) {
  239.             ++s;
  240.         }
  241.         else if ( s[0] == ' ' && !realStuffSeen ) {
  242.             ++s;
  243.         }
  244.         else if ( s[0] == '\r' || s[0] == '\n' ) {
  245.             *r++ = *s++;
  246.         }
  247.         else {
  248.             *r++ = *s++;
  249.             realStuffSeen = true;
  250.         }
  251.     }
  252.     *r = '\0';
  253.     bool doAgain;
  254.     do {
  255.         if ( r > rc && r[-1] == ' ' ) {
  256.             --r;
  257.             *r = '\0';
  258.             doAgain = true;
  259.         }
  260.         else if ( r-4 > rc && 0 == strcmp( r-5, "\\line" ) ) {
  261.             r -= 5;
  262.             *r = '\0';
  263.             doAgain = true;
  264.         }
  265.         else
  266.           doAgain = false;
  267.     } while ( doAgain );
  268.     return( rc );
  269. }
  270.  
  271. extern "C" DLLEXPORT const char *RTFGuestimateColumnWidth( int argc, char **argv )
  272. {
  273.     double outliers = .1; // percentage which we can treat as abnormally long.
  274.     double mainBody = .7; // percentage which we would like to see always fit
  275.                   //   in the column.
  276.     unsigned int acceptableWidth = 3600; // If the table gets bigger than this, start looking
  277.                              //   for breakpoints
  278.     unsigned int maxWidth = 4800; // The largest value which we can return
  279.     double widthPerCharacter = 100.0;
  280.  
  281.     if ( argc == 2 )
  282.       sscanf( argv[1], "%d,%d,%lg,%lg,%lg", &acceptableWidth, &maxWidth,
  283.           &widthPerCharacter, &mainBody, &outliers );
  284.  
  285.     unsigned int numRows;
  286.     unsigned int *widths;
  287.     unsigned int widestRow;
  288.  
  289.     // columns (argv[0]) is a newline separated list of strings that'll be the
  290.     //   left-hand side of a column in a table.
  291.     numRows = 1;
  292.     for ( const char *s = argv[0]; *s != '\0'; ++s )
  293.       if ( *s == '\n' )
  294.         ++numRows;
  295.  
  296.     widths = new unsigned int[numRows];
  297.     char *dup = strdup( argv[0] );
  298.  
  299.     unsigned int i = 0;
  300.     for ( s = strtok( dup, "\n" ); s != 0; s = strtok( 0, "\n" ) )
  301.       widths[i++] = (unsigned int)(strlen(s) * widthPerCharacter);
  302.  
  303.     numRows = i;
  304.  
  305.     for ( i = 0; i < numRows; ++i )
  306.       for ( unsigned int j = i+1; j < numRows; ++j )
  307.         if ( widths[i] > widths[j] ) {
  308.             unsigned int t = widths[i];
  309.             widths[i] = widths[j];
  310.             widths[j] = t;
  311.         }
  312.  
  313.     free( dup );
  314.  
  315.  
  316.     unsigned int mainWidth = widths[ (unsigned int)(numRows * mainBody) ];
  317.  
  318.     unsigned int solution;
  319.     widestRow = widths[numRows-1];
  320.     if ( numRows < 3 || // Trivial case
  321.          widestRow < acceptableWidth || // Within normal bounds
  322.          mainWidth > 0.75 * widestRow ) { // No advantage to breaking it
  323.         solution = widestRow;
  324.     }
  325.     else {
  326.         // Look for the biggest gap between numRows*mainBody and numRows*outliers,
  327.         //   use that as the width.
  328.  
  329.         unsigned int bigBreak = 0;
  330.         unsigned int bigBreakIndex;
  331.         for ( i = (unsigned int)(numRows * mainBody);
  332.               i < numRows * (1.0-outliers) + .5 && i < numRows-1;
  333.               ++i )
  334.           if ( widths[i+1] - widths[i] > bigBreak ) {
  335.               bigBreak = widths[i+1] - widths[i];
  336.               bigBreakIndex = i;
  337.           }
  338.  
  339.         if ( bigBreak == 0 )
  340.           solution = widestRow;
  341.         else
  342.           solution = widths[bigBreakIndex];
  343.     }
  344.  
  345.     delete[numRows] widths;
  346.     if ( solution > maxWidth )
  347.       solution = maxWidth;
  348.  
  349.     char buf[16];
  350.     sprintf( buf, "%d", solution );
  351.     return( strdup( buf ) );
  352. }
  353.  
  354.  
  355.  
  356. START_DECLARE_FUNCTIONS()
  357.   DECLARE_NOARG_FUNCTION(RTFColorTable)
  358.   DECLARE_1ARG_FUNCTION(RTFColorMatch)
  359.   DECLARE_1ARG_FUNCTION(RTFLoseLastParaMarker)
  360.   DECLARE_2ARG_FUNCTION(RTFAliasListToKeywordList)
  361.   DECLARE_1ARG_FUNCTION(RTFRemoveMarkups)
  362.   DECLARE_VARARG_FUNCTION(RTFGuestimateColumnWidth,1,2)
  363. END_DECLARE_FUNCTIONS()
  364.  
  365.