e945a9faa6
* NEW: Requesting a component interface automatically loads the component now. * NEW: The Image and Picture functions in the interpreter API were removed. [GB.DRAW] * NEW: A new function in the Draw interface to get the size of a picture. This function replaces the removed Picture interpreter API. [GB.IMAGE] * NEW: This is a new component that manages images in memory. It implements the Image class, can create images of many formats (RGB, RGBA, BGRA...) and convert image data between different formats. This component replaces the previous interpreter Image API. All components were ported to this new image management system by loading this component automatically. Beware that the Image constructor has changed! The transparent property has been removed, and there is an optional color argument that is used for initializing the image data. Moreover, many classes (Webcam, PdfDocument...) that have an Image property lost their Picture property. Now to get a Picture, you must use the Image property and then convert the Image to a Picture. [GB.QT] * BUG: As now the Image class overrides the one located in gb.image, it must be declared early, at least earlier than the Picture class. git-svn-id: svn://localhost/gambas/trunk@1803 867c0c6c-44f3-4631-809d-bfa615b0a4ec
1898 lines
31 KiB
C
1898 lines
31 KiB
C
/***************************************************************************
|
||
|
||
gbx_api.c
|
||
|
||
Gambas API for external libraries
|
||
|
||
(c) 2000-2007 Benoit Minisini <gambas@users.sourceforge.net>
|
||
|
||
This program is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 1, or (at your option)
|
||
any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program; if not, write to the Free Software
|
||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
||
***************************************************************************/
|
||
|
||
#define __GBX_API_C
|
||
|
||
#include "gb_common.h"
|
||
#include "gb_common_case.h"
|
||
#include "gb_common_buffer.h"
|
||
#include "gb_error.h"
|
||
#include "gb_alloc.h"
|
||
|
||
#include <stdarg.h>
|
||
|
||
#include "gbx_class.h"
|
||
#include "gbx_exec.h"
|
||
#include "gbx_event.h"
|
||
#include "gbx_stack.h"
|
||
#include "gbx_stream.h"
|
||
#include "gbx_library.h"
|
||
#include "gbx_watch.h"
|
||
#include "gbx_project.h"
|
||
#include "gbx_eval.h"
|
||
#include "gbx_local.h"
|
||
#include "gb_hash.h"
|
||
#include "gb_file.h"
|
||
#include "gbx_number.h"
|
||
#include "gbx_object.h"
|
||
#include "gbx_string.h"
|
||
#include "gbx_date.h"
|
||
#include "gbx_print.h"
|
||
#include "gbx_regexp.h"
|
||
#include "gbx_c_array.h"
|
||
#include "gbx_c_timer.h"
|
||
#include "gbx_component.h"
|
||
#include "gbx_c_gambas.h"
|
||
|
||
#include "gambas.h"
|
||
#include "gbx_api.h"
|
||
|
||
typedef
|
||
struct {
|
||
OBJECT *object;
|
||
CLASS_DESC_METHOD *desc;
|
||
}
|
||
GB_API_FUNCTION;
|
||
|
||
void *GAMBAS_Api[] =
|
||
{
|
||
(void *)GB_VERSION,
|
||
|
||
(void *)GB_GetInterface,
|
||
|
||
(void *)GB_Hook,
|
||
|
||
(void *)GB_LoadComponent,
|
||
(void *)COMPONENT_find,
|
||
(void *)GB_CurrentComponent,
|
||
(void *)COMPONENT_get_info,
|
||
|
||
(void *)GB_Push,
|
||
(void *)GB_GetFunction,
|
||
(void *)GB_Call,
|
||
(void *)GB_GetClassInterface,
|
||
|
||
(void *)WATCH_one_loop,
|
||
(void *)EVENT_post,
|
||
(void *)EVENT_post2,
|
||
(void *)GB_Raise,
|
||
(void *)EVENT_post_event,
|
||
(void *)EVENT_check_post,
|
||
(void *)GB_CanRaise,
|
||
(void *)GB_GetEvent,
|
||
(void *)GB_GetLastEventName,
|
||
(void *)CTIMER_raise,
|
||
(void *)GB_Stopped,
|
||
(void *)COMPONENT_signal,
|
||
|
||
(void *)GB_NParam,
|
||
(void *)GB_Conv,
|
||
(void *)GB_GetUnknown,
|
||
(void *)GB_IsProperty,
|
||
|
||
(void *)GB_Error,
|
||
(void *)ERROR_propagate,
|
||
|
||
(void *)GB_GetClass,
|
||
(void *)GB_GetClassName,
|
||
(void *)GB_ExistClass,
|
||
(void *)CLASS_find_global,
|
||
(void *)GB_ExistClassLocal,
|
||
(void *)CLASS_find,
|
||
(void *)GB_Is,
|
||
(void *)GB_Ref,
|
||
(void *)GB_Unref,
|
||
(void *)GB_UnrefKeep,
|
||
(void *)GB_Detach,
|
||
(void *)GB_Attach,
|
||
(void *)OBJECT_parent,
|
||
(void *)GB_New,
|
||
(void *)CLASS_auto_create,
|
||
(void *)GB_CheckObject,
|
||
|
||
(void *)GB_GetEnum,
|
||
(void *)GB_StopEnum,
|
||
(void *)GB_ListEnum,
|
||
(void *)GB_NextEnum,
|
||
(void *)GB_StopAllEnum,
|
||
|
||
(void *)GB_Return,
|
||
(void *)GB_ReturnInteger,
|
||
(void *)GB_ReturnLong,
|
||
(void *)GB_ReturnPointer,
|
||
(void *)GB_ReturnBoolean,
|
||
(void *)GB_ReturnDate,
|
||
(void *)GB_ReturnObject,
|
||
(void *)GB_ReturnNull,
|
||
(void *)GB_ReturnFloat,
|
||
(void *)GB_ReturnPtr,
|
||
(void *)GB_ReturnSelf,
|
||
|
||
(void *)GB_ReturnString,
|
||
(void *)GB_ReturnConstString,
|
||
(void *)GB_ReturnConstZeroString,
|
||
(void *)GB_ReturnNewString,
|
||
(void *)GB_ReturnNewZeroString,
|
||
|
||
(void *)STRING_new,
|
||
(void *)GB_TempString,
|
||
(void *)GB_FreeString,
|
||
(void *)STRING_extend,
|
||
(void *)STRING_add,
|
||
(void *)GB_StringLength,
|
||
(void *)GB_ToZeroString,
|
||
(void *)REGEXP_match,
|
||
(void *)NUMBER_from_string,
|
||
(void *)GB_NumberToString,
|
||
(void *)LOCAL_gettext,
|
||
|
||
(void *)STRING_subst,
|
||
(void *)STRING_subst_add,
|
||
(void *)STRING_make,
|
||
(void *)GB_ConvString,
|
||
(void *)STRING_conv_file_name,
|
||
(void *)GB_RealFileName,
|
||
|
||
(void *)GB_LoadFile,
|
||
(void *)STREAM_unmap,
|
||
(void *)FILE_exist,
|
||
(void *)GB_GetTempDir,
|
||
|
||
(void *)GB_Store,
|
||
(void *)GB_StoreString,
|
||
(void *)GB_StoreObject,
|
||
(void *)GB_StoreVariant,
|
||
|
||
(void *)DATE_split,
|
||
(void *)DATE_make,
|
||
(void *)DATE_from_time,
|
||
(void *)DATE_timer,
|
||
|
||
(void *)GB_Watch,
|
||
|
||
(void *)GB_Eval,
|
||
|
||
(void *)GB_Alloc,
|
||
(void *)GB_Free,
|
||
(void *)GB_Realloc,
|
||
|
||
(void *)GB_NewArray,
|
||
(void *)ARRAY_delete,
|
||
(void *)GB_CountArray,
|
||
(void *)GB_Add,
|
||
(void *)ARRAY_insert_many,
|
||
(void *)ARRAY_remove_many,
|
||
|
||
(void *)GB_PrintData,
|
||
(void *)PRINT_string,
|
||
|
||
(void *)GB_SubCollectionNew,
|
||
(void *)GB_SubCollectionAdd,
|
||
(void *)GB_SubCollectionRemove,
|
||
(void *)GB_SubCollectionGet,
|
||
(void *)GB_SubCollectionContainer,
|
||
|
||
(void *)GB_tolower,
|
||
(void *)GB_toupper,
|
||
(void *)strcasecmp,
|
||
(void *)strncasecmp,
|
||
|
||
(void *)GB_AppName,
|
||
(void *)GB_AppTitle,
|
||
(void *)GB_AppVersion,
|
||
(void *)GB_AppPath,
|
||
(void *)GB_AppStartup,
|
||
|
||
(void *)GB_SystemCharset,
|
||
(void *)LOCAL_get_lang,
|
||
(void *)GB_SystemDomainName,
|
||
(void *)GB_IsRightToLeft,
|
||
|
||
(void *)GB_ArrayNew,
|
||
(void *)GB_ArrayCount,
|
||
(void *)GB_ArrayAdd,
|
||
(void *)GB_ArrayGet,
|
||
(void *)GB_ArrayType,
|
||
|
||
(void *)GB_CollectionNew,
|
||
(void *)GB_CollectionCount,
|
||
(void *)GB_CollectionSet,
|
||
(void *)GB_CollectionGet,
|
||
|
||
(void *)GB_HashTableNew,
|
||
(void *)HASH_TABLE_delete,
|
||
(void *)HASH_TABLE_size,
|
||
(void *)GB_HashTableAdd,
|
||
(void *)GB_HashTableRemove,
|
||
(void *)GB_HashTableGet,
|
||
(void *)GB_HashTableEnum,
|
||
|
||
(void *)GB_StreamSetBytesRead,
|
||
(void *)GB_StreamSetSwapping,
|
||
(void *)GB_StreamBlock,
|
||
|
||
(void *)STRING_start_len,
|
||
(void *)STRING_end,
|
||
(void *)STRING_make,
|
||
|
||
NULL
|
||
};
|
||
|
||
void *GAMBAS_DebugApi[] =
|
||
{
|
||
(void *)GB_DebugGetExec,
|
||
(void *)STACK_get_frame,
|
||
(void *)ERROR_print_at,
|
||
(void *)ERROR_save,
|
||
(void *)ERROR_restore,
|
||
(void *)VALUE_to_string,
|
||
(void *)LOCAL_format_date,
|
||
(void *)LOCAL_format_number,
|
||
(void *)DEBUG_get_value,
|
||
(void *)CARRAY_get_value,
|
||
(void *)GB_CollectionEnum,
|
||
(void *)CLASS_get_next_sorted_symbol,
|
||
(void *)DEBUG_can_be_used_like_an_array,
|
||
NULL
|
||
};
|
||
|
||
|
||
bool GAMBAS_Error = FALSE;
|
||
bool GAMBAS_DoNotRaiseEvent = FALSE;
|
||
bool GAMBAS_StopEvent = FALSE;
|
||
|
||
static bool _event_stopped = FALSE;
|
||
|
||
int GB_GetInterface(const char *name, int version, void *iface)
|
||
{
|
||
GB_LoadComponent(name);
|
||
|
||
if (LIBRARY_get_interface_by_name(name, version, iface))
|
||
ERROR_panic("Cannot find interface of library '%s'", name);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
void *GB_Hook(int type, void *hook)
|
||
{
|
||
void *old_hook;
|
||
void **phook = (void **)(void *)&EXEC_Hook;
|
||
|
||
if ((type < GB_HOOK_MAIN) || (type > GB_HOOK_PICTURE))
|
||
return NULL;
|
||
|
||
type--;
|
||
old_hook = phook[type];
|
||
if (hook)
|
||
phook[type] = hook;
|
||
|
||
return old_hook;
|
||
}
|
||
|
||
|
||
int GB_LoadComponent(const char *name)
|
||
{
|
||
int ret = 0;
|
||
|
||
TRY
|
||
{
|
||
COMPONENT *comp = COMPONENT_create(name);
|
||
COMPONENT_load(comp);
|
||
}
|
||
CATCH
|
||
{
|
||
ret = 1;
|
||
GAMBAS_Error = TRUE;
|
||
}
|
||
END_TRY
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
static void push(int nval, va_list args)
|
||
{
|
||
TYPE type;
|
||
|
||
STACK_check(nval);
|
||
|
||
while (nval)
|
||
{
|
||
type = va_arg(args, int);
|
||
SP->type = type;
|
||
|
||
switch(type)
|
||
{
|
||
case T_INTEGER:
|
||
case T_BOOLEAN:
|
||
SP->_integer.value = va_arg(args, int);
|
||
break;
|
||
|
||
case T_LONG:
|
||
SP->_long.value = va_arg(args, int64_t);
|
||
break;
|
||
|
||
case T_STRING:
|
||
SP->type = T_CSTRING;
|
||
SP->_string.addr = va_arg(args, char *);
|
||
SP->_string.start = 0;
|
||
SP->_string.len = va_arg(args, int);
|
||
if (SP->_string.len <= 0 && SP->_string.addr)
|
||
SP->_string.len = strlen(SP->_string.addr);
|
||
break;
|
||
|
||
case T_FLOAT:
|
||
SP->_float.value = va_arg(args, double);
|
||
break;
|
||
|
||
case T_OBJECT:
|
||
SP->_object.object = va_arg(args, void *);
|
||
OBJECT_REF(SP->_object.object, "push");
|
||
break;
|
||
|
||
default:
|
||
ERROR_panic("GB.Push: unknown datatype");
|
||
break;
|
||
}
|
||
|
||
SP++;
|
||
nval--;
|
||
}
|
||
}
|
||
|
||
|
||
void GB_Push(int nval, ...)
|
||
{
|
||
va_list args;
|
||
|
||
va_start(args, nval);
|
||
push(nval, args);
|
||
va_end(args);
|
||
}
|
||
|
||
|
||
static void call_method(void *object, CLASS_DESC_METHOD *desc, int nparam)
|
||
{
|
||
if (OBJECT_is_class(object))
|
||
{
|
||
EXEC.object = NULL;
|
||
//EXEC.class = (CLASS *)object;
|
||
}
|
||
else
|
||
{
|
||
EXEC.object = object;
|
||
//EXEC.class = OBJECT_class(object);
|
||
}
|
||
|
||
EXEC.class = desc->class;
|
||
EXEC.nparam = nparam; /*desc->npmin;*/
|
||
EXEC.drop = FALSE;
|
||
|
||
if (FUNCTION_is_native(desc))
|
||
{
|
||
EXEC.native = TRUE;
|
||
EXEC.use_stack = FALSE;
|
||
EXEC.desc = desc;
|
||
EXEC_native();
|
||
SP--;
|
||
*RP = *SP;
|
||
SP->type = T_VOID;
|
||
}
|
||
else
|
||
{
|
||
EXEC.native = FALSE;
|
||
EXEC.index = (int)(intptr_t)desc->exec;
|
||
EXEC_function_keep();
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
int GB_CanRaise(void *object, int event_id)
|
||
{
|
||
ushort *event_tab;
|
||
int func_id;
|
||
COBSERVER *obs;
|
||
|
||
if (object == NULL)
|
||
return FALSE;
|
||
|
||
LIST_for_each(obs, OBJECT_event(object)->observer)
|
||
{
|
||
if (OBJECT_active_parent(obs) && obs->event && obs->event[event_id])
|
||
return TRUE;
|
||
}
|
||
|
||
if (!OBJECT_active_parent(object))
|
||
return FALSE;
|
||
|
||
event_tab = OBJECT_event(object)->event;
|
||
func_id = event_tab[event_id];
|
||
|
||
return (func_id != 0);
|
||
}
|
||
|
||
|
||
static int get_event_func_id(ushort *event_tab, int event_id)
|
||
{
|
||
int func_id;
|
||
|
||
if (!event_tab)
|
||
return 0;
|
||
|
||
func_id = event_tab[event_id];
|
||
if (!func_id)
|
||
return 0;
|
||
|
||
return func_id;
|
||
}
|
||
|
||
static bool raise_event(OBJECT *observer, void *object, int func_id, int nparam)
|
||
{
|
||
bool stop_event;
|
||
CLASS *class;
|
||
CLASS_DESC_METHOD *desc;
|
||
void *old_last;
|
||
bool result;
|
||
|
||
class = OBJECT_class(object);
|
||
func_id--;
|
||
|
||
if (OBJECT_is_class(observer))
|
||
desc = &(((CLASS *)observer)->table[func_id].desc->method);
|
||
else
|
||
desc = &(observer->class->table[func_id].desc->method);
|
||
|
||
old_last = EVENT_Last;
|
||
EVENT_Last = object;
|
||
|
||
// if (arg)
|
||
// {
|
||
// EXEC_dup(nparam);
|
||
// }
|
||
// else
|
||
// {
|
||
// va_start(args, nparam);
|
||
// push(nparam, args);
|
||
// va_end(args);
|
||
// }
|
||
|
||
stop_event = GAMBAS_StopEvent;
|
||
GAMBAS_StopEvent = FALSE;
|
||
|
||
call_method(observer, desc, nparam);
|
||
|
||
if (RP->type == T_VOID)
|
||
result = FALSE;
|
||
else
|
||
result = RP->_boolean.value != 0;
|
||
|
||
if (GAMBAS_StopEvent)
|
||
result = TRUE;
|
||
|
||
GAMBAS_StopEvent = stop_event;
|
||
EVENT_Last = old_last;
|
||
|
||
EXEC_release_return_value();
|
||
|
||
return result;
|
||
}
|
||
|
||
// If nparam < 0, the args are already on the stack
|
||
|
||
int GB_Raise(void *object, int event_id, int nparam, ...)
|
||
{
|
||
OBJECT *parent;
|
||
int func_id;
|
||
int result;
|
||
va_list args;
|
||
bool arg;
|
||
COBSERVER *obs;
|
||
bool after = FALSE;
|
||
|
||
/*MEMORY_check_ptr(object);*/
|
||
|
||
if (GAMBAS_DoNotRaiseEvent)
|
||
return FALSE;
|
||
|
||
if (!OBJECT_is_valid(object))
|
||
return FALSE;
|
||
|
||
/*TRY
|
||
{*/
|
||
OBJECT_REF(object, "GB_Raise");
|
||
|
||
arg = nparam < 0;
|
||
nparam = abs(nparam);
|
||
|
||
if (!arg)
|
||
{
|
||
va_start(args, nparam);
|
||
push(nparam, args);
|
||
va_end(args);
|
||
}
|
||
|
||
result = FALSE;
|
||
|
||
// Observers before
|
||
|
||
LIST_for_each(obs, OBJECT_event(object)->observer)
|
||
{
|
||
parent = OBJECT_active_parent(obs);
|
||
if (!parent)
|
||
continue;
|
||
if (obs->after)
|
||
{
|
||
after = TRUE;
|
||
continue;
|
||
}
|
||
|
||
func_id = get_event_func_id(obs->event, event_id);
|
||
if (!func_id)
|
||
continue;
|
||
|
||
if (!OBJECT_is_valid(parent))
|
||
{
|
||
OBJECT_detach(object);
|
||
continue;
|
||
}
|
||
|
||
EXEC_dup(nparam);
|
||
result = raise_event(parent, object, func_id, nparam);
|
||
|
||
if (result)
|
||
goto __RETURN;
|
||
}
|
||
|
||
// Parent
|
||
|
||
parent = OBJECT_active_parent(object);
|
||
if (parent)
|
||
{
|
||
func_id = get_event_func_id(OBJECT_event(object)->event, event_id);
|
||
if (func_id)
|
||
{
|
||
#if DEBUG_EVENT
|
||
class = OBJECT_class(object);
|
||
printf("GB_Raise(%p, %d, %s)\n", object, event_id, class->event[event_id].name);
|
||
printf("func_id = %d parent = (%s %p)\n", func_id, parent->class->name, parent);
|
||
if (OBJECT_is_locked(parent))
|
||
printf("parent is locked!\n");
|
||
fflush(NULL);
|
||
#endif
|
||
|
||
if (!OBJECT_is_valid(parent))
|
||
OBJECT_detach(object);
|
||
else
|
||
{
|
||
EXEC_dup(nparam);
|
||
result = raise_event(parent, object, func_id, nparam);
|
||
if (result)
|
||
goto __RETURN;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Observers after
|
||
|
||
LIST_for_each(obs, OBJECT_event(object)->observer)
|
||
{
|
||
parent = OBJECT_active_parent(obs);
|
||
if (!parent)
|
||
continue;
|
||
if (!obs->after)
|
||
continue;
|
||
|
||
func_id = get_event_func_id(obs->event, event_id);
|
||
if (!func_id)
|
||
continue;
|
||
|
||
if (!OBJECT_is_valid(parent))
|
||
{
|
||
OBJECT_detach(object);
|
||
continue;
|
||
}
|
||
|
||
EXEC_dup(nparam);
|
||
result = raise_event(parent, object, func_id, nparam);
|
||
if (result)
|
||
goto __RETURN;
|
||
}
|
||
|
||
__RETURN:
|
||
|
||
RELEASE_MANY(SP, nparam);
|
||
OBJECT_UNREF(object, "GB_Raise");
|
||
/*}
|
||
CATCH
|
||
{
|
||
RELEASE_MANY(SP, nparam);
|
||
OBJECT_UNREF(object, "GB_Raise");
|
||
PROPAGATE();
|
||
}
|
||
END_TRY*/
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
int GB_GetFunction(GB_FUNCTION *_func, void *object, const char *name, const char *sign, const char *type)
|
||
{
|
||
GB_API_FUNCTION *func = (GB_API_FUNCTION *)_func;
|
||
char len_min, nparam, npvar;
|
||
TYPE *tsign;
|
||
TYPE tret;
|
||
int index;
|
||
CLASS *class;
|
||
int kind;
|
||
CLASS_DESC *desc;
|
||
bool error;
|
||
|
||
if (OBJECT_is_class(object))
|
||
{
|
||
class = (CLASS *)object;
|
||
kind = CD_STATIC_METHOD;
|
||
}
|
||
else
|
||
{
|
||
class = OBJECT_class(object);
|
||
kind = CD_METHOD;
|
||
}
|
||
|
||
CLASS_load(class);
|
||
|
||
index = CLASS_find_symbol(class, name);
|
||
if (index == NO_SYMBOL)
|
||
goto _NOT_FOUND;
|
||
|
||
desc = class->table[index].desc;
|
||
if (CLASS_DESC_get_type(desc) != kind)
|
||
goto _NOT_FOUND;
|
||
|
||
if (sign)
|
||
{
|
||
TYPE_signature_length(sign, &len_min, &nparam, &npvar);
|
||
tsign = NULL;
|
||
|
||
if (nparam)
|
||
{
|
||
ALLOC(&tsign, nparam * sizeof(TYPE), "GB_GetFunction");
|
||
tsign = TYPE_transform_signature(&tsign, sign, nparam);
|
||
}
|
||
|
||
error = TYPE_compare_signature(desc->method.signature, desc->method.npmax, tsign, nparam);
|
||
|
||
if (nparam)
|
||
FREE(&tsign, "GB_GetFunction");
|
||
|
||
if (error)
|
||
{
|
||
GB_Error("Parameters do not match");
|
||
goto _NOT_FOUND;
|
||
}
|
||
}
|
||
|
||
if (type)
|
||
{
|
||
tret = TYPE_from_string(&type);
|
||
if (tret != desc->method.type)
|
||
{
|
||
if (tret == T_VOID)
|
||
GB_Error("Must be a procedure");
|
||
else if (desc->method.type == T_VOID)
|
||
GB_Error("Must be a function");
|
||
else
|
||
GB_Error("Return type does not match");
|
||
|
||
goto _NOT_FOUND;
|
||
}
|
||
}
|
||
|
||
func->object = object;
|
||
func->desc = &desc->method;
|
||
|
||
if (!func->desc)
|
||
abort();
|
||
|
||
return 0;
|
||
|
||
_NOT_FOUND:
|
||
|
||
func->object = NULL;
|
||
func->desc = NULL;
|
||
return 1;
|
||
}
|
||
|
||
|
||
void *GB_GetClassInterface(void *_class, const char *_name)
|
||
{
|
||
CLASS_DESC *desc;
|
||
int index;
|
||
CLASS *class = (CLASS *)_class;
|
||
int len = strlen(_name);
|
||
char name[len + 4];
|
||
|
||
CLASS_load(class);
|
||
|
||
strcpy(name, "_@");
|
||
strcat(name, _name);
|
||
|
||
index = CLASS_find_symbol(class, name);
|
||
if (index == NO_SYMBOL)
|
||
goto __NOT_FOUND;
|
||
|
||
desc = class->table[index].desc;
|
||
if (CLASS_DESC_get_type(desc) != CD_CONSTANT)
|
||
goto __NOT_FOUND;
|
||
|
||
if (desc->constant.type != T_POINTER)
|
||
goto __NOT_FOUND;
|
||
|
||
return desc->constant.value._pointer;
|
||
|
||
__NOT_FOUND:
|
||
return NULL;
|
||
}
|
||
|
||
|
||
GB_VALUE *GB_Call(GB_FUNCTION *_func, int nparam, int release)
|
||
{
|
||
GB_API_FUNCTION *func = (GB_API_FUNCTION *)_func;
|
||
bool stop_event;
|
||
|
||
if (!func || !func->desc)
|
||
GB_Error("Unknown function call");
|
||
else
|
||
{
|
||
stop_event = GAMBAS_StopEvent;
|
||
call_method(func->object, func->desc, nparam);
|
||
_event_stopped = GAMBAS_StopEvent;
|
||
GAMBAS_StopEvent = stop_event;
|
||
|
||
if (release)
|
||
EXEC_release_return_value();
|
||
else
|
||
{
|
||
UNBORROW(RP);
|
||
TEMP = *RP;
|
||
RP->type = T_VOID;
|
||
}
|
||
}
|
||
|
||
return (GB_VALUE *)&TEMP;
|
||
}
|
||
|
||
|
||
int GB_GetEvent(void *class, char *name)
|
||
{
|
||
CLASS_DESC_EVENT *cd;
|
||
|
||
cd = CLASS_get_event_desc((CLASS *)class, name);
|
||
if (!cd)
|
||
return (-1);
|
||
else
|
||
return *cd->index;
|
||
}
|
||
|
||
|
||
char *GB_GetLastEventName()
|
||
{
|
||
return EVENT_Name;
|
||
}
|
||
|
||
|
||
int GB_Stopped(void)
|
||
{
|
||
return _event_stopped;
|
||
}
|
||
|
||
|
||
int GB_NParam(void)
|
||
{
|
||
return EXEC.nparvar;
|
||
}
|
||
|
||
|
||
int GB_IsProperty(void)
|
||
{
|
||
return EXEC.property;
|
||
}
|
||
|
||
|
||
const char *GB_GetUnknown(void)
|
||
{
|
||
return EXEC.unknown;
|
||
}
|
||
|
||
|
||
void GB_Error(const char *error, ...)
|
||
{
|
||
va_list args;
|
||
char *arg[8];
|
||
int i;
|
||
|
||
if (!error)
|
||
{
|
||
GAMBAS_Error = FALSE;
|
||
return;
|
||
}
|
||
|
||
va_start(args, error);
|
||
|
||
for (i = 0; i < 8; i++)
|
||
arg[i] = va_arg(args, char *);
|
||
|
||
ERROR_define(error, arg);
|
||
|
||
GAMBAS_Error = TRUE;
|
||
}
|
||
|
||
|
||
|
||
void GB_Ref(void *object)
|
||
{
|
||
#if TRACE_MEMORY
|
||
CLASS *save = CP;
|
||
CP = NULL;
|
||
#endif
|
||
|
||
if (object)
|
||
OBJECT_REF(object, "GB_Ref");
|
||
|
||
#if TRACE_MEMORY
|
||
CP = save;
|
||
#endif
|
||
}
|
||
|
||
|
||
void GB_Unref(void **object)
|
||
{
|
||
#if TRACE_MEMORY
|
||
CLASS *save = CP;
|
||
CP = NULL;
|
||
#endif
|
||
|
||
if (*object)
|
||
OBJECT_UNREF(*object, "GB_Unref");
|
||
|
||
#if TRACE_MEMORY
|
||
CP = save;
|
||
#endif
|
||
}
|
||
|
||
|
||
void GB_UnrefKeep(void **object, int delete)
|
||
{
|
||
#if TRACE_MEMORY
|
||
CLASS *save = CP;
|
||
CP = NULL;
|
||
#endif
|
||
|
||
if (*object != NULL)
|
||
{
|
||
if (delete)
|
||
{
|
||
OBJECT_UNREF(*object, "GB_UnrefKeep");
|
||
}
|
||
else
|
||
{
|
||
OBJECT_UNREF_KEEP(*object, "GB_UnrefKeep");
|
||
}
|
||
}
|
||
|
||
#if TRACE_MEMORY
|
||
CP = save;
|
||
#endif
|
||
}
|
||
|
||
|
||
void GB_Detach(void *object)
|
||
{
|
||
if (object)
|
||
OBJECT_detach(object);
|
||
}
|
||
|
||
|
||
void GB_Attach(void *object, void *parent, const char *name)
|
||
{
|
||
if (object)
|
||
OBJECT_attach(object, parent, name);
|
||
}
|
||
|
||
|
||
void GB_StopEnum(void)
|
||
{
|
||
/* Do not forget than event if we stop the enumeration, the return value
|
||
of _next will be converted
|
||
*/
|
||
//VALUE_default(&TEMP, *GAMBAS_ReturnType);
|
||
TEMP.type = T_VOID;
|
||
EXEC_enum->stop = TRUE;
|
||
}
|
||
|
||
|
||
void *GB_GetEnum(void)
|
||
{
|
||
return (void *)&EXEC_enum->data;
|
||
}
|
||
|
||
|
||
static void *_enum_object;
|
||
|
||
void GB_ListEnum(void *enum_object)
|
||
{
|
||
EXEC_enum = NULL;
|
||
_enum_object = enum_object;
|
||
}
|
||
|
||
|
||
int GB_NextEnum(void)
|
||
{
|
||
for(;;)
|
||
{
|
||
EXEC_enum = CENUM_get_next(EXEC_enum);
|
||
if (!EXEC_enum)
|
||
return TRUE;
|
||
if (EXEC_enum->enum_object == _enum_object)
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
void GB_StopAllEnum(void *enum_object)
|
||
{
|
||
GB_ListEnum(enum_object);
|
||
while (!GB_NextEnum())
|
||
GB_StopEnum();
|
||
}
|
||
|
||
|
||
void GB_Return(unsigned int type, ...)
|
||
{
|
||
static void *jump[16] = {
|
||
&&__VOID, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE,
|
||
&&__STRING, &&__STRING, &&__VARIANT, &&__ARRAY, &&__FUNCTION, &&__CLASS, &&__NULL
|
||
};
|
||
|
||
VALUE *ret = &TEMP;
|
||
va_list args;
|
||
|
||
va_start(args, type);
|
||
|
||
ret->type = type;
|
||
if (TYPE_is_object(type))
|
||
goto __OBJECT;
|
||
else
|
||
goto *jump[type];
|
||
|
||
__BOOLEAN:
|
||
|
||
ret->_integer.value = va_arg(args, int) ? (-1) : 0;
|
||
goto __CONV;
|
||
|
||
__BYTE:
|
||
|
||
ret->_integer.value = va_arg(args, int);
|
||
goto __CONV;
|
||
|
||
__SHORT:
|
||
|
||
ret->_integer.value = va_arg(args, int);
|
||
goto __CONV;
|
||
|
||
__INTEGER:
|
||
|
||
ret->_integer.value = va_arg(args, int);
|
||
goto __CONV;
|
||
|
||
__LONG:
|
||
|
||
ret->_long.value = va_arg(args, int64_t);
|
||
goto __CONV;
|
||
|
||
__SINGLE:
|
||
|
||
ret->_single.value = va_arg(args, double);
|
||
goto __CONV;
|
||
|
||
__FLOAT:
|
||
|
||
ret->_float.value = va_arg(args, double);
|
||
goto __CONV;
|
||
|
||
__DATE:
|
||
|
||
ret->_date.date = va_arg(args, int);
|
||
ret->_date.time = va_arg(args, int);
|
||
goto __CONV;
|
||
|
||
__OBJECT:
|
||
|
||
ret->_object.object = va_arg(args, void *);
|
||
goto __CONV;
|
||
|
||
__CLASS:
|
||
ret->_class.class = va_arg(args, CLASS *);
|
||
goto __CONV;
|
||
|
||
__CONV:
|
||
__STRING:
|
||
__VOID:
|
||
__VARIANT:
|
||
__ARRAY:
|
||
__FUNCTION:
|
||
__NULL:
|
||
return;
|
||
}
|
||
|
||
|
||
void GB_ReturnInteger(int val)
|
||
{
|
||
GB_Return(T_INTEGER, val);
|
||
}
|
||
|
||
|
||
void GB_ReturnLong(int64_t val)
|
||
{
|
||
GB_Return(T_LONG, val);
|
||
}
|
||
|
||
|
||
void GB_ReturnPointer(void *val)
|
||
{
|
||
GB_Return(T_POINTER, (intptr_t)val);
|
||
}
|
||
|
||
|
||
void GB_ReturnFloat(double val)
|
||
{
|
||
GB_Return(T_FLOAT, val);
|
||
}
|
||
|
||
|
||
void GB_ReturnDate(GB_DATE *date)
|
||
{
|
||
TEMP = *((VALUE *)date);
|
||
TEMP.type = T_DATE;
|
||
}
|
||
|
||
|
||
void GB_ReturnBoolean(int val)
|
||
{
|
||
GB_Return(T_BOOLEAN, val);
|
||
}
|
||
|
||
|
||
void GB_ReturnObject(void *val)
|
||
{
|
||
if (val == NULL)
|
||
GB_ReturnNull();
|
||
else
|
||
GB_Return(T_OBJECT, val);
|
||
}
|
||
|
||
|
||
void GB_ReturnPtr(unsigned int type, void *value)
|
||
{
|
||
if (type == T_VOID)
|
||
return;
|
||
|
||
if (!value)
|
||
VALUE_default(&TEMP, type);
|
||
else
|
||
VALUE_read(&TEMP, value, type);
|
||
}
|
||
|
||
|
||
void GB_ReturnSelf(void *object)
|
||
{
|
||
if (object)
|
||
GB_ReturnObject(object);
|
||
else
|
||
GB_Return(T_CLASS, NULL);
|
||
}
|
||
|
||
|
||
char *GB_ToZeroString(GB_STRING *src)
|
||
{
|
||
char *str;
|
||
|
||
STRING_new_temp(&str, src->value.addr + src->value.start, src->value.len);
|
||
|
||
if (str == NULL)
|
||
return "";
|
||
else
|
||
return str;
|
||
}
|
||
|
||
|
||
void GB_ReturnString(char *str)
|
||
{
|
||
TEMP.type = T_STRING;
|
||
TEMP._string.addr = str;
|
||
TEMP._string.start = 0;
|
||
TEMP._string.len = STRING_length(str);
|
||
|
||
if (TEMP._string.len == 0)
|
||
TEMP._string.addr = 0;
|
||
}
|
||
|
||
|
||
void GB_ReturnConstString(const char *str, int len)
|
||
{
|
||
TEMP.type = T_CSTRING;
|
||
TEMP._string.addr = (char *)str;
|
||
TEMP._string.start = 0;
|
||
TEMP._string.len = len;
|
||
|
||
if (TEMP._string.len == 0)
|
||
TEMP._string.addr = 0;
|
||
}
|
||
|
||
|
||
void GB_ReturnConstZeroString(const char *str)
|
||
{
|
||
int len;
|
||
|
||
if (str)
|
||
len = strlen(str);
|
||
else
|
||
len = 0;
|
||
|
||
GB_ReturnConstString(str, len);
|
||
}
|
||
|
||
|
||
void GB_ReturnNewString(const char *src, int len)
|
||
{
|
||
char *str;
|
||
|
||
STRING_new_temp(&str, src, len);
|
||
GB_ReturnString(str);
|
||
}
|
||
|
||
|
||
void GB_ReturnNewZeroString(const char *src)
|
||
{
|
||
GB_ReturnNewString(src, 0);
|
||
}
|
||
|
||
|
||
void GB_ReturnNull(void)
|
||
{
|
||
TEMP.type = T_NULL;
|
||
}
|
||
|
||
|
||
void *GB_GetClass(void *object)
|
||
{
|
||
if (object)
|
||
return OBJECT_class(object);
|
||
else
|
||
return EXEC.class;
|
||
}
|
||
|
||
|
||
char *GB_GetClassName(void *object)
|
||
{
|
||
CLASS *class = GB_GetClass(object);
|
||
return class->name;
|
||
}
|
||
|
||
|
||
int GB_Is(void *object, void *class)
|
||
{
|
||
CLASS *ob_class;
|
||
|
||
if (!object)
|
||
return FALSE;
|
||
|
||
ob_class = OBJECT_class(object);
|
||
|
||
return ((ob_class == class) || CLASS_inherits(ob_class, class));
|
||
}
|
||
|
||
|
||
int GB_LoadFile(const char *path, int lenp, char **addr, int *len)
|
||
{
|
||
int ret = 0;
|
||
|
||
//fprintf(stderr, "GB_LoadFile: %.*s\n", lenp ? lenp : strlen(path), path);
|
||
|
||
TRY
|
||
{
|
||
*addr = 0;
|
||
*len = 0;
|
||
|
||
STREAM_map(STRING_conv_file_name(path, lenp), addr, len);
|
||
}
|
||
CATCH
|
||
{
|
||
if (*addr)
|
||
STREAM_unmap(*addr, *len);
|
||
|
||
GAMBAS_Error = TRUE;
|
||
ret = 1;
|
||
}
|
||
END_TRY
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
void GB_Store(GB_TYPE type, GB_VALUE *src, void *dst)
|
||
{
|
||
if (src != NULL)
|
||
{
|
||
/* Ne marche que parce que value->type == type apr<70> un VALUE_read()
|
||
Sinon il y'aurait des probl<62>es de r<><72>ences - VALUE_write faisant
|
||
appel <20>VALUE_conv() (ceci est un ancien commentaire)
|
||
|
||
=> src->type doit <20>re <20>al <20>type
|
||
*/
|
||
VALUE_write((VALUE *)src, dst, type);
|
||
}
|
||
else
|
||
{
|
||
VALUE_free(dst, type);
|
||
}
|
||
}
|
||
|
||
|
||
void GB_StoreString(GB_STRING *src, char **dst)
|
||
{
|
||
char *str;
|
||
|
||
STRING_unref(dst);
|
||
if (src)
|
||
{
|
||
STRING_new(&str, src->value.addr + src->value.start, src->value.len);
|
||
*dst = str;
|
||
}
|
||
else
|
||
*dst = NULL;
|
||
}
|
||
|
||
void GB_StoreObject(GB_OBJECT *src, void **dst)
|
||
{
|
||
void *object;
|
||
|
||
if (src)
|
||
object = src->value;
|
||
else
|
||
object = NULL;
|
||
|
||
if (object)
|
||
GB_Ref(object);
|
||
|
||
GB_Unref(dst);
|
||
*dst = object;
|
||
}
|
||
|
||
void GB_StoreVariant(GB_VARIANT *src, void *dst)
|
||
{
|
||
/*GB_Store(GB_T_VARIANT, (GB_VALUE *)src, dst);*/
|
||
if (src)
|
||
{
|
||
VALUE_write((VALUE *)src, dst, T_VARIANT);
|
||
|
||
/*VARIANT_keep((VARIANT *)&src->value);
|
||
VARIANT_free((VARIANT *)dst);
|
||
*((VARIANT *)dst) = *((VARIANT *)&src->value);*/
|
||
}
|
||
else
|
||
{
|
||
VARIANT_free((VARIANT *)dst);
|
||
((VARIANT *)dst)->type = T_NULL;
|
||
}
|
||
}
|
||
|
||
|
||
void GB_Watch(int fd, int flag, void *callback, intptr_t param)
|
||
{
|
||
HOOK_DEFAULT(watch, WATCH_watch)(fd, flag, callback, param);
|
||
}
|
||
|
||
|
||
int GB_New(void **object, void *class, const char *name, void *parent)
|
||
{
|
||
if (name && !parent)
|
||
{
|
||
parent = OP;
|
||
if (!parent)
|
||
parent = CP;
|
||
}
|
||
|
||
if (!((CLASS *)class)->no_create)
|
||
OBJECT_create(object, class, name, parent, 0);
|
||
else
|
||
{
|
||
OBJECT_new(object, class, name, parent);
|
||
OBJECT_UNREF_KEEP(*object, "GB_New");
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
int GB_CheckObject(void *object)
|
||
{
|
||
CLASS *class;
|
||
|
||
if (object == NULL)
|
||
{
|
||
GB_Error((char *)E_NULL);
|
||
return TRUE;
|
||
}
|
||
|
||
class = OBJECT_class(object);
|
||
|
||
if (class->check && (*(class->check))(object))
|
||
{
|
||
GB_Error((char *)E_IOBJECT);
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
const char *GB_AppName(void)
|
||
{
|
||
return PROJECT_name;
|
||
}
|
||
|
||
const char *GB_AppPath(void)
|
||
{
|
||
return PROJECT_path;
|
||
}
|
||
|
||
const char *GB_AppTitle(void)
|
||
{
|
||
return LOCAL_gettext(PROJECT_title);
|
||
}
|
||
|
||
const char *GB_AppVersion(void)
|
||
{
|
||
return PROJECT_version;
|
||
}
|
||
|
||
const char *GB_AppStartup(void)
|
||
{
|
||
return PROJECT_startup;
|
||
}
|
||
|
||
|
||
void *GB_Eval(void *expr, void *func)
|
||
{
|
||
GAMBAS_Error = EVAL_expression((EXPRESSION *)expr, (EVAL_FUNCTION)func);
|
||
if (GAMBAS_Error)
|
||
return NULL;
|
||
else
|
||
return &TEMP;
|
||
}
|
||
|
||
|
||
void GB_Alloc(void **addr, int len)
|
||
{
|
||
ALLOC(addr, len, "GB_Alloc");
|
||
}
|
||
|
||
void GB_Free(void **addr)
|
||
{
|
||
FREE(addr, "GB_Free");
|
||
}
|
||
|
||
void GB_Realloc(void **addr, int len)
|
||
{
|
||
REALLOC(addr, len, "GB_Realloc");
|
||
}
|
||
|
||
|
||
int GB_Conv(GB_VALUE *arg, GB_TYPE type)
|
||
{
|
||
int ret = 0;
|
||
|
||
TRY
|
||
{
|
||
VALUE_conv((VALUE *)arg, (GB_TYPE)type);
|
||
}
|
||
CATCH
|
||
{
|
||
ret = 1;
|
||
GAMBAS_Error = TRUE;
|
||
}
|
||
END_TRY
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
int GB_StringLength(const char *str)
|
||
{
|
||
return STRING_length(str);
|
||
}
|
||
|
||
|
||
int GB_NumberToString(int local, double value, const char *format, char **str, int *len)
|
||
{
|
||
return
|
||
LOCAL_format_number
|
||
(
|
||
value,
|
||
format ? LF_USER : LF_GENERAL_NUMBER,
|
||
format,
|
||
format ? strlen(format) : 0,
|
||
str, len, local != 0
|
||
);
|
||
}
|
||
|
||
|
||
void GB_HashTableNew(GB_HASHTABLE *hash, int mode)
|
||
{
|
||
HASH_TABLE_create((HASH_TABLE **)hash, sizeof(void *), mode);
|
||
}
|
||
|
||
void GB_HashTableAdd(GB_HASHTABLE hash, const char *key, int len, void *data)
|
||
{
|
||
if (len <= 0)
|
||
len = strlen(key);
|
||
|
||
*((void **)HASH_TABLE_insert((HASH_TABLE *)hash, key, len)) = data;
|
||
}
|
||
|
||
void GB_HashTableRemove(GB_HASHTABLE hash, const char *key, int len)
|
||
{
|
||
if (len <= 0)
|
||
len = strlen(key);
|
||
|
||
HASH_TABLE_remove((HASH_TABLE *)hash, key, len);
|
||
}
|
||
|
||
int GB_HashTableGet(GB_HASHTABLE hash, const char *key, int len, void **data)
|
||
{
|
||
void **pdata;
|
||
|
||
if (len <= 0)
|
||
len = strlen(key);
|
||
|
||
pdata = (void **)HASH_TABLE_lookup((HASH_TABLE *)hash, key, len);
|
||
if (pdata)
|
||
{
|
||
*data = *pdata;
|
||
return 0;
|
||
}
|
||
else
|
||
return 1;
|
||
}
|
||
|
||
|
||
void GB_HashTableEnum(GB_HASHTABLE hash, GB_HASHTABLE_ENUM_FUNC func)
|
||
{
|
||
HASH_ENUM iter;
|
||
void **data;
|
||
|
||
CLEAR(&iter);
|
||
|
||
for(;;)
|
||
{
|
||
data = (void **)HASH_TABLE_next((HASH_TABLE *)hash, &iter);
|
||
if (!data)
|
||
break;
|
||
|
||
(*func)(*data);
|
||
}
|
||
}
|
||
|
||
void GB_NewArray(void *pdata, int size, int count)
|
||
{
|
||
ARRAY_create_with_size(pdata, size, 16);
|
||
ARRAY_add_data(pdata, count, TRUE);
|
||
}
|
||
|
||
|
||
int GB_CountArray(void *data)
|
||
{
|
||
return ARRAY_count(data);
|
||
}
|
||
|
||
|
||
void *GB_Add(void *pdata)
|
||
{
|
||
return ARRAY_add_void(pdata);
|
||
}
|
||
|
||
|
||
void GB_TempString(char **str, char *src, int len)
|
||
{
|
||
STRING_new_temp(str, src, len);
|
||
}
|
||
|
||
void GB_FreeString(char **str)
|
||
{
|
||
STRING_unref(str);
|
||
*str = NULL;
|
||
}
|
||
|
||
bool GB_ConvString(char **result, const char *str, int len, const char *src, const char *dst)
|
||
{
|
||
bool err = FALSE;
|
||
|
||
TRY
|
||
{
|
||
STRING_conv(result, str, len, src, dst, TRUE);
|
||
}
|
||
CATCH
|
||
{
|
||
err = TRUE;
|
||
GAMBAS_Error = TRUE;
|
||
}
|
||
END_TRY
|
||
|
||
return err;
|
||
}
|
||
|
||
|
||
char *GB_SystemCharset(void)
|
||
{
|
||
return LOCAL_encoding;
|
||
}
|
||
|
||
char *GB_SystemDomainName(void)
|
||
{
|
||
char host[256], domain[256];
|
||
|
||
if (gethostname(host, sizeof(host) - 1))
|
||
return "";
|
||
|
||
if (getdomainname(domain, sizeof(domain) - 1))
|
||
return "";
|
||
|
||
if ((strlen(host) + strlen(domain)) > COMMON_BUF_MAX)
|
||
return "";
|
||
|
||
*COMMON_buffer = 0;
|
||
if (*domain && strcmp(domain, "(none)"))
|
||
{
|
||
strcpy(COMMON_buffer, domain);
|
||
strcat(COMMON_buffer, ".");
|
||
}
|
||
strcat(COMMON_buffer, host);
|
||
|
||
return COMMON_buffer;
|
||
}
|
||
|
||
int GB_IsRightToLeft(void)
|
||
{
|
||
return LOCAL_local.rtl;
|
||
}
|
||
|
||
|
||
/*void GB_StreamInit(GB_STREAM *stream, int fd)
|
||
{
|
||
STREAM *s = (STREAM *)stream;
|
||
|
||
s->type = &STREAM_direct;
|
||
s->direct.fd = fd;
|
||
}*/
|
||
|
||
void GB_StreamSetBytesRead(GB_STREAM *stream, int length)
|
||
{
|
||
STREAM_eff_read = length;
|
||
}
|
||
|
||
void GB_StreamSetSwapping(GB_STREAM *stream, int swap)
|
||
{
|
||
((STREAM *)stream)->common.swap = swap;
|
||
}
|
||
|
||
int GB_StreamBlock(GB_STREAM *stream, int block)
|
||
{
|
||
STREAM *st = (STREAM *)stream;
|
||
int old = STREAM_is_blocking(st);
|
||
STREAM_blocking(st, block);
|
||
return old;
|
||
}
|
||
|
||
int GB_tolower(int c)
|
||
{
|
||
return tolower(c);
|
||
}
|
||
|
||
int GB_toupper(int c)
|
||
{
|
||
return toupper(c);
|
||
}
|
||
|
||
char *GB_GetTempDir(void)
|
||
{
|
||
return FILE_make_temp(NULL, NULL);
|
||
}
|
||
|
||
char *GB_RealFileName(const char *name, int len)
|
||
{
|
||
char *path = STRING_conv_file_name(name, len);
|
||
char *real;
|
||
char *temp;
|
||
|
||
if (!STREAM_in_archive(path))
|
||
return path;
|
||
|
||
temp = FILE_make_temp(NULL, NULL);
|
||
STRING_new_temp(&real, NULL, strlen(temp) + strlen(path) + strlen("/data/"));
|
||
snprintf(real, strlen(temp) + strlen(path) + strlen("/data/"), "%s/data/%s", temp, path);
|
||
|
||
if (!FILE_exist(real))
|
||
{
|
||
TRY
|
||
{
|
||
FILE_make_path_dir(real);
|
||
FILE_copy(path, real);
|
||
}
|
||
CATCH
|
||
{
|
||
real = path;
|
||
}
|
||
END_TRY
|
||
}
|
||
|
||
//fprintf(stderr, "GB.RealFileName: %s -> %s\n", path, real);
|
||
|
||
return real;
|
||
}
|
||
|
||
void GB_PrintData(GB_TYPE type, void *addr)
|
||
{
|
||
VALUE value;
|
||
|
||
VALUE_read(&value, addr, (TYPE)type);
|
||
PRINT_value(&value);
|
||
}
|
||
|
||
|
||
const char *GB_CurrentComponent()
|
||
{
|
||
ARCHIVE *arch;
|
||
|
||
ARCHIVE_get_current(&arch);
|
||
return arch->name ? arch->name : "";
|
||
}
|
||
|
||
|
||
void *GB_DebugGetExec(void)
|
||
{
|
||
return &EXEC_current;
|
||
}
|
||
|
||
|
||
int GB_ExistClass(const char *name)
|
||
{
|
||
return CLASS_look_global(name, strlen(name)) != NULL;
|
||
}
|
||
|
||
|
||
int GB_ExistClassLocal(const char *name)
|
||
{
|
||
return CLASS_look(name, strlen(name)) != NULL;
|
||
}
|
||
|
||
#if 0
|
||
int GB_ImageCreate(GB_IMAGE *image, void *data, int width, int height, int format)
|
||
{
|
||
GB_IMAGE_INFO info;
|
||
|
||
if (!EXEC_Hook.image)
|
||
{
|
||
GB_Error("No image provider");
|
||
return TRUE;
|
||
}
|
||
|
||
if (image)
|
||
*image = NULL;
|
||
|
||
info.width = width;
|
||
info.height = height;
|
||
info.format = format;
|
||
info.data = data;
|
||
|
||
return (*EXEC_Hook.image)(image, &info);
|
||
}
|
||
|
||
void GB_ImageInfo(GB_IMAGE image, GB_IMAGE_INFO *info)
|
||
{
|
||
if (!EXEC_Hook.image)
|
||
{
|
||
GB_Error("No image provider");
|
||
return;
|
||
}
|
||
|
||
if (image)
|
||
(*EXEC_Hook.image)(&image, info);
|
||
}
|
||
|
||
int GB_PictureCreate(GB_PICTURE *picture, void *data, int width, int height, int format)
|
||
{
|
||
GB_PICTURE_INFO info;
|
||
|
||
if (!EXEC_Hook.picture)
|
||
{
|
||
GB_Error("No picture provider");
|
||
return TRUE;
|
||
}
|
||
|
||
info.width = width;
|
||
info.height = height;
|
||
info.format = format;
|
||
info.data = data;
|
||
|
||
return (*EXEC_Hook.picture)(picture, &info);
|
||
}
|
||
|
||
void GB_PictureInfo(GB_PICTURE picture, GB_PICTURE_INFO *info)
|
||
{
|
||
if (!EXEC_Hook.image)
|
||
{
|
||
GB_Error("No image provider");
|
||
return;
|
||
}
|
||
|
||
if (picture)
|
||
(*EXEC_Hook.picture)(&picture, info);
|
||
}
|
||
|
||
void GB_ImageConvert(void *dst, int dst_format, void *src, int src_format, int w, int h)
|
||
{
|
||
register char *s = (char *)src;
|
||
register char *d = (char *)dst;
|
||
register char *dm = &d[w * h * 4];
|
||
|
||
if (dst_format == GB_IMAGE_BGRA || dst_format == GB_IMAGE_BGRX)
|
||
{
|
||
switch (src_format)
|
||
{
|
||
case GB_IMAGE_BGRA: case GB_IMAGE_BGRX:
|
||
goto __0123;
|
||
|
||
case GB_IMAGE_ARGB: case GB_IMAGE_XRGB:
|
||
goto __3210;
|
||
|
||
case GB_IMAGE_RGBA: case GB_IMAGE_RGBX:
|
||
goto __2103;
|
||
|
||
case GB_IMAGE_ABGR: case GB_IMAGE_XBGR:
|
||
goto __1230;
|
||
|
||
case GB_IMAGE_BGR:
|
||
goto __012X;
|
||
|
||
case GB_IMAGE_RGB:
|
||
goto __210X;
|
||
}
|
||
}
|
||
else if (dst_format == GB_IMAGE_RGBA || dst_format == GB_IMAGE_RGBX)
|
||
{
|
||
switch (src_format)
|
||
{
|
||
case GB_IMAGE_RGBA: case GB_IMAGE_RGBX:
|
||
goto __0123;
|
||
|
||
case GB_IMAGE_ABGR: case GB_IMAGE_XBGR:
|
||
goto __3210;
|
||
|
||
case GB_IMAGE_BGRA: case GB_IMAGE_BGRX:
|
||
goto __2103;
|
||
|
||
case GB_IMAGE_ARGB: case GB_IMAGE_XRGB:
|
||
goto __1230;
|
||
|
||
case GB_IMAGE_RGB:
|
||
goto __012X;
|
||
|
||
case GB_IMAGE_BGR:
|
||
goto __210X;
|
||
}
|
||
}
|
||
|
||
__0123:
|
||
|
||
memcpy(dst, src, w * h * 4);
|
||
return;
|
||
|
||
__3210:
|
||
|
||
while (d < dm)
|
||
{
|
||
d[0] = s[3];
|
||
d[1] = s[2];
|
||
d[2] = s[1];
|
||
d[3] = s[0];
|
||
s += 4;
|
||
d += 4;
|
||
}
|
||
return;
|
||
|
||
__2103:
|
||
|
||
while (d < dm)
|
||
{
|
||
d[0] = s[2];
|
||
d[1] = s[1];
|
||
d[2] = s[0];
|
||
d[3] = s[3];
|
||
s += 4;
|
||
d += 4;
|
||
}
|
||
return;
|
||
|
||
__1230:
|
||
|
||
while (d < dm)
|
||
{
|
||
d[0] = s[1];
|
||
d[1] = s[2];
|
||
d[2] = s[3];
|
||
d[3] = s[0];
|
||
s += 4;
|
||
d += 4;
|
||
}
|
||
return;
|
||
|
||
__012X:
|
||
|
||
while (d < dm)
|
||
{
|
||
d[0] = s[0];
|
||
d[1] = s[1];
|
||
d[2] = s[2];
|
||
d[3] = 0xFF;
|
||
s += 3;
|
||
d += 4;
|
||
}
|
||
return;
|
||
|
||
__210X:
|
||
|
||
while (d < dm)
|
||
{
|
||
d[0] = s[2];
|
||
d[1] = s[1];
|
||
d[2] = s[0];
|
||
d[3] = 0xFF;
|
||
s += 3;
|
||
d += 4;
|
||
}
|
||
return;
|
||
}
|
||
#endif
|