0N/A/*
2362N/A * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * These routines are used for display string with multi font.
0N/A */
0N/A
0N/A#ifdef HEADLESS
0N/A #error This file should not be included in headless library
0N/A#endif
0N/A
0N/A#include <stdlib.h>
0N/A#include <string.h>
0N/A#include <math.h>
0N/A#include <ctype.h>
0N/A#include <jni.h>
0N/A#include <jni_util.h>
0N/A#include <jvm.h>
0N/A#ifndef XAWT
0N/A#include <Xm/Display.h>
0N/A#endif
0N/A#include "awt_Font.h"
0N/A#ifndef XAWT
0N/A#include "awt_Component.h"
0N/A#endif
0N/A#include "awt_MenuItem.h"
0N/A#include "awt_p.h"
0N/A#include "multi_font.h"
0N/A
0N/Aextern XFontStruct *loadFont(Display *, char *, int32_t);
0N/A
0N/Aextern struct FontIDs fontIDs;
547N/A//extern struct MComponentPeerIDs mComponentPeerIDs;
547N/A//extern struct MMenuItemPeerIDs mMenuItemPeerIDs;
0N/Aextern struct PlatformFontIDs platformFontIDs;
0N/Aextern struct MFontPeerIDs mFontPeerIDs;
0N/A
0N/A/*
0N/A * make string with str + string representation of num
0N/A * This string is used as tag string of Motif Compound String and FontList.
0N/A */
0N/Astatic void
0N/AmakeTag(char *str, int32_t num, char *buf)
0N/A{
0N/A int32_t len = strlen(str);
0N/A
0N/A strcpy(buf, str);
0N/A buf[len] = '0' + num % 100;
0N/A buf[len + 1] = '\0';
0N/A}
0N/A#ifndef XAWT
0N/Ajobject
0N/AawtJNI_CreateAndSetGlobalRef(JNIEnv * env, jobject this)
0N/A{
0N/A jobject gRef;
0N/A
0N/A gRef = (*env)->NewGlobalRef(env, this);
0N/A
0N/A JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.jniGlobalRef, gRef);
0N/A
0N/A return gRef;
0N/A}
0N/A
0N/Astruct gRefStruct
0N/A{
0N/A jobject gRef;
0N/A struct gRefStruct *next;
0N/A};
0N/A
0N/Astatic struct gRefStruct *gRefHead = NULL;
0N/Astatic struct gRefStruct *gRefTail = NULL;
0N/A
0N/A/*
0N/A * This function is called by components that
0N/A * are being disposed. It used to invalidate
0N/A * the global ref immediately, but the awt is
0N/A * rather full of thread race conditions involving
0N/A * component disposal and outstanding events.
0N/A * Now we queue up 'to be deleted' global refs
0N/A * as they come in, and don't invalidate them
0N/A * until the X event queue is empty. Callers of
0N/A * either of these functions _must_ have AWT_LOCK'd
0N/A * before using them!
0N/A */
0N/Avoid
0N/AawtJNI_DeleteGlobalRef(JNIEnv * env, jobject this)
0N/A{
0N/A jobject gRef;
0N/A struct gRefStruct *newGRef;
0N/A struct gRefStruct *temp;
0N/A
0N/A gRef = (jobject)
0N/A JNU_GetLongFieldAsPtr(env, this, mComponentPeerIDs.jniGlobalRef);
0N/A JNU_SetLongFieldFromPtr(env, this, mComponentPeerIDs.jniGlobalRef, NULL);
0N/A
0N/A /*
0N/A * Verra handy for tracking down race conditions. If you
0N/A * have a peer getting called after its been disposed...
0N/A */
0N/A /* jio_fprintf(stderr,"%p\n",(void *)gRef); */
0N/A
0N/A newGRef = (struct gRefStruct *)malloc((size_t)sizeof(struct gRefStruct));
0N/A
0N/A if(newGRef == NULL)
0N/A (*env)->DeleteGlobalRef(env, gRef);
0N/A else
0N/A {
0N/A newGRef->gRef = gRef;
0N/A newGRef->next = NULL;
0N/A
0N/A if(gRefHead == NULL)
0N/A {
0N/A gRefTail = newGRef;
0N/A gRefHead = newGRef;
0N/A }
0N/A else
0N/A {
0N/A gRefTail->next = newGRef;
0N/A gRefTail = newGRef;
0N/A }
0N/A }
0N/A}
0N/A
0N/Avoid
0N/AawtJNI_DeleteGlobalMenuRef(JNIEnv * env, jobject this)
0N/A{
0N/A jobject gRef;
0N/A struct gRefStruct *newGRef;
0N/A struct gRefStruct *temp;
0N/A
0N/A gRef = (jobject)
547N/A //JNU_GetLongFieldAsPtr(env, this, mMenuItemPeerIDs.jniGlobalRef);
547N/A //JNU_SetLongFieldFromPtr(env, this, mMenuItemPeerIDs.jniGlobalRef, NULL);
0N/A
0N/A /*
0N/A * Verra handy for tracking down race conditions. If you
0N/A * have a peer getting called after its been disposed...
0N/A */
0N/A /* jio_fprintf(stderr,"%p\n",(void *)gRef); */
0N/A
0N/A newGRef = (struct gRefStruct *)malloc((size_t)sizeof(struct gRefStruct));
0N/A
0N/A if(newGRef == NULL)
0N/A (*env)->DeleteGlobalRef(env, gRef);
0N/A else
0N/A {
0N/A newGRef->gRef = gRef;
0N/A newGRef->next = NULL;
0N/A
0N/A if(gRefHead == NULL)
0N/A {
0N/A gRefTail = newGRef;
0N/A gRefHead = newGRef;
0N/A }
0N/A else
0N/A {
0N/A gRefTail->next = newGRef;
0N/A gRefTail = newGRef;
0N/A }
0N/A }
0N/A}
0N/A
0N/Avoid awtJNI_CleanupGlobalRefs()
0N/A{
0N/A struct gRefStruct *working,*next;
0N/A JNIEnv *env;
0N/A int32_t count = 0;
0N/A
0N/A if(gRefHead == NULL) {
0N/A return;
0N/A }
0N/A
0N/A env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
0N/A
0N/A working = gRefHead;
0N/A gRefHead = gRefTail = NULL;
0N/A
0N/A while(working != NULL)
0N/A {
0N/A count++;
0N/A next = working->next;
0N/A (*env)->DeleteGlobalRef(env, working->gRef);
0N/A
0N/A free((void *)working);
0N/A
0N/A working = next;
0N/A }
0N/A}
0N/A#endif
0N/Astatic int32_t
0N/AawtJNI_GetFontDescriptorNumber(JNIEnv * env
0N/A ,jobject font
0N/A ,jobject fd)
0N/A{
0N/A int32_t i = 0, num;
0N/A /* initialize to NULL so that DeleteLocalRef will work. */
0N/A jobjectArray componentFonts = NULL;
0N/A jobject peer = NULL;
0N/A jobject temp = NULL;
0N/A jboolean validRet = JNI_FALSE;
0N/A
0N/A if ((*env)->EnsureLocalCapacity(env, 2) < 0)
0N/A goto done;
0N/A
0N/A peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
0N/A if (peer == NULL)
0N/A goto done;
0N/A
0N/A componentFonts = (jobjectArray)
0N/A (*env)->GetObjectField(env,peer,platformFontIDs.componentFonts);
0N/A
0N/A if (componentFonts == NULL)
0N/A goto done;
0N/A
0N/A num = (*env)->GetArrayLength(env, componentFonts);
0N/A
0N/A for (i = 0; i < num; i++) {
0N/A temp = (*env)->GetObjectArrayElement(env, componentFonts, i);
0N/A
0N/A if ((*env)->IsSameObject(env, fd, temp)) {
0N/A validRet = JNI_TRUE;
0N/A break;
0N/A }
0N/A (*env)->DeleteLocalRef(env, temp);
0N/A }
0N/A
0N/A done:
0N/A (*env)->DeleteLocalRef(env, peer);
0N/A (*env)->DeleteLocalRef(env, componentFonts);
0N/A
0N/A if (validRet)
0N/A return i;
0N/A
0N/A return 0;
0N/A}
0N/A#ifndef XAWT
0N/Ajobject
0N/AawtJNI_GetFont(JNIEnv * env, jobject this)
0N/A{
0N/A jobject target = NULL;
0N/A jobject font = NULL;
0N/A
0N/A target = (*env)->GetObjectField(env, this, mComponentPeerIDs.target);
0N/A // SECURITY: Must call _NoClientCode() methods to ensure that we
0N/A // are not invoking client code on the privileged thread
0N/A font = JNU_CallMethodByName(env,
0N/A NULL,
0N/A target,
0N/A "getFont_NoClientCode",
0N/A "()Ljava/awt/Font;").l;
0N/A (*env)->DeleteLocalRef(env, target);
0N/A return font;
0N/A}
0N/A#endif
0N/Ajobject
0N/AawtJNI_GetFMFont(JNIEnv * env, jobject this)
0N/A{
0N/A return JNU_CallMethodByName(env, NULL, this, "getFont_NoClientCode",
0N/A "()Ljava/awt/Font;").l;
0N/A}
0N/A
0N/Ajboolean
0N/AawtJNI_IsMultiFont(JNIEnv * env, jobject this)
0N/A{
0N/A jobject peer = NULL;
0N/A jobject fontConfig = NULL;
0N/A
0N/A if (this == NULL) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A peer = (*env)->CallObjectMethod(env,this,fontIDs.getPeer);
0N/A if (peer == NULL) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A fontConfig = (*env)->GetObjectField(env,peer,platformFontIDs.fontConfig);
0N/A (*env)->DeleteLocalRef(env, peer);
0N/A
0N/A if (fontConfig == NULL) {
0N/A return JNI_FALSE;
0N/A }
0N/A (*env)->DeleteLocalRef(env, fontConfig);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Ajboolean
0N/AawtJNI_IsMultiFontMetrics(JNIEnv * env, jobject this)
0N/A{
0N/A jobject peer = NULL;
0N/A jobject fontConfig = NULL;
0N/A jobject font = NULL;
0N/A
0N/A if (JNU_IsNull(env, this)) {
0N/A return JNI_FALSE;
0N/A }
0N/A if ((*env)->EnsureLocalCapacity(env, 3) < 0) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A font = JNU_CallMethodByName(env, NULL, this, "getFont_NoClientCode",
0N/A "()Ljava/awt/Font;").l;
0N/A if (JNU_IsNull(env, font)) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
0N/A (*env)->DeleteLocalRef(env, font);
0N/A
0N/A if (peer == NULL) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A fontConfig = (*env)->GetObjectField(env,peer,platformFontIDs.fontConfig);
0N/A (*env)->DeleteLocalRef(env, peer);
0N/A if (fontConfig == NULL) {
0N/A return JNI_FALSE;
0N/A }
0N/A (*env)->DeleteLocalRef(env, fontConfig);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A#ifndef XAWT
0N/A#ifdef __linux__
0N/AXmString
0N/AunicodeXmStringCreate(char* text, char* tag, int len) {
0N/A XmString ret_val;
0N/A XtProcessLock();
0N/A ret_val = _XmStringNCreate (text, tag, len);
0N/A XtProcessUnlock();
0N/A return ret_val;
0N/A}
0N/A#endif
0N/A
0N/A/*
0N/A * Unicode to Motif Multi Font Compound String converter
0N/A *
0N/A * ASSUMES: We are not running on a privileged thread
0N/A */
0N/AXmString
0N/AawtJNI_MakeMultiFontString(JNIEnv * env, jstring s, jobject font)
0N/A{
0N/A XmString xmstr = NULL, xmtmp1, xmtmp2;
0N/A jobjectArray dataArray = NULL;
0N/A char *err = NULL;
0N/A int32_t stringCount,i;
0N/A int32_t fdnumber;
0N/A struct FontData *fdata = awtJNI_GetFontData(env, font, &err);
0N/A jobject fontDescriptor = NULL;
0N/A jbyteArray data = NULL;
0N/A char *stringData = NULL;
0N/A char tag[BUFSIZ];
0N/A
0N/A if ((*env)->PushLocalFrame(env, 16) < 0)
0N/A return NULL;
0N/A
0N/A if (!JNU_IsNull(env, s) && !JNU_IsNull(env, font)) {
0N/A jobject peer;
0N/A
0N/A peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
0N/A
0N/A DASSERT(!awt_currentThreadIsPrivileged(env));
0N/A dataArray =
0N/A (*env)->CallObjectMethod(
0N/A env,
0N/A peer,
0N/A platformFontIDs.makeConvertedMultiFontString,
0N/A s);
0N/A
0N/A if ((*env)->ExceptionOccurred(env)) {
0N/A (*env)->ExceptionDescribe(env);
0N/A (*env)->ExceptionClear(env);
0N/A
0N/A (*env)->PopLocalFrame(env, NULL);
0N/A return (XmString) NULL;
0N/A }
0N/A
0N/A if(dataArray == NULL) {
0N/A (*env)->PopLocalFrame(env, NULL);
0N/A return (XmString) NULL;
0N/A }
0N/A } else {
0N/A (*env)->PopLocalFrame(env, NULL);
0N/A return (XmString) NULL;
0N/A }
0N/A
0N/A stringCount = (*env)->GetArrayLength(env, dataArray);
0N/A
0N/A for (i = 0; i < stringCount; i+=2) {
0N/A fontDescriptor = (*env)->GetObjectArrayElement(env, dataArray, i);
0N/A data = (*env)->GetObjectArrayElement(env, dataArray, i + 1);
0N/A
0N/A /* Bail if we've finished */
0N/A if(fontDescriptor == NULL || data == NULL)
0N/A break;
0N/A
0N/A fdnumber = awtJNI_GetFontDescriptorNumber(env, font, fontDescriptor);
0N/A fdata = awtJNI_GetFontData(env, font, &err);
0N/A
0N/A makeTag(fdata->flist[fdnumber].charset_name, fdnumber, tag);
0N/A
0N/A stringData = (char *)(*env)->GetPrimitiveArrayCritical(env, data, NULL);
0N/A if(stringData != NULL) {
0N/A unsigned char* buf = stringData;
0N/A int len;
0N/A char *offsetStringData;
0N/A
0N/A offsetStringData = stringData + (4 * sizeof(char));
0N/A#ifdef __linux__
0N/A len = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
0N/A /* Motif XmStringCreate() API requests "text must be a NULL-terminated
0N/A string" and its implementation uses "strlen()" to calculate the length
0N/A of the text string. Unfortunately when we deal with iso10646 font
0N/A on linux, the "text" is requested to be encoded in UTF16, which has the
0N/A posibility of including code points like "0xYY00" ("0xYY" + "0x00") that
0N/A causes problem when XmStringCreate() calls _XmStringNCreate() without
0N/A specifying a specific text lenth (see Motif XmString.c). The workaround is
0N/A to call _XmStringNCreate() directly with specific text length at this
0N/A cirsumstance.
0N/A */
0N/A if (strstr(fdata->flist[fdnumber].charset_name, "UnicodeBigUnmarked"))
0N/A xmtmp1 = unicodeXmStringCreate(offsetStringData, tag, len);
0N/A else
0N/A xmtmp1 = XmStringCreate(offsetStringData, tag);
0N/A if (xmstr == NULL)
0N/A xmstr = xmtmp1;
0N/A else {
0N/A xmtmp2 = XmStringConcat(xmstr, xmtmp1);
0N/A XmStringFree(xmtmp1);
0N/A XmStringFree(xmstr);
0N/A xmstr = xmtmp2;
0N/A }
0N/A#else
0N/A if(xmstr == NULL) {
0N/A xmstr = XmStringCreate(offsetStringData, tag);
0N/A }
0N/A else {
0N/A xmtmp1 = XmStringCreate(offsetStringData, tag);
0N/A xmtmp2 = XmStringConcat(xmstr, xmtmp1);
0N/A XmStringFree(xmtmp1);
0N/A XmStringFree(xmstr);
0N/A xmstr = xmtmp2;
0N/A }
0N/A#endif
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, data, stringData, JNI_ABORT);
0N/A (*env)->DeleteLocalRef(env, fontDescriptor);
0N/A (*env)->DeleteLocalRef(env, data);
0N/A }
0N/A (*env)->PopLocalFrame(env, NULL);
0N/A return xmstr;
0N/A}
0N/A
0N/A/*
0N/A * Find the character encoding for a given font and register that encoding
0N/A * with the given tag. The encoding is the last two fields of the XLFD of
0N/A * the font (converted to uppercase).
0N/A */
0N/Astatic void registerEncoding(char *xlfd, char *tag)
0N/A{
0N/A char *e = xlfd + strlen(xlfd);
0N/A char *ret = NULL;
0N/A
0N/A do { --e; } while (e != xlfd && *e != '-');
0N/A do { --e; } while (e != xlfd && *e != '-');
0N/A if (e != xlfd) {
0N/A char *encoding = strdup(++e);
0N/A char *u = NULL;
0N/A
0N/A for (u = encoding; *u != '\0'; ++u) {
0N/A if (islower(*u)) {
0N/A *u = toupper(*u);
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Motif will core dump on or otherwise mishandle unknown (or
0N/A * non-standard) character encodings (in conversion to compound
0N/A * text, bug 4122785). Register Sun private encodings for
0N/A * Symbol or dingbat fonts as ISO8859-1, which is a lie,
0N/A * but produces predictable results.
0N/A */
0N/A if (strncmp(encoding, "SUN-", 4) == 0) {
0N/A free(encoding);
0N/A encoding = strdup("ISO8859-1");
0N/A }
0N/A ret = XmRegisterSegmentEncoding(tag, encoding);
0N/A if (ret != NULL)
0N/A XtFree(ret);
0N/A free(encoding);
0N/A }
0N/A}
0N/A
0N/A
0N/AXmFontList
0N/AawtJNI_GetFontList(JNIEnv * env, jobject font)
0N/A{
0N/A int32_t i;
0N/A XmFontListEntry fle;
0N/A XmFontList fontlist;
0N/A XFontStruct *xf = NULL;
0N/A int32_t size;
0N/A struct FontData *fdata = NULL;
0N/A char *err = NULL, tag[BUFSIZ];
0N/A
0N/A fdata = awtJNI_GetFontData(env, font, &err);
0N/A
0N/A makeTag(fdata->flist[0].charset_name, 0, tag);
0N/A
0N/A size = (int32_t) (*env)->GetIntField(env, font, fontIDs.size);
0N/A
0N/A if (fdata->flist[0].load == 0) {
0N/A xf = loadFont(awt_display, fdata->flist[0].xlfd, size * 10);
0N/A
0N/A if (xf == NULL) {
0N/A /* printf("Cannot load font: %s\n", fdata->list[0].xlfd); */
0N/A } else {
0N/A fdata->flist[0].xfont = xf;
0N/A fdata->flist[0].load = 1;
0N/A
0N/A if (xf->min_byte1 == 0 && xf->max_byte1 == 0)
0N/A fdata->flist[0].index_length = 1;
0N/A else
0N/A fdata->flist[0].index_length = 2;
0N/A }
0N/A }
0N/A registerEncoding(fdata->flist[0].xlfd, tag);
0N/A fle = XmFontListEntryCreate(tag, XmFONT_IS_FONT,
0N/A (XtPointer) fdata->flist[0].xfont);
0N/A
0N/A fontlist = XmFontListAppendEntry(NULL, fle);
0N/A /*
0N/A * Some versions of motif have a bug in
0N/A * XmFontListEntryFree() which causes it to free more than it
0N/A * should. Use XtFree() is used instead. See O'Reilly's
0N/A * Motif Reference Manual for more information.
0N/A */
0N/A XmFontListEntryFree(&fle);
0N/A
0N/A for (i = 1; i < fdata->charset_num; i++) {
0N/A makeTag(fdata->flist[i].charset_name, i, tag);
0N/A
0N/A if (fdata->flist[i].load == 0) {
0N/A xf = loadFont(awt_display, fdata->flist[i].xlfd, size * 10);
0N/A
0N/A if (xf == NULL) {
0N/A /* printf("Cannot load font: %s\n", fdata->flist[0].xlfd); */
0N/A continue;
0N/A }
0N/A fdata->flist[i].xfont = xf;
0N/A fdata->flist[i].load = 1;
0N/A if (xf->min_byte1 == 0 && xf->max_byte1 == 0) {
0N/A fdata->flist[i].index_length = 1;
0N/A } else {
0N/A fdata->flist[i].index_length = 2;
0N/A }
0N/A }
0N/A registerEncoding(fdata->flist[i].xlfd, tag);
0N/A fle = XmFontListEntryCreate(tag, XmFONT_IS_FONT,
0N/A (XtPointer) fdata->flist[i].xfont);
0N/A fontlist = XmFontListAppendEntry(fontlist, fle);
0N/A /*
0N/A * Some versions of motif have a bug in
0N/A * XmFontListEntryFree() which causes it to free more than it
0N/A * should. Use XtFree() instead. See O'Reilly's
0N/A * Motif Reference Manual for more information.
0N/A */
0N/A XmFontListEntryFree(&fle);
0N/A }
0N/A
0N/A return fontlist;
0N/A}
0N/A#endif
0N/A/* #define FONT_DEBUG 2 */
0N/A
0N/AXFontSet
0N/AawtJNI_MakeFontSet(JNIEnv * env, jobject font)
0N/A{
0N/A jstring xlfd = NULL;
0N/A char *xfontset = NULL;
0N/A int32_t size;
0N/A int32_t length = 0;
0N/A char *realxlfd = NULL, *ptr = NULL, *prev = NULL;
0N/A char **missing_list = NULL;
0N/A int32_t missing_count;
0N/A char *def_string = NULL;
0N/A XFontSet xfs;
0N/A jobject peer = NULL;
0N/A jstring xfsname = NULL;
0N/A#ifdef FONT_DEBUG
0N/A char xx[1024];
0N/A#endif
0N/A
0N/A if ((*env)->EnsureLocalCapacity(env, 2) < 0)
0N/A return 0;
0N/A
0N/A size = (*env)->GetIntField(env, font, fontIDs.size) * 10;
0N/A
0N/A peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
0N/A xfsname = (*env)->GetObjectField(env, peer, mFontPeerIDs.xfsname);
0N/A
0N/A if (JNU_IsNull(env, xfsname))
0N/A xfontset = "";
0N/A else
0N/A xfontset = (char *)JNU_GetStringPlatformChars(env, xfsname, NULL);
0N/A
0N/A realxlfd = malloc(strlen(xfontset) + 50);
0N/A
0N/A prev = ptr = xfontset;
0N/A while ((ptr = strstr(ptr, "%d"))) {
0N/A char save = *(ptr + 2);
0N/A
0N/A *(ptr + 2) = '\0';
0N/A jio_snprintf(realxlfd + length, strlen(xfontset) + 50 - length,
0N/A prev, size);
0N/A length = strlen(realxlfd);
0N/A *(ptr + 2) = save;
0N/A
0N/A prev = ptr + 2;
0N/A ptr += 2;
0N/A }
0N/A strcpy(realxlfd + length, prev);
0N/A
0N/A#ifdef FONT_DEBUG
0N/A strcpy(xx, realxlfd);
0N/A#endif
0N/A xfs = XCreateFontSet(awt_display, realxlfd, &missing_list,
0N/A &missing_count, &def_string);
0N/A#if FONT_DEBUG >= 2
0N/A fprintf(stderr, "XCreateFontSet(%s)->0x%x\n", xx, xfs);
0N/A#endif
0N/A
0N/A#if FONT_DEBUG
0N/A if (missing_count != 0) {
0N/A int32_t i;
0N/A fprintf(stderr, "XCreateFontSet missing %d fonts:\n", missing_count);
0N/A for (i = 0; i < missing_count; ++i) {
0N/A fprintf(stderr, "\t\"%s\"\n", missing_list[i]);
0N/A }
0N/A fprintf(stderr, " requested \"%s\"\n", xx);
0N/A#if FONT_DEBUG >= 3
0N/A exit(-1);
0N/A#endif
0N/A }
0N/A#endif
0N/A
0N/A free((void *)realxlfd);
0N/A
0N/A if (xfontset && !JNU_IsNull(env, xfsname))
0N/A JNU_ReleaseStringPlatformChars(env, xfsname, (const char *) xfontset);
0N/A
0N/A (*env)->DeleteLocalRef(env, peer);
0N/A (*env)->DeleteLocalRef(env, xfsname);
0N/A return xfs;
0N/A}
0N/A
0N/A/*
0N/A * get multi font string width with multiple X11 font
0N/A *
0N/A * ASSUMES: We are not running on a privileged thread
0N/A */
0N/Aint32_t
0N/AawtJNI_GetMFStringWidth(JNIEnv * env, jcharArray s, int offset, int sLength, jobject font)
0N/A{
0N/A char *err = NULL;
0N/A unsigned char *stringData = NULL;
0N/A char *offsetStringData = NULL;
0N/A int32_t stringCount, i;
0N/A int32_t size;
0N/A struct FontData *fdata = NULL;
0N/A jobject fontDescriptor = NULL;
0N/A jbyteArray data = NULL;
0N/A int32_t j;
0N/A int32_t width = 0;
0N/A int32_t length;
0N/A XFontStruct *xf = NULL;
0N/A jobjectArray dataArray = NULL;
0N/A#ifndef XAWT
0N/A DASSERT(!awt_currentThreadIsPrivileged(env));
0N/A#endif
0N/A if ((*env)->EnsureLocalCapacity(env, 3) < 0)
0N/A return 0;
0N/A
0N/A if (!JNU_IsNull(env, s) && !JNU_IsNull(env, font))
0N/A {
0N/A jobject peer;
0N/A peer = (*env)->CallObjectMethod(env,font,fontIDs.getPeer);
0N/A
0N/A dataArray = (*env)->CallObjectMethod(
0N/A env,
0N/A peer,
0N/A platformFontIDs.makeConvertedMultiFontChars,
0N/A s, offset, sLength);
0N/A
0N/A if ((*env)->ExceptionOccurred(env))
0N/A {
0N/A (*env)->ExceptionDescribe(env);
0N/A (*env)->ExceptionClear(env);
0N/A }
0N/A
0N/A (*env)->DeleteLocalRef(env, peer);
0N/A
0N/A if(dataArray == NULL)
0N/A {
0N/A return 0;
0N/A }
0N/A } else {
0N/A return 0;
0N/A }
0N/A
0N/A fdata = awtJNI_GetFontData(env, font, &err);
0N/A
0N/A stringCount = (*env)->GetArrayLength(env, dataArray);
0N/A
0N/A size = (*env)->GetIntField(env, font, fontIDs.size);
0N/A
0N/A for (i = 0; i < stringCount; i+=2)
0N/A {
0N/A fontDescriptor = (*env)->GetObjectArrayElement(env, dataArray, i);
0N/A data = (*env)->GetObjectArrayElement(env, dataArray, i + 1);
0N/A
0N/A /* Bail if we've finished */
0N/A if (fontDescriptor == NULL || data == NULL) {
0N/A (*env)->DeleteLocalRef(env, fontDescriptor);
0N/A (*env)->DeleteLocalRef(env, data);
0N/A break;
0N/A }
0N/A
0N/A j = awtJNI_GetFontDescriptorNumber(env, font, fontDescriptor);
0N/A
0N/A if (fdata->flist[j].load == 0) {
0N/A xf = loadFont(awt_display,
0N/A fdata->flist[j].xlfd, size * 10);
0N/A if (xf == NULL) {
0N/A (*env)->DeleteLocalRef(env, fontDescriptor);
0N/A (*env)->DeleteLocalRef(env, data);
0N/A continue;
0N/A }
0N/A fdata->flist[j].load = 1;
0N/A fdata->flist[j].xfont = xf;
0N/A if (xf->min_byte1 == 0 && xf->max_byte1 == 0)
0N/A fdata->flist[j].index_length = 1;
0N/A else
0N/A fdata->flist[j].index_length = 2;
0N/A }
0N/A xf = fdata->flist[j].xfont;
0N/A
0N/A stringData =
0N/A (unsigned char *)(*env)->GetPrimitiveArrayCritical(env, data,NULL);
0N/A length = (stringData[0] << 24) | (stringData[1] << 16) |
0N/A (stringData[2] << 8) | stringData[3];
0N/A offsetStringData = (char *)(stringData + (4 * sizeof(char)));
0N/A
0N/A if (fdata->flist[j].index_length == 2) {
0N/A width += XTextWidth16(xf, (XChar2b *)offsetStringData, length/2);
0N/A } else {
0N/A width += XTextWidth(xf, offsetStringData, length);
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, data, stringData, JNI_ABORT);
0N/A (*env)->DeleteLocalRef(env, fontDescriptor);
0N/A (*env)->DeleteLocalRef(env, data);
0N/A }
0N/A (*env)->DeleteLocalRef(env, dataArray);
0N/A
0N/A return width;
0N/A}