diff options
32 files changed, 6049 insertions, 5470 deletions
diff --git a/libX11/modules/im/ximcp/imCallbk.c b/libX11/modules/im/ximcp/imCallbk.c index 866b27c64..761021354 100644 --- a/libX11/modules/im/ximcp/imCallbk.c +++ b/libX11/modules/im/ximcp/imCallbk.c @@ -1,752 +1,754 @@ -/*********************************************************************** -Copyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts, -Copyright 1994 by FUJITSU LIMITED -Copyright 1994 by Sony Corporation - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital, FUJITSU -LIMITED and Sony Corporation not be used in advertising or publicity -pertaining to distribution of the software without specific, written -prior permission. - -DIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED -AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - Author: Hiroyuki Miyamoto Digital Equipment Corporation - miyamoto@jrd.dec.com - Modifier: Takashi Fujiwara FUJITSU LIMITED - fujiwara@a80.tech.yk.fujitsu.co.jp - Makoto Wakamatsu Sony Corporation - makoto@sm.sony.co.jp - -***********************************************************************/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "Xlibint.h" -#include "Xlcint.h" -#include "Ximint.h" -#include "XlcPubI.h" -#ifdef X_LOCALE -#define mblen(a,b) _Xmblen(a,b) -extern int _Xmblen (); -#endif - -#define sz_CARD8 1 -#define sz_INT8 1 -#define sz_CARD16 2 -#define sz_INT16 2 -#define sz_BITMASK16 sz_CARD16 -#define sz_CARD32 4 -#define sz_INT32 4 -#define sz_BITMASK32 sz_CARD32 -#define sz_XIMID sizeof(XIMID) -#define sz_XICID sizeof(XICID) -#define sz_XIMATTRID sizeof(XIMATTRID) -#define sz_XICATTRID sizeof(XICATTRID) -#define sz_ximPacketHeader (XIM_HEADER_SIZE + sz_XIMID + sz_XICID) -#define sz_ximGeometry 0 -#define sz_ximStrConversion (sz_CARD32 + sz_CARD32 + sz_CARD32 + sz_CARD32) -#define sz_ximPreeditStart 0 -#define sz_ximPreeditStartReply sz_INT32 -#define sz_ximPreeditCaret (sz_INT32 + sz_CARD32 + sz_CARD32) -#define sz_ximPreeditCaretReply sz_CARD32 -#define sz_ximPreeditDone 0 -#define sz_ximStatusStart 0 -#define sz_ximStatusDone 0 - -typedef enum { - XimCbSuccess, - XimCbNoCallback, - XimCbError, - XimCbQueued, - XimCbBadContextID, - XimCbBadOpcode -} XimCbStatus; - -typedef XimCbStatus (*XimCb)( - Xim, Xic, char*, int - ); - -#define PACKET_TO_MAJOROPCODE(p) (*(CARD8*)((CARD8*)(p))) -#define PACKET_TO_MINOROPCODE(p) (*(CARD8*)((CARD8*)(p) + sz_CARD8)) -#define PACKET_TO_LENGTH(p) (*(CARD16*)((CARD8*)(p) + sz_CARD8 + sz_CARD8)) -#define PACKET_TO_IMID(p) (*(XIMID*)((CARD8*)(p) + XIM_HEADER_SIZE)) -#define PACKET_TO_ICID(p) (*(XICID*)((CARD8*)(p) + XIM_HEADER_SIZE + sz_XIMID)) - -#define _XimWriteData(im,len,data) \ - (im->private.proto.write((im),(len),(XPointer)(data))) -#define _XimReadData(im,buf,buf_len,len) \ - (im->private.proto.read((im),(XPointer)(buf),(buf_len),&(len))) -#define _XimFlushData(im) im->private.proto.flush((im)) - -Private XimCbStatus _XimGeometryCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimStrConversionCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimPreeditStartCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimPreeditDoneCallback(Xim, Xic, char*, int); -Private void _free_memory_for_text(XIMText*); -Private XimCbStatus _XimPreeditDrawCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimPreeditCaretCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimStatusStartCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimStatusDoneCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimStatusDrawCallback(Xim, Xic, char*, int); -Private XimCbStatus _XimPreeditStateNotifyCallback(Xim, Xic, char *, int); - -#if defined(__STDC__) && ((defined(sun) && defined(SVR4)) || defined(WIN32)) -#define RConst /**/ -#else -#define RConst const -#endif - -/* NOTE: - * the table below depends on the protocol number - * defined in the IM Protocol document. - */ -static RConst XimCb callback_table[] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #000-009 */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #010-019 */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #020-029 */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #030-039 */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #040-049 */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #050-059 */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #060-069 */ - _XimGeometryCallback, /* #070 */ - _XimStrConversionCallback, /* #071 */ - NULL, /* #072 */ - _XimPreeditStartCallback, /* #073 */ - NULL, /* #074 */ - _XimPreeditDrawCallback, /* #075 */ - _XimPreeditCaretCallback, /* #076 */ - NULL, /* #077 */ - _XimPreeditDoneCallback, /* #078 */ - _XimStatusStartCallback, /* #079 */ - _XimStatusDrawCallback, /* #080 */ - _XimStatusDoneCallback, /* #081 */ - _XimPreeditStateNotifyCallback /* #082 */ - }; - - -Private Bool -_XimIsReadyForProcess(Xic ic) -{ - return(!ic->private.proto.waitCallback); /* check HM */ -} - -Private void -_XimProcessPendingCallbacks(Xic ic) -{ - XimPendingCallback pcbq; - - while (((pcbq = ic->private.proto.pend_cb_que) != (XimPendingCallback)NULL) - && _XimIsReadyForProcess(ic)) { - (void) (*callback_table[pcbq->major_opcode])(pcbq->im, - pcbq->ic, - pcbq->proto, - pcbq->proto_len); - ic->private.proto.pend_cb_que = pcbq->next; - Xfree(pcbq->proto); /* free memory of XimPendingCallback */ - Xfree(pcbq); - } -} - -Private void -_XimPutCbIntoQueue(Xic ic, XimPendingCallback call_data) -{ - XimPendingCallback pcbq = ic->private.proto.pend_cb_que; - - /* Queuing is FIFO - */ - while (pcbq != (XimPendingCallback)NULL) { - if (pcbq->next == (XimPendingCallback)NULL) { - break; - } - pcbq = pcbq->next; - } - if (pcbq == (XimPendingCallback)NULL) { - ic->private.proto.pend_cb_que = call_data; - } - else { - pcbq->next = call_data; - } -} - -Public Bool -_XimCbDispatch(Xim xim, - INT16 len, - XPointer data, - XPointer call_data) -{ - /* `data' points to the beginning of the packet defined in IM Protocol doc. - */ - int major_opcode = PACKET_TO_MAJOROPCODE(data); - XIMID imid = PACKET_TO_IMID(data); - XICID icid = PACKET_TO_ICID(data); - Xim im = (Xim)call_data; /* check HM */ - Xic ic = _XimICOfXICID(im, icid); - char* proto; - int proto_len; - - /* check validity of im/ic - */ - if ((imid != im->private.proto.imid) || !ic) { - return False; /* status = XimCbBadContextID; */ - } - - /* process pending callbacks - */ - _XimProcessPendingCallbacks(ic); - - /* check if the protocol should be processed here - */ - if (major_opcode > 82) { - return False; /* status = XimCbBadOpcode; */ - } - if (!callback_table[major_opcode]) { - return False; /* status = XimCbBadOpcode; */ - } - - /* move the pointer ahead by the IM Protocol packet header size - */ - proto = (char*)data + sz_ximPacketHeader; - proto_len = (int)len - sz_ximPacketHeader; - - /* check if it can be processed right away - * and if no, queue the protocol, otherwise invoke a callback - */ - if (!_XimIsReadyForProcess(ic)) { - - /* queue the protocol - */ - XimPendingCallback pcb; - char *proto_buf = (proto_len > 0) ? (char*)Xmalloc(proto_len) : NULL; - - pcb = (XimPendingCallback)Xmalloc(sizeof(XimPendingCallbackRec)); - if (pcb && (proto_len <= 0 || proto_buf)) { - if (proto_len > 0) - memcpy(proto_buf, proto, proto_len); - - pcb->major_opcode = major_opcode; - pcb->im = im; - pcb->ic = ic; - pcb->proto = proto_buf; - pcb->proto_len = proto_len; - pcb->next = (XimPendingCallback)NULL; /* queue is FIFO */ - _XimPutCbIntoQueue(ic, pcb); - /* status = XimCbQueued; */ - } else { - /* status = XimCbError; */ - } - } - else { - /* invoke each callback according to the major opcode. - * `proto' points to the next address of IM-ID and IC-ID. - * `proto_len' specifies the packet length. - */ - (void) (*callback_table[major_opcode])(im, ic, proto, proto_len); - } - return True; -} - -Private XimCbStatus -_XimGeometryCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.geometry_callback; - - /* invoke the callack - */ - if (cb && cb->callback) { - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); - } - else { - - /* no callback registered - */ - return XimCbNoCallback; - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimStrConversionCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.string_conversion_callback; /* check HM */ - XIMStringConversionCallbackStruct cbrec; - - /* invoke the callback - */ - if (cb && cb->callback) { - int p = XIM_HEADER_SIZE; - cbrec.position = (XIMStringConversionPosition) - *(CARD32*)&proto[p]; p += sz_CARD32; - cbrec.direction = (XIMCaretDirection) - *(CARD32*)&proto[p]; p += sz_CARD32; - cbrec.operation = (XIMStringConversionOperation) - *(CARD32*)&proto[p]; p += sz_CARD32; - cbrec.factor = (unsigned short) - *(CARD32*)&proto[p]; - - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbrec); - } - else { - - /* no callback registered - */ - _XimError(im, ic, - (CARD16)XIM_BadSomething, - (INT16)len, - (CARD16)XIM_STR_CONVERSION, - (char*)proto); /* send XIM_ERROR */ - return XimCbNoCallback; - } - - /* send a reply - */ - { - CARD8 *buf; - INT16 buf_len; - int p, length_in_bytes, i; - - /* Assumption: - * `cbrec.text->length' means the string length in characters - */ - { - length_in_bytes = (cbrec.text->encoding_is_wchar)? - sizeof(wchar_t) * cbrec.text->length: /* wchar */ - strlen(cbrec.text->string.mbs); /* mb */ - buf_len = XIM_HEADER_SIZE + - sz_CARD16 + - 2 + length_in_bytes + - XIM_PAD(2 + length_in_bytes) + - 2 + 2 + sz_CARD32 * cbrec.text->length; - buf = (CARD8*)Xmalloc(buf_len); - } - _XimSetHeader((XPointer)buf, XIM_STR_CONVERSION_REPLY, 0, &buf_len); - buf_len -= XIM_HEADER_SIZE; /* added by _XimSetHeader (HACK) */ - p = XIM_HEADER_SIZE; - *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16; - *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16; - *(CARD16*)&buf[p] = (CARD16)cbrec.text->length; p += sz_CARD16; - memcpy(&buf[p],&cbrec.text->string.mbs,length_in_bytes); - p += length_in_bytes; - *(CARD16*)&buf[p] = (CARD16)(sz_CARD32*cbrec.text->length); - p += XIM_PAD(2); - for (i = 0; i < (int)cbrec.text->length; i++) { - *(CARD32*)&buf[p] = (CARD32)cbrec.text->feedback[i]; - p += sz_CARD32; - } - - if (!(_XimWriteData(im, buf_len, buf))) { - return XimCbError; - } - _XimFlushData(im); - - Xfree(buf); - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimPreeditStartCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.preedit_attr.start_callback; - int ret; - - /* invoke the callback - */ - if (cb && cb->callback){ - ret = (*(cb->callback))((XIC)ic, cb->client_data, (XPointer)NULL); - } - else { - - /* no callback registered - */ - _XimError(im, ic, - (CARD16)XIM_BadSomething, - (INT16)len, - (CARD16)XIM_PREEDIT_START, - (char*)proto); /* send XIM_ERROR */ - return XimCbNoCallback; - } - - /* send a reply - */ - { - CARD32 buf32[(sz_ximPacketHeader + sz_ximPreeditStartReply) / 4]; - CARD8 *buf = (CARD8 *)buf32; - INT16 buf_len = sz_XIMID + sz_XICID + sz_ximPreeditStartReply; - int p; - - _XimSetHeader((XPointer)buf, XIM_PREEDIT_START_REPLY, 0, &buf_len); - p = XIM_HEADER_SIZE; - *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16; - *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16; - *(INT32*)&buf[p] = (INT32)ret; - - if (!(_XimWriteData(im, buf_len, buf))) { - return XimCbError; - } - _XimFlushData(im); - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimPreeditDoneCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.preedit_attr.done_callback; - - /* invoke the callback - */ - if (cb && cb->callback) { - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); - } - else { - - /* no callback registered - */ - return XimCbNoCallback; - } - - return XimCbSuccess; -} - -Private void -_read_text_from_packet(Xim im, - char* buf, - XIMText** text_ptr) -{ - int status; - XIMText* text; - int tmp_len; - char* tmp_buf; - Status s = 0; - - status = (int)*(BITMASK32*)buf; buf += sz_BITMASK32; - - /* string part - */ - if (status & 0x00000001) /* "no string" bit on */ { - buf += sz_CARD16; /* skip "length of preedit string" */ - buf += 2; /* pad */ - *text_ptr = (XIMText*)NULL; - return; - } - - *text_ptr = text = (XIMText*)Xmalloc(sizeof(XIMText)); - if (text == (XIMText*)NULL) return; - - tmp_len = (int)*(CARD16*)buf; - buf += sz_CARD16; - if ((tmp_buf = (char*)Xmalloc(tmp_len + 1))) { - memcpy(tmp_buf, buf, tmp_len); - tmp_buf[tmp_len] = '\0'; - - text->encoding_is_wchar = False; - text->length = im->methods->ctstombs((XIM)im, - tmp_buf, tmp_len, - NULL, 0, &s); /* CT? HM */ - if (s != XLookupNone) { -#ifndef NO_DEC_I18N_FIX - /* Allow for NULL-terminated */ - if ((text->string.multi_byte = - (char*)Xmalloc(text->length * - XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) { -#else - if (text->string.multi_byte = (char*)Xmalloc(text->length+1)) { -#endif - int tmp; -#ifndef NO_DEC_I18N_FIX - char *char_tmp; - int char_len; -#endif - tmp = im->methods->ctstombs((XIM)im, - tmp_buf, tmp_len, -#ifndef NO_DEC_I18N_FIX - text->string.multi_byte, - text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1, -#else - text->string.multi_byte, text->length, -#endif - &s); - text->string.multi_byte[tmp] = '\0'; -#ifndef NO_DEC_I18N_FIX - text->length = 0; - char_tmp = text->string.multi_byte; - while (*char_tmp != '\0') { - char_len = mblen(char_tmp, strlen(char_tmp)); - char_tmp = char_tmp + char_len; - (text->length)++; - } -#endif - } - } - else { - text->length = 0; - text->string.multi_byte = NULL; - } - - Xfree(tmp_buf); - } - buf += tmp_len; - - buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */ - - /* feedback part - */ - if (status & 0x00000002) /* "no feedback" bit on */ { - text->feedback = (XIMFeedback*)NULL; - } - else { - int i, j; - - i = (int)*(CARD16*)buf; buf += sz_CARD16; - buf += sz_CARD16; /* skip `unused' */ - text->feedback = (XIMFeedback*)Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32))); - j = 0; - while (i > 0) { - text->feedback[j] = (XIMFeedback)*(CARD32*)buf; - buf += sz_CARD32; - i -= sz_CARD32; - j++; - } - /* - * text->length tells how long both the status string and - * the feedback array are. If there's "no string" the - * text->length was set to zero previously. See above. - * But if there is feedback (i.e. not "no feedback") then - * we need to convey the length of the feedback array. - * It might have been better if the protocol sent two - * different values, one for the length of the status - * string and one for the length of the feedback array. - */ - if (status & 0x00000001) /* "no string" bit on */ { - text->length = j; - } - } -} - -Private void -_free_memory_for_text(XIMText* text) -{ - if (text) { - if (text->string.multi_byte) - Xfree(text->string.multi_byte); - if (text->feedback) - Xfree(text->feedback); - Xfree(text); - } -} - -Private XimCbStatus -_XimPreeditDrawCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.preedit_attr.draw_callback; - XIMPreeditDrawCallbackStruct cbs; - - /* invoke the callback - */ - if (cb && cb->callback) { - cbs.caret = (int)*(INT32*)proto; proto += sz_INT32; - cbs.chg_first = (int)*(INT32*)proto; proto += sz_INT32; - cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32; - _read_text_from_packet(im, proto, &cbs.text); - - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); - - _free_memory_for_text((XIMText*)cbs.text); - } - else { - - /* no callback registered - */ - return XimCbNoCallback; - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimPreeditCaretCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.preedit_attr.caret_callback; - XIMPreeditCaretCallbackStruct cbs; - - /* invoke the callback - */ - if (cb && cb->callback) { - cbs.position = (int)*(INT32*)proto; proto += sz_INT32; - cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32; - cbs.style = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32; - - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); - } - else { - - /* no callback registered - */ - _XimError(im, ic, - (CARD16)XIM_BadSomething, - (INT16)len, - (CARD16)XIM_PREEDIT_CARET, - (char*)proto); /* send XIM_ERROR */ - return XimCbNoCallback; - } - - /* Send a reply - */ - { - CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply]; - INT16 len = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply; - int p; - - _XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &len); - p = XIM_HEADER_SIZE; - *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16; - *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16; - *(CARD32*)&buf[p] = (CARD32)cbs.position; - - if (!(_XimWriteData(im, len, buf))) { - return XimCbError; - } - _XimFlushData(im); - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimStatusStartCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.status_attr.start_callback; - - /* invoke the callback - */ - if (cb && cb->callback) { - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); - } - else { - - /* no callback registered - */ - return XimCbNoCallback; - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimStatusDoneCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.status_attr.done_callback; - - /* invoke the callback - */ - if (cb && cb->callback) { - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); - } - else { - - /* no callback registered - */ - return XimCbNoCallback; - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimStatusDrawCallback(Xim im, - Xic ic, - char* proto, - int len) -{ - XICCallback* cb = &ic->core.status_attr.draw_callback; - XIMStatusDrawCallbackStruct cbs; - - /* invoke the callback - */ - if (cb && cb->callback) { - cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32; - if (cbs.type == XIMTextType) { - _read_text_from_packet(im, proto, &cbs.data.text); - } - else if (cbs.type == XIMBitmapType) { - cbs.data.bitmap = (Pixmap)*(CARD32*)proto; - } - - (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); - - if (cbs.type == XIMTextType) - _free_memory_for_text((XIMText *)cbs.data.text); - } - else { - - /* no callback registered - */ - return XimCbNoCallback; - } - - return XimCbSuccess; -} - -Private XimCbStatus -_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len ) -{ - XICCallback *cb = &ic->core.preedit_attr.state_notify_callback; - - /* invoke the callack - */ - if( cb && cb->callback ) { - XIMPreeditStateNotifyCallbackStruct cbrec; - - cbrec.state = *(BITMASK32 *)proto; - (*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec ); - } - else { - /* no callback registered - */ - return XimCbNoCallback; - } - - return XimCbSuccess; -} - +/***********************************************************************
+Copyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
+Copyright 1994 by FUJITSU LIMITED
+Copyright 1994 by Sony Corporation
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital, FUJITSU
+LIMITED and Sony Corporation not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+
+DIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED
+AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+ Author: Hiroyuki Miyamoto Digital Equipment Corporation
+ miyamoto@jrd.dec.com
+ Modifier: Takashi Fujiwara FUJITSU LIMITED
+ fujiwara@a80.tech.yk.fujitsu.co.jp
+ Makoto Wakamatsu Sony Corporation
+ makoto@sm.sony.co.jp
+
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "Xlibint.h"
+#include "Xlcint.h"
+#include "Ximint.h"
+#include "XlcPubI.h"
+#ifdef X_LOCALE
+#define mblen(a,b) _Xmblen(a,b)
+extern int _Xmblen ();
+#endif
+
+#define sz_CARD8 1
+#define sz_INT8 1
+#define sz_CARD16 2
+#define sz_INT16 2
+#define sz_BITMASK16 sz_CARD16
+#define sz_CARD32 4
+#define sz_INT32 4
+#define sz_BITMASK32 sz_CARD32
+#define sz_XIMID sizeof(XIMID)
+#define sz_XICID sizeof(XICID)
+#define sz_XIMATTRID sizeof(XIMATTRID)
+#define sz_XICATTRID sizeof(XICATTRID)
+#define sz_ximPacketHeader (XIM_HEADER_SIZE + sz_XIMID + sz_XICID)
+#define sz_ximGeometry 0
+#define sz_ximStrConversion (sz_CARD32 + sz_CARD32 + sz_CARD32 + sz_CARD32)
+#define sz_ximPreeditStart 0
+#define sz_ximPreeditStartReply sz_INT32
+#define sz_ximPreeditCaret (sz_INT32 + sz_CARD32 + sz_CARD32)
+#define sz_ximPreeditCaretReply sz_CARD32
+#define sz_ximPreeditDone 0
+#define sz_ximStatusStart 0
+#define sz_ximStatusDone 0
+
+typedef enum {
+ XimCbSuccess,
+ XimCbNoCallback,
+ XimCbError,
+ XimCbQueued,
+ XimCbBadContextID,
+ XimCbBadOpcode
+} XimCbStatus;
+
+typedef XimCbStatus (*XimCb)(
+ Xim, Xic, char*, int
+ );
+
+#define PACKET_TO_MAJOROPCODE(p) (*(CARD8*)((CARD8*)(p)))
+#define PACKET_TO_MINOROPCODE(p) (*(CARD8*)((CARD8*)(p) + sz_CARD8))
+#define PACKET_TO_LENGTH(p) (*(CARD16*)((CARD8*)(p) + sz_CARD8 + sz_CARD8))
+#define PACKET_TO_IMID(p) (*(XIMID*)((CARD8*)(p) + XIM_HEADER_SIZE))
+#define PACKET_TO_ICID(p) (*(XICID*)((CARD8*)(p) + XIM_HEADER_SIZE + sz_XIMID))
+
+#define _XimWriteData(im,len,data) \
+ (im->private.proto.write((im),(len),(XPointer)(data)))
+#define _XimReadData(im,buf,buf_len,len) \
+ (im->private.proto.read((im),(XPointer)(buf),(buf_len),&(len)))
+#define _XimFlushData(im) im->private.proto.flush((im))
+
+Private XimCbStatus _XimGeometryCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimStrConversionCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimPreeditStartCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimPreeditDoneCallback(Xim, Xic, char*, int);
+Private void _free_memory_for_text(XIMText*);
+Private XimCbStatus _XimPreeditDrawCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimPreeditCaretCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimStatusStartCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimStatusDoneCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimStatusDrawCallback(Xim, Xic, char*, int);
+Private XimCbStatus _XimPreeditStateNotifyCallback(Xim, Xic, char *, int);
+
+#if defined(__STDC__) && ((defined(sun) && defined(SVR4)) || defined(WIN32))
+#define RConst /**/
+#else
+#define RConst const
+#endif
+
+/* NOTE:
+ * the table below depends on the protocol number
+ * defined in the IM Protocol document.
+ */
+static RConst XimCb callback_table[] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #000-009 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #010-019 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #020-029 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #030-039 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #040-049 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #050-059 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #060-069 */
+ _XimGeometryCallback, /* #070 */
+ _XimStrConversionCallback, /* #071 */
+ NULL, /* #072 */
+ _XimPreeditStartCallback, /* #073 */
+ NULL, /* #074 */
+ _XimPreeditDrawCallback, /* #075 */
+ _XimPreeditCaretCallback, /* #076 */
+ NULL, /* #077 */
+ _XimPreeditDoneCallback, /* #078 */
+ _XimStatusStartCallback, /* #079 */
+ _XimStatusDrawCallback, /* #080 */
+ _XimStatusDoneCallback, /* #081 */
+ _XimPreeditStateNotifyCallback /* #082 */
+ };
+
+
+Private Bool
+_XimIsReadyForProcess(Xic ic)
+{
+ return(!ic->private.proto.waitCallback); /* check HM */
+}
+
+Private void
+_XimProcessPendingCallbacks(Xic ic)
+{
+ XimPendingCallback pcbq;
+
+ while (((pcbq = ic->private.proto.pend_cb_que) != (XimPendingCallback)NULL)
+ && _XimIsReadyForProcess(ic)) {
+ (void) (*callback_table[pcbq->major_opcode])(pcbq->im,
+ pcbq->ic,
+ pcbq->proto,
+ pcbq->proto_len);
+ ic->private.proto.pend_cb_que = pcbq->next;
+ Xfree(pcbq->proto); /* free memory of XimPendingCallback */
+ Xfree(pcbq);
+ }
+}
+
+Private void
+_XimPutCbIntoQueue(Xic ic, XimPendingCallback call_data)
+{
+ XimPendingCallback pcbq = ic->private.proto.pend_cb_que;
+
+ /* Queuing is FIFO
+ */
+ while (pcbq != (XimPendingCallback)NULL) {
+ if (pcbq->next == (XimPendingCallback)NULL) {
+ break;
+ }
+ pcbq = pcbq->next;
+ }
+ if (pcbq == (XimPendingCallback)NULL) {
+ ic->private.proto.pend_cb_que = call_data;
+ }
+ else {
+ pcbq->next = call_data;
+ }
+}
+
+Public Bool
+_XimCbDispatch(Xim xim,
+ INT16 len,
+ XPointer data,
+ XPointer call_data)
+{
+ /* `data' points to the beginning of the packet defined in IM Protocol doc.
+ */
+ int major_opcode = PACKET_TO_MAJOROPCODE(data);
+ XIMID imid = PACKET_TO_IMID(data);
+ XICID icid = PACKET_TO_ICID(data);
+ Xim im = (Xim)call_data; /* check HM */
+ Xic ic = _XimICOfXICID(im, icid);
+ char* proto;
+ int proto_len;
+
+ /* check validity of im/ic
+ */
+ if ((imid != im->private.proto.imid) || !ic) {
+ return False; /* status = XimCbBadContextID; */
+ }
+
+ /* process pending callbacks
+ */
+ _XimProcessPendingCallbacks(ic);
+
+ /* check if the protocol should be processed here
+ */
+ if (major_opcode > 82) {
+ return False; /* status = XimCbBadOpcode; */
+ }
+ if (!callback_table[major_opcode]) {
+ return False; /* status = XimCbBadOpcode; */
+ }
+
+ /* move the pointer ahead by the IM Protocol packet header size
+ */
+ proto = (char*)data + sz_ximPacketHeader;
+ proto_len = (int)len - sz_ximPacketHeader;
+
+ /* check if it can be processed right away
+ * and if no, queue the protocol, otherwise invoke a callback
+ */
+ if (!_XimIsReadyForProcess(ic)) {
+
+ /* queue the protocol
+ */
+ XimPendingCallback pcb;
+ char *proto_buf = (proto_len > 0) ? (char*)Xmalloc(proto_len) : NULL;
+
+ pcb = (XimPendingCallback)Xmalloc(sizeof(XimPendingCallbackRec));
+ if (pcb && (proto_len <= 0 || proto_buf)) {
+ if (proto_len > 0)
+ memcpy(proto_buf, proto, proto_len);
+
+ pcb->major_opcode = major_opcode;
+ pcb->im = im;
+ pcb->ic = ic;
+ pcb->proto = proto_buf;
+ pcb->proto_len = proto_len;
+ pcb->next = (XimPendingCallback)NULL; /* queue is FIFO */
+ _XimPutCbIntoQueue(ic, pcb);
+ /* status = XimCbQueued; */
+ } else {
+ /* status = XimCbError; */
+ Xfree(pcb);
+ Xfree(proto_buf);
+ }
+ }
+ else {
+ /* invoke each callback according to the major opcode.
+ * `proto' points to the next address of IM-ID and IC-ID.
+ * `proto_len' specifies the packet length.
+ */
+ (void) (*callback_table[major_opcode])(im, ic, proto, proto_len);
+ }
+ return True;
+}
+
+Private XimCbStatus
+_XimGeometryCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.geometry_callback;
+
+ /* invoke the callack
+ */
+ if (cb && cb->callback) {
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
+ }
+ else {
+
+ /* no callback registered
+ */
+ return XimCbNoCallback;
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimStrConversionCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.string_conversion_callback; /* check HM */
+ XIMStringConversionCallbackStruct cbrec;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback) {
+ int p = XIM_HEADER_SIZE;
+ cbrec.position = (XIMStringConversionPosition)
+ *(CARD32*)&proto[p]; p += sz_CARD32;
+ cbrec.direction = (XIMCaretDirection)
+ *(CARD32*)&proto[p]; p += sz_CARD32;
+ cbrec.operation = (XIMStringConversionOperation)
+ *(CARD32*)&proto[p]; p += sz_CARD32;
+ cbrec.factor = (unsigned short)
+ *(CARD32*)&proto[p];
+
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbrec);
+ }
+ else {
+
+ /* no callback registered
+ */
+ _XimError(im, ic,
+ (CARD16)XIM_BadSomething,
+ (INT16)len,
+ (CARD16)XIM_STR_CONVERSION,
+ (char*)proto); /* send XIM_ERROR */
+ return XimCbNoCallback;
+ }
+
+ /* send a reply
+ */
+ {
+ CARD8 *buf;
+ INT16 buf_len;
+ int p, length_in_bytes, i;
+
+ /* Assumption:
+ * `cbrec.text->length' means the string length in characters
+ */
+ {
+ length_in_bytes = (cbrec.text->encoding_is_wchar)?
+ sizeof(wchar_t) * cbrec.text->length: /* wchar */
+ strlen(cbrec.text->string.mbs); /* mb */
+ buf_len = XIM_HEADER_SIZE +
+ sz_CARD16 +
+ 2 + length_in_bytes +
+ XIM_PAD(2 + length_in_bytes) +
+ 2 + 2 + sz_CARD32 * cbrec.text->length;
+ buf = (CARD8*)Xmalloc(buf_len);
+ }
+ _XimSetHeader((XPointer)buf, XIM_STR_CONVERSION_REPLY, 0, &buf_len);
+ buf_len -= XIM_HEADER_SIZE; /* added by _XimSetHeader (HACK) */
+ p = XIM_HEADER_SIZE;
+ *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
+ *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
+ *(CARD16*)&buf[p] = (CARD16)cbrec.text->length; p += sz_CARD16;
+ memcpy(&buf[p],&cbrec.text->string.mbs,length_in_bytes);
+ p += length_in_bytes;
+ *(CARD16*)&buf[p] = (CARD16)(sz_CARD32*cbrec.text->length);
+ p += XIM_PAD(2);
+ for (i = 0; i < (int)cbrec.text->length; i++) {
+ *(CARD32*)&buf[p] = (CARD32)cbrec.text->feedback[i];
+ p += sz_CARD32;
+ }
+
+ if (!(_XimWriteData(im, buf_len, buf))) {
+ return XimCbError;
+ }
+ _XimFlushData(im);
+
+ Xfree(buf);
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimPreeditStartCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.preedit_attr.start_callback;
+ int ret;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback){
+ ret = (*(cb->callback))((XIC)ic, cb->client_data, (XPointer)NULL);
+ }
+ else {
+
+ /* no callback registered
+ */
+ _XimError(im, ic,
+ (CARD16)XIM_BadSomething,
+ (INT16)len,
+ (CARD16)XIM_PREEDIT_START,
+ (char*)proto); /* send XIM_ERROR */
+ return XimCbNoCallback;
+ }
+
+ /* send a reply
+ */
+ {
+ CARD32 buf32[(sz_ximPacketHeader + sz_ximPreeditStartReply) / 4];
+ CARD8 *buf = (CARD8 *)buf32;
+ INT16 buf_len = sz_XIMID + sz_XICID + sz_ximPreeditStartReply;
+ int p;
+
+ _XimSetHeader((XPointer)buf, XIM_PREEDIT_START_REPLY, 0, &buf_len);
+ p = XIM_HEADER_SIZE;
+ *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
+ *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
+ *(INT32*)&buf[p] = (INT32)ret;
+
+ if (!(_XimWriteData(im, buf_len, buf))) {
+ return XimCbError;
+ }
+ _XimFlushData(im);
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimPreeditDoneCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.preedit_attr.done_callback;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback) {
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
+ }
+ else {
+
+ /* no callback registered
+ */
+ return XimCbNoCallback;
+ }
+
+ return XimCbSuccess;
+}
+
+Private void
+_read_text_from_packet(Xim im,
+ char* buf,
+ XIMText** text_ptr)
+{
+ int status;
+ XIMText* text;
+ int tmp_len;
+ char* tmp_buf;
+ Status s = 0;
+
+ status = (int)*(BITMASK32*)buf; buf += sz_BITMASK32;
+
+ /* string part
+ */
+ if (status & 0x00000001) /* "no string" bit on */ {
+ buf += sz_CARD16; /* skip "length of preedit string" */
+ buf += 2; /* pad */
+ *text_ptr = (XIMText*)NULL;
+ return;
+ }
+
+ *text_ptr = text = (XIMText*)Xmalloc(sizeof(XIMText));
+ if (text == (XIMText*)NULL) return;
+
+ tmp_len = (int)*(CARD16*)buf;
+ buf += sz_CARD16;
+ if ((tmp_buf = (char*)Xmalloc(tmp_len + 1))) {
+ memcpy(tmp_buf, buf, tmp_len);
+ tmp_buf[tmp_len] = '\0';
+
+ text->encoding_is_wchar = False;
+ text->length = im->methods->ctstombs((XIM)im,
+ tmp_buf, tmp_len,
+ NULL, 0, &s); /* CT? HM */
+ if (s != XLookupNone) {
+#ifndef NO_DEC_I18N_FIX
+ /* Allow for NULL-terminated */
+ if ((text->string.multi_byte =
+ (char*)Xmalloc(text->length *
+ XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) {
+#else
+ if (text->string.multi_byte = (char*)Xmalloc(text->length+1)) {
+#endif
+ int tmp;
+#ifndef NO_DEC_I18N_FIX
+ char *char_tmp;
+ int char_len;
+#endif
+ tmp = im->methods->ctstombs((XIM)im,
+ tmp_buf, tmp_len,
+#ifndef NO_DEC_I18N_FIX
+ text->string.multi_byte,
+ text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1,
+#else
+ text->string.multi_byte, text->length,
+#endif
+ &s);
+ text->string.multi_byte[tmp] = '\0';
+#ifndef NO_DEC_I18N_FIX
+ text->length = 0;
+ char_tmp = text->string.multi_byte;
+ while (*char_tmp != '\0') {
+ char_len = mblen(char_tmp, strlen(char_tmp));
+ char_tmp = char_tmp + char_len;
+ (text->length)++;
+ }
+#endif
+ }
+ }
+ else {
+ text->length = 0;
+ text->string.multi_byte = NULL;
+ }
+
+ Xfree(tmp_buf);
+ }
+ buf += tmp_len;
+
+ buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */
+
+ /* feedback part
+ */
+ if (status & 0x00000002) /* "no feedback" bit on */ {
+ text->feedback = (XIMFeedback*)NULL;
+ }
+ else {
+ int i, j;
+
+ i = (int)*(CARD16*)buf; buf += sz_CARD16;
+ buf += sz_CARD16; /* skip `unused' */
+ text->feedback = (XIMFeedback*)Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32)));
+ j = 0;
+ while (i > 0) {
+ text->feedback[j] = (XIMFeedback)*(CARD32*)buf;
+ buf += sz_CARD32;
+ i -= sz_CARD32;
+ j++;
+ }
+ /*
+ * text->length tells how long both the status string and
+ * the feedback array are. If there's "no string" the
+ * text->length was set to zero previously. See above.
+ * But if there is feedback (i.e. not "no feedback") then
+ * we need to convey the length of the feedback array.
+ * It might have been better if the protocol sent two
+ * different values, one for the length of the status
+ * string and one for the length of the feedback array.
+ */
+ if (status & 0x00000001) /* "no string" bit on */ {
+ text->length = j;
+ }
+ }
+}
+
+Private void
+_free_memory_for_text(XIMText* text)
+{
+ if (text) {
+ if (text->string.multi_byte)
+ Xfree(text->string.multi_byte);
+ if (text->feedback)
+ Xfree(text->feedback);
+ Xfree(text);
+ }
+}
+
+Private XimCbStatus
+_XimPreeditDrawCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.preedit_attr.draw_callback;
+ XIMPreeditDrawCallbackStruct cbs;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback) {
+ cbs.caret = (int)*(INT32*)proto; proto += sz_INT32;
+ cbs.chg_first = (int)*(INT32*)proto; proto += sz_INT32;
+ cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32;
+ _read_text_from_packet(im, proto, &cbs.text);
+
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
+
+ _free_memory_for_text((XIMText*)cbs.text);
+ }
+ else {
+
+ /* no callback registered
+ */
+ return XimCbNoCallback;
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimPreeditCaretCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.preedit_attr.caret_callback;
+ XIMPreeditCaretCallbackStruct cbs;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback) {
+ cbs.position = (int)*(INT32*)proto; proto += sz_INT32;
+ cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32;
+ cbs.style = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32;
+
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
+ }
+ else {
+
+ /* no callback registered
+ */
+ _XimError(im, ic,
+ (CARD16)XIM_BadSomething,
+ (INT16)len,
+ (CARD16)XIM_PREEDIT_CARET,
+ (char*)proto); /* send XIM_ERROR */
+ return XimCbNoCallback;
+ }
+
+ /* Send a reply
+ */
+ {
+ CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply];
+ INT16 len = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply;
+ int p;
+
+ _XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &len);
+ p = XIM_HEADER_SIZE;
+ *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
+ *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
+ *(CARD32*)&buf[p] = (CARD32)cbs.position;
+
+ if (!(_XimWriteData(im, len, buf))) {
+ return XimCbError;
+ }
+ _XimFlushData(im);
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimStatusStartCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.status_attr.start_callback;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback) {
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
+ }
+ else {
+
+ /* no callback registered
+ */
+ return XimCbNoCallback;
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimStatusDoneCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.status_attr.done_callback;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback) {
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
+ }
+ else {
+
+ /* no callback registered
+ */
+ return XimCbNoCallback;
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimStatusDrawCallback(Xim im,
+ Xic ic,
+ char* proto,
+ int len)
+{
+ XICCallback* cb = &ic->core.status_attr.draw_callback;
+ XIMStatusDrawCallbackStruct cbs;
+
+ /* invoke the callback
+ */
+ if (cb && cb->callback) {
+ cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32;
+ if (cbs.type == XIMTextType) {
+ _read_text_from_packet(im, proto, &cbs.data.text);
+ }
+ else if (cbs.type == XIMBitmapType) {
+ cbs.data.bitmap = (Pixmap)*(CARD32*)proto;
+ }
+
+ (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
+
+ if (cbs.type == XIMTextType)
+ _free_memory_for_text((XIMText *)cbs.data.text);
+ }
+ else {
+
+ /* no callback registered
+ */
+ return XimCbNoCallback;
+ }
+
+ return XimCbSuccess;
+}
+
+Private XimCbStatus
+_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len )
+{
+ XICCallback *cb = &ic->core.preedit_attr.state_notify_callback;
+
+ /* invoke the callack
+ */
+ if( cb && cb->callback ) {
+ XIMPreeditStateNotifyCallbackStruct cbrec;
+
+ cbrec.state = *(BITMASK32 *)proto;
+ (*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec );
+ }
+ else {
+ /* no callback registered
+ */
+ return XimCbNoCallback;
+ }
+
+ return XimCbSuccess;
+}
+
diff --git a/libX11/modules/im/ximcp/imDefIc.c b/libX11/modules/im/ximcp/imDefIc.c index 6e7519a28..27e04e11c 100644 --- a/libX11/modules/im/ximcp/imDefIc.c +++ b/libX11/modules/im/ximcp/imDefIc.c @@ -1436,7 +1436,7 @@ _XimProtoCreateIC( num = im->core.ic_num_resources;
len = sizeof(XIMResource) * num;
if (!(res = (XIMResourceList)Xmalloc(len)))
- return (XIC)NULL;
+ goto ErrorOnCreatingIC;
(void)memcpy((char *)res, (char *)im->core.ic_resources, len);
ic->private.proto.ic_resources = res;
ic->private.proto.ic_num_resources = num;
@@ -1464,7 +1464,7 @@ _XimProtoCreateIC( num = im->private.proto.ic_num_inner_resources;
len = sizeof(XIMResource) * num;
if (!(res = (XIMResourceList)Xmalloc(len)))
- return (XIC)NULL;
+ goto ErrorOnCreatingIC;
(void)memcpy((char *)res,
(char *)im->private.proto.ic_inner_resources, len);
ic->private.proto.ic_inner_resources = res;
diff --git a/libX11/modules/im/ximcp/imDefIm.c b/libX11/modules/im/ximcp/imDefIm.c index 936ce12b2..2ea4427c3 100644 --- a/libX11/modules/im/ximcp/imDefIm.c +++ b/libX11/modules/im/ximcp/imDefIm.c @@ -1713,11 +1713,8 @@ _XimEncodingNegotiation( if (!(_XimSetEncodingByName(im, &name_ptr, &name_len)))
return False;
- if (!(_XimSetEncodingByDetail(im, &detail_ptr, &detail_len))) {
- if (name_ptr)
- Xfree(name_ptr);
- return False;
- }
+ if (!(_XimSetEncodingByDetail(im, &detail_ptr, &detail_len)))
+ goto free_name_ptr;
len = sizeof(CARD16)
+ sizeof(INT16)
@@ -1727,13 +1724,9 @@ _XimEncodingNegotiation( + sizeof(CARD16)
+ detail_len;
- if (!(buf = (CARD8 *)Xmalloc(XIM_HEADER_SIZE + len))) {
- if (name_ptr)
- Xfree(name_ptr);
- if (detail_ptr)
- Xfree(detail_ptr);
- return False;
- }
+ if (!(buf = (CARD8 *)Xmalloc(XIM_HEADER_SIZE + len)))
+ goto free_detail_ptr;
+
buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
buf_s[0] = im->private.proto.imid;
@@ -1750,7 +1743,7 @@ _XimEncodingNegotiation( _XimSetHeader((XPointer)buf, XIM_ENCODING_NEGOTIATION, 0, &len);
if (!(_XimWrite(im, len, (XPointer)buf))) {
Xfree(buf);
- return False;
+ goto free_detail_ptr;
}
_XimFlush(im);
Xfree(buf);
@@ -1767,27 +1760,21 @@ _XimEncodingNegotiation( preply = (XPointer)Xmalloc(buf_size);
ret_code = _XimRead(im, &len, preply, buf_size,
_XimEncodingNegoCheck, 0);
- if(ret_code != XIM_TRUE) {
- Xfree(preply);
- return False;
- }
+ if(ret_code != XIM_TRUE)
+ goto free_preply;
}
} else
- return False;
+ goto free_detail_ptr;
buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
if (*((CARD8 *)preply) == XIM_ERROR) {
_XimProcError(im, 0, (XPointer)&buf_s[3]);
- if(reply != preply)
- Xfree(preply);
- return False;
+ goto free_preply;
}
if (!(_XimGetEncoding(im, &buf_s[1], name_ptr, name_len,
- detail_ptr, detail_len))) {
- if(reply != preply)
- Xfree(preply);
- return False;
- }
+ detail_ptr, detail_len)))
+ goto free_preply;
+
if (name_ptr)
Xfree(name_ptr);
if (detail_ptr)
@@ -1797,6 +1784,18 @@ _XimEncodingNegotiation( Xfree(preply);
return True;
+
+free_preply:
+ if (reply != preply)
+ Xfree(preply);
+
+free_detail_ptr:
+ Xfree(detail_ptr);
+
+free_name_ptr:
+ Xfree(name_ptr);
+
+ return False;
}
#ifdef XIM_CONNECTABLE
diff --git a/libX11/modules/im/ximcp/imDefLkup.c b/libX11/modules/im/ximcp/imDefLkup.c index a269df062..e53845d4c 100644 --- a/libX11/modules/im/ximcp/imDefLkup.c +++ b/libX11/modules/im/ximcp/imDefLkup.c @@ -691,8 +691,10 @@ _XimCommitRecv( return False;
if (!(_XimProcCommit(ic, (BYTE *)&buf_s[5],
- (int)buf_s[4], &string, &string_len)))
+ (int)buf_s[4], &string, &string_len))) {
+ Xfree(keysym);
return False;
+ }
}
if (!(_XimRegCommitInfo(ic, string, string_len, keysym, keysym_len))) {
diff --git a/libX11/modules/im/ximcp/imLcIm.c b/libX11/modules/im/ximcp/imLcIm.c index 430e318d2..44516e9ee 100644 --- a/libX11/modules/im/ximcp/imLcIm.c +++ b/libX11/modules/im/ximcp/imLcIm.c @@ -489,10 +489,13 @@ _XimWriteCachedDefaultTree( /* This STILL might be racy on NFS */
if ( (fd = _XOpenFileMode (cachename, O_WRONLY | O_CREAT | O_EXCL,
- 0600)) < 0)
+ 0600)) < 0) {
+ Xfree(m);
return;
+ }
if (! (fp = fdopen (fd, "wb")) ) {
close (fd);
+ Xfree(m);
return;
}
fwrite (m, msize, 1, fp);
diff --git a/libX11/modules/im/ximcp/imRmAttr.c b/libX11/modules/im/ximcp/imRmAttr.c index f31af79aa..3183a6005 100644 --- a/libX11/modules/im/ximcp/imRmAttr.c +++ b/libX11/modules/im/ximcp/imRmAttr.c @@ -1433,8 +1433,10 @@ _XimGetAttributeID( bzero((char *)res, res_len);
values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
- if (!(tmp = (XPointer)Xmalloc(values_len)))
+ if (!(tmp = (XPointer)Xmalloc(values_len))) {
+ Xfree(res);
return False;
+ }
bzero(tmp, values_len);
values_list = (XIMValuesList *)tmp;
@@ -1480,8 +1482,10 @@ _XimGetAttributeID( bzero((char *)res, res_len);
values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len;
- if (!(tmp = (XPointer)Xmalloc(values_len)))
+ if (!(tmp = (XPointer)Xmalloc(values_len))) {
+ Xfree(res);
return False;
+ }
bzero(tmp, values_len);
values_list = (XIMValuesList *)tmp;
diff --git a/libX11/modules/om/generic/omGeneric.c b/libX11/modules/om/generic/omGeneric.c index c78c0a9d6..330186d13 100644 --- a/libX11/modules/om/generic/omGeneric.c +++ b/libX11/modules/om/generic/omGeneric.c @@ -1,2188 +1,2190 @@ -/* #define FONTDEBUG */ -/* - * Copyright 1992, 1993 by TOSHIBA Corp. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of TOSHIBA not be used in advertising - * or publicity pertaining to distribution of the software without specific, - * written prior permission. TOSHIBA make no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING - * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL - * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR - * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Katsuhisa Yano TOSHIBA Corp. - * mopi@osa.ilab.toshiba.co.jp - */ -/* - * Copyright 1995 by FUJITSU LIMITED - * This is source code modified by FUJITSU LIMITED under the Joint - * Development Agreement for the CDE/Motif PST. - * - * Modifier: Takanori Tateno FUJITSU LIMITED - * - */ - -/* - * Fixed the algorithms in parse_fontname() and parse_fontdata() - * to improve the logic for determining which font should be - * returned for a given CharSet. We even added some comments - * so that you can figure out what in the heck we're doing. We - * realize this is a departure from the norm, but hey, we're - * rebels! :-) :-) - * - * Modifiers: Jeff Walls, Paul Anderson: HEWLETT-PACKARD - */ -/* - * Cleaned up mess, removed some blabla - * Egbert Eich, SuSE Linux AG - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "Xlibint.h" -#include "XomGeneric.h" -#include "XlcGeneric.h" -#include <X11/Xos.h> -#include <X11/Xatom.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#define MAXFONTS 100 -#define PIXEL_SIZE_FIELD 7 -#define POINT_SIZE_FIELD 8 -#define CHARSET_ENCODING_FIELD 14 -#define XLFD_MAX_LEN 255 - -#if 0 -extern int _XmbDefaultTextEscapement(), _XwcDefaultTextEscapement(), - _Xutf8DefaultTextEscapement(); -extern int _XmbDefaultTextExtents(), _XwcDefaultTextExtents(), - _Xutf8DefaultTextExtents(); -extern Status _XmbDefaultTextPerCharExtents(), _XwcDefaultTextPerCharExtents(), - _Xutf8DefaultTextPerCharExtents(); -extern int _XmbDefaultDrawString(), _XwcDefaultDrawString(), - _Xutf8DefaultDrawString(); -extern void _XmbDefaultDrawImageString(), _XwcDefaultDrawImageString(), - _Xutf8DefaultDrawImageString(); - -extern int _XmbGenericTextEscapement(), _XwcGenericTextEscapement(), - _Xutf8GenericTextEscapement(); -extern int _XmbGenericTextExtents(), _XwcGenericTextExtents(), - _Xutf8GenericTextExtents(); -extern Status _XmbGenericTextPerCharExtents(), _XwcGenericTextPerCharExtents(), - _Xutf8GenericTextPerCharExtents(); -extern int _XmbGenericDrawString(), _XwcGenericDrawString(), - _Xutf8GenericDrawString(); -extern void _XmbGenericDrawImageString(), _XwcGenericDrawImageString(), - _Xutf8GenericDrawImageString(); - -extern void _XlcDbg_printValue (const char *str, char **value, int num); -#endif - -/* For VW/UDC start */ - -static FontData -init_fontdata( - FontData font_data, - int font_data_count) -{ - FontData fd; - int i; - - fd = (FontData)Xmalloc(sizeof(FontDataRec) * font_data_count); - if(fd == (FontData) NULL) - return False; - - memset(fd, 0x00, sizeof(FontData) * font_data_count); - for(i = 0 ; i < font_data_count ; i++) - fd[i] = font_data[i]; - - return fd; -} - -static VRotate -init_vrotate( - FontData font_data, - int font_data_count, - int type, - CodeRange code_range, - int code_range_num) -{ - VRotate vrotate; - int i; - - if(type == VROTATE_NONE) - return (VRotate)NULL; - - vrotate = (VRotate)Xmalloc(sizeof(VRotateRec) * font_data_count); - if(vrotate == (VRotate) NULL) - return False; - - memset(vrotate, 0x00, sizeof(VRotateRec) * font_data_count); - for(i = 0 ; i < font_data_count ; i++) { - vrotate[i].charset_name = font_data[i].name; - vrotate[i].side = font_data[i].side; - if(type == VROTATE_PART) { - vrotate[i].num_cr = code_range_num; - vrotate[i].code_range = code_range; - } - } - - return vrotate; -} - -static Bool -init_fontset( - XOC oc) -{ - XOCGenericPart *gen; - FontSet font_set; - OMData data; - int count; - - count = XOM_GENERIC(oc->core.om)->data_num; - data = XOM_GENERIC(oc->core.om)->data; - - font_set = (FontSet) Xmalloc(sizeof(FontSetRec) * count); - if (font_set == NULL) - return False; - memset((char *) font_set, 0x00, sizeof(FontSetRec) * count); - - gen = XOC_GENERIC(oc); - gen->font_set_num = count; - gen->font_set = font_set; - - for ( ; count-- > 0; data++, font_set++) { - font_set->charset_count = data->charset_count; - font_set->charset_list = data->charset_list; - - if((font_set->font_data = init_fontdata(data->font_data, - data->font_data_count)) == NULL) - goto err; - font_set->font_data_count = data->font_data_count; - if((font_set->substitute = init_fontdata(data->substitute, - data->substitute_num)) == NULL) - goto err; - font_set->substitute_num = data->substitute_num; - if((font_set->vmap = init_fontdata(data->vmap, - data->vmap_num)) == NULL) - goto err; - font_set->vmap_num = data->vmap_num; - - if(data->vrotate_type != VROTATE_NONE) { - /* A vrotate member is specified primary font data */ - /* as initial value. */ - if((font_set->vrotate = init_vrotate(data->font_data, - data->font_data_count, - data->vrotate_type, - data->vrotate, - data->vrotate_num)) == NULL) - goto err; - font_set->vrotate_num = data->font_data_count; - } - } - return True; - -err: - if(font_set->font_data) - Xfree(font_set->font_data); - if(font_set->substitute) - Xfree(font_set->substitute); - if(font_set->vmap) - Xfree(font_set->vmap); - if(font_set->vrotate) - Xfree(font_set->vrotate); - if(font_set) - Xfree(font_set); - gen->font_set = (FontSet) NULL; - gen->font_set_num = 0; - return False; -} - -/* For VW/UDC end */ - -static char * -get_prop_name( - Display *dpy, - XFontStruct *fs) -{ - unsigned long fp; - - if (XGetFontProperty(fs, XA_FONT, &fp)) - return XGetAtomName(dpy, fp); - - return (char *) NULL; -} - -/* For VW/UDC start */ - -static Bool -load_fontdata( - XOC oc, - FontData font_data, - int font_data_num) -{ - Display *dpy = oc->core.om->core.display; - FontData fd = font_data; - - if(font_data == NULL) return(True); - for( ; font_data_num-- ; fd++) { - if(fd->xlfd_name != (char *) NULL && fd->font == NULL) { - fd->font = XLoadQueryFont(dpy, fd->xlfd_name); - if (fd->font == NULL){ - return False; - } - } - } - return True; -} - -static Bool -load_fontset_data( - XOC oc, - FontSet font_set) -{ - Display *dpy = oc->core.om->core.display; - - if(font_set->font_name == (char *)NULL) return False ; - - /* If font_set->font is not NULL, it contains the *best* - * match font for this FontSet. - * -- jjw/pma (HP) - */ - if(font_set->font == NULL) { - font_set->font = XLoadQueryFont(dpy, font_set->font_name); - if (font_set->font == NULL){ - return False; - } - } - return True; -} - -static Bool -load_font( - XOC oc) -{ - XOCGenericPart *gen = XOC_GENERIC(oc); - FontSet font_set = gen->font_set; - int num = gen->font_set_num; - - for ( ; num-- > 0; font_set++) { - if (font_set->font_name == NULL) - continue; - - if (load_fontset_data (oc, font_set) != True) - return False; -#ifndef TESTVERSION - if(load_fontdata(oc, font_set->font_data, - font_set->font_data_count) != True) - return False; - - if(load_fontdata(oc, font_set->substitute, - font_set->substitute_num) != True) - return False; -#endif - -/* Add 1996.05.20 */ - if( oc->core.orientation == XOMOrientation_TTB_RTL || - oc->core.orientation == XOMOrientation_TTB_LTR ){ - if (font_set->vpart_initialize == 0) { - load_fontdata(oc, font_set->vmap, font_set->vmap_num); - load_fontdata(oc, (FontData) font_set->vrotate, - font_set->vrotate_num); - font_set->vpart_initialize = 1; - } - } - - if (font_set->font->min_byte1 || font_set->font->max_byte1) - font_set->is_xchar2b = True; - else - font_set->is_xchar2b = False; - } - - return True; -} - -/* For VW/UDC end */ - -static Bool -load_font_info( - XOC oc) -{ - Display *dpy = oc->core.om->core.display; - XOCGenericPart *gen = XOC_GENERIC(oc); - FontSet font_set = gen->font_set; - char **fn_list; - int fn_num, num = gen->font_set_num; - - for ( ; num-- > 0; font_set++) { - if (font_set->font_name == NULL) - continue; - - if (font_set->info == NULL) { - fn_list = XListFontsWithInfo(dpy, font_set->font_name, 1, &fn_num, - &font_set->info); - if (font_set->info == NULL) - return False; - - XFreeFontNames(fn_list); - } - } - - return True; -} - -/* For Vertical Writing start */ - -static void -check_fontset_extents( - XCharStruct *overall, - int *logical_ascent, - int *logical_descent, - XFontStruct *font) -{ - overall->lbearing = min(overall->lbearing, font->min_bounds.lbearing); - overall->rbearing = max(overall->rbearing, font->max_bounds.rbearing); - overall->ascent = max(overall->ascent, font->max_bounds.ascent); - overall->descent = max(overall->descent, font->max_bounds.descent); - overall->width = max(overall->width, font->max_bounds.width); - *logical_ascent = max(*logical_ascent, font->ascent); - *logical_descent = max(*logical_descent, font->descent); -} - -/* For Vertical Writing end */ - -static void -set_fontset_extents( - XOC oc) -{ - XRectangle *ink = &oc->core.font_set_extents.max_ink_extent; - XRectangle *logical = &oc->core.font_set_extents.max_logical_extent; - XFontStruct **font_list, *font; - XCharStruct overall; - int logical_ascent, logical_descent; - int num = oc->core.font_info.num_font; - - font_list = oc->core.font_info.font_struct_list; - font = *font_list++; - overall = font->max_bounds; - overall.lbearing = font->min_bounds.lbearing; - logical_ascent = font->ascent; - logical_descent = font->descent; - - /* For Vertical Writing start */ - - while (--num > 0) { - font = *font_list++; - check_fontset_extents(&overall, &logical_ascent, &logical_descent, - font); - } - - { - XOCGenericPart *gen = XOC_GENERIC(oc); - FontSet font_set = gen->font_set; - FontData font_data; - int font_set_num = gen->font_set_num; - int font_data_count; - - for( ; font_set_num-- ; font_set++) { - if(font_set->vmap_num > 0) { - font_data = font_set->vmap; - font_data_count = font_set->vmap_num; - for( ; font_data_count-- ; font_data++) { - if(font_data->font != NULL) { - check_fontset_extents(&overall, &logical_ascent, - &logical_descent, - font_data->font); - } - } - } - - if(font_set->vrotate_num > 0 && font_set->vrotate != NULL) { - font_data = (FontData) font_set->vrotate; - font_data_count = font_set->vrotate_num; - for( ; font_data_count-- ; font_data++) { - if(font_data->font != NULL) { - check_fontset_extents(&overall, &logical_ascent, - &logical_descent, - font_data->font); - } - } - } - } - } - - /* For Vertical Writing start */ - - ink->x = overall.lbearing; - ink->y = -(overall.ascent); - ink->width = overall.rbearing - overall.lbearing; - ink->height = overall.ascent + overall.descent; - - logical->x = 0; - logical->y = -(logical_ascent); - logical->width = overall.width; - logical->height = logical_ascent + logical_descent; -} - -static Bool -init_core_part( - XOC oc) -{ - XOCGenericPart *gen = XOC_GENERIC(oc); - FontSet font_set; - int font_set_num; - XFontStruct **font_struct_list; - char **font_name_list, *font_name_buf; - int count, length; - - font_set = gen->font_set; - font_set_num = gen->font_set_num; - count = length = 0; - - for ( ; font_set_num-- > 0; font_set++) { - if (font_set->font_name == NULL) - continue; - - length += strlen(font_set->font_name) + 1; - - count++; - } - if (count == 0) - return False; - - font_struct_list = (XFontStruct **) Xmalloc(sizeof(XFontStruct *) * count); - if (font_struct_list == NULL) - return False; - - font_name_list = (char **) Xmalloc(sizeof(char *) * count); - if (font_name_list == NULL) - goto err; - - font_name_buf = (char *) Xmalloc(length); - if (font_name_buf == NULL) - goto err; - - oc->core.font_info.num_font = count; - oc->core.font_info.font_name_list = font_name_list; - oc->core.font_info.font_struct_list = font_struct_list; - - font_set = gen->font_set; - font_set_num = gen->font_set_num; - - for (count = 0; font_set_num-- > 0; font_set++) { - if (font_set->font_name == NULL) - continue; - - font_set->id = count; - if (font_set->font) - *font_struct_list++ = font_set->font; - else - *font_struct_list++ = font_set->info; - strcpy(font_name_buf, font_set->font_name); - Xfree(font_set->font_name); - *font_name_list++ = font_set->font_name = font_name_buf; - font_name_buf += strlen(font_name_buf) + 1; - - count++; - } - - set_fontset_extents(oc); - - return True; - -err: - if (font_name_list) - Xfree(font_name_list); - Xfree(font_struct_list); - - return False; -} - -static char * -get_font_name( - XOC oc, - char *pattern) -{ - char **list, *name; - int count = 0; - - list = XListFonts(oc->core.om->core.display, pattern, 1, &count); - if (list == NULL) - return NULL; - - name = (char *) Xmalloc(strlen(*list) + 1); - if (name) - strcpy(name, *list); - - XFreeFontNames(list); - - return name; -} - -/* For VW/UDC start*/ - -static char * -get_rotate_fontname( - char *font_name) -{ - char *pattern = NULL, *ptr = NULL; - char *fields[CHARSET_ENCODING_FIELD]; - char str_pixel[32], str_point[4]; - char *rotate_font_ptr = NULL; - int pixel_size = 0; - int field_num = 0, len = 0; - - if(font_name == (char *) NULL || (len = strlen(font_name)) <= 0 - || len > XLFD_MAX_LEN) - return NULL; - - pattern = (char *)Xmalloc(len + 1); - if(!pattern) - return NULL; - strcpy(pattern, font_name); - - memset(fields, 0, sizeof(char *) * 14); - ptr = pattern; - while(isspace(*ptr)) { - ptr++; - } - if(*ptr == '-') - ptr++; - - for(field_num = 0 ; field_num < CHARSET_ENCODING_FIELD && ptr && *ptr ; - ptr++, field_num++) { - fields[field_num] = ptr; - - if((ptr = strchr(ptr, '-'))) { - *ptr = '\0'; - } else { - field_num++; /* Count last field */ - break; - } - } - - if(field_num < CHARSET_ENCODING_FIELD) - return NULL; - - /* Pixel Size field : fields[6] */ - for(ptr = fields[PIXEL_SIZE_FIELD - 1] ; ptr && *ptr; ptr++) { - if(!isdigit(*ptr)) { - if(*ptr == '['){ /* 960730 */ - strcpy(pattern, font_name); - return(pattern); - } - if(pattern) - Xfree(pattern); - return NULL; - } - } - pixel_size = atoi(fields[PIXEL_SIZE_FIELD - 1]); - sprintf(str_pixel, "[ 0 ~%d %d 0 ]", pixel_size, pixel_size); - fields[6] = str_pixel; - - /* Point Size field : fields[7] */ - strcpy(str_point, "*"); - fields[POINT_SIZE_FIELD - 1] = str_point; - - len = 0; - for (field_num = 0; field_num < CHARSET_ENCODING_FIELD && - fields[field_num]; field_num++) { - len += 1 + strlen(fields[field_num]); - } - - /* Max XLFD length is 255 */ - if (len > XLFD_MAX_LEN) - return NULL; - - rotate_font_ptr = (char *)Xmalloc(len + 1); - if(!rotate_font_ptr) - return NULL; - - rotate_font_ptr[0] = '\0'; - - for(field_num = 0 ; field_num < CHARSET_ENCODING_FIELD && - fields[field_num] ; field_num++) { - strcat(rotate_font_ptr, "-"); - strcat(rotate_font_ptr, fields[field_num]); - } - - if(pattern) - Xfree(pattern); - - return rotate_font_ptr; -} - -static Bool -is_match_charset( - FontData font_data, - char *font_name) -{ - char *last; - int length, name_len; - - name_len = strlen(font_name); - last = font_name + name_len; - - length = strlen(font_data->name); - if (length > name_len) - return False; - - if (_XlcCompareISOLatin1(last - length, font_data->name) == 0) - return True; - - return False; -} - -#if 0 -static char * -get_font_name_from_list( - XOC oc, - char *pattern, - FontData font_data) -{ - char **list, *name = (char *)NULL, *fname; - int count = 0, i; - - list = XListFonts(oc->core.om->core.display, pattern, MAXFONTS, &count); - if (list == NULL) - return NULL; - - for (i = 0; i < count; i++) { - fname = list[i]; - if(is_match_charset(font_data, fname) == True) { - name = (char *) Xmalloc(strlen(fname) + 1); - if (name) - strcpy(name, fname); - break; - } - } - - XFreeFontNames(list); - - return name; -} -#endif - -static int -parse_all_name( - XOC oc, - FontData font_data, - char *pattern) -{ - -#ifdef OLDCODE - if(is_match_charset(font_data, pattern) != True) - return False; - - font_data->xlfd_name = (char *)Xmalloc(strlen(pattern)+1); - if(font_data->xlfd_name == NULL) - return (-1); - - strcpy(font_data->xlfd_name, pattern); - return True; -#else /* OLDCODE */ - Display *dpy = oc->core.om->core.display; - char **fn_list = NULL, *prop_fname = NULL; - int list_num; - XFontStruct *fs_list; - if(is_match_charset(font_data, pattern) != True) { - /* - * pattern should not contain any wildcard (execpt '?') - * this was probably added to make this case insensitive. - */ - if ((fn_list = XListFontsWithInfo(dpy, pattern, - MAXFONTS, - &list_num, &fs_list)) == NULL) { - return False; - } - /* shouldn't we loop here ? */ - else if ((prop_fname = get_prop_name(dpy, fs_list)) == NULL) { - XFreeFontInfo(fn_list, fs_list, list_num); - return False; - } - else if ((is_match_charset(font_data, prop_fname) != True)) { - XFree(prop_fname); - XFreeFontInfo(fn_list, fs_list, list_num); - return False; - } - else { - font_data->xlfd_name = prop_fname; - XFreeFontInfo(fn_list, fs_list, list_num); - return True; - } - } - - font_data->xlfd_name = (char *)Xmalloc(strlen(pattern)+1); - if(font_data->xlfd_name == NULL) - return (-1); - - strcpy(font_data->xlfd_name, pattern); - return True; -#endif /* OLDCODE */ -} - -static int -parse_omit_name( - XOC oc, - FontData font_data, - char *pattern) -{ - char* last = (char *) NULL; - char* base_name; - char buf[XLFD_MAX_LEN + 1]; - int length = 0; - int num_fields; - /* - * If the font specified by "pattern" is expandable to be - * a member of "font_data"'s FontSet, we've found a match. - */ - if(is_match_charset(font_data, pattern) == True) { - if ((font_data->xlfd_name = get_font_name(oc, pattern)) != NULL) { - return True; - } - } - - length = strlen (pattern); - - if (length > XLFD_MAX_LEN) - return -1; - - strcpy(buf, pattern); - last = buf + length - 1; - - /* Replace the original encoding with the encoding for this FontSet. */ - - /* Figure out how many fields have been specified in this xlfd. */ - for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++) - if (*base_name == '-') num_fields++; - - switch (num_fields) { - case 12: - /* This is the best way to have specifed the fontset. In this - * case, there is no original encoding. E.g., - * -*-*-*-*-*-*-14-*-*-*-*-* - * To this, we'll append a dash: - * -*-*-*-*-*-*-14-*-*-*-*-*- - * then append the encoding to get: - * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0 - */ - /* - * Take care of: - * -*-*-*-*-*-*-14-*-*-*-*- - */ - if (*(last) == '-') - *++last = '*'; - - *++last = '-'; - break; - case 13: - /* Got the charset, not the encoding, zap the charset In this - * case, there is no original encoding, but there is a charset. E.g., - * -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990 - * To this, we remove the charset: - * -*-*-*-*-*-*-14-*-*-*-*-*- - * then append the new encoding to get: - * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0 - */ - last = strrchr (buf, '-'); - num_fields = 12; - break; - case 14: - /* Both the charset and the encoding are specified. Get rid - * of them so that we can append the new charset encoding. E.g., - * -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990-0 - * To this, we'll remove the encoding and charset to get: - * -*-*-*-*-*-*-14-*-*-*-*-*- - * then append the new encoding to get: - * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0 - */ - last = strrchr (buf, '-'); - *last = '\0'; - last = strrchr (buf, '-'); - num_fields = 12; - break; - default: - if (*last != '-') - *++last = '-'; - break; - } - - /* At this point, "last" is pointing to the last "-" in the - * xlfd, and all xlfd's at this point take a form similar to: - * -*-*-*-*-*-*-14-*-*-*-*-*- - * (i.e., no encoding). - * After the strcpy, we'll end up with something similar to: - * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0 - * - * If the modified font is found in the current FontSet, - * we've found a match. - */ - - last++; - - if ((last - buf) + strlen(font_data->name) > XLFD_MAX_LEN) - return -1; - - strcpy(last, font_data->name); - if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL) - return True; - - /* This may mot be needed anymore as XListFonts() takes care of this */ - while (num_fields < 12) { - if ((last - buf) > (XLFD_MAX_LEN - 2)) - return -1; - *last = '*'; - *(last + 1) = '-'; - strcpy(last + 2, font_data->name); - num_fields++; - last+=2; - if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL) - return True; - } - - - return False; -} - - -typedef enum{C_PRIMARY, C_SUBSTITUTE, C_VMAP, C_VROTATE } ClassType; - -static int -parse_fontdata( - XOC oc, - FontSet font_set, - FontData font_data, - int font_data_count, - char **name_list, - int name_list_count, - ClassType class, - FontDataRec *font_data_return) -{ - - char **cur_name_list = name_list; - char *font_name = (char *) NULL; - char *pattern = (char *) NULL; - int found_num = 0, ret = 0; - int count = name_list_count; - - if(name_list == NULL || count <= 0) { - return False; - } - - if(font_data == NULL || font_data_count <= 0) { - return False; - } - - /* Loop through each font encoding defined in the "font_data" FontSet. */ - for ( ; font_data_count-- > 0; font_data++) { - Bool is_found = False; - font_name = (char *) NULL; - count = name_list_count; - cur_name_list = name_list; - - /* - * Loop through each font specified by the user - * in the call to XCreateFontset(). - */ - while (count-- > 0) { - pattern = *cur_name_list++; - if (pattern == NULL || *pattern == '\0') - continue; -#ifdef FONTDEBUG - fprintf(stderr,"Font pattern: %s %s\n", - pattern,font_data->name); -#endif - - /* - * If the current font is fully specified (i.e., the - * xlfd contains no wildcards) and the font exists on - * the X Server, we have a match. - */ - if (strchr(pattern, '*') == NULL && - (font_name = get_font_name(oc, pattern))) { - /* - * Find the full xlfd name for this font. If the font is - * already in xlfd format, it is simply returned. If the - * font is an alias for another font, the xlfd of the - * aliased font is returned. - */ - ret = parse_all_name(oc, font_data, font_name); - Xfree(font_name); - - if (ret == -1) return -1; - if (ret == False) continue; - /* - * Since there was an exact match of a fully-specified font - * or a font alias, we can return now since the desired font - * was found for the current font encoding for this FontSet. - * - * Previous implementations of this algorithm would - * not return here. Instead, they continued searching - * through the font encodings for this FontSet. The side-effect - * of that behavior is you may return a "substitute" match - * instead of an "exact" match. We believe there should be a - * preference on exact matches. Therefore, as soon as we - * find one, we bail. - * - * Also, previous implementations seemed to think it was - * important to find either a primary or substitute font - * for each Font encoding in the FontSet before returning an - * acceptable font. We don't believe this is necessary. - * All the client cares about is finding a reasonable font - * for what was passed in. If we find an exact match, - * there's no reason to look any further. - * - * -- jjw/pma (HP) - */ - if (font_data_return) { - font_data_return->xlfd_name = (char *)Xmalloc - (strlen(font_data->xlfd_name) + 1); - if (!font_data_return->xlfd_name) return -1; - - strcpy (font_data_return->xlfd_name, font_data->xlfd_name); - - font_data_return->side = font_data->side; - } -#ifdef FONTDEBUG - fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name); -#endif - - return True; - } - /* - * If the font name is not fully specified - * (i.e., it has wildcards), we have more work to do. - * See the comments in parse_omit_name() - * for the list of things to do. - */ - ret = parse_omit_name(oc, font_data, pattern); - - if (ret == -1) return -1; - if (ret == False) continue; - - /* - * A font which matched the wild-carded specification was found. - * Only update the return data if a font has not yet been found. - * This maintains the convention that FontSets listed higher in - * a CodeSet in the Locale Database have higher priority than - * those FontSets listed lower in the CodeSet. In the following - * example: - * - * fs1 { - * charset HP-JIS:GR - * font JISX0208.1990-0:GL;\ - * JISX0208.1990-1:GR;\ - * JISX0208.1983-0:GL;\ - * JISX0208.1983-1:GR - * } - * - * a font found in the JISX0208.1990-0 FontSet will have a - * higher priority than a font found in the JISX0208.1983-0 - * FontSet. - */ - if (font_data_return && font_data_return->xlfd_name == NULL) { - -#ifdef FONTDEBUG - fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name); -#endif - font_data_return->xlfd_name = (char *)Xmalloc - (strlen(font_data->xlfd_name) + 1); - if (!font_data_return->xlfd_name) return -1; - - strcpy (font_data_return->xlfd_name, font_data->xlfd_name); - font_data_return->side = font_data->side; - } - - found_num++; - is_found = True; - - break; - } - - switch(class) { - case C_PRIMARY: - if(is_found == False) { - /* - * Did not find a font for the current FontSet. Check the - * FontSet's "substitute" font for a match. If we find a - * match, we'll keep searching in hopes of finding an exact - * match later down the FontSet list. - * - * when we return and we have found a font font_data_return - * contains the first (ie. best) match no matter if this - * is a C_PRIMARY or a C_SUBSTITUTE font - */ - ret = parse_fontdata(oc, font_set, font_set->substitute, - font_set->substitute_num, name_list, - name_list_count, C_SUBSTITUTE, - font_data_return); - if (ret == -1) return -1; - if (ret == False) continue; - - found_num++; - is_found = True; - } -#ifdef TESTVERSION - else - return True; -#endif - break; - - case C_SUBSTITUTE: - case C_VMAP: - if(is_found == True) - return True; - break; - - case C_VROTATE: - if(is_found == True) { - char *rotate_name; - - if((rotate_name = get_rotate_fontname(font_data->xlfd_name)) - != NULL) { - Xfree(font_data->xlfd_name); - font_data->xlfd_name = rotate_name; - - return True; - } - Xfree(font_data->xlfd_name); - font_data->xlfd_name = NULL; - return False; - } - break; - } - } - - if(class == C_PRIMARY && found_num >= 1) - return True; - - return False; -} - - -static int -parse_vw( - XOC oc, - FontSet font_set, - char **name_list, - int count) -{ - FontData vmap = font_set->vmap; - VRotate vrotate = font_set->vrotate; - int vmap_num = font_set->vmap_num; - int vrotate_num = font_set->vrotate_num; - int ret = 0, i = 0; - - if(vmap_num > 0) { - if(parse_fontdata(oc, font_set, vmap, vmap_num, name_list, - count, C_VMAP,NULL) == -1) - return (-1); - } - - if(vrotate_num > 0) { - ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num, - name_list, count, C_VROTATE, NULL); - if(ret == -1) { - return (-1); - } else if(ret == False) { - CodeRange code_range; - int num_cr; - int sub_num = font_set->substitute_num; - - code_range = vrotate[0].code_range; /* ? */ - num_cr = vrotate[0].num_cr; /* ? */ - for(i = 0 ; i < vrotate_num ; i++) { - if(vrotate[i].xlfd_name) - Xfree(vrotate[i].xlfd_name); - } - Xfree(vrotate); - - if(sub_num > 0) { - vrotate = font_set->vrotate = (VRotate)Xmalloc - (sizeof(VRotateRec) * sub_num); - if(font_set->vrotate == (VRotate)NULL) - return (-1); - memset(font_set->vrotate, 0x00, sizeof(VRotateRec) * sub_num); - - for(i = 0 ; i < sub_num ; i++) { - vrotate[i].charset_name = font_set->substitute[i].name; - vrotate[i].side = font_set->substitute[i].side; - vrotate[i].code_range = code_range; - vrotate[i].num_cr = num_cr; - } - vrotate_num = font_set->vrotate_num = sub_num; - } else { - vrotate = font_set->vrotate = (VRotate)NULL; - } - - ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num, - name_list, count, C_VROTATE, NULL); - if(ret == -1) - return (-1); - } - } - - return True; -} - -static int -parse_fontname( - XOC oc) -{ - XOCGenericPart *gen = XOC_GENERIC(oc); - FontSet font_set; - FontDataRec font_data_return; - char *base_name, **name_list; - int font_set_num = 0; - int found_num = 0; - int count = 0; - int ret; - int i; - - name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count); - if (name_list == NULL) - return -1; - - font_set = gen->font_set; - font_set_num = gen->font_set_num; - - /* Loop through all of the CharSets defined in the Locale - * database for the current Locale. - */ - for( ; font_set_num-- > 0 ; font_set++) { - if(font_set->font_name) - continue; - - if(font_set->font_data_count > 0) { - - /* - * If there are a non-zero number of FontSets defined - * for this CharSet. - * Try to find a font for this CharSet. If we find an - * acceptable font, we save the information for return - * to the client. If we do not find an acceptable font, - * a "missing_charset" will be reported to the client - * for this CharSet. - */ - font_data_return. xlfd_name = NULL; - font_data_return.side = XlcUnknown; - - ret = parse_fontdata(oc, font_set, font_set->font_data, - font_set->font_data_count, - name_list, count, C_PRIMARY, - &font_data_return); - if(ret == -1) { - goto err; - } else if(ret == True) { - /* - * We can't just loop thru fontset->font_data to - * find the first (ie. best) match: parse_fontdata - * will try a substitute font if no primary one could - * be matched. It returns the required information in - * font_data_return. - */ - font_set->font_name = (char *)Xmalloc - (strlen(font_data_return.xlfd_name) + 1); - if(font_set->font_name == (char *) NULL) - goto err; - strcpy(font_set->font_name, font_data_return.xlfd_name); - font_set->side = font_data_return.side; - - Xfree (font_data_return.xlfd_name); - font_data_return.xlfd_name = NULL; - - if(parse_vw(oc, font_set, name_list, count) == -1) - goto err; - found_num++; - } - - } else if(font_set->substitute_num > 0) { - /* - * If there are no FontSets defined for this - * CharSet. We can only find "substitute" fonts. - */ - ret = parse_fontdata(oc, font_set, font_set->substitute, - font_set->substitute_num, - name_list, count, C_SUBSTITUTE, NULL); - if(ret == -1) { - goto err; - } else if(ret == True) { - for(i=0;i<font_set->substitute_num;i++){ - if(font_set->substitute[i].xlfd_name != NULL){ - break; - } - } - font_set->font_name = (char *)Xmalloc - (strlen(font_set->substitute[i].xlfd_name) + 1); - if(font_set->font_name == (char *) NULL) - goto err; - strcpy(font_set->font_name,font_set->substitute[i].xlfd_name); - font_set->side = font_set->substitute[i].side; - if(parse_vw(oc, font_set, name_list, count) == -1) - goto err; - - found_num++; - } - } - } - - base_name = (char *) Xmalloc(strlen(oc->core.base_name_list) + 1); - if (base_name == NULL) - goto err; - - strcpy(base_name, oc->core.base_name_list); - oc->core.base_name_list = base_name; - - XFreeStringList(name_list); - - return found_num; - -err: - XFreeStringList(name_list); - /* Prevent this from being freed twice */ - oc->core.base_name_list = NULL; - - return -1; -} - -/* For VW/UDC end*/ - -static Bool -set_missing_list( - XOC oc) -{ - XOCGenericPart *gen = XOC_GENERIC(oc); - FontSet font_set; - char **charset_list, *charset_buf; - int count, length, font_set_num; - int result = 1; - - font_set = gen->font_set; - font_set_num = gen->font_set_num; - count = length = 0; - - for ( ; font_set_num-- > 0; font_set++) { - if (font_set->info || font_set->font) { - continue; - } - - /* Change 1996.01.23 start */ - if(font_set->font_data_count <= 0 || - font_set->font_data == (FontData)NULL) { - if(font_set->substitute_num <= 0 || - font_set->substitute == (FontData)NULL) { - if(font_set->charset_list != NULL){ - length += - strlen(font_set->charset_list[0]->encoding_name) + 1; - } else { - length += 1; - } - } else { - length += strlen(font_set->substitute->name) + 1; - } - } else { - length += strlen(font_set->font_data->name) + 1; - } - /* Change 1996.01.23 end */ - count++; - } - - if (count < 1) { - return True; - } - - charset_list = (char **) Xmalloc(sizeof(char *) * count); - if (charset_list == NULL) { - return False; - } - - charset_buf = (char *) Xmalloc(length); - if (charset_buf == NULL) { - Xfree(charset_list); - return False; - } - - oc->core.missing_list.charset_list = charset_list; - oc->core.missing_list.charset_count = count; - - font_set = gen->font_set; - font_set_num = gen->font_set_num; - - for ( ; font_set_num-- > 0; font_set++) { - if (font_set->info || font_set->font) { - continue; - } - - /* Change 1996.01.23 start */ - if(font_set->font_data_count <= 0 || - font_set->font_data == (FontData)NULL) { - if(font_set->substitute_num <= 0 || - font_set->substitute == (FontData)NULL) { - if(font_set->charset_list != NULL){ - strcpy(charset_buf, - font_set->charset_list[0]->encoding_name); - } else { - strcpy(charset_buf, ""); - } - result = 0; - } else { - strcpy(charset_buf, font_set->substitute->name); - } - } else { - strcpy(charset_buf, font_set->font_data->name); - } - /* Change 1996.01.23 end */ - *charset_list++ = charset_buf; - charset_buf += strlen(charset_buf) + 1; - } - - if(result == 0) { - return(False); - } - - return True; -} - -static Bool -create_fontset( - XOC oc) -{ - XOMGenericPart *gen = XOM_GENERIC(oc->core.om); - int found_num; - - if (init_fontset(oc) == False) - return False; - - found_num = parse_fontname(oc); - if (found_num <= 0) { - if (found_num == 0) - set_missing_list(oc); - return False; - } - - if (gen->on_demand_loading == True) { - if (load_font_info(oc) == False) - return False; - } else { - if (load_font(oc) == False) - return False; - } - - if (init_core_part(oc) == False) - return False; - - if (set_missing_list(oc) == False) - return False; - - return True; -} - -/* For VW/UDC start */ -static void -free_fontdataOC( - Display *dpy, - FontData font_data, - int font_data_count) -{ - for( ; font_data_count-- ; font_data++) { - if(font_data->xlfd_name){ - Xfree(font_data->xlfd_name); - font_data->xlfd_name = NULL; - } - if(font_data->font){ /* ADD 1996.01.7 */ - if(font_data->font->fid) /* Add 1996.01.23 */ - XFreeFont(dpy,font_data->font); /* ADD 1996.01.7 */ - else /* Add 1996.01.23 */ - XFreeFontInfo(NULL, font_data->font, 1);/* Add 1996.01.23 */ - font_data->font = NULL; - } -/* - * font_data->name and font_data->scopes belong to the OM not OC. - * To save space this data is shared between OM and OC. We are - * not allowed to free it here. - * It has been moved to free_fontdataOM() - */ -/* - if(font_data->scopes){ - Xfree(font_data->scopes); - font_data->scopes = NULL; - } - if(font_data->name){ - Xfree(font_data->name); - font_data->name = NULL; - } -*/ - } -} - -static void destroy_fontdata( - XOCGenericPart *gen, - Display *dpy) -{ - FontSet font_set = (FontSet) NULL; - int font_set_num = 0; - - if (gen->font_set) { - font_set = gen->font_set; - font_set_num = gen->font_set_num; - for( ; font_set_num-- ; font_set++) { - if (font_set->font) { - if(font_set->font->fid) - XFreeFont(dpy,font_set->font); - else - XFreeFontInfo(NULL, font_set->font, 1); - font_set->font = NULL; - } - if(font_set->font_data) { - if (font_set->info) - XFreeFontInfo(NULL, font_set->info, 1); - free_fontdataOC(dpy, - font_set->font_data, font_set->font_data_count); - Xfree(font_set->font_data); - font_set->font_data = NULL; - } - if(font_set->substitute) { - free_fontdataOC(dpy, - font_set->substitute, font_set->substitute_num); - Xfree(font_set->substitute); - font_set->substitute = NULL; - } - if(font_set->vmap) { - free_fontdataOC(dpy, - font_set->vmap, font_set->vmap_num); - Xfree(font_set->vmap); - font_set->vmap = NULL; - } - if(font_set->vrotate) { - free_fontdataOC(dpy, - (FontData)font_set->vrotate, - font_set->vrotate_num); - Xfree(font_set->vrotate); - font_set->vrotate = NULL; - } - } - Xfree(gen->font_set); - gen->font_set = NULL; - } -} -/* For VW/UDC end */ - -static void -destroy_oc( - XOC oc) -{ - Display *dpy = oc->core.om->core.display; - XOCGenericPart *gen = XOC_GENERIC(oc); - - if (gen->mbs_to_cs) - _XlcCloseConverter(gen->mbs_to_cs); - - if (gen->wcs_to_cs) - _XlcCloseConverter(gen->wcs_to_cs); - - if (gen->utf8_to_cs) - _XlcCloseConverter(gen->utf8_to_cs); - -/* For VW/UDC start */ /* Change 1996.01.8 */ - destroy_fontdata(gen,dpy); -/* -*/ -/* For VW/UDC end */ - - if (oc->core.base_name_list) - Xfree(oc->core.base_name_list); - - if (oc->core.font_info.font_name_list) - XFreeStringList(oc->core.font_info.font_name_list); - - if (oc->core.font_info.font_struct_list) { - Xfree(oc->core.font_info.font_struct_list); - } - - if (oc->core.missing_list.charset_list) - XFreeStringList(oc->core.missing_list.charset_list); - -#ifdef notdef - if (oc->core.res_name) - Xfree(oc->core.res_name); - if (oc->core.res_class) - Xfree(oc->core.res_class); -#endif - - Xfree(oc); -} - -static char * -set_oc_values( - XOC oc, - XlcArgList args, - int num_args) -{ - XOCGenericPart *gen = XOC_GENERIC(oc); - FontSet font_set = gen->font_set; - char *ret; - int num = gen->font_set_num; - - if (oc->core.resources == NULL) - return NULL; - - ret = _XlcSetValues((XPointer) oc, oc->core.resources, - oc->core.num_resources, args, num_args, XlcSetMask); - if(ret != NULL){ - return(ret); - } else { - for ( ; num-- > 0; font_set++) { - if (font_set->font_name == NULL) - continue; - if (font_set->vpart_initialize != 0) - continue; - if( oc->core.orientation == XOMOrientation_TTB_RTL || - oc->core.orientation == XOMOrientation_TTB_LTR ){ - load_fontdata(oc, font_set->vmap, font_set->vmap_num); - load_fontdata(oc, (FontData) font_set->vrotate, - font_set->vrotate_num); - font_set->vpart_initialize = 1; - } - } - return(NULL); - } -} - -static char * -get_oc_values( - XOC oc, - XlcArgList args, - int num_args) -{ - if (oc->core.resources == NULL) - return NULL; - - return _XlcGetValues((XPointer) oc, oc->core.resources, - oc->core.num_resources, args, num_args, XlcGetMask); -} - -static XOCMethodsRec oc_default_methods = { - destroy_oc, - set_oc_values, - get_oc_values, - _XmbDefaultTextEscapement, - _XmbDefaultTextExtents, - _XmbDefaultTextPerCharExtents, - _XmbDefaultDrawString, - _XmbDefaultDrawImageString, - _XwcDefaultTextEscapement, - _XwcDefaultTextExtents, - _XwcDefaultTextPerCharExtents, - _XwcDefaultDrawString, - _XwcDefaultDrawImageString, - _Xutf8DefaultTextEscapement, - _Xutf8DefaultTextExtents, - _Xutf8DefaultTextPerCharExtents, - _Xutf8DefaultDrawString, - _Xutf8DefaultDrawImageString -}; - -static XOCMethodsRec oc_generic_methods = { - destroy_oc, - set_oc_values, - get_oc_values, - _XmbGenericTextEscapement, - _XmbGenericTextExtents, - _XmbGenericTextPerCharExtents, - _XmbGenericDrawString, - _XmbGenericDrawImageString, - _XwcGenericTextEscapement, - _XwcGenericTextExtents, - _XwcGenericTextPerCharExtents, - _XwcGenericDrawString, - _XwcGenericDrawImageString, - _Xutf8GenericTextEscapement, - _Xutf8GenericTextExtents, - _Xutf8GenericTextPerCharExtents, - _Xutf8GenericDrawString, - _Xutf8GenericDrawImageString -}; - -typedef struct _XOCMethodsListRec { - const char *name; - XOCMethods methods; -} XOCMethodsListRec, *XOCMethodsList; - -static XOCMethodsListRec oc_methods_list[] = { - { "default", &oc_default_methods }, - { "generic", &oc_generic_methods } -}; - -static XlcResource oc_resources[] = { - { XNBaseFontName, NULLQUARK, sizeof(char *), - XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask }, - { XNOMAutomatic, NULLQUARK, sizeof(Bool), - XOffsetOf(XOCRec, core.om_automatic), XlcGetMask }, - { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList), - XOffsetOf(XOCRec, core.missing_list), XlcGetMask }, - { XNDefaultString, NULLQUARK, sizeof(char *), - XOffsetOf(XOCRec, core.default_string), XlcGetMask }, - { XNOrientation, NULLQUARK, sizeof(XOrientation), - XOffsetOf(XOCRec, core.orientation), XlcDefaultMask | XlcSetMask | XlcGetMask }, - { XNResourceName, NULLQUARK, sizeof(char *), - XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask }, - { XNResourceClass, NULLQUARK, sizeof(char *), - XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask }, - { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo), - XOffsetOf(XOCRec, core.font_info), XlcGetMask } -}; - -static XOC -create_oc( - XOM om, - XlcArgList args, - int num_args) -{ - XOC oc; - XOMGenericPart *gen = XOM_GENERIC(om); - XOCMethodsList methods_list = oc_methods_list; - int count; - - oc = (XOC) Xmalloc(sizeof(XOCGenericRec)); - if (oc == NULL) - return (XOC) NULL; - bzero((char *) oc, sizeof(XOCGenericRec)); - - oc->core.om = om; - - if (oc_resources[0].xrm_name == NULLQUARK) - _XlcCompileResourceList(oc_resources, XlcNumber(oc_resources)); - - if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources), - args, num_args, XlcCreateMask | XlcDefaultMask)) - goto err; - - if (oc->core.base_name_list == NULL) - goto err; - - oc->core.resources = oc_resources; - oc->core.num_resources = XlcNumber(oc_resources); - - if (create_fontset(oc) == False) - goto err; - - oc->methods = &oc_generic_methods; - - if (gen->object_name) { - count = XlcNumber(oc_methods_list); - - for ( ; count-- > 0; methods_list++) { - if (!_XlcCompareISOLatin1(gen->object_name, methods_list->name)) { - oc->methods = methods_list->methods; - break; - } - } - } - - return oc; - -err: - destroy_oc(oc); - - return (XOC) NULL; -} - -static void -free_fontdataOM( - FontData font_data, - int font_data_count) -{ - for( ; font_data_count-- ; font_data++) { - if(font_data->name){ - Xfree(font_data->name); - font_data->name = NULL; - } - if(font_data->scopes){ - Xfree(font_data->scopes); - font_data->scopes = NULL; - } - } -} - -static Status -close_om( - XOM om) -{ - XOMGenericPart *gen = XOM_GENERIC(om); - OMData data; - int count; - - if ((data = gen->data)) { - for (count = gen->data_num; count-- > 0; data++) { - if (data->charset_list){ - Xfree(data->charset_list); - data->charset_list = NULL; - } - /* free font_data for om */ - if (data->font_data) { - free_fontdataOM(data->font_data,data->font_data_count); - Xfree(data->font_data); - data->font_data = NULL; - } - /* free substitute for om */ - if (data->substitute) { - free_fontdataOM(data->substitute,data->substitute_num); - Xfree(data->substitute); - data->substitute = NULL; - } - /* free vmap for om */ - if (data->vmap) { - free_fontdataOM(data->vmap,data->vmap_num); - Xfree(data->vmap); - data->vmap = NULL; - } - /* free vrotate for om */ - if (data->vrotate) { - Xfree(data->vrotate); - data->vrotate = NULL; - } - } - Xfree(gen->data); - gen->data = NULL; - } - - if (gen->object_name){ - Xfree(gen->object_name); - gen->object_name = NULL; - } - - if (om->core.res_name){ - Xfree(om->core.res_name); - om->core.res_name = NULL; - } - if (om->core.res_class){ - Xfree(om->core.res_class); - om->core.res_class = NULL; - } - if (om->core.required_charset.charset_list && - om->core.required_charset.charset_count > 0){ - XFreeStringList(om->core.required_charset.charset_list); - om->core.required_charset.charset_list = NULL; - } else { - Xfree((char*)om->core.required_charset.charset_list); - om->core.required_charset.charset_list = NULL; - } - if (om->core.orientation_list.orientation){ - Xfree(om->core.orientation_list.orientation); - om->core.orientation_list.orientation = NULL; - } - - Xfree(om); - - return 1; -} - -static char * -set_om_values( - XOM om, - XlcArgList args, - int num_args) -{ - if (om->core.resources == NULL) - return NULL; - - return _XlcSetValues((XPointer) om, om->core.resources, - om->core.num_resources, args, num_args, XlcSetMask); -} - -static char * -get_om_values( - XOM om, - XlcArgList args, - int num_args) -{ - if (om->core.resources == NULL) - return NULL; - - return _XlcGetValues((XPointer) om, om->core.resources, - om->core.num_resources, args, num_args, XlcGetMask); -} - -static XOMMethodsRec methods = { - close_om, - set_om_values, - get_om_values, - create_oc -}; - -static XlcResource om_resources[] = { - { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList), - XOffsetOf(XOMRec, core.required_charset), XlcGetMask }, - { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation), - XOffsetOf(XOMRec, core.orientation_list), XlcGetMask }, - { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool), - XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask }, - { XNContextualDrawing, NULLQUARK, sizeof(Bool), - XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask } -}; - -static XOM -create_om( - XLCd lcd, - Display *dpy, - XrmDatabase rdb, - _Xconst char *res_name, - _Xconst char *res_class) -{ - XOM om; - - om = (XOM) Xmalloc(sizeof(XOMGenericRec)); - if (om == NULL) - return (XOM) NULL; - bzero((char *) om, sizeof(XOMGenericRec)); - - om->methods = &methods; - om->core.lcd = lcd; - om->core.display = dpy; - om->core.rdb = rdb; - if (res_name) { - om->core.res_name = (char *) Xmalloc(strlen(res_name) + 1); - if (om->core.res_name == NULL) - goto err; - strcpy(om->core.res_name, res_name); - } - if (res_class) { - om->core.res_class = (char *) Xmalloc(strlen(res_class) + 1); - if (om->core.res_class == NULL) - goto err; - strcpy(om->core.res_class, res_class); - } - - if (om_resources[0].xrm_name == NULLQUARK) - _XlcCompileResourceList(om_resources, XlcNumber(om_resources)); - - om->core.resources = om_resources; - om->core.num_resources = XlcNumber(om_resources); - - return om; - -err: - close_om(om); - - return (XOM) NULL; -} - -static OMData -add_data( - XOM om) -{ - XOMGenericPart *gen = XOM_GENERIC(om); - OMData new; - int num; - - if ((num = gen->data_num)) - new = (OMData) Xrealloc(gen->data, (num + 1) * sizeof(OMDataRec)); - else - new = (OMData) Xmalloc(sizeof(OMDataRec)); - - if (new == NULL) - return NULL; - - gen->data_num = num + 1; - gen->data = new; - - new += num; - bzero((char *) new, sizeof(OMDataRec)); - - return new; -} - -/* For VW/UDC */ - -FontData -read_EncodingInfo( - int count, - char **value) -{ - FontData font_data,ret; - char *buf, *bufptr,*scp; - int len; - font_data = (FontData) Xmalloc(sizeof(FontDataRec) * count); - if (font_data == NULL) - return NULL; - bzero((char *) font_data, sizeof(FontDataRec) * count); - - ret = font_data; - for ( ; count-- > 0; font_data++) { -/* - strcpy(buf, *value++); -*/ - buf = *value; value++; - if ((bufptr = strchr(buf, ':'))) { - len = (int)(bufptr - buf); - bufptr++ ; - } else - len = strlen(buf); - font_data->name = (char *) Xmalloc(len + 1); - if (font_data->name == NULL) - return NULL; - strncpy(font_data->name, buf,len); - font_data->name[len] = 0; - if (bufptr && _XlcCompareISOLatin1(bufptr, "GL") == 0) - font_data->side = XlcGL; - else if (bufptr && _XlcCompareISOLatin1(bufptr, "GR") == 0) - font_data->side = XlcGR; - else - font_data->side = XlcGLGR; - - if (bufptr && (scp = strchr(bufptr, '['))){ - font_data->scopes = _XlcParse_scopemaps(scp,&(font_data->scopes_num)); - } - } - return(ret); -} - -static CodeRange read_vrotate( - int count, - char **value, - int *type, - int *vrotate_num) -{ - CodeRange range; - if(!strcmp(value[0],"all")){ - *type = VROTATE_ALL ; - *vrotate_num = 0 ; - return (NULL); - } else if(*(value[0]) == '['){ - *type = VROTATE_PART ; - range = (CodeRange) _XlcParse_scopemaps(value[0],vrotate_num); - return (range); - } else { - *type = VROTATE_NONE ; - *vrotate_num = 0 ; - return (NULL); - } -} - -static void read_vw( - XLCd lcd, - OMData font_set, - int num) -{ - char **value, buf[BUFSIZ]; - int count; - - sprintf(buf, "fs%d.font.vertical_map", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if (count > 0){ - _XlcDbg_printValue(buf,value,count); - font_set->vmap_num = count; - font_set->vmap = read_EncodingInfo(count,value); - } - - sprintf(buf, "fs%d.font.vertical_rotate", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if (count > 0){ - _XlcDbg_printValue(buf,value,count); - font_set->vrotate = read_vrotate(count,value,&(font_set->vrotate_type), - &(font_set->vrotate_num)); - } -} -/* VW/UDC end */ -static Bool -init_om( - XOM om) -{ - XLCd lcd = om->core.lcd; - XOMGenericPart *gen = XOM_GENERIC(om); - OMData data; - XlcCharSet *charset_list; - FontData font_data; - char **required_list; - XOrientation *orientation; - char **value, buf[BUFSIZ], *bufptr; - int count = 0, num = 0, length = 0; - - _XlcGetResource(lcd, "XLC_FONTSET", "on_demand_loading", &value, &count); - if (count > 0 && _XlcCompareISOLatin1(*value, "True") == 0) - gen->on_demand_loading = True; - - _XlcGetResource(lcd, "XLC_FONTSET", "object_name", &value, &count); - if (count > 0) { - gen->object_name = (char *) Xmalloc(strlen(*value) + 1); - if (gen->object_name == NULL) - return False; - strcpy(gen->object_name, *value); - } - - for (num = 0; ; num++) { - - sprintf(buf, "fs%d.charset.name", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - - if( count < 1){ - sprintf(buf, "fs%d.charset", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if (count < 1) - break; - } - - data = add_data(om); - if (data == NULL) - return False; - - charset_list = (XlcCharSet *) Xmalloc(sizeof(XlcCharSet) * count); - if (charset_list == NULL) - return False; - data->charset_list = charset_list; - data->charset_count = count; - - while (count-- > 0){ - *charset_list++ = _XlcGetCharSet(*value++); - } - sprintf(buf, "fs%d.charset.udc_area", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if( count > 0){ - UDCArea udc; - int i,flag = 0; - udc = (UDCArea)Xmalloc(count * sizeof(UDCAreaRec)); - if (udc == NULL) - return False; - for(i=0;i<count;i++){ - sscanf(value[i],"\\x%lx,\\x%lx", &(udc[i].start), - &(udc[i].end)); - } - for(i=0;i<data->charset_count;i++){ - if(data->charset_list[i]->udc_area == NULL){ - data->charset_list[i]->udc_area = udc; - data->charset_list[i]->udc_area_num = count; - flag = 1; - } - } - if(flag == 0){ - Xfree(udc); - } - } - - sprintf(buf, "fs%d.font.primary", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if (count < 1){ - sprintf(buf, "fs%d.font", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if (count < 1) - return False; - } - - font_data = read_EncodingInfo(count,value); - if (font_data == NULL) - return False; - - data->font_data = font_data; - data->font_data_count = count; - - sprintf(buf, "fs%d.font.substitute", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if (count > 0){ - font_data = read_EncodingInfo(count,value); - if (font_data == NULL) - return False; - data->substitute = font_data; - data->substitute_num = count; - } else { - sprintf(buf, "fs%d.font", num); - _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count); - if (count < 1) { - data->substitute = NULL; - data->substitute_num = 0; - } else { - font_data = read_EncodingInfo(count,value); - data->substitute = font_data; - data->substitute_num = count; - } - } - read_vw(lcd,data,num); - length += strlen(data->font_data->name) + 1; - } - - /* required charset list */ - required_list = (char **) Xmalloc(sizeof(char *) * gen->data_num); - if (required_list == NULL) - return False; - - bufptr = (char *) Xmalloc(length); - if (bufptr == NULL) { - Xfree(required_list); - return False; - } - - om->core.required_charset.charset_list = required_list; - om->core.required_charset.charset_count = gen->data_num; - - count = gen->data_num; - data = gen->data; - - for ( ; count-- > 0; data++) { - strcpy(bufptr, data->font_data->name); - *required_list++ = bufptr; - bufptr += strlen(bufptr) + 1; - } - - /* orientation list */ - orientation = (XOrientation *) Xmalloc(sizeof(XOrientation) * 2); - if (orientation == NULL) - return False; - - orientation[0] = XOMOrientation_LTR_TTB; - orientation[1] = XOMOrientation_TTB_RTL; - om->core.orientation_list.orientation = orientation; - om->core.orientation_list.num_orientation = 2; - - /* directional dependent drawing */ - om->core.directional_dependent = False; - - /* contexual drawing */ - om->core.contextual_drawing = False; - - /* context dependent */ - om->core.context_dependent = False; - - return True; -} - -XOM -_XomGenericOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb, - _Xconst char *res_name, _Xconst char *res_class) -{ - XOM om; - - om = create_om(lcd, dpy, rdb, res_name, res_class); - if (om == NULL) - return (XOM) NULL; - - if (init_om(om) == False) - goto err; - - return om; - -err: - close_om(om); - - return (XOM) NULL; -} - -Bool -_XInitOM( - XLCd lcd) -{ - lcd->methods->open_om = _XomGenericOpenOM; - - return True; -} +/* #define FONTDEBUG */
+/*
+ * Copyright 1992, 1993 by TOSHIBA Corp.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of TOSHIBA not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. TOSHIBA make no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Author: Katsuhisa Yano TOSHIBA Corp.
+ * mopi@osa.ilab.toshiba.co.jp
+ */
+/*
+ * Copyright 1995 by FUJITSU LIMITED
+ * This is source code modified by FUJITSU LIMITED under the Joint
+ * Development Agreement for the CDE/Motif PST.
+ *
+ * Modifier: Takanori Tateno FUJITSU LIMITED
+ *
+ */
+
+/*
+ * Fixed the algorithms in parse_fontname() and parse_fontdata()
+ * to improve the logic for determining which font should be
+ * returned for a given CharSet. We even added some comments
+ * so that you can figure out what in the heck we're doing. We
+ * realize this is a departure from the norm, but hey, we're
+ * rebels! :-) :-)
+ *
+ * Modifiers: Jeff Walls, Paul Anderson: HEWLETT-PACKARD
+ */
+/*
+ * Cleaned up mess, removed some blabla
+ * Egbert Eich, SuSE Linux AG
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "Xlibint.h"
+#include "XomGeneric.h"
+#include "XlcGeneric.h"
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#define MAXFONTS 100
+#define PIXEL_SIZE_FIELD 7
+#define POINT_SIZE_FIELD 8
+#define CHARSET_ENCODING_FIELD 14
+#define XLFD_MAX_LEN 255
+
+#if 0
+extern int _XmbDefaultTextEscapement(), _XwcDefaultTextEscapement(),
+ _Xutf8DefaultTextEscapement();
+extern int _XmbDefaultTextExtents(), _XwcDefaultTextExtents(),
+ _Xutf8DefaultTextExtents();
+extern Status _XmbDefaultTextPerCharExtents(), _XwcDefaultTextPerCharExtents(),
+ _Xutf8DefaultTextPerCharExtents();
+extern int _XmbDefaultDrawString(), _XwcDefaultDrawString(),
+ _Xutf8DefaultDrawString();
+extern void _XmbDefaultDrawImageString(), _XwcDefaultDrawImageString(),
+ _Xutf8DefaultDrawImageString();
+
+extern int _XmbGenericTextEscapement(), _XwcGenericTextEscapement(),
+ _Xutf8GenericTextEscapement();
+extern int _XmbGenericTextExtents(), _XwcGenericTextExtents(),
+ _Xutf8GenericTextExtents();
+extern Status _XmbGenericTextPerCharExtents(), _XwcGenericTextPerCharExtents(),
+ _Xutf8GenericTextPerCharExtents();
+extern int _XmbGenericDrawString(), _XwcGenericDrawString(),
+ _Xutf8GenericDrawString();
+extern void _XmbGenericDrawImageString(), _XwcGenericDrawImageString(),
+ _Xutf8GenericDrawImageString();
+
+extern void _XlcDbg_printValue (const char *str, char **value, int num);
+#endif
+
+/* For VW/UDC start */
+
+static FontData
+init_fontdata(
+ FontData font_data,
+ int font_data_count)
+{
+ FontData fd;
+ int i;
+
+ fd = (FontData)Xmalloc(sizeof(FontDataRec) * font_data_count);
+ if(fd == (FontData) NULL)
+ return False;
+
+ memset(fd, 0x00, sizeof(FontData) * font_data_count);
+ for(i = 0 ; i < font_data_count ; i++)
+ fd[i] = font_data[i];
+
+ return fd;
+}
+
+static VRotate
+init_vrotate(
+ FontData font_data,
+ int font_data_count,
+ int type,
+ CodeRange code_range,
+ int code_range_num)
+{
+ VRotate vrotate;
+ int i;
+
+ if(type == VROTATE_NONE)
+ return (VRotate)NULL;
+
+ vrotate = (VRotate)Xmalloc(sizeof(VRotateRec) * font_data_count);
+ if(vrotate == (VRotate) NULL)
+ return False;
+
+ memset(vrotate, 0x00, sizeof(VRotateRec) * font_data_count);
+ for(i = 0 ; i < font_data_count ; i++) {
+ vrotate[i].charset_name = font_data[i].name;
+ vrotate[i].side = font_data[i].side;
+ if(type == VROTATE_PART) {
+ vrotate[i].num_cr = code_range_num;
+ vrotate[i].code_range = code_range;
+ }
+ }
+
+ return vrotate;
+}
+
+static Bool
+init_fontset(
+ XOC oc)
+{
+ XOCGenericPart *gen;
+ FontSet font_set;
+ OMData data;
+ int count;
+
+ count = XOM_GENERIC(oc->core.om)->data_num;
+ data = XOM_GENERIC(oc->core.om)->data;
+
+ font_set = (FontSet) Xmalloc(sizeof(FontSetRec) * count);
+ if (font_set == NULL)
+ return False;
+ memset((char *) font_set, 0x00, sizeof(FontSetRec) * count);
+
+ gen = XOC_GENERIC(oc);
+ gen->font_set_num = count;
+ gen->font_set = font_set;
+
+ for ( ; count-- > 0; data++, font_set++) {
+ font_set->charset_count = data->charset_count;
+ font_set->charset_list = data->charset_list;
+
+ if((font_set->font_data = init_fontdata(data->font_data,
+ data->font_data_count)) == NULL)
+ goto err;
+ font_set->font_data_count = data->font_data_count;
+ if((font_set->substitute = init_fontdata(data->substitute,
+ data->substitute_num)) == NULL)
+ goto err;
+ font_set->substitute_num = data->substitute_num;
+ if((font_set->vmap = init_fontdata(data->vmap,
+ data->vmap_num)) == NULL)
+ goto err;
+ font_set->vmap_num = data->vmap_num;
+
+ if(data->vrotate_type != VROTATE_NONE) {
+ /* A vrotate member is specified primary font data */
+ /* as initial value. */
+ if((font_set->vrotate = init_vrotate(data->font_data,
+ data->font_data_count,
+ data->vrotate_type,
+ data->vrotate,
+ data->vrotate_num)) == NULL)
+ goto err;
+ font_set->vrotate_num = data->font_data_count;
+ }
+ }
+ return True;
+
+err:
+ if(font_set->font_data)
+ Xfree(font_set->font_data);
+ if(font_set->substitute)
+ Xfree(font_set->substitute);
+ if(font_set->vmap)
+ Xfree(font_set->vmap);
+ if(font_set->vrotate)
+ Xfree(font_set->vrotate);
+ if(font_set)
+ Xfree(font_set);
+ gen->font_set = (FontSet) NULL;
+ gen->font_set_num = 0;
+ return False;
+}
+
+/* For VW/UDC end */
+
+static char *
+get_prop_name(
+ Display *dpy,
+ XFontStruct *fs)
+{
+ unsigned long fp;
+
+ if (XGetFontProperty(fs, XA_FONT, &fp))
+ return XGetAtomName(dpy, fp);
+
+ return (char *) NULL;
+}
+
+/* For VW/UDC start */
+
+static Bool
+load_fontdata(
+ XOC oc,
+ FontData font_data,
+ int font_data_num)
+{
+ Display *dpy = oc->core.om->core.display;
+ FontData fd = font_data;
+
+ if(font_data == NULL) return(True);
+ for( ; font_data_num-- ; fd++) {
+ if(fd->xlfd_name != (char *) NULL && fd->font == NULL) {
+ fd->font = XLoadQueryFont(dpy, fd->xlfd_name);
+ if (fd->font == NULL){
+ return False;
+ }
+ }
+ }
+ return True;
+}
+
+static Bool
+load_fontset_data(
+ XOC oc,
+ FontSet font_set)
+{
+ Display *dpy = oc->core.om->core.display;
+
+ if(font_set->font_name == (char *)NULL) return False ;
+
+ /* If font_set->font is not NULL, it contains the *best*
+ * match font for this FontSet.
+ * -- jjw/pma (HP)
+ */
+ if(font_set->font == NULL) {
+ font_set->font = XLoadQueryFont(dpy, font_set->font_name);
+ if (font_set->font == NULL){
+ return False;
+ }
+ }
+ return True;
+}
+
+static Bool
+load_font(
+ XOC oc)
+{
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+ FontSet font_set = gen->font_set;
+ int num = gen->font_set_num;
+
+ for ( ; num-- > 0; font_set++) {
+ if (font_set->font_name == NULL)
+ continue;
+
+ if (load_fontset_data (oc, font_set) != True)
+ return False;
+#ifndef TESTVERSION
+ if(load_fontdata(oc, font_set->font_data,
+ font_set->font_data_count) != True)
+ return False;
+
+ if(load_fontdata(oc, font_set->substitute,
+ font_set->substitute_num) != True)
+ return False;
+#endif
+
+/* Add 1996.05.20 */
+ if( oc->core.orientation == XOMOrientation_TTB_RTL ||
+ oc->core.orientation == XOMOrientation_TTB_LTR ){
+ if (font_set->vpart_initialize == 0) {
+ load_fontdata(oc, font_set->vmap, font_set->vmap_num);
+ load_fontdata(oc, (FontData) font_set->vrotate,
+ font_set->vrotate_num);
+ font_set->vpart_initialize = 1;
+ }
+ }
+
+ if (font_set->font->min_byte1 || font_set->font->max_byte1)
+ font_set->is_xchar2b = True;
+ else
+ font_set->is_xchar2b = False;
+ }
+
+ return True;
+}
+
+/* For VW/UDC end */
+
+static Bool
+load_font_info(
+ XOC oc)
+{
+ Display *dpy = oc->core.om->core.display;
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+ FontSet font_set = gen->font_set;
+ char **fn_list;
+ int fn_num, num = gen->font_set_num;
+
+ for ( ; num-- > 0; font_set++) {
+ if (font_set->font_name == NULL)
+ continue;
+
+ if (font_set->info == NULL) {
+ fn_list = XListFontsWithInfo(dpy, font_set->font_name, 1, &fn_num,
+ &font_set->info);
+ if (font_set->info == NULL)
+ return False;
+
+ XFreeFontNames(fn_list);
+ }
+ }
+
+ return True;
+}
+
+/* For Vertical Writing start */
+
+static void
+check_fontset_extents(
+ XCharStruct *overall,
+ int *logical_ascent,
+ int *logical_descent,
+ XFontStruct *font)
+{
+ overall->lbearing = min(overall->lbearing, font->min_bounds.lbearing);
+ overall->rbearing = max(overall->rbearing, font->max_bounds.rbearing);
+ overall->ascent = max(overall->ascent, font->max_bounds.ascent);
+ overall->descent = max(overall->descent, font->max_bounds.descent);
+ overall->width = max(overall->width, font->max_bounds.width);
+ *logical_ascent = max(*logical_ascent, font->ascent);
+ *logical_descent = max(*logical_descent, font->descent);
+}
+
+/* For Vertical Writing end */
+
+static void
+set_fontset_extents(
+ XOC oc)
+{
+ XRectangle *ink = &oc->core.font_set_extents.max_ink_extent;
+ XRectangle *logical = &oc->core.font_set_extents.max_logical_extent;
+ XFontStruct **font_list, *font;
+ XCharStruct overall;
+ int logical_ascent, logical_descent;
+ int num = oc->core.font_info.num_font;
+
+ font_list = oc->core.font_info.font_struct_list;
+ font = *font_list++;
+ overall = font->max_bounds;
+ overall.lbearing = font->min_bounds.lbearing;
+ logical_ascent = font->ascent;
+ logical_descent = font->descent;
+
+ /* For Vertical Writing start */
+
+ while (--num > 0) {
+ font = *font_list++;
+ check_fontset_extents(&overall, &logical_ascent, &logical_descent,
+ font);
+ }
+
+ {
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+ FontSet font_set = gen->font_set;
+ FontData font_data;
+ int font_set_num = gen->font_set_num;
+ int font_data_count;
+
+ for( ; font_set_num-- ; font_set++) {
+ if(font_set->vmap_num > 0) {
+ font_data = font_set->vmap;
+ font_data_count = font_set->vmap_num;
+ for( ; font_data_count-- ; font_data++) {
+ if(font_data->font != NULL) {
+ check_fontset_extents(&overall, &logical_ascent,
+ &logical_descent,
+ font_data->font);
+ }
+ }
+ }
+
+ if(font_set->vrotate_num > 0 && font_set->vrotate != NULL) {
+ font_data = (FontData) font_set->vrotate;
+ font_data_count = font_set->vrotate_num;
+ for( ; font_data_count-- ; font_data++) {
+ if(font_data->font != NULL) {
+ check_fontset_extents(&overall, &logical_ascent,
+ &logical_descent,
+ font_data->font);
+ }
+ }
+ }
+ }
+ }
+
+ /* For Vertical Writing start */
+
+ ink->x = overall.lbearing;
+ ink->y = -(overall.ascent);
+ ink->width = overall.rbearing - overall.lbearing;
+ ink->height = overall.ascent + overall.descent;
+
+ logical->x = 0;
+ logical->y = -(logical_ascent);
+ logical->width = overall.width;
+ logical->height = logical_ascent + logical_descent;
+}
+
+static Bool
+init_core_part(
+ XOC oc)
+{
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+ FontSet font_set;
+ int font_set_num;
+ XFontStruct **font_struct_list;
+ char **font_name_list, *font_name_buf;
+ int count, length;
+
+ font_set = gen->font_set;
+ font_set_num = gen->font_set_num;
+ count = length = 0;
+
+ for ( ; font_set_num-- > 0; font_set++) {
+ if (font_set->font_name == NULL)
+ continue;
+
+ length += strlen(font_set->font_name) + 1;
+
+ count++;
+ }
+ if (count == 0)
+ return False;
+
+ font_struct_list = (XFontStruct **) Xmalloc(sizeof(XFontStruct *) * count);
+ if (font_struct_list == NULL)
+ return False;
+
+ font_name_list = (char **) Xmalloc(sizeof(char *) * count);
+ if (font_name_list == NULL)
+ goto err;
+
+ font_name_buf = (char *) Xmalloc(length);
+ if (font_name_buf == NULL)
+ goto err;
+
+ oc->core.font_info.num_font = count;
+ oc->core.font_info.font_name_list = font_name_list;
+ oc->core.font_info.font_struct_list = font_struct_list;
+
+ font_set = gen->font_set;
+ font_set_num = gen->font_set_num;
+
+ for (count = 0; font_set_num-- > 0; font_set++) {
+ if (font_set->font_name == NULL)
+ continue;
+
+ font_set->id = count;
+ if (font_set->font)
+ *font_struct_list++ = font_set->font;
+ else
+ *font_struct_list++ = font_set->info;
+ strcpy(font_name_buf, font_set->font_name);
+ Xfree(font_set->font_name);
+ *font_name_list++ = font_set->font_name = font_name_buf;
+ font_name_buf += strlen(font_name_buf) + 1;
+
+ count++;
+ }
+
+ set_fontset_extents(oc);
+
+ return True;
+
+err:
+ if (font_name_list)
+ Xfree(font_name_list);
+ Xfree(font_struct_list);
+
+ return False;
+}
+
+static char *
+get_font_name(
+ XOC oc,
+ char *pattern)
+{
+ char **list, *name;
+ int count = 0;
+
+ list = XListFonts(oc->core.om->core.display, pattern, 1, &count);
+ if (list == NULL)
+ return NULL;
+
+ name = (char *) Xmalloc(strlen(*list) + 1);
+ if (name)
+ strcpy(name, *list);
+
+ XFreeFontNames(list);
+
+ return name;
+}
+
+/* For VW/UDC start*/
+
+static char *
+get_rotate_fontname(
+ char *font_name)
+{
+ char *pattern = NULL, *ptr = NULL;
+ char *fields[CHARSET_ENCODING_FIELD];
+ char str_pixel[32], str_point[4];
+ char *rotate_font_ptr = NULL;
+ int pixel_size = 0;
+ int field_num = 0, len = 0;
+
+ if(font_name == (char *) NULL || (len = strlen(font_name)) <= 0
+ || len > XLFD_MAX_LEN)
+ return NULL;
+
+ pattern = (char *)Xmalloc(len + 1);
+ if(!pattern)
+ return NULL;
+ strcpy(pattern, font_name);
+
+ memset(fields, 0, sizeof(char *) * 14);
+ ptr = pattern;
+ while(isspace(*ptr)) {
+ ptr++;
+ }
+ if(*ptr == '-')
+ ptr++;
+
+ for(field_num = 0 ; field_num < CHARSET_ENCODING_FIELD && ptr && *ptr ;
+ ptr++, field_num++) {
+ fields[field_num] = ptr;
+
+ if((ptr = strchr(ptr, '-'))) {
+ *ptr = '\0';
+ } else {
+ field_num++; /* Count last field */
+ break;
+ }
+ }
+
+ if(field_num < CHARSET_ENCODING_FIELD)
+ goto free_pattern;
+
+ /* Pixel Size field : fields[6] */
+ for(ptr = fields[PIXEL_SIZE_FIELD - 1] ; ptr && *ptr; ptr++) {
+ if(!isdigit(*ptr)) {
+ if(*ptr == '['){ /* 960730 */
+ strcpy(pattern, font_name);
+ return(pattern);
+ }
+ goto free_pattern;
+ }
+ }
+ pixel_size = atoi(fields[PIXEL_SIZE_FIELD - 1]);
+ sprintf(str_pixel, "[ 0 ~%d %d 0 ]", pixel_size, pixel_size);
+ fields[6] = str_pixel;
+
+ /* Point Size field : fields[7] */
+ strcpy(str_point, "*");
+ fields[POINT_SIZE_FIELD - 1] = str_point;
+
+ len = 0;
+ for (field_num = 0; field_num < CHARSET_ENCODING_FIELD &&
+ fields[field_num]; field_num++) {
+ len += 1 + strlen(fields[field_num]);
+ }
+
+ /* Max XLFD length is 255 */
+ if (len > XLFD_MAX_LEN)
+ goto free_pattern;
+
+ rotate_font_ptr = (char *)Xmalloc(len + 1);
+ if(!rotate_font_ptr)
+ goto free_pattern;
+
+ rotate_font_ptr[0] = '\0';
+
+ for(field_num = 0 ; field_num < CHARSET_ENCODING_FIELD &&
+ fields[field_num] ; field_num++) {
+ strcat(rotate_font_ptr, "-");
+ strcat(rotate_font_ptr, fields[field_num]);
+ }
+
+free_pattern:
+ Xfree(pattern);
+
+ return rotate_font_ptr;
+}
+
+static Bool
+is_match_charset(
+ FontData font_data,
+ char *font_name)
+{
+ char *last;
+ int length, name_len;
+
+ name_len = strlen(font_name);
+ last = font_name + name_len;
+
+ length = strlen(font_data->name);
+ if (length > name_len)
+ return False;
+
+ if (_XlcCompareISOLatin1(last - length, font_data->name) == 0)
+ return True;
+
+ return False;
+}
+
+#if 0
+static char *
+get_font_name_from_list(
+ XOC oc,
+ char *pattern,
+ FontData font_data)
+{
+ char **list, *name = (char *)NULL, *fname;
+ int count = 0, i;
+
+ list = XListFonts(oc->core.om->core.display, pattern, MAXFONTS, &count);
+ if (list == NULL)
+ return NULL;
+
+ for (i = 0; i < count; i++) {
+ fname = list[i];
+ if(is_match_charset(font_data, fname) == True) {
+ name = (char *) Xmalloc(strlen(fname) + 1);
+ if (name)
+ strcpy(name, fname);
+ break;
+ }
+ }
+
+ XFreeFontNames(list);
+
+ return name;
+}
+#endif
+
+static int
+parse_all_name(
+ XOC oc,
+ FontData font_data,
+ char *pattern)
+{
+
+#ifdef OLDCODE
+ if(is_match_charset(font_data, pattern) != True)
+ return False;
+
+ font_data->xlfd_name = (char *)Xmalloc(strlen(pattern)+1);
+ if(font_data->xlfd_name == NULL)
+ return (-1);
+
+ strcpy(font_data->xlfd_name, pattern);
+ return True;
+#else /* OLDCODE */
+ Display *dpy = oc->core.om->core.display;
+ char **fn_list = NULL, *prop_fname = NULL;
+ int list_num;
+ XFontStruct *fs_list;
+ if(is_match_charset(font_data, pattern) != True) {
+ /*
+ * pattern should not contain any wildcard (execpt '?')
+ * this was probably added to make this case insensitive.
+ */
+ if ((fn_list = XListFontsWithInfo(dpy, pattern,
+ MAXFONTS,
+ &list_num, &fs_list)) == NULL) {
+ return False;
+ }
+ /* shouldn't we loop here ? */
+ else if ((prop_fname = get_prop_name(dpy, fs_list)) == NULL) {
+ XFreeFontInfo(fn_list, fs_list, list_num);
+ return False;
+ }
+ else if ((is_match_charset(font_data, prop_fname) != True)) {
+ XFree(prop_fname);
+ XFreeFontInfo(fn_list, fs_list, list_num);
+ return False;
+ }
+ else {
+ font_data->xlfd_name = prop_fname;
+ XFreeFontInfo(fn_list, fs_list, list_num);
+ return True;
+ }
+ }
+
+ font_data->xlfd_name = (char *)Xmalloc(strlen(pattern)+1);
+ if(font_data->xlfd_name == NULL)
+ return (-1);
+
+ strcpy(font_data->xlfd_name, pattern);
+ return True;
+#endif /* OLDCODE */
+}
+
+static int
+parse_omit_name(
+ XOC oc,
+ FontData font_data,
+ char *pattern)
+{
+ char* last = (char *) NULL;
+ char* base_name;
+ char buf[XLFD_MAX_LEN + 1];
+ int length = 0;
+ int num_fields;
+ /*
+ * If the font specified by "pattern" is expandable to be
+ * a member of "font_data"'s FontSet, we've found a match.
+ */
+ if(is_match_charset(font_data, pattern) == True) {
+ if ((font_data->xlfd_name = get_font_name(oc, pattern)) != NULL) {
+ return True;
+ }
+ }
+
+ length = strlen (pattern);
+
+ if (length > XLFD_MAX_LEN)
+ return -1;
+
+ strcpy(buf, pattern);
+ last = buf + length - 1;
+
+ /* Replace the original encoding with the encoding for this FontSet. */
+
+ /* Figure out how many fields have been specified in this xlfd. */
+ for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
+ if (*base_name == '-') num_fields++;
+
+ switch (num_fields) {
+ case 12:
+ /* This is the best way to have specifed the fontset. In this
+ * case, there is no original encoding. E.g.,
+ * -*-*-*-*-*-*-14-*-*-*-*-*
+ * To this, we'll append a dash:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-
+ * then append the encoding to get:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
+ */
+ /*
+ * Take care of:
+ * -*-*-*-*-*-*-14-*-*-*-*-
+ */
+ if (*(last) == '-')
+ *++last = '*';
+
+ *++last = '-';
+ break;
+ case 13:
+ /* Got the charset, not the encoding, zap the charset In this
+ * case, there is no original encoding, but there is a charset. E.g.,
+ * -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990
+ * To this, we remove the charset:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-
+ * then append the new encoding to get:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
+ */
+ last = strrchr (buf, '-');
+ num_fields = 12;
+ break;
+ case 14:
+ /* Both the charset and the encoding are specified. Get rid
+ * of them so that we can append the new charset encoding. E.g.,
+ * -*-*-*-*-*-*-14-*-*-*-*-*-jisx0212.1990-0
+ * To this, we'll remove the encoding and charset to get:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-
+ * then append the new encoding to get:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
+ */
+ last = strrchr (buf, '-');
+ *last = '\0';
+ last = strrchr (buf, '-');
+ num_fields = 12;
+ break;
+ default:
+ if (*last != '-')
+ *++last = '-';
+ break;
+ }
+
+ /* At this point, "last" is pointing to the last "-" in the
+ * xlfd, and all xlfd's at this point take a form similar to:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-
+ * (i.e., no encoding).
+ * After the strcpy, we'll end up with something similar to:
+ * -*-*-*-*-*-*-14-*-*-*-*-*-JISX0208.1990-0
+ *
+ * If the modified font is found in the current FontSet,
+ * we've found a match.
+ */
+
+ last++;
+
+ if ((last - buf) + strlen(font_data->name) > XLFD_MAX_LEN)
+ return -1;
+
+ strcpy(last, font_data->name);
+ if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL)
+ return True;
+
+ /* This may mot be needed anymore as XListFonts() takes care of this */
+ while (num_fields < 12) {
+ if ((last - buf) > (XLFD_MAX_LEN - 2))
+ return -1;
+ *last = '*';
+ *(last + 1) = '-';
+ strcpy(last + 2, font_data->name);
+ num_fields++;
+ last+=2;
+ if ((font_data->xlfd_name = get_font_name(oc, buf)) != NULL)
+ return True;
+ }
+
+
+ return False;
+}
+
+
+typedef enum{C_PRIMARY, C_SUBSTITUTE, C_VMAP, C_VROTATE } ClassType;
+
+static int
+parse_fontdata(
+ XOC oc,
+ FontSet font_set,
+ FontData font_data,
+ int font_data_count,
+ char **name_list,
+ int name_list_count,
+ ClassType class,
+ FontDataRec *font_data_return)
+{
+
+ char **cur_name_list = name_list;
+ char *font_name = (char *) NULL;
+ char *pattern = (char *) NULL;
+ int found_num = 0, ret = 0;
+ int count = name_list_count;
+
+ if(name_list == NULL || count <= 0) {
+ return False;
+ }
+
+ if(font_data == NULL || font_data_count <= 0) {
+ return False;
+ }
+
+ /* Loop through each font encoding defined in the "font_data" FontSet. */
+ for ( ; font_data_count-- > 0; font_data++) {
+ Bool is_found = False;
+ font_name = (char *) NULL;
+ count = name_list_count;
+ cur_name_list = name_list;
+
+ /*
+ * Loop through each font specified by the user
+ * in the call to XCreateFontset().
+ */
+ while (count-- > 0) {
+ pattern = *cur_name_list++;
+ if (pattern == NULL || *pattern == '\0')
+ continue;
+#ifdef FONTDEBUG
+ fprintf(stderr,"Font pattern: %s %s\n",
+ pattern,font_data->name);
+#endif
+
+ /*
+ * If the current font is fully specified (i.e., the
+ * xlfd contains no wildcards) and the font exists on
+ * the X Server, we have a match.
+ */
+ if (strchr(pattern, '*') == NULL &&
+ (font_name = get_font_name(oc, pattern))) {
+ /*
+ * Find the full xlfd name for this font. If the font is
+ * already in xlfd format, it is simply returned. If the
+ * font is an alias for another font, the xlfd of the
+ * aliased font is returned.
+ */
+ ret = parse_all_name(oc, font_data, font_name);
+ Xfree(font_name);
+
+ if (ret == -1) return -1;
+ if (ret == False) continue;
+ /*
+ * Since there was an exact match of a fully-specified font
+ * or a font alias, we can return now since the desired font
+ * was found for the current font encoding for this FontSet.
+ *
+ * Previous implementations of this algorithm would
+ * not return here. Instead, they continued searching
+ * through the font encodings for this FontSet. The side-effect
+ * of that behavior is you may return a "substitute" match
+ * instead of an "exact" match. We believe there should be a
+ * preference on exact matches. Therefore, as soon as we
+ * find one, we bail.
+ *
+ * Also, previous implementations seemed to think it was
+ * important to find either a primary or substitute font
+ * for each Font encoding in the FontSet before returning an
+ * acceptable font. We don't believe this is necessary.
+ * All the client cares about is finding a reasonable font
+ * for what was passed in. If we find an exact match,
+ * there's no reason to look any further.
+ *
+ * -- jjw/pma (HP)
+ */
+ if (font_data_return) {
+ font_data_return->xlfd_name = (char *)Xmalloc
+ (strlen(font_data->xlfd_name) + 1);
+ if (!font_data_return->xlfd_name) return -1;
+
+ strcpy (font_data_return->xlfd_name, font_data->xlfd_name);
+
+ font_data_return->side = font_data->side;
+ }
+#ifdef FONTDEBUG
+ fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name);
+#endif
+
+ return True;
+ }
+ /*
+ * If the font name is not fully specified
+ * (i.e., it has wildcards), we have more work to do.
+ * See the comments in parse_omit_name()
+ * for the list of things to do.
+ */
+ ret = parse_omit_name(oc, font_data, pattern);
+
+ if (ret == -1) return -1;
+ if (ret == False) continue;
+
+ /*
+ * A font which matched the wild-carded specification was found.
+ * Only update the return data if a font has not yet been found.
+ * This maintains the convention that FontSets listed higher in
+ * a CodeSet in the Locale Database have higher priority than
+ * those FontSets listed lower in the CodeSet. In the following
+ * example:
+ *
+ * fs1 {
+ * charset HP-JIS:GR
+ * font JISX0208.1990-0:GL;\
+ * JISX0208.1990-1:GR;\
+ * JISX0208.1983-0:GL;\
+ * JISX0208.1983-1:GR
+ * }
+ *
+ * a font found in the JISX0208.1990-0 FontSet will have a
+ * higher priority than a font found in the JISX0208.1983-0
+ * FontSet.
+ */
+ if (font_data_return && font_data_return->xlfd_name == NULL) {
+
+#ifdef FONTDEBUG
+ fprintf(stderr,"XLFD name: %s\n",font_data->xlfd_name);
+#endif
+ font_data_return->xlfd_name = (char *)Xmalloc
+ (strlen(font_data->xlfd_name) + 1);
+ if (!font_data_return->xlfd_name) return -1;
+
+ strcpy (font_data_return->xlfd_name, font_data->xlfd_name);
+ font_data_return->side = font_data->side;
+ }
+
+ found_num++;
+ is_found = True;
+
+ break;
+ }
+
+ switch(class) {
+ case C_PRIMARY:
+ if(is_found == False) {
+ /*
+ * Did not find a font for the current FontSet. Check the
+ * FontSet's "substitute" font for a match. If we find a
+ * match, we'll keep searching in hopes of finding an exact
+ * match later down the FontSet list.
+ *
+ * when we return and we have found a font font_data_return
+ * contains the first (ie. best) match no matter if this
+ * is a C_PRIMARY or a C_SUBSTITUTE font
+ */
+ ret = parse_fontdata(oc, font_set, font_set->substitute,
+ font_set->substitute_num, name_list,
+ name_list_count, C_SUBSTITUTE,
+ font_data_return);
+ if (ret == -1) return -1;
+ if (ret == False) continue;
+
+ found_num++;
+ is_found = True;
+ }
+#ifdef TESTVERSION
+ else
+ return True;
+#endif
+ break;
+
+ case C_SUBSTITUTE:
+ case C_VMAP:
+ if(is_found == True)
+ return True;
+ break;
+
+ case C_VROTATE:
+ if(is_found == True) {
+ char *rotate_name;
+
+ if((rotate_name = get_rotate_fontname(font_data->xlfd_name))
+ != NULL) {
+ Xfree(font_data->xlfd_name);
+ font_data->xlfd_name = rotate_name;
+
+ return True;
+ }
+ Xfree(font_data->xlfd_name);
+ font_data->xlfd_name = NULL;
+ return False;
+ }
+ break;
+ }
+ }
+
+ if(class == C_PRIMARY && found_num >= 1)
+ return True;
+
+ return False;
+}
+
+
+static int
+parse_vw(
+ XOC oc,
+ FontSet font_set,
+ char **name_list,
+ int count)
+{
+ FontData vmap = font_set->vmap;
+ VRotate vrotate = font_set->vrotate;
+ int vmap_num = font_set->vmap_num;
+ int vrotate_num = font_set->vrotate_num;
+ int ret = 0, i = 0;
+
+ if(vmap_num > 0) {
+ if(parse_fontdata(oc, font_set, vmap, vmap_num, name_list,
+ count, C_VMAP,NULL) == -1)
+ return (-1);
+ }
+
+ if(vrotate_num > 0) {
+ ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num,
+ name_list, count, C_VROTATE, NULL);
+ if(ret == -1) {
+ return (-1);
+ } else if(ret == False) {
+ CodeRange code_range;
+ int num_cr;
+ int sub_num = font_set->substitute_num;
+
+ code_range = vrotate[0].code_range; /* ? */
+ num_cr = vrotate[0].num_cr; /* ? */
+ for(i = 0 ; i < vrotate_num ; i++) {
+ if(vrotate[i].xlfd_name)
+ Xfree(vrotate[i].xlfd_name);
+ }
+ Xfree(vrotate);
+
+ if(sub_num > 0) {
+ vrotate = font_set->vrotate = (VRotate)Xmalloc
+ (sizeof(VRotateRec) * sub_num);
+ if(font_set->vrotate == (VRotate)NULL)
+ return (-1);
+ memset(font_set->vrotate, 0x00, sizeof(VRotateRec) * sub_num);
+
+ for(i = 0 ; i < sub_num ; i++) {
+ vrotate[i].charset_name = font_set->substitute[i].name;
+ vrotate[i].side = font_set->substitute[i].side;
+ vrotate[i].code_range = code_range;
+ vrotate[i].num_cr = num_cr;
+ }
+ vrotate_num = font_set->vrotate_num = sub_num;
+ } else {
+ vrotate = font_set->vrotate = (VRotate)NULL;
+ }
+
+ ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num,
+ name_list, count, C_VROTATE, NULL);
+ if(ret == -1)
+ return (-1);
+ }
+ }
+
+ return True;
+}
+
+static int
+parse_fontname(
+ XOC oc)
+{
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+ FontSet font_set;
+ FontDataRec font_data_return;
+ char *base_name, **name_list;
+ int font_set_num = 0;
+ int found_num = 0;
+ int count = 0;
+ int ret;
+ int i;
+
+ name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
+ if (name_list == NULL)
+ return -1;
+
+ font_set = gen->font_set;
+ font_set_num = gen->font_set_num;
+
+ /* Loop through all of the CharSets defined in the Locale
+ * database for the current Locale.
+ */
+ for( ; font_set_num-- > 0 ; font_set++) {
+ if(font_set->font_name)
+ continue;
+
+ if(font_set->font_data_count > 0) {
+
+ /*
+ * If there are a non-zero number of FontSets defined
+ * for this CharSet.
+ * Try to find a font for this CharSet. If we find an
+ * acceptable font, we save the information for return
+ * to the client. If we do not find an acceptable font,
+ * a "missing_charset" will be reported to the client
+ * for this CharSet.
+ */
+ font_data_return. xlfd_name = NULL;
+ font_data_return.side = XlcUnknown;
+
+ ret = parse_fontdata(oc, font_set, font_set->font_data,
+ font_set->font_data_count,
+ name_list, count, C_PRIMARY,
+ &font_data_return);
+ if(ret == -1) {
+ goto err;
+ } else if(ret == True) {
+ /*
+ * We can't just loop thru fontset->font_data to
+ * find the first (ie. best) match: parse_fontdata
+ * will try a substitute font if no primary one could
+ * be matched. It returns the required information in
+ * font_data_return.
+ */
+ font_set->font_name = (char *)Xmalloc
+ (strlen(font_data_return.xlfd_name) + 1);
+ if(font_set->font_name == (char *) NULL)
+ goto err;
+ strcpy(font_set->font_name, font_data_return.xlfd_name);
+ font_set->side = font_data_return.side;
+
+ Xfree (font_data_return.xlfd_name);
+ font_data_return.xlfd_name = NULL;
+
+ if(parse_vw(oc, font_set, name_list, count) == -1)
+ goto err;
+ found_num++;
+ }
+
+ } else if(font_set->substitute_num > 0) {
+ /*
+ * If there are no FontSets defined for this
+ * CharSet. We can only find "substitute" fonts.
+ */
+ ret = parse_fontdata(oc, font_set, font_set->substitute,
+ font_set->substitute_num,
+ name_list, count, C_SUBSTITUTE, NULL);
+ if(ret == -1) {
+ goto err;
+ } else if(ret == True) {
+ for(i=0;i<font_set->substitute_num;i++){
+ if(font_set->substitute[i].xlfd_name != NULL){
+ break;
+ }
+ }
+ font_set->font_name = (char *)Xmalloc
+ (strlen(font_set->substitute[i].xlfd_name) + 1);
+ if(font_set->font_name == (char *) NULL)
+ goto err;
+ strcpy(font_set->font_name,font_set->substitute[i].xlfd_name);
+ font_set->side = font_set->substitute[i].side;
+ if(parse_vw(oc, font_set, name_list, count) == -1)
+ goto err;
+
+ found_num++;
+ }
+ }
+ }
+
+ base_name = (char *) Xmalloc(strlen(oc->core.base_name_list) + 1);
+ if (base_name == NULL)
+ goto err;
+
+ strcpy(base_name, oc->core.base_name_list);
+ oc->core.base_name_list = base_name;
+
+ XFreeStringList(name_list);
+
+ return found_num;
+
+err:
+ XFreeStringList(name_list);
+ /* Prevent this from being freed twice */
+ oc->core.base_name_list = NULL;
+
+ return -1;
+}
+
+/* For VW/UDC end*/
+
+static Bool
+set_missing_list(
+ XOC oc)
+{
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+ FontSet font_set;
+ char **charset_list, *charset_buf;
+ int count, length, font_set_num;
+ int result = 1;
+
+ font_set = gen->font_set;
+ font_set_num = gen->font_set_num;
+ count = length = 0;
+
+ for ( ; font_set_num-- > 0; font_set++) {
+ if (font_set->info || font_set->font) {
+ continue;
+ }
+
+ /* Change 1996.01.23 start */
+ if(font_set->font_data_count <= 0 ||
+ font_set->font_data == (FontData)NULL) {
+ if(font_set->substitute_num <= 0 ||
+ font_set->substitute == (FontData)NULL) {
+ if(font_set->charset_list != NULL){
+ length +=
+ strlen(font_set->charset_list[0]->encoding_name) + 1;
+ } else {
+ length += 1;
+ }
+ } else {
+ length += strlen(font_set->substitute->name) + 1;
+ }
+ } else {
+ length += strlen(font_set->font_data->name) + 1;
+ }
+ /* Change 1996.01.23 end */
+ count++;
+ }
+
+ if (count < 1) {
+ return True;
+ }
+
+ charset_list = (char **) Xmalloc(sizeof(char *) * count);
+ if (charset_list == NULL) {
+ return False;
+ }
+
+ charset_buf = (char *) Xmalloc(length);
+ if (charset_buf == NULL) {
+ Xfree(charset_list);
+ return False;
+ }
+
+ oc->core.missing_list.charset_list = charset_list;
+ oc->core.missing_list.charset_count = count;
+
+ font_set = gen->font_set;
+ font_set_num = gen->font_set_num;
+
+ for ( ; font_set_num-- > 0; font_set++) {
+ if (font_set->info || font_set->font) {
+ continue;
+ }
+
+ /* Change 1996.01.23 start */
+ if(font_set->font_data_count <= 0 ||
+ font_set->font_data == (FontData)NULL) {
+ if(font_set->substitute_num <= 0 ||
+ font_set->substitute == (FontData)NULL) {
+ if(font_set->charset_list != NULL){
+ strcpy(charset_buf,
+ font_set->charset_list[0]->encoding_name);
+ } else {
+ strcpy(charset_buf, "");
+ }
+ result = 0;
+ } else {
+ strcpy(charset_buf, font_set->substitute->name);
+ }
+ } else {
+ strcpy(charset_buf, font_set->font_data->name);
+ }
+ /* Change 1996.01.23 end */
+ *charset_list++ = charset_buf;
+ charset_buf += strlen(charset_buf) + 1;
+ }
+
+ if(result == 0) {
+ return(False);
+ }
+
+ return True;
+}
+
+static Bool
+create_fontset(
+ XOC oc)
+{
+ XOMGenericPart *gen = XOM_GENERIC(oc->core.om);
+ int found_num;
+
+ if (init_fontset(oc) == False)
+ return False;
+
+ found_num = parse_fontname(oc);
+ if (found_num <= 0) {
+ if (found_num == 0)
+ set_missing_list(oc);
+ return False;
+ }
+
+ if (gen->on_demand_loading == True) {
+ if (load_font_info(oc) == False)
+ return False;
+ } else {
+ if (load_font(oc) == False)
+ return False;
+ }
+
+ if (init_core_part(oc) == False)
+ return False;
+
+ if (set_missing_list(oc) == False)
+ return False;
+
+ return True;
+}
+
+/* For VW/UDC start */
+static void
+free_fontdataOC(
+ Display *dpy,
+ FontData font_data,
+ int font_data_count)
+{
+ for( ; font_data_count-- ; font_data++) {
+ if(font_data->xlfd_name){
+ Xfree(font_data->xlfd_name);
+ font_data->xlfd_name = NULL;
+ }
+ if(font_data->font){ /* ADD 1996.01.7 */
+ if(font_data->font->fid) /* Add 1996.01.23 */
+ XFreeFont(dpy,font_data->font); /* ADD 1996.01.7 */
+ else /* Add 1996.01.23 */
+ XFreeFontInfo(NULL, font_data->font, 1);/* Add 1996.01.23 */
+ font_data->font = NULL;
+ }
+/*
+ * font_data->name and font_data->scopes belong to the OM not OC.
+ * To save space this data is shared between OM and OC. We are
+ * not allowed to free it here.
+ * It has been moved to free_fontdataOM()
+ */
+/*
+ if(font_data->scopes){
+ Xfree(font_data->scopes);
+ font_data->scopes = NULL;
+ }
+ if(font_data->name){
+ Xfree(font_data->name);
+ font_data->name = NULL;
+ }
+*/
+ }
+}
+
+static void destroy_fontdata(
+ XOCGenericPart *gen,
+ Display *dpy)
+{
+ FontSet font_set = (FontSet) NULL;
+ int font_set_num = 0;
+
+ if (gen->font_set) {
+ font_set = gen->font_set;
+ font_set_num = gen->font_set_num;
+ for( ; font_set_num-- ; font_set++) {
+ if (font_set->font) {
+ if(font_set->font->fid)
+ XFreeFont(dpy,font_set->font);
+ else
+ XFreeFontInfo(NULL, font_set->font, 1);
+ font_set->font = NULL;
+ }
+ if(font_set->font_data) {
+ if (font_set->info)
+ XFreeFontInfo(NULL, font_set->info, 1);
+ free_fontdataOC(dpy,
+ font_set->font_data, font_set->font_data_count);
+ Xfree(font_set->font_data);
+ font_set->font_data = NULL;
+ }
+ if(font_set->substitute) {
+ free_fontdataOC(dpy,
+ font_set->substitute, font_set->substitute_num);
+ Xfree(font_set->substitute);
+ font_set->substitute = NULL;
+ }
+ if(font_set->vmap) {
+ free_fontdataOC(dpy,
+ font_set->vmap, font_set->vmap_num);
+ Xfree(font_set->vmap);
+ font_set->vmap = NULL;
+ }
+ if(font_set->vrotate) {
+ free_fontdataOC(dpy,
+ (FontData)font_set->vrotate,
+ font_set->vrotate_num);
+ Xfree(font_set->vrotate);
+ font_set->vrotate = NULL;
+ }
+ }
+ Xfree(gen->font_set);
+ gen->font_set = NULL;
+ }
+}
+/* For VW/UDC end */
+
+static void
+destroy_oc(
+ XOC oc)
+{
+ Display *dpy = oc->core.om->core.display;
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+
+ if (gen->mbs_to_cs)
+ _XlcCloseConverter(gen->mbs_to_cs);
+
+ if (gen->wcs_to_cs)
+ _XlcCloseConverter(gen->wcs_to_cs);
+
+ if (gen->utf8_to_cs)
+ _XlcCloseConverter(gen->utf8_to_cs);
+
+/* For VW/UDC start */ /* Change 1996.01.8 */
+ destroy_fontdata(gen,dpy);
+/*
+*/
+/* For VW/UDC end */
+
+ if (oc->core.base_name_list)
+ Xfree(oc->core.base_name_list);
+
+ if (oc->core.font_info.font_name_list)
+ XFreeStringList(oc->core.font_info.font_name_list);
+
+ if (oc->core.font_info.font_struct_list) {
+ Xfree(oc->core.font_info.font_struct_list);
+ }
+
+ if (oc->core.missing_list.charset_list)
+ XFreeStringList(oc->core.missing_list.charset_list);
+
+#ifdef notdef
+ if (oc->core.res_name)
+ Xfree(oc->core.res_name);
+ if (oc->core.res_class)
+ Xfree(oc->core.res_class);
+#endif
+
+ Xfree(oc);
+}
+
+static char *
+set_oc_values(
+ XOC oc,
+ XlcArgList args,
+ int num_args)
+{
+ XOCGenericPart *gen = XOC_GENERIC(oc);
+ FontSet font_set = gen->font_set;
+ char *ret;
+ int num = gen->font_set_num;
+
+ if (oc->core.resources == NULL)
+ return NULL;
+
+ ret = _XlcSetValues((XPointer) oc, oc->core.resources,
+ oc->core.num_resources, args, num_args, XlcSetMask);
+ if(ret != NULL){
+ return(ret);
+ } else {
+ for ( ; num-- > 0; font_set++) {
+ if (font_set->font_name == NULL)
+ continue;
+ if (font_set->vpart_initialize != 0)
+ continue;
+ if( oc->core.orientation == XOMOrientation_TTB_RTL ||
+ oc->core.orientation == XOMOrientation_TTB_LTR ){
+ load_fontdata(oc, font_set->vmap, font_set->vmap_num);
+ load_fontdata(oc, (FontData) font_set->vrotate,
+ font_set->vrotate_num);
+ font_set->vpart_initialize = 1;
+ }
+ }
+ return(NULL);
+ }
+}
+
+static char *
+get_oc_values(
+ XOC oc,
+ XlcArgList args,
+ int num_args)
+{
+ if (oc->core.resources == NULL)
+ return NULL;
+
+ return _XlcGetValues((XPointer) oc, oc->core.resources,
+ oc->core.num_resources, args, num_args, XlcGetMask);
+}
+
+static XOCMethodsRec oc_default_methods = {
+ destroy_oc,
+ set_oc_values,
+ get_oc_values,
+ _XmbDefaultTextEscapement,
+ _XmbDefaultTextExtents,
+ _XmbDefaultTextPerCharExtents,
+ _XmbDefaultDrawString,
+ _XmbDefaultDrawImageString,
+ _XwcDefaultTextEscapement,
+ _XwcDefaultTextExtents,
+ _XwcDefaultTextPerCharExtents,
+ _XwcDefaultDrawString,
+ _XwcDefaultDrawImageString,
+ _Xutf8DefaultTextEscapement,
+ _Xutf8DefaultTextExtents,
+ _Xutf8DefaultTextPerCharExtents,
+ _Xutf8DefaultDrawString,
+ _Xutf8DefaultDrawImageString
+};
+
+static XOCMethodsRec oc_generic_methods = {
+ destroy_oc,
+ set_oc_values,
+ get_oc_values,
+ _XmbGenericTextEscapement,
+ _XmbGenericTextExtents,
+ _XmbGenericTextPerCharExtents,
+ _XmbGenericDrawString,
+ _XmbGenericDrawImageString,
+ _XwcGenericTextEscapement,
+ _XwcGenericTextExtents,
+ _XwcGenericTextPerCharExtents,
+ _XwcGenericDrawString,
+ _XwcGenericDrawImageString,
+ _Xutf8GenericTextEscapement,
+ _Xutf8GenericTextExtents,
+ _Xutf8GenericTextPerCharExtents,
+ _Xutf8GenericDrawString,
+ _Xutf8GenericDrawImageString
+};
+
+typedef struct _XOCMethodsListRec {
+ const char *name;
+ XOCMethods methods;
+} XOCMethodsListRec, *XOCMethodsList;
+
+static XOCMethodsListRec oc_methods_list[] = {
+ { "default", &oc_default_methods },
+ { "generic", &oc_generic_methods }
+};
+
+static XlcResource oc_resources[] = {
+ { XNBaseFontName, NULLQUARK, sizeof(char *),
+ XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
+ { XNOMAutomatic, NULLQUARK, sizeof(Bool),
+ XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
+ { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
+ XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
+ { XNDefaultString, NULLQUARK, sizeof(char *),
+ XOffsetOf(XOCRec, core.default_string), XlcGetMask },
+ { XNOrientation, NULLQUARK, sizeof(XOrientation),
+ XOffsetOf(XOCRec, core.orientation), XlcDefaultMask | XlcSetMask | XlcGetMask },
+ { XNResourceName, NULLQUARK, sizeof(char *),
+ XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
+ { XNResourceClass, NULLQUARK, sizeof(char *),
+ XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
+ { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
+ XOffsetOf(XOCRec, core.font_info), XlcGetMask }
+};
+
+static XOC
+create_oc(
+ XOM om,
+ XlcArgList args,
+ int num_args)
+{
+ XOC oc;
+ XOMGenericPart *gen = XOM_GENERIC(om);
+ XOCMethodsList methods_list = oc_methods_list;
+ int count;
+
+ oc = (XOC) Xmalloc(sizeof(XOCGenericRec));
+ if (oc == NULL)
+ return (XOC) NULL;
+ bzero((char *) oc, sizeof(XOCGenericRec));
+
+ oc->core.om = om;
+
+ if (oc_resources[0].xrm_name == NULLQUARK)
+ _XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
+
+ if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
+ args, num_args, XlcCreateMask | XlcDefaultMask))
+ goto err;
+
+ if (oc->core.base_name_list == NULL)
+ goto err;
+
+ oc->core.resources = oc_resources;
+ oc->core.num_resources = XlcNumber(oc_resources);
+
+ if (create_fontset(oc) == False)
+ goto err;
+
+ oc->methods = &oc_generic_methods;
+
+ if (gen->object_name) {
+ count = XlcNumber(oc_methods_list);
+
+ for ( ; count-- > 0; methods_list++) {
+ if (!_XlcCompareISOLatin1(gen->object_name, methods_list->name)) {
+ oc->methods = methods_list->methods;
+ break;
+ }
+ }
+ }
+
+ return oc;
+
+err:
+ destroy_oc(oc);
+
+ return (XOC) NULL;
+}
+
+static void
+free_fontdataOM(
+ FontData font_data,
+ int font_data_count)
+{
+ for( ; font_data_count-- ; font_data++) {
+ if(font_data->name){
+ Xfree(font_data->name);
+ font_data->name = NULL;
+ }
+ if(font_data->scopes){
+ Xfree(font_data->scopes);
+ font_data->scopes = NULL;
+ }
+ }
+}
+
+static Status
+close_om(
+ XOM om)
+{
+ XOMGenericPart *gen = XOM_GENERIC(om);
+ OMData data;
+ int count;
+
+ if ((data = gen->data)) {
+ for (count = gen->data_num; count-- > 0; data++) {
+ if (data->charset_list){
+ Xfree(data->charset_list);
+ data->charset_list = NULL;
+ }
+ /* free font_data for om */
+ if (data->font_data) {
+ free_fontdataOM(data->font_data,data->font_data_count);
+ Xfree(data->font_data);
+ data->font_data = NULL;
+ }
+ /* free substitute for om */
+ if (data->substitute) {
+ free_fontdataOM(data->substitute,data->substitute_num);
+ Xfree(data->substitute);
+ data->substitute = NULL;
+ }
+ /* free vmap for om */
+ if (data->vmap) {
+ free_fontdataOM(data->vmap,data->vmap_num);
+ Xfree(data->vmap);
+ data->vmap = NULL;
+ }
+ /* free vrotate for om */
+ if (data->vrotate) {
+ Xfree(data->vrotate);
+ data->vrotate = NULL;
+ }
+ }
+ Xfree(gen->data);
+ gen->data = NULL;
+ }
+
+ if (gen->object_name){
+ Xfree(gen->object_name);
+ gen->object_name = NULL;
+ }
+
+ if (om->core.res_name){
+ Xfree(om->core.res_name);
+ om->core.res_name = NULL;
+ }
+ if (om->core.res_class){
+ Xfree(om->core.res_class);
+ om->core.res_class = NULL;
+ }
+ if (om->core.required_charset.charset_list &&
+ om->core.required_charset.charset_count > 0){
+ XFreeStringList(om->core.required_charset.charset_list);
+ om->core.required_charset.charset_list = NULL;
+ } else {
+ Xfree((char*)om->core.required_charset.charset_list);
+ om->core.required_charset.charset_list = NULL;
+ }
+ if (om->core.orientation_list.orientation){
+ Xfree(om->core.orientation_list.orientation);
+ om->core.orientation_list.orientation = NULL;
+ }
+
+ Xfree(om);
+
+ return 1;
+}
+
+static char *
+set_om_values(
+ XOM om,
+ XlcArgList args,
+ int num_args)
+{
+ if (om->core.resources == NULL)
+ return NULL;
+
+ return _XlcSetValues((XPointer) om, om->core.resources,
+ om->core.num_resources, args, num_args, XlcSetMask);
+}
+
+static char *
+get_om_values(
+ XOM om,
+ XlcArgList args,
+ int num_args)
+{
+ if (om->core.resources == NULL)
+ return NULL;
+
+ return _XlcGetValues((XPointer) om, om->core.resources,
+ om->core.num_resources, args, num_args, XlcGetMask);
+}
+
+static XOMMethodsRec methods = {
+ close_om,
+ set_om_values,
+ get_om_values,
+ create_oc
+};
+
+static XlcResource om_resources[] = {
+ { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
+ XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
+ { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
+ XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
+ { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
+ XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
+ { XNContextualDrawing, NULLQUARK, sizeof(Bool),
+ XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
+};
+
+static XOM
+create_om(
+ XLCd lcd,
+ Display *dpy,
+ XrmDatabase rdb,
+ _Xconst char *res_name,
+ _Xconst char *res_class)
+{
+ XOM om;
+
+ om = (XOM) Xmalloc(sizeof(XOMGenericRec));
+ if (om == NULL)
+ return (XOM) NULL;
+ bzero((char *) om, sizeof(XOMGenericRec));
+
+ om->methods = &methods;
+ om->core.lcd = lcd;
+ om->core.display = dpy;
+ om->core.rdb = rdb;
+ if (res_name) {
+ om->core.res_name = (char *) Xmalloc(strlen(res_name) + 1);
+ if (om->core.res_name == NULL)
+ goto err;
+ strcpy(om->core.res_name, res_name);
+ }
+ if (res_class) {
+ om->core.res_class = (char *) Xmalloc(strlen(res_class) + 1);
+ if (om->core.res_class == NULL)
+ goto err;
+ strcpy(om->core.res_class, res_class);
+ }
+
+ if (om_resources[0].xrm_name == NULLQUARK)
+ _XlcCompileResourceList(om_resources, XlcNumber(om_resources));
+
+ om->core.resources = om_resources;
+ om->core.num_resources = XlcNumber(om_resources);
+
+ return om;
+
+err:
+ close_om(om);
+
+ return (XOM) NULL;
+}
+
+static OMData
+add_data(
+ XOM om)
+{
+ XOMGenericPart *gen = XOM_GENERIC(om);
+ OMData new;
+ int num;
+
+ if ((num = gen->data_num))
+ new = (OMData) Xrealloc(gen->data, (num + 1) * sizeof(OMDataRec));
+ else
+ new = (OMData) Xmalloc(sizeof(OMDataRec));
+
+ if (new == NULL)
+ return NULL;
+
+ gen->data_num = num + 1;
+ gen->data = new;
+
+ new += num;
+ bzero((char *) new, sizeof(OMDataRec));
+
+ return new;
+}
+
+/* For VW/UDC */
+
+FontData
+read_EncodingInfo(
+ int count,
+ char **value)
+{
+ FontData font_data,ret;
+ char *buf, *bufptr,*scp;
+ int len;
+ font_data = (FontData) Xmalloc(sizeof(FontDataRec) * count);
+ if (font_data == NULL)
+ return NULL;
+ bzero((char *) font_data, sizeof(FontDataRec) * count);
+
+ ret = font_data;
+ for ( ; count-- > 0; font_data++) {
+/*
+ strcpy(buf, *value++);
+*/
+ buf = *value; value++;
+ if ((bufptr = strchr(buf, ':'))) {
+ len = (int)(bufptr - buf);
+ bufptr++ ;
+ } else
+ len = strlen(buf);
+ font_data->name = (char *) Xmalloc(len + 1);
+ if (font_data->name == NULL) {
+ Xfree(font_data);
+ return NULL;
+ }
+ strncpy(font_data->name, buf,len);
+ font_data->name[len] = 0;
+ if (bufptr && _XlcCompareISOLatin1(bufptr, "GL") == 0)
+ font_data->side = XlcGL;
+ else if (bufptr && _XlcCompareISOLatin1(bufptr, "GR") == 0)
+ font_data->side = XlcGR;
+ else
+ font_data->side = XlcGLGR;
+
+ if (bufptr && (scp = strchr(bufptr, '['))){
+ font_data->scopes = _XlcParse_scopemaps(scp,&(font_data->scopes_num));
+ }
+ }
+ return(ret);
+}
+
+static CodeRange read_vrotate(
+ int count,
+ char **value,
+ int *type,
+ int *vrotate_num)
+{
+ CodeRange range;
+ if(!strcmp(value[0],"all")){
+ *type = VROTATE_ALL ;
+ *vrotate_num = 0 ;
+ return (NULL);
+ } else if(*(value[0]) == '['){
+ *type = VROTATE_PART ;
+ range = (CodeRange) _XlcParse_scopemaps(value[0],vrotate_num);
+ return (range);
+ } else {
+ *type = VROTATE_NONE ;
+ *vrotate_num = 0 ;
+ return (NULL);
+ }
+}
+
+static void read_vw(
+ XLCd lcd,
+ OMData font_set,
+ int num)
+{
+ char **value, buf[BUFSIZ];
+ int count;
+
+ sprintf(buf, "fs%d.font.vertical_map", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if (count > 0){
+ _XlcDbg_printValue(buf,value,count);
+ font_set->vmap_num = count;
+ font_set->vmap = read_EncodingInfo(count,value);
+ }
+
+ sprintf(buf, "fs%d.font.vertical_rotate", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if (count > 0){
+ _XlcDbg_printValue(buf,value,count);
+ font_set->vrotate = read_vrotate(count,value,&(font_set->vrotate_type),
+ &(font_set->vrotate_num));
+ }
+}
+/* VW/UDC end */
+static Bool
+init_om(
+ XOM om)
+{
+ XLCd lcd = om->core.lcd;
+ XOMGenericPart *gen = XOM_GENERIC(om);
+ OMData data;
+ XlcCharSet *charset_list;
+ FontData font_data;
+ char **required_list;
+ XOrientation *orientation;
+ char **value, buf[BUFSIZ], *bufptr;
+ int count = 0, num = 0, length = 0;
+
+ _XlcGetResource(lcd, "XLC_FONTSET", "on_demand_loading", &value, &count);
+ if (count > 0 && _XlcCompareISOLatin1(*value, "True") == 0)
+ gen->on_demand_loading = True;
+
+ _XlcGetResource(lcd, "XLC_FONTSET", "object_name", &value, &count);
+ if (count > 0) {
+ gen->object_name = (char *) Xmalloc(strlen(*value) + 1);
+ if (gen->object_name == NULL)
+ return False;
+ strcpy(gen->object_name, *value);
+ }
+
+ for (num = 0; ; num++) {
+
+ sprintf(buf, "fs%d.charset.name", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+
+ if( count < 1){
+ sprintf(buf, "fs%d.charset", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if (count < 1)
+ break;
+ }
+
+ data = add_data(om);
+ if (data == NULL)
+ return False;
+
+ charset_list = (XlcCharSet *) Xmalloc(sizeof(XlcCharSet) * count);
+ if (charset_list == NULL)
+ return False;
+ data->charset_list = charset_list;
+ data->charset_count = count;
+
+ while (count-- > 0){
+ *charset_list++ = _XlcGetCharSet(*value++);
+ }
+ sprintf(buf, "fs%d.charset.udc_area", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if( count > 0){
+ UDCArea udc;
+ int i,flag = 0;
+ udc = (UDCArea)Xmalloc(count * sizeof(UDCAreaRec));
+ if (udc == NULL)
+ return False;
+ for(i=0;i<count;i++){
+ sscanf(value[i],"\\x%lx,\\x%lx", &(udc[i].start),
+ &(udc[i].end));
+ }
+ for(i=0;i<data->charset_count;i++){
+ if(data->charset_list[i]->udc_area == NULL){
+ data->charset_list[i]->udc_area = udc;
+ data->charset_list[i]->udc_area_num = count;
+ flag = 1;
+ }
+ }
+ if(flag == 0){
+ Xfree(udc);
+ }
+ }
+
+ sprintf(buf, "fs%d.font.primary", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if (count < 1){
+ sprintf(buf, "fs%d.font", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if (count < 1)
+ return False;
+ }
+
+ font_data = read_EncodingInfo(count,value);
+ if (font_data == NULL)
+ return False;
+
+ data->font_data = font_data;
+ data->font_data_count = count;
+
+ sprintf(buf, "fs%d.font.substitute", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if (count > 0){
+ font_data = read_EncodingInfo(count,value);
+ if (font_data == NULL)
+ return False;
+ data->substitute = font_data;
+ data->substitute_num = count;
+ } else {
+ sprintf(buf, "fs%d.font", num);
+ _XlcGetResource(lcd, "XLC_FONTSET", buf, &value, &count);
+ if (count < 1) {
+ data->substitute = NULL;
+ data->substitute_num = 0;
+ } else {
+ font_data = read_EncodingInfo(count,value);
+ data->substitute = font_data;
+ data->substitute_num = count;
+ }
+ }
+ read_vw(lcd,data,num);
+ length += strlen(data->font_data->name) + 1;
+ }
+
+ /* required charset list */
+ required_list = (char **) Xmalloc(sizeof(char *) * gen->data_num);
+ if (required_list == NULL)
+ return False;
+
+ om->core.required_charset.charset_list = required_list;
+ om->core.required_charset.charset_count = gen->data_num;
+
+ count = gen->data_num;
+ data = gen->data;
+
+ if (count > 0) {
+ bufptr = (char *) Xmalloc(length);
+ if (bufptr == NULL) {
+ Xfree(required_list);
+ return False;
+ }
+
+ for ( ; count-- > 0; data++) {
+ strcpy(bufptr, data->font_data->name);
+ *required_list++ = bufptr;
+ bufptr += strlen(bufptr) + 1;
+ }
+ }
+
+ /* orientation list */
+ orientation = (XOrientation *) Xmalloc(sizeof(XOrientation) * 2);
+ if (orientation == NULL)
+ return False;
+
+ orientation[0] = XOMOrientation_LTR_TTB;
+ orientation[1] = XOMOrientation_TTB_RTL;
+ om->core.orientation_list.orientation = orientation;
+ om->core.orientation_list.num_orientation = 2;
+
+ /* directional dependent drawing */
+ om->core.directional_dependent = False;
+
+ /* contexual drawing */
+ om->core.contextual_drawing = False;
+
+ /* context dependent */
+ om->core.context_dependent = False;
+
+ return True;
+}
+
+XOM
+_XomGenericOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
+ _Xconst char *res_name, _Xconst char *res_class)
+{
+ XOM om;
+
+ om = create_om(lcd, dpy, rdb, res_name, res_class);
+ if (om == NULL)
+ return (XOM) NULL;
+
+ if (init_om(om) == False)
+ goto err;
+
+ return om;
+
+err:
+ close_om(om);
+
+ return (XOM) NULL;
+}
+
+Bool
+_XInitOM(
+ XLCd lcd)
+{
+ lcd->methods->open_om = _XomGenericOpenOM;
+
+ return True;
+}
diff --git a/libX11/src/FSWrap.c b/libX11/src/FSWrap.c index a94709365..c9c3867c1 100644 --- a/libX11/src/FSWrap.c +++ b/libX11/src/FSWrap.c @@ -1,263 +1,263 @@ - -/* - * Copyright 1991 by the Open Software Foundation - * Copyright 1993 by the TOSHIBA Corp. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name Open Software Foundation - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Open Software - * Foundation makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * OPEN SOFTWARE FOUNDATION DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL OPEN SOFTWARE FOUNDATIONN BE - * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * M. Collins OSF - * - * Katsuhisa Yano TOSHIBA Corp. - */ - -/* - -Copyright 1991, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - -*/ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "Xlibint.h" -#include "Xlcint.h" -#include <ctype.h> -#include <X11/Xos.h> - - -#define XMAXLIST 256 - -char ** -_XParseBaseFontNameList( - char *str, - int *num) -{ - char *plist[XMAXLIST]; - char **list; - char *ptr, *psave; - - *num = 0; - if (!str || !*str) { - return (char **)NULL; - } - while (*str && isspace(*str)) - str++; - if (!*str) - return (char **)NULL; - - if (!(ptr = Xmalloc((unsigned)strlen(str) + 1))) { - return (char **)NULL; - } - strcpy(ptr, str); - - psave = ptr; - /* somebody who specifies more than XMAXLIST basefontnames will lose */ - while (*num < (sizeof plist / sizeof plist[0])) { - char *back; - - plist[*num] = ptr; - if ((ptr = strchr(ptr, ','))) { - back = ptr; - } else { - back = plist[*num] + strlen(plist[*num]); - } - while (isspace(*(back - 1))) - back--; - *back = '\0'; - (*num)++; - if (!ptr) - break; - ptr++; - while (*ptr && isspace(*ptr)) - ptr++; - if (!*ptr) - break; - } - if (!(list = (char **) Xmalloc((unsigned)sizeof(char *) * (*num + 1)))) { - Xfree(psave); - return (char **)NULL; - } - memcpy((char *)list, (char *)plist, sizeof(char *) * (*num)); - *(list + *num) = NULL; - - return list; -} - -static char ** -copy_string_list( - char **string_list, - int list_count) -{ - char **string_list_ret, **list_src, **list_dst, *dst; - int length, count; - - if (string_list == NULL) - return (char **) NULL; - - string_list_ret = (char **) Xmalloc(sizeof(char *) * list_count); - if (string_list_ret == NULL) - return (char **) NULL; - - list_src = string_list; - count = list_count; - for (length = 0; count-- > 0; list_src++) - length += strlen(*list_src) + 1; - - dst = (char *) Xmalloc(length); - if (dst == NULL) { - Xfree(string_list_ret); - return (char **) NULL; - } - - list_src = string_list; - count = list_count; - list_dst = string_list_ret; - for ( ; count-- > 0; list_src++) { - strcpy(dst, *list_src); - *list_dst++ = dst; - dst += strlen(dst) + 1; - } - - return string_list_ret; -} - -XFontSet -XCreateFontSet ( - Display *dpy, - _Xconst char *base_font_name_list, - char ***missing_charset_list, - int *missing_charset_count, - char **def_string) -{ - XOM om; - XOC oc; - XOMCharSetList *list; - - *missing_charset_list = NULL; - *missing_charset_count = 0; - - om = XOpenOM(dpy, NULL, NULL, NULL); - if (om == NULL) - return (XFontSet) NULL; - - if ((oc = XCreateOC(om, XNBaseFontName, base_font_name_list, NULL))) { - list = &oc->core.missing_list; - oc->core.om_automatic = True; - } else - list = &om->core.required_charset; - - *missing_charset_list = copy_string_list(list->charset_list, - list->charset_count); - *missing_charset_count = list->charset_count; - - if (list->charset_list && *missing_charset_list == NULL) - oc = NULL; - - if (oc && def_string) { - *def_string = oc->core.default_string; - if (!*def_string) - *def_string = ""; - } - - if (oc == NULL) - XCloseOM(om); - - return (XFontSet) oc; -} - -int -XFontsOfFontSet( - XFontSet font_set, - XFontStruct ***font_struct_list, - char ***font_name_list) -{ - *font_name_list = font_set->core.font_info.font_name_list; - *font_struct_list = font_set->core.font_info.font_struct_list; - return font_set->core.font_info.num_font; -} - -char * -XBaseFontNameListOfFontSet(XFontSet font_set) -{ - return font_set->core.base_name_list; -} - -char * -XLocaleOfFontSet(XFontSet font_set) -{ - return font_set->core.om->core.lcd->core->name; -} - -Bool -XContextDependentDrawing(XFontSet font_set) -{ - return font_set->core.om->core.context_dependent; -} - -Bool -XDirectionalDependentDrawing(XFontSet font_set) -{ - return font_set->core.om->core.directional_dependent; -} - -Bool -XContextualDrawing(XFontSet font_set) -{ - return font_set->core.om->core.contextual_drawing; -} - -XFontSetExtents * -XExtentsOfFontSet(XFontSet font_set) -{ - if (!font_set) - return NULL; - return &font_set->core.font_set_extents; -} - -void -XFreeFontSet( - Display *dpy, - XFontSet font_set) -{ - XCloseOM(font_set->core.om); -} +
+/*
+ * Copyright 1991 by the Open Software Foundation
+ * Copyright 1993 by the TOSHIBA Corp.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Open Software Foundation
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Open Software
+ * Foundation makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * OPEN SOFTWARE FOUNDATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL OPEN SOFTWARE FOUNDATIONN BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * M. Collins OSF
+ *
+ * Katsuhisa Yano TOSHIBA Corp.
+ */
+
+/*
+
+Copyright 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "Xlibint.h"
+#include "Xlcint.h"
+#include <ctype.h>
+#include <X11/Xos.h>
+
+
+#define XMAXLIST 256
+
+char **
+_XParseBaseFontNameList(
+ char *str,
+ int *num)
+{
+ char *plist[XMAXLIST];
+ char **list;
+ char *ptr, *psave;
+
+ *num = 0;
+ if (!str || !*str) {
+ return (char **)NULL;
+ }
+ while (*str && isspace(*str))
+ str++;
+ if (!*str)
+ return (char **)NULL;
+
+ if (!(ptr = Xmalloc((unsigned)strlen(str) + 1))) {
+ return (char **)NULL;
+ }
+ strcpy(ptr, str);
+
+ psave = ptr;
+ /* somebody who specifies more than XMAXLIST basefontnames will lose */
+ while (*num < (sizeof plist / sizeof plist[0])) {
+ char *back;
+
+ plist[*num] = ptr;
+ if ((ptr = strchr(ptr, ','))) {
+ back = ptr;
+ } else {
+ back = plist[*num] + strlen(plist[*num]);
+ }
+ while (isspace(*(back - 1)))
+ back--;
+ *back = '\0';
+ (*num)++;
+ if (!ptr)
+ break;
+ ptr++;
+ while (*ptr && isspace(*ptr))
+ ptr++;
+ if (!*ptr)
+ break;
+ }
+ if (!(list = (char **) Xmalloc((unsigned)sizeof(char *) * (*num + 1)))) {
+ Xfree(psave);
+ return (char **)NULL;
+ }
+ memcpy((char *)list, (char *)plist, sizeof(char *) * (*num));
+ *(list + *num) = NULL;
+
+ return list;
+}
+
+static char **
+copy_string_list(
+ char **string_list,
+ int list_count)
+{
+ char **string_list_ret, **list_src, **list_dst, *dst;
+ int length, count;
+
+ if (string_list == NULL || list_count == 0)
+ return (char **) NULL;
+
+ string_list_ret = (char **) Xmalloc(sizeof(char *) * list_count);
+ if (string_list_ret == NULL)
+ return (char **) NULL;
+
+ list_src = string_list;
+ count = list_count;
+ for (length = 0; count-- > 0; list_src++)
+ length += strlen(*list_src) + 1;
+
+ dst = (char *) Xmalloc(length);
+ if (dst == NULL) {
+ Xfree(string_list_ret);
+ return (char **) NULL;
+ }
+
+ list_src = string_list;
+ count = list_count;
+ list_dst = string_list_ret;
+ for ( ; count-- > 0; list_src++) {
+ strcpy(dst, *list_src);
+ *list_dst++ = dst;
+ dst += strlen(dst) + 1;
+ }
+
+ return string_list_ret;
+}
+
+XFontSet
+XCreateFontSet (
+ Display *dpy,
+ _Xconst char *base_font_name_list,
+ char ***missing_charset_list,
+ int *missing_charset_count,
+ char **def_string)
+{
+ XOM om;
+ XOC oc;
+ XOMCharSetList *list;
+
+ *missing_charset_list = NULL;
+ *missing_charset_count = 0;
+
+ om = XOpenOM(dpy, NULL, NULL, NULL);
+ if (om == NULL)
+ return (XFontSet) NULL;
+
+ if ((oc = XCreateOC(om, XNBaseFontName, base_font_name_list, NULL))) {
+ list = &oc->core.missing_list;
+ oc->core.om_automatic = True;
+ } else
+ list = &om->core.required_charset;
+
+ *missing_charset_list = copy_string_list(list->charset_list,
+ list->charset_count);
+ *missing_charset_count = list->charset_count;
+
+ if (list->charset_list && *missing_charset_list == NULL)
+ oc = NULL;
+
+ if (oc && def_string) {
+ *def_string = oc->core.default_string;
+ if (!*def_string)
+ *def_string = "";
+ }
+
+ if (oc == NULL)
+ XCloseOM(om);
+
+ return (XFontSet) oc;
+}
+
+int
+XFontsOfFontSet(
+ XFontSet font_set,
+ XFontStruct ***font_struct_list,
+ char ***font_name_list)
+{
+ *font_name_list = font_set->core.font_info.font_name_list;
+ *font_struct_list = font_set->core.font_info.font_struct_list;
+ return font_set->core.font_info.num_font;
+}
+
+char *
+XBaseFontNameListOfFontSet(XFontSet font_set)
+{
+ return font_set->core.base_name_list;
+}
+
+char *
+XLocaleOfFontSet(XFontSet font_set)
+{
+ return font_set->core.om->core.lcd->core->name;
+}
+
+Bool
+XContextDependentDrawing(XFontSet font_set)
+{
+ return font_set->core.om->core.context_dependent;
+}
+
+Bool
+XDirectionalDependentDrawing(XFontSet font_set)
+{
+ return font_set->core.om->core.directional_dependent;
+}
+
+Bool
+XContextualDrawing(XFontSet font_set)
+{
+ return font_set->core.om->core.contextual_drawing;
+}
+
+XFontSetExtents *
+XExtentsOfFontSet(XFontSet font_set)
+{
+ if (!font_set)
+ return NULL;
+ return &font_set->core.font_set_extents;
+}
+
+void
+XFreeFontSet(
+ Display *dpy,
+ XFontSet font_set)
+{
+ XCloseOM(font_set->core.om);
+}
diff --git a/libX11/src/RdBitF.c b/libX11/src/RdBitF.c index e9a509c55..6b920c609 100644 --- a/libX11/src/RdBitF.c +++ b/libX11/src/RdBitF.c @@ -1,257 +1,262 @@ -/* - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - -*/ - -/* - * Code to read bitmaps from disk files. Interprets - * data from X10 and X11 bitmap files and creates - * Pixmap representations of files. Returns Pixmap - * ID and specifics about image. - * - * Modified for speedup by Jim Becker, changed image - * data parsing logic (removed some fscanf()s). - * Aug 5, 1988 - * - * Note that this file and ../Xmu/RdBitF.c look very similar.... Keep them - * that way (but don't use common source code so that people can have one - * without the other). - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "Xlibint.h" -#include <X11/Xos.h> -#include "Xutil.h" -#include <stdio.h> -#include <ctype.h> - - -#define MAX_SIZE 255 - -/* shared data for the image read/parse logic */ -static const signed char hexTable[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0 - , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0 - , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0 - , 0, 10, 11, 12, 13, 14, 15, 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, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0 - , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 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, 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, 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, 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, 0, 0 -}; - -/* - * read next hex value in the input stream, return -1 if EOF - */ -static int -NextInt ( - FILE *fstream) -{ - int ch; - int value = 0; - int gotone = 0; - int done = 0; - - /* loop, accumulate hex value until find delimiter */ - /* skip any initial delimiters found in read stream */ - - while (!done) { - ch = getc(fstream); - if (ch == EOF) { - value = -1; - done++; - } else { - /* trim high bits, check type and accumulate */ - ch &= 0xff; - if (isascii(ch) && isxdigit(ch)) { - value = (value << 4) + hexTable[ch]; - gotone++; - } else if ((hexTable[ch]) < 0 && gotone) - done++; - } - } - return value; -} - -int -XReadBitmapFileData ( - _Xconst char *filename, - unsigned int *width, /* RETURNED */ - unsigned int *height, /* RETURNED */ - unsigned char **data, /* RETURNED */ - int *x_hot, /* RETURNED */ - int *y_hot) /* RETURNED */ -{ - FILE *fstream; /* handle on file */ - unsigned char *bits = NULL; /* working variable */ - char line[MAX_SIZE]; /* input line from file */ - int size; /* number of bytes of data */ - char name_and_type[MAX_SIZE]; /* an input line */ - char *type; /* for parsing */ - int value; /* from an input line */ - int version10p; /* boolean, old format */ - int padding; /* to handle alignment */ - int bytes_per_line; /* per scanline of data */ - unsigned int ww = 0; /* width */ - unsigned int hh = 0; /* height */ - int hx = -1; /* x hotspot */ - int hy = -1; /* y hotspot */ - -#ifdef __UNIXOS2__ - filename = __XOS2RedirRoot(filename); -#endif - if (!(fstream = fopen(filename, "r"))) - return BitmapOpenFailed; - - /* error cleanup and return macro */ -#define RETURN(code) \ -{ if (bits) Xfree ((char *)bits); fclose (fstream); return code; } - - while (fgets(line, MAX_SIZE, fstream)) { - if (strlen(line) == MAX_SIZE-1) - RETURN (BitmapFileInvalid); - if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) { - if (!(type = strrchr(name_and_type, '_'))) - type = name_and_type; - else - type++; - - if (!strcmp("width", type)) - ww = (unsigned int) value; - if (!strcmp("height", type)) - hh = (unsigned int) value; - if (!strcmp("hot", type)) { - if (type-- == name_and_type || type-- == name_and_type) - continue; - if (!strcmp("x_hot", type)) - hx = value; - if (!strcmp("y_hot", type)) - hy = value; - } - continue; - } - - if (sscanf(line, "static short %s = {", name_and_type) == 1) - version10p = 1; - else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1) - version10p = 0; - else if (sscanf(line, "static char %s = {", name_and_type) == 1) - version10p = 0; - else - continue; - - if (!(type = strrchr(name_and_type, '_'))) - type = name_and_type; - else - type++; - - if (strcmp("bits[]", type)) - continue; - - if (!ww || !hh) - RETURN (BitmapFileInvalid); - - if ((ww % 16) && ((ww % 16) < 9) && version10p) - padding = 1; - else - padding = 0; - - bytes_per_line = (ww+7)/8 + padding; - - size = bytes_per_line * hh; - bits = (unsigned char *) Xmalloc ((unsigned int) size); - if (!bits) - RETURN (BitmapNoMemory); - - if (version10p) { - unsigned char *ptr; - int bytes; - - for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) { - if ((value = NextInt(fstream)) < 0) - RETURN (BitmapFileInvalid); - *(ptr++) = value; - if (!padding || ((bytes+2) % bytes_per_line)) - *(ptr++) = value >> 8; - } - } else { - unsigned char *ptr; - int bytes; - - for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) { - if ((value = NextInt(fstream)) < 0) - RETURN (BitmapFileInvalid); - *ptr=value; - } - } - } /* end while */ - - fclose(fstream); - if (!bits) - return (BitmapFileInvalid); - - *data = bits; - *width = ww; - *height = hh; - if (x_hot) *x_hot = hx; - if (y_hot) *y_hot = hy; - - return (BitmapSuccess); -} - -int -XReadBitmapFile ( - Display *display, - Drawable d, - _Xconst char *filename, - unsigned int *width, /* RETURNED */ - unsigned int *height, /* RETURNED */ - Pixmap *pixmap, /* RETURNED */ - int *x_hot, /* RETURNED */ - int *y_hot) /* RETURNED */ -{ - unsigned char *data; - int res; - - res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot); - if (res != BitmapSuccess) - return res; - *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height); - Xfree((char *)data); - if (*pixmap == None) - return (BitmapNoMemory); - return (BitmapSuccess); -} +/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * Code to read bitmaps from disk files. Interprets
+ * data from X10 and X11 bitmap files and creates
+ * Pixmap representations of files. Returns Pixmap
+ * ID and specifics about image.
+ *
+ * Modified for speedup by Jim Becker, changed image
+ * data parsing logic (removed some fscanf()s).
+ * Aug 5, 1988
+ *
+ * Note that this file and ../Xmu/RdBitF.c look very similar.... Keep them
+ * that way (but don't use common source code so that people can have one
+ * without the other).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "Xlibint.h"
+#include <X11/Xos.h>
+#include "Xutil.h"
+#include <stdio.h>
+#include <ctype.h>
+
+
+#define MAX_SIZE 255
+
+/* shared data for the image read/parse logic */
+static const signed char hexTable[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0
+ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0
+ , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0
+ , 0, 10, 11, 12, 13, 14, 15, 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, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 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, 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, 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, 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, 0, 0
+};
+
+/*
+ * read next hex value in the input stream, return -1 if EOF
+ */
+static int
+NextInt (
+ FILE *fstream)
+{
+ int ch;
+ int value = 0;
+ int gotone = 0;
+ int done = 0;
+
+ /* loop, accumulate hex value until find delimiter */
+ /* skip any initial delimiters found in read stream */
+
+ while (!done) {
+ ch = getc(fstream);
+ if (ch == EOF) {
+ value = -1;
+ done++;
+ } else {
+ /* trim high bits, check type and accumulate */
+ ch &= 0xff;
+ if (isascii(ch) && isxdigit(ch)) {
+ value = (value << 4) + hexTable[ch];
+ gotone++;
+ } else if ((hexTable[ch]) < 0 && gotone)
+ done++;
+ }
+ }
+ return value;
+}
+
+int
+XReadBitmapFileData (
+ _Xconst char *filename,
+ unsigned int *width, /* RETURNED */
+ unsigned int *height, /* RETURNED */
+ unsigned char **data, /* RETURNED */
+ int *x_hot, /* RETURNED */
+ int *y_hot) /* RETURNED */
+{
+ FILE *fstream; /* handle on file */
+ unsigned char *bits = NULL; /* working variable */
+ char line[MAX_SIZE]; /* input line from file */
+ int size; /* number of bytes of data */
+ char name_and_type[MAX_SIZE]; /* an input line */
+ char *type; /* for parsing */
+ int value; /* from an input line */
+ int version10p; /* boolean, old format */
+ int padding; /* to handle alignment */
+ int bytes_per_line; /* per scanline of data */
+ unsigned int ww = 0; /* width */
+ unsigned int hh = 0; /* height */
+ int hx = -1; /* x hotspot */
+ int hy = -1; /* y hotspot */
+
+#ifdef __UNIXOS2__
+ filename = __XOS2RedirRoot(filename);
+#endif
+ if (!(fstream = fopen(filename, "r")))
+ return BitmapOpenFailed;
+
+ /* error cleanup and return macro */
+#define RETURN(code) \
+{ if (bits) Xfree ((char *)bits); fclose (fstream); return code; }
+
+ while (fgets(line, MAX_SIZE, fstream)) {
+ if (strlen(line) == MAX_SIZE-1)
+ RETURN (BitmapFileInvalid);
+ if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
+ if (!(type = strrchr(name_and_type, '_')))
+ type = name_and_type;
+ else
+ type++;
+
+ if (!strcmp("width", type))
+ ww = (unsigned int) value;
+ if (!strcmp("height", type))
+ hh = (unsigned int) value;
+ if (!strcmp("hot", type)) {
+ if (type-- == name_and_type || type-- == name_and_type)
+ continue;
+ if (!strcmp("x_hot", type))
+ hx = value;
+ if (!strcmp("y_hot", type))
+ hy = value;
+ }
+ continue;
+ }
+
+ if (sscanf(line, "static short %s = {", name_and_type) == 1)
+ version10p = 1;
+ else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
+ version10p = 0;
+ else if (sscanf(line, "static char %s = {", name_and_type) == 1)
+ version10p = 0;
+ else
+ continue;
+
+ if (!(type = strrchr(name_and_type, '_')))
+ type = name_and_type;
+ else
+ type++;
+
+ if (strcmp("bits[]", type))
+ continue;
+
+ if (!ww || !hh)
+ RETURN (BitmapFileInvalid);
+
+ if ((ww % 16) && ((ww % 16) < 9) && version10p)
+ padding = 1;
+ else
+ padding = 0;
+
+ bytes_per_line = (ww+7)/8 + padding;
+
+ size = bytes_per_line * hh;
+ bits = (unsigned char *) Xmalloc ((unsigned int) size);
+ if (!bits)
+ RETURN (BitmapNoMemory);
+
+ if (version10p) {
+ unsigned char *ptr;
+ int bytes;
+
+ for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
+ if ((value = NextInt(fstream)) < 0)
+ RETURN (BitmapFileInvalid);
+ *(ptr++) = value;
+ if (!padding || ((bytes+2) % bytes_per_line))
+ *(ptr++) = value >> 8;
+ }
+ } else {
+ unsigned char *ptr;
+ int bytes;
+
+ for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
+ if ((value = NextInt(fstream)) < 0)
+ RETURN (BitmapFileInvalid);
+ *ptr=value;
+ }
+ }
+
+ /* If we got to this point, we read a full bitmap file. Break so we don't
+ * start reading another one from the same file and leak the memory
+ * allocated for the previous one. */
+ break;
+ } /* end while */
+
+ fclose(fstream);
+ if (!bits)
+ return (BitmapFileInvalid);
+
+ *data = bits;
+ *width = ww;
+ *height = hh;
+ if (x_hot) *x_hot = hx;
+ if (y_hot) *y_hot = hy;
+
+ return (BitmapSuccess);
+}
+
+int
+XReadBitmapFile (
+ Display *display,
+ Drawable d,
+ _Xconst char *filename,
+ unsigned int *width, /* RETURNED */
+ unsigned int *height, /* RETURNED */
+ Pixmap *pixmap, /* RETURNED */
+ int *x_hot, /* RETURNED */
+ int *y_hot) /* RETURNED */
+{
+ unsigned char *data;
+ int res;
+
+ res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot);
+ if (res != BitmapSuccess)
+ return res;
+ *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height);
+ Xfree((char *)data);
+ if (*pixmap == None)
+ return (BitmapNoMemory);
+ return (BitmapSuccess);
+}
diff --git a/libX11/src/xcms/LRGB.c b/libX11/src/xcms/LRGB.c index 8f1394b7f..2dc5a20cf 100644 --- a/libX11/src/xcms/LRGB.c +++ b/libX11/src/xcms/LRGB.c @@ -653,7 +653,7 @@ LINEAR_RGB_InitSCCData( */
if (!(pScreenData = (LINEAR_RGB_SCCData *)
Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
- return(XcmsFailure);
+ goto Free_property_return;
}
/* copy matrices */
memcpy((char *)pScreenData, (char *)pScreenDefaultData,
@@ -663,7 +663,7 @@ LINEAR_RGB_InitSCCData( if (!(pNewMap = (XcmsIntensityMap *)
Xcalloc (1, sizeof(XcmsIntensityMap)))) {
Xfree((char *)pScreenData);
- return(XcmsFailure);
+ goto Free_property_return;
}
pNewMap->visualID = visualID;
pNewMap->screenData = (XPointer)pScreenData;
@@ -802,7 +802,7 @@ FreeBlueTbl: Xfree((char *)pScreenData->pBlueTbl);
FreeGreenTblElements:
- Xfree((char *)pScreenData->pBlueTbl->pBase);
+ Xfree((char *)pScreenData->pGreenTbl->pBase);
FreeGreenTbl:
Xfree((char *)pScreenData->pGreenTbl);
@@ -817,7 +817,7 @@ Free_property_return: Xfree ((char *)property_return);
FreeSCCData:
- Xfree((char *)pScreenData);
+ Xfree((char *)pScreenDefaultData);
pPerScrnInfo->state = XcmsInitNone;
return(XcmsFailure);
}
diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 5c6ac445c..c0541c3f9 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -319,6 +319,21 @@ else esac
fi
+dnl
+dnl potentially-infringing-but-nobody-knows-for-sure stuff
+dnl
+AC_ARG_ENABLE([texture-float],
+ [AS_HELP_STRING([--enable-texture-float],
+ [enable floating-point textures and renderbuffers @<:@default=disabled@:>@])],
+ [enable_texture_float="$enableval"],
+ [enable_texture_float=no]
+)
+if test "x$enable_texture_float" = xyes; then
+ AC_MSG_WARN([Floating-point textures enabled.])
+ AC_MSG_WARN([Please consult docs/patents.txt with your lawyer before building Mesa.])
+ DEFINES="$DEFINES -DTEXTURE_FLOAT_ENABLED"
+fi
+
GL_LIB_NAME='lib$(GL_LIB).'${LIB_EXTENSION}
GLU_LIB_NAME='lib$(GLU_LIB).'${LIB_EXTENSION}
GLUT_LIB_NAME='lib$(GLUT_LIB).'${LIB_EXTENSION}
diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index b11f6aa5f..9792a188b 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -12,11 +12,11 @@ Feature Status GL 3.0:
-GLSL changes (GL_EXT_gpu_shader4, etc) not started
+GLSL 1.30 (GL_EXT_gpu_shader4, etc.) not started
Conditional rendering (GL_NV_conditional_render) DONE (swrast & softpipe)
Map buffer subranges (GL_ARB_map_buffer_range) DONE
Clamping controls (GL_ARB_color_buffer_float) DONE
-Float textures, renderbuffers (GL_ARB_texture_float) BRANCH ~mareko/mesa floating2
+Float textures, renderbuffers (GL_ARB_texture_float) DONE (gallium r300)
GL_EXT_packed_float not started
GL_EXT_texture_shared_exponent not started
Float depth buffers (GL_ARB_depth_buffer_float) not started
@@ -45,7 +45,7 @@ Depth format cube textures 0% done GL 3.1:
-GLSL 1.30 and 1.40 not started
+GLSL 1.40 not started
Instanced drawing (GL_ARB_draw_instanced) DONE (gallium, swrast)
Buffer copying (GL_ARB_copy_buffer) DONE
Primitive restart (GL_NV_primitive_restart) DONE (gallium)
diff --git a/mesalib/docs/relnotes-7.11.html b/mesalib/docs/relnotes-7.11.html index 4ac32e7e8..719073dbf 100644 --- a/mesalib/docs/relnotes-7.11.html +++ b/mesalib/docs/relnotes-7.11.html @@ -36,12 +36,22 @@ tbd <h2>New features</h2>
<ul>
+<li>GL_ARB_color_buffer_float (gallium drivers)
+<li>GL_ARB_draw_buffers_blend (gallium)
<li>GL_ARB_draw_instanced extension (gallium drivers, swrast)
<li>GL_ARB_instanced_arrays extension (gallium drivers)
-<li>GL_ARB_texture_compression_rgtc (gallium r600, swrast)
-<li>GL_ARB_draw_buffers_blend (gallium)
-<li>GL_EXT_texture_sRGB_decode (gallium drivers, swrast, i965)
+<li>GL_ARB_occlusion_query2 (gallium drivers, swrast)
<li>GL_ARB_sampler_objects (gallium drivers)
+<li>GL_ARB_texture_compression_rgtc (gallium drivers, swrast)
+<li>GL_ARB_texture_float (gallium)
+<li>GL_EXT_texture_compression_latc (gallium drivers, swrast)
+<li>GL_EXT_texture_compression_rgtc (gallium drivers, swrast)
+<li>GL_EXT_texture_sRGB_decode (gallium drivers, swrast, i965)
+<li>GL_EXT_texture_snorm (gallium drivers)
+<li>GL_ATI_draw_buffers (all drivers)
+<li>GL_ATI_texture_compression_3dc (gallium drivers, swrast)
+<li>GL_ATI_texture_float (gallium)
+<li>GL_NV_texture_barrier (gallium drivers)
</ul>
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index 1f6e67fa0..c8dc34a1c 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -1,1896 +1,1896 @@ -%{ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <inttypes.h> - -#include "glcpp.h" -#include "main/core.h" /* for struct gl_extensions */ -#include "main/mtypes.h" /* for gl_api enum */ - -static void -yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error); - -static void -_define_object_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *macro, - token_list_t *replacements); - -static void -_define_function_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *macro, - string_list_t *parameters, - token_list_t *replacements); - -static string_list_t * -_string_list_create (void *ctx); - -static void -_string_list_append_item (string_list_t *list, const char *str); - -static int -_string_list_contains (string_list_t *list, const char *member, int *index); - -static int -_string_list_length (string_list_t *list); - -static int -_string_list_equal (string_list_t *a, string_list_t *b); - -static argument_list_t * -_argument_list_create (void *ctx); - -static void -_argument_list_append (argument_list_t *list, token_list_t *argument); - -static int -_argument_list_length (argument_list_t *list); - -static token_list_t * -_argument_list_member_at (argument_list_t *list, int index); - -/* Note: This function ralloc_steal()s the str pointer. */ -static token_t * -_token_create_str (void *ctx, int type, char *str); - -static token_t * -_token_create_ival (void *ctx, int type, int ival); - -static token_list_t * -_token_list_create (void *ctx); - -/* Note: This function calls ralloc_steal on token. */ -static void -_token_list_append (token_list_t *list, token_t *token); - -static void -_token_list_append_list (token_list_t *list, token_list_t *tail); - -static int -_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b); - -static active_list_t * -_active_list_push (active_list_t *list, - const char *identifier, - token_node_t *marker); - -static active_list_t * -_active_list_pop (active_list_t *list); - -int -_active_list_contains (active_list_t *list, const char *identifier); - -static void -_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list); - -static void -_glcpp_parser_expand_token_list (glcpp_parser_t *parser, - token_list_t *list); - -static void -_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, - token_list_t *list); - -static void -_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, - int condition); - -static void -_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, - const char *type, int condition); - -static void -_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc); - -#define yylex glcpp_parser_lex - -static int -glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser); - -static void -glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list); - -static void -add_builtin_define(glcpp_parser_t *parser, const char *name, int value); - -%} - -%pure-parser -%error-verbose - -%locations -%initial-action { - @$.first_line = 1; - @$.first_column = 1; - @$.last_line = 1; - @$.last_column = 1; - @$.source = 0; -} - -%parse-param {glcpp_parser_t *parser} -%lex-param {glcpp_parser_t *parser} - -%expect 0 -%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE -%token PASTE -%type <ival> expression INTEGER operator SPACE integer_constant -%type <str> IDENTIFIER INTEGER_STRING OTHER -%type <string_list> identifier_list -%type <token> preprocessing_token conditional_token -%type <token_list> pp_tokens replacement_list text_line conditional_tokens -%left OR -%left AND -%left '|' -%left '^' -%left '&' -%left EQUAL NOT_EQUAL -%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL -%left LEFT_SHIFT RIGHT_SHIFT -%left '+' '-' -%left '*' '/' '%' -%right UNARY - -%% - -input: - /* empty */ -| input line -; - -line: - control_line { - ralloc_strcat (&parser->output, "\n"); - } -| text_line { - _glcpp_parser_print_expanded_token_list (parser, $1); - ralloc_strcat (&parser->output, "\n"); - ralloc_free ($1); - } -| expanded_line -| HASH non_directive -; - -expanded_line: - IF_EXPANDED expression NEWLINE { - _glcpp_parser_skip_stack_push_if (parser, & @1, $2); - } -| ELIF_EXPANDED expression NEWLINE { - _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2); - } -; - -control_line: - HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE { - _define_object_macro (parser, & @2, $2, $3); - } -| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE { - _define_function_macro (parser, & @2, $2, NULL, $5); - } -| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE { - _define_function_macro (parser, & @2, $2, $4, $6); - } -| HASH_UNDEF IDENTIFIER NEWLINE { - macro_t *macro = hash_table_find (parser->defines, $2); - if (macro) { - hash_table_remove (parser->defines, $2); - ralloc_free (macro); - } - ralloc_free ($2); - } -| HASH_IF conditional_tokens NEWLINE { - /* Be careful to only evaluate the 'if' expression if - * we are not skipping. When we are skipping, we - * simply push a new 0-valued 'if' onto the skip - * stack. - * - * This avoids generating diagnostics for invalid - * expressions that are being skipped. */ - if (parser->skip_stack == NULL || - parser->skip_stack->type == SKIP_NO_SKIP) - { - _glcpp_parser_expand_if (parser, IF_EXPANDED, $2); - } - else - { - _glcpp_parser_skip_stack_push_if (parser, & @1, 0); - parser->skip_stack->type = SKIP_TO_ENDIF; - } - } -| HASH_IF NEWLINE { - /* #if without an expression is only an error if we - * are not skipping */ - if (parser->skip_stack == NULL || - parser->skip_stack->type == SKIP_NO_SKIP) - { - glcpp_error(& @1, parser, "#if with no expression"); - } - _glcpp_parser_skip_stack_push_if (parser, & @1, 0); - } -| HASH_IFDEF IDENTIFIER junk NEWLINE { - macro_t *macro = hash_table_find (parser->defines, $2); - ralloc_free ($2); - _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL); - } -| HASH_IFNDEF IDENTIFIER junk NEWLINE { - macro_t *macro = hash_table_find (parser->defines, $2); - ralloc_free ($2); - _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL); - } -| HASH_ELIF conditional_tokens NEWLINE { - /* Be careful to only evaluate the 'elif' expression - * if we are not skipping. When we are skipping, we - * simply change to a 0-valued 'elif' on the skip - * stack. - * - * This avoids generating diagnostics for invalid - * expressions that are being skipped. */ - if (parser->skip_stack && - parser->skip_stack->type == SKIP_TO_ELSE) - { - _glcpp_parser_expand_if (parser, ELIF_EXPANDED, $2); - } - else - { - _glcpp_parser_skip_stack_change_if (parser, & @1, - "elif", 0); - } - } -| HASH_ELIF NEWLINE { - /* #elif without an expression is an error unless we - * are skipping. */ - if (parser->skip_stack && - parser->skip_stack->type == SKIP_TO_ELSE) - { - glcpp_error(& @1, parser, "#elif with no expression"); - } - else - { - _glcpp_parser_skip_stack_change_if (parser, & @1, - "elif", 0); - glcpp_warning(& @1, parser, "ignoring illegal #elif without expression"); - } - } -| HASH_ELSE NEWLINE { - _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1); - } -| HASH_ENDIF NEWLINE { - _glcpp_parser_skip_stack_pop (parser, & @1); - } -| HASH_VERSION integer_constant NEWLINE { - macro_t *macro = hash_table_find (parser->defines, "__VERSION__"); - if (macro) { - hash_table_remove (parser->defines, "__VERSION__"); - ralloc_free (macro); - } - add_builtin_define (parser, "__VERSION__", $2); - - if ($2 == 100) - add_builtin_define (parser, "GL_ES", 1); - - /* Currently, all ES2 implementations support highp in the - * fragment shader, so we always define this macro in ES2. - * If we ever get a driver that doesn't support highp, we'll - * need to add a flag to the gl_context and check that here. - */ - if ($2 >= 130 || $2 == 100) - add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); - - ralloc_asprintf_append (&parser->output, "#version %" PRIiMAX, $2); - } -| HASH NEWLINE -; - -integer_constant: - INTEGER_STRING { - if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) { - $$ = strtoll ($1 + 2, NULL, 16); - } else if ($1[0] == '0') { - $$ = strtoll ($1, NULL, 8); - } else { - $$ = strtoll ($1, NULL, 10); - } - } -| INTEGER { - $$ = $1; - } - -expression: - integer_constant -| expression OR expression { - $$ = $1 || $3; - } -| expression AND expression { - $$ = $1 && $3; - } -| expression '|' expression { - $$ = $1 | $3; - } -| expression '^' expression { - $$ = $1 ^ $3; - } -| expression '&' expression { - $$ = $1 & $3; - } -| expression NOT_EQUAL expression { - $$ = $1 != $3; - } -| expression EQUAL expression { - $$ = $1 == $3; - } -| expression GREATER_OR_EQUAL expression { - $$ = $1 >= $3; - } -| expression LESS_OR_EQUAL expression { - $$ = $1 <= $3; - } -| expression '>' expression { - $$ = $1 > $3; - } -| expression '<' expression { - $$ = $1 < $3; - } -| expression RIGHT_SHIFT expression { - $$ = $1 >> $3; - } -| expression LEFT_SHIFT expression { - $$ = $1 << $3; - } -| expression '-' expression { - $$ = $1 - $3; - } -| expression '+' expression { - $$ = $1 + $3; - } -| expression '%' expression { - if ($3 == 0) { - yyerror (& @1, parser, - "zero modulus in preprocessor directive"); - } else { - $$ = $1 % $3; - } - } -| expression '/' expression { - if ($3 == 0) { - yyerror (& @1, parser, - "division by 0 in preprocessor directive"); - } else { - $$ = $1 / $3; - } - } -| expression '*' expression { - $$ = $1 * $3; - } -| '!' expression %prec UNARY { - $$ = ! $2; - } -| '~' expression %prec UNARY { - $$ = ~ $2; - } -| '-' expression %prec UNARY { - $$ = - $2; - } -| '+' expression %prec UNARY { - $$ = + $2; - } -| '(' expression ')' { - $$ = $2; - } -; - -identifier_list: - IDENTIFIER { - $$ = _string_list_create (parser); - _string_list_append_item ($$, $1); - ralloc_steal ($$, $1); - } -| identifier_list ',' IDENTIFIER { - $$ = $1; - _string_list_append_item ($$, $3); - ralloc_steal ($$, $3); - } -; - -text_line: - NEWLINE { $$ = NULL; } -| pp_tokens NEWLINE -; - -non_directive: - pp_tokens NEWLINE { - yyerror (& @1, parser, "Invalid tokens after #"); - } -; - -replacement_list: - /* empty */ { $$ = NULL; } -| pp_tokens -; - -junk: - /* empty */ -| pp_tokens { - glcpp_warning(&@1, parser, "extra tokens at end of directive"); - } -; - -conditional_token: - /* Handle "defined" operator */ - DEFINED IDENTIFIER { - int v = hash_table_find (parser->defines, $2) ? 1 : 0; - $$ = _token_create_ival (parser, INTEGER, v); - } -| DEFINED '(' IDENTIFIER ')' { - int v = hash_table_find (parser->defines, $3) ? 1 : 0; - $$ = _token_create_ival (parser, INTEGER, v); - } -| preprocessing_token -; - -conditional_tokens: - /* Exactly the same as pp_tokens, but using conditional_token */ - conditional_token { - $$ = _token_list_create (parser); - _token_list_append ($$, $1); - } -| conditional_tokens conditional_token { - $$ = $1; - _token_list_append ($$, $2); - } -; - -pp_tokens: - preprocessing_token { - parser->space_tokens = 1; - $$ = _token_list_create (parser); - _token_list_append ($$, $1); - } -| pp_tokens preprocessing_token { - $$ = $1; - _token_list_append ($$, $2); - } -; - -preprocessing_token: - IDENTIFIER { - $$ = _token_create_str (parser, IDENTIFIER, $1); - $$->location = yylloc; - } -| INTEGER_STRING { - $$ = _token_create_str (parser, INTEGER_STRING, $1); - $$->location = yylloc; - } -| operator { - $$ = _token_create_ival (parser, $1, $1); - $$->location = yylloc; - } -| OTHER { - $$ = _token_create_str (parser, OTHER, $1); - $$->location = yylloc; - } -| SPACE { - $$ = _token_create_ival (parser, SPACE, SPACE); - $$->location = yylloc; - } -; - -operator: - '[' { $$ = '['; } -| ']' { $$ = ']'; } -| '(' { $$ = '('; } -| ')' { $$ = ')'; } -| '{' { $$ = '{'; } -| '}' { $$ = '}'; } -| '.' { $$ = '.'; } -| '&' { $$ = '&'; } -| '*' { $$ = '*'; } -| '+' { $$ = '+'; } -| '-' { $$ = '-'; } -| '~' { $$ = '~'; } -| '!' { $$ = '!'; } -| '/' { $$ = '/'; } -| '%' { $$ = '%'; } -| LEFT_SHIFT { $$ = LEFT_SHIFT; } -| RIGHT_SHIFT { $$ = RIGHT_SHIFT; } -| '<' { $$ = '<'; } -| '>' { $$ = '>'; } -| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; } -| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; } -| EQUAL { $$ = EQUAL; } -| NOT_EQUAL { $$ = NOT_EQUAL; } -| '^' { $$ = '^'; } -| '|' { $$ = '|'; } -| AND { $$ = AND; } -| OR { $$ = OR; } -| ';' { $$ = ';'; } -| ',' { $$ = ','; } -| '=' { $$ = '='; } -| PASTE { $$ = PASTE; } -; - -%% - -string_list_t * -_string_list_create (void *ctx) -{ - string_list_t *list; - - list = ralloc (ctx, string_list_t); - list->head = NULL; - list->tail = NULL; - - return list; -} - -void -_string_list_append_item (string_list_t *list, const char *str) -{ - string_node_t *node; - - node = ralloc (list, string_node_t); - node->str = ralloc_strdup (node, str); - - node->next = NULL; - - if (list->head == NULL) { - list->head = node; - } else { - list->tail->next = node; - } - - list->tail = node; -} - -int -_string_list_contains (string_list_t *list, const char *member, int *index) -{ - string_node_t *node; - int i; - - if (list == NULL) - return 0; - - for (i = 0, node = list->head; node; i++, node = node->next) { - if (strcmp (node->str, member) == 0) { - if (index) - *index = i; - return 1; - } - } - - return 0; -} - -int -_string_list_length (string_list_t *list) -{ - int length = 0; - string_node_t *node; - - if (list == NULL) - return 0; - - for (node = list->head; node; node = node->next) - length++; - - return length; -} - -int -_string_list_equal (string_list_t *a, string_list_t *b) -{ - string_node_t *node_a, *node_b; - - if (a == NULL && b == NULL) - return 1; - - if (a == NULL || b == NULL) - return 0; - - for (node_a = a->head, node_b = b->head; - node_a && node_b; - node_a = node_a->next, node_b = node_b->next) - { - if (strcmp (node_a->str, node_b->str)) - return 0; - } - - /* Catch the case of lists being different lengths, (which - * would cause the loop above to terminate after the shorter - * list). */ - return node_a == node_b; -} - -argument_list_t * -_argument_list_create (void *ctx) -{ - argument_list_t *list; - - list = ralloc (ctx, argument_list_t); - list->head = NULL; - list->tail = NULL; - - return list; -} - -void -_argument_list_append (argument_list_t *list, token_list_t *argument) -{ - argument_node_t *node; - - node = ralloc (list, argument_node_t); - node->argument = argument; - - node->next = NULL; - - if (list->head == NULL) { - list->head = node; - } else { - list->tail->next = node; - } - - list->tail = node; -} - -int -_argument_list_length (argument_list_t *list) -{ - int length = 0; - argument_node_t *node; - - if (list == NULL) - return 0; - - for (node = list->head; node; node = node->next) - length++; - - return length; -} - -token_list_t * -_argument_list_member_at (argument_list_t *list, int index) -{ - argument_node_t *node; - int i; - - if (list == NULL) - return NULL; - - node = list->head; - for (i = 0; i < index; i++) { - node = node->next; - if (node == NULL) - break; - } - - if (node) - return node->argument; - - return NULL; -} - -/* Note: This function ralloc_steal()s the str pointer. */ -token_t * -_token_create_str (void *ctx, int type, char *str) -{ - token_t *token; - - token = ralloc (ctx, token_t); - token->type = type; - token->value.str = str; - - ralloc_steal (token, str); - - return token; -} - -token_t * -_token_create_ival (void *ctx, int type, int ival) -{ - token_t *token; - - token = ralloc (ctx, token_t); - token->type = type; - token->value.ival = ival; - - return token; -} - -token_list_t * -_token_list_create (void *ctx) -{ - token_list_t *list; - - list = ralloc (ctx, token_list_t); - list->head = NULL; - list->tail = NULL; - list->non_space_tail = NULL; - - return list; -} - -void -_token_list_append (token_list_t *list, token_t *token) -{ - token_node_t *node; - - node = ralloc (list, token_node_t); - node->token = token; - node->next = NULL; - - ralloc_steal (list, token); - - if (list->head == NULL) { - list->head = node; - } else { - list->tail->next = node; - } - - list->tail = node; - if (token->type != SPACE) - list->non_space_tail = node; -} - -void -_token_list_append_list (token_list_t *list, token_list_t *tail) -{ - if (tail == NULL || tail->head == NULL) - return; - - if (list->head == NULL) { - list->head = tail->head; - } else { - list->tail->next = tail->head; - } - - list->tail = tail->tail; - list->non_space_tail = tail->non_space_tail; -} - -static token_list_t * -_token_list_copy (void *ctx, token_list_t *other) -{ - token_list_t *copy; - token_node_t *node; - - if (other == NULL) - return NULL; - - copy = _token_list_create (ctx); - for (node = other->head; node; node = node->next) { - token_t *new_token = ralloc (copy, token_t); - *new_token = *node->token; - _token_list_append (copy, new_token); - } - - return copy; -} - -static void -_token_list_trim_trailing_space (token_list_t *list) -{ - token_node_t *tail, *next; - - if (list->non_space_tail) { - tail = list->non_space_tail->next; - list->non_space_tail->next = NULL; - list->tail = list->non_space_tail; - - while (tail) { - next = tail->next; - ralloc_free (tail); - tail = next; - } - } -} - -static int -_token_list_is_empty_ignoring_space (token_list_t *l) -{ - token_node_t *n; - - if (l == NULL) - return 1; - - n = l->head; - while (n != NULL && n->token->type == SPACE) - n = n->next; - - return n == NULL; -} - -int -_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b) -{ - token_node_t *node_a, *node_b; - - if (a == NULL || b == NULL) { - int a_empty = _token_list_is_empty_ignoring_space(a); - int b_empty = _token_list_is_empty_ignoring_space(b); - return a_empty == b_empty; - } - - node_a = a->head; - node_b = b->head; - - while (1) - { - if (node_a == NULL && node_b == NULL) - break; - - if (node_a == NULL || node_b == NULL) - return 0; - - if (node_a->token->type == SPACE) { - node_a = node_a->next; - continue; - } - - if (node_b->token->type == SPACE) { - node_b = node_b->next; - continue; - } - - if (node_a->token->type != node_b->token->type) - return 0; - - switch (node_a->token->type) { - case INTEGER: - if (node_a->token->value.ival != - node_b->token->value.ival) - { - return 0; - } - break; - case IDENTIFIER: - case INTEGER_STRING: - case OTHER: - if (strcmp (node_a->token->value.str, - node_b->token->value.str)) - { - return 0; - } - break; - } - - node_a = node_a->next; - node_b = node_b->next; - } - - return 1; -} - -static void -_token_print (char **out, token_t *token) -{ - if (token->type < 256) { - ralloc_asprintf_append (out, "%c", token->type); - return; - } - - switch (token->type) { - case INTEGER: - ralloc_asprintf_append (out, "%" PRIiMAX, token->value.ival); - break; - case IDENTIFIER: - case INTEGER_STRING: - case OTHER: - ralloc_strcat (out, token->value.str); - break; - case SPACE: - ralloc_strcat (out, " "); - break; - case LEFT_SHIFT: - ralloc_strcat (out, "<<"); - break; - case RIGHT_SHIFT: - ralloc_strcat (out, ">>"); - break; - case LESS_OR_EQUAL: - ralloc_strcat (out, "<="); - break; - case GREATER_OR_EQUAL: - ralloc_strcat (out, ">="); - break; - case EQUAL: - ralloc_strcat (out, "=="); - break; - case NOT_EQUAL: - ralloc_strcat (out, "!="); - break; - case AND: - ralloc_strcat (out, "&&"); - break; - case OR: - ralloc_strcat (out, "||"); - break; - case PASTE: - ralloc_strcat (out, "##"); - break; - case COMMA_FINAL: - ralloc_strcat (out, ","); - break; - case PLACEHOLDER: - /* Nothing to print. */ - break; - default: - assert(!"Error: Don't know how to print token."); - break; - } -} - -/* Return a new token (ralloc()ed off of 'token') formed by pasting - * 'token' and 'other'. Note that this function may return 'token' or - * 'other' directly rather than allocating anything new. - * - * Caution: Only very cursory error-checking is performed to see if - * the final result is a valid single token. */ -static token_t * -_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) -{ - token_t *combined = NULL; - - /* Pasting a placeholder onto anything makes no change. */ - if (other->type == PLACEHOLDER) - return token; - - /* When 'token' is a placeholder, just return 'other'. */ - if (token->type == PLACEHOLDER) - return other; - - /* A very few single-character punctuators can be combined - * with another to form a multi-character punctuator. */ - switch (token->type) { - case '<': - if (other->type == '<') - combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT); - else if (other->type == '=') - combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL); - break; - case '>': - if (other->type == '>') - combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT); - else if (other->type == '=') - combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL); - break; - case '=': - if (other->type == '=') - combined = _token_create_ival (token, EQUAL, EQUAL); - break; - case '!': - if (other->type == '=') - combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL); - break; - case '&': - if (other->type == '&') - combined = _token_create_ival (token, AND, AND); - break; - case '|': - if (other->type == '|') - combined = _token_create_ival (token, OR, OR); - break; - } - - if (combined != NULL) { - /* Inherit the location from the first token */ - combined->location = token->location; - return combined; - } - - /* Two string-valued tokens can usually just be mashed - * together. - * - * XXX: This isn't actually legitimate. Several things here - * should result in a diagnostic since the result cannot be a - * valid, single pre-processing token. For example, pasting - * "123" and "abc" is not legal, but we don't catch that - * here. */ - if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) && - (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING)) - { - char *str; - - str = ralloc_asprintf (token, "%s%s", token->value.str, - other->value.str); - combined = _token_create_str (token, token->type, str); - combined->location = token->location; - return combined; - } - - glcpp_error (&token->location, parser, ""); - ralloc_strcat (&parser->info_log, "Pasting \""); - _token_print (&parser->info_log, token); - ralloc_strcat (&parser->info_log, "\" and \""); - _token_print (&parser->info_log, other); - ralloc_strcat (&parser->info_log, "\" does not give a valid preprocessing token.\n"); - - return token; -} - -static void -_token_list_print (glcpp_parser_t *parser, token_list_t *list) -{ - token_node_t *node; - - if (list == NULL) - return; - - for (node = list->head; node; node = node->next) - _token_print (&parser->output, node->token); -} - -void -yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error) -{ - glcpp_error(locp, parser, "%s", error); -} - -static void add_builtin_define(glcpp_parser_t *parser, - const char *name, int value) -{ - token_t *tok; - token_list_t *list; - - tok = _token_create_ival (parser, INTEGER, value); - - list = _token_list_create(parser); - _token_list_append(list, tok); - _define_object_macro(parser, NULL, name, list); -} - -glcpp_parser_t * -glcpp_parser_create (const struct gl_extensions *extensions, int api) -{ - glcpp_parser_t *parser; - int language_version; - - parser = ralloc (NULL, glcpp_parser_t); - - glcpp_lex_init_extra (parser, &parser->scanner); - parser->defines = hash_table_ctor (32, hash_table_string_hash, - hash_table_string_compare); - parser->active = NULL; - parser->lexing_if = 0; - parser->space_tokens = 1; - parser->newline_as_space = 0; - parser->in_control_line = 0; - parser->paren_count = 0; - - parser->skip_stack = NULL; - - parser->lex_from_list = NULL; - parser->lex_from_node = NULL; - - parser->output = ralloc_strdup(parser, ""); - parser->info_log = ralloc_strdup(parser, ""); - parser->error = 0; - - /* Add pre-defined macros. */ - add_builtin_define(parser, "GL_ARB_draw_buffers", 1); - add_builtin_define(parser, "GL_ARB_texture_rectangle", 1); - - if (api == API_OPENGLES2) - add_builtin_define(parser, "GL_ES", 1); - - if (extensions != NULL) { - if (extensions->EXT_texture_array) { - add_builtin_define(parser, "GL_EXT_texture_array", 1); - } - - if (extensions->ARB_fragment_coord_conventions) - add_builtin_define(parser, "GL_ARB_fragment_coord_conventions", - 1); - - if (extensions->ARB_explicit_attrib_location) - add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1); - if (extensions->AMD_conservative_depth) - add_builtin_define(parser, "GL_AMD_conservative_depth", 1); - } - - language_version = 110; - add_builtin_define(parser, "__VERSION__", language_version); - - return parser; -} - -int -glcpp_parser_parse (glcpp_parser_t *parser) -{ - return yyparse (parser); -} - -void -glcpp_parser_destroy (glcpp_parser_t *parser) -{ - glcpp_lex_destroy (parser->scanner); - hash_table_dtor (parser->defines); - ralloc_free (parser); -} - -typedef enum function_status -{ - FUNCTION_STATUS_SUCCESS, - FUNCTION_NOT_A_FUNCTION, - FUNCTION_UNBALANCED_PARENTHESES -} function_status_t; - -/* Find a set of function-like macro arguments by looking for a - * balanced set of parentheses. - * - * When called, 'node' should be the opening-parenthesis token, (or - * perhaps preceeding SPACE tokens). Upon successful return *last will - * be the last consumed node, (corresponding to the closing right - * parenthesis). - * - * Return values: - * - * FUNCTION_STATUS_SUCCESS: - * - * Successfully parsed a set of function arguments. - * - * FUNCTION_NOT_A_FUNCTION: - * - * Macro name not followed by a '('. This is not an error, but - * simply that the macro name should be treated as a non-macro. - * - * FUNCTION_UNBALANCED_PARENTHESES - * - * Macro name is not followed by a balanced set of parentheses. - */ -static function_status_t -_arguments_parse (argument_list_t *arguments, - token_node_t *node, - token_node_t **last) -{ - token_list_t *argument; - int paren_count; - - node = node->next; - - /* Ignore whitespace before first parenthesis. */ - while (node && node->token->type == SPACE) - node = node->next; - - if (node == NULL || node->token->type != '(') - return FUNCTION_NOT_A_FUNCTION; - - node = node->next; - - argument = _token_list_create (arguments); - _argument_list_append (arguments, argument); - - for (paren_count = 1; node; node = node->next) { - if (node->token->type == '(') - { - paren_count++; - } - else if (node->token->type == ')') - { - paren_count--; - if (paren_count == 0) - break; - } - - if (node->token->type == ',' && - paren_count == 1) - { - _token_list_trim_trailing_space (argument); - argument = _token_list_create (arguments); - _argument_list_append (arguments, argument); - } - else { - if (argument->head == NULL) { - /* Don't treat initial whitespace as - * part of the arguement. */ - if (node->token->type == SPACE) - continue; - } - _token_list_append (argument, node->token); - } - } - - if (paren_count) - return FUNCTION_UNBALANCED_PARENTHESES; - - *last = node; - - return FUNCTION_STATUS_SUCCESS; -} - -static token_list_t * -_token_list_create_with_one_space (void *ctx) -{ - token_list_t *list; - token_t *space; - - list = _token_list_create (ctx); - space = _token_create_ival (list, SPACE, SPACE); - _token_list_append (list, space); - - return list; -} - -static void -_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list) -{ - token_list_t *expanded; - token_t *token; - - expanded = _token_list_create (parser); - token = _token_create_ival (parser, type, type); - _token_list_append (expanded, token); - _glcpp_parser_expand_token_list (parser, list); - _token_list_append_list (expanded, list); - glcpp_parser_lex_from (parser, expanded); -} - -/* This is a helper function that's essentially part of the - * implementation of _glcpp_parser_expand_node. It shouldn't be called - * except for by that function. - * - * Returns NULL if node is a simple token with no expansion, (that is, - * although 'node' corresponds to an identifier defined as a - * function-like macro, it is not followed with a parenthesized - * argument list). - * - * Compute the complete expansion of node (which is a function-like - * macro) and subsequent nodes which are arguments. - * - * Returns the token list that results from the expansion and sets - * *last to the last node in the list that was consumed by the - * expansion. Specifically, *last will be set as follows: as the - * token of the closing right parenthesis. - */ -static token_list_t * -_glcpp_parser_expand_function (glcpp_parser_t *parser, - token_node_t *node, - token_node_t **last) - -{ - macro_t *macro; - const char *identifier; - argument_list_t *arguments; - function_status_t status; - token_list_t *substituted; - int parameter_index; - - identifier = node->token->value.str; - - macro = hash_table_find (parser->defines, identifier); - - assert (macro->is_function); - - arguments = _argument_list_create (parser); - status = _arguments_parse (arguments, node, last); - - switch (status) { - case FUNCTION_STATUS_SUCCESS: - break; - case FUNCTION_NOT_A_FUNCTION: - return NULL; - case FUNCTION_UNBALANCED_PARENTHESES: - glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier); - return NULL; - } - - /* Replace a macro defined as empty with a SPACE token. */ - if (macro->replacements == NULL) { - ralloc_free (arguments); - return _token_list_create_with_one_space (parser); - } - - if (! ((_argument_list_length (arguments) == - _string_list_length (macro->parameters)) || - (_string_list_length (macro->parameters) == 0 && - _argument_list_length (arguments) == 1 && - arguments->head->argument->head == NULL))) - { - glcpp_error (&node->token->location, parser, - "Error: macro %s invoked with %d arguments (expected %d)\n", - identifier, - _argument_list_length (arguments), - _string_list_length (macro->parameters)); - return NULL; - } - - /* Perform argument substitution on the replacement list. */ - substituted = _token_list_create (arguments); - - for (node = macro->replacements->head; node; node = node->next) - { - if (node->token->type == IDENTIFIER && - _string_list_contains (macro->parameters, - node->token->value.str, - ¶meter_index)) - { - token_list_t *argument; - argument = _argument_list_member_at (arguments, - parameter_index); - /* Before substituting, we expand the argument - * tokens, or append a placeholder token for - * an empty argument. */ - if (argument->head) { - token_list_t *expanded_argument; - expanded_argument = _token_list_copy (parser, - argument); - _glcpp_parser_expand_token_list (parser, - expanded_argument); - _token_list_append_list (substituted, - expanded_argument); - } else { - token_t *new_token; - - new_token = _token_create_ival (substituted, - PLACEHOLDER, - PLACEHOLDER); - _token_list_append (substituted, new_token); - } - } else { - _token_list_append (substituted, node->token); - } - } - - /* After argument substitution, and before further expansion - * below, implement token pasting. */ - - _token_list_trim_trailing_space (substituted); - - node = substituted->head; - while (node) - { - token_node_t *next_non_space; - - /* Look ahead for a PASTE token, skipping space. */ - next_non_space = node->next; - while (next_non_space && next_non_space->token->type == SPACE) - next_non_space = next_non_space->next; - - if (next_non_space == NULL) - break; - - if (next_non_space->token->type != PASTE) { - node = next_non_space; - continue; - } - - /* Now find the next non-space token after the PASTE. */ - next_non_space = next_non_space->next; - while (next_non_space && next_non_space->token->type == SPACE) - next_non_space = next_non_space->next; - - if (next_non_space == NULL) { - yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n"); - return NULL; - } - - node->token = _token_paste (parser, node->token, next_non_space->token); - node->next = next_non_space->next; - if (next_non_space == substituted->tail) - substituted->tail = node; - - node = node->next; - } - - substituted->non_space_tail = substituted->tail; - - return substituted; -} - -/* Compute the complete expansion of node, (and subsequent nodes after - * 'node' in the case that 'node' is a function-like macro and - * subsequent nodes are arguments). - * - * Returns NULL if node is a simple token with no expansion. - * - * Otherwise, returns the token list that results from the expansion - * and sets *last to the last node in the list that was consumed by - * the expansion. Specifically, *last will be set as follows: - * - * As 'node' in the case of object-like macro expansion. - * - * As the token of the closing right parenthesis in the case of - * function-like macro expansion. - */ -static token_list_t * -_glcpp_parser_expand_node (glcpp_parser_t *parser, - token_node_t *node, - token_node_t **last) -{ - token_t *token = node->token; - const char *identifier; - macro_t *macro; - - /* We only expand identifiers */ - if (token->type != IDENTIFIER) { - /* We change any COMMA into a COMMA_FINAL to prevent - * it being mistaken for an argument separator - * later. */ - if (token->type == ',') { - token->type = COMMA_FINAL; - token->value.ival = COMMA_FINAL; - } - - return NULL; - } - - /* Look up this identifier in the hash table. */ - identifier = token->value.str; - macro = hash_table_find (parser->defines, identifier); - - /* Not a macro, so no expansion needed. */ - if (macro == NULL) - return NULL; - - /* Finally, don't expand this macro if we're already actively - * expanding it, (to avoid infinite recursion). */ - if (_active_list_contains (parser->active, identifier)) { - /* We change the token type here from IDENTIFIER to - * OTHER to prevent any future expansion of this - * unexpanded token. */ - char *str; - token_list_t *expansion; - token_t *final; - - str = ralloc_strdup (parser, token->value.str); - final = _token_create_str (parser, OTHER, str); - expansion = _token_list_create (parser); - _token_list_append (expansion, final); - *last = node; - return expansion; - } - - if (! macro->is_function) - { - *last = node; - - /* Replace a macro defined as empty with a SPACE token. */ - if (macro->replacements == NULL) - return _token_list_create_with_one_space (parser); - - return _token_list_copy (parser, macro->replacements); - } - - return _glcpp_parser_expand_function (parser, node, last); -} - -/* Push a new identifier onto the active list, returning the new list. - * - * Here, 'marker' is the token node that appears in the list after the - * expansion of 'identifier'. That is, when the list iterator begins - * examinging 'marker', then it is time to pop this node from the - * active stack. - */ -active_list_t * -_active_list_push (active_list_t *list, - const char *identifier, - token_node_t *marker) -{ - active_list_t *node; - - node = ralloc (list, active_list_t); - node->identifier = ralloc_strdup (node, identifier); - node->marker = marker; - node->next = list; - - return node; -} - -active_list_t * -_active_list_pop (active_list_t *list) -{ - active_list_t *node = list; - - if (node == NULL) - return NULL; - - node = list->next; - ralloc_free (list); - - return node; -} - -int -_active_list_contains (active_list_t *list, const char *identifier) -{ - active_list_t *node; - - if (list == NULL) - return 0; - - for (node = list; node; node = node->next) - if (strcmp (node->identifier, identifier) == 0) - return 1; - - return 0; -} - -/* Walk over the token list replacing nodes with their expansion. - * Whenever nodes are expanded the walking will walk over the new - * nodes, continuing to expand as necessary. The results are placed in - * 'list' itself; - */ -static void -_glcpp_parser_expand_token_list (glcpp_parser_t *parser, - token_list_t *list) -{ - token_node_t *node_prev; - token_node_t *node, *last = NULL; - token_list_t *expansion; - - if (list == NULL) - return; - - _token_list_trim_trailing_space (list); - - node_prev = NULL; - node = list->head; - - while (node) { - - while (parser->active && parser->active->marker == node) - parser->active = _active_list_pop (parser->active); - - /* Find the expansion for node, which will replace all - * nodes from node to last, inclusive. */ - expansion = _glcpp_parser_expand_node (parser, node, &last); - if (expansion) { - token_node_t *n; - - for (n = node; n != last->next; n = n->next) - while (parser->active && - parser->active->marker == n) - { - parser->active = _active_list_pop (parser->active); - } - - parser->active = _active_list_push (parser->active, - node->token->value.str, - last->next); - - /* Splice expansion into list, supporting a - * simple deletion if the expansion is - * empty. */ - if (expansion->head) { - if (node_prev) - node_prev->next = expansion->head; - else - list->head = expansion->head; - expansion->tail->next = last->next; - if (last == list->tail) - list->tail = expansion->tail; - } else { - if (node_prev) - node_prev->next = last->next; - else - list->head = last->next; - if (last == list->tail) - list->tail = NULL; - } - } else { - node_prev = node; - } - node = node_prev ? node_prev->next : list->head; - } - - while (parser->active) - parser->active = _active_list_pop (parser->active); - - list->non_space_tail = list->tail; -} - -void -_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, - token_list_t *list) -{ - if (list == NULL) - return; - - _glcpp_parser_expand_token_list (parser, list); - - _token_list_trim_trailing_space (list); - - _token_list_print (parser, list); -} - -static void -_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc, - const char *identifier) -{ - /* According to the GLSL specification, macro names starting with "__" - * or "GL_" are reserved for future use. So, don't allow them. - */ - if (strncmp(identifier, "__", 2) == 0) { - glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n"); - } - if (strncmp(identifier, "GL_", 3) == 0) { - glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); - } -} - -static int -_macro_equal (macro_t *a, macro_t *b) -{ - if (a->is_function != b->is_function) - return 0; - - if (a->is_function) { - if (! _string_list_equal (a->parameters, b->parameters)) - return 0; - } - - return _token_list_equal_ignoring_space (a->replacements, - b->replacements); -} - -void -_define_object_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *identifier, - token_list_t *replacements) -{ - macro_t *macro, *previous; - - if (loc != NULL) - _check_for_reserved_macro_name(parser, loc, identifier); - - macro = ralloc (parser, macro_t); - - macro->is_function = 0; - macro->parameters = NULL; - macro->identifier = ralloc_strdup (macro, identifier); - macro->replacements = replacements; - ralloc_steal (macro, replacements); - - previous = hash_table_find (parser->defines, identifier); - if (previous) { - if (_macro_equal (macro, previous)) { - ralloc_free (macro); - return; - } - glcpp_error (loc, parser, "Redefinition of macro %s\n", - identifier); - } - - hash_table_insert (parser->defines, macro, identifier); -} - -void -_define_function_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *identifier, - string_list_t *parameters, - token_list_t *replacements) -{ - macro_t *macro, *previous; - - _check_for_reserved_macro_name(parser, loc, identifier); - - macro = ralloc (parser, macro_t); - ralloc_steal (macro, parameters); - ralloc_steal (macro, replacements); - - macro->is_function = 1; - macro->parameters = parameters; - macro->identifier = ralloc_strdup (macro, identifier); - macro->replacements = replacements; - previous = hash_table_find (parser->defines, identifier); - if (previous) { - if (_macro_equal (macro, previous)) { - ralloc_free (macro); - return; - } - glcpp_error (loc, parser, "Redefinition of macro %s\n", - identifier); - } - - hash_table_insert (parser->defines, macro, identifier); -} - -static int -glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) -{ - token_node_t *node; - int ret; - - if (parser->lex_from_list == NULL) { - ret = glcpp_lex (yylval, yylloc, parser->scanner); - - /* XXX: This ugly block of code exists for the sole - * purpose of converting a NEWLINE token into a SPACE - * token, but only in the case where we have seen a - * function-like macro name, but have not yet seen its - * closing parenthesis. - * - * There's perhaps a more compact way to do this with - * mid-rule actions in the grammar. - * - * I'm definitely not pleased with the complexity of - * this code here. - */ - if (parser->newline_as_space) - { - if (ret == '(') { - parser->paren_count++; - } else if (ret == ')') { - parser->paren_count--; - if (parser->paren_count == 0) - parser->newline_as_space = 0; - } else if (ret == NEWLINE) { - ret = SPACE; - } else if (ret != SPACE) { - if (parser->paren_count == 0) - parser->newline_as_space = 0; - } - } - else if (parser->in_control_line) - { - if (ret == NEWLINE) - parser->in_control_line = 0; - } - else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC || - ret == HASH_UNDEF || ret == HASH_IF || - ret == HASH_IFDEF || ret == HASH_IFNDEF || - ret == HASH_ELIF || ret == HASH_ELSE || - ret == HASH_ENDIF || ret == HASH) - { - parser->in_control_line = 1; - } - else if (ret == IDENTIFIER) - { - macro_t *macro; - macro = hash_table_find (parser->defines, - yylval->str); - if (macro && macro->is_function) { - parser->newline_as_space = 1; - parser->paren_count = 0; - } - } - - return ret; - } - - node = parser->lex_from_node; - - if (node == NULL) { - ralloc_free (parser->lex_from_list); - parser->lex_from_list = NULL; - return NEWLINE; - } - - *yylval = node->token->value; - ret = node->token->type; - - parser->lex_from_node = node->next; - - return ret; -} - -static void -glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list) -{ - token_node_t *node; - - assert (parser->lex_from_list == NULL); - - /* Copy list, eliminating any space tokens. */ - parser->lex_from_list = _token_list_create (parser); - - for (node = list->head; node; node = node->next) { - if (node->token->type == SPACE) - continue; - _token_list_append (parser->lex_from_list, node->token); - } - - ralloc_free (list); - - parser->lex_from_node = parser->lex_from_list->head; - - /* It's possible the list consisted of nothing but whitespace. */ - if (parser->lex_from_node == NULL) { - ralloc_free (parser->lex_from_list); - parser->lex_from_list = NULL; - } -} - -static void -_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, - int condition) -{ - skip_type_t current = SKIP_NO_SKIP; - skip_node_t *node; - - if (parser->skip_stack) - current = parser->skip_stack->type; - - node = ralloc (parser, skip_node_t); - node->loc = *loc; - - if (current == SKIP_NO_SKIP) { - if (condition) - node->type = SKIP_NO_SKIP; - else - node->type = SKIP_TO_ELSE; - } else { - node->type = SKIP_TO_ENDIF; - } - - node->next = parser->skip_stack; - parser->skip_stack = node; -} - -static void -_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, - const char *type, int condition) -{ - if (parser->skip_stack == NULL) { - glcpp_error (loc, parser, "%s without #if\n", type); - return; - } - - if (parser->skip_stack->type == SKIP_TO_ELSE) { - if (condition) - parser->skip_stack->type = SKIP_NO_SKIP; - } else { - parser->skip_stack->type = SKIP_TO_ENDIF; - } -} - -static void -_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc) -{ - skip_node_t *node; - - if (parser->skip_stack == NULL) { - glcpp_error (loc, parser, "#endif without #if\n"); - return; - } - - node = parser->skip_stack; - parser->skip_stack = node->next; - ralloc_free (node); -} +%{
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include "glcpp.h"
+#include "main/core.h" /* for struct gl_extensions */
+#include "main/mtypes.h" /* for gl_api enum */
+
+static void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
+
+static void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ token_list_t *replacements);
+
+static void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *macro,
+ string_list_t *parameters,
+ token_list_t *replacements);
+
+static string_list_t *
+_string_list_create (void *ctx);
+
+static void
+_string_list_append_item (string_list_t *list, const char *str);
+
+static int
+_string_list_contains (string_list_t *list, const char *member, int *index);
+
+static int
+_string_list_length (string_list_t *list);
+
+static int
+_string_list_equal (string_list_t *a, string_list_t *b);
+
+static argument_list_t *
+_argument_list_create (void *ctx);
+
+static void
+_argument_list_append (argument_list_t *list, token_list_t *argument);
+
+static int
+_argument_list_length (argument_list_t *list);
+
+static token_list_t *
+_argument_list_member_at (argument_list_t *list, int index);
+
+/* Note: This function ralloc_steal()s the str pointer. */
+static token_t *
+_token_create_str (void *ctx, int type, char *str);
+
+static token_t *
+_token_create_ival (void *ctx, int type, int ival);
+
+static token_list_t *
+_token_list_create (void *ctx);
+
+/* Note: This function calls ralloc_steal on token. */
+static void
+_token_list_append (token_list_t *list, token_t *token);
+
+static void
+_token_list_append_list (token_list_t *list, token_list_t *tail);
+
+static int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
+
+static void
+_parser_active_list_push (glcpp_parser_t *parser,
+ const char *identifier,
+ token_node_t *marker);
+
+static void
+_parser_active_list_pop (glcpp_parser_t *parser);
+
+static int
+_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier);
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
+
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list);
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition);
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition);
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
+
+#define yylex glcpp_parser_lex
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
+
+static void
+add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
+
+%}
+
+%pure-parser
+%error-verbose
+
+%locations
+%initial-action {
+ @$.first_line = 1;
+ @$.first_column = 1;
+ @$.last_line = 1;
+ @$.last_column = 1;
+ @$.source = 0;
+}
+
+%parse-param {glcpp_parser_t *parser}
+%lex-param {glcpp_parser_t *parser}
+
+%expect 0
+%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
+%token PASTE
+%type <ival> expression INTEGER operator SPACE integer_constant
+%type <str> IDENTIFIER INTEGER_STRING OTHER
+%type <string_list> identifier_list
+%type <token> preprocessing_token conditional_token
+%type <token_list> pp_tokens replacement_list text_line conditional_tokens
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOT_EQUAL
+%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
+%left LEFT_SHIFT RIGHT_SHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+
+%%
+
+input:
+ /* empty */
+| input line
+;
+
+line:
+ control_line {
+ ralloc_strcat (&parser->output, "\n");
+ }
+| text_line {
+ _glcpp_parser_print_expanded_token_list (parser, $1);
+ ralloc_strcat (&parser->output, "\n");
+ ralloc_free ($1);
+ }
+| expanded_line
+| HASH non_directive
+;
+
+expanded_line:
+ IF_EXPANDED expression NEWLINE {
+ _glcpp_parser_skip_stack_push_if (parser, & @1, $2);
+ }
+| ELIF_EXPANDED expression NEWLINE {
+ _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2);
+ }
+;
+
+control_line:
+ HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
+ _define_object_macro (parser, & @2, $2, $3);
+ }
+| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @2, $2, NULL, $5);
+ }
+| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
+ _define_function_macro (parser, & @2, $2, $4, $6);
+ }
+| HASH_UNDEF IDENTIFIER NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ if (macro) {
+ hash_table_remove (parser->defines, $2);
+ ralloc_free (macro);
+ }
+ ralloc_free ($2);
+ }
+| HASH_IF conditional_tokens NEWLINE {
+ /* Be careful to only evaluate the 'if' expression if
+ * we are not skipping. When we are skipping, we
+ * simply push a new 0-valued 'if' onto the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ _glcpp_parser_expand_if (parser, IF_EXPANDED, $2);
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+ }
+| HASH_IF NEWLINE {
+ /* #if without an expression is only an error if we
+ * are not skipping */
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ glcpp_error(& @1, parser, "#if with no expression");
+ }
+ _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+ }
+| HASH_IFDEF IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ ralloc_free ($2);
+ _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
+ }
+| HASH_IFNDEF IDENTIFIER junk NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, $2);
+ ralloc_free ($2);
+ _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
+ }
+| HASH_ELIF conditional_tokens NEWLINE {
+ /* Be careful to only evaluate the 'elif' expression
+ * if we are not skipping. When we are skipping, we
+ * simply change to a 0-valued 'elif' on the skip
+ * stack.
+ *
+ * This avoids generating diagnostics for invalid
+ * expressions that are being skipped. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ _glcpp_parser_expand_if (parser, ELIF_EXPANDED, $2);
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & @1,
+ "elif", 0);
+ }
+ }
+| HASH_ELIF NEWLINE {
+ /* #elif without an expression is an error unless we
+ * are skipping. */
+ if (parser->skip_stack &&
+ parser->skip_stack->type == SKIP_TO_ELSE)
+ {
+ glcpp_error(& @1, parser, "#elif with no expression");
+ }
+ else
+ {
+ _glcpp_parser_skip_stack_change_if (parser, & @1,
+ "elif", 0);
+ glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
+ }
+ }
+| HASH_ELSE NEWLINE {
+ _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
+ }
+| HASH_ENDIF NEWLINE {
+ _glcpp_parser_skip_stack_pop (parser, & @1);
+ }
+| HASH_VERSION integer_constant NEWLINE {
+ macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
+ if (macro) {
+ hash_table_remove (parser->defines, "__VERSION__");
+ ralloc_free (macro);
+ }
+ add_builtin_define (parser, "__VERSION__", $2);
+
+ if ($2 == 100)
+ add_builtin_define (parser, "GL_ES", 1);
+
+ /* Currently, all ES2 implementations support highp in the
+ * fragment shader, so we always define this macro in ES2.
+ * If we ever get a driver that doesn't support highp, we'll
+ * need to add a flag to the gl_context and check that here.
+ */
+ if ($2 >= 130 || $2 == 100)
+ add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
+
+ ralloc_asprintf_append (&parser->output, "#version %" PRIiMAX, $2);
+ }
+| HASH NEWLINE
+;
+
+integer_constant:
+ INTEGER_STRING {
+ if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) {
+ $$ = strtoll ($1 + 2, NULL, 16);
+ } else if ($1[0] == '0') {
+ $$ = strtoll ($1, NULL, 8);
+ } else {
+ $$ = strtoll ($1, NULL, 10);
+ }
+ }
+| INTEGER {
+ $$ = $1;
+ }
+
+expression:
+ integer_constant
+| expression OR expression {
+ $$ = $1 || $3;
+ }
+| expression AND expression {
+ $$ = $1 && $3;
+ }
+| expression '|' expression {
+ $$ = $1 | $3;
+ }
+| expression '^' expression {
+ $$ = $1 ^ $3;
+ }
+| expression '&' expression {
+ $$ = $1 & $3;
+ }
+| expression NOT_EQUAL expression {
+ $$ = $1 != $3;
+ }
+| expression EQUAL expression {
+ $$ = $1 == $3;
+ }
+| expression GREATER_OR_EQUAL expression {
+ $$ = $1 >= $3;
+ }
+| expression LESS_OR_EQUAL expression {
+ $$ = $1 <= $3;
+ }
+| expression '>' expression {
+ $$ = $1 > $3;
+ }
+| expression '<' expression {
+ $$ = $1 < $3;
+ }
+| expression RIGHT_SHIFT expression {
+ $$ = $1 >> $3;
+ }
+| expression LEFT_SHIFT expression {
+ $$ = $1 << $3;
+ }
+| expression '-' expression {
+ $$ = $1 - $3;
+ }
+| expression '+' expression {
+ $$ = $1 + $3;
+ }
+| expression '%' expression {
+ if ($3 == 0) {
+ yyerror (& @1, parser,
+ "zero modulus in preprocessor directive");
+ } else {
+ $$ = $1 % $3;
+ }
+ }
+| expression '/' expression {
+ if ($3 == 0) {
+ yyerror (& @1, parser,
+ "division by 0 in preprocessor directive");
+ } else {
+ $$ = $1 / $3;
+ }
+ }
+| expression '*' expression {
+ $$ = $1 * $3;
+ }
+| '!' expression %prec UNARY {
+ $$ = ! $2;
+ }
+| '~' expression %prec UNARY {
+ $$ = ~ $2;
+ }
+| '-' expression %prec UNARY {
+ $$ = - $2;
+ }
+| '+' expression %prec UNARY {
+ $$ = + $2;
+ }
+| '(' expression ')' {
+ $$ = $2;
+ }
+;
+
+identifier_list:
+ IDENTIFIER {
+ $$ = _string_list_create (parser);
+ _string_list_append_item ($$, $1);
+ ralloc_steal ($$, $1);
+ }
+| identifier_list ',' IDENTIFIER {
+ $$ = $1;
+ _string_list_append_item ($$, $3);
+ ralloc_steal ($$, $3);
+ }
+;
+
+text_line:
+ NEWLINE { $$ = NULL; }
+| pp_tokens NEWLINE
+;
+
+non_directive:
+ pp_tokens NEWLINE {
+ yyerror (& @1, parser, "Invalid tokens after #");
+ }
+;
+
+replacement_list:
+ /* empty */ { $$ = NULL; }
+| pp_tokens
+;
+
+junk:
+ /* empty */
+| pp_tokens {
+ glcpp_warning(&@1, parser, "extra tokens at end of directive");
+ }
+;
+
+conditional_token:
+ /* Handle "defined" operator */
+ DEFINED IDENTIFIER {
+ int v = hash_table_find (parser->defines, $2) ? 1 : 0;
+ $$ = _token_create_ival (parser, INTEGER, v);
+ }
+| DEFINED '(' IDENTIFIER ')' {
+ int v = hash_table_find (parser->defines, $3) ? 1 : 0;
+ $$ = _token_create_ival (parser, INTEGER, v);
+ }
+| preprocessing_token
+;
+
+conditional_tokens:
+ /* Exactly the same as pp_tokens, but using conditional_token */
+ conditional_token {
+ $$ = _token_list_create (parser);
+ _token_list_append ($$, $1);
+ }
+| conditional_tokens conditional_token {
+ $$ = $1;
+ _token_list_append ($$, $2);
+ }
+;
+
+pp_tokens:
+ preprocessing_token {
+ parser->space_tokens = 1;
+ $$ = _token_list_create (parser);
+ _token_list_append ($$, $1);
+ }
+| pp_tokens preprocessing_token {
+ $$ = $1;
+ _token_list_append ($$, $2);
+ }
+;
+
+preprocessing_token:
+ IDENTIFIER {
+ $$ = _token_create_str (parser, IDENTIFIER, $1);
+ $$->location = yylloc;
+ }
+| INTEGER_STRING {
+ $$ = _token_create_str (parser, INTEGER_STRING, $1);
+ $$->location = yylloc;
+ }
+| operator {
+ $$ = _token_create_ival (parser, $1, $1);
+ $$->location = yylloc;
+ }
+| OTHER {
+ $$ = _token_create_str (parser, OTHER, $1);
+ $$->location = yylloc;
+ }
+| SPACE {
+ $$ = _token_create_ival (parser, SPACE, SPACE);
+ $$->location = yylloc;
+ }
+;
+
+operator:
+ '[' { $$ = '['; }
+| ']' { $$ = ']'; }
+| '(' { $$ = '('; }
+| ')' { $$ = ')'; }
+| '{' { $$ = '{'; }
+| '}' { $$ = '}'; }
+| '.' { $$ = '.'; }
+| '&' { $$ = '&'; }
+| '*' { $$ = '*'; }
+| '+' { $$ = '+'; }
+| '-' { $$ = '-'; }
+| '~' { $$ = '~'; }
+| '!' { $$ = '!'; }
+| '/' { $$ = '/'; }
+| '%' { $$ = '%'; }
+| LEFT_SHIFT { $$ = LEFT_SHIFT; }
+| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
+| '<' { $$ = '<'; }
+| '>' { $$ = '>'; }
+| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
+| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
+| EQUAL { $$ = EQUAL; }
+| NOT_EQUAL { $$ = NOT_EQUAL; }
+| '^' { $$ = '^'; }
+| '|' { $$ = '|'; }
+| AND { $$ = AND; }
+| OR { $$ = OR; }
+| ';' { $$ = ';'; }
+| ',' { $$ = ','; }
+| '=' { $$ = '='; }
+| PASTE { $$ = PASTE; }
+;
+
+%%
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+ string_list_t *list;
+
+ list = ralloc (ctx, string_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_string_list_append_item (string_list_t *list, const char *str)
+{
+ string_node_t *node;
+
+ node = ralloc (list, string_node_t);
+ node->str = ralloc_strdup (node, str);
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_string_list_contains (string_list_t *list, const char *member, int *index)
+{
+ string_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return 0;
+
+ for (i = 0, node = list->head; node; i++, node = node->next) {
+ if (strcmp (node->str, member) == 0) {
+ if (index)
+ *index = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+_string_list_length (string_list_t *list)
+{
+ int length = 0;
+ string_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+int
+_string_list_equal (string_list_t *a, string_list_t *b)
+{
+ string_node_t *node_a, *node_b;
+
+ if (a == NULL && b == NULL)
+ return 1;
+
+ if (a == NULL || b == NULL)
+ return 0;
+
+ for (node_a = a->head, node_b = b->head;
+ node_a && node_b;
+ node_a = node_a->next, node_b = node_b->next)
+ {
+ if (strcmp (node_a->str, node_b->str))
+ return 0;
+ }
+
+ /* Catch the case of lists being different lengths, (which
+ * would cause the loop above to terminate after the shorter
+ * list). */
+ return node_a == node_b;
+}
+
+argument_list_t *
+_argument_list_create (void *ctx)
+{
+ argument_list_t *list;
+
+ list = ralloc (ctx, argument_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+
+ return list;
+}
+
+void
+_argument_list_append (argument_list_t *list, token_list_t *argument)
+{
+ argument_node_t *node;
+
+ node = ralloc (list, argument_node_t);
+ node->argument = argument;
+
+ node->next = NULL;
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+}
+
+int
+_argument_list_length (argument_list_t *list)
+{
+ int length = 0;
+ argument_node_t *node;
+
+ if (list == NULL)
+ return 0;
+
+ for (node = list->head; node; node = node->next)
+ length++;
+
+ return length;
+}
+
+token_list_t *
+_argument_list_member_at (argument_list_t *list, int index)
+{
+ argument_node_t *node;
+ int i;
+
+ if (list == NULL)
+ return NULL;
+
+ node = list->head;
+ for (i = 0; i < index; i++) {
+ node = node->next;
+ if (node == NULL)
+ break;
+ }
+
+ if (node)
+ return node->argument;
+
+ return NULL;
+}
+
+/* Note: This function ralloc_steal()s the str pointer. */
+token_t *
+_token_create_str (void *ctx, int type, char *str)
+{
+ token_t *token;
+
+ token = ralloc (ctx, token_t);
+ token->type = type;
+ token->value.str = str;
+
+ ralloc_steal (token, str);
+
+ return token;
+}
+
+token_t *
+_token_create_ival (void *ctx, int type, int ival)
+{
+ token_t *token;
+
+ token = ralloc (ctx, token_t);
+ token->type = type;
+ token->value.ival = ival;
+
+ return token;
+}
+
+token_list_t *
+_token_list_create (void *ctx)
+{
+ token_list_t *list;
+
+ list = ralloc (ctx, token_list_t);
+ list->head = NULL;
+ list->tail = NULL;
+ list->non_space_tail = NULL;
+
+ return list;
+}
+
+void
+_token_list_append (token_list_t *list, token_t *token)
+{
+ token_node_t *node;
+
+ node = ralloc (list, token_node_t);
+ node->token = token;
+ node->next = NULL;
+
+ ralloc_steal (list, token);
+
+ if (list->head == NULL) {
+ list->head = node;
+ } else {
+ list->tail->next = node;
+ }
+
+ list->tail = node;
+ if (token->type != SPACE)
+ list->non_space_tail = node;
+}
+
+void
+_token_list_append_list (token_list_t *list, token_list_t *tail)
+{
+ if (tail == NULL || tail->head == NULL)
+ return;
+
+ if (list->head == NULL) {
+ list->head = tail->head;
+ } else {
+ list->tail->next = tail->head;
+ }
+
+ list->tail = tail->tail;
+ list->non_space_tail = tail->non_space_tail;
+}
+
+static token_list_t *
+_token_list_copy (void *ctx, token_list_t *other)
+{
+ token_list_t *copy;
+ token_node_t *node;
+
+ if (other == NULL)
+ return NULL;
+
+ copy = _token_list_create (ctx);
+ for (node = other->head; node; node = node->next) {
+ token_t *new_token = ralloc (copy, token_t);
+ *new_token = *node->token;
+ _token_list_append (copy, new_token);
+ }
+
+ return copy;
+}
+
+static void
+_token_list_trim_trailing_space (token_list_t *list)
+{
+ token_node_t *tail, *next;
+
+ if (list->non_space_tail) {
+ tail = list->non_space_tail->next;
+ list->non_space_tail->next = NULL;
+ list->tail = list->non_space_tail;
+
+ while (tail) {
+ next = tail->next;
+ ralloc_free (tail);
+ tail = next;
+ }
+ }
+}
+
+static int
+_token_list_is_empty_ignoring_space (token_list_t *l)
+{
+ token_node_t *n;
+
+ if (l == NULL)
+ return 1;
+
+ n = l->head;
+ while (n != NULL && n->token->type == SPACE)
+ n = n->next;
+
+ return n == NULL;
+}
+
+int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
+{
+ token_node_t *node_a, *node_b;
+
+ if (a == NULL || b == NULL) {
+ int a_empty = _token_list_is_empty_ignoring_space(a);
+ int b_empty = _token_list_is_empty_ignoring_space(b);
+ return a_empty == b_empty;
+ }
+
+ node_a = a->head;
+ node_b = b->head;
+
+ while (1)
+ {
+ if (node_a == NULL && node_b == NULL)
+ break;
+
+ if (node_a == NULL || node_b == NULL)
+ return 0;
+
+ if (node_a->token->type == SPACE) {
+ node_a = node_a->next;
+ continue;
+ }
+
+ if (node_b->token->type == SPACE) {
+ node_b = node_b->next;
+ continue;
+ }
+
+ if (node_a->token->type != node_b->token->type)
+ return 0;
+
+ switch (node_a->token->type) {
+ case INTEGER:
+ if (node_a->token->value.ival !=
+ node_b->token->value.ival)
+ {
+ return 0;
+ }
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ if (strcmp (node_a->token->value.str,
+ node_b->token->value.str))
+ {
+ return 0;
+ }
+ break;
+ }
+
+ node_a = node_a->next;
+ node_b = node_b->next;
+ }
+
+ return 1;
+}
+
+static void
+_token_print (char **out, token_t *token)
+{
+ if (token->type < 256) {
+ ralloc_asprintf_append (out, "%c", token->type);
+ return;
+ }
+
+ switch (token->type) {
+ case INTEGER:
+ ralloc_asprintf_append (out, "%" PRIiMAX, token->value.ival);
+ break;
+ case IDENTIFIER:
+ case INTEGER_STRING:
+ case OTHER:
+ ralloc_strcat (out, token->value.str);
+ break;
+ case SPACE:
+ ralloc_strcat (out, " ");
+ break;
+ case LEFT_SHIFT:
+ ralloc_strcat (out, "<<");
+ break;
+ case RIGHT_SHIFT:
+ ralloc_strcat (out, ">>");
+ break;
+ case LESS_OR_EQUAL:
+ ralloc_strcat (out, "<=");
+ break;
+ case GREATER_OR_EQUAL:
+ ralloc_strcat (out, ">=");
+ break;
+ case EQUAL:
+ ralloc_strcat (out, "==");
+ break;
+ case NOT_EQUAL:
+ ralloc_strcat (out, "!=");
+ break;
+ case AND:
+ ralloc_strcat (out, "&&");
+ break;
+ case OR:
+ ralloc_strcat (out, "||");
+ break;
+ case PASTE:
+ ralloc_strcat (out, "##");
+ break;
+ case COMMA_FINAL:
+ ralloc_strcat (out, ",");
+ break;
+ case PLACEHOLDER:
+ /* Nothing to print. */
+ break;
+ default:
+ assert(!"Error: Don't know how to print token.");
+ break;
+ }
+}
+
+/* Return a new token (ralloc()ed off of 'token') formed by pasting
+ * 'token' and 'other'. Note that this function may return 'token' or
+ * 'other' directly rather than allocating anything new.
+ *
+ * Caution: Only very cursory error-checking is performed to see if
+ * the final result is a valid single token. */
+static token_t *
+_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
+{
+ token_t *combined = NULL;
+
+ /* Pasting a placeholder onto anything makes no change. */
+ if (other->type == PLACEHOLDER)
+ return token;
+
+ /* When 'token' is a placeholder, just return 'other'. */
+ if (token->type == PLACEHOLDER)
+ return other;
+
+ /* A very few single-character punctuators can be combined
+ * with another to form a multi-character punctuator. */
+ switch (token->type) {
+ case '<':
+ if (other->type == '<')
+ combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
+ break;
+ case '>':
+ if (other->type == '>')
+ combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
+ else if (other->type == '=')
+ combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
+ break;
+ case '=':
+ if (other->type == '=')
+ combined = _token_create_ival (token, EQUAL, EQUAL);
+ break;
+ case '!':
+ if (other->type == '=')
+ combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
+ break;
+ case '&':
+ if (other->type == '&')
+ combined = _token_create_ival (token, AND, AND);
+ break;
+ case '|':
+ if (other->type == '|')
+ combined = _token_create_ival (token, OR, OR);
+ break;
+ }
+
+ if (combined != NULL) {
+ /* Inherit the location from the first token */
+ combined->location = token->location;
+ return combined;
+ }
+
+ /* Two string-valued tokens can usually just be mashed
+ * together.
+ *
+ * XXX: This isn't actually legitimate. Several things here
+ * should result in a diagnostic since the result cannot be a
+ * valid, single pre-processing token. For example, pasting
+ * "123" and "abc" is not legal, but we don't catch that
+ * here. */
+ if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
+ (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
+ {
+ char *str;
+
+ str = ralloc_asprintf (token, "%s%s", token->value.str,
+ other->value.str);
+ combined = _token_create_str (token, token->type, str);
+ combined->location = token->location;
+ return combined;
+ }
+
+ glcpp_error (&token->location, parser, "");
+ ralloc_strcat (&parser->info_log, "Pasting \"");
+ _token_print (&parser->info_log, token);
+ ralloc_strcat (&parser->info_log, "\" and \"");
+ _token_print (&parser->info_log, other);
+ ralloc_strcat (&parser->info_log, "\" does not give a valid preprocessing token.\n");
+
+ return token;
+}
+
+static void
+_token_list_print (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ if (list == NULL)
+ return;
+
+ for (node = list->head; node; node = node->next)
+ _token_print (&parser->output, node->token);
+}
+
+void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
+{
+ glcpp_error(locp, parser, "%s", error);
+}
+
+static void add_builtin_define(glcpp_parser_t *parser,
+ const char *name, int value)
+{
+ token_t *tok;
+ token_list_t *list;
+
+ tok = _token_create_ival (parser, INTEGER, value);
+
+ list = _token_list_create(parser);
+ _token_list_append(list, tok);
+ _define_object_macro(parser, NULL, name, list);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions, int api)
+{
+ glcpp_parser_t *parser;
+ int language_version;
+
+ parser = ralloc (NULL, glcpp_parser_t);
+
+ glcpp_lex_init_extra (parser, &parser->scanner);
+ parser->defines = hash_table_ctor (32, hash_table_string_hash,
+ hash_table_string_compare);
+ parser->active = NULL;
+ parser->lexing_if = 0;
+ parser->space_tokens = 1;
+ parser->newline_as_space = 0;
+ parser->in_control_line = 0;
+ parser->paren_count = 0;
+
+ parser->skip_stack = NULL;
+
+ parser->lex_from_list = NULL;
+ parser->lex_from_node = NULL;
+
+ parser->output = ralloc_strdup(parser, "");
+ parser->info_log = ralloc_strdup(parser, "");
+ parser->error = 0;
+
+ /* Add pre-defined macros. */
+ add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+ add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+ if (api == API_OPENGLES2)
+ add_builtin_define(parser, "GL_ES", 1);
+
+ if (extensions != NULL) {
+ if (extensions->EXT_texture_array) {
+ add_builtin_define(parser, "GL_EXT_texture_array", 1);
+ }
+
+ if (extensions->ARB_fragment_coord_conventions)
+ add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+ 1);
+
+ if (extensions->ARB_explicit_attrib_location)
+ add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
+ if (extensions->AMD_conservative_depth)
+ add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
+ }
+
+ language_version = 110;
+ add_builtin_define(parser, "__VERSION__", language_version);
+
+ return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+ return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+ glcpp_lex_destroy (parser->scanner);
+ hash_table_dtor (parser->defines);
+ ralloc_free (parser);
+}
+
+typedef enum function_status
+{
+ FUNCTION_STATUS_SUCCESS,
+ FUNCTION_NOT_A_FUNCTION,
+ FUNCTION_UNBALANCED_PARENTHESES
+} function_status_t;
+
+/* Find a set of function-like macro arguments by looking for a
+ * balanced set of parentheses.
+ *
+ * When called, 'node' should be the opening-parenthesis token, (or
+ * perhaps preceeding SPACE tokens). Upon successful return *last will
+ * be the last consumed node, (corresponding to the closing right
+ * parenthesis).
+ *
+ * Return values:
+ *
+ * FUNCTION_STATUS_SUCCESS:
+ *
+ * Successfully parsed a set of function arguments.
+ *
+ * FUNCTION_NOT_A_FUNCTION:
+ *
+ * Macro name not followed by a '('. This is not an error, but
+ * simply that the macro name should be treated as a non-macro.
+ *
+ * FUNCTION_UNBALANCED_PARENTHESES
+ *
+ * Macro name is not followed by a balanced set of parentheses.
+ */
+static function_status_t
+_arguments_parse (argument_list_t *arguments,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_list_t *argument;
+ int paren_count;
+
+ node = node->next;
+
+ /* Ignore whitespace before first parenthesis. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL || node->token->type != '(')
+ return FUNCTION_NOT_A_FUNCTION;
+
+ node = node->next;
+
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+
+ for (paren_count = 1; node; node = node->next) {
+ if (node->token->type == '(')
+ {
+ paren_count++;
+ }
+ else if (node->token->type == ')')
+ {
+ paren_count--;
+ if (paren_count == 0)
+ break;
+ }
+
+ if (node->token->type == ',' &&
+ paren_count == 1)
+ {
+ _token_list_trim_trailing_space (argument);
+ argument = _token_list_create (arguments);
+ _argument_list_append (arguments, argument);
+ }
+ else {
+ if (argument->head == NULL) {
+ /* Don't treat initial whitespace as
+ * part of the arguement. */
+ if (node->token->type == SPACE)
+ continue;
+ }
+ _token_list_append (argument, node->token);
+ }
+ }
+
+ if (paren_count)
+ return FUNCTION_UNBALANCED_PARENTHESES;
+
+ *last = node;
+
+ return FUNCTION_STATUS_SUCCESS;
+}
+
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+ token_list_t *list;
+ token_t *space;
+
+ list = _token_list_create (ctx);
+ space = _token_create_ival (list, SPACE, SPACE);
+ _token_list_append (list, space);
+
+ return list;
+}
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
+{
+ token_list_t *expanded;
+ token_t *token;
+
+ expanded = _token_list_create (parser);
+ token = _token_create_ival (parser, type, type);
+ _token_list_append (expanded, token);
+ _glcpp_parser_expand_token_list (parser, list);
+ _token_list_append_list (expanded, list);
+ glcpp_parser_lex_from (parser, expanded);
+}
+
+/* This is a helper function that's essentially part of the
+ * implementation of _glcpp_parser_expand_node. It shouldn't be called
+ * except for by that function.
+ *
+ * Returns NULL if node is a simple token with no expansion, (that is,
+ * although 'node' corresponds to an identifier defined as a
+ * function-like macro, it is not followed with a parenthesized
+ * argument list).
+ *
+ * Compute the complete expansion of node (which is a function-like
+ * macro) and subsequent nodes which are arguments.
+ *
+ * Returns the token list that results from the expansion and sets
+ * *last to the last node in the list that was consumed by the
+ * expansion. Specifically, *last will be set as follows: as the
+ * token of the closing right parenthesis.
+ */
+static token_list_t *
+_glcpp_parser_expand_function (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+
+{
+ macro_t *macro;
+ const char *identifier;
+ argument_list_t *arguments;
+ function_status_t status;
+ token_list_t *substituted;
+ int parameter_index;
+
+ identifier = node->token->value.str;
+
+ macro = hash_table_find (parser->defines, identifier);
+
+ assert (macro->is_function);
+
+ arguments = _argument_list_create (parser);
+ status = _arguments_parse (arguments, node, last);
+
+ switch (status) {
+ case FUNCTION_STATUS_SUCCESS:
+ break;
+ case FUNCTION_NOT_A_FUNCTION:
+ return NULL;
+ case FUNCTION_UNBALANCED_PARENTHESES:
+ glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
+ return NULL;
+ }
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL) {
+ ralloc_free (arguments);
+ return _token_list_create_with_one_space (parser);
+ }
+
+ if (! ((_argument_list_length (arguments) ==
+ _string_list_length (macro->parameters)) ||
+ (_string_list_length (macro->parameters) == 0 &&
+ _argument_list_length (arguments) == 1 &&
+ arguments->head->argument->head == NULL)))
+ {
+ glcpp_error (&node->token->location, parser,
+ "Error: macro %s invoked with %d arguments (expected %d)\n",
+ identifier,
+ _argument_list_length (arguments),
+ _string_list_length (macro->parameters));
+ return NULL;
+ }
+
+ /* Perform argument substitution on the replacement list. */
+ substituted = _token_list_create (arguments);
+
+ for (node = macro->replacements->head; node; node = node->next)
+ {
+ if (node->token->type == IDENTIFIER &&
+ _string_list_contains (macro->parameters,
+ node->token->value.str,
+ ¶meter_index))
+ {
+ token_list_t *argument;
+ argument = _argument_list_member_at (arguments,
+ parameter_index);
+ /* Before substituting, we expand the argument
+ * tokens, or append a placeholder token for
+ * an empty argument. */
+ if (argument->head) {
+ token_list_t *expanded_argument;
+ expanded_argument = _token_list_copy (parser,
+ argument);
+ _glcpp_parser_expand_token_list (parser,
+ expanded_argument);
+ _token_list_append_list (substituted,
+ expanded_argument);
+ } else {
+ token_t *new_token;
+
+ new_token = _token_create_ival (substituted,
+ PLACEHOLDER,
+ PLACEHOLDER);
+ _token_list_append (substituted, new_token);
+ }
+ } else {
+ _token_list_append (substituted, node->token);
+ }
+ }
+
+ /* After argument substitution, and before further expansion
+ * below, implement token pasting. */
+
+ _token_list_trim_trailing_space (substituted);
+
+ node = substituted->head;
+ while (node)
+ {
+ token_node_t *next_non_space;
+
+ /* Look ahead for a PASTE token, skipping space. */
+ next_non_space = node->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL)
+ break;
+
+ if (next_non_space->token->type != PASTE) {
+ node = next_non_space;
+ continue;
+ }
+
+ /* Now find the next non-space token after the PASTE. */
+ next_non_space = next_non_space->next;
+ while (next_non_space && next_non_space->token->type == SPACE)
+ next_non_space = next_non_space->next;
+
+ if (next_non_space == NULL) {
+ yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+ return NULL;
+ }
+
+ node->token = _token_paste (parser, node->token, next_non_space->token);
+ node->next = next_non_space->next;
+ if (next_non_space == substituted->tail)
+ substituted->tail = node;
+
+ node = node->next;
+ }
+
+ substituted->non_space_tail = substituted->tail;
+
+ return substituted;
+}
+
+/* Compute the complete expansion of node, (and subsequent nodes after
+ * 'node' in the case that 'node' is a function-like macro and
+ * subsequent nodes are arguments).
+ *
+ * Returns NULL if node is a simple token with no expansion.
+ *
+ * Otherwise, returns the token list that results from the expansion
+ * and sets *last to the last node in the list that was consumed by
+ * the expansion. Specifically, *last will be set as follows:
+ *
+ * As 'node' in the case of object-like macro expansion.
+ *
+ * As the token of the closing right parenthesis in the case of
+ * function-like macro expansion.
+ */
+static token_list_t *
+_glcpp_parser_expand_node (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_t *token = node->token;
+ const char *identifier;
+ macro_t *macro;
+
+ /* We only expand identifiers */
+ if (token->type != IDENTIFIER) {
+ /* We change any COMMA into a COMMA_FINAL to prevent
+ * it being mistaken for an argument separator
+ * later. */
+ if (token->type == ',') {
+ token->type = COMMA_FINAL;
+ token->value.ival = COMMA_FINAL;
+ }
+
+ return NULL;
+ }
+
+ /* Look up this identifier in the hash table. */
+ identifier = token->value.str;
+ macro = hash_table_find (parser->defines, identifier);
+
+ /* Not a macro, so no expansion needed. */
+ if (macro == NULL)
+ return NULL;
+
+ /* Finally, don't expand this macro if we're already actively
+ * expanding it, (to avoid infinite recursion). */
+ if (_parser_active_list_contains (parser, identifier)) {
+ /* We change the token type here from IDENTIFIER to
+ * OTHER to prevent any future expansion of this
+ * unexpanded token. */
+ char *str;
+ token_list_t *expansion;
+ token_t *final;
+
+ str = ralloc_strdup (parser, token->value.str);
+ final = _token_create_str (parser, OTHER, str);
+ expansion = _token_list_create (parser);
+ _token_list_append (expansion, final);
+ *last = node;
+ return expansion;
+ }
+
+ if (! macro->is_function)
+ {
+ *last = node;
+
+ /* Replace a macro defined as empty with a SPACE token. */
+ if (macro->replacements == NULL)
+ return _token_list_create_with_one_space (parser);
+
+ return _token_list_copy (parser, macro->replacements);
+ }
+
+ return _glcpp_parser_expand_function (parser, node, last);
+}
+
+/* Push a new identifier onto the parser's active list.
+ *
+ * Here, 'marker' is the token node that appears in the list after the
+ * expansion of 'identifier'. That is, when the list iterator begins
+ * examining 'marker', then it is time to pop this node from the
+ * active stack.
+ */
+static void
+_parser_active_list_push (glcpp_parser_t *parser,
+ const char *identifier,
+ token_node_t *marker)
+{
+ active_list_t *node;
+
+ node = ralloc (parser->active, active_list_t);
+ node->identifier = ralloc_strdup (node, identifier);
+ node->marker = marker;
+ node->next = parser->active;
+
+ parser->active = node;
+}
+
+static void
+_parser_active_list_pop (glcpp_parser_t *parser)
+{
+ active_list_t *node = parser->active;
+
+ if (node == NULL) {
+ parser->active = NULL;
+ return;
+ }
+
+ node = parser->active->next;
+ ralloc_free (parser->active);
+
+ parser->active = node;
+}
+
+static int
+_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier)
+{
+ active_list_t *node;
+
+ if (parser->active == NULL)
+ return 0;
+
+ for (node = parser->active; node; node = node->next)
+ if (strcmp (node->identifier, identifier) == 0)
+ return 1;
+
+ return 0;
+}
+
+/* Walk over the token list replacing nodes with their expansion.
+ * Whenever nodes are expanded the walking will walk over the new
+ * nodes, continuing to expand as necessary. The results are placed in
+ * 'list' itself;
+ */
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ token_node_t *node_prev;
+ token_node_t *node, *last = NULL;
+ token_list_t *expansion;
+
+ if (list == NULL)
+ return;
+
+ _token_list_trim_trailing_space (list);
+
+ node_prev = NULL;
+ node = list->head;
+
+ while (node) {
+
+ while (parser->active && parser->active->marker == node)
+ _parser_active_list_pop (parser);
+
+ expansion = _glcpp_parser_expand_node (parser, node, &last);
+ if (expansion) {
+ token_node_t *n;
+
+ for (n = node; n != last->next; n = n->next)
+ while (parser->active &&
+ parser->active->marker == n)
+ {
+ _parser_active_list_pop (parser);
+ }
+
+ _parser_active_list_push (parser,
+ node->token->value.str,
+ last->next);
+
+ /* Splice expansion into list, supporting a
+ * simple deletion if the expansion is
+ * empty. */
+ if (expansion->head) {
+ if (node_prev)
+ node_prev->next = expansion->head;
+ else
+ list->head = expansion->head;
+ expansion->tail->next = last->next;
+ if (last == list->tail)
+ list->tail = expansion->tail;
+ } else {
+ if (node_prev)
+ node_prev->next = last->next;
+ else
+ list->head = last->next;
+ if (last == list->tail)
+ list->tail = NULL;
+ }
+ } else {
+ node_prev = node;
+ }
+ node = node_prev ? node_prev->next : list->head;
+ }
+
+ while (parser->active)
+ _parser_active_list_pop (parser);
+
+ list->non_space_tail = list->tail;
+}
+
+void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ if (list == NULL)
+ return;
+
+ _glcpp_parser_expand_token_list (parser, list);
+
+ _token_list_trim_trailing_space (list);
+
+ _token_list_print (parser, list);
+}
+
+static void
+_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *identifier)
+{
+ /* According to the GLSL specification, macro names starting with "__"
+ * or "GL_" are reserved for future use. So, don't allow them.
+ */
+ if (strncmp(identifier, "__", 2) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
+ }
+ if (strncmp(identifier, "GL_", 3) == 0) {
+ glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
+ }
+}
+
+static int
+_macro_equal (macro_t *a, macro_t *b)
+{
+ if (a->is_function != b->is_function)
+ return 0;
+
+ if (a->is_function) {
+ if (! _string_list_equal (a->parameters, b->parameters))
+ return 0;
+ }
+
+ return _token_list_equal_ignoring_space (a->replacements,
+ b->replacements);
+}
+
+void
+_define_object_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ token_list_t *replacements)
+{
+ macro_t *macro, *previous;
+
+ if (loc != NULL)
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = ralloc (parser, macro_t);
+
+ macro->is_function = 0;
+ macro->parameters = NULL;
+ macro->identifier = ralloc_strdup (macro, identifier);
+ macro->replacements = replacements;
+ ralloc_steal (macro, replacements);
+
+ previous = hash_table_find (parser->defines, identifier);
+ if (previous) {
+ if (_macro_equal (macro, previous)) {
+ ralloc_free (macro);
+ return;
+ }
+ glcpp_error (loc, parser, "Redefinition of macro %s\n",
+ identifier);
+ }
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+void
+_define_function_macro (glcpp_parser_t *parser,
+ YYLTYPE *loc,
+ const char *identifier,
+ string_list_t *parameters,
+ token_list_t *replacements)
+{
+ macro_t *macro, *previous;
+
+ _check_for_reserved_macro_name(parser, loc, identifier);
+
+ macro = ralloc (parser, macro_t);
+ ralloc_steal (macro, parameters);
+ ralloc_steal (macro, replacements);
+
+ macro->is_function = 1;
+ macro->parameters = parameters;
+ macro->identifier = ralloc_strdup (macro, identifier);
+ macro->replacements = replacements;
+ previous = hash_table_find (parser->defines, identifier);
+ if (previous) {
+ if (_macro_equal (macro, previous)) {
+ ralloc_free (macro);
+ return;
+ }
+ glcpp_error (loc, parser, "Redefinition of macro %s\n",
+ identifier);
+ }
+
+ hash_table_insert (parser->defines, macro, identifier);
+}
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
+{
+ token_node_t *node;
+ int ret;
+
+ if (parser->lex_from_list == NULL) {
+ ret = glcpp_lex (yylval, yylloc, parser->scanner);
+
+ /* XXX: This ugly block of code exists for the sole
+ * purpose of converting a NEWLINE token into a SPACE
+ * token, but only in the case where we have seen a
+ * function-like macro name, but have not yet seen its
+ * closing parenthesis.
+ *
+ * There's perhaps a more compact way to do this with
+ * mid-rule actions in the grammar.
+ *
+ * I'm definitely not pleased with the complexity of
+ * this code here.
+ */
+ if (parser->newline_as_space)
+ {
+ if (ret == '(') {
+ parser->paren_count++;
+ } else if (ret == ')') {
+ parser->paren_count--;
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ } else if (ret == NEWLINE) {
+ ret = SPACE;
+ } else if (ret != SPACE) {
+ if (parser->paren_count == 0)
+ parser->newline_as_space = 0;
+ }
+ }
+ else if (parser->in_control_line)
+ {
+ if (ret == NEWLINE)
+ parser->in_control_line = 0;
+ }
+ else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+ ret == HASH_UNDEF || ret == HASH_IF ||
+ ret == HASH_IFDEF || ret == HASH_IFNDEF ||
+ ret == HASH_ELIF || ret == HASH_ELSE ||
+ ret == HASH_ENDIF || ret == HASH)
+ {
+ parser->in_control_line = 1;
+ }
+ else if (ret == IDENTIFIER)
+ {
+ macro_t *macro;
+ macro = hash_table_find (parser->defines,
+ yylval->str);
+ if (macro && macro->is_function) {
+ parser->newline_as_space = 1;
+ parser->paren_count = 0;
+ }
+ }
+
+ return ret;
+ }
+
+ node = parser->lex_from_node;
+
+ if (node == NULL) {
+ ralloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ return NEWLINE;
+ }
+
+ *yylval = node->token->value;
+ ret = node->token->type;
+
+ parser->lex_from_node = node->next;
+
+ return ret;
+}
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
+{
+ token_node_t *node;
+
+ assert (parser->lex_from_list == NULL);
+
+ /* Copy list, eliminating any space tokens. */
+ parser->lex_from_list = _token_list_create (parser);
+
+ for (node = list->head; node; node = node->next) {
+ if (node->token->type == SPACE)
+ continue;
+ _token_list_append (parser->lex_from_list, node->token);
+ }
+
+ ralloc_free (list);
+
+ parser->lex_from_node = parser->lex_from_list->head;
+
+ /* It's possible the list consisted of nothing but whitespace. */
+ if (parser->lex_from_node == NULL) {
+ ralloc_free (parser->lex_from_list);
+ parser->lex_from_list = NULL;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ int condition)
+{
+ skip_type_t current = SKIP_NO_SKIP;
+ skip_node_t *node;
+
+ if (parser->skip_stack)
+ current = parser->skip_stack->type;
+
+ node = ralloc (parser, skip_node_t);
+ node->loc = *loc;
+
+ if (current == SKIP_NO_SKIP) {
+ if (condition)
+ node->type = SKIP_NO_SKIP;
+ else
+ node->type = SKIP_TO_ELSE;
+ } else {
+ node->type = SKIP_TO_ENDIF;
+ }
+
+ node->next = parser->skip_stack;
+ parser->skip_stack = node;
+}
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+ const char *type, int condition)
+{
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "%s without #if\n", type);
+ return;
+ }
+
+ if (parser->skip_stack->type == SKIP_TO_ELSE) {
+ if (condition)
+ parser->skip_stack->type = SKIP_NO_SKIP;
+ } else {
+ parser->skip_stack->type = SKIP_TO_ENDIF;
+ }
+}
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
+{
+ skip_node_t *node;
+
+ if (parser->skip_stack == NULL) {
+ glcpp_error (loc, parser, "#endif without #if\n");
+ return;
+ }
+
+ node = parser->skip_stack;
+ parser->skip_stack = node->next;
+ ralloc_free (node);
+}
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index da55c61f9..9c59ed82c 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -124,6 +124,7 @@ static const struct extension extension_table[] = { { "GL_ARB_texture_env_combine", o(ARB_texture_env_combine), GL, 2001 },
{ "GL_ARB_texture_env_crossbar", o(ARB_texture_env_crossbar), GL, 2001 },
{ "GL_ARB_texture_env_dot3", o(ARB_texture_env_dot3), GL, 2001 },
+ { "GL_ARB_texture_float", o(ARB_texture_float), GL, 2004 },
{ "GL_ARB_texture_mirrored_repeat", o(ARB_texture_mirrored_repeat), GL, 2001 },
{ "GL_ARB_texture_multisample", o(ARB_texture_multisample), GL, 2009 },
{ "GL_ARB_texture_non_power_of_two", o(ARB_texture_non_power_of_two), GL, 2003 },
@@ -268,6 +269,7 @@ static const struct extension extension_table[] = { { "GL_ATI_separate_stencil", o(ATI_separate_stencil), GL, 2006 },
{ "GL_ATI_texture_compression_3dc", o(ATI_texture_compression_3dc), GL, 2004 },
{ "GL_ATI_texture_env_combine3", o(ATI_texture_env_combine3), GL, 2002 },
+ { "GL_ATI_texture_float", o(ARB_texture_float), GL, 2002 },
{ "GL_ATI_texture_mirror_once", o(ATI_texture_mirror_once), GL, 2006 },
{ "GL_IBM_multimode_draw_arrays", o(IBM_multimode_draw_arrays), GL, 1998 },
{ "GL_IBM_rasterpos_clip", o(IBM_rasterpos_clip), GL, 1996 },
@@ -278,7 +280,6 @@ static const struct extension extension_table[] = { { "GL_MESA_texture_array", o(MESA_texture_array), GL, 2007 },
{ "GL_MESA_texture_signed_rgba", o(EXT_texture_snorm), GL, 2009 },
{ "GL_MESA_window_pos", o(ARB_window_pos), GL, 2000 },
- { "GL_MESAX_texture_float", o(ARB_texture_float), GL, 2009 },
{ "GL_MESA_ycbcr_texture", o(MESA_ycbcr_texture), GL, 2002 },
{ "GL_NV_blend_square", o(NV_blend_square), GL, 1999 },
{ "GL_NV_conditional_render", o(NV_conditional_render), GL, 2008 },
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 76493f1a8..a961e68cb 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -1145,7 +1145,37 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_INTENSITY16_SNORM:
return ctx->Extensions.EXT_texture_snorm &&
ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
- /* XXX add floating point and integer formats eventually */
+ case GL_R16F:
+ case GL_R32F:
+ return ctx->Extensions.ARB_texture_rg &&
+ ctx->Extensions.ARB_texture_float ? GL_RED : 0;
+ case GL_RG16F:
+ case GL_RG32F:
+ return ctx->Extensions.ARB_texture_rg &&
+ ctx->Extensions.ARB_texture_float ? GL_RG : 0;
+ case GL_RGB16F:
+ case GL_RGB32F:
+ return ctx->Extensions.ARB_texture_float ? GL_RGB : 0;
+ case GL_RGBA16F:
+ case GL_RGBA32F:
+ return ctx->Extensions.ARB_texture_float ? GL_RGBA : 0;
+ case GL_ALPHA16F_ARB:
+ case GL_ALPHA32F_ARB:
+ return ctx->Extensions.ARB_texture_float &&
+ ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
+ case GL_LUMINANCE16F_ARB:
+ case GL_LUMINANCE32F_ARB:
+ return ctx->Extensions.ARB_texture_float &&
+ ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ return ctx->Extensions.ARB_texture_float &&
+ ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
+ case GL_INTENSITY16F_ARB:
+ case GL_INTENSITY32F_ARB:
+ return ctx->Extensions.ARB_texture_float &&
+ ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
+ /* XXX add integer formats eventually */
default:
return 0;
}
diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index 8d2d4bfc1..5ae8e2e29 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -677,7 +677,7 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = {
MESA_FORMAT_LUMINANCE_FLOAT32,
"MESA_FORMAT_LUMINANCE_FLOAT32",
- GL_ALPHA,
+ GL_LUMINANCE,
GL_FLOAT,
0, 0, 0, 0,
32, 0, 0, 0, 0,
@@ -686,7 +686,7 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = {
MESA_FORMAT_LUMINANCE_FLOAT16,
"MESA_FORMAT_LUMINANCE_FLOAT16",
- GL_ALPHA,
+ GL_LUMINANCE,
GL_FLOAT,
0, 0, 0, 0,
16, 0, 0, 0, 0,
@@ -728,6 +728,42 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 0, 16, 0, 0, 0,
1, 1, 2
},
+ {
+ MESA_FORMAT_R_FLOAT32,
+ "MESA_FORMAT_R_FLOAT32",
+ GL_RED,
+ GL_FLOAT,
+ 32, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 4
+ },
+ {
+ MESA_FORMAT_R_FLOAT16,
+ "MESA_FORMAT_R_FLOAT16",
+ GL_RED,
+ GL_FLOAT,
+ 16, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 2
+ },
+ {
+ MESA_FORMAT_RG_FLOAT32,
+ "MESA_FORMAT_RG_FLOAT32",
+ GL_RG,
+ GL_FLOAT,
+ 32, 32, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 8
+ },
+ {
+ MESA_FORMAT_RG_FLOAT16,
+ "MESA_FORMAT_RG_FLOAT16",
+ GL_RG,
+ GL_FLOAT,
+ 16, 16, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 4
+ },
/* unnormalized signed int formats */
{
@@ -1714,22 +1750,26 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 3;
return;
case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
+ case MESA_FORMAT_RG_FLOAT32:
*datatype = GL_FLOAT;
*comps = 2;
return;
case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
+ case MESA_FORMAT_RG_FLOAT16:
*datatype = GL_HALF_FLOAT_ARB;
*comps = 2;
return;
case MESA_FORMAT_ALPHA_FLOAT32:
case MESA_FORMAT_LUMINANCE_FLOAT32:
case MESA_FORMAT_INTENSITY_FLOAT32:
+ case MESA_FORMAT_R_FLOAT32:
*datatype = GL_FLOAT;
*comps = 1;
return;
case MESA_FORMAT_ALPHA_FLOAT16:
case MESA_FORMAT_LUMINANCE_FLOAT16:
case MESA_FORMAT_INTENSITY_FLOAT16:
+ case MESA_FORMAT_R_FLOAT16:
*datatype = GL_HALF_FLOAT_ARB;
*comps = 1;
return;
diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 1eaca9b4c..492eef917 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -142,6 +142,10 @@ typedef enum MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16,
MESA_FORMAT_INTENSITY_FLOAT32,
MESA_FORMAT_INTENSITY_FLOAT16,
+ MESA_FORMAT_R_FLOAT32,
+ MESA_FORMAT_R_FLOAT16,
+ MESA_FORMAT_RG_FLOAT32,
+ MESA_FORMAT_RG_FLOAT16,
/*@}*/
/**
diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index b741c51ab..6acfa7660 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -551,7 +551,6 @@ _mesa_update_framebuffer_visual(struct gl_context *ctx, fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
fb->Visual.rgbBits = fb->Visual.redBits
+ fb->Visual.greenBits + fb->Visual.blueBits;
- fb->Visual.floatMode = GL_FALSE;
fb->Visual.samples = rb->NumSamples;
if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
fb->Visual.sRGBCapable = ctx->Const.sRGBCapable;
@@ -560,6 +559,19 @@ _mesa_update_framebuffer_visual(struct gl_context *ctx, }
}
+ fb->Visual.floatMode = GL_FALSE;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (fb->Attachment[i].Renderbuffer) {
+ const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
+ const gl_format fmt = rb->Format;
+
+ if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
+ fb->Visual.floatMode = GL_TRUE;
+ break;
+ }
+ }
+ }
+
if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
const struct gl_renderbuffer *rb =
fb->Attachment[BUFFER_DEPTH].Renderbuffer;
diff --git a/mesalib/src/mesa/main/texfetch.c b/mesalib/src/mesa/main/texfetch.c index b3ac64f6f..cb2716619 100644 --- a/mesalib/src/mesa/main/texfetch.c +++ b/mesalib/src/mesa/main/texfetch.c @@ -631,6 +631,34 @@ texfetch_funcs[MESA_FORMAT_COUNT] = fetch_texel_3d_f_intensity_f16,
store_texel_intensity_f16
},
+ {
+ MESA_FORMAT_R_FLOAT32,
+ fetch_texel_1d_f_r_f32,
+ fetch_texel_2d_f_r_f32,
+ fetch_texel_3d_f_r_f32,
+ store_texel_r_f32
+ },
+ {
+ MESA_FORMAT_R_FLOAT16,
+ fetch_texel_1d_f_r_f16,
+ fetch_texel_2d_f_r_f16,
+ fetch_texel_3d_f_r_f16,
+ store_texel_r_f16
+ },
+ {
+ MESA_FORMAT_RG_FLOAT32,
+ fetch_texel_1d_f_rg_f32,
+ fetch_texel_2d_f_rg_f32,
+ fetch_texel_3d_f_rg_f32,
+ store_texel_rg_f32
+ },
+ {
+ MESA_FORMAT_RG_FLOAT16,
+ fetch_texel_1d_f_rg_f16,
+ fetch_texel_2d_f_rg_f16,
+ fetch_texel_3d_f_rg_f16,
+ store_texel_rg_f16
+ },
/* non-normalized, signed int */
{
diff --git a/mesalib/src/mesa/main/texfetch_tmp.h b/mesalib/src/mesa/main/texfetch_tmp.h index fe525aa62..57bb94c68 100644 --- a/mesalib/src/mesa/main/texfetch_tmp.h +++ b/mesalib/src/mesa/main/texfetch_tmp.h @@ -438,6 +438,110 @@ static void store_texel_intensity_f16(struct gl_texture_image *texImage, #endif
+/* MESA_FORMAT_R_FLOAT32 *****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D R_FLOAT32 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_r_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ texel[RCOMP] = src[0];
+ texel[GCOMP] = 0.0F;
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_r_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ dst[0] = rgba[RCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_R_FLOAT16 *****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D R_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_r_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ texel[RCOMP] = _mesa_half_to_float(src[0]);
+ texel[GCOMP] = 0.0F;
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_r_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ dst[0] = _mesa_float_to_half(rgba[RCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_RG_FLOAT32 ****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RG_FLOAT32 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_rg_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
+ texel[RCOMP] = src[0];
+ texel[GCOMP] = src[1];
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rg_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
+ dst[0] = rgba[RCOMP];
+ dst[1] = rgba[GCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_RG_FLOAT16 ****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RG_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_rg_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
+ texel[RCOMP] = _mesa_half_to_float(src[0]);
+ texel[GCOMP] = _mesa_half_to_float(src[1]);
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rg_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
+ dst[0] = _mesa_float_to_half(rgba[RCOMP]);
+ dst[1] = _mesa_float_to_half(rgba[GCOMP]);
+}
+#endif
/*
diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index e22e90693..99513a222 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -628,6 +628,22 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, }
}
+ if (ctx->Extensions.ARB_texture_rg && ctx->Extensions.ARB_texture_float) {
+ switch (internalFormat) {
+ case GL_R16F:
+ return MESA_FORMAT_R_FLOAT16;
+ case GL_R32F:
+ return MESA_FORMAT_R_FLOAT32;
+ case GL_RG16F:
+ return MESA_FORMAT_RG_FLOAT16;
+ case GL_RG32F:
+ return MESA_FORMAT_RG_FLOAT32;
+
+ default:
+ ; /* fallthrough */
+ }
+ }
+
if (ctx->Extensions.EXT_texture_format_BGRA8888) {
switch (internalFormat) {
case GL_BGRA:
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 46ae867c1..066535111 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -3535,13 +3535,17 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS) dstFormat == MESA_FORMAT_ALPHA_FLOAT32 ||
dstFormat == MESA_FORMAT_LUMINANCE_FLOAT32 ||
dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32 ||
- dstFormat == MESA_FORMAT_INTENSITY_FLOAT32);
+ dstFormat == MESA_FORMAT_INTENSITY_FLOAT32 ||
+ dstFormat == MESA_FORMAT_R_FLOAT32 ||
+ dstFormat == MESA_FORMAT_RG_FLOAT32);
ASSERT(baseInternalFormat == GL_RGBA ||
baseInternalFormat == GL_RGB ||
baseInternalFormat == GL_ALPHA ||
baseInternalFormat == GL_LUMINANCE ||
baseInternalFormat == GL_LUMINANCE_ALPHA ||
- baseInternalFormat == GL_INTENSITY);
+ baseInternalFormat == GL_INTENSITY ||
+ baseInternalFormat == GL_RED ||
+ baseInternalFormat == GL_RG);
ASSERT(texelBytes == components * sizeof(GLfloat));
if (!ctx->_ImageTransferState &&
@@ -3605,13 +3609,17 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS) dstFormat == MESA_FORMAT_ALPHA_FLOAT16 ||
dstFormat == MESA_FORMAT_LUMINANCE_FLOAT16 ||
dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16 ||
- dstFormat == MESA_FORMAT_INTENSITY_FLOAT16);
+ dstFormat == MESA_FORMAT_INTENSITY_FLOAT16 ||
+ dstFormat == MESA_FORMAT_R_FLOAT16 ||
+ dstFormat == MESA_FORMAT_RG_FLOAT16);
ASSERT(baseInternalFormat == GL_RGBA ||
baseInternalFormat == GL_RGB ||
baseInternalFormat == GL_ALPHA ||
baseInternalFormat == GL_LUMINANCE ||
baseInternalFormat == GL_LUMINANCE_ALPHA ||
- baseInternalFormat == GL_INTENSITY);
+ baseInternalFormat == GL_INTENSITY ||
+ baseInternalFormat == GL_RED ||
+ baseInternalFormat == GL_RG);
ASSERT(texelBytes == components * sizeof(GLhalfARB));
if (!ctx->_ImageTransferState &&
@@ -4252,6 +4260,10 @@ texstore_funcs[MESA_FORMAT_COUNT] = { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 },
{ MESA_FORMAT_INTENSITY_FLOAT32, _mesa_texstore_rgba_float32 },
{ MESA_FORMAT_INTENSITY_FLOAT16, _mesa_texstore_rgba_float16 },
+ { MESA_FORMAT_R_FLOAT32, _mesa_texstore_rgba_float32 },
+ { MESA_FORMAT_R_FLOAT16, _mesa_texstore_rgba_float16 },
+ { MESA_FORMAT_RG_FLOAT32, _mesa_texstore_rgba_float32 },
+ { MESA_FORMAT_RG_FLOAT16, _mesa_texstore_rgba_float16 },
{ MESA_FORMAT_RGBA_INT8, _mesa_texstore_rgba_int8 },
{ MESA_FORMAT_RGBA_INT16, _mesa_texstore_rgba_int16 },
diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index 425019dca..08f53054d 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -201,7 +201,8 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, enum combination {
A8R8G8B8_UNORM_TO_RGBA_UBYTE,
A8R8G8B8_UNORM_TO_RGB_UBYTE,
- A8R8G8B8_UNORM_TO_BGRA_UINT
+ A8R8G8B8_UNORM_TO_BGRA_UINT,
+ A8R8G8B8_UNORM_TO_RGBA_UINT
} combo;
if (ctx->_ImageTransferState)
@@ -219,6 +220,10 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
combo = A8R8G8B8_UNORM_TO_BGRA_UINT;
}
+ else if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM &&
+ format == GL_RGBA && type == GL_UNSIGNED_INT_8_8_8_8) {
+ combo = A8R8G8B8_UNORM_TO_RGBA_UINT;
+ }
else {
return GL_FALSE;
}
@@ -305,6 +310,20 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, y += dy;
}
break;
+ case A8R8G8B8_UNORM_TO_RGBA_UINT:
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = map + y * trans->stride;
+ for (col = 0; col < width; col++) {
+ GLuint pixel = ((GLuint *) src)[col];
+ dst[col*4+0] = (pixel >> 24) & 0xff;
+ dst[col*4+1] = (pixel >> 0) & 0xff;
+ dst[col*4+2] = (pixel >> 8) & 0xff;
+ dst[col*4+3] = (pixel >> 16) & 0xff;
+ }
+ dst += dstStride;
+ y += dy;
+ }
+ break;
default:
; /* nothing */
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 6223733d3..0dc61bba9 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -600,7 +600,12 @@ st_TexImage(struct gl_context * ctx, * memory or malloc space for it.
*/
if (stImage->pt) {
- /* Store the image in the gallium texture memory buffer */
+ if (!pixels) {
+ /* We've allocated texture resource, but have no pixel data - all done. */
+ goto done;
+ }
+
+ /* Store the image in the gallium transfer object */
if (format == GL_DEPTH_COMPONENT &&
util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 9a3fb4ee6..1cbe618ce 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -382,6 +382,18 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
}
+ /* float support - assume nothing exclusively supports 64-bit floats */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_RENDER_TARGET) &&
+ screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_TEXTURE_2D, 0,
+ PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_RENDER_TARGET)) {
+ ctx->Extensions.ARB_texture_float = GL_TRUE;
+ }
+
/* sRGB support */
if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB,
PIPE_TEXTURE_2D, 0,
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index e057958e6..8b3e782a5 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -214,6 +214,39 @@ st_mesa_format_to_pipe_format(gl_format mesaFormat) case MESA_FORMAT_SARGB8:
return PIPE_FORMAT_B8G8R8A8_SRGB;
#endif
+ case MESA_FORMAT_RGBA_FLOAT32:
+ return PIPE_FORMAT_R32G32B32A32_FLOAT;
+ case MESA_FORMAT_RGBA_FLOAT16:
+ return PIPE_FORMAT_R16G16B16A16_FLOAT;
+ case MESA_FORMAT_RGB_FLOAT32:
+ return PIPE_FORMAT_R32G32B32_FLOAT;
+ case MESA_FORMAT_RGB_FLOAT16:
+ return PIPE_FORMAT_R16G16B16_FLOAT;
+ case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
+ return PIPE_FORMAT_L32A32_FLOAT;
+ case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
+ return PIPE_FORMAT_L16A16_FLOAT;
+ case MESA_FORMAT_LUMINANCE_FLOAT32:
+ return PIPE_FORMAT_L32_FLOAT;
+ case MESA_FORMAT_LUMINANCE_FLOAT16:
+ return PIPE_FORMAT_L16_FLOAT;
+ case MESA_FORMAT_ALPHA_FLOAT32:
+ return PIPE_FORMAT_A32_FLOAT;
+ case MESA_FORMAT_ALPHA_FLOAT16:
+ return PIPE_FORMAT_A16_FLOAT;
+ case MESA_FORMAT_INTENSITY_FLOAT32:
+ return PIPE_FORMAT_I32_FLOAT;
+ case MESA_FORMAT_INTENSITY_FLOAT16:
+ return PIPE_FORMAT_I16_FLOAT;
+ case MESA_FORMAT_R_FLOAT32:
+ return PIPE_FORMAT_R32_FLOAT;
+ case MESA_FORMAT_R_FLOAT16:
+ return PIPE_FORMAT_R16_FLOAT;
+ case MESA_FORMAT_RG_FLOAT32:
+ return PIPE_FORMAT_R32G32_FLOAT;
+ case MESA_FORMAT_RG_FLOAT16:
+ return PIPE_FORMAT_R16G16_FLOAT;
+
case MESA_FORMAT_R8:
return PIPE_FORMAT_R8_UNORM;
case MESA_FORMAT_R16:
@@ -403,6 +436,38 @@ st_pipe_format_to_mesa_format(enum pipe_format format) case PIPE_FORMAT_B8G8R8A8_SRGB:
return MESA_FORMAT_SARGB8;
#endif
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return MESA_FORMAT_RGBA_FLOAT32;
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ return MESA_FORMAT_RGBA_FLOAT16;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ return MESA_FORMAT_RGB_FLOAT32;
+ case PIPE_FORMAT_R16G16B16_FLOAT:
+ return MESA_FORMAT_RGB_FLOAT16;
+ case PIPE_FORMAT_L32A32_FLOAT:
+ return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32;
+ case PIPE_FORMAT_L16A16_FLOAT:
+ return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16;
+ case PIPE_FORMAT_L32_FLOAT:
+ return MESA_FORMAT_LUMINANCE_FLOAT32;
+ case PIPE_FORMAT_L16_FLOAT:
+ return MESA_FORMAT_LUMINANCE_FLOAT16;
+ case PIPE_FORMAT_A32_FLOAT:
+ return MESA_FORMAT_ALPHA_FLOAT32;
+ case PIPE_FORMAT_A16_FLOAT:
+ return MESA_FORMAT_ALPHA_FLOAT16;
+ case PIPE_FORMAT_I32_FLOAT:
+ return MESA_FORMAT_INTENSITY_FLOAT32;
+ case PIPE_FORMAT_I16_FLOAT:
+ return MESA_FORMAT_INTENSITY_FLOAT16;
+ case PIPE_FORMAT_R32_FLOAT:
+ return MESA_FORMAT_R_FLOAT32;
+ case PIPE_FORMAT_R16_FLOAT:
+ return MESA_FORMAT_R_FLOAT16;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ return MESA_FORMAT_RG_FLOAT32;
+ case PIPE_FORMAT_R16G16_FLOAT:
+ return MESA_FORMAT_RG_FLOAT16;
case PIPE_FORMAT_R8_UNORM:
return MESA_FORMAT_R8;
@@ -887,6 +952,178 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return PIPE_FORMAT_L8_SRGB;
return default_srgba_format( screen, target, sample_count, bindings);
+ /* prefer formats in order of data size, choosing 16-bit ones if equal sized */
+ case GL_RGBA16F_ARB:
+ case GL_RGB16F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_ALPHA16F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_A16_FLOAT,
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_A32_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_INTENSITY16F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_I16_FLOAT,
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_I32_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_LUMINANCE16F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_L16_FLOAT,
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_L32_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_R16F:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_R16_FLOAT,
+ PIPE_FORMAT_R16G16_FLOAT,
+ PIPE_FORMAT_R32_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_RG16F:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_R16G16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT,
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+
+ /* try a 32-bit format if available, otherwise fallback to a 16-bit one */
+ case GL_RGBA32F_ARB:
+ case GL_RGB32F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_ALPHA32F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_A32_FLOAT,
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_A16_FLOAT,
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_INTENSITY32F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_I32_FLOAT,
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_I16_FLOAT,
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_LUMINANCE32F_ARB:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_L32_FLOAT,
+ PIPE_FORMAT_L32A32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_L16_FLOAT,
+ PIPE_FORMAT_L16A16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_R32F:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_R32_FLOAT,
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_R16_FLOAT,
+ PIPE_FORMAT_R16G16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+ case GL_RG32F:
+ {
+ static const enum pipe_format formats[] = {
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_R16G16_FLOAT,
+ PIPE_FORMAT_R16G16B16A16_FLOAT
+ };
+ return find_supported_format(screen, formats, Elements(formats),
+ target, sample_count, bindings);
+ }
+
case GL_RED:
case GL_R8:
if (screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, target,
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c index c754b760f..ae890882b 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.c +++ b/xorg-server/hw/xfree86/dri2/dri2.c @@ -358,7 +358,7 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds, static void
update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
- DRI2BufferPtr *buffers, int *out_count, int *width, int *height)
+ DRI2BufferPtr *buffers, int out_count, int *width, int *height)
{
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
int i;
@@ -374,7 +374,7 @@ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw, }
pPriv->buffers = buffers;
- pPriv->bufferCount = *out_count;
+ pPriv->bufferCount = out_count;
pPriv->width = pDraw->width;
pPriv->height = pDraw->height;
*width = pPriv->width;
@@ -409,6 +409,8 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, && (pPriv->serialNumber == DRI2DrawableSerial(pDraw));
buffers = calloc((count + 1), sizeof(buffers[0]));
+ if (!buffers)
+ goto err_out;
for (i = 0; i < count; i++) {
const unsigned attachment = *(attachments++);
@@ -475,7 +477,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, *out_count = i;
- update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height);
+ update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width, height);
/* If the client is getting a fake front-buffer, pre-fill it with the
* contents of the real front-buffer. This ensures correct operation of
@@ -501,15 +503,17 @@ err_out: *out_count = 0;
- for (i = 0; i < count; i++) {
+ if (buffers) {
+ for (i = 0; i < count; i++) {
if (buffers[i] != NULL)
- (*ds->DestroyBuffer)(pDraw, buffers[i]);
- }
+ (*ds->DestroyBuffer)(pDraw, buffers[i]);
+ }
- free(buffers);
- buffers = NULL;
+ free(buffers);
+ buffers = NULL;
+ }
- update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height);
+ update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width, height);
return buffers;
}
diff --git a/xorg-server/xkeyboard-config/rules/base.extras.xml.in b/xorg-server/xkeyboard-config/rules/base.extras.xml.in index f845488e0..c3dcaa46f 100644 --- a/xorg-server/xkeyboard-config/rules/base.extras.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.extras.xml.in @@ -14,6 +14,30 @@ </layout>
<layout>
<configItem>
+ <name>ca</name>
+ <_shortDescription>fr</_shortDescription>
+ <_description>French (Canada)</_description>
+ <languageList><iso639Id>fr</iso639Id></languageList>
+ </configItem>
+ <variantList>
+ <variant>
+ <configItem>
+ <name>kut</name>
+ <_shortDescription>kut</_shortDescription>
+ <_description>Kutenai</_description>
+ </configItem>
+ </variant>
+ <variant>
+ <configItem>
+ <name>shs</name>
+ <_shortDescription>shs</_shortDescription>
+ <_description>Secwepemctsin</_description>
+ </configItem>
+ </variant>
+ </variantList>
+ </layout>
+ <layout>
+ <configItem>
<name>ir</name>
<_shortDescription>Iran</_shortDescription>
<_description>Iran</_description>
diff --git a/xorg-server/xkeyboard-config/rules/base.xml.in b/xorg-server/xkeyboard-config/rules/base.xml.in index 74666dcd3..fddc4c44b 100644 --- a/xorg-server/xkeyboard-config/rules/base.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.xml.in @@ -2179,20 +2179,6 @@ </variant>
<variant>
<configItem>
- <name>shs</name>
- <_shortDescription>shs</_shortDescription>
- <_description>Secwepemctsin</_description>
- </configItem>
- </variant>
- <variant>
- <configItem>
- <name>kut</name>
- <_shortDescription>kut</_shortDescription>
- <_description>Kutenai</_description>
- </configItem>
- </variant>
- <variant>
- <configItem>
<name>eng</name>
<_shortDescription>en</_shortDescription>
<_description>English (Canada)</_description>
diff --git a/xorg-server/xkeyboard-config/symbols/ca b/xorg-server/xkeyboard-config/symbols/ca index 00ef316f8..328be5bca 100644 --- a/xorg-server/xkeyboard-config/symbols/ca +++ b/xorg-server/xkeyboard-config/symbols/ca @@ -451,31 +451,6 @@ xkb_symbols "multix" { include "level5(rctrl_switch)"
};
-// Secwepemctsin keyboard for X11
-// written by Neskie Manuel <neskiem@gmail.com>
-
-partial alphanumeric_keys
-xkb_symbols "shs" {
-
- include "us"
-
- name[Group1]= "Secwepemctsin";
-
- //Using Dead key to get COMBINING COMMA ABOVE for ejectives on
- //q, l, t, s, m, g, k, p, w, y, r
- //XCompose key is used for the other accute and grave.
-
- key <AB08> { [ comma, less, U0313 ] };
- key <AC01> { [ a, A, aacute, Aacute ] };
- key <AD03> { [ e, E, eacute, Eacute ] };
- key <AD07> { [ u, U, uacute, Uacute ] };
- key <AD08> { [ i, I, iacute, Iacute ] };
- key <AD09> { [ o, O, oacute, Oacute ] };
-
- include "level3(ralt_switch)"
- include "compose(rctrl)"
-};
-
// OLPC Section
xkb_symbols "olpc" {
@@ -492,6 +467,14 @@ xkb_symbols "olpc" { };
partial alphanumeric_keys
+xkb_symbols "eng" {
+ name[Group1] = "English (Canada)";
+ include "us(basic)"
+};
+
+// EXTRAS:
+
+partial alphanumeric_keys
xkb_symbols "kut" {
//Ejective U0313 and compose accents are from shs layout
@@ -520,8 +503,28 @@ xkb_symbols "kut" { key <AC10> { [ semicolon, colon,U02BE,U02BE ] };
};
-partial alphanumeric_keys
-xkb_symbols "eng" {
- name[Group1] = "English (Canada)";
- include "us(basic)"
+// Secwepemctsin keyboard for X11
+// written by Neskie Manuel <neskiem@gmail.com>
+
+partial alphanumeric_keys
+xkb_symbols "shs" {
+
+ include "us"
+
+ name[Group1]= "Secwepemctsin";
+
+ //Using Dead key to get COMBINING COMMA ABOVE for ejectives on
+ //q, l, t, s, m, g, k, p, w, y, r
+ //XCompose key is used for the other accute and grave.
+
+ key <AB08> { [ comma, less, U0313 ] };
+ key <AC01> { [ a, A, aacute, Aacute ] };
+ key <AD03> { [ e, E, eacute, Eacute ] };
+ key <AD07> { [ u, U, uacute, Uacute ] };
+ key <AD08> { [ i, I, iacute, Iacute ] };
+ key <AD09> { [ o, O, oacute, Oacute ] };
+
+ include "level3(ralt_switch)"
+ include "compose(rctrl)"
};
+
diff --git a/xorg-server/xkeyboard-config/symbols/lv b/xorg-server/xkeyboard-config/symbols/lv index 7d38c10b6..176df5d28 100644 --- a/xorg-server/xkeyboard-config/symbols/lv +++ b/xorg-server/xkeyboard-config/symbols/lv @@ -42,7 +42,7 @@ //============================================================================
// Latvian QWERTY layout
-// http://en.wikipedia.org/wiki/QWERTY
+// http://en.wikipedia.org/wiki/QWERTY
//
partial default alphanumeric_keys modifier_keys
xkb_symbols "basic" {
@@ -262,7 +262,7 @@ xkb_symbols "modern" { name[Group1]= "Latvian (modern)";
- key <TLDE> {[ grave, asciitilde, acute, asciitilde ]};
+ key <TLDE> {[ grave, asciitilde, acute, copyright ]};
key <AE01> {[ 1, exclam, onesuperior, exclamdown ]};
key <AE02> {[ 2, at, twosuperior, oneeighth ]};
key <AE03> {[ 3, numbersign, threesuperior, sterling ]};
@@ -273,8 +273,8 @@ xkb_symbols "modern" { key <AE08> {[ 8, asterisk, bracketleft, trademark ]};
key <AE09> {[ 9, parenleft, bracketright, plusminus ]};
key <AE10> {[ 0, parenright, braceright, degree ]};
- key <AE11> {[ minus, underscore, backslash, endash ]};
- key <AE12> {[ equal, plus, bar, emdash ]};
+ key <AE11> {[ minus, underscore, backslash, questiondown ]};
+ key <AE12> {[ equal, plus, endash, emdash ]};
key <AD01> {[ emacron, Emacron, emacron, Emacron ]};
key <AD02> {[ o, O, omacron, Omacron ]};
@@ -285,8 +285,8 @@ xkb_symbols "modern" { key <AD07> {[ d, D, d, D ]};
key <AD08> {[ imacron, Imacron, imacron, Imacron ]};
key <AD09> {[ l, L, lcedilla, Lcedilla ]};
- key <AD10> {[ g, G, gcedilla, Gcedilla ]};
- key <AD11> {[ bracketleft, braceleft, guillemotleft, leftdoublequotemark ]};
+ key <AD10> {[ g, G, gcedilla, Gcedilla ]};
+ Key <AD11> {[ bracketleft, braceleft, guillemotleft, leftdoublequotemark ]};
key <AD12> {[ bracketright, braceright, guillemotright, rightdoublequotemark ]};
key <AC01> {[ e, E, e, E ]};
@@ -299,8 +299,8 @@ xkb_symbols "modern" { key <AC08> {[ i, I, i, I ]};
key <AC09> {[ t, T, t, T ]};
key <AC10> {[ r, R, rcedilla, Rcedilla ]};
- key <AC11> {[ m, M, m, M ]};
- key <AC12> {[ slash, question, backslash, bar ]};
+ key <AC11> {[ m, M, bar, M ]};
+ key <AC12> {[ slash, question, backslash, U263A ]};
key <LSGT> {[ q, Q, q, Q ]};
key <AB01> {[ x, X, q, Q ]};
@@ -310,7 +310,7 @@ xkb_symbols "modern" { key <AB05> {[ w, W, w, W ]};
key <AB06> {[ f, F, f, F ]};
key <AB07> {[ y, Y, y, Y ]};
- key <AB08> {[ h, H, h, H ]};
+ key <AB08> {[ h, H, h, H ]};
key <AB09> {[ comma, semicolon, less, multiply ]};
key <AB10> {[ period, colon, greater, division ]};
key <SPCE> {[ space, space, apostrophe ]};
|