static char * get_webkit_datadir(void) { static char retval[1000]; static int beenhere = 0; unsigned char *p; if (beenhere) return retval; if (!GetModuleFileName (hmodule, (CHAR *) retval, sizeof(retval) - 10)) return DATA_DIR; p = _mbsrchr((const unsigned char *) retval, '\\'); *p = '\0'; p = _mbsrchr((const unsigned char *) retval, '\\'); if (p) { if (!stricmp((const char *) (p+1), "bin")) *p = '\0'; } strcat(retval, "\\share"); beenhere = 1; return retval; }
void boundary_set_from_string (boundary *bound, char *loc_str) { /* Must search in reverse since the file name field may * contain `.' or `:'. */ char *delim = _mbsrchr (loc_str, '.'); aver (delim); *delim = '\0'; bound->column = atoi (delim+1); delim = _mbsrchr (loc_str, ':'); aver (delim); *delim = '\0'; bound->line = atoi (delim+1); bound->file = uniqstr_new (loc_str); }
DWORD SearchPathA (LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart) { char *filename; char *filepart; int filename_len; _dbus_assert (lpPath == NULL); _dbus_assert (lpExtension == NULL); filename = find_program_in_inst_dir (lpFileName); if (!filename) { SetLastError (ERROR_FILE_NOT_FOUND); return 0; } filename_len = strlen (filename) + 1; if (filename_len > nBufferLength) { free (filename); return filename_len; } strcpy (lpBuffer, filename); free (filename); filepart = _mbsrchr (lpBuffer, '\\'); if (!filepart) filepart = lpBuffer; *lpFilePart = filepart; return filename_len - 1; }
// return pointer to last instance of the given separator static inline char *GetLastSeparator(const char *str, char sep) { #if defined(XP_WIN) || defined(XP_OS2) return (char*) _mbsrchr((const unsigned char *) str, sep); #else return (char*) strrchr(str, sep); #endif }
// バイトコードがメモリにロードされた直後のコールバック。 // 対応するDLLがあればロードする static void cb4dll(const char* hybPath) { int len = HMD_STRLEN(hybPath); char* dllPath = (char*)HMD_ALLOCA(len + sizeof(dll_prefix)+sizeof(dll_ext)); char* q = dllPath; char* q2 = q; const unsigned char* p = _mbsrchr((const unsigned char*)hybPath, PATH_DELIM); if (p == NULL) { p = (const unsigned char*)hybPath; } else { p += 1; size_t lp = p - (const unsigned char*)hybPath; memcpy(q, hybPath, lp); q += lp; q2 = q; } // pはhybPathのファイル名部分の先頭アドレス const unsigned char* p2 = _mbsstr((const unsigned char*)p, (const unsigned char*)".hyb"); if ((p2 <= p) || (p2 >= (const unsigned char*)hybPath + len)) { p2 = (const unsigned char*)hybPath + len; } // p2は拡張子を抜いたファイル名部分の末尾アドレス memcpy(q, dll_prefix, sizeof(dll_prefix)); q += sizeof(dll_prefix) - 1; size_t lp2 = p2 - p; memcpy(q, p, lp2); q += lp2; memcpy(q, dll_ext, sizeof(dll_ext)); q += sizeof(dll_ext) - 1; *q = '\0'; #ifdef VERBOSE_LOAD_DLL HMD_PRINTF("try load dll: %s\n", dllPath); #endif HMODULE hmod = LoadLibraryMB(dllPath); // dllロード #ifdef VERBOSE_LOAD_DLL if (hmod == NULL) printLastError(); #endif if (hmod == NULL && q2 != dllPath) { // パス抜きのファイル名だけでロードしてみる #ifdef VERBOSE_LOAD_DLL HMD_PRINTF("try load dll: %s\n", q2); #endif hmod = LoadLibraryMB(q2); #ifdef VERBOSE_LOAD_DLL if (hmod == NULL) printLastError(); #endif } if (hmod != NULL) { dllHandleArr.add(hmod); #ifdef VERBOSE_LOAD_DLL HMD_PRINTF("DLL '%s' loaded.\n", q2); #endif } }
// --------------------------------------------------------------------- SInt32 WinMBCString::RFind(AChar character) const { const unsigned char* target = reinterpret_cast<const unsigned char*>(innerString.c_str()); const unsigned char* found = _mbsrchr(target, static_cast<unsigned char>(character)); if (NULL == found) { return -1; } else { return found - target; } }
static inline void _dbus_verbose_init (void) { if (!verbose_initted) { const char *p = _dbus_getenv ("DBUS_VERBOSE"); verbose = p != NULL && *p == '1'; verbose_initted = TRUE; #ifdef DBUS_USE_OUTPUT_DEBUG_STRING { char *last_period, *last_slash; GetModuleFileName(0,module_name,sizeof(module_name)-1); last_period = _mbsrchr(module_name,'.'); if (last_period) *last_period ='\0'; last_slash = _mbsrchr(module_name,'\\'); if (last_slash) strcpy(module_name,last_slash+1); strcat(module_name,": "); } #endif } }
static const char* getWebKitDataDirectory() { static char* dataDirectory = 0; if (dataDirectory) return dataDirectory; dataDirectory = new char[PATH_MAX]; if (!GetModuleFileName(hmodule, static_cast<CHAR*>(dataDirectory), sizeof(dataDirectory) - 10)) return DATA_DIR; // FIXME: This is pretty ugly. Ideally we should be using Windows API // functions or GLib methods to calculate paths. unsigned char *p; p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\'); *p = '\0'; p = _mbsrchr(static_cast<const unsigned char *>(dataDirectory), '\\'); if (p) { if (!stricmp((const char *) (p+1), "bin")) *p = '\0'; } strcat(dataDirectory, "\\share"); return dataDirectory; }
BOOL TInifile::Lock() { if (!hMutex) { char buf[1024]; char *key = (char *)_mbsrchr((u_char *)ini_file, '\\'); key = key ? key+1 : ini_file; sprintf(buf, "%s_%x", key, MakeHash(ini_file, (int)strlen(ini_file), 0)); if (!(hMutex = ::CreateMutex(NULL, FALSE, buf))) return FALSE; } return ::WaitForSingleObject(hMutex, INFINITE); }
static void file_name_split (const char *file_name, const char **base, const char **tab, const char **ext) { *base = last_component (file_name); /* Look for the extension, i.e., look for the last dot. */ *ext = (const char*)_mbsrchr ((const unsigned char*)*base, '.'); *tab = NULL; /* If there is an extension, check if there is a '.tab' part right before. */ if (*ext) { size_t baselen = *ext - *base; size_t dottablen = sizeof (TAB_EXT) - 1; if (dottablen < baselen && STRPREFIX_LIT (TAB_EXT, *ext - dottablen)) *tab = *ext - dottablen; } }
FILE * __cdecl _tpopen ( const _TSCHAR *cmdstring, const _TSCHAR *type ) { int phdls[2]; /* I/O handles for pipe */ int ph_open[2]; /* flags, set if correspond phdls is open */ int i1; /* index into phdls[] */ int i2; /* index into phdls[] */ int tm = 0; /* flag indicating text or binary mode */ int stdhdl; /* either STDIN or STDOUT */ HANDLE newhnd; /* ...in calls to DuplicateHandle API */ FILE *pstream = NULL; /* stream to be associated with pipe */ HANDLE prochnd; /* handle for current process */ _TSCHAR *cmdexe; /* pathname for the command processor */ _TSCHAR *envbuf = NULL; /* buffer for the env variable */ intptr_t childhnd; /* handle for child process (cmd.exe) */ IDpair *locidpair; /* pointer to IDpair table entry */ _TSCHAR *buf = NULL, *pfin, *env; _TSCHAR *CommandLine; size_t CommandLineSize = 0; _TSCHAR _type[3] = {0, 0, 0}; /* Info for spawning the child. */ STARTUPINFO StartupInfo; /* Info for spawning a child */ BOOL childstatus = 0; PROCESS_INFORMATION ProcessInfo; /* child process information */ errno_t save_errno; int fh_lock_held = 0; int popen_lock_held = 0; /* first check for errors in the arguments */ _VALIDATE_RETURN((cmdstring != NULL), EINVAL,NULL); _VALIDATE_RETURN((type != NULL), EINVAL,NULL); while (*type == _T(' ')) { type++; } _VALIDATE_RETURN(((*type == _T('w')) || (*type == _T('r'))), EINVAL,NULL); _type[0] = *type; ++type; while (*type == _T(' ')) { ++type; } _VALIDATE_RETURN(((*type == 0) || (*type == _T('t')) || (*type == _T('b'))), EINVAL, NULL); _type[1] = *type; /* do the _pipe(). note that neither of the resulting handles will * be inheritable. */ if ( _type[1] == _T('t') ) tm = _O_TEXT; else if ( _type[1] == _T('b') ) tm = _O_BINARY; tm |= _O_NOINHERIT; if ( _pipe( phdls, PSIZE, tm ) == -1 ) goto error1; /* test _type[0] and set stdhdl, i1 and i2 accordingly. */ if ( _type[0] == _T('w') ) { stdhdl = STDIN; i1 = 0; i2 = 1; } else { stdhdl = STDOUT; i1 = 1; i2 = 0; } /* ASSERT LOCK FOR IDPAIRS HERE!!!! */ if ( !_mtinitlocknum( _POPEN_LOCK )) { _close( phdls[0] ); _close( phdls[1] ); return NULL; } _mlock( _POPEN_LOCK ); __try { /* set flags to indicate pipe handles are open. note, these are only * used for error recovery. */ ph_open[ 0 ] = ph_open[ 1 ] = 1; /* get the process handle, it will be needed in some API calls */ prochnd = GetCurrentProcess(); if ( !DuplicateHandle( prochnd, (HANDLE)_osfhnd( phdls[i1] ), prochnd, &newhnd, 0L, TRUE, /* inheritable */ DUPLICATE_SAME_ACCESS ) ) { goto error2; } (void)_close( phdls[i1] ); ph_open[ i1 ] = 0; /* associate a stream with phdls[i2]. note that if there are no * errors, pstream is the return value to the caller. */ if ( (pstream = _tfdopen( phdls[i2], _type )) == NULL ) goto error2; /* next, set locidpair to a free entry in the idpairs table. */ if ( (locidpair = idtab( NULL )) == NULL ) goto error3; /* Find what to use. command.com or cmd.exe */ if ( (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envbuf, NULL, _T("COMSPEC"))) != 0) || (envbuf == NULL) ) { unsigned int osver = 0; _get_osver(&osver); cmdexe = ( osver & 0x8000 ) ? _T("command.com") : _T("cmd.exe"); } else { cmdexe = envbuf; } /* * Initialise the variable for passing to CreateProcess */ memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); /* Used by os for duplicating the Handles. */ StartupInfo.dwFlags = STARTF_USESTDHANDLES; StartupInfo.hStdInput = stdhdl == STDIN ? (HANDLE) newhnd : (HANDLE) _osfhnd(0); StartupInfo.hStdOutput = stdhdl == STDOUT ? (HANDLE) newhnd : (HANDLE) _osfhnd(1); StartupInfo.hStdError = (HANDLE) _osfhnd(2); CommandLineSize = _tcslen(cmdexe) + _tcslen(_T(" /c ")) + (_tcslen(cmdstring)) +1; if ((CommandLine = _calloc_crt( CommandLineSize, sizeof(_TSCHAR))) == NULL) goto error3; _ERRCHECK(_tcscpy_s(CommandLine, CommandLineSize, cmdexe)); _ERRCHECK(_tcscat_s(CommandLine, CommandLineSize, _T(" /c "))); _ERRCHECK(_tcscat_s(CommandLine, CommandLineSize, cmdstring)); /* Check if cmdexe can be accessed. If yes CreateProcess else try * searching path. */ save_errno = errno; if (_taccess_s(cmdexe, 0) == 0) { childstatus = CreateProcess( (LPTSTR) cmdexe, (LPTSTR) CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo ); } else { TCHAR* envPath = NULL; size_t envPathSize = 0; if ((buf = _calloc_crt(_MAX_PATH, sizeof(_TSCHAR))) == NULL) { _free_crt(buf); _free_crt(CommandLine); _free_crt(envbuf); cmdexe = NULL; errno = save_errno; goto error3; } if (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envPath, NULL, _T("PATH"))) != 0) { _free_crt(envPath); _free_crt(buf); _free_crt(CommandLine); _free_crt(envbuf); cmdexe = NULL; errno = save_errno; goto error3; } env = envPath; #ifdef WPRFLAG while ( (env = _wgetpath(env, buf, _MAX_PATH -1)) && (*buf) ) { #else /* WPRFLAG */ while ( (env = _getpath(env, buf, _MAX_PATH -1)) && (*buf) ) { #endif /* WPRFLAG */ pfin = buf + _tcslen(buf) -1; #ifdef _MBCS if (*pfin == SLASHCHAR) { if (pfin != _mbsrchr(buf, SLASHCHAR)) _ERRCHECK(strcat_s(buf, _MAX_PATH, SLASH)); } else if (*pfin != XSLASHCHAR) _ERRCHECK(strcat_s(buf, _MAX_PATH, SLASH)); #else /* _MBCS */ if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR) _ERRCHECK(_tcscat_s(buf, _MAX_PATH, SLASH)); #endif /* _MBCS */ /* check that the final path will be of legal size. if so, * build it. otherwise, return to the caller (return value * and errno rename set from initial call to _spawnve()). */ if ( (_tcslen(buf) + _tcslen(cmdexe)) < _MAX_PATH ) _ERRCHECK(_tcscat_s(buf, _MAX_PATH, cmdexe)); else break; /* Check if buf can be accessed. If yes CreateProcess else try * again. */ if (_taccess_s(buf, 0) == 0) { childstatus = CreateProcess( (LPTSTR) buf, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo ); break; } } _free_crt(envPath); _free_crt(buf); } _free_crt(CommandLine); _free_crt(envbuf); cmdexe = NULL; CloseHandle((HANDLE)newhnd); CloseHandle((HANDLE)ProcessInfo.hThread); errno = save_errno; /* check if the CreateProcess was sucessful. */ if ( childstatus) childhnd = (intptr_t)ProcessInfo.hProcess; else goto error4; locidpair->prochnd = childhnd; locidpair->stream = pstream; /* success, return the stream to the caller */ goto done; /** * error handling code. all detected errors end up here, entering * via a goto one of the labels. note that the logic is currently * a straight fall-thru scheme (e.g., if entered at error4, the * code for error4, error3,...,error1 is all executed). **********************************************************************/ error4: /* make sure locidpair is reusable */ locidpair->stream = NULL; error3: /* close pstream (also, clear ph_open[i2] since the stream * close will also close the pipe handle) */ (void)fclose( pstream ); ph_open[ i2 ] = 0; pstream = NULL; error2: /* close handles on pipe (if they are still open) */ if ( ph_open[i1] ) _close( phdls[i1] ); if ( ph_open[i2] ) _close( phdls[i2] ); done: ;} __finally { _munlock(_POPEN_LOCK); } error1: return pstream; } #ifndef _UNICODE /*** *int _pclose(pstream) - wait on a child command and close the stream on the * associated pipe * *Purpose: * Closes pstream then waits on the associated child command. The * argument, pstream, must be the return value from a previous call to * _popen. _pclose first looks up the process handle of child command * started by that _popen and does a cwait on it. Then, it closes pstream * and returns the exit status of the child command to the caller. * *Entry: * FILE *pstream - file stream returned by a previous call to _popen * *Exit: * If successful, _pclose returns the exit status of the child command. * The format of the return value is that same as for cwait, except that * the low order and high order bytes are swapped. * * If an error occurs, -1 is returned. * *Exceptions: * *******************************************************************************/ int __cdecl _pclose ( FILE *pstream ) { IDpair *locidpair; /* pointer to entry in idpairs table */ int termstat; /* termination status word */ int retval = -1; /* return value (to caller) */ errno_t save_errno; _VALIDATE_RETURN((pstream != NULL), EINVAL, -1); if (!_mtinitlocknum(_POPEN_LOCK)) return -1; _mlock(_POPEN_LOCK); __try { if ((locidpair = idtab(pstream)) == NULL) { /* invalid pstream, exit with retval == -1 */ errno = EBADF; goto done; } /* close pstream */ (void)fclose(pstream); /* wait on the child (copy of the command processor) and all of its * children. */ save_errno = errno; errno = 0; if ( (_cwait(&termstat, locidpair->prochnd, _WAIT_GRANDCHILD) != -1) || (errno == EINTR) ) retval = termstat; errno = save_errno; /* Mark the IDpairtable entry as free (note: prochnd was closed by the * preceding call to _cwait). */ locidpair->stream = NULL; locidpair->prochnd = 0; /* only return path! */ done: ; } __finally { _munlock(_POPEN_LOCK); } return(retval); }
int __cdecl _tspawnvpe ( int modeflag, REG3 const _TSCHAR *filename, const _TSCHAR * const *argv, const _TSCHAR * const *envptr ) { int i; REG1 _TSCHAR *env; REG2 _TSCHAR *buf = NULL; _TSCHAR *pfin; _ASSERTE(filename != NULL); _ASSERTE(*filename != _T('\0')); _ASSERTE(argv != NULL); _ASSERTE(*argv != NULL); _ASSERTE(**argv != _T('\0')); if ( (i = _tspawnve(modeflag, filename, argv, envptr)) != -1 /* everything worked just fine; return i */ || (errno != ENOENT) /* couldn't spawn the process, return failure */ || (_tcschr(filename, XSLASHCHAR) != NULL) /* filename contains a '/', return failure */ || !(env = _tgetenv(_T("PATH"))) /* no PATH environment string name, return failure */ || ( (buf = _malloc_crt(_MAX_PATH * sizeof(_TSCHAR))) == NULL ) /* cannot allocate buffer to build alternate pathnames, return * failure */ ) { goto done; } /* could not find the file as specified, search PATH. try each * component of the PATH until we get either no error return, or the * error is not ENOENT and the component is not a UNC name, or we run * out of components to try. */ #ifdef WPRFLAG while ( (env = _wgetpath(env, buf, _MAX_PATH - 1)) && (*buf) ) { #else /* WPRFLAG */ while ( (env = _getpath(env, buf, _MAX_PATH - 1)) && (*buf) ) { #endif /* WPRFLAG */ pfin = buf + _tcslen(buf) - 1; /* if necessary, append a '/' */ #ifdef _MBCS if (*pfin == SLASHCHAR) { if (pfin != _mbsrchr(buf,SLASHCHAR)) /* fin is the second byte of a double-byte char */ strcat(buf, SLASH ); } else if (*pfin !=XSLASHCHAR) strcat(buf, SLASH); #else /* _MBCS */ if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR) _tcscat(buf, SLASH); #endif /* _MBCS */ /* check that the final path will be of legal size. if so, * build it. otherwise, return to the caller (return value * and errno rename set from initial call to _spawnve()). */ if ( (_tcslen(buf) + _tcslen(filename)) < _MAX_PATH ) _tcscat(buf, filename); else break; /* try spawning it. if successful, or if errno comes back with a * value other than ENOENT and the pathname is not a UNC name, * return to the caller. */ if ( (i = _tspawnve(modeflag, buf, argv, envptr)) != -1 || ((errno != ENOENT) #ifdef _MBCS && (!ISPSLASH(buf) || !ISPSLASH(buf+1))) ) #else /* _MBCS */ && (!ISSLASH(*buf) || !ISSLASH(*(buf+1)))) ) #endif /* _MBCS */ break; } done: if (buf != NULL) _free_crt(buf); return(i); }
static void setup (void) { char *full_prefix = NULL; char *cp_prefix; wchar_t wcbfr[1000]; G_LOCK (mutex); if (locale_dir != NULL) { G_UNLOCK (mutex); return; } if (GetModuleFileNameW (hmodule, wcbfr, G_N_ELEMENTS (wcbfr))) { full_prefix = g_utf16_to_utf8 (wcbfr, -1, NULL, NULL, NULL); if (GetShortPathNameW (wcbfr, wcbfr, G_N_ELEMENTS (wcbfr))) cp_prefix = g_utf16_to_utf8 (wcbfr, -1, NULL, NULL, NULL); else if (full_prefix) cp_prefix = g_locale_from_utf8 (full_prefix, -1, NULL, NULL, NULL); } if (full_prefix != NULL) { gchar *p = strrchr (full_prefix, '\\'); if (p != NULL) *p = '\0'; p = strrchr (full_prefix, '\\'); if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0)) *p = '\0'; /* Replace backslashes with forward slashes to avoid * problems for instance in makefiles that use * gconftool-2 --get-default-source. */ while ((p = strchr (full_prefix, '\\')) != NULL) *p = '/'; runtime_prefix = full_prefix; } else { runtime_prefix = g_strdup (""); } if (cp_prefix != NULL) { gchar *p = _mbsrchr (cp_prefix, '\\'); if (p != NULL) *p = '\0'; p = _mbsrchr (cp_prefix, '\\'); if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0)) *p = '\0'; } else { cp_prefix = g_strdup (""); } locale_dir = g_strconcat (cp_prefix, GCONF_LOCALE_DIR + strlen (PREFIX), NULL); confdir = _gconf_win32_replace_prefix (GCONF_CONFDIR); etcdir = _gconf_win32_replace_prefix (GCONF_ETCDIR); serverdir = _gconf_win32_replace_prefix (GCONF_SERVERDIR); backend_dir = _gconf_win32_replace_prefix (GCONF_BACKEND_DIR); G_UNLOCK (mutex); }
static void cmd_create(CTar32CmdInfo &cmdinfo) { { EXTRACTINGINFOEX extractinfo; memset(&extractinfo,0,sizeof(extractinfo)); EXTRACTINGINFOEX64 exinfo64; memset(&exinfo64,0,sizeof(exinfo64)); exinfo64.dwStructSize=sizeof(exinfo64); strncpy(extractinfo.exinfo.szSourceFileName, cmdinfo.arcfile.c_str() ,FNAME_MAX32+1); exinfo64.exinfo=extractinfo.exinfo; strncpy(exinfo64.szSourceFileName, extractinfo.exinfo.szSourceFileName ,FNAME_MAX32+1); int ret = SendArcMessage(cmdinfo, ARCEXTRACT_OPEN, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} } CTar32 tarfile; int ret; bool bret; int filenum = 0; //char mode[10]; //sprintf(mode, "wb%d", cmdinfo.compress_level); ret = tarfile.open(cmdinfo.arcfile.c_str(), "wb",cmdinfo.compress_level, cmdinfo.archive_type,cmdinfo.archive_charset); if(!ret){ throw CTar32Exception("can't open archive file", ERROR_ARC_FILE_OPEN); } std::vector<char> buffer; buffer.resize(1024*1024); // const list<string> &files = cmdinfo.files; const std::list<CTar32CmdInfo::CArgs> &args = cmdinfo.argfiles; std::list<CTar32CmdInfo::CArgs>::const_iterator filei; //enumerate files std::vector<FILE_TO_ADD> files_to_add; for(filei = args.begin();filei!=args.end();filei++){ std::vector<std::string> files_enumed; { std::string file_internal = (*filei).file; std::string file_external = make_pathname((*filei).current_dir.c_str(), (*filei).file.c_str()); find_files(file_external.c_str(),files_enumed); if(_mbsrchr((const unsigned char*)file_external.c_str(),'*')==0 && files_enumed.empty()){ // fixed by tsuneo. 2001.05.15 throw CTar32Exception((std::string("can't find file [") + file_external + "]").c_str(), ERROR_FILE_OPEN); } } for(std::vector<std::string>::iterator files2i = files_enumed.begin(); files2i != files_enumed.end(); files2i++){ std::string file_path = *files2i; std::string file_relative; if(cmdinfo.b_use_directory){ file_relative = file_path.substr((*filei).current_dir.length()); }else{ file_relative = get_filename(file_path.c_str()); } // FILE_TO_ADD file_entry; file_entry.fullPath=file_path; file_entry.relativePath=file_relative; files_to_add.push_back(file_entry); } } //sort? : by filepath or by extension if(cmdinfo.b_sort_by_ext){ struct SORTER_BY_EXT{ bool operator()(const FILE_TO_ADD& a,const FILE_TO_ADD& b){ //sort by ext int ret=stricmp(PathFindExtension(a.relativePath.c_str()),PathFindExtension(b.relativePath.c_str())); if(ret==0){ //sort by path if ext is same return stricmp(a.relativePath.c_str(),b.relativePath.c_str())<0; }else{ return ret<0; } } }; std::sort(files_to_add.begin(),files_to_add.end(),SORTER_BY_EXT()); }else if(cmdinfo.b_sort_by_path){ struct SORTER_BY_PATH{ bool operator()(const FILE_TO_ADD& a,const FILE_TO_ADD& b){ return stricmp(a.relativePath.c_str(),b.relativePath.c_str())<0; } }; std::sort(files_to_add.begin(),files_to_add.end(),SORTER_BY_PATH()); } //compression { for(std::vector<FILE_TO_ADD>::const_iterator ite=files_to_add.begin();ite!=files_to_add.end();++ite){ const FILE_TO_ADD &file_entry=*ite; CTar32FileStatus stat; if(!stat.SetFromFile(file_entry.fullPath.c_str())){ continue; } std::string filepath_to_store=file_entry.relativePath; convert_yen_to_slash(filepath_to_store); { // if file is directory, add '/' to the tail of filename. struct _stat st; if(_stat(file_entry.fullPath.c_str(), &st)!=-1 && st.st_mode & _S_IFDIR){ char const*f = filepath_to_store.c_str(); if((char*)max(_mbsrchr((unsigned char*)f, '/'), _mbsrchr((unsigned char*)f,'\\')) != f+strlen(f)-1){ filepath_to_store.append(1,'/'); } } } stat.filename = filepath_to_store; bret = tarfile.addheader(stat); // bret = tarfile.addbody(file_external2.c_str()); bool bret2 = add_file(cmdinfo,&tarfile,file_entry.fullPath.c_str(),buffer); filenum ++; } } { EXTRACTINGINFOEX extractinfo; memset(&extractinfo,0,sizeof(extractinfo)); EXTRACTINGINFOEX64 exinfo64; memset(&exinfo64,0,sizeof(exinfo64)); exinfo64.dwStructSize=sizeof(exinfo64); int ret = SendArcMessage(cmdinfo, ARCEXTRACT_END, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} } if(filenum == 0){ // fixed by tsuneo. 2001.05.14 throw CTar32Exception("There is no file to archive. ", ERROR_FILE_OPEN); } }
void tar_cmd_parser(LPCSTR szCmdLine,CTar32CmdInfo &cmdinfo) { std::vector<std::string> args; // command line array if(!split_cmdline_with_response(szCmdLine,args)){ throw CTar32Exception("commandline split error", ERROR_COMMAND_NAME); } char command = 0; // main command. ('x','c','l') //std::string current_directory; -> into CTar32CmdInfo std::vector<std::string>::iterator argi = args.begin(); bool option_end = false; while(argi != args.end()){ //string::iterator stri = (*argi).begin(); const char *stri = (*argi).c_str(); if(argi==args.begin() || (*stri == '-' && *(stri+1) != '\0' && option_end == false)){ if(*stri == '-'){ stri++; } if(*stri == '-' && *(stri+1) != '\0'){ stri++; const std::string long_option = (*argi).substr(stri - (*argi).c_str()); std::string key = long_option; std::string val; int len; if((len = long_option.find('=')) != std::string::npos){ key = long_option.substr(0, len); val = long_option.substr(len + 1); } if(key == "use-directory"){ cmdinfo.b_use_directory = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "absolute-paths"){ cmdinfo.b_absolute_paths = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "display-dialog"){ cmdinfo.b_display_dialog = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "message-loop"){ cmdinfo.b_message_loop = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "inverse-procresult"){ cmdinfo.b_inverse_procresult = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "bzip2" || key == "bzip"){ cmdinfo.archive_type = ARCHIVETYPE_BZ2; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<1) cmdinfo.compress_level = 9; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 9; }else if(key == "gzip"){ cmdinfo.archive_type = ARCHIVETYPE_GZ; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<1) cmdinfo.compress_level = 5; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 5; }else if(key == "lzma"){ cmdinfo.archive_type = ARCHIVETYPE_LZMA; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<0) cmdinfo.compress_level = 6; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 6; }else if(key == "xz"){ cmdinfo.archive_type = ARCHIVETYPE_XZ; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<0) cmdinfo.compress_level = 6; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 6; }else if(key == "confirm-overwrite"){ cmdinfo.b_confirm_overwrite = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "convert-charset"){ if(val=="")cmdinfo.archive_charset = CHARSET_UNKNOWN; else if(stricmp(val.c_str(),"none")==0)cmdinfo.archive_charset = CHARSET_DONTCARE; else if(stricmp(val.c_str(),"auto")==0)cmdinfo.archive_charset = CHARSET_UNKNOWN; else if(stricmp(val.c_str(),"sjis")==0)cmdinfo.archive_charset = CHARSET_SJIS; else if(stricmp(val.c_str(),"eucjp")==0)cmdinfo.archive_charset = CHARSET_EUCJP; else if(stricmp(val.c_str(),"utf8")==0)cmdinfo.archive_charset = CHARSET_UTF8; else cmdinfo.archive_charset = CHARSET_DONTCARE; }else if(key == "sort-by-ext"){ cmdinfo.b_sort_by_ext = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "sort-by-path"){ cmdinfo.b_sort_by_path = ((val=="") ? true : (0!=atoi(val.c_str()))); }else{ /* igonore */; } argi++; continue; } std::vector<std::string>::iterator cur_argi = argi; //while(stri != (*cur_argi).end()){ while(stri != (*cur_argi).c_str()+(*cur_argi).length()){ switch(*stri){ case 'x': command = 'x';break; case 'c': command = 'c';break; case 'l': case 't': // どんぞ:追加 command = 'l';break; case 'p': command = 'x'; cmdinfo.b_print = true; break; case 'f': if(++argi == args.end()){ throw CTar32Exception("'f' follow no directory name", ERROR_COMMAND_NAME); } cmdinfo.arcfile = *argi; break; case 'o': if(++argi == args.end()){ throw CTar32Exception("'o' follow no directory name", ERROR_COMMAND_NAME); } cmdinfo.current_directory = *argi; // stri = argi->end()-1; break; case 'z': cmdinfo.archive_type = ARCHIVETYPE_GZ; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 6; } break; case 'B': case 'j': cmdinfo.archive_type = ARCHIVETYPE_BZ2; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 9; } break; case 'J': cmdinfo.archive_type = ARCHIVETYPE_XZ; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 6; } break; case 'Z': cmdinfo.archive_type = ARCHIVETYPE_Z; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 6; } break; case 'G': cmdinfo.b_archive_tar = false; if(cmdinfo.archive_type == ARCHIVETYPE_NORMAL){ cmdinfo.archive_type = ARCHIVETYPE_GZ; cmdinfo.compress_level = 6; } break; case 'P': cmdinfo.b_absolute_paths = true; break; case 'a': case 'v': case 'V': case 'I': case 'i': case 'e': case 'g': case 'S': case 'R': // added by tsuneo 2001.05.14 /*ignore*/ break; case 'A': stri++; /*ignore*/ break; case 'b': case 'N': argi++; //stri = argi->end()-1; stri = (*argi).c_str()+(*argi).length()-1; /*ignore*/ break; case 'U': if(isdigit(*(stri+1))){ stri++; } /*ignore*/ break; case '-': // added by tsuneo on 2006/08/04. Patch is provided by Niiyama(HEROPA)-san. Special Thanks to Niiyama(HEROPA)-san. option_end = true; break; default: throw CTar32Exception("Invalid Arguments", ERROR_COMMAND_NAME); } stri++; } argi++; }else{ const char *file = (*argi).c_str(); if(*file && ((char*)_mbsrchr((const unsigned char*)file, '\\') == file + strlen(file) - 1)){ cmdinfo.current_directory = (char*)file; }else if(cmdinfo.arcfile.length() == 0){ cmdinfo.arcfile = *argi; }else{ std::string file = *argi; cmdinfo.argfiles.push_back(CTar32CmdInfo::CArgs(file,cmdinfo.current_directory)); } argi++; } } cmdinfo.command = command; }
bool CTar32::readdir_TAR(CTar32FileStatus &stat) { HEADER tar_header; if(!readTarHeader(tar_header))return false; //get tar format : GNU or POSIX int tar_format=tar_header.getFormat(); // HP-UX's tar command create 100chars filename part. fixed on 2003.12.19 char tmp_name[COUNTOF(tar_header.dbuf.name)+1]; strncpy(tmp_name, tar_header.dbuf.name, COUNTOF(tar_header.dbuf.name)); tmp_name[COUNTOF(tar_header.dbuf.name)] = '\0'; stat.filename = tmp_name; /* tar_header.dbuf.name; */ stat.original_size = parseOctNum(tar_header.dbuf.size,COUNTOF(tar_header.dbuf.size)); if(tar_header.dbuf.typeflag == LNKTYPE){ // Fixed on 2003/11/28. For "spencer_pwb.tar.gz". Thanks to rollo-san. stat.original_size = 0; } stat.blocksize = 512; if(tar_header.dbuf.typeflag == LONGLINK){ // tar_header.dbuf.name == "././@LongLink" //NOTE:TAR32.DLL earlier than 2.33 makes LONGLINK entry with POSIX header tar_format=TAR_FORMAT_GNU; //char longfilename[2000] = ""; std::vector<char> longfilename; size64 readsize = (size_t(stat.original_size-1)/512+1)*512; longfilename.resize((size_t)readsize+1); //TODO:size lost size64 ret = m_pfile->read(&longfilename[0], readsize); if(ret == 0){ throw CTar32Exception("can't get filename(LongLink)",ERROR_HEADER_BROKEN); } longfilename[(size_t)stat.original_size]='\0'; //TODO:size lost if(!readTarHeader(tar_header))return false; stat.filename = &longfilename[0]; stat.original_size = parseOctNum(tar_header.dbuf.size, COUNTOF(tar_header.dbuf.size)); } bool bPaxFilenameSupplied=false; time_t pax_atime=0,pax_ctime=0,pax_mtime=0; if(tar_header.dbuf.typeflag == PAX_GLOBAL || tar_header.dbuf.typeflag == PAX_ENTRTY){ std::vector<char> content; size64 readsize = (size_t(stat.original_size-1)/512+1)*512; content.resize((size_t)readsize+1); //TODO:size lost size64 ret = m_pfile->read(&content[0], readsize); if(ret == 0){ throw CTar32Exception("can't get PAX Extended Global Header",ERROR_HEADER_BROKEN); } content[(size_t)stat.original_size]='\0'; //TODO:size lost if(!readTarHeader(tar_header))return false; stat.original_size = parseOctNum(tar_header.dbuf.size, COUNTOF(tar_header.dbuf.size)); strncpy(tmp_name, tar_header.dbuf.name, COUNTOF(tar_header.dbuf.name)); tmp_name[COUNTOF(tar_header.dbuf.name)] = '\0'; stat.filename = tmp_name; /* tar_header.dbuf.name; */ std::string extFilename; size64 filesize; if(!parsePaxExtHeader(&content[0],content.size(),extFilename,filesize,pax_atime,pax_ctime,pax_mtime)){ if(tar_header.dbuf.typeflag == PAX_GLOBAL){ throw CTar32Exception("Broken PAX Extended Global Header",ERROR_HEADER_BROKEN); }else{ throw CTar32Exception("Broken PAX Extended Header",ERROR_HEADER_BROKEN); } } if(tar_header.dbuf.typeflag == PAX_GLOBAL){ //global header //TODO:need test //if(filesize!=-1)m_currentfile_status.original_size=filesize; }else{ //entry header //TODO:need test //if(filesize!=-1)stat.original_size=filesize; if(!extFilename.empty()){ bPaxFilenameSupplied=true; stat.filename=extFilename; } } } //charset conversion if(m_archive_charset!=CHARSET_DONTCARE && !bPaxFilenameSupplied){ if(m_archive_charset==CHARSET_UNKNOWN){ //detect charset m_archive_charset=detect_charset(stat.filename.c_str()); } switch(m_archive_charset){ case CHARSET_EUCJP: stat.filename=CConvertCharsetHelper::getInstance().eucjp_to_sjis(stat.filename.c_str(),stat.filename.size()); break; case CHARSET_UTF8N: //FALLTHROUGH case CHARSET_UTF8: stat.filename=CConvertCharsetHelper::getInstance().utf8_to_sjis(stat.filename.c_str(),stat.filename.size()); break; case CHARSET_JIS: //FALLTHROUGH /* force to extract even if charset is not supported. */ //throw CTar32Exception("tar header charset error.",ERROR_NOT_SUPPORT); //break; case CHARSET_SJIS: //FALLTHROUGH default: //nothing to do break; } } stat.mode = strtol(tar_header.dbuf.mode, NULL, 8); stat.uid = strtol(tar_header.dbuf.uid , NULL, 8); stat.gid = strtol(tar_header.dbuf.gid , NULL, 8); stat.mtime = strtol(tar_header.dbuf.mtime , NULL, 8); stat.chksum = strtol(tar_header.dbuf.chksum , NULL, 8); stat.typeflag = tar_header.dbuf.typeflag; stat.linkname = tar_header.dbuf.linkname; strncpy(stat.magic_version, tar_header.dbuf.magic,8); strncpy(stat.uname, tar_header.dbuf.uname, 32); strncpy(stat.gname, tar_header.dbuf.gname, 32); stat.devmajor = strtol(tar_header.dbuf.devmajor , NULL, 8); stat.devminor = strtol(tar_header.dbuf.devminor , NULL, 8); if(tar_format==TAR_FORMAT_GNU){ stat.atime = strtol(tar_header.dbuf.exthead.gnu.atime , NULL, 8); stat.ctime = strtol(tar_header.dbuf.exthead.gnu.ctime , NULL, 8); stat.offset = parseOctNum(tar_header.dbuf.exthead.gnu.offset , COUNTOF(tar_header.dbuf.exthead.gnu.offset)); }else{ //POSIX int length=min(COUNTOF(tar_header.dbuf.exthead.posix.prefix),strlen(tar_header.dbuf.exthead.posix.prefix)); if(length>0){ std::string prefix(tar_header.dbuf.exthead.posix.prefix,tar_header.dbuf.exthead.posix.prefix+length); stat.filename= prefix + '/' + stat.filename; } } if(pax_atime!=0)stat.atime=pax_atime; if(pax_ctime!=0)stat.ctime=pax_ctime; if(pax_mtime!=0)stat.mtime=pax_mtime; if(stat.typeflag == DIRTYPE){ stat.mode &= ~_S_IFMT; stat.mode |= _S_IFDIR; } if((stat.mode & _S_IFMT) == _S_IFDIR){ const char * f = stat.filename.c_str(); if((char*)max(_mbsrchr((unsigned char*)f, '/'), _mbsrchr((unsigned char*)f,'\\')) != f+strlen(f)-1){ stat.filename = stat.filename + "/"; } } return true; }
static void setup_runtime_paths (void) { char cpbfr[1000]; wchar_t wcbfr[1000]; char *full_prefix = NULL; char *cp_prefix = NULL; G_LOCK (mutex); if (prefix != NULL) { G_UNLOCK (mutex); return; } if (G_WIN32_HAVE_WIDECHAR_API ()) { /* NT-based Windows */ if (GetModuleFileNameW (hmodule, wcbfr, G_N_ELEMENTS (wcbfr))) { full_prefix = g_utf16_to_utf8 (wcbfr, -1, NULL, NULL, NULL); if (GetShortPathNameW (wcbfr, wcbfr, G_N_ELEMENTS (wcbfr)) && WideCharToMultiByte (CP_ACP, 0, wcbfr, -1, cpbfr, G_N_ELEMENTS (cpbfr), NULL, NULL)) cp_prefix = g_strdup (cpbfr); else if (full_prefix) cp_prefix = g_locale_from_utf8 (full_prefix, -1, NULL, NULL, NULL); } } else { /* Win9x */ if (GetModuleFileNameA (hmodule, cpbfr, G_N_ELEMENTS (cpbfr))) { full_prefix = g_locale_to_utf8 (cpbfr, -1, NULL, NULL, NULL); cp_prefix = g_strdup (cpbfr); } } if (full_prefix != NULL) { gchar *p = strrchr (full_prefix, '\\'); if (p != NULL) *p = '\0'; p = strrchr (full_prefix, '\\'); if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0)) *p = '\0'; prefix = full_prefix; } if (cp_prefix != NULL) { gchar *p = _mbsrchr (cp_prefix, '\\'); if (p != NULL) *p = '\0'; p = _mbsrchr (cp_prefix, '\\'); if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0)) *p = '\0'; } server_libexecdir = _matecomponent_activation_win32_replace_prefix (full_prefix, SERVER_LIBEXECDIR); serverinfodir = _matecomponent_activation_win32_replace_prefix (full_prefix, SERVERINFODIR); server_confdir = _matecomponent_activation_win32_replace_prefix (full_prefix, SERVER_CONFDIR); localedir = _matecomponent_activation_win32_replace_prefix (cp_prefix, MATECOMPONENT_ACTIVATION_LOCALEDIR); G_UNLOCK (mutex); }
HSURFACE CTextHelper::CreateWrappedSurface (ILTClient* pClientDE, int nWidth, HLTFONT hFont, char* pString, HLTCOLOR foreColor, HLTCOLOR backColor, int nAlignment, LTBOOL bCropped, int nExtraX, int nExtraY) { if (!pString || !pClientDE) return LTNULL; // check if we are supposed to do hard wrapping bool bHardTextWrap = false; { HSTRING hStr = pClientDE->FormatString(IDS_ENABLETEXTHARDWRAP); if (hStr) { const char* pComp = pClientDE->GetStringData(hStr); if (pComp != NULL) { if (stricmp(pComp,"TRUE") == 0) bHardTextWrap = true; } pClientDE->FreeString (hStr); } } // get period or other characters that are not supposed to be at start of a line char sPeriodChars[256] = "."; { HSTRING hStr = pClientDE->FormatString(IDS_EXCLULTLineSTARTCHARS); if (hStr) { const char* pComp = pClientDE->GetStringData(hStr); if (pComp != NULL) { _mbsncpy((unsigned char*)sPeriodChars, (const unsigned char*)pComp, 255); sPeriodChars[255] = '\0'; } pClientDE->FreeString (hStr); } } char* pWorkingString = new char [strlen (pString) + 1]; if (!pWorkingString) return LTNULL; CDynArray<uint32> surfaces (1, 2); // cannot create a dynarray of HSURFACES - compiler error C2926 uint32 nSurfaces = 0; char* ptr = (char*) pString; while (*ptr != '\0') { // copy what's left into the working string strcpy (pWorkingString, ptr); // create a string that will fit into the desired width LTBOOL bDone = LTFALSE; HSURFACE hSurface = LTNULL; while (!bDone) { // create a string surface from the working string to test HSTRING hString = pClientDE->CreateString (pWorkingString); if (!hString) break; hSurface = pClientDE->CreateSurfaceFromString (hFont, hString, foreColor, backColor, nExtraX, nExtraY); if (!hSurface) { pClientDE->FreeString (hString); break; } pClientDE->FreeString (hString); // get the dimensions of the surface uint32 nTestWidth = 0; uint32 nTestHeight = 0; pClientDE->GetSurfaceDims (hSurface, &nTestWidth, &nTestHeight); if (nTestWidth > (uint32)nWidth) { // string too long, remove some and try again char* pSpace; // remove by character if we are hard wrapping if (bHardTextWrap) { pSpace = pWorkingString; // find last hard in string pPrev char* pPrev = NULL; while (pSpace != NULL) { pPrev = pSpace; pSpace = (char*)_mbsinc ((const unsigned char*)pSpace); if (*pSpace == '\0') pSpace = NULL; } if (pPrev == NULL) pSpace = pWorkingString; else { //decrement 1 character pSpace = (char*)_mbsdec ((const unsigned char*)pWorkingString, (const unsigned char*)pPrev); // check if we are on a period then we need to decrement 3 more if ((char*)_mbsspnp((const unsigned char*)pPrev, (const unsigned char*)sPeriodChars) != pPrev) { if (pSpace != NULL) pSpace = (char*)_mbsdec ((const unsigned char*)pWorkingString, (const unsigned char*)pSpace); if (pSpace != NULL) pSpace = (char*)_mbsdec ((const unsigned char*)pWorkingString, (const unsigned char*)pSpace); } } } // remove by word if hard wrap is not on else { pSpace = (char*)_mbsrchr ((const unsigned char*)pWorkingString, ' '); if (!pSpace) pSpace = pWorkingString; while (_mbsnbcmp ((const unsigned char*)pSpace, (const unsigned char*)" ", 1) == 0 && pSpace != pWorkingString) { pSpace = (char*)_mbsdec ((const unsigned char*)pWorkingString, (const unsigned char*)pSpace); if (!pSpace) pSpace = pWorkingString; } } if (pSpace == pWorkingString) { bDone = LTTRUE; } else { pSpace = (char*)_mbsinc ((const unsigned char*)pSpace); *pSpace = '\0'; } pClientDE->DeleteSurface (hSurface); hSurface = LTNULL; } else { // it fits! bDone = LTTRUE; } } // if we got here without bDone being TRUE, there was an error if (!bDone) { delete [] pWorkingString; for (uint32 i = 0; i < nSurfaces; i++) { pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); } return LTNULL; } // if bDone is true but there's no surface, we couldn't make it fit // just create a surface from the string and it will get clipped later if (bDone && !hSurface) { HSTRING hString = pClientDE->CreateString (pWorkingString); hSurface = pClientDE->CreateSurfaceFromString (hFont, hString, foreColor, backColor, nExtraX, nExtraY); if (!hString || !hSurface) { if (hString) pClientDE->FreeString (hString); if (hSurface) pClientDE->DeleteSurface (hSurface); delete [] pWorkingString; for (uint32 i = 0; i < nSurfaces; i++) { pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); } return LTNULL; } pClientDE->FreeString (hString); } // add this surface to the array surfaces[nSurfaces] = (uint32) hSurface; nSurfaces++; // increment ptr to next character in the string ptr += strlen (pWorkingString); char* pPrev = NULL; while (_mbsnbcmp ((const unsigned char*)ptr, (const unsigned char*)" ", 1) == 0 && *ptr) { pPrev = ptr; ptr = (char*)_mbsinc ((const unsigned char*)ptr); if (!ptr) { ptr = pPrev; break; } } } delete [] pWorkingString; // ok, now we should have an array of surfaces that we can combine into one large one... if (!nSurfaces) return LTNULL; // crop the surfaces if they need to be cropped (leave a one-pixel border) if (bCropped) { for (uint32 i = 0; i < nSurfaces; i++) { HSURFACE hCropped = CropSurface (pClientDE, (HSURFACE)surfaces[i], LTNULL); if (hCropped) { pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); surfaces[i] = (uint32) hCropped; } } } // get the final surface height uint32 nTotalHeight = 0; for (uint32 i = 0; i < nSurfaces; i++) { uint32 nSurfWidth = 0; uint32 nSurfHeight = 0; pClientDE->GetSurfaceDims ((HSURFACE)surfaces[i], &nSurfWidth, &nSurfHeight); nTotalHeight += nSurfHeight; } // create the final surface HSURFACE hFinalSurface = pClientDE->CreateSurface (nWidth, nTotalHeight); if (!hFinalSurface) { for (uint32 i = 0; i < nSurfaces; i++) { pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); } return LTNULL; } pClientDE->FillRect ((HSURFACE)hFinalSurface, LTNULL, LTNULL); // draw the string surfaces onto final one int y = 0; for (int i = 0; i < nSurfaces; i++) { uint32 nSurfWidth = 0; uint32 nSurfHeight = 0; pClientDE->GetSurfaceDims ((HSURFACE)surfaces[i], &nSurfWidth, &nSurfHeight); int x = 0; switch (nAlignment) { case TH_ALIGN_CENTER: x = ((int)nWidth - (int)nSurfWidth) / 2; break; case TH_ALIGN_RIGHT: x = (int)nWidth - (int)nSurfWidth; break; } pClientDE->DrawSurfaceToSurface (hFinalSurface, (HSURFACE)surfaces[i], LTNULL, x, y); y += nSurfHeight; // delete this surface since we don't need it anymore pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); } if (bCropped) { HSURFACE hCropped = CropSurface (pClientDE, hFinalSurface, backColor); if (hCropped) { pClientDE->DeleteSurface (hFinalSurface); return hCropped; } } return hFinalSurface; }