GUI library for Windows \ Linux (window9)

Headers, Bindings, Libraries for use with FreeBASIC, Please include example of use to help ensure they are tested and usable.
Post Reply
j8w344c6
Posts: 184
Joined: Oct 25, 2021 10:18

Re: FBGUI library for Windows 2

Post by j8w344c6 »

I refactored your code a bit. I tried to compile with MSYS2 and it's error-free. This means my refactored code works.

First, I renamed your string.h to fbstring_compat.h and changed ustring to a proper class.

fbstring_compat.h

Code: Select all

#include <cstdlib>
#include <cstdio>
#include <string.h>
#include <iostream>
#include <locale>

/*
 * Класс для работы с динамическими строками (внутренний формат UTF8)
 * 
 * 							доступные операторы: 
 * 	+ 	объединяет две строки ustring. Так же можно в один из параметров отправлять char* 
 * 	+=	объединяет текущую строку с другой строкой ustring. Так же можно в параметр отправлять char*
 * 	== 	проверка строк на равенство.
 *  !=	проверка строк на неравенство.
 * 	*	возвращает указатель на fbstring*
 * 	=	присвоение строки ustring или const char*
 * 	[]	индексация (возвращает отдельный байт по индексу)
 * 	
 * 							конструкторы (примеры)
 * 	ustring s; // пустая строка , содержит только символ конца строки
 * 	ustring s1 = s; // создание новой строки из существующей ustring
 * 	ustring s2 = "one"; // создание новой строки с помощью типа const char*
 * 	ustring s2 = 5; // создание строки с выделенной памятью на 5 байт
 * 	ustring s2 = {8,'Q'}; // создание строки с выделенной памятью на 8 байт и символом по умолчанию (во 2 параметре передается только один байт char)
 * 
 * 							функции
 * 	lensymbols	кол-во символов в строке
 * 	len			кол-во байт в строке
 * 	in_unicode	возвращает unicode представление строки wchar_t*
 * 	in_utf8		создает обычную строку ustring из unicode строки wchar_t*
 * 	mid			возвращает часть строки. По умолчанию работает с символами , но может работать с отдельными байтами
 * 	instr		поиск подстроки. По умолчанию работает с символами , но может работать с отдельными байтами
 * 	trim		обрезка ненужных символов с обих сторон
 * 	ltrim		обрезка ненужных символов слева
 * 	ltrim		обрезка ненужных символов справа
 * 	chr			возвращает строку ustring из отдельного символа char
 * 	asc			возвращает байт из символа
 * 	val			преобразует строку в число double
 * 	valint		преобразует строку в число int
 * 	str			преобразует число (double или int) в строку
 * 	right		возвращает часть строки справа (работает только с символами)
 * 	left		возвращает часть строки слева (работает только с символами)
 * 	space		создает строку ustring c нужным кол-вом пробелов
 * 	string		создает строку ustring c нужным кол-вом любых символов в диапазоне char
 * 	lcase		возвращает строку в нижнем регистре (желательно использовать в программе setlocale(LC_ALL, ""))
 * 	lcase		возвращает строку в верхнем регистре (желательно использовать в программе setlocale(LC_ALL, ""))
 * 	replace		перезапись части строки
 * 	insert		вставка в любую часть строки
 * 	clear		очистка от ненужных символов
*/

using namespace std;

namespace fbc
{	
	struct fbstring
	{
		char *sBuf;
		
		long iLen;
		
		long iSize;
		
	};	
	
	class ustring;
	
	// operator overloading
	
	ustring operator + (const char* psz , const ustring &s);

	ustring operator + (const ustring &s , const char* psz);

	ustring operator + (const ustring &s1 , const ustring &s2);
}

using fbc::ustring;

class ustring
{
	//private:
	
		//fbstring* obj;
	
	public:
	
	// everything must be public for this code to work
	
	fbstring* obj;
	
	// constructor
	
	ustring();
		
	ustring(const char*);
	
	ustring(const ustring &s);
	
	ustring(int iCount);
	
	ustring(int iCount , char ch);
	
	// destructor
	
	~ustring();
	
	// public methods
	
	void createnullstring();
		
	int lensymbols();
	
	wchar_t* in_unicode();
	
	void in_utf8(const wchar_t *s);
	
	ustring mid(unsigned int iStart , unsigned int iNcount = 0x7FFFFFFF , int iUni = 1);
	
	int instr(int iStart , const ustring & sSearch , int iUni = 1);
	
	int instr(int iStart , const char* pszSearch , int iUni = 1);
	
	ustring trim(const char* s = " ");
	
	ustring ltrim(const char* s = " ");
	
	ustring rtrim(const char* s = " ");
	
	ustring chr(char i);
	
	int asc();
	
	double val();
	
	int valint();
	
	ustring str(double i);
	
	ustring str(int i);
	
	ustring right(int iCount);
	
	ustring left(int iCount);
	
	ustring space(int iCount);
	
	ustring string(int iCount , char ch);
	
	int len();
	
	ustring lcase();
	
	ustring ucase();
	
	ustring replace(ustring & sSearch , ustring & sReplace , int iPos = 1 , int iParam = 0 , int iReg = 0 , int iUni = 1);
	
	ustring insert(ustring & sInsert , int iPos , int iUni = 1);
	
	ustring clear(ustring & sTrim);
	
	// operator overloading
	
	unsigned char & operator [] (int i)
	{
		return reinterpret_cast<unsigned char&>((obj->sBuf)[i]);
	};
	
	bool operator == (const ustring &s)
	{
		return !strcmp(s.obj->sBuf , obj->sBuf);
	};
	
	bool operator != (const ustring &s)
	{
		return strcmp(s.obj->sBuf , obj->sBuf);
	};
	
	fbstring* operator * ()
	{
		return obj;
	};	
	
	ustring& operator = (const ustring &s)
	{
		if (&s == this) return *this;
		
		if (obj->sBuf) free(obj->sBuf);
		
		if (!s.obj->iLen)
		{
			createnullstring();
			
			return *this;
		
		}
		else
		{
			char *ps = static_cast<char*>(malloc(s.obj->iSize));
			
			if (s.obj->sBuf) 
				obj->sBuf = strcpy(ps , s.obj->sBuf);
			else 
				obj->sBuf = ps;
				
			obj->iLen = s.obj->iLen;
			
			(obj->sBuf)[obj->iLen] = 0;
			
			obj->iSize = s.obj->iSize;
			
			return *this;
		};
	};
	
	ustring& operator = (const char* psz)
	{
		if (!psz) return *this;	
			
		if (obj->sBuf) free(obj->sBuf);
		
		int iLen =strlen(psz);
		
		if (!iLen)
		{
			createnullstring();
			
			return *this;
		
		}
		else
		{
			int iAlloc = (iLen + 1);
			
			char *ps = static_cast<char*>(malloc(iAlloc));
			
			obj->sBuf = strcpy(ps , psz);
			
			this->obj->iLen = iLen;
			
			(obj->sBuf)[iLen] = 0;
			
			obj->iSize = iAlloc;
			
			return *this;
		};
	};
	
	ustring& operator = (fbstring* psz)
	{
		if (!psz) return *this;
			
		if (obj->sBuf) free(obj->sBuf);
		
		if (!(psz->iLen))
		{
			createnullstring();
			
			return *this;
		
		}
		else
		{		
			char *ps = static_cast<char*>(malloc(psz->iSize));
			
			obj->sBuf = strcpy(ps , psz->sBuf);
			
			this->obj->iLen = psz->iLen;
			
			(obj->sBuf)[this->obj->iLen] = 0;
			
			obj->iSize = psz->iSize;
			
			return *this;
		};
	};
	
	ustring& operator += (const ustring &s)
	{
		if (!(s.obj->iLen)) return *this;
		
		int iAlloc = s.obj->iSize + obj->iSize;
		
		char *ps = static_cast<char*>(malloc(iAlloc));
		
		sprintf(ps , "%s%s", obj->sBuf , s.obj->sBuf);
		
		obj->iLen = s.obj->iLen+obj->iLen;
		
		obj->iSize = iAlloc;
			
		free(obj->sBuf);
		
		obj->sBuf = ps;
		
		return *this;		
	};
	
	ustring& operator += (const char* psz)
	{
		if (!psz) return *this;
		
		int iLen = strlen(psz);
		
		if (!iLen) return *this;
		
		int iAlloc = (iLen + 1 + obj->iSize);
		
		char *ps = static_cast<char*>(malloc(iAlloc));
		
		sprintf(ps , "%s%s", obj->sBuf , psz);
		
		this->obj->iLen = this->obj->iLen+iLen;
		
		obj->iSize = iAlloc;
		
		free(obj->sBuf);
		
		obj->sBuf = ps;
		
		return *this;
	};
};

// implement missing methods
// put everything inside a header is bad practice
// but it's C++ anyway

void ustring::createnullstring()
{
	
	char *ps = static_cast<char*>(malloc(sizeof(char)));
	
	if (ps)
	{
		obj->sBuf = ps;
		
		ps[0] = 0;
		
		obj->iLen = 0;
		
		obj->iSize = sizeof(char);
	};
};

// constructors

ustring::ustring()
{
	obj = static_cast<fbstring*>(malloc(sizeof(fbstring)));
	
	createnullstring();
};

ustring::ustring(const char* psz)
{
	if (!psz) 
	{
		obj = static_cast<fbstring*>(malloc(sizeof(fbstring)));
		
		createnullstring();
		
		return;
	};
	
	int iLen = strlen(psz);
	
	if (!iLen)
	{
		obj = static_cast<fbstring*>(malloc(sizeof(fbstring)));
		
		createnullstring();
		
		return;
	};	 
	
	int iAlloc = (iLen+1);
	
	char *ps = static_cast<char*>(malloc(iAlloc));
	
	if (ps)
	{
		obj = static_cast<fbstring*>(malloc(sizeof(fbstring)));
		
		obj->sBuf = strcpy(ps , psz);
		
		this->obj->iLen = iLen;
		
		this->obj->iSize = iAlloc;
		
		(obj->sBuf)[iLen] = 0;
	}	
};

ustring::ustring(const ustring &s)
{
	
	if (&s == this) return;	
	
	char *ps = static_cast<char*>(malloc(s.obj->iSize));
		
	if (ps)
	{
		obj = static_cast<fbstring*>(malloc(sizeof(fbstring)));
		
		obj->sBuf = strcpy(ps , s.obj->sBuf);
		
		obj->iLen = s.obj->iLen;
		
		obj->iSize = s.obj->iSize;
		
		(obj->sBuf)[obj->iLen] = 0;
		
	}	
};

ustring::ustring(int iCount)
{
	int iAlloc = (iCount+1);
	
	char *ps = static_cast<char*>(malloc(iAlloc));
	
	if (ps)
	{
		obj = static_cast<fbstring*>(malloc(sizeof(fbstring)));
		
		obj->sBuf = ps;
		
		obj->iLen = iCount;
		
		obj->iSize = iAlloc;
		
		(obj->sBuf)[iCount] = 0;
		
	};
};

ustring::ustring(int iCount , char ch)
{
	int iAlloc = (iCount+1);
	
	char *ps = static_cast<char*>(malloc(iAlloc));
	
	memset(ps , ch , iCount);
	
	if (ps)
	{
		obj = static_cast<fbstring*>(malloc(sizeof(fbstring)));
		
		obj->sBuf = ps;
		
		obj->iLen = iCount;
		
		obj->iSize = iAlloc;
		
		(obj->sBuf)[iCount] = 0;
		
	};
};

// destructor

ustring::~ustring()
{
	if (obj->sBuf) free(obj->sBuf);
	
	obj->sBuf = 0;
	
	obj->iLen = 0;
	
	obj->iSize = 0;
	
	free(obj);
};

// public methods

int ustring::lensymbols()
{	
	int iIndex = 0;
	
	for (int i = 0; i < obj->iLen; i++)
	{
		if ((((obj->sBuf)[i] & 0xF0) == 0xE0) && (((obj->sBuf)[i+1] & 0xC0) == 0x80) && (((obj->sBuf)[i+2] & 0xC0) == 0x80))
			i+=2;
		else if (((obj->sBuf)[i] & 0xC0) == 0xC0 && ((obj->sBuf)[i+1] & 0xC0) == 0x80)
			i++;
		iIndex++;
	};

	return iIndex;
};

wchar_t* ustring::in_unicode()
{	
	int iIndex = 0;
	
	int shUnicodeSymbol = 0;
	
	int iAlloc = (lensymbols()+1) * sizeof(wchar_t);
	
	wchar_t *ws = static_cast<wchar_t*>(calloc(1, iAlloc));
	
	for (int i = 0; i < obj->iLen; i++)
	{	
		if ((((obj->sBuf)[i] & 0xF0) == 0xE0) && (((obj->sBuf)[i+1] & 0xC0) == 0x80) && (((obj->sBuf)[i+2] & 0xC0) == 0x80))
		{	
			shUnicodeSymbol = (((obj->sBuf)[i] & 0xF) << 12) | ((((obj->sBuf)[i+1] & 0x3F) << 6) | ((obj->sBuf)[i+2] & 0x3F));
			
			i+=2;
		}
		else if (((obj->sBuf)[i] & 0xC0) == 0xC0 && ((obj->sBuf)[i+1] & 0xC0) == 0x80)
		{	
			shUnicodeSymbol = (((obj->sBuf)[i] & 0x1F) << 6) | (((obj->sBuf)[i+1] & 0x3F));
			
			i++;			
		}
		else if (((obj->sBuf)[i] & 0x80) == 0 )
			shUnicodeSymbol = (obj->sBuf)[i];
			
		else
			shUnicodeSymbol = 0xFFFD;
		
		(ws)[iIndex] = shUnicodeSymbol;
		
		iIndex++;
		
	};
	
	(ws)[iIndex] = 0;
	
	return ws;
};

void ustring::in_utf8(const wchar_t *s)
{
	int iSimbol = 0;	
	int j = 0;
	int iLen = wcslen(s);
	int iAlloc = (iLen+1)*6;
	
	char *ps = static_cast<char*>(calloc(1 , iAlloc));
	
	for (int i = 0; i < iLen ; i++)
	{	
		iSimbol = s[i];
		if (iSimbol < 0x80)
			ps[j++] = iSimbol;
		else if (iSimbol < 0x800)
		{	
			ps[j++] = (0xC0 | (iSimbol >> 6));
			ps[j++] = (0x80 | (iSimbol & 0x3f));
		}
		else if (iSimbol < 0x10000 && (iSimbol < 0xD800 || iSimbol > 0xDFFF))
		{	
			ps[j++] = (0xE0 | (0xF & (iSimbol >> 12)));
			ps[j++] = 0x80 | (0x3F & (iSimbol >> 6));
			ps[j++] = 0x80 | (iSimbol & 0x3F);
		}
		else
		{	
			ps[j++] = 0xEF;
			ps[j++] = 0xBF;
			ps[j++] = 0xBD;
		};
	};
	
	if (obj->sBuf) free(obj->sBuf);
	
	obj->sBuf = ps;
	
	this->obj->iLen = strlen(ps);
	
	this->obj->iSize = iAlloc;
};

ustring ustring::mid(unsigned int iStart , unsigned int iNcount , int iUni)
{
	ustring sRet;
	
	if (iUni)
	{
		wchar_t *ws = in_unicode();
		
		if (!ws) return sRet;
		
		unsigned int iLenws = wcslen(ws);
		
		if (iStart > iLenws || iStart <=0 || !iNcount)
		{
			free(ws);
			
			return sRet;
		};
		
		wchar_t *pAddr = ws + iStart - 1;
		
		unsigned int iCount = ((iNcount+iStart-1) > iLenws) ? (iLenws-iStart+1) : iNcount;
		
		pAddr[iCount] = 0;

		sRet.in_utf8(pAddr);
		
		free(ws);
		
		return sRet;
	}
	else
	{
		if (iStart > obj->iLen || iStart <=0 || !iNcount) return sRet;
		
		char *pAddr = obj->sBuf + iStart - 1;
		
		unsigned int iCount = ((iNcount+iStart-1) > obj->iLen) ? (obj->iLen-iStart+1) : iNcount;

		int iAlloc = (iCount+1);
		
		char *ps = static_cast<char*>(malloc(iAlloc));
		
		if (!ps) return sRet;
		
		memcpy(ps , pAddr , iCount);
		
		ps[iCount] = 0;

		if (sRet.obj->sBuf) free(sRet.obj->sBuf);

		sRet.obj->sBuf = ps;
		
		sRet.obj->iLen = iCount;
		
		sRet.obj->iSize = iAlloc;
		
		return sRet;
	};
};

int ustring::instr(int iStart , const ustring & sSearch , int iUni)
{
	if (iUni)
	{
		wchar_t *ws = in_unicode();
		
		if (!ws) return 0;
		
		wchar_t *wsSearch = ((ustring &)sSearch).in_unicode();
		
		if (!wsSearch) 
			{free(ws); return 0;};
		
		int iLenws = wcslen(ws);
		
		if (!iStart || iStart > iLenws) 
			{free(ws); free(wsSearch); return 0;};
		
		wchar_t* pAddr = ws + iStart - 1;
		
		wchar_t* pRet = wcsstr(pAddr , wsSearch);
		
		if (!pRet)
			{free(ws); free(wsSearch); return 0;};
		
		int iRet = static_cast<int>(pRet-pAddr);
		
		free(ws);
		
		free(wsSearch);
		
		return iRet+iStart;
	}
	else
	{
		if (!iStart || iStart > obj->iLen) return 0;
		
		char* pAddr = obj->sBuf + iStart - 1;
		
		char* pRet = strstr(pAddr , sSearch.obj->sBuf);
		
		if (!pRet) return 0;
		
		int iRet = static_cast<int>(pRet-pAddr);
		
		return iRet+iStart;			
	};
};

int ustring::instr(int iStart , const char* pszSearch , int iUni)
{
	if (iUni)
	{
		wchar_t *ws = in_unicode();
		
		if (!ws) return 0;
		
		ustring sSearch = pszSearch;
		
		wchar_t *wsSearch = sSearch.in_unicode();
		
		if (!wsSearch) 
			{free(ws); return 0;};
		
		int iLenws = wcslen(ws);
		
		if (!iStart || iStart > iLenws) 
			{free(ws); free(wsSearch); return 0;};
		
		wchar_t* pAddr = ws + iStart - 1;
		
		wchar_t* pRet = wcsstr(pAddr , wsSearch);
		
		if (!pRet)
			{free(ws); free(wsSearch); return 0;};
		
		int iRet = static_cast<int>(pRet-pAddr);
		
		free(ws);
		
		free(wsSearch);
		
		return iRet+iStart;
	}
	else
	{
		if (!iStart || iStart > obj->iLen) return 0;
		
		char* pAddr = obj->sBuf + iStart - 1;
		
		char* pRet = strstr(pAddr , pszSearch);
		
		if (!pRet) return 0;
		
		int iRet = static_cast<int>(pRet-pAddr);
		
		return iRet+iStart;
	};
};

ustring ustring::trim(const char* s)
{
	int iLenchar = strlen(s);
	
	ustring sRet;
	
	if (!(obj->iLen)) return sRet;
	
	if (iLenchar == 1)
	{
		char *ps = obj->sBuf;
		
		int i = 0, j = obj->iLen-1;
		
		while (ps[i] == s[0] && i != obj->iLen) i++;
		
		while (ps[j] == s[0] && j>=0) j--;

		sRet = ps+i;
		
		sRet.obj->iLen = j-i+1;
		
		(sRet.obj->sBuf)[sRet.obj->iLen] = 0;
		
		return sRet;
	}
	else if (iLenchar > 1)
	{
		wchar_t *ws = in_unicode();
		
		ustring sSymb = s;
		
		wchar_t *wsSymb = sSymb.in_unicode();
		
		if (!ws) return sRet;
		
		int iLenws = wcslen(ws);
		
		int i = 0, j = iLenws-1;
		
		while (ws[i] == wsSymb[0] && i != iLenws) i++;
		
		while (ws[j] == wsSymb[0] && j>=0) j--;
		
		ws[j-i+1+i] = 0;
		
		sRet.in_utf8(ws+i);
		
		free(ws);
		
		free(wsSymb);
		
		return sRet;			
	}
	else
		return sRet;
};

ustring ustring::ltrim(const char* s)
{		

	int iLenchar = strlen(s);
	
	ustring sRet;
	
	if (!(obj->iLen)) return sRet;
	
	if (iLenchar == 1)
	{
		char *ps = obj->sBuf;
		
		int i = 0;
		
		while (ps[i] == s[0] && i != obj->iLen) i++;

		sRet = ps+i;
		
		sRet.obj->iLen = obj->iLen - i;
		
		return sRet;
	}
	else if (iLenchar > 1)
	{
		wchar_t *ws = in_unicode();
		
		ustring sSymb = s;
		
		wchar_t *wsSymb = sSymb.in_unicode();
		
		if (!ws) return sRet;
		
		int iLenws = wcslen(ws);
		
		int i = 0;
		
		while (ws[i] == wsSymb[0] && i != iLenws) i++;
		
		sRet.in_utf8(ws+i);
		
		free(ws);
		
		free(wsSymb);
		
		return sRet;			
	}
	else
		return sRet;		
		
};

ustring ustring::rtrim(const char* s)
{
	
	int iLenchar = strlen(s);
	
	ustring sRet;
	
	if (!obj->iLen) return sRet;
	
	if (iLenchar == 1)
	{
		char *ps = obj->sBuf;
		
		int j = obj->iLen-1;
		
		while (ps[j] == s[0] && j>=0) j--;

		sRet = ps;
		
		sRet.obj->iLen = j+1;
		
		(sRet.obj->sBuf)[sRet.obj->iLen] = 0;
		
		return sRet;
	}
	else if (iLenchar > 1)
	{
		wchar_t *ws = in_unicode();
		
		ustring sSymb = s;
		
		wchar_t *wsSymb = sSymb.in_unicode();
		
		if (!ws) return sRet;
		
		int iLenws = wcslen(ws);
		
		int j = iLenws-1;
		
		while (ws[j] == wsSymb[0] && j>=0) j--;
		
		ws[j+1] = 0;
		
		sRet.in_utf8(ws);
		
		free(ws);
		
		free(wsSymb);
		
		return sRet;			
	}
	else
		return sRet;
		
};

ustring ustring::chr(char i)
{
	ustring sRet = " ";
	
	(sRet.obj->sBuf)[0] = i;

	return sRet;
};

int ustring::asc()
{
	return (obj->sBuf)[0];
};

double ustring::val()
{
	return atof(obj->sBuf);
};

int ustring::valint()
{
	return atoi(obj->sBuf);
};

ustring ustring::str(double d)
{
	char* ps = static_cast<char*>(calloc(1, 80));
	
	sprintf(ps , "%f" , d);
	
	ustring sRet = ps;
	
	free(ps);
	
	return sRet;	
}

ustring ustring::str(int i)
{
	char* ps = static_cast<char*>(calloc(1, 15));
	
	sprintf(ps , "%d" , i);
	
	ustring sRet = ps;
	
	free(ps);
	
	return sRet;
}

ustring ustring::right(int iCount)
{
	ustring sRet;
	
	wchar_t *ws = in_unicode();
	
	if (!ws) return *this;
	
	int iLenws = wcslen(ws);
	
	if (iCount > iLenws) iCount = iLenws;
	
	wchar_t *ps = ws +(iLenws - iCount);
	
	sRet.in_utf8(ps);
	
	free(ws);
	
	return sRet;
};

ustring ustring::left(int iCount)
{
	ustring sRet;
	
	wchar_t *ws = in_unicode();
	
	if (!ws) return *this;
	
	int iLenws = wcslen(ws);
	
	if (iCount<=0) 
	{ 
		free(ws);
		
		return *this;
	};
	
	if (iCount > iLenws) iCount = iLenws;
	
	ws[iCount] = 0;
	
	sRet.in_utf8(ws);
	
	free(ws);
	
	return sRet;
};

ustring ustring::space(int iCount)
{
	ustring sRet(iCount);
	
	memset(sRet.obj->sBuf , 32 , iCount);
	
	return sRet;
};

ustring ustring::string(int iCount , char ch)
{
	ustring sRet(iCount);
	
	memset(sRet.obj->sBuf , ch , iCount);
	
	return sRet;
};

int ustring::len()
{
	return obj->iLen;
};

ustring ustring::lcase()
{
	ustring sRet;
	
	wchar_t *ws = in_unicode();
	
	if (!ws) return sRet;
	
	int iLenws = wcslen(ws);
	
	for (int i = 0 ; i < iLenws ; i++)
		ws[i] = towlower(ws[i]);
	
	sRet.in_utf8(ws);
	
	free(ws);
	
	return sRet;
};

ustring ustring::ucase()
{
	ustring sRet;
	
	wchar_t *ws = in_unicode();
	
	if (!ws) return sRet;
	
	int iLenws = wcslen(ws);
	
	for (int i = 0 ; i < iLenws ; i++)
		ws[i] = towupper(ws[i]);
	
	sRet.in_utf8(ws);
	
	free(ws);
	
	return sRet;
};

ustring ustring::replace(ustring & sSearch , ustring & sReplace , int iPos , int iParam , int iReg , int iUni)
{
	if (iUni)
	{			
		if (!(obj->iLen) || !(sSearch.obj->iLen)) return *this;
		
		wchar_t *ws_S = sSearch.in_unicode();
		
		if (!ws_S) return *this;
		
		int iLen_S = wcslen(ws_S);
		
		int iPosSearch , iPosSearchNext = iPos;
		
		ustring sReturnString = *this;
		
		if (!iReg)
		{
			for (int i = 0; i < iLen_S; i++)
				ws_S[i] = towlower(ws_S[i]);
		};
		
		while (1)
		{
			if (!iReg)
			{
				wchar_t *ws = sReturnString.in_unicode();
		
				if (ws)
				{
					int iLenWS = wcslen(ws);
					
					for (int i = 0; i < iLenWS; i++)
						ws[i] = towlower(ws[i]);
					
					wchar_t* pAddr = ws + iPosSearchNext - 1;
				
					wchar_t* pRet = wcsstr(pAddr , ws_S);
					
					if (pRet) 
						iPosSearch = (pRet-pAddr)+iPosSearchNext;
					else
						iPosSearch = 0;
						
					free(ws);
				}
				else
					iPosSearch = 0;
			}
			else
				iPosSearch = sReturnString.instr( iPosSearchNext , sSearch  , iUni);
			
			if (iPosSearch)
			{
				sReturnString = sReturnString.mid( 1 , iPosSearch - 1  , iUni) + sReplace + sReturnString.mid( iPosSearch + sSearch.lensymbols()  , 0x7fffffff , iUni);
				
				if (iParam)
					iPosSearchNext = iPosSearch + sReplace.lensymbols();
				else
				{
					if (!iReg) free(ws_S);
					
					return sReturnString;
				};				
			}	
			else
			{
				if (!iReg) free(ws_S);
				
				return sReturnString;
			};
		};
	}
	else
	{
		ustring sReturnString = *this;
		
		int iPosSearch , iPosSearchNext = iPos;
		
		while (1)
		{	
			if (!iReg)
				iPosSearch = (sReturnString.lcase()).instr( iPosSearchNext , sSearch.lcase()  , 0);
			else
				iPosSearch = sReturnString.instr( iPosSearchNext , sSearch  , 0);
			
			if (iPosSearch)
			{
				sReturnString = sReturnString.mid( 1 , iPosSearch - 1  , 0) + sReplace + sReturnString.mid( iPosSearch + sSearch.len()  , 0x7fffffff  , 0);
				
				if (iParam)
					iPosSearchNext = iPosSearch + sReplace.len();
				else
					return sReturnString;
			}
			else
				return sReturnString;
				
		};		
	};
};

ustring ustring::insert(ustring & sInsert , int iPos , int iUni)
{
	int iLenDest;
	
	if (iUni) 
		iLenDest = lensymbols();
	else
		iLenDest = obj->iLen;
	
	if (iPos == -1) iPos = iLenDest+1;
	
	if ((iLenDest+1 < iPos) || (iPos == 0) || (iPos < -1)) return *this;
	
	return mid(1,iPos-1 , iUni) + sInsert + mid(iPos , 0x7fffffff , iUni);
};

ustring ustring::clear(ustring & sTrim)
{
	if (!(obj->iLen) || !(sTrim.obj->iLen)) return *this;
	
	wchar_t* ws = in_unicode();
	
	wchar_t* wtr = sTrim.in_unicode();
	
	int iIndex = 0 , iResult = 0;
	
	for (int i = 0 ; i < static_cast<int>(wcslen(ws)) ; i++)
	{
		for (int j = 0 ; j < static_cast<int>(wcslen(wtr)) ; j++)
			if (ws[i] == wtr[j])
				iResult = 1;
		if (iResult)
			iResult = 0;
		else
			ws[iIndex++] = ws[i];
	};
	
	ws[iIndex] = 0;
	
	ustring sRet;
	
	sRet.in_utf8(ws);
	
	free(ws); free(wtr);
	
	return sRet;
};

// outside class operator overloading

ustring fbc::operator + (const char* psz , const ustring &s)
{
	int iLen = 0;
	
	if (psz) iLen = strlen(psz);
		
	ustring sRet;
		
	int iAlloc = (iLen + 1 + s.obj->iSize);
	
	sRet.obj->sBuf = static_cast<char*>(malloc(iAlloc));
	
	sprintf(sRet.obj->sBuf , "%s%s", psz , s.obj->sBuf );
	
	sRet.obj->iLen = s.obj->iLen + iLen;
	
	sRet.obj->iSize = iAlloc;
	
	return sRet;
};

ustring fbc::operator + (const ustring &s , const char* psz)
{
	int iLen = 0;	
	
	if (psz) iLen = strlen(psz);
		
	ustring sRet;
	
	int iAlloc = (iLen + 1 + s.obj->iSize);
	
	sRet.obj->sBuf = static_cast<char*>(malloc(iAlloc));
	
	sprintf(sRet.obj->sBuf , "%s%s", s.obj->sBuf , psz );
	
	sRet.obj->iLen = s.obj->iLen + iLen;
	
	sRet.obj->iSize = iAlloc;
	
	return sRet;
};

ustring fbc::operator + (const ustring &s1 , const ustring &s2)
{
	ustring sRet;
	
	int iAlloc = (s1.obj->iSize + s2.obj->iSize);
	
	sRet.obj->sBuf = static_cast<char*>(malloc(iAlloc));
	
	sprintf(sRet.obj->sBuf , "%s%s", s1.obj->sBuf , s2.obj->sBuf );
	
	sRet.obj->iLen = s1.obj->iLen + s2.obj->iLen;
	
	sRet.obj->iSize = iAlloc;
	
	return sRet;
};
Your key.h remains intact.

Instead of using a whole fbc namespace, I changed to only using fbc::fbstring in window9.h.

Your example w9.cpp compiled fine on MSYS2 (of course can't link because the dynamic library is of Linux, but it proves my refactored code is error-free).

On MSYS2, for no known reason pkg-config doesn't work right. So I have to add all include paths manually.

g++ -c w9.cpp -I. -I/mingw64/include/gtk-3.0 -I/mingw64/include/glib-2.0 -I/mingw64/lib/glib-2.0/include -mms-bitfields -I/mingw64/include -I/mingw64/include/pango-1.0 -I/mingw64/include/harfbuzz -I/mingw64/include/cairo -I/mingw64/include/gdk-pixbuf-2.0 -I/mingw64/include/atk-1.0
j8w344c6
Posts: 184
Joined: Oct 25, 2021 10:18

Re: FBGUI library for Windows 2

Post by j8w344c6 »

I spent the whole night to debug what's wrong with window9_wrap.cxx. It's because swig doesn't support C++'s define once principle. It's swig's own limitation, we can't do anything to help it. For anyone doesn't know, the C++'s define only once but can implement later is something like this example:

https://stackoverflow.com/questions/623 ... -namespace

Define it first, then implement it later. Swig can't distinguish between definitions and implementations. It wrapped both. This caused the error redefinition of methods when we tried compiling window9_wrap.cxx.

This swig interface is perfectly valid but the wrapper generated by swig can't compile:

window9.i

Code: Select all

%module window9

%{
#include "keys.h"
#include "fbstring_compat.h"
#include "window9.h"
%}

%rename(__charAt__) fbc::ustring::operator[];
%rename(__equals__) fbc::ustring::operator==;
%rename(__differs__) fbc::ustring::operator!=;
%rename(__from__) fbc::ustring::operator=;
%rename(__append__) fbc::ustring::operator+=;
%rename(__concat__) fbc::operator+;

%include "keys.h"
%include "fbstring_compat.h"
%include "window9.h"
j8w344c6
Posts: 184
Joined: Oct 25, 2021 10:18

Re: FBGUI library for Windows 2

Post by j8w344c6 »

I have a workaround for this. In window9.h there is no usage of an ustring. This means you only provide ustring for compatibility issue. So we commented out fbstring_compat.h and add the definition of fbstring struct directly to window9.h like this:

Code: Select all

//#define __USE_GTK3__

#include <gtk/gtk.h>
#include <gdk/gdk.h>
//#include "fbstring_compat.h"
#include "keys.h"

/*
#include "dir.bi"

#include Once "gtk/gtk.bi"

#include Once "crt/stdio.bi"

#include Once "crt/string.bi" 

#include Once "crt/stdlib.bi"

#include Once "zlib.bi"

#include Once "X11/Xlib.bi"

#include Once "GL/gl.bi"

#include Once "GL/glu.bi"

#include Once "extwstring.bi"

*/

//using fbc::fbstring;

struct fbstring
{
	char *sBuf;
	
	long iLen;
	
	long iSize;
	
};
...
We changed our swig interface like this:

Code: Select all

%module window9

%{
#include "keys.h"
//#include "fbstring_compat.h"
#include "window9.h"
%}

/*
%rename(__charAt__) fbc::ustring::operator[];
%rename(__equals__) fbc::ustring::operator==;
%rename(__differs__) fbc::ustring::operator!=;
%rename(__from__) fbc::ustring::operator=;
%rename(__append__) fbc::ustring::operator+=;
%rename(__concat__) fbc::operator+;
*/

%include "keys.h"
//%include "fbstring_compat.h"
%include "window9.h"
Now our window9_wrap.cxx compiled without any problems.

g++ -c window9_wrap.cxx -I. -I/mingw64/include/gtk-3.0 -I/mingw64/include/glib-2.0 -I/mingw64/lib/glib-2.0/include -mms-bitfields -I/mingw64/include -I/mingw64/include/pango-1.0 -I/mingw64/include/harfbuzz -I/mingw64/include/cairo -I/mingw64/include/gdk-pixbuf-2.0 -I/mingw64/include/atk-1.0
paul doe
Moderator
Posts: 1733
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FBGUI library for Windows 2

Post by paul doe »

j8w344c6 wrote:...
Your example w9.cpp compiled fine on MSYS2 (of course can't link because the dynamic library is of Linux, but it proves my refactored code is error-free).
...
It only proves that your refactored code compiles, not that it is error-free. For that, you'll need to build the lib, and run units tests against it (if available).
j8w344c6
Posts: 184
Joined: Oct 25, 2021 10:18

Re: FBGUI library for Windows 2

Post by j8w344c6 »

paul doe wrote:
j8w344c6 wrote:...
Your example w9.cpp compiled fine on MSYS2 (of course can't link because the dynamic library is of Linux, but it proves my refactored code is error-free).
...
It only proves that your refactored code compiles, not that it is error-free. For that, you'll need to build the lib, and run units tests against it (if available).
There is no library to build. He provided C++ headers to use with his FreeBASIC written window9 library and an example. This example compiled fine this means my refactored code is fine as well. I didn't do any intrusive changes to his code, just changed ustring from a struct to a proper class and reorganize the namespace to fit the C++ standard. Of course you could say what I'm having is just an object file. I need to have a binary that works. But sorry my friend, the dynamic library he provided is for Linux so I can't link with it (I'm on Windows). The C++ headers is also Linux only (they are only account for Linux, so there is currently no Windows C++ binding of this library).
j8w344c6
Posts: 184
Joined: Oct 25, 2021 10:18

Re: FBGUI library for Windows 2

Post by j8w344c6 »

I have a workaround to wrap this library completely with swig. You have to split declarations (definitions) and implementations into the appropriate header and source file (fbstring.h and fbstring.cpp). Putting everything in one header only is a bad practice (even with C++ when there is no templates involved). The more it close to C, the easier it is to wrap. Finally, get rid of the namespace fbc. There is no need of it, it only complicated everything.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: FBGUI library for Windows 2

Post by marcov »

j8w344c6 wrote:I have a workaround to wrap this library completely with swig. You have to split declarations (definitions) and implementations into the appropriate header and source file (fbstring.h and fbstring.cpp). Putting everything in one header only is a bad practice (even with C++ when there is no templates involved). The more it close to C, the easier it is to wrap. Finally, get rid of the namespace fbc. There is no need of it, it only complicated everything.
(splitting macros/constants/type declarations/function declarations/interface declarations into separate files using a simple heuristic script is a technique that I have also used for header conversions in the past. I can recommend it, it makes running substitutions and scripts over the more uniform parts more reliable.
I had planned to tag every split declaration with the original linenumber to be able to rejoin them afterwards, but I haven't tried that yet)
miilvyxg
Posts: 193
Joined: Dec 07, 2021 6:51

Re: FBGUI library for Windows 2

Post by miilvyxg »

VANYA wrote:
miilvyxg wrote:Could you build the dynamic library? I only see static library.
I dabbled somehow and created a dynamic library for linux 64-bit. For Windows did not try to create.

If you want, you can try a dynamic library with an example and header files for the C ++ language. The version of window9 in the archive is not the newest, it was just for testing:

test window9+language C++
A dynamic library to be able to update to new version of the library seamlessly. We still can link with the dynamic library. It's all about FB and I didn't say anything about C++. Don't know why you seem to associate a dynamic library with C++? I need the .so/.dll but not these C++ headers. Thank you anyway.
miilvyxg
Posts: 193
Joined: Dec 07, 2021 6:51

Re: FBGUI library for Windows 2

Post by miilvyxg »

VANYA wrote:
j8w344c6 wrote:
VANYA wrote:
I dabbled somehow and created a dynamic library for linux 64-bit. For Windows did not try to create.

If you want, you can try a dynamic library with an example and header files for the C ++ language. The version of window9 in the archive is not the newest, it was just for testing:

test window9+language C++
Your library could be used from C++? Does the C++ binding complete or only as a proof of concept?
If it's a complete binding then with swig I could create binding for many languages.
I haven't done full testing, but in principle almost all functions should work in C ++. Again I write: the library being built is not the newest version of the library. In addition, it will not work so easily to translate into other programming languages, since the library actively uses the freebasic type "STRING". For C ++, I wrote a similar analogue (file string.h).
Your C++ is very old schooled. He was right to turn ustring from a struct to a class. BTW, I think libustring/libfbstring should be provided as a separate .dll/.so.
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FBGUI library for Windows 2

Post by VANYA »

miilvyxg wrote:BTW, I think libustring/libfbstring should be provided as a separate .dll/.so.
My goal is not to create dll / so files, and I also have no goal to translate the library for other languages. What I gave you the archive, it was just pampering \ test \ test of the pen, nothing more.
miilvyxg
Posts: 193
Joined: Dec 07, 2021 6:51

Re: FBGUI library for Windows 2

Post by miilvyxg »

VANYA wrote:
miilvyxg wrote:BTW, I think libustring/libfbstring should be provided as a separate .dll/.so.
My goal is not to create dll / so files,
Why? DLL/SO makes updating applications use window9 easier. Instead of having to rebuild everything, the developers only have to provide the updated DLL/SO (in case where no code change is needed to trigger a rebuild, and most of the time it's the case).
VANYA wrote: and I also have no goal to translate the library for other languages. What I gave you the archive, it was just pampering \ test \ test of the pen, nothing more.
Understand.
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FBGUI library for Windows 2

Post by VANYA »

Why? DLL/SO makes updating applications use window9 easier. Instead of having to rebuild everything, the developers only have to provide the updated DLL/SO (in case where no code change is needed to trigger a rebuild, and most of the time it's the case).
Because there is a huge number of users who prefer static linking and do not like unnecessary dll files in their project. And I am one of these users. Whenever possible, I choose a static library. If the static library is not available, I use the dynamic library.
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FBGUI library for Windows 2

Post by VANYA »

Library update:

Windows:

rewritten event handler
minor fixes
Linux:
minor fixes
j8w344c6
Posts: 184
Joined: Oct 25, 2021 10:18

Re: FBGUI library for Windows 2

Post by j8w344c6 »

VANYA wrote:Because there is a huge number of users who prefer static linking and do not like unnecessary dll files in their project. And I am one of these users. Whenever possible, I choose a static library. If the static library is not available, I use the dynamic library.
This is like religion. But your source is available so I can easily create dynamic library myself. Thank you for your work anyway.
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: FBGUI library for Windows 2

Post by VANYA »

One of my projects using window9 urgently needed the ability to specify a parent window for another window. So I decided to edit the library.

And so an very small update:

windows and linux:
added optional parameter for function OpenWindow
Post Reply