Milán Major

netscape-revival

1 branch
Code

sun-java/awt/x/ustring.c

/*************************************************************************************
 *
 * Copyright (c) 1996 Netscape Communications Corp.  All rights reserved.
 *
 * Description:
 *  
 *
 * Authors:
 *  Brian Beck <bcbeck@netscape.com>    Feb 22, 1996     created this file.
 *
 *************************************************************************************/

#include "libi18n.h"
#include "awt_p.h"
#include "java_awt_Font.h"
#include "ustring.h"
#include <sys/time.h>
   
int16         awt_LocaleCharSetID;


/*************************************************************************************
 *
 * Description:
 *  Creates a Motif compound string (XmString) from a Java string.  The Java string's
 *  Unicode is converted piecewise into a series of new encodings.  The new encodings
 *  are chosen to match the non-Unicode fonts that are available on the system.
 *
 *************************************************************************************/

XmString  makeXmString( Hjava_lang_String* javaStringHandle )
{
   long        length;
   unicode*    uniChars;
   unicode     emptyString = 0;

   /* Many awt routines seem to use the convention that NULL pointers to Java strings
    * should be treated as empty strings.  This routine preserves that convention.
    */
   if( javaStringHandle == NULL )
   {
      uniChars = &emptyString;
      length = 0;
   }
   else
   {
      Classjava_lang_String* javaStringClass = unhand( javaStringHandle );
      HArrayOfChar* unicodeArrayHandle = (HArrayOfChar *)javaStringClass->value;
      uniChars =  unhand(unicodeArrayHandle)->body + javaStringClass->offset;
      length = javaStringClass->count;
   }

   return makeXmStringFromChars( uniChars, length );
}


/*************************************************************************************
 *
 * Description:
 *  Creates a Motif compound string (XmString) from an array of Unicode characters.
 *  The Unicode is converted piecewise into a series of new encodings.  The new
 *  encodings are chosen to match the non-Unicode fonts that are available on the
 *  system.
 *
 *************************************************************************************/

XmString  makeXmStringFromChars( unicode* uniChars, long length )
{
   INTL_CompoundStr*        compoundString;
   INTL_Encoding_ID         encodingID;
   unsigned char*           stringSegment;
   INTL_CompoundStrIterator iter;
   XmString                 xString;
   char                     tag[48];

   
   /* Many awt routines seem to use the convention that NULL pointers to Java strings
    * should be treated as empty strings.  This routine preserves that convention.
    */   
   if( uniChars == NULL )
   {
      unicode emptyString = 0;
      compoundString = INTL_CompoundStrFromUnicode( &emptyString, 0 );
   }
   else
   {
      compoundString = INTL_CompoundStrFromUnicode( uniChars, length );
   }

   if( compoundString == 0 )
   {
      SignalError(0, JAVAPKG "OutOfMemoryError", 0);
      return (XmString)NULL;
   }      
   

   /* Create an XmString from the INTL_CompoundString */
   iter = INTL_CompoundStrFirstStr( compoundString, &encodingID, &stringSegment );
   if( iter == NULL )
   {
      SignalError(0, JAVAPKG "OutOfMemoryError", 0);
      return (XmString)NULL;
   }      
   INTL_CharSetIDToName( encodingID, tag );
   xString = XmStringCreate( stringSegment, tag );
   
   while((iter = INTL_CompoundStrNextStr( iter, &encodingID, &stringSegment ) ))
   {
      XmString tmpXString1;
      XmString tmpXString2;

      INTL_CharSetIDToName( encodingID, tag );

      tmpXString1 = XmStringCreate( stringSegment, tag );
      tmpXString2 = XmStringConcat( xString, tmpXString1 );
      XmStringFree( xString );
      XmStringFree(tmpXString1);

      xString = tmpXString2;
   }
   
   INTL_CompoundStrDestroy(compoundString);        

   /* return the XmString */
   return xString;
}

/*************************************************************************************
 *
 * Description:
 *  Creates a Motif font list representing all the fonts needed to display the Unicode
 *  character set.
 *
 *************************************************************************************/

char* makeLocalizedCString( Hjava_lang_String* javaStringHandle )
{
   unicode*             uniChars;
   long                 uniCharsLength;
   unicode              emptyString = 0;
   char*                cString;
   long                 approxCStringLength;
   HArrayOfByte*        cStringHandle;
   extern HArrayOfByte* MakeByteString(char *str, long len);

   
   /* Many awt routines seem to use the convention that NULL pointers to Java strings
    * should be treated as empty strings.  This routine preserves that convention.
    */
   if( javaStringHandle == NULL )
   {
      uniChars = &emptyString;
      uniCharsLength = 0;
   }
   else
   {
      Classjava_lang_String* javaStringClass = unhand( javaStringHandle );
      HArrayOfChar* unicodeArrayHandle = (HArrayOfChar *)javaStringClass->value;
      uniChars =  unhand(unicodeArrayHandle)->body + javaStringClass->offset;
      uniCharsLength = javaStringClass->count;
   }

   /* Get an upper bound on the length of the converted string. */
   approxCStringLength = INTL_UnicodeToStrLen( awt_LocaleCharSetID, uniChars,
                                               uniCharsLength );
   
   cStringHandle = MakeByteString( NULL, approxCStringLength );
   if (cStringHandle == 0)
   {
      SignalError(0, JAVAPKG "OutOfMemoryError", 0);
      return NULL;
   }
   cString = unhand(cStringHandle)->body;
   
   INTL_UnicodeToStr( awt_LocaleCharSetID, uniChars, uniCharsLength,
                      cString, approxCStringLength );
   
   return cString;
}



/*************************************************************************************
 *
 * Description:
 *
 *************************************************************************************/

Hjava_lang_String*  makeJavaStringFromLocalizedCString( char* cString )
{
   HArrayOfChar* uniCharsHandle;
   unicode*      uniChars;
   long          uniCharsBufferLength;
   long          uniCharsStringLength;

   if( cString == NULL )
      uniCharsBufferLength = 0;
   else
      uniCharsBufferLength = INTL_StrToUnicodeLen( awt_LocaleCharSetID, cString );
   
   uniCharsHandle = (HArrayOfChar*) ArrayAlloc( T_CHAR, uniCharsBufferLength );
   if(uniCharsHandle == 0)
   {
      SignalError(0, JAVAPKG "OutOfMemoryError", 0);
      return 0;
   }
   
   uniChars = unhand( uniCharsHandle )->body;
   
   if( cString )
   {
      uniCharsStringLength = INTL_StrToUnicode( awt_LocaleCharSetID, cString, uniChars,
                                                uniCharsBufferLength );
   }
   
   return (Hjava_lang_String *)
      execute_java_constructor(EE(), 0, classJavaLangString, "([CII)",
                               uniCharsHandle, 0, uniCharsStringLength);
}



/* Some forward declarations needed at this  point. */

static void  getXFontFamilyAndFoundry( char* javaFontName, int16 csid,
                                       char** family, char** foundry );

static XFontSet makeXFontSet( Display* display, char* javaFamily, int size, int style );

XFontStruct*  INTL_GetFont( Display*, int16 , char*, char*, int, int );

int16*  INTL_GetXCharSetIDs(Display *display);

char* INTL_GetXFontName(Display *display, int16 characterSet, char *familyName,
                        char *foundry, int sizeNum, int style);

/*************************************************************************************
 *
 * Description:
 *  Creates a Motif font list representing all the fonts needed to display the Unicode
 *  character set.
 *
 *************************************************************************************/

XmFontList makeXmFontList( struct Hjava_awt_Font* javaFontHandle, XFontStruct *xfont)
{
   Classjava_awt_Font*   javaFont;
   char*                 javaFamily;
   int16*                csidList;
   int16                 csidListLength;
   int16                 i;
   XmFontList            fontList = NULL; 
   XFontSet              fontSet;
   XmFontListEntry       fontEntry;
   Display*              display;

   
   if( javaFontHandle == NULL )
   {
      /* *errmsg = JAVAPKG "NullPointerException"; */
      return (XmFontList) NULL;
   }
   
   javaFont = unhand( javaFontHandle );
   javaFamily = makeCString( javaFont->family );

   display = XDISPLAY;
   
   csidList = INTL_GetUnicodeCSIDList( &csidListLength );
   for( i=0; i<csidListLength; i++ )
   {
      char*            family;
      char*            foundry;
      XFontStruct*     fontStruct;
      char             tag[48];   

      getXFontFamilyAndFoundry( javaFamily, csidList[i], &family, &foundry );
      fontStruct = INTL_GetFont( display, csidList[i], family, foundry,
                                 javaFont->size, javaFont->style );
      if( fontStruct == NULL )
      {
         /* Some error */
         return (XmFontList) NULL;
      }

      /* Add this thing to our fontlist */
      INTL_CharSetIDToName( csidList[i], tag );
      fontEntry = XmFontListEntryCreate( tag, XmFONT_IS_FONT, fontStruct );
      fontList = XmFontListAppendEntry( fontList, fontEntry );

      XmFontListEntryFree(&fontEntry);
   }

   /* Now create an XFontSet for the widgets that can only handle a single locale. */
   fontSet = makeXFontSet( display, javaFamily, javaFont->size, javaFont->style );
   fontEntry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, XmFONT_IS_FONTSET, fontSet);
   fontList = XmFontListAppendEntry( fontList, fontEntry );
   XmFontListEntryFree(&fontEntry);

   return fontList;
}

XmFontList makeXmFontListTest( )
{
   char*                 javaFamily;
   int16*                csidList;
   int16                 csidListLength;
   int16                 i;
   XmFontList            fontList = NULL; 
   XFontSet              fontSet;
   XmFontListEntry       fontEntry;
   Display*              display;

   
   javaFamily = "Courier";

   display = XDISPLAY;
   
   csidList = INTL_GetUnicodeCSIDList( &csidListLength );
   for( i=0; i<csidListLength; i++ )
   {
      char*            family;
      char*            foundry;
      XFontStruct*     fontStruct;
      char             tag[48];   

      getXFontFamilyAndFoundry( javaFamily, csidList[i], &family, &foundry );
      fontStruct = INTL_GetFont( display, csidList[i], family, foundry,
                                 12, 0 );
      if( fontStruct == NULL )
      {
         /* Some error */
         return (XmFontList) NULL;
      }

      /* Add this thing to our fontlist */
      INTL_CharSetIDToName( csidList[i], tag );
      fontEntry = XmFontListEntryCreate( tag, XmFONT_IS_FONT, fontStruct );
      fontList = XmFontListAppendEntry( fontList, fontEntry );

      XmFontListEntryFree(&fontEntry);
   }

   /* Now create an XFontSet for the widgets that can only handle a single locale. */
   fontSet = makeXFontSet( display, javaFamily, 12, 0 );
   fontEntry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, XmFONT_IS_FONTSET, fontSet);
   fontList = XmFontListAppendEntry( fontList, fontEntry );
   XmFontListEntryFree(&fontEntry);

   return fontList;
}

static XFontSet
makeXFontSet( Display* display, char* javaFamily, int size, int style )
{
   int16*   csidList;
   int      i;
   char*    fontName;
   char*    fontNameList = NULL;
   char*    newFontNameList;
   char*    family;
   char*    foundry;
   char**   missingCharSets;
   int      missingCharSetCount;
   char*    missingCharString;

   csidList = INTL_GetXCharSetIDs( display );
   if( csidList == NULL )
      return NULL;

   
   for( i=0; csidList[i] != 0; i++ )
   {
      getXFontFamilyAndFoundry( javaFamily, csidList[i], &family, &foundry );
      fontName = INTL_GetXFontName( display, csidList[i], family, foundry, size, style );
      if (!fontName)
      {
	 continue;
      }

      if( fontNameList == NULL )
         newFontNameList = strdup( fontName );
      else
      {
         newFontNameList = PR_smprintf("%s,%s", fontNameList, fontName);
	 if (newFontNameList)
	 {
            free( fontNameList );
	 }
      }
      free( fontName );
      if (!newFontNameList)
      {
         continue;
      }

      fontNameList = newFontNameList;
   }
   free( csidList );
   
   return XCreateFontSet( display, fontNameList, &missingCharSets,
                          &missingCharSetCount, &missingCharString );
}



/* The following tables map Java font names to X font names for various character sets.
 * The tables are indexed by CSID.  Null values indicate "don't care" names.  These  
 * tables are used to implement the function getXFontFamilyAndFoundry and should be
 * considered private to that function.
 */
struct FontInfo
{
   char* foundry;
   char* family;
};

static struct FontInfo  helveticaFonts[INTL_CHAR_SET_MAX ] =
{
   {0,0},
   {"adobe","helvetica"},              /* CS_ASCII */
   {"adobe","helvetica"},              /* CS_LATIN1 */
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},
   {"adobe","helvetica"},              /* CS_LATIN2 */
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,"gothic"},                       /* CS_JISX0208 */
   {0,"gothic"}                        /* CS_JISX0201 */
};

static struct FontInfo  timesRomanFonts[ INTL_CHAR_SET_MAX ] =
{
   {0,0},
   {"adobe","times"},                  /* CS_ASCII */
   {"adobe","times"},                  /* CS_LATIN1 */
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},                                
   {"adobe","times"},                  /* CS_LATIN2 */
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {"daewoo","mincho"},                /* CS_JISX0208 */
   {"daewoo","mincho"}                 /* CS_JISX0201 */
};

static struct FontInfo  courierFonts[ INTL_CHAR_SET_MAX ] =
{
   {0,0},
   {"adobe","courier"},                  /* CS_ASCII */
   {"adobe","courier"},                  /* CS_LATIN1 */
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},                                
   {"adobe","courier"},                  /* CS_LATIN2 */
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {"jis","fixed"},                      /* CS_JISX0208 */
   {"jis","fixed"}                       /* CS_JISX0201 */
};

static struct FontInfo  dialogFonts[ INTL_CHAR_SET_MAX ] =
{
   {0,0},
   {"b&h","lucida"},                   /* CS_ASCII */
   {"b&h","lucida"},                   /* CS_LATIN1 */
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},
   {"b&h","lucida"},                   /* CS_LATIN2 */
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,"gothic"},                       /* CS_JISX0208 */
   {0,"gothic"}                        /* CS_JISX0201 */
};

static struct FontInfo  dialogInputFonts[ INTL_CHAR_SET_MAX ] =
{
   {0,0},
   {"b&h","lucidatypewriter"},         /* CS_ASCII */
   {"b&h","lucidatypewriter"},         /* CS_LATIN1 */
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},                                
   {"b&h","lucidatypewriter"},         /* CS_LATIN2 */
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,"gothic"},                       /* CS_JISX0208 */
   {0,"gothic"}                        /* CS_JISX0201 */
};

static struct FontInfo  zapfDingbatsFonts[ INTL_CHAR_SET_MAX ] =
{
   {0,0},
   {"itc","zapfdingbats"},             /* CS_ASCII */
   {"itc","zapfdingbats"},             /* CS_LATIN1 */
   {0,0},{0,0},{0,0},{0,0},{0,0},                          
   {0,0},{0,0},                                
   {"itc","zapfdingbats"},             /* CS_LATIN2 */
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},{0,0},{0,0},{0,0},{0,0},
   {0,0},                              /* CS_JISX0208 */
   {0,0}                               /* CS_JISX0201 */
};


/*************************************************************************************
 *
 * Description:
 *  This function maps a Java font name to an X font name and foundry for a given
 *  character set.  The X font name and foundry are returned in the fill-in parameters
 *  "family" and "foundry".
 *  
 ************************************************************************************/

static void
getXFontFamilyAndFoundry( char* javaFontName, int16 csid,
                          char** family, char** foundry )
{
   int16 maskedCsid = csid & 0x00ff;
   
   if(strcmp(javaFontName,"Helvetica")==0)
   {
      *family =  helveticaFonts[maskedCsid].family;
      *foundry =  helveticaFonts[maskedCsid].foundry;
   }
   else if(strcmp(javaFontName,"TimesRoman") == 0)
   {
      *family =  timesRomanFonts[maskedCsid].family;
      *foundry =  timesRomanFonts[maskedCsid].foundry;
   }
   else if(strcmp(javaFontName,"Courier") == 0)
   {
      *family =  courierFonts[maskedCsid].family;
      *foundry =  courierFonts[maskedCsid].foundry;
   }
   else if(strcmp(javaFontName,"Dialog") == 0)
   {
      *family =  dialogFonts[maskedCsid].family;
      *foundry =  dialogFonts[maskedCsid].foundry;
   }
   else if(strcmp(javaFontName,"DialogInput") == 0)
   {
      *family =  dialogInputFonts[maskedCsid].family;
      *foundry =  dialogInputFonts[maskedCsid].foundry;
   }
   else if(strcmp(javaFontName,"ZapfDingbats") == 0)
   {
      *family =  zapfDingbatsFonts[maskedCsid].family;
      *foundry =  zapfDingbatsFonts[maskedCsid].foundry;
   }
   else
   {
      *family  = NULL;
      *foundry = NULL;
   }
}


void printFontInfo( Widget widget )
{
   XmFontList      fontList;
   XmFontContext   context;
   XmFontListEntry fontListEntry;
   
   XtVaGetValues(widget,  XmNfontList, &fontList,  NULL);

   XmFontListInitFontContext( &context, fontList );
   while ((fontListEntry = XmFontListNextEntry(context) ))
   {
      char*       tag;
      XtPointer   font;
      XmFontType  type;

      tag = XmFontListEntryGetTag( fontListEntry );
      fprintf(stderr,"Font Tag: %s ", tag);
      font = XmFontListEntryGetFont( fontListEntry, &type );
      if( type == XmFONT_IS_FONTSET )
      {
         XFontStruct** fontStructList;
         char**        fontNameList;
         int           length;
         int           i;

         length = XFontsOfFontSet( font, &fontStructList, &fontNameList );
         
         fprintf(stderr,"is a fontset.\n");
         for( i=0; i<length; i++ )
            fprintf(stderr,"\t%s\n",fontNameList[i]);
      }
      else if( type == XmFONT_IS_FONT )
      {
         fprintf(stderr,"is a font.\n");
      }
      else
      {
         fprintf(stderr,"is ???.\n");
      }
      
 
      
   }
   
   XmFontListFreeFontContext( context );
   
}

void printAncestry( Widget widget )
{
   Widget parent;
   int    ancestor=1;

   fprintf(stderr, "Target Widget: %s\n", widget);
   
   parent = XtParent(widget);
   while( ( parent!=NULL ) && (parent != widget) )
   {
      fprintf(stderr,"Ancestor %d: %s\n", ancestor++, XtName(parent) );
      widget = parent;
      parent = XtParent(widget);
   }
}