mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-23 16:43:58 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
358c940763 | ||
|
|
b3d6c70a45 | ||
|
|
5fc1c1101e | ||
|
|
f336b8401b | ||
|
|
78a0a8addf | ||
|
|
be5f46f92d | ||
|
|
07592ad802 | ||
|
|
1764c47131 | ||
|
|
f83c92d91b | ||
|
|
bf85472935 | ||
|
|
ff6856ec1f | ||
|
|
a4d532f85e |
+2
-1
@@ -4,6 +4,8 @@
|
||||
*.al
|
||||
*.a
|
||||
*.so
|
||||
\#
|
||||
am--include-marker
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps/
|
||||
@@ -23,7 +25,6 @@ Makefile.in
|
||||
/*config.h
|
||||
/*config.h.in
|
||||
/*config.h.in~
|
||||
|
||||
/src/font/utils/emoji/
|
||||
/src/font/utils/ucd/
|
||||
/src/sysres/font_list
|
||||
|
||||
+22
-1
@@ -1,5 +1,8 @@
|
||||
# Release Notes
|
||||
|
||||
- [Version 5.0.2](#version-502)
|
||||
+ [What's new in version 5.0.2](#whats-new-in-version-502)
|
||||
|
||||
- [Version 5.0.0](#version-500)
|
||||
+ [What's new in version 5.0.0](#whats-new-in-version-500)
|
||||
+ [Compositing schema](#compositing-schema)
|
||||
@@ -10,6 +13,24 @@
|
||||
+ [Changes leading to incompatibility](#changes-leading-to-incompatibility)
|
||||
+ [Deprecated APIs](#deprecated-apis)
|
||||
|
||||
## Version 5.0.2
|
||||
|
||||
The MiniGUI development team announces the availability of MiniGUI 5.0.2,
|
||||
which is the bug fixing release of MiniGUI 5.0.x.
|
||||
|
||||
### What's new in version 5.0.2
|
||||
|
||||
In this version, we tuned some code for GCC 9 and fixed some bugs:
|
||||
|
||||
* BUGFIXING:
|
||||
- Initialize `cfg_res_path` in function `__sysres_get_system_res_path()`.
|
||||
- Always return TRUE in `subtract_rgn_by_node()`.
|
||||
* ADJUSTMENTS:
|
||||
- Use upstream Harfbuzz for glyph shaping of complex scripts instead
|
||||
of the modified version.
|
||||
* TUNING:
|
||||
- Tune some code to depress compilation warnings.
|
||||
|
||||
## Version 5.0.0
|
||||
|
||||
The MiniGUI development team announces the availability of MiniGUI 5.0.0,
|
||||
@@ -63,7 +84,7 @@ exciting features for MiniGUI:
|
||||
* ADJUSTMENTS:
|
||||
- `g_rcScr` now is defined a macro calling function `GetScreenRect()`.
|
||||
- `mgIsServer` now is define a macro calling function `IsServer()`.
|
||||
* TUNNING
|
||||
* TUNING
|
||||
- Tune the `drm` (DRM) engine to support MiniGUI-Processes runtime mode
|
||||
and compositing schema.
|
||||
- Tune the `fbcon` (Linux Frame Buffer) engine to support compositing schema.
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ(2.60)
|
||||
AC_INIT(libminigui, 5.0.0)
|
||||
AC_INIT(libminigui, 5.0.2)
|
||||
AC_CONFIG_SRCDIR(src/main/main.c)
|
||||
|
||||
dnl Set various version strings - taken gratefully from the SDL sources
|
||||
@@ -16,9 +16,9 @@ dnl Set various version strings - taken gratefully from the SDL sources
|
||||
#
|
||||
MINIGUI_MAJOR_VERSION=5
|
||||
MINIGUI_MINOR_VERSION=0
|
||||
MINIGUI_MICRO_VERSION=0
|
||||
MINIGUI_INTERFACE_AGE=0
|
||||
MINIGUI_BINARY_AGE=0
|
||||
MINIGUI_MICRO_VERSION=2
|
||||
MINIGUI_INTERFACE_AGE=2
|
||||
MINIGUI_BINARY_AGE=2
|
||||
MINIGUI_VERSION=$MINIGUI_MAJOR_VERSION.$MINIGUI_MINOR_VERSION.$MINIGUI_MICRO_VERSION
|
||||
|
||||
AC_SUBST(MINIGUI_MAJOR_VERSION)
|
||||
@@ -94,7 +94,7 @@ osname="unspecified"
|
||||
runtime_mode="procs"
|
||||
compositing_schema="no"
|
||||
virtual_window="no"
|
||||
use_shmopen="no"
|
||||
use_shmopen="yes"
|
||||
mgslice_use_fallback="no"
|
||||
|
||||
incore_res="no"
|
||||
@@ -2143,7 +2143,7 @@ if test "x$build_ttf_support" = "xyes"; then
|
||||
if test "x$build_complex_scripts" = "xyes"; then
|
||||
dnl Check for HarfBuzz library
|
||||
AC_CHECK_LIB(harfbuzz, hb_version,
|
||||
DEP_LIBS="$DEP_LIBS -lharfbuzzex -lfreetype",
|
||||
DEP_LIBS="$DEP_LIBS -lharfbuzz -lfreetype",
|
||||
build_complex_scripts="no; support for complex scripts requires libharfbuzz")
|
||||
else
|
||||
DEP_LIBS="$DEP_LIBS -lfreetype",
|
||||
@@ -2223,7 +2223,7 @@ if test "x$build_complex_scripts" = "xyes"; then
|
||||
[ --with-hb-includes=DIR where the HarfBuzz includes are])
|
||||
|
||||
if test "x$with_hb_includes" = "x"; then
|
||||
HB_INC_DIR="-I/usr/local/include/harfbuzz"
|
||||
HB_INC_DIR="-I/usr/include/harfbuzz"
|
||||
else
|
||||
HB_INC_DIR="-I$with_hb_includes"
|
||||
fi
|
||||
|
||||
@@ -1433,10 +1433,12 @@ static LRESULT NewToolbarCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARA
|
||||
item_info->add_data = item->add_data;
|
||||
|
||||
if (item_info->which & MTB_WHICH_TEXT)
|
||||
strncpy (item_info->text, item->text, NTB_TEXT_LEN);
|
||||
//strncpy (item_info->text, item->text, NTB_TEXT_LEN);
|
||||
strcpy (item_info->text, item->text);
|
||||
|
||||
if (item_info->which & MTB_WHICH_TIP)
|
||||
strncpy (item_info->tip, item->tip, NTB_TIP_LEN);
|
||||
//strncpy (item_info->tip, item->tip, NTB_TIP_LEN);
|
||||
strcpy (item_info->tip, item->tip);
|
||||
|
||||
return NTB_OKAY;
|
||||
}
|
||||
|
||||
+11
-13
@@ -1012,8 +1012,9 @@ void GUIAPI DestroyDynamicDevFont (DEVFONT** devfont)
|
||||
{
|
||||
char font_name [LEN_UNIDEVFONT_NAME + 1];
|
||||
|
||||
memset(font_name, 0, LEN_UNIDEVFONT_NAME + 1);
|
||||
strncpy(font_name, (*devfont)->name, LEN_UNIDEVFONT_NAME);
|
||||
//memset(font_name, 0, LEN_UNIDEVFONT_NAME + 1);
|
||||
//strncpy(font_name, (*devfont)->name, LEN_UNIDEVFONT_NAME);
|
||||
strcpy(font_name, (*devfont)->name);
|
||||
|
||||
font_DelDevFont (font_name);
|
||||
*devfont = NULL;
|
||||
@@ -1069,25 +1070,22 @@ static BOOL init_or_term_specifical_fonts (char* etc_section, BOOL is_unload)
|
||||
added_num ++;
|
||||
}
|
||||
else {
|
||||
/* [DK] Fix Bug #4801, which introduce a absolute path check error in Windows,
|
||||
* first to load from sytem res path, else load it directly(relative or absolute path).*/
|
||||
if ((add_dev_font (font_name, font_file, TRUE)) == TRUE)
|
||||
/* [DK] Fix Bug #4801, which introduce an absolute path check error in Windows,
|
||||
* first to load from sytem res path, else load it directly (relative or absolute path).*/
|
||||
if (add_dev_font (font_name, font_file, TRUE))
|
||||
added_num++;
|
||||
else if ((0 == __mg_path_joint(font_path, MAX_PATH + 1,
|
||||
__sysres_get_system_res_path(), font_file))
|
||||
&& ((add_dev_font (font_name, font_path, TRUE)) == TRUE))
|
||||
__sysres_get_system_res_path(), font_file)) &&
|
||||
add_dev_font (font_name, font_path, TRUE))
|
||||
added_num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_unload || added_num > 0 || added_num == font_num)
|
||||
{
|
||||
if (is_unload || added_num > 0 || added_num == font_num) {
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL font_InitSpecificalFonts (char* etc_section)
|
||||
|
||||
@@ -120,47 +120,42 @@ hb_minigui_unicode_decompose (hb_unicode_funcs_t *ufuncs,
|
||||
return UCharDecompose(ab, a, b);
|
||||
}
|
||||
|
||||
static hb_unicode_funcs_t *_funcs;
|
||||
static hb_unicode_funcs_t *get_unicode_funcs(void)
|
||||
{
|
||||
if (_funcs)
|
||||
return _funcs;
|
||||
|
||||
_funcs = hb_unicode_funcs_create (NULL);
|
||||
|
||||
hb_unicode_funcs_set_combining_class_func (_funcs,
|
||||
hb_minigui_unicode_combining_class, NULL, NULL);
|
||||
hb_unicode_funcs_set_general_category_func (_funcs,
|
||||
hb_minigui_unicode_general_category, NULL, NULL);
|
||||
hb_unicode_funcs_set_mirroring_func (_funcs,
|
||||
hb_minigui_unicode_mirroring, NULL, NULL);
|
||||
hb_unicode_funcs_set_script_func (_funcs,
|
||||
hb_minigui_unicode_script, NULL, NULL);
|
||||
hb_unicode_funcs_set_compose_func (_funcs,
|
||||
hb_minigui_unicode_compose, NULL, NULL);
|
||||
hb_unicode_funcs_set_decompose_func (_funcs,
|
||||
hb_minigui_unicode_decompose, NULL, NULL);
|
||||
|
||||
hb_unicode_funcs_make_immutable (_funcs);
|
||||
|
||||
return _funcs;
|
||||
}
|
||||
|
||||
typedef hb_unicode_funcs_t *(*hb_get_unicode_funcs) (void);
|
||||
extern hb_get_unicode_funcs __hb_extern_get_unicode_funcs;
|
||||
/* extern hb_unicode_funcs_t *__mg_hb_unifuncs */
|
||||
hb_unicode_funcs_t *__mg_hb_unifuncs;
|
||||
|
||||
void __mg_init_harzbuff_funcs(void)
|
||||
{
|
||||
_DBG_PRINTF("%s: called\n", __FUNCTION__);
|
||||
__hb_extern_get_unicode_funcs = get_unicode_funcs;
|
||||
|
||||
if (__mg_hb_unifuncs)
|
||||
return;
|
||||
|
||||
__mg_hb_unifuncs = hb_unicode_funcs_create (NULL);
|
||||
|
||||
hb_unicode_funcs_set_combining_class_func (__mg_hb_unifuncs,
|
||||
hb_minigui_unicode_combining_class, NULL, NULL);
|
||||
hb_unicode_funcs_set_general_category_func (__mg_hb_unifuncs,
|
||||
hb_minigui_unicode_general_category, NULL, NULL);
|
||||
hb_unicode_funcs_set_mirroring_func (__mg_hb_unifuncs,
|
||||
hb_minigui_unicode_mirroring, NULL, NULL);
|
||||
hb_unicode_funcs_set_script_func (__mg_hb_unifuncs,
|
||||
hb_minigui_unicode_script, NULL, NULL);
|
||||
hb_unicode_funcs_set_compose_func (__mg_hb_unifuncs,
|
||||
hb_minigui_unicode_compose, NULL, NULL);
|
||||
hb_unicode_funcs_set_decompose_func (__mg_hb_unifuncs,
|
||||
hb_minigui_unicode_decompose, NULL, NULL);
|
||||
|
||||
hb_unicode_funcs_make_immutable (__mg_hb_unifuncs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void __mg_term_harzbuff_funcs(void)
|
||||
{
|
||||
_DBG_PRINTF("%s: called\n", __FUNCTION__);
|
||||
|
||||
if (_funcs) {
|
||||
hb_unicode_funcs_destroy(_funcs);
|
||||
if (__mg_hb_unifuncs) {
|
||||
hb_unicode_funcs_destroy(__mg_hb_unifuncs);
|
||||
}
|
||||
else {
|
||||
_ERR_PRINTF("%s: hb_unicode_funcs_t object is NULL\n",
|
||||
|
||||
@@ -1243,11 +1243,9 @@ static int wait_event_ex (int maxfd, fd_set *in, fd_set *out, fd_set *except,
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
default:
|
||||
_DBG_PRINTF("IAL>LIBINPUT: got a UNKNOWN event type: %d\n", type);
|
||||
_WRN_PRINTF("IAL>LIBINPUT: got a UNKNOWN event type: %d\n", type);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
@@ -188,7 +188,7 @@ static BOOL subtract_rgn_by_node (PCLIPRGN region, const ZORDERINFO* zi,
|
||||
else
|
||||
SubtractClipRect(region, &(node->rc));
|
||||
|
||||
return !IsEmptyClipRgn(region);
|
||||
return TRUE; // !IsEmptyClipRgn(region); We must return TRUE for this callback.
|
||||
}
|
||||
|
||||
#else /* not defined _MGSCHEMA_COMPOSITING */
|
||||
@@ -505,8 +505,13 @@ static BOOL _cb_update_znode (void* context,
|
||||
{
|
||||
const RECT* rc = (RECT*)context;
|
||||
|
||||
_DBG_PRINTF ("Checking window (%s), visibility: %s, referred: %s\n", znode->caption,
|
||||
(znode->flags & ZOF_VISIBLE)? "TRUE" : "FALSE",
|
||||
(znode->flags & ZOF_IF_REFERENCE)? "TRUE" : "FALSE");
|
||||
|
||||
if (znode->flags & ZOF_VISIBLE &&
|
||||
znode->flags & ZOF_IF_REFERENCE) {
|
||||
_DBG_PRINTF ("Widnow (%s) will be updated\n", znode->caption);
|
||||
update_client_window (znode, rc);
|
||||
znode->flags &= ~ZOF_IF_REFERENCE;
|
||||
return TRUE;
|
||||
|
||||
@@ -478,8 +478,10 @@ int InitGUI (int argc, const char* agr[])
|
||||
/* Since 5.0.0
|
||||
* Copy the video engine information to the shared resource segement
|
||||
*/
|
||||
strncpy (SHAREDRES_VIDEO_ENGINE, engine, LEN_ENGINE_NAME);
|
||||
strncpy (SHAREDRES_VIDEO_MODE, mode, LEN_VIDEO_MODE);
|
||||
//strncpy (SHAREDRES_VIDEO_ENGINE, engine, LEN_ENGINE_NAME);
|
||||
strcpy (SHAREDRES_VIDEO_ENGINE, engine);
|
||||
//strncpy (SHAREDRES_VIDEO_MODE, mode, LEN_VIDEO_MODE);
|
||||
strcpy (SHAREDRES_VIDEO_MODE, mode);
|
||||
#if 0 /* deprecated code */
|
||||
// these fileds will be initialized by DRM engine.
|
||||
if (GetMgEtcValue (engine, "device",
|
||||
|
||||
+11
-2
@@ -1433,7 +1433,9 @@ char * strtrimall( char *src)
|
||||
return src;
|
||||
}
|
||||
|
||||
strcpy (src, src + nIndex1);
|
||||
// VW: use memmove instead of strcpy to avoid overlapping
|
||||
// strcpy (src, src + nIndex1);
|
||||
memmove (src, src + nIndex1, nLen - nIndex1 + 1);
|
||||
|
||||
nLen = strlen (src);
|
||||
nIndex1 = nLen - 1;
|
||||
@@ -1468,11 +1470,18 @@ int __mg_path_joint (char* dst, int dst_size,
|
||||
if (__mg_is_abs_path(abs_path) && (!__mg_is_abs_path(sub_path))) {
|
||||
if (dst_size >= strlen(abs_path) + strlen(sub_path)
|
||||
+ 2/* size of split '/' and terminator '\0' */) {
|
||||
sprintf(dst, "%s/%s", abs_path, sub_path);
|
||||
strcpy (dst, abs_path);
|
||||
strcat (dst, "/");
|
||||
strcat (dst, sub_path);
|
||||
//sprintf(dst, "%s/%s", abs_path, sub_path);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
_WRN_PRINTF ("The buffer space for the full path is too short: %d\n", dst_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,9 @@
|
||||
#include <hb.h>
|
||||
#include <hb-ft.h>
|
||||
|
||||
/* __mg_hb_unifuncs is implemented in src/font/harzbuff-minigui-funcs.c */
|
||||
extern hb_unicode_funcs_t *__mg_hb_unifuncs;
|
||||
|
||||
// define _CACHED_HB_FONT if you want use the cached HB fonts
|
||||
#define _CACHED_HB_FONT 1
|
||||
|
||||
@@ -216,6 +219,14 @@ static BOOL shape_layout_run(SEInstance* inst,
|
||||
if (hb_buf == NULL)
|
||||
goto error;
|
||||
|
||||
/* use our own unicode functions */
|
||||
if (__mg_hb_unifuncs) {
|
||||
hb_buffer_set_unicode_funcs(hb_buf, __mg_hb_unifuncs);
|
||||
}
|
||||
else {
|
||||
_DBG_PRINTF("Unicode functions for HarfBuzz does not initialized\n");
|
||||
}
|
||||
|
||||
hb_buffer_set_content_type(hb_buf, HB_BUFFER_CONTENT_TYPE_UNICODE);
|
||||
for (i = 0; i < run->len; i++) {
|
||||
hb_buffer_add(hb_buf, run->ucs[i], i);
|
||||
|
||||
+2
-1
@@ -409,7 +409,7 @@ int __mg_init_layers ()
|
||||
return -1;
|
||||
|
||||
/* mark the first semphore is used; it is reserved for wallpaper pattern */
|
||||
assert (__mg_alloc_mutual_sem (_ssm_shared_surf, NULL) == 0);
|
||||
__mg_alloc_mutual_sem (_ssm_shared_surf, NULL);
|
||||
|
||||
on_exit (__mg_delete_sem_set_manager, _ssm_shared_surf);
|
||||
#endif
|
||||
@@ -870,6 +870,7 @@ const ZNODEHEADER* GUIAPI ServerGetWinZNodeHeader (MG_Layer* layer,
|
||||
#ifdef _MGSCHEMA_COMPOSITING
|
||||
if (lock && (pdc = dc_HDC2PDC (hdr->mem_dc))) {
|
||||
assert (pdc->surface->dirty_info);
|
||||
|
||||
if (hdr->lock_count == 0) {
|
||||
if (pdc->surface->shared_header) {
|
||||
// XXX: consider timeout.
|
||||
|
||||
@@ -812,10 +812,10 @@ static int get_shared_surface (int cli, int clifd, void* buff, size_t len)
|
||||
|
||||
static int authenticate_client (int cli, int clifd, void* buff, size_t len)
|
||||
{
|
||||
uint32_t magic;
|
||||
int auth_result = 1;
|
||||
|
||||
#ifdef _MGGAL_DRM
|
||||
uint32_t magic;
|
||||
extern int __drm_auth_client(int, uint32_t);
|
||||
magic = *(uint32_t*)buff;
|
||||
auth_result = __drm_auth_client (cli, magic);
|
||||
|
||||
+32
-27
@@ -397,29 +397,10 @@ static void free_val_bitmap (void *val)
|
||||
map_t* __mg_sys_bmp_map;
|
||||
BOOL mg_InitResManager(int hash_table_size)
|
||||
{
|
||||
char szpath[MAX_PATH+1];
|
||||
char* p = NULL;
|
||||
pwd_res_path = strdup("./");
|
||||
|
||||
//initialize paths
|
||||
#if !defined(__NOUNIX__) || defined(WIN32)
|
||||
if ((p = getenv ("MG_RES_PATH"))) {
|
||||
int len = strlen(p);
|
||||
if (p[len-1] == '/')
|
||||
sprintf(szpath, "%s", p);
|
||||
else
|
||||
sprintf(szpath, "%s/", p);
|
||||
cfg_res_path = strdup(szpath);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
//step 2: get from MiniGUI.cfg
|
||||
if (GetMgEtcValue("resinfo", "respath",
|
||||
szpath, sizeof(szpath)-1) == ETC_OK) {
|
||||
cfg_res_path = strdup(szpath);
|
||||
}
|
||||
}
|
||||
// initialize paths
|
||||
if (pwd_res_path == NULL)
|
||||
pwd_res_path = strdup ("./");
|
||||
__sysres_get_system_res_path();
|
||||
|
||||
//initialize hash table
|
||||
init_hash_table (&hash_table, hash_table_size);
|
||||
@@ -475,6 +456,31 @@ void TerminateResManager()
|
||||
|
||||
const char* __sysres_get_system_res_path()
|
||||
{
|
||||
char szpath [MAX_PATH+1];
|
||||
char* p = NULL;
|
||||
|
||||
if (cfg_res_path)
|
||||
return cfg_res_path;
|
||||
|
||||
#if !defined(__NOUNIX__) || defined(WIN32)
|
||||
if ((p = getenv ("MG_RES_PATH"))) {
|
||||
int len = strlen (p);
|
||||
if (p[len-1] == '/')
|
||||
sprintf (szpath, "%s", p);
|
||||
else
|
||||
sprintf (szpath, "%s/", p);
|
||||
cfg_res_path = strdup (szpath);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// get from MiniGUI.cfg
|
||||
if (GetMgEtcValue ("resinfo", "respath",
|
||||
szpath, sizeof (szpath)-1) == ETC_OK) {
|
||||
cfg_res_path = strdup (szpath);
|
||||
}
|
||||
}
|
||||
|
||||
return cfg_res_path;
|
||||
}
|
||||
|
||||
@@ -496,7 +502,7 @@ int SetResPath(const char* path)
|
||||
//test path is valid directory
|
||||
#if !defined(__NOUNIX__) && !defined(WIN32)
|
||||
struct stat buf;
|
||||
if(stat(path, &buf) != 0 || !S_ISDIR(buf.st_mode)) {
|
||||
if (stat(path, &buf) != 0 || !S_ISDIR(buf.st_mode)) {
|
||||
# ifdef _DEBUG
|
||||
ERR_RETV (RES_RET_INVALID_PARAM, RES_RET_INVALID_PARAM, "param path (%s) is not a valid directory", path);
|
||||
# else
|
||||
@@ -505,7 +511,7 @@ int SetResPath(const char* path)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(usr_res_path != NULL)
|
||||
if (usr_res_path != NULL)
|
||||
DELETE(usr_res_path);
|
||||
|
||||
usr_res_path = STR_DUP(path);
|
||||
@@ -632,8 +638,7 @@ static char* get_res_file(const char* res_name, char* filename)
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; res_paths[i]; i++)
|
||||
{
|
||||
for (i=0; res_paths[i]; i++) {
|
||||
#ifndef __NOUNIX__
|
||||
struct stat buf;
|
||||
sprintf(filename,"%s/%s", res_paths[i], res_name);
|
||||
|
||||
Reference in New Issue
Block a user